n acetylcysteine in recurrent uti
N-acetylcysteine urinary tract infection recurrent
PMID: 37630763
PMID: 34438950
N-acetylcysteine biofilm urinary catheter
PMID: 37965267
PMID: 40726828
N-acetylcysteine recurrent cystitis clinical trial prevention
acetylcysteine D-mannose hyaluronic acid UTI prevention combination
N-acetylcysteine recurrent UTI clinical evidence mechanism 2023 2024
| Level | Evidence |
|---|---|
| In vitro | Strong - inhibits invasion, biofilm, urease across multiple uropathogens |
| Animal/model | Positive - catheter bladder models show 4-8 log reduction in viable bacteria |
| Clinical RCT | Very limited - no large, dedicated RCT on NAC monotherapy for recurrent UTI |
| Guidelines | Not included in AUA 2024 rUTI guidelines; not in standard prophylaxis recommendations |
Create a clinical summary or quick reference PDF on NAC mechanisms and dosing
ls -la /home/daytona/workspace/ 2>/dev/null || echo "workspace empty or not found"
mkdir -p /home/daytona/workspace/nac-uti-pdf
~/nac-uti-pdf/generate_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import mm, cm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate
from reportlab.lib.colors import HexColor
OUTPUT = "/home/daytona/workspace/nac-uti-pdf/NAC_in_Recurrent_UTI_Clinical_Reference.pdf"
# --- Color palette ---
DARK_BLUE = HexColor("#1A3A5C")
MED_BLUE = HexColor("#2563A8")
LIGHT_BLUE = HexColor("#D6E4F7")
ACCENT = HexColor("#0E7A6E") # teal for secondary headers
ACCENT_LIGHT= HexColor("#D0F0EC")
ORANGE = HexColor("#C0522B")
ORANGE_LIGHT= HexColor("#FAE5DA")
GREY_BG = HexColor("#F4F6F9")
GREY_LINE = HexColor("#C8D0DB")
WHITE = colors.white
BLACK = colors.black
W, H = A4 # 595.27 x 841.89 pts
# --- Page drawing callbacks ---
def draw_header(canvas, doc):
canvas.saveState()
# Top banner
canvas.setFillColor(DARK_BLUE)
canvas.rect(0, H - 52, W, 52, fill=1, stroke=0)
canvas.setFillColor(WHITE)
canvas.setFont("Helvetica-Bold", 17)
canvas.drawString(20, H - 28, "N-Acetylcysteine (NAC) in Recurrent UTI")
canvas.setFont("Helvetica", 9)
canvas.drawString(20, H - 43, "Clinical Quick Reference | Mechanisms, Dosing & Evidence")
# Right badge
canvas.setFillColor(ACCENT)
canvas.roundRect(W - 110, H - 48, 98, 36, 6, fill=1, stroke=0)
canvas.setFillColor(WHITE)
canvas.setFont("Helvetica-Bold", 8)
canvas.drawCentredString(W - 61, H - 30, "UROLOGY / ID")
canvas.setFont("Helvetica", 7)
canvas.drawCentredString(W - 61, H - 41, "Quick Reference Card")
# Footer
canvas.setFillColor(GREY_LINE)
canvas.rect(0, 0, W, 22, fill=1, stroke=0)
canvas.setFillColor(DARK_BLUE)
canvas.setFont("Helvetica", 7.5)
canvas.drawString(20, 7, "For clinical guidance only. Not a substitute for professional judgment. Sources: Manoharan et al. 2021/2023/2025; Crocetto et al. 2023.")
canvas.drawRightString(W - 20, 7, f"Page {doc.page}")
canvas.restoreState()
def draw_first_page(canvas, doc):
draw_header(canvas, doc)
# --- Document setup ---
doc = BaseDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=18*mm, rightMargin=18*mm,
topMargin=60, bottomMargin=30,
title="NAC in Recurrent UTI - Clinical Quick Reference",
author="Orris Clinical Reference"
)
frame = Frame(doc.leftMargin, doc.bottomMargin,
doc.width, doc.height, id='normal')
doc.addPageTemplates([
PageTemplate(id='all', frames=frame, onPage=draw_header)
])
# --- Styles ---
styles = getSampleStyleSheet()
def S(name, **kwargs):
return ParagraphStyle(name, **kwargs)
body = S("body", fontSize=9, leading=13, textColor=BLACK, spaceAfter=4,
fontName="Helvetica")
body_j = S("body_j", fontSize=9, leading=13, textColor=BLACK, spaceAfter=4,
fontName="Helvetica", alignment=TA_JUSTIFY)
bold_body = S("bold_body", fontSize=9, leading=13, textColor=BLACK, spaceAfter=3,
fontName="Helvetica-Bold")
section_hdr = S("sec_hdr", fontSize=11, leading=14, textColor=WHITE,
fontName="Helvetica-Bold", alignment=TA_LEFT,
backColor=DARK_BLUE, spaceBefore=8, spaceAfter=0,
leftIndent=0)
sub_hdr = S("sub_hdr", fontSize=9.5, leading=12, textColor=DARK_BLUE,
fontName="Helvetica-Bold", spaceBefore=5, spaceAfter=2)
bullet = S("bullet", fontSize=9, leading=13, textColor=BLACK,
fontName="Helvetica", leftIndent=12, bulletIndent=2,
spaceAfter=2)
small = S("small", fontSize=7.5, leading=10, textColor=HexColor("#555555"),
fontName="Helvetica", spaceAfter=2)
note = S("note", fontSize=8, leading=11, textColor=HexColor("#333333"),
fontName="Helvetica-Oblique", spaceAfter=3)
warn = S("warn", fontSize=8.5, leading=12, textColor=ORANGE,
fontName="Helvetica-Bold", spaceAfter=3)
def section_title(text, bg=DARK_BLUE, fg=WHITE):
tbl = Table([[Paragraph(f" {text}", S("sh", fontSize=10.5,
fontName="Helvetica-Bold", textColor=fg, leading=14))]],
colWidths=[doc.width])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("ROUNDEDCORNERS", [4]),
]))
return tbl
def accent_section(text):
return section_title(text, bg=ACCENT, fg=WHITE)
def orange_section(text):
return section_title(text, bg=ORANGE, fg=WHITE)
def info_box(paragraphs, bg=LIGHT_BLUE, border=MED_BLUE):
inner = [[p] for p in paragraphs]
flat = [[item] for sublist in [[p] for p in paragraphs] for item in [sublist[0]]]
tbl = Table([[Paragraph(p.text if hasattr(p,'text') else '', p)
if not isinstance(p, str) else Paragraph(p, body)
for _ in [1]] for p in paragraphs],
colWidths=[doc.width - 16])
# Use a simpler approach: stack all paras in one cell
cell_content = paragraphs
tbl2 = Table([cell_content], colWidths=[doc.width])
# Actually best: one column, each para in its own row
rows = [[p] for p in paragraphs]
tbl3 = Table(rows, colWidths=[doc.width])
tbl3.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("LINEAFTER", (0,0), (0,-1), 3, border),
("LINEBEFORE", (0,0), (0,-1), 3, border),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
]))
return tbl3
# ============================================================
# BUILD CONTENT
# ============================================================
story = []
# ---- INTRO BOX ----
intro_rows = [
[Paragraph("<b>What is NAC?</b>", S("ib", fontSize=9.5, fontName="Helvetica-Bold",
textColor=DARK_BLUE, leading=13)),
Paragraph(
"N-Acetylcysteine (NAC) is a thiol-containing antioxidant and glutathione precursor. "
"In the urinary tract it acts as a mucolytic, anti-biofilm, anti-inflammatory, and "
"anti-invasive agent. It is not an antibiotic, carries no resistance risk, and has a "
"well-established safety profile.",
S("ib2", fontSize=9, fontName="Helvetica", textColor=BLACK, leading=13))]
]
intro_tbl = Table(intro_rows, colWidths=[110, doc.width - 110])
intro_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), LIGHT_BLUE),
("VALIGN", (0,0), (-1,-1), "TOP"),
("LINEABOVE", (0,0), (-1,0), 2, MED_BLUE),
("LINEBELOW", (0,-1), (-1,-1), 2, MED_BLUE),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
]))
story.append(intro_tbl)
story.append(Spacer(1, 8))
# ============================================================
# SECTION 1: MECHANISMS
# ============================================================
story.append(section_title("1. Mechanisms of Action in Recurrent UTI"))
story.append(Spacer(1, 6))
mech_data = [
# header row
[
Paragraph("<b>Mechanism</b>", S("th", fontSize=9, fontName="Helvetica-Bold",
textColor=WHITE, leading=12)),
Paragraph("<b>Detail</b>", S("th2", fontSize=9, fontName="Helvetica-Bold",
textColor=WHITE, leading=12)),
Paragraph("<b>Pathogens / Context</b>", S("th3", fontSize=9, fontName="Helvetica-Bold",
textColor=WHITE, leading=12)),
],
[
Paragraph("<b>Anti-biofilm</b>", S("mc", fontSize=8.5, fontName="Helvetica-Bold",
textColor=DARK_BLUE, leading=12)),
Paragraph(
"Cleaves disulfide bonds in extracellular polymeric substance (EPS). "
"Inhibits biofilm formation and reduces viable counts in 48-h preformed biofilms. "
"Alters bacterial surface structure, impairing initial attachment.",
S("md", fontSize=8.5, fontName="Helvetica", leading=12)),
Paragraph("<i>E. coli, E. faecalis, P. aeruginosa, P. mirabilis</i>",
S("mp", fontSize=8.5, fontName="Helvetica-Oblique", leading=12)),
],
[
Paragraph("<b>Prevents Intracellular Bacterial Communities (IBCs)</b>",
S("mc2", fontSize=8.5, fontName="Helvetica-Bold", textColor=DARK_BLUE, leading=12)),
Paragraph(
"UPEC invades bladder epithelial cells (BECs), forming quiescent reservoirs that "
"survive antibiotic courses and seed relapse. NAC completely inhibits BEC invasion "
"by UPEC and E. faecalis in a dose-dependent manner (p<0.01) with no cytotoxicity "
"to host cells (>90% viability at 48 h).",
S("md2", fontSize=8.5, fontName="Helvetica", leading=12)),
Paragraph("Recurrent <i>E. coli</i> UTI (most common cause of rUTI)",
S("mp2", fontSize=8.5, fontName="Helvetica-Oblique", leading=12)),
],
[
Paragraph("<b>Urease inhibition</b>",
S("mc3", fontSize=8.5, fontName="Helvetica-Bold", textColor=DARK_BLUE, leading=12)),
Paragraph(
"Inhibits P. mirabilis urease at >=1 mM, preventing ammonia-driven urine "
"alkalinization, struvite crystal formation, and catheter occlusion. Independent "
"of bactericidal action. Bacteriostatic effect also observed.",
S("md3", fontSize=8.5, fontName="Helvetica", leading=12)),
Paragraph("Catheter-associated UTI (CA-UTI); <i>Proteus mirabilis</i>",
S("mp3", fontSize=8.5, fontName="Helvetica-Oblique", leading=12)),
],
[
Paragraph("<b>Anti-inflammatory</b>",
S("mc4", fontSize=8.5, fontName="Helvetica-Bold", textColor=DARK_BLUE, leading=12)),
Paragraph(
"Reduces IL-6, IL-8, and IL-1beta production in BECs exposed to P. mirabilis "
"and urease. Antioxidant action via glutathione replenishment limits oxidative "
"epithelial damage, reducing vulnerability to re-infection.",
S("md4", fontSize=8.5, fontName="Helvetica", leading=12)),
Paragraph("Urothelial protection; post-infection recovery",
S("mp4", fontSize=8.5, fontName="Helvetica-Oblique", leading=12)),
],
[
Paragraph("<b>Synergy with antibiotics</b>",
S("mc5", fontSize=8.5, fontName="Helvetica-Bold", textColor=DARK_BLUE, leading=12)),
Paragraph(
"Combination of NAC + ciprofloxacin significantly reduces bacterial loads in "
"preformed biofilms beyond either agent alone. Disrupts biofilm matrix, improving "
"antibiotic penetration.",
S("md5", fontSize=8.5, fontName="Helvetica", leading=12)),
Paragraph("Biofilm-mediated recurrent UTI; treatment failure cases",
S("mp5", fontSize=8.5, fontName="Helvetica-Oblique", leading=12)),
],
]
col_w = [120, doc.width - 120 - 110, 110]
mech_tbl = Table(mech_data, colWidths=col_w, repeatRows=1)
mech_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("BACKGROUND", (0,1), (-1,1), GREY_BG),
("BACKGROUND", (0,2), (-1,2), WHITE),
("BACKGROUND", (0,3), (-1,3), GREY_BG),
("BACKGROUND", (0,4), (-1,4), WHITE),
("BACKGROUND", (0,5), (-1,5), GREY_BG),
("VALIGN", (0,0), (-1,-1), "TOP"),
("GRID", (0,0), (-1,-1), 0.4, GREY_LINE),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("LINEABOVE", (0,0), (-1,0), 0, DARK_BLUE),
("LINEBELOW", (0,-1), (-1,-1), 1.2, DARK_BLUE),
]))
story.append(mech_tbl)
story.append(Spacer(1, 10))
# ============================================================
# SECTION 2: DOSING
# ============================================================
story.append(section_title("2. Dosing Guidance"))
story.append(Spacer(1, 6))
# Two-column layout for dosing
dose_left = [
Paragraph("<b>Oral (systemic) - most studied for UTI:</b>", sub_hdr),
Paragraph("600 mg <b>2-3 times daily</b> (total 1200-1800 mg/day)", body),
Paragraph("- Duration: typically 3-6 months for prophylaxis", bullet),
Paragraph("- Taken with food to reduce GI upset", bullet),
Paragraph("- No consensus clinical dose specific to UTI; extrapolated from in vitro MIC data and "
"combination product trials", note),
Spacer(1, 6),
Paragraph("<b>Intravesical (investigational):</b>", sub_hdr),
Paragraph("Used in catheter-flushing protocols in research settings. Not standard of care.", body),
Spacer(1, 6),
Paragraph("<b>Combination products (e.g. Uroial PLUS):</b>", sub_hdr),
Paragraph("NAC 200 mg + D-mannose + hyaluronic acid + chondroitin sulphate", body),
Paragraph("- 1 sachet once daily for 30-90 days (per manufacturer)", bullet),
Paragraph("- Available in Italy/Europe; not FDA-approved for UTI indication", bullet),
]
dose_right = [
Paragraph("<b>Key Pharmacology:</b>", sub_hdr),
Paragraph("<b>Bioavailability:</b> ~10% oral (first-pass effect); IV bypasses this", body),
Paragraph("<b>Urinary excretion:</b> NAC and metabolites excreted in urine - direct contact "
"with uroepithelium achieved at therapeutic concentrations", body),
Paragraph("<b>pH:</b> Intrinsic pH ~2.6 (acidic); does not damage BECs at therapeutic concentrations", body),
Paragraph("<b>Half-life:</b> ~6 hours oral", body),
Spacer(1, 6),
Paragraph("<b>Safety Profile:</b>", sub_hdr),
Paragraph("- No cytotoxicity to bladder epithelial cells in vitro", bullet),
Paragraph("- Common side effects: nausea, GI upset (oral); rash rare", bullet),
Paragraph("- No antibiotic resistance risk", bullet),
Paragraph("- Safe in renal impairment (no dose adjustment needed at standard doses)", bullet),
Paragraph("- Pregnancy: Category B (animal studies reassuring; human data limited)", bullet),
]
# Wrap each column into a sub-table
def mini_col(items):
rows = [[item] for item in items]
t = Table(rows, colWidths=[(doc.width/2) - 6])
t.setStyle(TableStyle([
("TOPPADDING", (0,0), (-1,-1), 1),
("BOTTOMPADDING", (0,0), (-1,-1), 1),
("LEFTPADDING", (0,0), (-1,-1), 0),
("RIGHTPADDING", (0,0), (-1,-1), 0),
]))
return t
two_col = Table([[mini_col(dose_left), mini_col(dose_right)]],
colWidths=[doc.width/2 - 3, doc.width/2 - 3],
hAlign='LEFT')
two_col.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("LINEBETWEEN", (0,0), (1,0), 0.5, GREY_LINE),
("TOPPADDING", (0,0), (-1,-1), 0),
("BOTTOMPADDING", (0,0), (-1,-1), 0),
("LEFTPADDING", (0,0), (-1,-1), 4),
("RIGHTPADDING", (0,0), (-1,-1), 4),
]))
story.append(two_col)
story.append(Spacer(1, 10))
# ============================================================
# SECTION 3: EVIDENCE SUMMARY
# ============================================================
story.append(accent_section("3. Evidence Summary"))
story.append(Spacer(1, 6))
ev_data = [
[
Paragraph("<b>Evidence Level</b>", S("eh", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE, leading=12)),
Paragraph("<b>Finding</b>", S("eh2", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE, leading=12)),
Paragraph("<b>Key Reference</b>", S("eh3", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE, leading=12)),
],
[
Paragraph("In vitro (strong)", S("el", fontSize=8.5, fontName="Helvetica-Bold", textColor=ACCENT, leading=12)),
Paragraph("Inhibits BEC invasion by UPEC/E. faecalis (dose-dependent, p<0.01). "
"Disrupts 48-h E. coli and E. faecalis biofilms. "
"NAC + ciprofloxacin superior to either alone in biofilm eradication.",
S("ef", fontSize=8.5, fontName="Helvetica", leading=12)),
Paragraph("Manoharan et al., <i>Antibiotics</i> 2021 [PMID 34438950]",
S("er", fontSize=8, fontName="Helvetica-Oblique", leading=12)),
],
[
Paragraph("In vitro / CA-UTI model (strong)",
S("el2", fontSize=8.5, fontName="Helvetica-Bold", textColor=ACCENT, leading=12)),
Paragraph("NAC inhibits P. mirabilis urease at 1 mM; prevents catheter occlusion and "
"crystalline biofilm; 4-8 log10 reduction in viable bacteria; reduces IL-6, IL-8, IL-1b in BECs.",
S("ef2", fontSize=8.5, fontName="Helvetica", leading=12)),
Paragraph("Manoharan et al., <i>Front Cell Infect Microbiol</i> 2023 [PMID 37965267]",
S("er2", fontSize=8, fontName="Helvetica-Oblique", leading=12)),
],
[
Paragraph("In vitro (2025)", S("el3", fontSize=8.5, fontName="Helvetica-Bold", textColor=ACCENT, leading=12)),
Paragraph("NAC reduces P. aeruginosa viability >4 log10 (p<0.01) in catheter model; "
"inhibits biofilm and catheter obstruction to 96 h endpoint. "
"Alters bacterial surface structure, disrupting virulence.",
S("ef3", fontSize=8.5, fontName="Helvetica", leading=12)),
Paragraph("Manoharan et al., <i>Biofilm</i> 2025 [PMID 40726828]",
S("er3", fontSize=8, fontName="Helvetica-Oblique", leading=12)),
],
[
Paragraph("Review (clinical context)",
S("el4", fontSize=8.5, fontName="Helvetica-Bold", textColor=ACCENT, leading=12)),
Paragraph("NAC + D-mannose + hyaluronic acid + chondroitin sulphate combination: "
"mechanistically synergistic; NAC provides anti-biofilm action complementing "
"D-mannose anti-adhesion and GAG layer replenishment.",
S("ef4", fontSize=8.5, fontName="Helvetica", leading=12)),
Paragraph("Crocetto et al., <i>Nutrients</i> 2023 [PMID 37630763]",
S("er4", fontSize=8, fontName="Helvetica-Oblique", leading=12)),
],
[
Paragraph("Small clinical study",
S("el5", fontSize=8.5, fontName="Helvetica-Bold", textColor=ORANGE, leading=12)),
Paragraph("D-mannose + probiotic + NAC combination comparable to 7-day antibiotics for "
"UTI recurrence prevention in post-urodynamics patients.",
S("ef5", fontSize=8.5, fontName="Helvetica", leading=12)),
Paragraph("Palleschi et al., <i>Arch Ital Urol Androl</i> 2017",
S("er5", fontSize=8, fontName="Helvetica-Oblique", leading=12)),
],
[
Paragraph("Guideline position",
S("el6", fontSize=8.5, fontName="Helvetica-Bold", textColor=ORANGE, leading=12)),
Paragraph("NOT included in AUA 2024 rUTI guidelines. No large dedicated RCT on NAC "
"monotherapy for recurrent UTI as of June 2026. Evidence remains preclinical/small study.",
S("ef6", fontSize=8.5, fontName="Helvetica", leading=12)),
Paragraph("AUA Recurrent UTI Guideline 2024 (updated Nov 2024)",
S("er6", fontSize=8, fontName="Helvetica-Oblique", leading=12)),
],
]
ev_col_w = [105, doc.width - 105 - 130, 130]
ev_tbl = Table(ev_data, colWidths=ev_col_w, repeatRows=1)
ev_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), ACCENT),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("BACKGROUND", (0,1), (-1,1), ACCENT_LIGHT),
("BACKGROUND", (0,2), (-1,2), WHITE),
("BACKGROUND", (0,3), (-1,3), ACCENT_LIGHT),
("BACKGROUND", (0,4), (-1,4), WHITE),
("BACKGROUND", (0,5), (-1,5), ORANGE_LIGHT),
("BACKGROUND", (0,6), (-1,6), ORANGE_LIGHT),
("VALIGN", (0,0), (-1,-1), "TOP"),
("GRID", (0,0), (-1,-1), 0.4, GREY_LINE),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("LINEBELOW", (0,-1), (-1,-1), 1.2, ACCENT),
]))
story.append(ev_tbl)
story.append(Spacer(1, 10))
# ============================================================
# SECTION 4: COMBINATION STRATEGY
# ============================================================
story.append(section_title("4. Combination Strategy: Non-Antibiotic Prophylaxis"))
story.append(Spacer(1, 6))
combo_data = [
[
Paragraph("<b>Agent</b>", S("ch", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE, leading=12)),
Paragraph("<b>Mechanism</b>", S("ch2", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE, leading=12)),
Paragraph("<b>Role alongside NAC</b>", S("ch3", fontSize=9, fontName="Helvetica-Bold", textColor=WHITE, leading=12)),
],
[
Paragraph("N-Acetylcysteine", S("ca", fontSize=8.5, fontName="Helvetica-Bold", textColor=DARK_BLUE, leading=12)),
Paragraph("Anti-biofilm, anti-invasive, urease inhibition, anti-inflammatory",
S("cb", fontSize=8.5, fontName="Helvetica", leading=12)),
Paragraph("Core agent", S("cc", fontSize=8.5, fontName="Helvetica-Bold", textColor=ACCENT, leading=12)),
],
[
Paragraph("D-Mannose", S("ca2", fontSize=8.5, fontName="Helvetica-Bold", textColor=DARK_BLUE, leading=12)),
Paragraph("Competitively blocks FimH-mediated E. coli adhesion to uroepithelium",
S("cb2", fontSize=8.5, fontName="Helvetica", leading=12)),
Paragraph("Anti-adhesion; complementary (targets step before biofilm)",
S("cc2", fontSize=8.5, fontName="Helvetica-Oblique", leading=12)),
],
[
Paragraph("Hyaluronic acid / Chondroitin sulphate",
S("ca3", fontSize=8.5, fontName="Helvetica-Bold", textColor=DARK_BLUE, leading=12)),
Paragraph("Replenishes the glycosaminoglycan (GAG) layer; reduces urothelial permeability",
S("cb3", fontSize=8.5, fontName="Helvetica", leading=12)),
Paragraph("Urothelial barrier restoration",
S("cc3", fontSize=8.5, fontName="Helvetica-Oblique", leading=12)),
],
[
Paragraph("Vaginal estrogens (postmenopausal)",
S("ca4", fontSize=8.5, fontName="Helvetica-Bold", textColor=DARK_BLUE, leading=12)),
Paragraph("Restores vaginal flora (Lactobacilli), reduces uropathogens, improves urothelial integrity",
S("cb4", fontSize=8.5, fontName="Helvetica", leading=12)),
Paragraph("Strong evidence (AUA guideline recommended)",
S("cc4", fontSize=8.5, fontName="Helvetica-Oblique", leading=12)),
],
[
Paragraph("Methenamine hippurate",
S("ca5", fontSize=8.5, fontName="Helvetica-Bold", textColor=DARK_BLUE, leading=12)),
Paragraph("Releases formaldehyde in acidic urine; bacteriostatic; urinary antiseptic",
S("cb5", fontSize=8.5, fontName="Helvetica", leading=12)),
Paragraph("Evidence-based; can combine with D-mannose and NAC",
S("cc5", fontSize=8.5, fontName="Helvetica-Oblique", leading=12)),
],
]
combo_col_w = [115, doc.width - 115 - 130, 130]
combo_tbl = Table(combo_data, colWidths=combo_col_w, repeatRows=1)
combo_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("BACKGROUND", (0,1), (-1,1), LIGHT_BLUE),
("BACKGROUND", (0,2), (-1,2), WHITE),
("BACKGROUND", (0,3), (-1,3), LIGHT_BLUE),
("BACKGROUND", (0,4), (-1,4), WHITE),
("BACKGROUND", (0,5), (-1,5), LIGHT_BLUE),
("VALIGN", (0,0), (-1,-1), "TOP"),
("GRID", (0,0), (-1,-1), 0.4, GREY_LINE),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("LINEBELOW", (0,-1), (-1,-1), 1.2, DARK_BLUE),
]))
story.append(combo_tbl)
story.append(Spacer(1, 10))
# ============================================================
# SECTION 5: WHO BENEFITS MOST + CLINICAL PEARLS
# ============================================================
story.append(orange_section("5. Who May Benefit & Clinical Pearls"))
story.append(Spacer(1, 6))
pearls_left = [
Paragraph("<b>Most Likely to Benefit:</b>", sub_hdr),
Paragraph("- Catheter-associated recurrent UTI (especially Proteus, Pseudomonas)", bullet),
Paragraph("- Biofilm-driven recurrence (treatment failure despite appropriate antibiotics)", bullet),
Paragraph("- Patients where long-term antibiotic prophylaxis is being avoided (resistance concerns, "
"side effects, patient preference)", bullet),
Paragraph("- Combination with D-mannose when E. coli is the dominant pathogen", bullet),
Paragraph("- Adjunct during acute treatment to improve antibiotic penetration of biofilms", bullet),
]
pearls_right = [
Paragraph("<b>Clinical Pearls:</b>", sub_hdr),
Paragraph("- No antibiotic resistance risk - important advantage as rUTI prophylaxis "
"increasingly limited by resistance", bullet),
Paragraph("- Dosing: 600 mg 2-3x/day oral; no renal dose adjustment needed", bullet),
Paragraph("- Evidence is preclinical/early clinical only - do not replace guideline-based "
"management (vaginal estrogens, methenamine, targeted antibiotics)", bullet),
Paragraph("- Best evidence is for CA-UTI and biofilm-associated recurrence, not uncomplicated rUTI", bullet),
Paragraph("- Consider as adjunct, not monotherapy, until RCT data available", bullet),
]
two_col_pearls = Table([[mini_col(pearls_left), mini_col(pearls_right)]],
colWidths=[doc.width/2 - 3, doc.width/2 - 3])
two_col_pearls.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("LINEBETWEEN", (0,0), (1,0), 0.5, GREY_LINE),
("TOPPADDING", (0,0), (-1,-1), 0),
("BOTTOMPADDING", (0,0), (-1,-1), 0),
("LEFTPADDING", (0,0), (-1,-1), 4),
("RIGHTPADDING", (0,0), (-1,-1), 4),
]))
story.append(two_col_pearls)
story.append(Spacer(1, 10))
# ============================================================
# SECTION 6: LIMITATIONS
# ============================================================
story.append(HRFlowable(width="100%", thickness=1, color=GREY_LINE))
story.append(Spacer(1, 4))
lim_rows = [
[Paragraph("<b>Limitations of Current Evidence</b>",
S("lh", fontSize=9.5, fontName="Helvetica-Bold", textColor=DARK_BLUE, leading=13)),
Paragraph(
"Most data are in vitro or from small pilot studies. No large RCT has evaluated "
"NAC monotherapy specifically for recurrent UTI prevention. The AUA 2024 rUTI "
"Guideline does not endorse NAC. Optimal dose, duration, and patient selection "
"criteria remain undefined. Combination products vary in NAC content and quality. "
"Until prospective RCT data exist, NAC should be used as an adjunct to - not a "
"replacement for - evidence-based prophylaxis strategies.",
S("lb", fontSize=8.5, fontName="Helvetica", leading=12, textColor=HexColor("#333333")))]
]
lim_tbl = Table(lim_rows, colWidths=[160, doc.width - 160])
lim_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), ORANGE_LIGHT),
("VALIGN", (0,0), (-1,-1), "TOP"),
("LINELEFT", (0,0), (0,-1), 4, ORANGE),
("TOPPADDING", (0,0), (-1,-1), 7),
("BOTTOMPADDING", (0,0), (-1,-1), 7),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
]))
story.append(lim_tbl)
story.append(Spacer(1, 6))
# References
story.append(Paragraph("<b>Key References:</b>",
S("rh", fontSize=8, fontName="Helvetica-Bold", textColor=DARK_BLUE, leading=11)))
refs = [
"1. Manoharan A et al. N-Acetylcysteine Protects Bladder Epithelial Cells from Bacterial Invasion and Displays Antibiofilm Activity. <i>Antibiotics</i> 2021; PMID 34438950.",
"2. Manoharan A et al. NAC prevents catheter occlusion and inflammation in CA-UTIs by suppressing urease activity. <i>Front Cell Infect Microbiol</i> 2023; PMID 37965267.",
"3. Manoharan A et al. NAC's efficacy against Pseudomonas aeruginosa in urinary catheters. <i>Biofilm</i> 2025; PMID 40726828.",
"4. Crocetto F et al. Role of D-mannose, Chondroitin Sulphate, Hyaluronic Acid, and N-acetylcysteine in UTI. <i>Nutrients</i> 2023; PMID 37630763.",
"5. AUA Recurrent Uncomplicated UTI Guideline 2019, amended 2024.",
]
for r in refs:
story.append(Paragraph(r, S("ref", fontSize=7.5, fontName="Helvetica",
textColor=HexColor("#444444"), leading=11, spaceAfter=2)))
# Build
doc.build(story)
print(f"PDF generated: {OUTPUT}")
cd /home/daytona/workspace/nac-uti-pdf && python generate_pdf.py 2>&1
ls -lh /home/daytona/workspace/nac-uti-pdf/NAC_in_Recurrent_UTI_Clinical_Reference.pdf
NAC in Recurrent UTI Clinical Reference
PDF Document · PDF
| Section | Contents |
|---|---|
| 1. Mechanisms of Action | 5-mechanism table: anti-biofilm, IBC prevention, urease inhibition, anti-inflammatory, antibiotic synergy - with specific pathogens for each |
| 2. Dosing Guidance | Oral dosing (600 mg 2-3x/day), combination products (Uroial PLUS), intravesical use, pharmacokinetics, safety profile |
| 3. Evidence Summary | Color-coded table (green = strong preclinical, orange = limited clinical/no guideline endorsement) with PMIDs for each reference |
| 4. Combination Strategy | NAC vs. D-mannose vs. HA/chondroitin vs. vaginal estrogens vs. methenamine - mechanism and role |
| 5. Who Benefits Most | Patient selection guide + clinical pearls in two-column layout |
| Limitations box | Clear caveat on preclinical-only evidence and AUA 2024 non-endorsement |
Create a clinical summary or quick reference PDF on NAC mechanisms and dosing
NAC in Recurrent UTI Clinical Reference
PDF Document · PDF