UTI in pregnancy
"urinary tract infection" AND "pregnancy"
| Organism | Frequency |
|---|---|
| Escherichia coli | 70-80% |
| Klebsiella pneumoniae | 3-7% |
| Proteus mirabilis | 2% |
| Staphylococcus aureus | ~7% |
| Group B Streptococcus | ~10% |
| Drug | Status | Notes |
|---|---|---|
| Penicillins (amoxicillin, ampicillin) | Safe | First-line for cystitis/ASB |
| Cephalosporins (cephalexin, cefazolin) | Safe | First-line; preferred for pyelonephritis |
| β-lactamase inhibitors (amox-clavulanate) | Safe | Use when indicated |
| Nitrofurantoin | Safe in 1st-2nd trimester | Avoid in 3rd trimester (hemolysis risk, especially G6PD); also avoid at term |
| Azithromycin | Safe |
| Drug | Reason to Avoid |
|---|---|
| Fluoroquinolones | Interfere with cartilage formation |
| Tetracyclines | Dysplasia and discoloration of teeth/bones |
| Trimethoprim | Folate antagonist - interferes with neural tube development (especially 1st trimester) |
| Sulfonamides | Kernicterus (avoid in 3rd trimester) |
| Aminoglycosides | Nerve damage (ototoxicity/nephrotoxicity) |
Create a treatment protocol guide for UTI management in pregnancy
ls -la /tmp/workspace/ 2>/dev/null || echo "workspace does not exist"
~/uti_protocol/generate_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, PageBreak, KeepTogether
)
from reportlab.platypus.flowables import HRFlowable
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Polygon
from reportlab.graphics import renderPDF
from reportlab.platypus import Flowable
import os
OUTPUT_PATH = "/tmp/workspace/uti_protocol/UTI_in_Pregnancy_Protocol.pdf"
os.makedirs(os.path.dirname(OUTPUT_PATH), exist_ok=True)
# ── Colour palette ──────────────────────────────────────────────────
NAVY = colors.HexColor("#1A3A5C")
TEAL = colors.HexColor("#1D7A8C")
MINT = colors.HexColor("#E8F7F9")
AMBER = colors.HexColor("#E8A020")
AMBER_BG = colors.HexColor("#FFF8EC")
RED = colors.HexColor("#C0392B")
RED_BG = colors.HexColor("#FDEEEC")
GREEN = colors.HexColor("#1E8449")
GREEN_BG = colors.HexColor("#EAF7EE")
GREY = colors.HexColor("#5D6D7E")
LGREY = colors.HexColor("#F2F3F4")
WHITE = colors.white
# ── Document setup ──────────────────────────────────────────────────
doc = SimpleDocTemplate(
OUTPUT_PATH,
pagesize=A4,
leftMargin=1.8*cm, rightMargin=1.8*cm,
topMargin=2.2*cm, bottomMargin=2.2*cm,
title="UTI in Pregnancy – Treatment Protocol",
author="Orris Medical Education",
)
W = A4[0] - 3.6*cm # usable page width
# ── Styles ──────────────────────────────────────────────────────────
styles = getSampleStyleSheet()
def S(name, **kw):
"""Quick ParagraphStyle factory."""
return ParagraphStyle(name, **kw)
cover_title = S("CoverTitle", fontSize=28, textColor=WHITE,
fontName="Helvetica-Bold", leading=34, alignment=TA_CENTER)
cover_sub = S("CoverSub", fontSize=14, textColor=colors.HexColor("#BEE6F0"),
fontName="Helvetica", leading=18, alignment=TA_CENTER)
cover_meta = S("CoverMeta", fontSize=10, textColor=colors.HexColor("#A0C8D8"),
fontName="Helvetica", leading=14, alignment=TA_CENTER)
sec_head = S("SecHead", fontSize=13, textColor=WHITE,
fontName="Helvetica-Bold", leading=16, alignment=TA_LEFT,
leftIndent=6, spaceBefore=0, spaceAfter=0)
sub_head = S("SubHead", fontSize=11, textColor=NAVY,
fontName="Helvetica-Bold", leading=14,
spaceBefore=8, spaceAfter=4)
body = S("Body", fontSize=9, textColor=colors.HexColor("#2C3E50"),
fontName="Helvetica", leading=14,
spaceBefore=2, spaceAfter=2)
body_bold = S("BodyBold", fontSize=9, textColor=colors.HexColor("#2C3E50"),
fontName="Helvetica-Bold", leading=14)
small = S("Small", fontSize=8, textColor=GREY,
fontName="Helvetica", leading=11)
table_hdr = S("TblHdr", fontSize=9, textColor=WHITE,
fontName="Helvetica-Bold", leading=12, alignment=TA_CENTER)
table_cell = S("TblCell", fontSize=8.5,textColor=colors.HexColor("#2C3E50"),
fontName="Helvetica", leading=12)
table_cell_b= S("TblCellB", fontSize=8.5,textColor=colors.HexColor("#2C3E50"),
fontName="Helvetica-Bold", leading=12)
warn_style = S("Warn", fontSize=9, textColor=RED,
fontName="Helvetica-Bold", leading=13,
leftIndent=8, spaceBefore=4, spaceAfter=4)
note_style = S("Note", fontSize=8.5,textColor=colors.HexColor("#5D4037"),
fontName="Helvetica-Oblique", leading=12,
leftIndent=8)
bullet = S("Bullet", fontSize=9, textColor=colors.HexColor("#2C3E50"),
fontName="Helvetica", leading=13,
leftIndent=14, firstLineIndent=-8,
spaceBefore=1, spaceAfter=1)
# ── Helper Flowables ────────────────────────────────────────────────
def section_banner(text, bg=NAVY):
data = [[Paragraph(text, sec_head)]]
t = Table(data, colWidths=[W])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0), (-1,-1), 7),
("BOTTOMPADDING",(0,0),(-1,-1), 7),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING",(0,0), (-1,-1), 10),
("ROUNDEDCORNERS", [4]),
]))
return t
def colored_box(paragraphs, bg=MINT, border=TEAL, radius=4):
data = [[p] for p in paragraphs]
# flatten to single cell
inner = [p for p in paragraphs]
container_data = [[inner[0]] if len(inner)==1 else inner]
# Use a 1-cell table with stacked paragraphs
combined = [p for p in paragraphs]
t = Table([[combined[0]]] if len(combined)==1 else [[combined[0]]],
colWidths=[W])
# Better: put all in one cell using KeepTogether
cell_content = paragraphs
t2 = Table([cell_content], colWidths=[W])
t2.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), bg),
("BOX", (0,0),(-1,-1), 1.2, border),
("TOPPADDING", (0,0),(-1,-1), 8),
("BOTTOMPADDING",(0,0),(-1,-1), 8),
("LEFTPADDING", (0,0),(-1,-1), 10),
("RIGHTPADDING",(0,0),(-1,-1), 10),
]))
return t2
def info_box(title, items, bg=MINT, border=TEAL):
"""Titled box with bullet items."""
rows = []
rows.append(Paragraph(f"<b>{title}</b>", S("IB", fontSize=9.5, textColor=border,
fontName="Helvetica-Bold", leading=13)))
for item in items:
rows.append(Paragraph(f"• {item}", bullet))
data = [[r] for r in rows]
t = Table(data, colWidths=[W])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), bg),
("BOX", (0,0),(-1,-1), 1.5, border),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING",(0,0),(-1,-1), 4),
("LEFTPADDING", (0,0),(-1,-1), 10),
("RIGHTPADDING",(0,0),(-1,-1), 10),
]))
return t
def spacer(h=6):
return Spacer(1, h)
def hr(color=TEAL, thickness=0.8):
return HRFlowable(width="100%", thickness=thickness, color=color,
spaceAfter=4, spaceBefore=4)
# ── COVER PAGE ──────────────────────────────────────────────────────
def build_cover():
elements = []
# Big header band
header_data = [
[Paragraph("UTI IN PREGNANCY", cover_title)],
[Spacer(1, 6)],
[Paragraph("Treatment Protocol Guide", cover_sub)],
[Spacer(1, 4)],
[Paragraph("For Medical Students", cover_meta)],
[Spacer(1, 4)],
[Paragraph("Based on Creasy & Resnik's Maternal-Fetal Medicine | Smith & Tanagho's Urology | Tintinalli's Emergency Medicine", cover_meta)],
]
cover_table = Table(header_data, colWidths=[W])
cover_table.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), NAVY),
("TOPPADDING", (0,0),(-1,-1), 28),
("BOTTOMPADDING", (0,0),(-1,-1), 28),
("LEFTPADDING", (0,0),(-1,-1), 20),
("RIGHTPADDING", (0,0),(-1,-1), 20),
("ROUNDEDCORNERS",[6]),
]))
elements.append(cover_table)
elements.append(spacer(14))
# 3-column quick-facts
qf_style = S("QF", fontSize=8.5, textColor=NAVY, fontName="Helvetica",
leading=13, alignment=TA_CENTER)
qf_num = S("QFN", fontSize=22, textColor=TEAL, fontName="Helvetica-Bold",
leading=26, alignment=TA_CENTER, spaceBefore=4)
def qf_cell(num, label):
return [Paragraph(num, qf_num), Paragraph(label, qf_style)]
qf_data = [
[qf_cell("5–10%", "Prevalence of\nAsymptomatic Bacteriuria"),
qf_cell("2–4%", "Pregnant women\ndevelop Pyelonephritis"),
qf_cell("75%", "Pyelonephritis cases\nare Right-sided")]
]
qf_t = Table(qf_data, colWidths=[W/3]*3)
qf_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), MINT),
("BOX", (0,0),(-1,-1), 1.5, TEAL),
("INNERGRID", (0,0),(-1,-1), 0.5, TEAL),
("TOPPADDING", (0,0),(-1,-1), 14),
("BOTTOMPADDING", (0,0),(-1,-1), 14),
("ALIGN", (0,0),(-1,-1), "CENTER"),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
]))
elements.append(qf_t)
elements.append(spacer(12))
# TOC / overview
toc_items = [
("01", "Pathophysiology", "Why pregnancy increases UTI risk"),
("02", "Classification", "ASB · Cystitis · Pyelonephritis"),
("03", "Microbiology", "Common organisms"),
("04", "Diagnosis", "Screening & investigations"),
("05", "Safe Antibiotics","What to use & what to avoid"),
("06", "Treatment", "Regimens by category"),
("07", "Complications", "Maternal & fetal risks"),
("08", "Prevention", "Suppression & follow-up"),
]
toc_data = []
for num, title_t, desc in toc_items:
toc_data.append([
Paragraph(f"<b>{num}</b>", S("TN", fontSize=10, textColor=TEAL,
fontName="Helvetica-Bold", leading=13, alignment=TA_CENTER)),
Paragraph(f"<b>{title_t}</b>", S("TT", fontSize=9.5, textColor=NAVY,
fontName="Helvetica-Bold", leading=13)),
Paragraph(desc, S("TD", fontSize=9, textColor=GREY,
fontName="Helvetica", leading=13)),
])
toc_t = Table(toc_data, colWidths=[1.2*cm, 5*cm, W - 6.2*cm])
toc_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), LGREY),
("ROWBACKGROUNDS",(0,0),(-1,-1), [LGREY, WHITE]),
("BOX", (0,0),(-1,-1), 1, TEAL),
("LINEBEFORE", (0,0),(0,-1), 3, TEAL),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
("LEFTPADDING", (0,0),(-1,-1), 8),
("RIGHTPADDING", (0,0),(-1,-1), 8),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
]))
elements.append(toc_t)
elements.append(spacer(12))
# Footer note
elements.append(Paragraph(
"⚠ This guide is intended for educational purposes. Always consult current institutional guidelines and senior clinicians for patient management.",
S("FootNote", fontSize=7.5, textColor=GREY, fontName="Helvetica-Oblique",
leading=11, alignment=TA_CENTER)
))
elements.append(PageBreak())
return elements
# ── PAGE 2: PATHOPHYSIOLOGY + CLASSIFICATION ────────────────────────
def build_page2():
e = []
e.append(section_banner("01 | PATHOPHYSIOLOGY OF UTI IN PREGNANCY"))
e.append(spacer(8))
# Two-column layout: anatomic vs physiologic
col1 = [
Paragraph("<b>Anatomic Changes</b>", sub_head),
Paragraph("• Gravid uterus compresses ureters at the pelvic brim", bullet),
Paragraph("• Significant ureteral dilation → hydro-ureter (2nd–3rd trimester)", bullet),
Paragraph("• Renal length increases ~1 cm (↑ vascular/interstitial volume)", bullet),
Paragraph("• Bladder displaced superiorly/anteriorly; incomplete emptying", bullet),
Paragraph("• Mild right hydronephrosis: 75% of women by mid-pregnancy", bullet),
Paragraph("• Mild left hydronephrosis: ~33%", bullet),
]
col2 = [
Paragraph("<b>Physiologic Changes</b>", sub_head),
Paragraph("• Progesterone reduces ureteral + bladder smooth muscle tone", bullet),
Paragraph("• GFR increases 30–50% (↑ cardiac output)", bullet),
Paragraph("• Urinary pH rises (↑ bicarbonate excretion) → ↑ bacterial growth", bullet),
Paragraph("• Glycosuria is common → accelerates bacterial multiplication", bullet),
Paragraph("• ↑ Urinary estrogen excretion → accelerates uropathogenic E. coli growth", bullet),
Paragraph("• Vesicoureteric reflux risk ↑ (↓ bladder tone, ↑ capacity)", bullet),
]
tbl = Table([[col1, col2]], colWidths=[W/2 - 4, W/2 - 4])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,-1), MINT),
("BACKGROUND", (1,0),(1,-1), colors.HexColor("#F0F9FF")),
("BOX", (0,0),(0,-1), 1, TEAL),
("BOX", (1,0),(1,-1), 1, TEAL),
("TOPPADDING", (0,0),(-1,-1), 8),
("BOTTOMPADDING", (0,0),(-1,-1), 8),
("LEFTPADDING", (0,0),(-1,-1), 10),
("RIGHTPADDING", (0,0),(-1,-1), 10),
("VALIGN", (0,0),(-1,-1), "TOP"),
]))
e.append(tbl)
e.append(spacer(12))
e.append(section_banner("02 | CLASSIFICATION", bg=TEAL))
e.append(spacer(8))
# Classification table
cls_header = [
Paragraph("Category", table_hdr),
Paragraph("Definition", table_hdr),
Paragraph("Symptoms", table_hdr),
Paragraph("Timing / Prevalence", table_hdr),
]
cls_rows = [
["Asymptomatic\nBacteriuria (ASB)",
"≥10⁵ CFU/mL on 2 consecutive cultures without symptoms",
"None",
"5–10% of pregnant women\nPeak: 9–17 weeks gestation"],
["Acute Cystitis",
"Symptomatic lower UTI",
"Dysuria, frequency,\nurgency, suprapubic pain\nNo fever",
"1–2% of pregnancies\nAny trimester"],
["Acute\nPyelonephritis",
"Upper UTI involving renal parenchyma",
"Fever >38.5°C, rigors, CVA\ntenderness, N&V, dysuria\nFrequency",
"2–4% of pregnancies\n60–70% in 2nd–3rd trimester"],
]
cls_colors = [MINT, colors.HexColor("#FFF5E6"), RED_BG]
cls_borders = [TEAL, AMBER, RED]
cls_data = [cls_header]
for row in cls_rows:
cls_data.append([Paragraph(str(c), table_cell) for c in row])
cls_t = Table(cls_data, colWidths=[3.2*cm, 5.5*cm, 4.2*cm, W-12.9*cm])
style_cmds = [
("BACKGROUND", (0,0),(-1,0), NAVY),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,0), 9),
("ALIGN", (0,0),(-1,-1), "LEFT"),
("VALIGN", (0,0),(-1,-1), "TOP"),
("GRID", (0,0),(-1,-1), 0.4, colors.HexColor("#BDC3C7")),
("ROWBACKGROUNDS",(0,1),(-1,-1), [MINT, colors.HexColor("#FFF5E6"), RED_BG]),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
("LEFTPADDING", (0,0),(-1,-1), 7),
("RIGHTPADDING", (0,0),(-1,-1), 7),
("FONTNAME", (0,1),(0,-1), "Helvetica-Bold"),
("TEXTCOLOR", (0,1),(0,1), TEAL),
("TEXTCOLOR", (0,2),(0,2), AMBER),
("TEXTCOLOR", (0,3),(0,3), RED),
]
cls_t.setStyle(TableStyle(style_cmds))
e.append(cls_t)
e.append(spacer(12))
e.append(PageBreak())
return e
# ── PAGE 3: MICROBIOLOGY + DIAGNOSIS ────────────────────────────────
def build_page3():
e = []
e.append(section_banner("03 | MICROBIOLOGY"))
e.append(spacer(8))
micro_header = [Paragraph(h, table_hdr) for h in ["Organism", "Frequency", "Notes"]]
micro_rows = [
["Escherichia coli", "70–80%", "Dominant pathogen; P fimbriae mediate adherence to uroepithelium"],
["Group B Streptococcus (GBS)","~10%", "Also screened at 35–37 weeks; important in neonatal sepsis"],
["Klebsiella pneumoniae", "3–7%", "Second most common gram-negative"],
["Staphylococcus aureus", "~7%", "Less common; consider in bacteremia"],
["Proteus mirabilis", "~2%", "Urease-producing; associated with struvite stones"],
["Enterobacter spp.", "~2%", "Gram-negative; less frequent"],
]
micro_data = [micro_header] + [[Paragraph(c, table_cell if i>0 else S("OrgName", fontSize=8.5,
fontName="Helvetica-Oblique" if i==0 else "Helvetica",
textColor=NAVY, leading=12)) for i, c in enumerate(row)]
for row in micro_rows]
micro_t = Table(micro_data, colWidths=[4.5*cm, 2.5*cm, W-7*cm])
micro_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), TEAL),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1), [LGREY, WHITE]),
("GRID", (0,0),(-1,-1), 0.4, colors.HexColor("#BDC3C7")),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
("LEFTPADDING", (0,0),(-1,-1), 8),
("RIGHTPADDING", (0,0),(-1,-1), 8),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("FONTNAME", (0,1),(-1,-1), "Helvetica"),
("FONTSIZE", (0,1),(-1,-1), 8.5),
]))
e.append(micro_t)
e.append(spacer(12))
e.append(section_banner("04 | DIAGNOSIS & SCREENING", bg=TEAL))
e.append(spacer(8))
# Two-column: screening vs investigations
col_l = [
Paragraph("<b>Screening (All Pregnant Women)</b>", sub_head),
Paragraph("• Universal urine culture at <b>first antenatal visit</b> (ideally 12–16 weeks)", bullet),
Paragraph("• Dipstick: positive leukocyte esterase or nitrite → send culture", bullet),
Paragraph("• A negative dipstick does not rule out ASB — culture remains gold standard", bullet),
Paragraph("• Repeat culture after treatment to confirm cure (1–2 weeks post-treatment)", bullet),
Paragraph("• Periodic re-screening in high-risk patients (DM, recurrent UTI, structural anomalies)", bullet),
spacer(6),
Paragraph("<b>Diagnostic Thresholds</b>", sub_head),
Paragraph("• ASB: ≥10⁵ CFU/mL on 2 consecutive midstream clean-catch cultures (no symptoms)", bullet),
Paragraph("• Symptomatic UTI: ≥10² CFU/mL with compatible symptoms", bullet),
Paragraph("• Catheter specimen: ≥10² CFU/mL", bullet),
]
col_r = [
Paragraph("<b>Investigations in Pyelonephritis</b>", sub_head),
Paragraph("• Urinalysis: pyuria, bacteriuria, WBC casts (highly predictive of pyelonephritis)", bullet),
Paragraph("• Urine culture + sensitivities: always obtain before antibiotics", bullet),
Paragraph("• FBC: leukocytosis, may show anaemia (haemolysis in severe cases)", bullet),
Paragraph("• U&E/Creatinine: 7–20% develop transient renal dysfunction", bullet),
Paragraph("• Blood cultures: obtain if febrile or systemically unwell (bacteraemia in 10–20%)", bullet),
Paragraph("• Renal USS: if no improvement in 48–72 hrs (exclude obstruction, abscess)", bullet),
Paragraph("• LFTs, coagulation: if DIC suspected", bullet),
Paragraph("• CTG / fetal monitoring: pyelonephritis can precipitate preterm labour", bullet),
]
diag_tbl = Table([[col_l, col_r]], colWidths=[W/2-4, W/2-4])
diag_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,-1), colors.HexColor("#F0F9FF")),
("BACKGROUND", (1,0),(1,-1), MINT),
("BOX", (0,0),(0,-1), 1, TEAL),
("BOX", (1,0),(1,-1), 1, TEAL),
("TOPPADDING", (0,0),(-1,-1), 8),
("BOTTOMPADDING", (0,0),(-1,-1), 8),
("LEFTPADDING", (0,0),(-1,-1), 8),
("RIGHTPADDING", (0,0),(-1,-1), 8),
("VALIGN", (0,0),(-1,-1), "TOP"),
]))
e.append(diag_tbl)
e.append(PageBreak())
return e
# ── PAGE 4: ANTIBIOTIC SAFETY ────────────────────────────────────────
def build_page4():
e = []
e.append(section_banner("05 | ANTIBIOTIC SAFETY IN PREGNANCY"))
e.append(spacer(8))
ab_header = [Paragraph(h, table_hdr) for h in
["Antibiotic", "Trimester Safety", "Fetal/Neonatal Risk", "Use in UTI"]]
ab_rows = [
["Penicillins\n(amoxicillin,\nampicillin)", "✔ All trimesters", "None known — SAFE", "1st-line cystitis/ASB\nIV ampicillin for pyelonephritis"],
["Cephalosporins\n(cephalexin,\ncefazolin,\nceftriaxone)", "✔ All trimesters", "None known — SAFE", "1st-line for all UTI categories\nCefazolin 1–2 g IV preferred for pyelonephritis"],
["Nitrofurantoin", "✔ 1st–2nd trimester\n✖ 3rd trimester / term", "3rd trimester: haemolysis\n(G6PD deficiency)\nAvoid at term (neonatal haemolysis)", "Lower UTI only\nNOT for pyelonephritis\n(poor tissue penetration)"],
["Trimethoprim", "⚠ Avoid 1st trimester\n✔ 2nd trimester only", "Folate antagonist →\nneural tube defects (1st trimester)\nAcceptable 2nd trimester", "Avoid if alternatives available"],
["Sulfonamides\n(TMP-SMX)", "✔ 1st–2nd trimester\n✖ 3rd trimester", "3rd trimester: kernicterus\n(displaces bilirubin from albumin)", "Use with caution; avoid 3rd trimester"],
["Fluoroquinolones\n(ciprofloxacin,\nnorfloxacin)", "✖ ALL trimesters\n(relative contraindication)", "Cartilage formation defects;\narthropathy in animal studies", "AVOID throughout pregnancy"],
["Tetracyclines", "✖ ALL trimesters", "Dysplasia + discolouration\nof teeth and bones", "AVOID throughout pregnancy"],
["Aminoglycosides\n(gentamicin)", "⚠ Use with extreme caution", "Fetal ototoxicity;\nnephrotoxicity", "Reserve for severe pyelonephritis +\nresistant organisms only"],
]
ab_bg = [GREEN_BG, GREEN_BG, AMBER_BG, AMBER_BG, AMBER_BG, RED_BG, RED_BG, AMBER_BG]
ab_data = [ab_header]
for i, row in enumerate(ab_rows):
ab_data.append([Paragraph(str(c), table_cell) for c in row])
ab_t = Table(ab_data, colWidths=[3.5*cm, 3.2*cm, 4.5*cm, W-11.2*cm])
style = [
("BACKGROUND", (0,0),(-1,0), NAVY),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("GRID", (0,0),(-1,-1), 0.4, colors.HexColor("#BDC3C7")),
("VALIGN", (0,0),(-1,-1), "TOP"),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
("LEFTPADDING", (0,0),(-1,-1), 7),
("RIGHTPADDING", (0,0),(-1,-1), 7),
("FONTNAME", (0,1),(-1,-1), "Helvetica"),
("FONTSIZE", (0,1),(-1,-1), 8),
]
for i, bg in enumerate(ab_bg):
style.append(("BACKGROUND", (0, i+1), (-1, i+1), bg))
ab_t.setStyle(TableStyle(style))
e.append(ab_t)
e.append(spacer(10))
# Legend
leg_data = [[
Paragraph("✔ SAFE", S("L", fontSize=8, fontName="Helvetica-Bold", textColor=GREEN, leading=11)),
Paragraph("⚠ CAUTION", S("L2", fontSize=8, fontName="Helvetica-Bold", textColor=AMBER, leading=11)),
Paragraph("✖ AVOID", S("L3", fontSize=8, fontName="Helvetica-Bold", textColor=RED, leading=11)),
Paragraph("Green = safe | Amber = caution / trimester-dependent | Red = contraindicated",
S("L4", fontSize=7.5, fontName="Helvetica", textColor=GREY, leading=11)),
]]
leg_t = Table(leg_data, colWidths=[2*cm, 2.5*cm, 2*cm, W-6.5*cm])
leg_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), LGREY),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 8),
("RIGHTPADDING", (0,0),(-1,-1), 8),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
]))
e.append(leg_t)
e.append(PageBreak())
return e
# ── PAGE 5: TREATMENT REGIMENS ───────────────────────────────────────
def build_page5():
e = []
e.append(section_banner("06 | TREATMENT REGIMENS"))
e.append(spacer(8))
# ─ ASB ─
e.append(Table([[Paragraph("A. ASYMPTOMATIC BACTERIURIA (ASB)", S("SH2",
fontSize=10.5, textColor=TEAL, fontName="Helvetica-Bold", leading=13))]],
colWidths=[W], style=[("BACKGROUND",(0,0),(-1,-1),MINT),
("LEFTPADDING",(0,0),(-1,-1),10),("TOPPADDING",(0,0),(-1,-1),6),
("BOTTOMPADDING",(0,0),(-1,-1),6)]))
e.append(spacer(5))
asb_data = [
[Paragraph("<b>Drug</b>", table_hdr), Paragraph("<b>Dose / Frequency</b>", table_hdr),
Paragraph("<b>Duration</b>", table_hdr), Paragraph("<b>Notes</b>", table_hdr)],
[Paragraph("Cephalexin", table_cell_b), Paragraph("500 mg PO 2–4× daily", table_cell),
Paragraph("3–7 days", table_cell), Paragraph("Preferred 1st-line", table_cell)],
[Paragraph("Amoxicillin", table_cell_b), Paragraph("500 mg PO 2–3× daily", table_cell),
Paragraph("3–7 days", table_cell), Paragraph("If susceptibility confirmed", table_cell)],
[Paragraph("Amoxicillin-Clavulanate", table_cell_b), Paragraph("625 mg PO 3× daily", table_cell),
Paragraph("3–7 days", table_cell), Paragraph("Use if resistant organism", table_cell)],
[Paragraph("Nitrofurantoin", table_cell_b), Paragraph("100 mg MR PO twice daily", table_cell),
Paragraph("5–7 days", table_cell), Paragraph("1st–2nd trimester ONLY; NOT in 3rd trimester", table_cell)],
]
asb_t = Table(asb_data, colWidths=[3.8*cm, 4.2*cm, 2.5*cm, W-10.5*cm])
asb_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), TEAL),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, LGREY]),
("GRID", (0,0),(-1,-1), 0.4, colors.HexColor("#BDC3C7")),
("TOPPADDING", (0,0),(-1,-1), 5), ("BOTTOMPADDING",(0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 7), ("RIGHTPADDING", (0,0),(-1,-1), 7),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
]))
e.append(asb_t)
e.append(spacer(4))
e.append(Paragraph("→ Follow-up urine culture 1–2 weeks after completing treatment. Treat each recurrence; consider suppressive therapy.", note_style))
e.append(spacer(10))
# ─ Cystitis ─
e.append(Table([[Paragraph("B. ACUTE CYSTITIS", S("SH3",
fontSize=10.5, textColor=AMBER, fontName="Helvetica-Bold", leading=13))]],
colWidths=[W], style=[("BACKGROUND",(0,0),(-1,-1),AMBER_BG),
("LEFTPADDING",(0,0),(-1,-1),10),("TOPPADDING",(0,0),(-1,-1),6),
("BOTTOMPADDING",(0,0),(-1,-1),6)]))
e.append(spacer(5))
e.append(Paragraph("Use same agents as for ASB above. Confirm sensitivity pattern. Duration: <b>5–7 days</b> (longer than non-pregnant). Follow-up culture mandatory.", body))
e.append(spacer(10))
# ─ Pyelonephritis ─
e.append(Table([[Paragraph("C. ACUTE PYELONEPHRITIS", S("SH4",
fontSize=10.5, textColor=RED, fontName="Helvetica-Bold", leading=13))]],
colWidths=[W], style=[("BACKGROUND",(0,0),(-1,-1),RED_BG),
("LEFTPADDING",(0,0),(-1,-1),10),("TOPPADDING",(0,0),(-1,-1),6),
("BOTTOMPADDING",(0,0),(-1,-1),6)]))
e.append(spacer(5))
pye_data = [
[Paragraph("<b>Setting</b>", table_hdr), Paragraph("<b>Drug</b>", table_hdr),
Paragraph("<b>Dose</b>", table_hdr), Paragraph("<b>Duration</b>", table_hdr)],
[Paragraph("IV (hospital)\n1st-line", table_cell_b),
Paragraph("Cefazolin", table_cell_b),
Paragraph("1–2 g IV every 8 hours", table_cell),
Paragraph("IV until afebrile 24–48 hrs;\nthen oral ×10–14 days total", table_cell)],
[Paragraph("IV (hospital)\nalternative", table_cell_b),
Paragraph("Ampicillin\n+ Gentamicin", table_cell),
Paragraph("Ampicillin 2 g IV q6h\nGentamicin 5 mg/kg IV once daily", table_cell),
Paragraph("Caution with gentamicin\n(monitor renal function)", table_cell)],
[Paragraph("Oral step-down\n(after IV)", table_cell_b),
Paragraph("Cephalexin\nor Amoxicillin-Clav", table_cell),
Paragraph("500 mg PO 4× daily\nor 625 mg PO 3× daily", table_cell),
Paragraph("Complete 10–14 days total", table_cell)],
]
pye_t = Table(pye_data, colWidths=[3.5*cm, 3.8*cm, 5*cm, W-12.3*cm])
pye_t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), colors.HexColor("#8B1A1A")),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("ROWBACKGROUNDS",(0,1),(-1,-1), [RED_BG, colors.HexColor("#FDF0EF"), RED_BG]),
("GRID", (0,0),(-1,-1), 0.4, colors.HexColor("#BDC3C7")),
("TOPPADDING", (0,0),(-1,-1), 6), ("BOTTOMPADDING",(0,0),(-1,-1), 6),
("LEFTPADDING", (0,0),(-1,-1), 7), ("RIGHTPADDING", (0,0),(-1,-1), 7),
("VALIGN", (0,0),(-1,-1), "TOP"),
]))
e.append(pye_t)
e.append(spacer(6))
# Pyelonephritis management steps
pye_mgmt = [
"Hospital admission is strongly recommended for all cases of pyelonephritis in pregnancy",
"Aggressive IV fluid resuscitation — reduces rate of transient renal dysfunction from ~20% to ~7%",
"Urine culture + sensitivities before first antibiotic dose",
"Blood cultures if systemically unwell or bacteraemia suspected",
"Regular monitoring: temperature, HR, RR, O₂ saturation, urine output, fetal CTG",
"If no improvement in 48–72 hrs → renal USS to exclude obstruction/abscess",
"Watch for ARDS (2–8%): dyspnoea, tachypnoea, hypoxia, pulmonary oedema on CXR",
"Suppressive antibiotics for the remainder of pregnancy after an episode of pyelonephritis",
]
e.append(info_box("Pyelonephritis Management Checklist", pye_mgmt, bg=RED_BG, border=RED))
e.append(PageBreak())
return e
# ── PAGE 6: COMPLICATIONS + PREVENTION ──────────────────────────────
def build_page6():
e = []
e.append(section_banner("07 | COMPLICATIONS"))
e.append(spacer(8))
col_mat = [
Paragraph("<b>Maternal Complications</b>", S("CH", fontSize=10, textColor=RED,
fontName="Helvetica-Bold", leading=13)),
Paragraph("• Septic shock — pyelonephritis is one of the most common causes in pregnancy", bullet),
Paragraph("• ARDS in 2–8% of pyelonephritis cases (cytokine-mediated endothelial injury)", bullet),
Paragraph("• Multiorgan dysfunction: up to 20% of pyelonephritis patients", bullet),
Paragraph("• Haemolytic anaemia, DIC (severe sepsis)", bullet),
Paragraph("• Transient renal dysfunction: ~7% with aggressive fluids; ~20% without", bullet),
Paragraph("• Recurrent pyelonephritis in 10–20% before delivery", bullet),
spacer(4),
Paragraph("<b>ARDS Risk Predictors in Pyelonephritis:</b>", body_bold),
Paragraph("• Maternal HR >110 bpm", bullet),
Paragraph("• Temp ≥103°F (39.4°C) within first 24 hrs", bullet),
Paragraph("• Tocolytic agent use", bullet),
Paragraph("• Ampicillin as sole antibiotic", bullet),
Paragraph("• Fluid overload", bullet),
]
col_fet = [
Paragraph("<b>Fetal / Obstetric Complications</b>", S("CH2", fontSize=10, textColor=AMBER,
fontName="Helvetica-Bold", leading=13)),
Paragraph("• Preterm labour — pyelonephritis is one of the most common identifiable causes\n(cytokine-mediated uterine contractions)", bullet),
Paragraph("• Low birth weight", bullet),
Paragraph("• Increased perinatal mortality (with untreated pyelonephritis)", bullet),
Paragraph("• Risk of neonatal sepsis (GBS bacteriuria warrants intrapartum prophylaxis)", bullet),
spacer(4),
Paragraph("<b>Consequences of Untreated ASB:</b>", body_bold),
Paragraph("• Progresses to pyelonephritis in 20–40% (vs <2% in non-pregnant women)", bullet),
Paragraph("• Associated with low birth weight and preterm delivery", bullet),
Paragraph("• This is why screening + treatment of ASB is mandatory in pregnancy", bullet),
spacer(4),
Paragraph("<b>Reflux Nephropathy (if present):</b>", body_bold),
Paragraph("• Increases risk of sudden escalating hypertension", bullet),
Paragraph("• Risk of worsening renal function during pregnancy", bullet),
]
comp_tbl = Table([[col_mat, col_fet]], colWidths=[W/2-4, W/2-4])
comp_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,-1), RED_BG),
("BACKGROUND", (1,0),(1,-1), AMBER_BG),
("BOX", (0,0),(0,-1), 1.5, RED),
("BOX", (1,0),(1,-1), 1.5, AMBER),
("TOPPADDING", (0,0),(-1,-1), 8),
("BOTTOMPADDING", (0,0),(-1,-1), 8),
("LEFTPADDING", (0,0),(-1,-1), 10),
("RIGHTPADDING", (0,0),(-1,-1), 10),
("VALIGN", (0,0),(-1,-1), "TOP"),
]))
e.append(comp_tbl)
e.append(spacer(12))
e.append(section_banner("08 | PREVENTION & FOLLOW-UP", bg=GREEN))
e.append(spacer(8))
prev_col1 = [
Paragraph("<b>Suppressive Antibiotic Therapy</b>", sub_head),
Paragraph("Indications:", body_bold),
Paragraph("• ≥2 UTIs during pregnancy", bullet),
Paragraph("• After an episode of pyelonephritis", bullet),
Paragraph("• Structural urinary tract abnormality", bullet),
Paragraph("• Reflux nephropathy", bullet),
spacer(4),
Paragraph("Agents for nightly suppression:", body_bold),
Paragraph("• Cephalexin 250–500 mg at bedtime", bullet),
Paragraph("• Nitrofurantoin 50–100 mg at bedtime (1st–2nd trimester only)", bullet),
Paragraph("• Amoxicillin 250 mg at bedtime (if susceptible)", bullet),
spacer(4),
Paragraph("<b>Duration:</b> Until 4–6 weeks postpartum, then reassess with urine culture.", body),
]
prev_col2 = [
Paragraph("<b>General Prevention Measures</b>", sub_head),
Paragraph("• Adequate hydration (8+ glasses of water/day)", bullet),
Paragraph("• Void frequently — avoid prolonged bladder distension", bullet),
Paragraph("• Void before and after intercourse", bullet),
Paragraph("• Wipe front-to-back after toileting", bullet),
Paragraph("• Avoid catheterisation unless essential", bullet),
spacer(4),
Paragraph("<b>Monitoring Schedule</b>", body_bold),
Paragraph("• Urine culture at first antenatal visit (12–16 weeks)", bullet),
Paragraph("• Culture 1–2 weeks after completing any UTI treatment", bullet),
Paragraph("• Culture each trimester in high-risk patients (DM, sickle cell, structural abnormality)", bullet),
Paragraph("• Postnatal urine culture at 6-week check", bullet),
Paragraph("• Renal imaging postpartum if recurrent UTI or structural concern", bullet),
]
prev_tbl = Table([[prev_col1, prev_col2]], colWidths=[W/2-4, W/2-4])
prev_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,-1), GREEN_BG),
("BACKGROUND", (1,0),(1,-1), colors.HexColor("#F0FFF4")),
("BOX", (0,0),(0,-1), 1.5, GREEN),
("BOX", (1,0),(1,-1), 1.5, GREEN),
("TOPPADDING", (0,0),(-1,-1), 8),
("BOTTOMPADDING", (0,0),(-1,-1), 8),
("LEFTPADDING", (0,0),(-1,-1), 10),
("RIGHTPADDING", (0,0),(-1,-1), 10),
("VALIGN", (0,0),(-1,-1), "TOP"),
]))
e.append(prev_tbl)
e.append(spacer(10))
# References
e.append(hr(color=GREY, thickness=0.5))
e.append(spacer(4))
e.append(Paragraph("<b>Sources:</b>", S("RefHdr", fontSize=8, fontName="Helvetica-Bold",
textColor=GREY, leading=11)))
refs = [
"Creasy & Resnik's Maternal-Fetal Medicine: Principles and Practice (9780323828499), Chapters on UTI and Pyelonephritis in Pregnancy, pp. 1124–1130",
"Smith and Tanagho's General Urology, 19th Edition (9781259834332), Chapter 14: UTI Related to Pregnancy, p. 234–235",
"Tintinalli's Emergency Medicine: A Comprehensive Study Guide (9781260019933), Chapter 99: Asymptomatic Bacteriuria, Cystitis and Pyelonephritis, pp. 667–668",
"Comprehensive Clinical Nephrology, 7th Edition (9780323825924), Chapter: Kidney Disease in Pregnancy",
"ACOG Practice Bulletin No. 91: Treatment of Urinary Tract Infections During Pregnancy",
]
for r in refs:
e.append(Paragraph(f"• {r}", S("Ref", fontSize=7.5, fontName="Helvetica",
textColor=GREY, leading=11, leftIndent=10, firstLineIndent=-8,
spaceBefore=2)))
return e
# ── Page number canvas callback ─────────────────────────────────────
def on_page(canvas, doc):
canvas.saveState()
canvas.setFont("Helvetica", 8)
canvas.setFillColor(GREY)
w, h = A4
canvas.drawRightString(w - 1.8*cm, 1.3*cm, f"Page {doc.page}")
canvas.drawString(1.8*cm, 1.3*cm, "UTI in Pregnancy – Treatment Protocol | Orris Medical Education")
canvas.setStrokeColor(TEAL)
canvas.setLineWidth(0.5)
canvas.line(1.8*cm, 1.6*cm, w - 1.8*cm, 1.6*cm)
canvas.restoreState()
# ── Build ────────────────────────────────────────────────────────────
story = []
story += build_cover()
story += build_page2()
story += build_page3()
story += build_page4()
story += build_page5()
story += build_page6()
doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
print(f"PDF created: {OUTPUT_PATH}")
cd /tmp/workspace/uti_protocol && python generate_pdf.py 2>&1
ls -lh /tmp/workspace/uti_protocol/UTI_in_Pregnancy_Protocol.pdf
UTI in Pregnancy Protocol
PDF Document · PDF
| Section | Content |
|---|---|
| Cover | Title banner, quick-stats panel (5-10% ASB prevalence, 2-4% pyelonephritis, 75% right-sided), visual table of contents |
| 01 - Pathophysiology | Two-column layout: anatomic changes vs physiologic changes during pregnancy |
| 02 - Classification | Colour-coded table: ASB / Acute Cystitis / Acute Pyelonephritis with definitions, symptoms, timing |
| 03 - Microbiology | Organism frequency table with clinical notes (E. coli dominant at 70-80%) |
| 04 - Diagnosis | Screening protocol + investigation checklist for pyelonephritis |
| 05 - Antibiotic Safety | Full colour-coded table: safe (green) / caution (amber) / avoid (red) for each antibiotic class by trimester |
| 06 - Treatment Regimens | Specific dose tables for ASB, cystitis, and IV/oral pyelonephritis; management checklist |
| 07 - Complications | Maternal (ARDS, septic shock, renal dysfunction) and fetal (preterm labour, low birth weight) risks |
| 08 - Prevention | Suppressive therapy indications + agents; monitoring schedule throughout pregnancy |