Jaundice - cause , types and symptoms explanation+ create an image lastly
Medical educational diagram of jaundice showing three types: pre-hepatic (hemolytic), hepatic (liver cell damage), and post-hepatic (obstructive). Include a human body silhouette with highlighted liver, bile ducts, and gallbladder. Show yellow skin and sclera (eyes), bilirubin pathway from red blood cell breakdown to liver to bile duct. Color-code each type clearly with arrows and labels. Clean, professional medical illustration style.
| Symptom | Explanation |
|---|---|
| Yellow skin and eyes (icterus) | Bilirubin deposits in skin and sclera |
| Fatigue and malaise | From the underlying disease |
| Nausea and loss of appetite | Liver dysfunction |
| Symptom | Explanation |
|---|---|
| Pale/clay-colored stools | No bilirubin reaching the gut (blocked bile duct) |
| Dark urine ("tea-colored") | Conjugated bilirubin excreted by kidneys |
| Pruritus (intense itching) | Bile salts depositing in skin - one of the most distressing symptoms |
| Right upper quadrant pain | If gallstones are the cause |
| Painless jaundice | Classic sign of pancreatic cancer |
| Symptom | Explanation |
|---|---|
| Pallor/anemia | Red cell destruction |
| Splenomegaly | Spleen working overtime to clear damaged RBCs |
| Normal stool/urine color | Liver still functioning and excreting bilirubin normally |
| Symptom | Explanation |
|---|---|
| Hepatomegaly (enlarged liver) | Inflamed/scarred liver tissue |
| Ascites | Portal hypertension in cirrhosis |
| Spider angiomata, palmar erythema | Estrogen accumulation from liver failure |
| Encephalopathy | Toxins (ammonia) not cleared by the failing liver |
| Prolonged bleeding / bruising | Impaired clotting factor synthesis + vitamin K malabsorption |
| Feature | Pre-Hepatic | Hepatic | Post-Hepatic |
|---|---|---|---|
| Bilirubin type | Unconjugated | Mixed | Conjugated |
| Urine color | Normal | Dark | Dark |
| Stool color | Normal | Variable | Pale/clay |
| Pruritus | Rare | Mild | Severe |
| Key cause | Hemolysis | Hepatitis/cirrhosis | Gallstones/cancer |

Create a comparison PDF: Gilbert's vs Crigler-Najjar syndrome
mkdir -p /home/daytona/workspace/jaundice-comparison && ls /home/daytona/workspace/
~/jaundice-comparison/create_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 cm, mm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import PageBreak
OUTPUT = "/home/daytona/workspace/jaundice-comparison/Gilberts_vs_CriglerNajjar.pdf"
# ── Colour palette ──────────────────────────────────────────────────────────
C_GOLD = colors.HexColor("#F5A623") # Gilbert accent
C_GOLD_LIGHT = colors.HexColor("#FEF3DC")
C_RED = colors.HexColor("#D0021B") # Crigler-Najjar accent
C_RED_LIGHT = colors.HexColor("#FDECEA")
C_DARK = colors.HexColor("#1A1A2E")
C_MID = colors.HexColor("#4A4A6A")
C_LIGHT_GREY = colors.HexColor("#F4F4F8")
C_WHITE = colors.white
C_TEAL = colors.HexColor("#0A7EA4")
C_TEAL_LIGHT = colors.HexColor("#E6F4FA")
C_TABLE_HDR = colors.HexColor("#2C3E6B")
W, H = A4
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
rightMargin=1.8*cm, leftMargin=1.8*cm,
topMargin=1.5*cm, bottomMargin=1.5*cm,
title="Gilbert's vs Crigler-Najjar Syndrome Comparison",
author="Orris Medical Library",
)
styles = getSampleStyleSheet()
# ── Custom styles ────────────────────────────────────────────────────────────
def S(name, **kw):
return ParagraphStyle(name, **kw)
sTitle = S("sTitle",
fontSize=26, textColor=C_WHITE, alignment=TA_CENTER,
fontName="Helvetica-Bold", leading=32, spaceAfter=4)
sSubtitle = S("sSubtitle",
fontSize=13, textColor=C_WHITE, alignment=TA_CENTER,
fontName="Helvetica", leading=18, spaceAfter=0)
sSectionHead = S("sSectionHead",
fontSize=13, textColor=C_WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=16)
sBodySmall = S("sBodySmall",
fontSize=8.5, textColor=C_DARK, fontName="Helvetica",
leading=12, spaceAfter=2, alignment=TA_JUSTIFY)
sBodyNormal = S("sBodyNormal",
fontSize=9.5, textColor=C_DARK, fontName="Helvetica",
leading=13, spaceAfter=3, alignment=TA_JUSTIFY)
sBullet = S("sBullet",
fontSize=9, textColor=C_DARK, fontName="Helvetica",
leading=13, leftIndent=12, bulletIndent=0, spaceAfter=2)
sCellHead = S("sCellHead",
fontSize=10, textColor=C_WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=14)
sCellBody = S("sCellBody",
fontSize=8.8, textColor=C_DARK, fontName="Helvetica",
leading=12, alignment=TA_LEFT)
sFootnote = S("sFootnote",
fontSize=7.5, textColor=C_MID, fontName="Helvetica-Oblique",
leading=10, alignment=TA_CENTER)
sCallout = S("sCallout",
fontSize=9, textColor=C_TEAL, fontName="Helvetica-BoldOblique",
leading=12, alignment=TA_LEFT)
sKeyNum = S("sKeyNum",
fontSize=22, textColor=C_GOLD, fontName="Helvetica-Bold",
leading=26, alignment=TA_CENTER)
sKeyLabel = S("sKeyLabel",
fontSize=8, textColor=C_MID, fontName="Helvetica",
leading=10, alignment=TA_CENTER)
# ── Helper: coloured box paragraph ──────────────────────────────────────────
def box_para(text, style, bg, radius=4, pad=6):
"""Wrap a paragraph in a single-cell table to get a coloured background."""
t = Table([[Paragraph(text, style)]], colWidths=[doc.width])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("ROUNDEDCORNERS", [radius]),
("TOPPADDING", (0,0), (-1,-1), pad),
("BOTTOMPADDING",(0,0), (-1,-1), pad),
("LEFTPADDING", (0,0), (-1,-1), pad+2),
("RIGHTPADDING", (0,0), (-1,-1), pad+2),
]))
return t
# ── STORY ────────────────────────────────────────────────────────────────────
story = []
# ════════════════════════════════════════════════════════════════
# HEADER BANNER
# ════════════════════════════════════════════════════════════════
banner = Table(
[[Paragraph("Gilbert's Syndrome vs Crigler-Najjar Syndrome", sTitle)],
[Paragraph("A Clinical Comparison of Hereditary Unconjugated Hyperbilirubinemias", sSubtitle)]],
colWidths=[doc.width]
)
banner.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), C_TABLE_HDR),
("TOPPADDING", (0,0), (-1,-1), 14),
("BOTTOMPADDING",(0,0), (-1,-1), 14),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
("ROUNDEDCORNERS", [6]),
]))
story.append(banner)
story.append(Spacer(1, 10))
# ── Source ribbon ────────────────────────────────────────────────────────────
src = Table([[Paragraph(
"Sources: Goldman-Cecil Medicine 2V (2022) • Harper's Illustrated Biochemistry 32e "
"• Yamada's Textbook of Gastroenterology 7e • Quick Compendium of Clinical Pathology 5e",
sFootnote)]], colWidths=[doc.width])
src.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), C_LIGHT_GREY),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0), (-1,-1), 5),
("ROUNDEDCORNERS", [3]),
]))
story.append(src)
story.append(Spacer(1, 12))
# ════════════════════════════════════════════════════════════════
# QUICK STATS ROW (3 columns)
# ════════════════════════════════════════════════════════════════
col = (doc.width - 10) / 3
def stat_card(num, label, bg):
t = Table(
[[Paragraph(num, sKeyNum)],
[Paragraph(label, sKeyLabel)]],
colWidths=[col]
)
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING",(0,0), (-1,-1), 8),
("ROUNDEDCORNERS", [5]),
]))
return t
stats = Table(
[[stat_card("4–16%", "Gilbert's prevalence\n(general population)", C_GOLD_LIGHT),
Spacer(5,1),
stat_card("<1:1,000,000","Crigler-Najjar prevalence\n(extremely rare)", C_RED_LIGHT),
Spacer(5,1),
stat_card("UGT1A1", "Shared causative gene\n(bilirubin conjugation)", C_TEAL_LIGHT)]],
colWidths=[col, 5, col, 5, col]
)
story.append(stats)
story.append(Spacer(1, 14))
# ════════════════════════════════════════════════════════════════
# OVERVIEW SECTION
# ════════════════════════════════════════════════════════════════
story.append(box_para("Overview", sSectionHead, C_TABLE_HDR))
story.append(Spacer(1, 6))
story.append(Paragraph(
"Both Gilbert's syndrome and Crigler-Najjar syndrome are <b>hereditary unconjugated hyperbilirubinemias</b> "
"caused by mutations in the <b>UGT1A1</b> gene, which encodes bilirubin UDP-glucuronosyltransferase — "
"the enzyme responsible for conjugating bilirubin with glucuronic acid in hepatocytes. "
"Despite sharing the same genetic target, their clinical severity differs dramatically depending on "
"how much residual enzyme activity remains.",
sBodyNormal))
story.append(Spacer(1, 4))
story.append(Paragraph(
"Enzyme activity thresholds (Goldman-Cecil Medicine):",
S("bold9", fontSize=9, fontName="Helvetica-Bold", textColor=C_DARK, leading=13)))
enz_data = [
[Paragraph("Condition", sCellHead),
Paragraph("Enzyme Activity", sCellHead),
Paragraph("Serum Bilirubin", sCellHead),
Paragraph("Key Mechanism", sCellHead)],
[Paragraph("Gilbert's Syndrome", sCellBody),
Paragraph("10–33% of normal", sCellBody),
Paragraph("1.5–4 mg/dL", sCellBody),
Paragraph("Promoter polymorphism → reduced transcription", sCellBody)],
[Paragraph("Crigler-Najjar Type 2", sCellBody),
Paragraph("Up to 10% of normal", sCellBody),
Paragraph("6–25 mg/dL", sCellBody),
Paragraph("Missense mutations → severely reduced activity", sCellBody)],
[Paragraph("Crigler-Najjar Type 1", sCellBody),
Paragraph("Absent (0%)", sCellBody),
Paragraph("18–45 mg/dL", sCellBody),
Paragraph("Null mutations → complete loss of function", sCellBody)],
]
enz_w = [doc.width*0.28, doc.width*0.18, doc.width*0.18, doc.width*0.36]
enz_table = Table(enz_data, colWidths=enz_w, repeatRows=1)
enz_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_TABLE_HDR),
("BACKGROUND", (0,1), (-1,1), C_GOLD_LIGHT),
("BACKGROUND", (0,2), (-1,2), colors.HexColor("#FDECEA")),
("BACKGROUND", (0,3), (-1,3), C_RED_LIGHT),
("ROWBACKGROUNDS",(0,0), (-1,-1), [None]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#CCCCCC")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
story.append(Spacer(1, 4))
story.append(enz_table)
story.append(Spacer(1, 14))
# ════════════════════════════════════════════════════════════════
# SIDE-BY-SIDE COMPARISON TABLE
# ════════════════════════════════════════════════════════════════
story.append(box_para("Detailed Side-by-Side Comparison", sSectionHead, C_TABLE_HDR))
story.append(Spacer(1, 6))
sGH = S("sGH", fontSize=10, textColor=C_WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=14, backColor=C_GOLD)
sCH = S("sCH", fontSize=10, textColor=C_WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=14, backColor=C_RED)
sRowHead = S("sRowHead", fontSize=9, textColor=C_WHITE, fontName="Helvetica-Bold",
alignment=TA_LEFT, leading=12)
sCG = S("sCG", fontSize=8.8, textColor=C_DARK, fontName="Helvetica",
leading=12, alignment=TA_LEFT)
sCR = S("sCR", fontSize=8.8, textColor=C_DARK, fontName="Helvetica",
leading=12, alignment=TA_LEFT)
COL_L = doc.width * 0.22
COL_G = doc.width * 0.35
COL_CN = doc.width * 0.43
rows = [
# header
[Paragraph("Feature", sRowHead),
Paragraph("Gilbert's Syndrome", sGH),
Paragraph("Crigler-Najjar Syndrome", sCH)],
# ── Genetics
[Paragraph("Gene / Mutation", S("rh", fontSize=8.5, fontName="Helvetica-Bold", textColor=C_WHITE, leading=12)),
Paragraph("UGT1A1 <b>promoter</b> region\nA(TA)₇TAA repeat (UGT1A1*28)\nAutosomal recessive", sCG),
Paragraph("<b>Type 1:</b> UGT1A1 coding sequence — null mutations (exons 2–5 common; exon A1 in Type 1B)\n"
"<b>Type 2:</b> Missense mutations in UGT1A1 — reduced but not absent activity\nAutosomal recessive", sCR)],
# ── Prevalence
[Paragraph("Prevalence", S("rh", fontSize=8.5, fontName="Helvetica-Bold", textColor=C_WHITE, leading=12)),
Paragraph("4–16% of general population\n(most common hereditary hyperbilirubinemia)\nAllele frequency: ~42% Black, ~30% White, ~10% Asian", sCG),
Paragraph("<b>Type 1:</b> Extremely rare (<1 per million)\n<b>Type 2:</b> Also rare; slightly more common than Type 1", sCR)],
# ── Onset
[Paragraph("Age of Onset", S("rh", fontSize=8.5, fontName="Helvetica-Bold", textColor=C_WHITE, leading=12)),
Paragraph("Adolescence (sex steroids alter bilirubin metabolism)\nOften first noticed incidentally on blood tests", sCG),
Paragraph("<b>Type 1:</b> Neonatal period — severe jaundice from birth\n<b>Type 2:</b> Neonatal/early childhood onset", sCR)],
# ── Bilirubin
[Paragraph("Bilirubin Level", S("rh", fontSize=8.5, fontName="Helvetica-Bold", textColor=C_WHITE, leading=12)),
Paragraph("1.5–4 mg/dL (unconjugated)\n2–3× rise with fasting, stress, illness, or exercise", sCG),
Paragraph("<b>Type 1:</b> 18–45 mg/dL (unconjugated)\n<b>Type 2:</b> 6–25 mg/dL (unconjugated)", sCR)],
# ── Clinical presentation
[Paragraph("Clinical Features", S("rh", fontSize=8.5, fontName="Helvetica-Bold", textColor=C_WHITE, leading=12)),
Paragraph("Mild, intermittent jaundice (icterus)\nNo hemolysis, no liver disease\nOtherwise completely asymptomatic\nFatigue occasionally reported", sCG),
Paragraph("<b>Type 1:</b> Severe jaundice, risk of kernicterus (bilirubin encephalopathy), brain damage, death if untreated\n"
"<b>Type 2:</b> Moderate jaundice; kernicterus rare but possible during illness/fasting", sCR)],
# ── Liver histology
[Paragraph("Liver Histology / Function", S("rh", fontSize=8.5, fontName="Helvetica-Bold", textColor=C_WHITE, leading=12)),
Paragraph("Normal liver histology\nNormal LFTs (except elevated unconjugated bilirubin)\nNo structural liver damage", sCG),
Paragraph("Normal liver histology and synthetic function\nAll liver enzymes (ALT, AST, ALP, albumin) normal\nNo cirrhosis or fibrosis", sCR)],
# ── Phenobarbital response
[Paragraph("Phenobarbital Response", S("rh", fontSize=8.5, fontName="Helvetica-Bold", textColor=C_WHITE, leading=12)),
Paragraph("Yes — phenobarbital induces UGT1A1, normalises bilirubin\n(used as a diagnostic test)", sCG),
Paragraph("<b>Type 1:</b> No response (no enzyme to induce)\n<b>Type 2:</b> Yes — phenobarbital reduces bilirubin to 3–5 mg/dL", sCR)],
# ── Prognosis
[Paragraph("Prognosis", S("rh", fontSize=8.5, fontName="Helvetica-Bold", textColor=C_WHITE, leading=12)),
Paragraph("Excellent — benign, lifelong but harmless\nNormal life expectancy\nNo treatment needed", sCG),
Paragraph("<b>Type 1:</b> Fatal without treatment (kernicterus in infancy)\n<b>Type 2:</b> Generally good with phenobarbital; rare kernicterus risk", sCR)],
# ── Treatment
[Paragraph("Treatment", S("rh", fontSize=8.5, fontName="Helvetica-Bold", textColor=C_WHITE, leading=12)),
Paragraph("None required\nAvoid prolonged fasting\nAwareness of drug interactions (irinotecan, raloxifene)", sCG),
Paragraph("<b>Type 1:</b>\n• Phototherapy ~12 hrs/day from birth\n• Exchange transfusion (neonatal)\n• Oral calcium phosphate (bind bilirubin isomers)\n• Early liver transplantation (before brain damage)\n• Plasmapheresis for acute bilirubin spikes\n\n<b>Type 2:</b>\n• Phenobarbital (first-line)\n• Phototherapy if needed\n• Avoid triggers (fasting, illness)", sCR)],
# ── Drug interactions
[Paragraph("Key Drug Interactions", S("rh", fontSize=8.5, fontName="Helvetica-Bold", textColor=C_WHITE, leading=12)),
Paragraph("<b>Irinotecan (CPT-11):</b> Active metabolite SN-38 is glucuronidated by UGT1A1 → severe diarrhea and myelosuppression in Gilbert's\n"
"<b>Raloxifene:</b> 2× higher drug exposure in *28 homozygotes\n"
"<b>HIV protease inhibitors</b> (atazanavir, indinavir): inhibit UGT1A1 → worsen hyperbilirubinemia", sCG),
Paragraph("<b>Type 1/2:</b> Any drug or state that inhibits residual UGT1A1 activity can precipitate acute bilirubin rise\nFasting, intercurrent illness, and infections are common triggers for dangerous bilirubin spikes in Type 2", sCR)],
# ── Inheritance
[Paragraph("Inheritance Pattern", S("rh", fontSize=8.5, fontName="Helvetica-Bold", textColor=C_WHITE, leading=12)),
Paragraph("Autosomal recessive\nHomozygous UGT1A1*28 (TA₇ repeat) in Black/White populations\nCoding region mutations more common in Asian patients", sCG),
Paragraph("Autosomal recessive\nHomozygous or compound heterozygous null mutations (Type 1)\nAt least 59 mutations identified for Type 1\nAt least 48 mutations for Type 2", sCR)],
]
cw = [COL_L, COL_G, COL_CN]
comp_table = Table(rows, colWidths=cw, repeatRows=1)
row_bg_G = C_GOLD_LIGHT
row_bg_CN = colors.HexColor("#FDECEA")
ts = TableStyle([
# Header row
("BACKGROUND", (0,0), (0,0), C_TABLE_HDR),
("BACKGROUND", (1,0), (1,0), C_GOLD),
("BACKGROUND", (2,0), (2,0), C_RED),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#CCCCCC")),
("ROWBACKGROUNDS",(0,0),(0,-1), [C_TABLE_HDR]),
])
# Alternate row backgrounds
for i in range(1, len(rows)):
bg = row_bg_G if i % 2 == 1 else colors.HexColor("#FFF8F8")
ts.add("BACKGROUND", (1, i), (1, i), bg)
bg2 = row_bg_CN if i % 2 == 1 else colors.HexColor("#FFF5F5")
ts.add("BACKGROUND", (2, i), (2, i), bg2)
ts.add("BACKGROUND", (0, i), (0, i), C_TABLE_HDR if i % 2 == 0 else colors.HexColor("#2C3E6B"))
comp_table.setStyle(ts)
story.append(comp_table)
story.append(Spacer(1, 14))
# ════════════════════════════════════════════════════════════════
# PATHOPHYSIOLOGY SECTION
# ════════════════════════════════════════════════════════════════
story.append(box_para("Pathophysiology: Shared Mechanism, Different Severity", sSectionHead, C_TABLE_HDR))
story.append(Spacer(1, 7))
# Pathway boxes
path_data = [[
Table([[
Paragraph("Normal Bilirubin Conjugation", S("ph", fontSize=9, fontName="Helvetica-Bold",
textColor=C_TABLE_HDR, alignment=TA_CENTER, leading=12)),
Paragraph("RBC breakdown → Heme → Biliverdin → <b>Unconjugated bilirubin</b> "
"(insoluble, bound to albumin) → Hepatocyte → <b>UGT1A1</b> adds glucuronic acid "
"→ <b>Conjugated bilirubin</b> (water-soluble) → Bile → Gut → Excreted",
S("pb", fontSize=8.5, fontName="Helvetica", textColor=C_DARK, leading=12,
alignment=TA_LEFT)),
]], colWidths=[doc.width/3 - 6]),
Table([[
Paragraph("Gilbert's Syndrome", S("ph", fontSize=9, fontName="Helvetica-Bold",
textColor=C_GOLD, alignment=TA_CENTER, leading=12)),
Paragraph("UGT1A1 promoter mutation (UGT1A1*28) → reduced enzyme transcription → "
"<b>10–33% of normal activity</b> → mild unconjugated bilirubin accumulation. "
"Enzyme activity retains ~30%, keeping condition harmless. Triggered by fasting, "
"stress, illness, alcohol, exercise.",
S("pb", fontSize=8.5, fontName="Helvetica", textColor=C_DARK, leading=12,
alignment=TA_LEFT)),
]], colWidths=[doc.width/3 - 6]),
Table([[
Paragraph("Crigler-Najjar Syndrome", S("ph", fontSize=9, fontName="Helvetica-Bold",
textColor=C_RED, alignment=TA_CENTER, leading=12)),
Paragraph("<b>Type 1:</b> Null mutations → 0% UGT1A1 activity → massive unconjugated "
"bilirubin accumulation → crosses blood-brain barrier → kernicterus, brain damage, death.\n\n"
"<b>Type 2:</b> Missense mutations → <10% residual activity → significant but "
"survivable hyperbilirubinemia; responds to phenobarbital induction.",
S("pb", fontSize=8.5, fontName="Helvetica", textColor=C_DARK, leading=12,
alignment=TA_LEFT)),
]], colWidths=[doc.width/3 - 6]),
]]
path_table = Table(path_data, colWidths=[doc.width/3, doc.width/3, doc.width/3])
path_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (0,0), C_TEAL_LIGHT),
("BACKGROUND", (1,0), (1,0), C_GOLD_LIGHT),
("BACKGROUND", (2,0), (2,0), C_RED_LIGHT),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 7),
("BOTTOMPADDING",(0,0), (-1,-1), 7),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")),
("ROUNDEDCORNERS", [4]),
]))
story.append(path_table)
story.append(Spacer(1, 14))
# ════════════════════════════════════════════════════════════════
# CLINICAL PEARLS
# ════════════════════════════════════════════════════════════════
story.append(box_para("Clinical Pearls & Exam Points", sSectionHead, C_TABLE_HDR))
story.append(Spacer(1, 7))
pearls = [
("Gilbert's Syndrome",
C_GOLD, C_GOLD_LIGHT,
[
"Most common hereditary hyperbilirubinemia; affects up to 16% of the population.",
"Unconjugated (indirect) bilirubin only — direct bilirubin is NORMAL.",
"All LFTs (ALT, AST, ALP, GGT, albumin, PT) are NORMAL — key diagnostic point.",
"Phenobarbital reduces bilirubin to normal (diagnostic + therapeutic).",
"Diagnosis is clinical: mild isolated unconjugated hyperbilirubinemia + normal LFTs + no hemolysis.",
"IMPORTANT drug interaction: Irinotecan (cancer chemotherapy) → SN-38 metabolite buildup → severe toxicity in Gilbert's patients. Genetic testing before irinotecan therapy is recommended.",
"Raloxifene (SERM for osteoporosis) has 2× higher exposure in Gilbert's patients.",
"HIV protease inhibitors (atazanavir, indinavir) inhibit UGT1A1 → can unmask or worsen Gilbert's.",
"No treatment required; excellent prognosis; normal life expectancy.",
"Fasting for 48 hours or IV nicotinic acid can provoke bilirubin rise (diagnostic provocative test).",
]),
("Crigler-Najjar — Type 1 vs Type 2",
C_RED, C_RED_LIGHT,
[
"Type 1: Bilirubin >20 mg/dL in neonates — EMERGENCY. Without phototherapy, fatal within 15 months (kernicterus).",
"Type 1: Completely unresponsive to phenobarbital — KEY differentiator from Type 2.",
"Type 1: Phototherapy 12 hrs/day required lifelong; liver transplantation is the only cure.",
"Type 2: Phenobarbital is first-line and effective (reduces bilirubin to 3–5 mg/dL).",
"Type 2: Kernicterus rare but documented — especially during fasting, illness, or surgery.",
"Both types: Liver histology and all liver synthetic functions are NORMAL.",
"Both types: Autosomal recessive; genetic counselling is important for affected families.",
"Plasmapheresis can bridge acutely elevated bilirubin spikes in Type 1.",
"Oral calcium phosphate captures bilirubin photo-isomers in gut, disrupts enterohepatic recirculation.",
"Gene therapy and hepatocyte transplantation are under active investigation for Type 1.",
]),
]
for title, hdr_col, bg_col, bullet_list in pearls:
pearl_header = Table([[Paragraph(title, S("ph2",
fontSize=10, fontName="Helvetica-Bold", textColor=C_WHITE,
alignment=TA_LEFT, leading=14))]], colWidths=[doc.width])
pearl_header.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), hdr_col),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
("ROUNDEDCORNERS", [3]),
]))
story.append(pearl_header)
bullet_rows = []
for b in bullet_list:
bullet_rows.append([
Paragraph("•", S("blt", fontSize=10, fontName="Helvetica-Bold",
textColor=hdr_col, leading=13, alignment=TA_CENTER)),
Paragraph(b, sCellBody)
])
bt = Table(bullet_rows, colWidths=[14, doc.width-14])
bt.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg_col),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING",(0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (0,-1), 6),
("LEFTPADDING", (1,0), (1,-1), 4),
("RIGHTPADDING", (0,0), (-1,-1), 4),
("VALIGN", (0,0), (-1,-1), "TOP"),
("LINEBELOW", (0,0), (-1,-2), 0.3, colors.HexColor("#E0E0E0")),
]))
story.append(bt)
story.append(Spacer(1, 8))
# ════════════════════════════════════════════════════════════════
# DIAGNOSTIC APPROACH
# ════════════════════════════════════════════════════════════════
story.append(box_para("Diagnostic Approach", sSectionHead, C_TABLE_HDR))
story.append(Spacer(1, 7))
diag_data = [
[Paragraph("Step", sCellHead), Paragraph("Investigation", sCellHead),
Paragraph("Gilbert's Expected", sCellHead), Paragraph("Crigler-Najjar Expected", sCellHead)],
[Paragraph("1", sCellBody), Paragraph("Total & Direct Bilirubin", sCellBody),
Paragraph("Total ↑ (1.5–4 mg/dL)\nDirect: NORMAL", sCellBody),
Paragraph("Total markedly ↑\nDirect: Normal (unconjugated)", sCellBody)],
[Paragraph("2", sCellBody), Paragraph("LFTs (ALT, AST, ALP, GGT, Albumin, PT)", sCellBody),
Paragraph("All NORMAL", sCellBody),
Paragraph("All NORMAL (liver synthetic function intact)", sCellBody)],
[Paragraph("3", sCellBody), Paragraph("CBC + Reticulocyte count + Coombs test", sCellBody),
Paragraph("Normal (rule out hemolysis)", sCellBody),
Paragraph("Normal (rule out hemolysis)", sCellBody)],
[Paragraph("4", sCellBody), Paragraph("Phenobarbital trial", sCellBody),
Paragraph("Bilirubin normalises", sCellBody),
Paragraph("Type 1: No response\nType 2: Bilirubin falls to 3–5 mg/dL", sCellBody)],
[Paragraph("5", sCellBody), Paragraph("Fasting test / IV nicotinic acid", sCellBody),
Paragraph("Bilirubin rises 2–3×", sCellBody),
Paragraph("Already markedly elevated at baseline", sCellBody)],
[Paragraph("6", sCellBody), Paragraph("UGT1A1 genetic testing", sCellBody),
Paragraph("UGT1A1*28 homozygous\n(TA)₇ promoter repeat", sCellBody),
Paragraph("Coding sequence mutations\n(59+ for Type 1; 48+ for Type 2)", sCellBody)],
[Paragraph("7", sCellBody), Paragraph("Liver biopsy", sCellBody),
Paragraph("Not usually needed\n(normal histology)", sCellBody),
Paragraph("Normal histology\n(not needed for diagnosis)", sCellBody)],
]
diag_col_w = [doc.width*0.06, doc.width*0.27, doc.width*0.30, doc.width*0.37]
diag_table = Table(diag_data, colWidths=diag_col_w, repeatRows=1)
diag_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_TABLE_HDR),
("BACKGROUND", (2,1), (2,-1), C_GOLD_LIGHT),
("BACKGROUND", (3,1), (3,-1), C_RED_LIGHT),
("ROWBACKGROUNDS",(0,1),(-1,-1), [C_LIGHT_GREY, C_WHITE]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#CCCCCC")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING",(0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(diag_table)
story.append(Spacer(1, 14))
# ════════════════════════════════════════════════════════════════
# FOOTER
# ════════════════════════════════════════════════════════════════
story.append(HRFlowable(width=doc.width, thickness=0.5, color=C_MID))
story.append(Spacer(1, 4))
story.append(Paragraph(
"Compiled by Orris Medical AI • Sources: Goldman-Cecil Medicine 2V (2022), Harper's Illustrated Biochemistry 32e, "
"Yamada's Textbook of Gastroenterology 7e, Quick Compendium of Clinical Pathology 5e • July 2026 • For educational use only",
sFootnote))
# ── BUILD ────────────────────────────────────────────────────────────────────
doc.build(story)
print("PDF created:", OUTPUT)
cd /home/daytona/workspace/jaundice-comparison && python create_pdf.py 2>&1
~/jaundice-comparison/create_pdf.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/jaundice-comparison/create_pdf.py'
cd /home/daytona/workspace/jaundice-comparison && python create_pdf.py 2>&1
cd /home/daytona/workspace/jaundice-comparison && python -c " from reportlab.lib.pagesizes import A4 from reportlab.lib.units import cm W, H = A4 rightMargin=1.8*cm; leftMargin=1.8*cm doc_width = W - rightMargin - leftMargin print('doc.width =', doc_width) PATH_COL = (doc_width - 12) / 3 print('PATH_COL =', PATH_COL) print('PATH_COL - 12 =', PATH_COL - 12) "
~/jaundice-comparison/create_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 cm
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, HRFlowable
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
OUTPUT = "/home/daytona/workspace/jaundice-comparison/Gilberts_vs_CriglerNajjar.pdf"
# ── Colour palette
C_GOLD = colors.HexColor("#D4860A")
C_GOLD_LIGHT = colors.HexColor("#FEF3DC")
C_RED = colors.HexColor("#B91C1C")
C_RED_LIGHT = colors.HexColor("#FDECEA")
C_DARK = colors.HexColor("#1A1A2E")
C_MID = colors.HexColor("#4A4A6A")
C_LIGHT_GREY = colors.HexColor("#F4F4F8")
C_WHITE = colors.white
C_TEAL = colors.HexColor("#0A7EA4")
C_TEAL_LIGHT = colors.HexColor("#E6F4FA")
C_NAVY = colors.HexColor("#1E3A5F")
W, H = A4
doc = SimpleDocTemplate(
OUTPUT, pagesize=A4,
rightMargin=1.8*cm, leftMargin=1.8*cm,
topMargin=1.5*cm, bottomMargin=1.5*cm,
title="Gilbert's vs Crigler-Najjar Syndrome",
author="Orris Medical Library",
)
DW = W - 2*1.8*cm # usable width
def ps(name, **kw):
return ParagraphStyle(name, **kw)
# Styles
sBannerTitle = ps("bT", fontSize=22, textColor=C_WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=28, spaceAfter=3)
sBannerSub = ps("bS", fontSize=11, textColor=colors.HexColor("#CBD5E1"),
fontName="Helvetica", alignment=TA_CENTER, leading=15)
sSrcNote = ps("sN", fontSize=7.5, textColor=C_MID, fontName="Helvetica-Oblique",
alignment=TA_CENTER, leading=10)
sSectionHdr = ps("sH", fontSize=12, textColor=C_WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=15)
sBody = ps("sB", fontSize=9, textColor=C_DARK, fontName="Helvetica",
leading=13, alignment=TA_JUSTIFY)
sBodyBold = ps("sBB", fontSize=9, textColor=C_DARK, fontName="Helvetica-Bold",
leading=13, alignment=TA_LEFT)
sCellHdr = ps("cH", fontSize=10, textColor=C_WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=14)
sCellRowHdr = ps("cRH", fontSize=8.5, textColor=C_WHITE, fontName="Helvetica-Bold",
alignment=TA_LEFT, leading=12)
sCellG = ps("cG", fontSize=8.8, textColor=C_DARK, fontName="Helvetica",
leading=12, alignment=TA_LEFT)
sCellCN = ps("cCN", fontSize=8.8, textColor=C_DARK, fontName="Helvetica",
leading=12, alignment=TA_LEFT)
sFootnote = ps("sF", fontSize=7.5, textColor=C_MID, fontName="Helvetica-Oblique",
alignment=TA_CENTER, leading=10)
sStatNum = ps("sN2", fontSize=20, textColor=C_NAVY, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=24)
sStatLbl = ps("sNL", fontSize=7.5, textColor=C_MID, fontName="Helvetica",
alignment=TA_CENTER, leading=10)
def section_header(text, bg=C_NAVY):
t = Table([[Paragraph(text, sSectionHdr)]], colWidths=[DW])
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),
]))
return t
story = []
# ═══════════════════════════════════════════════
# HEADER BANNER
# ═══════════════════════════════════════════════
hdr = Table([
[Paragraph("Gilbert's Syndrome vs Crigler-Najjar Syndrome", sBannerTitle)],
[Paragraph("Clinical Comparison of Hereditary Unconjugated Hyperbilirubinemias", sBannerSub)],
], colWidths=[DW])
hdr.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), C_NAVY),
("TOPPADDING", (0,0), (-1,-1), 14),
("BOTTOMPADDING", (0,0), (-1,-1), 14),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
]))
story.append(hdr)
story.append(Spacer(1, 6))
src_t = Table([[Paragraph(
"Sources: Goldman-Cecil Medicine (2022) • Harper's Biochemistry 32e "
"• Yamada's Gastroenterology 7e • Quick Compendium Clinical Pathology 5e",
sSrcNote)]], colWidths=[DW])
src_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), C_LIGHT_GREY),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
]))
story.append(src_t)
story.append(Spacer(1, 10))
# ═══════════════════════════════════════════════
# QUICK STATS (3 cards)
# ═══════════════════════════════════════════════
sc = (DW - 8) / 3
def stat_card(num, lbl, bg):
t = Table([
[Paragraph(num, sStatNum)],
[Paragraph(lbl, sStatLbl)],
], colWidths=[sc])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 4),
("RIGHTPADDING", (0,0), (-1,-1), 4),
("BOX", (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")),
]))
return t
stats_row = Table([[
stat_card("4-16%", "Gilbert's prevalence\nin general population", C_GOLD_LIGHT),
Spacer(4, 1),
stat_card("<1/1,000,000","Crigler-Najjar\n(extremely rare)", C_RED_LIGHT),
Spacer(4, 1),
stat_card("UGT1A1", "Shared causative gene\nbilirubin conjugation", C_TEAL_LIGHT),
]], colWidths=[sc, 4, sc, 4, sc])
story.append(stats_row)
story.append(Spacer(1, 12))
# ═══════════════════════════════════════════════
# OVERVIEW
# ═══════════════════════════════════════════════
story.append(section_header("Overview"))
story.append(Spacer(1, 6))
story.append(Paragraph(
"Both Gilbert's syndrome and Crigler-Najjar syndrome are <b>hereditary unconjugated hyperbilirubinemias</b> "
"caused by mutations in the <b>UGT1A1</b> gene, encoding bilirubin UDP-glucuronosyltransferase. "
"Despite sharing the same genetic locus, their clinical severity differs enormously based on residual enzyme activity. "
"Total UGT1A1 activity must fall below 50% of normal to produce hyperbilirubinemia; "
"all three conditions are inherited in an <b>autosomal recessive</b> pattern.",
sBody))
story.append(Spacer(1, 6))
# Enzyme activity table
enz_data = [
[Paragraph("Condition", sCellHdr),
Paragraph("Enzyme Activity", sCellHdr),
Paragraph("Serum Bilirubin", sCellHdr),
Paragraph("Mechanism", sCellHdr)],
[Paragraph("Gilbert's Syndrome", sCellG),
Paragraph("10-33% of normal", sCellG),
Paragraph("1.5-4 mg/dL", sCellG),
Paragraph("Promoter repeat (UGT1A1*28) reduces transcription", sCellG)],
[Paragraph("Crigler-Najjar Type 2", sCellCN),
Paragraph("Up to 10% of normal", sCellCN),
Paragraph("6-25 mg/dL", sCellCN),
Paragraph("Missense mutations - markedly reduced activity", sCellCN)],
[Paragraph("Crigler-Najjar Type 1", sCellCN),
Paragraph("Absent (0%)", sCellCN),
Paragraph("18-45 mg/dL", sCellCN),
Paragraph("Null mutations - complete loss of function", sCellCN)],
]
ew = [DW*0.28, DW*0.17, DW*0.16, DW*0.39]
et = Table(enz_data, colWidths=ew, repeatRows=1)
et.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_NAVY),
("BACKGROUND", (0,1), (-1,1), C_GOLD_LIGHT),
("BACKGROUND", (0,2), (-1,2), colors.HexColor("#FDECEA")),
("BACKGROUND", (0,3), (-1,3), C_RED_LIGHT),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#CCCCCC")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
story.append(et)
story.append(Spacer(1, 12))
# ═══════════════════════════════════════════════
# SIDE-BY-SIDE COMPARISON
# ═══════════════════════════════════════════════
story.append(section_header("Detailed Side-by-Side Comparison"))
story.append(Spacer(1, 6))
CL = DW * 0.20
CG = DW * 0.36
CC = DW * 0.44
comp = [
[Paragraph("Feature", sCellHdr),
Paragraph("Gilbert's Syndrome", sCellHdr),
Paragraph("Crigler-Najjar Syndrome", sCellHdr)],
[Paragraph("Gene / Mutation", sCellRowHdr),
Paragraph("UGT1A1 <b>promoter</b>: A(TA)7TAA repeat (UGT1A1*28)\n"
"Reduces transcription factor binding\nAutosomal recessive", sCellG),
Paragraph("<b>Type 1:</b> Null mutations in UGT1A1 coding sequence (59+ mutations identified)\n"
"<b>Type 2:</b> Missense mutations - reduced but detectable activity (48+ mutations)\n"
"Autosomal recessive", sCellCN)],
[Paragraph("Prevalence", sCellRowHdr),
Paragraph("4-16% of population (most common hereditary hyperbilirubinemia)\n"
"Allele freq: ~42% Black, ~30% White, ~10% Asian", sCellG),
Paragraph("<b>Type 1:</b> Fewer than 1 in 1,000,000 (extremely rare)\n"
"<b>Type 2:</b> Slightly more common than Type 1; still very rare", sCellCN)],
[Paragraph("Age of Onset", sCellRowHdr),
Paragraph("Adolescence (sex steroids alter bilirubin metabolism)\n"
"Often first found incidentally on blood tests", sCellG),
Paragraph("<b>Type 1:</b> Neonatal period - severe jaundice from birth\n"
"<b>Type 2:</b> Neonatal/early childhood", sCellCN)],
[Paragraph("Bilirubin Level", sCellRowHdr),
Paragraph("1.5-4 mg/dL (unconjugated/indirect)\n"
"2-3x rise with fasting, stress, illness, or exercise", sCellG),
Paragraph("<b>Type 1:</b> 18-45 mg/dL (unconjugated)\n"
"<b>Type 2:</b> 6-25 mg/dL (unconjugated)", sCellCN)],
[Paragraph("Clinical Features", sCellRowHdr),
Paragraph("Mild intermittent jaundice/icterus\nNo hemolysis, no liver disease\n"
"Completely asymptomatic otherwise\nNormal stools and urine color", sCellG),
Paragraph("<b>Type 1:</b> Severe jaundice, kernicterus (bilirubin encephalopathy), brain damage, death if untreated\n"
"<b>Type 2:</b> Moderate jaundice; kernicterus rare but possible during illness or fasting", sCellCN)],
[Paragraph("Liver Histology /\nLFTs", sCellRowHdr),
Paragraph("Normal liver histology\nAll LFTs normal (ALT, AST, ALP, albumin, PT)\n"
"No structural liver damage", sCellG),
Paragraph("Normal liver histology and synthetic function\n"
"All LFTs normal - no cirrhosis or fibrosis\n"
"(Liver structure is intact in both types)", sCellCN)],
[Paragraph("Phenobarbital\nResponse", sCellRowHdr),
Paragraph("YES - phenobarbital induces UGT1A1, normalises bilirubin\n"
"(Also used as a diagnostic test)", sCellG),
Paragraph("<b>Type 1:</b> NO response (no enzyme to induce - key differentiator)\n"
"<b>Type 2:</b> YES - bilirubin reduced to 3-5 mg/dL", sCellCN)],
[Paragraph("Treatment", sCellRowHdr),
Paragraph("None required\nAvoid prolonged fasting\n"
"Awareness of drug interactions (irinotecan, raloxifene)", sCellG),
Paragraph("<b>Type 1:</b> Phototherapy ~12 hrs/day; exchange transfusion (neonatal); "
"oral calcium phosphate; early liver transplantation (only cure); plasmapheresis for acute spikes\n\n"
"<b>Type 2:</b> Phenobarbital (first-line); phototherapy if needed; avoid fasting/illness triggers", sCellCN)],
[Paragraph("Prognosis", sCellRowHdr),
Paragraph("Excellent - benign, lifelong but harmless\n"
"Normal life expectancy, no treatment needed", sCellG),
Paragraph("<b>Type 1:</b> Fatal without treatment; liver transplant is the only cure\n"
"<b>Type 2:</b> Generally good with phenobarbital; rare kernicterus risk", sCellCN)],
[Paragraph("Key Drug\nInteractions", sCellRowHdr),
Paragraph("<b>Irinotecan (CPT-11):</b> SN-38 metabolite not cleared - causes severe diarrhea and myelosuppression\n"
"<b>Raloxifene:</b> 2x higher drug exposure\n"
"<b>HIV PIs</b> (atazanavir, indinavir): inhibit UGT1A1, worsen hyperbilirubinemia", sCellG),
Paragraph("Any drug or physiological state reducing residual UGT1A1 activity can cause dangerous bilirubin spikes\n"
"Fasting and infection are common triggers in Type 2", sCellCN)],
]
ct = Table(comp, colWidths=[CL, CG, CC], repeatRows=1)
ts = TableStyle([
("BACKGROUND", (0,0), (0,0), C_NAVY),
("BACKGROUND", (1,0), (1,0), C_GOLD),
("BACKGROUND", (2,0), (2,0), C_RED),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#CCCCCC")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
])
for i in range(1, len(comp)):
if i % 2 == 1:
ts.add("BACKGROUND", (0, i), (0, i), C_NAVY)
ts.add("BACKGROUND", (1, i), (1, i), C_GOLD_LIGHT)
ts.add("BACKGROUND", (2, i), (2, i), C_RED_LIGHT)
else:
ts.add("BACKGROUND", (0, i), (0, i), colors.HexColor("#243356"))
ts.add("BACKGROUND", (1, i), (1, i), colors.HexColor("#FFFBF0"))
ts.add("BACKGROUND", (2, i), (2, i), colors.HexColor("#FFF5F5"))
ct.setStyle(ts)
story.append(ct)
story.append(Spacer(1, 12))
# ═══════════════════════════════════════════════
# PATHOPHYSIOLOGY
# ═══════════════════════════════════════════════
story.append(section_header("Pathophysiology: Shared Gene, Different Severity"))
story.append(Spacer(1, 6))
P3 = (DW - 8) / 3
path = Table([[
Paragraph("<b>Normal Bilirubin Conjugation</b><br/><br/>"
"RBC breakdown → Heme → Biliverdin → "
"Unconjugated bilirubin (albumin-bound) → Hepatocyte uptake → "
"UGT1A1 attaches glucuronic acid → Conjugated bilirubin (water-soluble) → "
"Bile ducts → Gut → Excreted in stool",
ps("p1", fontSize=8.5, fontName="Helvetica", textColor=C_DARK, leading=12,
alignment=TA_LEFT)),
Paragraph("<b>Gilbert's Syndrome</b><br/><br/>"
"UGT1A1*28 promoter mutation reduces enzyme transcription to 10-33% of normal. "
"This partial activity is sufficient to prevent toxicity. "
"Mild unconjugated bilirubin rises intermittently with fasting or illness. "
"Completely benign.",
ps("p2", fontSize=8.5, fontName="Helvetica", textColor=C_DARK, leading=12,
alignment=TA_LEFT)),
Paragraph("<b>Crigler-Najjar Syndrome</b><br/><br/>"
"<b>Type 1:</b> Null mutations abolish all UGT1A1 activity (0%). Massive unconjugated "
"bilirubin crosses the blood-brain barrier causing kernicterus and death.<br/>"
"<b>Type 2:</b> Missense mutations leave less than 10% activity. "
"Serious but survivable; phenobarbital induces residual enzyme.",
ps("p3", fontSize=8.5, fontName="Helvetica", textColor=C_DARK, leading=12,
alignment=TA_LEFT)),
]], colWidths=[P3, P3, P3])
path.setStyle(TableStyle([
("BACKGROUND", (0,0), (0,0), C_TEAL_LIGHT),
("BACKGROUND", (1,0), (1,0), C_GOLD_LIGHT),
("BACKGROUND", (2,0), (2,0), C_RED_LIGHT),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#CCCCCC")),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(path)
story.append(Spacer(1, 12))
# ═══════════════════════════════════════════════
# CLINICAL PEARLS
# ═══════════════════════════════════════════════
story.append(section_header("Clinical Pearls & Exam Points"))
story.append(Spacer(1, 6))
def pearl_section(title, hdr_col, bg_col, bullets):
hdr = Table([[Paragraph(title, ps("ph",
fontSize=10, fontName="Helvetica-Bold", textColor=C_WHITE,
alignment=TA_LEFT, leading=14))]], colWidths=[DW])
hdr.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), hdr_col),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
]))
b_rows = []
for b in bullets:
b_rows.append([
Paragraph("•", ps("bt", fontSize=10, fontName="Helvetica-Bold",
textColor=hdr_col, leading=13, alignment=TA_CENTER)),
Paragraph(b, ps("bb", fontSize=8.8, fontName="Helvetica",
textColor=C_DARK, leading=12, alignment=TA_LEFT)),
])
bt = Table(b_rows, colWidths=[14, DW - 14])
bt.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg_col),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (0,-1), 5),
("LEFTPADDING", (1,0), (1,-1), 4),
("RIGHTPADDING", (0,0), (-1,-1), 4),
("VALIGN", (0,0), (-1,-1), "TOP"),
("LINEBELOW", (0,0), (-1,-2), 0.3, colors.HexColor("#E0E0E0")),
]))
return [hdr, bt, Spacer(1, 8)]
gilberts_pearls = [
"Most common hereditary hyperbilirubinemia - affects up to 16% of the population.",
"Only unconjugated (indirect) bilirubin is elevated - direct bilirubin is NORMAL.",
"All LFTs (ALT, AST, ALP, GGT, albumin, prothrombin time) are NORMAL - key diagnostic point.",
"Diagnosis is clinical: mild isolated unconjugated hyperbilirubinemia + normal LFTs + no hemolysis.",
"Phenobarbital reduces bilirubin to normal (diagnostic and therapeutic).",
"Fasting 48 hours or IV nicotinic acid provokes bilirubin rise (diagnostic provocative test).",
"CRITICAL drug interaction: Irinotecan (CPT-11) - active metabolite SN-38 is glucuronidated by UGT1A1; Gilbert's patients develop severe diarrhea and myelosuppression. Genetic testing before irinotecan is recommended.",
"Raloxifene (SERM for osteoporosis): 2x higher drug exposure in *28 homozygotes.",
"HIV protease inhibitors (atazanavir, indinavir) inhibit UGT1A1 and can unmask or worsen Gilbert's.",
"No treatment required; excellent prognosis; completely normal life expectancy.",
]
cn_pearls = [
"Type 1: Bilirubin over 20 mg/dL in neonates - EMERGENCY. Without phototherapy, fatal within 15 months from kernicterus.",
"Type 1: Completely UNRESPONSIVE to phenobarbital - this is the key clinical differentiator from Type 2.",
"Type 1: Phototherapy 12 hrs/day required from birth; liver transplantation is the ONLY definitive cure.",
"Type 1: Oral calcium phosphate binds bilirubin photo-isomers in gut, disrupting enterohepatic recirculation.",
"Type 1: Plasmapheresis can bridge acutely dangerous bilirubin spikes.",
"Type 2: Phenobarbital is first-line and effective (reduces bilirubin to 3-5 mg/dL).",
"Type 2: Kernicterus is rare but documented - especially during fasting, illness, or surgery.",
"Both types: Liver histology and all liver synthetic functions (albumin, PT) are NORMAL.",
"Both types: Autosomal recessive inheritance; genetic counselling for affected families is important.",
"Gene therapy and hepatocyte transplantation are under active investigation for Type 1 Crigler-Najjar.",
]
for item in pearl_section("Gilbert's Syndrome", C_GOLD, C_GOLD_LIGHT, gilberts_pearls):
story.append(item)
for item in pearl_section("Crigler-Najjar Syndrome (Types 1 and 2)", C_RED, C_RED_LIGHT, cn_pearls):
story.append(item)
story.append(Spacer(1, 4))
# ═══════════════════════════════════════════════
# DIAGNOSTIC WORKUP TABLE
# ═══════════════════════════════════════════════
story.append(section_header("Diagnostic Workup"))
story.append(Spacer(1, 6))
d_col = [DW*0.05, DW*0.25, DW*0.30, DW*0.40]
diag = [
[Paragraph("Step", sCellHdr),
Paragraph("Investigation", sCellHdr),
Paragraph("Gilbert's Expected", sCellHdr),
Paragraph("Crigler-Najjar Expected", sCellHdr)],
[Paragraph("1", sCellG),
Paragraph("Total & Direct Bilirubin", sCellG),
Paragraph("Total elevated (1.5-4 mg/dL)\nDirect bilirubin: NORMAL", sCellG),
Paragraph("Total markedly elevated\nDirect bilirubin: Normal (unconjugated disorder)", sCellCN)],
[Paragraph("2", sCellG),
Paragraph("Full LFTs (ALT, AST, ALP, GGT,\nAlbumin, Prothrombin time)", sCellG),
Paragraph("ALL NORMAL", sCellG),
Paragraph("ALL NORMAL\n(liver synthetic function intact)", sCellCN)],
[Paragraph("3", sCellG),
Paragraph("CBC + Reticulocytes + Coombs test", sCellG),
Paragraph("Normal (rules out hemolysis)", sCellG),
Paragraph("Normal (rules out hemolysis)", sCellCN)],
[Paragraph("4", sCellG),
Paragraph("Phenobarbital trial", sCellG),
Paragraph("Bilirubin normalises", sCellG),
Paragraph("Type 1: No response\nType 2: Bilirubin falls to 3-5 mg/dL", sCellCN)],
[Paragraph("5", sCellG),
Paragraph("Fasting test / IV nicotinic acid", sCellG),
Paragraph("Bilirubin rises 2-3x", sCellG),
Paragraph("Already markedly elevated at baseline", sCellCN)],
[Paragraph("6", sCellG),
Paragraph("UGT1A1 genetic testing", sCellG),
Paragraph("UGT1A1*28 homozygous\n(TA)7 promoter repeat", sCellG),
Paragraph("Coding sequence mutations\n(59+ for Type 1; 48+ for Type 2)", sCellCN)],
]
dt = Table(diag, colWidths=d_col, repeatRows=1)
dt.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_NAVY),
("BACKGROUND", (2,1), (2,-1), C_GOLD_LIGHT),
("BACKGROUND", (3,1), (3,-1), C_RED_LIGHT),
("ROWBACKGROUNDS",(0,1), (1,-1), [C_LIGHT_GREY, C_WHITE]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#CCCCCC")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(dt)
story.append(Spacer(1, 12))
# ═══════════════════════════════════════════════
# FOOTER
# ═══════════════════════════════════════════════
story.append(HRFlowable(width=DW, thickness=0.5, color=C_MID))
story.append(Spacer(1, 4))
story.append(Paragraph(
"Compiled by Orris Medical AI • Sources: Goldman-Cecil Medicine 2V (2022), Harper's Illustrated Biochemistry 32e, "
"Yamada's Textbook of Gastroenterology 7e, Quick Compendium of Clinical Pathology 5e • July 2026 • For educational use only",
sFootnote))
doc.build(story)
print("PDF created:", OUTPUT)
cat > /home/daytona/workspace/jaundice-comparison/create_pdf.py << 'PYEOF' from reportlab.lib.pagesizes import A4 from reportlab.lib import colors from reportlab.lib.styles import ParagraphStyle from reportlab.lib.units import cm from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, HRFlowable from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY OUTPUT = "/home/daytona/workspace/jaundice-comparison/Gilberts_vs_CriglerNajjar.pdf" C_GOLD = colors.HexColor("#D4860A") C_GOLD_LIGHT = colors.HexColor("#FEF3DC") C_RED = colors.HexColor("#B91C1C") C_RED_LIGHT = colors.HexColor("#FDECEA") C_DARK = colors.HexColor("#1A1A2E") C_MID = colors.HexColor("#4A4A6A") C_LIGHT_GREY = colors.HexColor("#F4F4F8") C_WHITE = colors.white C_TEAL_LIGHT = colors.HexColor("#E6F4FA") C_NAVY = colors.HexColor("#1E3A5F") W, H = A4 doc = SimpleDocTemplate(OUTPUT, pagesize=A4, rightMargin=1.8*cm, leftMargin=1.8*cm, topMargin=1.5*cm, bottomMargin=1.5*cm, title="Gilbert's vs Crigler-Najjar Syndrome", author="Orris Medical Library") DW = W - 2*1.8*cm def ps(name, **kw): return ParagraphStyle(name, **kw) sBT = ps("bT", fontSize=22, textColor=C_WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=28) sBS = ps("bS", fontSize=11, textColor=colors.HexColor("#CBD5E1"), fontName="Helvetica", alignment=TA_CENTER, leading=15) sSN = ps("sN", fontSize=7.5, textColor=C_MID, fontName="Helvetica-Oblique", alignment=TA_CENTER, leading=10) sSH = ps("sH", fontSize=12, textColor=C_WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=15) sBody = ps("sB", fontSize=9, textColor=C_DARK, fontName="Helvetica", leading=13, alignment=TA_JUSTIFY) sCH = ps("cH", fontSize=10, textColor=C_WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=14) sCRH = ps("cRH", fontSize=8.5, textColor=C_WHITE, fontName="Helvetica-Bold", alignment=TA_LEFT, leading=12) sCG = ps("cG", fontSize=8.8, textColor=C_DARK, fontName="Helvetica", leading=12, alignment=TA_LEFT) sCN_s = ps("cN", fontSize=8.8, textColor=C_DARK, fontName="Helvetica", leading=12, alignment=TA_LEFT) sF = ps("sF", fontSize=7.5, textColor=C_MID, fontName="Helvetica-Oblique", alignment=TA_CENTER, leading=10) sNum = ps("sNum", fontSize=18, textColor=C_NAVY, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=22) sNL = ps("sNL", fontSize=7.5, textColor=C_MID, fontName="Helvetica", alignment=TA_CENTER, leading=10) def sec_hdr(text): t = Table([[Paragraph(text, sSH)]], colWidths=[DW]) t.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),C_NAVY), ("TOPPADDING",(0,0),(-1,-1),7),("BOTTOMPADDING",(0,0),(-1,-1),7), ("LEFTPADDING",(0,0),(-1,-1),10),("RIGHTPADDING",(0,0),(-1,-1),10)])) return t story = [] # Header hdr = Table([[Paragraph("Gilbert's Syndrome vs Crigler-Najjar Syndrome", sBT)], [Paragraph("Clinical Comparison of Hereditary Unconjugated Hyperbilirubinemias", sBS)]], colWidths=[DW]) hdr.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),C_NAVY), ("TOPPADDING",(0,0),(-1,-1),14),("BOTTOMPADDING",(0,0),(-1,-1),14), ("LEFTPADDING",(0,0),(-1,-1),10),("RIGHTPADDING",(0,0),(-1,-1),10)])) story += [hdr, Spacer(1,6)] src = Table([[Paragraph("Sources: Goldman-Cecil Medicine (2022) | Harper's Biochemistry 32e | Yamada's Gastroenterology 7e | Quick Compendium Clinical Pathology 5e", sSN)]], colWidths=[DW]) src.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),C_LIGHT_GREY), ("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4), ("LEFTPADDING",(0,0),(-1,-1),6)])) story += [src, Spacer(1,10)] # Stats sc = (DW - 8) / 3 def stat_card(num, lbl, bg): t = Table([[Paragraph(num, sNum)],[Paragraph(lbl, sNL)]], colWidths=[sc]) t.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),bg), ("TOPPADDING",(0,0),(-1,-1),8),("BOTTOMPADDING",(0,0),(-1,-1),8), ("LEFTPADDING",(0,0),(-1,-1),4),("RIGHTPADDING",(0,0),(-1,-1),4), ("BOX",(0,0),(-1,-1),0.5,colors.HexColor("#CCCCCC"))])) return t stats = Table([[ stat_card("4-16%","Gilbert's prevalence\nin general population",C_GOLD_LIGHT), Spacer(4,1), stat_card("<1:1M","Crigler-Najjar\nextremely rare",C_RED_LIGHT), Spacer(4,1), stat_card("UGT1A1","Shared causative gene\nbilirubin conjugation",C_TEAL_LIGHT), ]], colWidths=[sc,4,sc,4,sc]) story += [stats, Spacer(1,12)] # Overview story += [sec_hdr("Overview"), Spacer(1,6)] story.append(Paragraph( "Both Gilbert's syndrome and Crigler-Najjar syndrome are <b>hereditary unconjugated " "hyperbilirubinemias</b> caused by mutations in <b>UGT1A1</b>, the gene encoding bilirubin " "UDP-glucuronosyltransferase. Despite sharing the same genetic locus, their clinical severity " "differs enormously based on residual enzyme activity. Total UGT1A1 activity must fall below 50% " "of normal to produce hyperbilirubinemia; all three conditions are autosomal recessive.", sBody)) story.append(Spacer(1,6)) ew = [DW*0.28, DW*0.17, DW*0.16, DW*0.39] et = Table([ [Paragraph("Condition",sCH),Paragraph("Enzyme Activity",sCH),Paragraph("Serum Bilirubin",sCH),Paragraph("Mechanism",sCH)], [Paragraph("Gilbert's Syndrome",sCG),Paragraph("10-33% of normal",sCG),Paragraph("1.5-4 mg/dL",sCG),Paragraph("Promoter repeat (UGT1A1*28) reduces transcription",sCG)], [Paragraph("Crigler-Najjar Type 2",sCN_s),Paragraph("Up to 10% of normal",sCN_s),Paragraph("6-25 mg/dL",sCN_s),Paragraph("Missense mutations - markedly reduced activity",sCN_s)], [Paragraph("Crigler-Najjar Type 1",sCN_s),Paragraph("Absent (0%)",sCN_s),Paragraph("18-45 mg/dL",sCN_s),Paragraph("Null mutations - complete loss of function",sCN_s)], ], colWidths=ew, repeatRows=1) et.setStyle(TableStyle([ ("BACKGROUND",(0,0),(-1,0),C_NAVY), ("BACKGROUND",(0,1),(-1,1),C_GOLD_LIGHT), ("BACKGROUND",(0,2),(-1,2),colors.HexColor("#FDECEA")), ("BACKGROUND",(0,3),(-1,3),C_RED_LIGHT), ("GRID",(0,0),(-1,-1),0.4,colors.HexColor("#CCCCCC")), ("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5), ("LEFTPADDING",(0,0),(-1,-1),5),("RIGHTPADDING",(0,0),(-1,-1),5), ("VALIGN",(0,0),(-1,-1),"MIDDLE")])) story += [et, Spacer(1,12)] # Side-by-side comparison story += [sec_hdr("Detailed Side-by-Side Comparison"), Spacer(1,6)] CL = DW*0.20; CG = DW*0.36; CC = DW*0.44 comp = [ [Paragraph("Feature",sCH), Paragraph("Gilbert's Syndrome",sCH), Paragraph("Crigler-Najjar Syndrome",sCH)], [Paragraph("Gene/Mutation",sCRH), Paragraph("UGT1A1 <b>promoter</b>: A(TA)7TAA repeat (UGT1A1*28) reduces transcription. Autosomal recessive.",sCG), Paragraph("<b>Type 1:</b> Null mutations in UGT1A1 coding sequence (59+ mutations identified).\n<b>Type 2:</b> Missense mutations - reduced activity (48+ mutations). Autosomal recessive.",sCN_s)], [Paragraph("Prevalence",sCRH), Paragraph("4-16% of population. Most common hereditary hyperbilirubinemia. Allele freq: ~42% Black, ~30% White, ~10% Asian.",sCG), Paragraph("<b>Type 1:</b> Fewer than 1 per million (extremely rare).\n<b>Type 2:</b> Slightly more common than Type 1, still very rare.",sCN_s)], [Paragraph("Age of Onset",sCRH), Paragraph("Adolescence (sex steroids alter bilirubin metabolism). Often found incidentally on blood tests.",sCG), Paragraph("<b>Type 1:</b> Neonatal period - severe jaundice from birth.\n<b>Type 2:</b> Neonatal or early childhood.",sCN_s)], [Paragraph("Bilirubin Level",sCRH), Paragraph("1.5-4 mg/dL (unconjugated). Rises 2-3x with fasting, stress, illness, or exercise.",sCG), Paragraph("<b>Type 1:</b> 18-45 mg/dL (unconjugated).\n<b>Type 2:</b> 6-25 mg/dL (unconjugated).",sCN_s)], [Paragraph("Clinical Features",sCRH), Paragraph("Mild intermittent jaundice/icterus. No hemolysis. No liver disease. Otherwise completely asymptomatic. Normal stools and urine.",sCG), Paragraph("<b>Type 1:</b> Severe jaundice, kernicterus (bilirubin encephalopathy), brain damage, death without treatment.\n<b>Type 2:</b> Moderate jaundice; kernicterus rare but possible during illness or fasting.",sCN_s)], [Paragraph("Liver Histology /\nLFTs",sCRH), Paragraph("Normal liver histology. All LFTs normal (ALT, AST, ALP, albumin, PT). No structural liver damage.",sCG), Paragraph("Normal liver histology and all synthetic functions. All LFTs normal. No cirrhosis or fibrosis in either type.",sCN_s)], [Paragraph("Phenobarbital\nResponse",sCRH), Paragraph("YES - phenobarbital induces UGT1A1, normalises bilirubin. (Also used as a diagnostic test.)",sCG), Paragraph("<b>Type 1:</b> NO response (no enzyme to induce) - KEY differentiator from Type 2.\n<b>Type 2:</b> YES - bilirubin reduced to 3-5 mg/dL.",sCN_s)], [Paragraph("Treatment",sCRH), Paragraph("None required. Avoid prolonged fasting. Awareness of drug interactions (irinotecan, raloxifene).",sCG), Paragraph("<b>Type 1:</b> Phototherapy ~12 hrs/day from birth; exchange transfusion (neonatal); oral calcium phosphate; early liver transplantation (only cure); plasmapheresis for acute spikes.\n<b>Type 2:</b> Phenobarbital first-line; phototherapy if needed; avoid fasting/illness triggers.",sCN_s)], [Paragraph("Prognosis",sCRH), Paragraph("Excellent. Benign, lifelong but harmless. Normal life expectancy. No treatment needed.",sCG), Paragraph("<b>Type 1:</b> Fatal without treatment. Liver transplant is the only cure.\n<b>Type 2:</b> Generally good with phenobarbital; rare kernicterus risk remains.",sCN_s)], [Paragraph("Key Drug\nInteractions",sCRH), Paragraph("<b>Irinotecan (CPT-11):</b> SN-38 metabolite accumulates; severe diarrhea and myelosuppression.\n<b>Raloxifene:</b> 2x higher exposure.\n<b>HIV PIs</b> (atazanavir, indinavir): inhibit UGT1A1.",sCG), Paragraph("Any drug or state reducing residual UGT1A1 activity can cause dangerous bilirubin spikes. Fasting and infection are common triggers in Type 2.",sCN_s)], ] ct = Table(comp, colWidths=[CL, CG, CC], repeatRows=1) ts = TableStyle([ ("BACKGROUND",(0,0),(0,0),C_NAVY),("BACKGROUND",(1,0),(1,0),C_GOLD),("BACKGROUND",(2,0),(2,0),C_RED), ("GRID",(0,0),(-1,-1),0.4,colors.HexColor("#CCCCCC")), ("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5), ("LEFTPADDING",(0,0),(-1,-1),5),("RIGHTPADDING",(0,0),(-1,-1),5), ("VALIGN",(0,0),(-1,-1),"TOP"), ]) for i in range(1, len(comp)): bg_g = C_GOLD_LIGHT if i%2==1 else colors.HexColor("#FFFBF0") bg_c = C_RED_LIGHT if i%2==1 else colors.HexColor("#FFF5F5") bg_l = C_NAVY if i%2==1 else colors.HexColor("#243356") ts.add("BACKGROUND",(0,i),(0,i),bg_l) ts.add("BACKGROUND",(1,i),(1,i),bg_g) ts.add("BACKGROUND",(2,i),(2,i),bg_c) ct.setStyle(ts) story += [ct, Spacer(1,12)] # Pathophysiology story += [sec_hdr("Pathophysiology: Shared Gene, Different Severity"), Spacer(1,6)] P3 = (DW - 8) / 3 path = Table([[ Paragraph("<b>Normal Bilirubin Conjugation</b><br/><br/>" "RBC breakdown to Heme to Biliverdin to Unconjugated bilirubin (albumin-bound) to " "Hepatocyte uptake to UGT1A1 attaches glucuronic acid to Conjugated bilirubin (water-soluble) to " "Bile ducts to Gut to Excreted in stool.", ps("p1",fontSize=8.5,fontName="Helvetica",textColor=C_DARK,leading=12,alignment=TA_LEFT)), Paragraph("<b>Gilbert's Syndrome</b><br/><br/>" "UGT1A1*28 promoter mutation reduces enzyme transcription to 10-33% of normal. " "Partial activity prevents toxicity. Mild unconjugated bilirubin rises intermittently " "with fasting or illness. Completely benign.", ps("p2",fontSize=8.5,fontName="Helvetica",textColor=C_DARK,leading=12,alignment=TA_LEFT)), Paragraph("<b>Crigler-Najjar Syndrome</b><br/><br/>" "<b>Type 1:</b> Null mutations abolish all UGT1A1 activity (0%). Massive unconjugated " "bilirubin crosses the blood-brain barrier causing kernicterus and death without treatment. " "<b>Type 2:</b> Missense mutations leave less than 10% residual activity; survivable; " "phenobarbital induces remaining enzyme.", ps("p3",fontSize=8.5,fontName="Helvetica",textColor=C_DARK,leading=12,alignment=TA_LEFT)), ]], colWidths=[P3, P3, P3]) path.setStyle(TableStyle([ ("BACKGROUND",(0,0),(0,0),C_TEAL_LIGHT), ("BACKGROUND",(1,0),(1,0),C_GOLD_LIGHT), ("BACKGROUND",(2,0),(2,0),C_RED_LIGHT), ("GRID",(0,0),(-1,-1),0.5,colors.HexColor("#CCCCCC")), ("TOPPADDING",(0,0),(-1,-1),8),("BOTTOMPADDING",(0,0),(-1,-1),8), ("LEFTPADDING",(0,0),(-1,-1),7),("RIGHTPADDING",(0,0),(-1,-1),7), ("VALIGN",(0,0),(-1,-1),"TOP")])) story += [path, Spacer(1,12)] # Clinical Pearls story += [sec_hdr("Clinical Pearls and Exam Points"), Spacer(1,6)] def pearl_sec(title, hdr_col, bg_col, bullets): items = [] hdr = Table([[Paragraph(title, ps("ph",fontSize=10,fontName="Helvetica-Bold", textColor=C_WHITE,alignment=TA_LEFT,leading=14))]], colWidths=[DW]) hdr.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),hdr_col), ("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5), ("LEFTPADDING",(0,0),(-1,-1),8)])) items.append(hdr) b_rows = [] for b in bullets: b_rows.append([ Paragraph("•", ps("bt",fontSize=10,fontName="Helvetica-Bold",textColor=hdr_col,leading=13,alignment=TA_CENTER)), Paragraph(b, ps("bb",fontSize=8.8,fontName="Helvetica",textColor=C_DARK,leading=12,alignment=TA_LEFT)), ]) bt = Table(b_rows, colWidths=[14, DW-14]) bt.setStyle(TableStyle([ ("BACKGROUND",(0,0),(-1,-1),bg_col), ("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3), ("LEFTPADDING",(0,0),(0,-1),5),("LEFTPADDING",(1,0),(1,-1),4), ("RIGHTPADDING",(0,0),(-1,-1),4),("VALIGN",(0,0),(-1,-1),"TOP"), ("LINEBELOW",(0,0),(-1,-2),0.3,colors.HexColor("#E0E0E0"))])) items += [bt, Spacer(1,8)] return items for item in pearl_sec("Gilbert's Syndrome", C_GOLD, C_GOLD_LIGHT, [ "Most common hereditary hyperbilirubinemia - affects up to 16% of the population.", "Only unconjugated (indirect) bilirubin is elevated - direct bilirubin is NORMAL.", "All LFTs (ALT, AST, ALP, GGT, albumin, prothrombin time) are NORMAL - the key diagnostic point.", "Diagnosis is clinical: mild isolated unconjugated hyperbilirubinemia + normal LFTs + no hemolysis.", "Phenobarbital normalises bilirubin (used as a diagnostic and therapeutic tool).", "Fasting 48 hours or IV nicotinic acid provokes a bilirubin rise (diagnostic provocative test).", "CRITICAL drug interaction: Irinotecan (CPT-11) - SN-38 active metabolite is glucuronidated by UGT1A1; Gilbert's patients develop severe diarrhea and myelosuppression. Genetic testing before irinotecan is now recommended.", "Raloxifene (SERM for osteoporosis): 2x higher drug exposure in UGT1A1*28 homozygotes.", "HIV protease inhibitors (atazanavir, indinavir) inhibit UGT1A1 and can unmask or worsen Gilbert's.", "No treatment required; excellent prognosis; completely normal life expectancy.", ]): story.append(item) for item in pearl_sec("Crigler-Najjar Syndrome (Types 1 and 2)", C_RED, C_RED_LIGHT, [ "Type 1: Bilirubin over 20 mg/dL in neonates - EMERGENCY. Without phototherapy, fatal within 15 months from kernicterus.", "Type 1: Completely UNRESPONSIVE to phenobarbital - this is the KEY clinical differentiator from Type 2.", "Type 1: Phototherapy 12 hrs/day required from birth; liver transplantation is the ONLY definitive cure.", "Type 1: Oral calcium phosphate binds bilirubin photo-isomers in gut, disrupting enterohepatic recirculation.", "Type 1: Plasmapheresis can bridge dangerously acute bilirubin spikes.", "Type 2: Phenobarbital is first-line and effective (reduces bilirubin to 3-5 mg/dL).", "Type 2: Kernicterus is rare but documented - especially during fasting, illness, or surgery.", "Both types: Liver histology and all liver synthetic functions (albumin, PT) are NORMAL.", "Both types: Autosomal recessive inheritance; genetic counselling for affected families.", "Gene therapy and hepatocyte transplantation are under active investigation for Type 1 Crigler-Najjar.", ]): story.append(item) # Diagnostic workup story += [sec_hdr("Diagnostic Workup"), Spacer(1,6)] d_col = [DW*0.05, DW*0.25, DW*0.30, DW*0.40] diag = [ [Paragraph("Step",sCH),Paragraph("Investigation",sCH),Paragraph("Gilbert's Expected",sCH),Paragraph("Crigler-Najjar Expected",sCH)], [Paragraph("1",sCG),Paragraph("Total and Direct Bilirubin",sCG),Paragraph("Total elevated (1.5-4 mg/dL)\nDirect bilirubin: NORMAL",sCG),Paragraph("Total markedly elevated\nDirect bilirubin: Normal (unconjugated disorder)",sCN_s)], [Paragraph("2",sCG),Paragraph("Full LFTs (ALT, AST, ALP, GGT, Albumin, PT)",sCG),Paragraph("ALL NORMAL",sCG),Paragraph("ALL NORMAL\n(liver synthetic function intact)",sCN_s)], [Paragraph("3",sCG),Paragraph("CBC + Reticulocytes + Coombs test",sCG),Paragraph("Normal (rules out hemolysis)",sCG),Paragraph("Normal (rules out hemolysis)",sCN_s)], [Paragraph("4",sCG),Paragraph("Phenobarbital trial",sCG),Paragraph("Bilirubin normalises",sCG),Paragraph("Type 1: No response\nType 2: Bilirubin falls to 3-5 mg/dL",sCN_s)], [Paragraph("5",sCG),Paragraph("Fasting test / IV nicotinic acid",sCG),Paragraph("Bilirubin rises 2-3x",sCG),Paragraph("Already markedly elevated at baseline",sCN_s)], [Paragraph("6",sCG),Paragraph("UGT1A1 genetic testing",sCG),Paragraph("UGT1A1*28 homozygous\n(TA)7 promoter repeat",sCG),Paragraph("Coding sequence mutations\n(59+ for Type 1; 48+ for Type 2)",sCN_s)], ] dt = Table(diag, colWidths=d_col, repeatRows=1) dt.setStyle(TableStyle([ ("BACKGROUND",(0,0),(-1,0),C_NAVY), ("BACKGROUND",(2,1),(2,-1),C_GOLD_LIGHT), ("BACKGROUND",(3,1),(3,-1),C_RED_LIGHT), ("ROWBACKGROUNDS",(0,1),(1,-1),[C_LIGHT_GREY,C_WHITE]), ("GRID",(0,0),(-1,-1),0.4,colors.HexColor("#CCCCCC")), ("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5), ("LEFTPADDING",(0,0),(-1,-1),5),("RIGHTPADDING",(0,0),(-1,-1),5), ("VALIGN",(0,0),(-1,-1),"TOP")])) story += [dt, Spacer(1,10)] # Footer story.append(HRFlowable(width=DW, thickness=0.5, color=C_MID)) story.append(Spacer(1,4)) story.append(Paragraph( "Compiled by Orris Medical AI | Goldman-Cecil Medicine (2022), Harper's Illustrated Biochemistry 32e, " "Yamada's Gastroenterology 7e, Quick Compendium Clinical Pathology 5e | July 2026 | For educational use only", sF)) doc.build(story) print("PDF created:", OUTPUT) PYEOF echo "File written"
cd /home/daytona/workspace/jaundice-comparison && python create_pdf.py 2>&1
cd /home/daytona/workspace/jaundice-comparison && python3 -c " from reportlab.lib.pagesizes import A4 from reportlab.lib.units import cm W, H = A4 DW = W - 2*1.8*cm print('DW:', DW) # stat card sc = (DW - 8) / 3 print('sc:', sc) # bullet table print('bullet col 2:', DW-14, 'with 4+4 padding =', DW-14-8) # path cols P3 = (DW - 8) / 3 print('P3:', P3, 'minus padding 14:', P3-14) # comp table CL=DW*0.20; CG=DW*0.36; CC=DW*0.44 print('CL+CG+CC:', CL+CG+CC, 'DW:', DW) # diag table d_col_sum = DW*0.05 + DW*0.25 + DW*0.30 + DW*0.40 print('diag sum:', d_col_sum, '== DW:', DW) "
cd /home/daytona/workspace/jaundice-comparison && python3 -c " # Find which table causes the problem by building story piece by piece from reportlab.lib.pagesizes import A4 from reportlab.lib import colors from reportlab.lib.styles import ParagraphStyle from reportlab.lib.units import cm from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, HRFlowable from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY import io W, H = A4 DW = W - 2*1.8*cm def ps(name, **kw): return ParagraphStyle(name, **kw) C_NAVY = colors.HexColor('#1E3A5F') C_WHITE = colors.white C_DARK = colors.HexColor('#1A1A2E') C_GOLD = colors.HexColor('#D4860A') C_GOLD_LIGHT = colors.HexColor('#FEF3DC') C_RED = colors.HexColor('#B91C1C') C_RED_LIGHT = colors.HexColor('#FDECEA') sCH = ps('cH', fontSize=10, textColor=C_WHITE, fontName='Helvetica-Bold', alignment=TA_CENTER, leading=14) sCRH = ps('cRH', fontSize=8.5, textColor=C_WHITE, fontName='Helvetica-Bold', alignment=TA_LEFT, leading=12) sCG = ps('cG', fontSize=8.8, textColor=C_DARK, fontName='Helvetica', leading=12, alignment=TA_LEFT) sCN_s = ps('cN', fontSize=8.8, textColor=C_DARK, fontName='Helvetica', leading=12, alignment=TA_LEFT) CL = DW*0.20; CG = DW*0.36; CC = DW*0.44 comp = [ [Paragraph('Feature',sCH), Paragraph(\"Gilbert's Syndrome\",sCH), Paragraph('Crigler-Najjar Syndrome',sCH)], [Paragraph('Gene/Mutation',sCRH), Paragraph('UGT1A1 <b>promoter</b>: A(TA)7TAA repeat (UGT1A1*28) reduces transcription. Autosomal recessive.',sCG), Paragraph('<b>Type 1:</b> Null mutations. <b>Type 2:</b> Missense mutations.',sCN_s)], ] ct = Table(comp, colWidths=[CL, CG, CC], repeatRows=1) ct.setStyle(TableStyle([ ('BACKGROUND',(0,0),(0,0),C_NAVY),('BACKGROUND',(1,0),(1,0),C_GOLD),('BACKGROUND',(2,0),(2,0),C_RED), ('GRID',(0,0),(-1,-1),0.4,colors.HexColor('#CCCCCC')), ('TOPPADDING',(0,0),(-1,-1),5),('BOTTOMPADDING',(0,0),(-1,-1),5), ('LEFTPADDING',(0,0),(-1,-1),5),('RIGHTPADDING',(0,0),(-1,-1),5), ('VALIGN',(0,0),(-1,-1),'TOP'), ('BACKGROUND',(0,1),(0,1),C_NAVY),('BACKGROUND',(1,1),(1,1),C_GOLD_LIGHT),('BACKGROUND',(2,1),(2,1),C_RED_LIGHT), ])) buf = io.BytesIO() doc = SimpleDocTemplate(buf, pagesize=A4, rightMargin=1.8*cm, leftMargin=1.8*cm, topMargin=1.5*cm, bottomMargin=1.5*cm) try: doc.build([ct]) print('comp table OK') except Exception as e: print('comp table FAIL:', e) " 2>&1
cd /home/daytona/workspace/jaundice-comparison && python3 -c " # Test the pearl_sec function - that's using colWidths=[14, DW-14] which may cause issues with padding from reportlab.lib.pagesizes import A4 from reportlab.lib import colors from reportlab.lib.styles import ParagraphStyle from reportlab.lib.units import cm from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle from reportlab.lib.enums import TA_CENTER, TA_LEFT import io W, H = A4 DW = W - 2*1.8*cm C_GOLD = colors.HexColor('#D4860A') C_GOLD_LIGHT = colors.HexColor('#FEF3DC') C_WHITE = colors.white C_DARK = colors.HexColor('#1A1A2E') C_NAVY = colors.HexColor('#1E3A5F') def ps(name, **kw): return ParagraphStyle(name, **kw) def pearl_sec(title, hdr_col, bg_col, bullets): items = [] hdr = Table([[Paragraph(title, ps('ph',fontSize=10,fontName='Helvetica-Bold', textColor=C_WHITE,alignment=TA_LEFT,leading=14))]], colWidths=[DW]) hdr.setStyle(TableStyle([('BACKGROUND',(0,0),(-1,-1),hdr_col), ('TOPPADDING',(0,0),(-1,-1),5),('BOTTOMPADDING',(0,0),(-1,-1),5), ('LEFTPADDING',(0,0),(-1,-1),8)])) items.append(hdr) b_rows = [] for b in bullets: b_rows.append([ Paragraph('•', ps('bt',fontSize=10,fontName='Helvetica-Bold',textColor=hdr_col,leading=13,alignment=TA_CENTER)), Paragraph(b, ps('bb',fontSize=8.8,fontName='Helvetica',textColor=C_DARK,leading=12,alignment=TA_LEFT)), ]) bt = Table(b_rows, colWidths=[14, DW-14]) bt.setStyle(TableStyle([ ('BACKGROUND',(0,0),(-1,-1),bg_col), ('TOPPADDING',(0,0),(-1,-1),3),('BOTTOMPADDING',(0,0),(-1,-1),3), ('LEFTPADDING',(0,0),(0,-1),5),('LEFTPADDING',(1,0),(1,-1),4), ('RIGHTPADDING',(0,0),(-1,-1),4),('VALIGN',(0,0),(-1,-1),'TOP'), ('LINEBELOW',(0,0),(-1,-2),0.3,colors.HexColor('#E0E0E0'))])) items += [bt, Spacer(1,8)] return items story = [] for item in pearl_sec(\"Gilbert's Syndrome\", C_GOLD, C_GOLD_LIGHT, [ 'Most common hereditary hyperbilirubinemia.', 'Only unconjugated (indirect) bilirubin is elevated - direct bilirubin is NORMAL.', ]): story.append(item) buf = io.BytesIO() doc = SimpleDocTemplate(buf, pagesize=A4, rightMargin=1.8*cm, leftMargin=1.8*cm, topMargin=1.5*cm, bottomMargin=1.5*cm) try: doc.build(story) print('pearl_sec OK') except Exception as e: print('pearl_sec FAIL:', e) " 2>&1
cd /home/daytona/workspace/jaundice-comparison && python3 -c " # Binary search - test with progressively more of the script # The issue must be the Spacer inside a Table cell (stats row) from reportlab.lib.pagesizes import A4 from reportlab.lib import colors from reportlab.lib.styles import ParagraphStyle from reportlab.lib.units import cm from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle from reportlab.lib.enums import TA_CENTER import io W, H = A4 DW = W - 2*1.8*cm C_GOLD_LIGHT = colors.HexColor('#FEF3DC') C_RED_LIGHT = colors.HexColor('#FDECEA') C_TEAL_LIGHT = colors.HexColor('#E6F4FA') C_NAVY = colors.HexColor('#1E3A5F') C_MID = colors.HexColor('#4A4A6A') C_WHITE = colors.white C_DARK = colors.HexColor('#1A1A2E') def ps(name, **kw): return ParagraphStyle(name, **kw) sNum = ps('sNum', fontSize=18, textColor=C_NAVY, fontName='Helvetica-Bold', alignment=TA_CENTER, leading=22) sNL = ps('sNL', fontSize=7.5, textColor=C_MID, fontName='Helvetica', alignment=TA_CENTER, leading=10) sc = (DW - 8) / 3 def stat_card(num, lbl, bg): t = Table([[Paragraph(num, sNum)],[Paragraph(lbl, sNL)]], colWidths=[sc]) t.setStyle(TableStyle([('BACKGROUND',(0,0),(-1,-1),bg), ('TOPPADDING',(0,0),(-1,-1),8),('BOTTOMPADDING',(0,0),(-1,-1),8), ('LEFTPADDING',(0,0),(-1,-1),4),('RIGHTPADDING',(0,0),(-1,-1),4), ('BOX',(0,0),(-1,-1),0.5,colors.HexColor('#CCCCCC'))])) return t # The stats row has Spacer() inside a Table cell - that might be the issue! stats = Table([[ stat_card('4-16%','Gilbert prevalence',C_GOLD_LIGHT), Spacer(4,1), stat_card('<1:1M','Crigler-Najjar',C_RED_LIGHT), Spacer(4,1), stat_card('UGT1A1','Shared gene',C_TEAL_LIGHT), ]], colWidths=[sc,4,sc,4,sc]) buf = io.BytesIO() doc = SimpleDocTemplate(buf, pagesize=A4, rightMargin=1.8*cm, leftMargin=1.8*cm, topMargin=1.5*cm, bottomMargin=1.5*cm) try: doc.build([stats]) print('stats OK') except Exception as e: print('stats FAIL:', e) " 2>&1
cd /home/daytona/workspace/jaundice-comparison && python3 << 'EOF' # Fix: replace Spacer in table cells with a blank Paragraph, or just use 3-col table with spacing via padding from reportlab.lib.pagesizes import A4 from reportlab.lib import colors from reportlab.lib.styles import ParagraphStyle from reportlab.lib.units import cm from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, HRFlowable from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY import io W, H = A4 DW = W - 2*1.8*cm C_GOLD_LIGHT = colors.HexColor('#FEF3DC') C_RED_LIGHT = colors.HexColor('#FDECEA') C_TEAL_LIGHT = colors.HexColor('#E6F4FA') C_NAVY = colors.HexColor('#1E3A5F') C_MID = colors.HexColor('#4A4A6A') def ps(name, **kw): return ParagraphStyle(name, **kw) sNum = ps('sNum', fontSize=18, textColor=C_NAVY, fontName='Helvetica-Bold', alignment=TA_CENTER, leading=22) sNL = ps('sNL', fontSize=7.5, textColor=C_MID, fontName='Helvetica', alignment=TA_CENTER, leading=10) sc = DW / 3 # no spacers, just equal columns with inner padding stats = Table([[ Paragraph("4-16%\nGilbert's prevalence\nin general population", ps("s1", fontSize=16, textColor=C_NAVY, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=20)), Paragraph("<1:1M\nCrigler-Najjar\nextremely rare", ps("s2", fontSize=16, textColor=colors.HexColor("#B91C1C"), fontName="Helvetica-Bold", alignment=TA_CENTER, leading=20)), Paragraph("UGT1A1\nShared causative gene\nbilirubin conjugation", ps("s3", fontSize=16, textColor=colors.HexColor("#0A7EA4"), fontName="Helvetica-Bold", alignment=TA_CENTER, leading=20)), ]], colWidths=[sc, sc, sc]) stats.setStyle(TableStyle([ ('BACKGROUND',(0,0),(0,0),C_GOLD_LIGHT), ('BACKGROUND',(1,0),(1,0),C_RED_LIGHT), ('BACKGROUND',(2,0),(2,0),C_TEAL_LIGHT), ('TOPPADDING',(0,0),(-1,-1),10),('BOTTOMPADDING',(0,0),(-1,-1),10), ('LEFTPADDING',(0,0),(-1,-1),6),('RIGHTPADDING',(0,0),(-1,-1),6), ('BOX',(0,0),(-1,-1),0.5,colors.HexColor('#CCCCCC')), ('INNERGRID',(0,0),(-1,-1),0.5,colors.HexColor('#CCCCCC')), ('VALIGN',(0,0),(-1,-1),'MIDDLE'), ])) buf = io.BytesIO() doc = SimpleDocTemplate(buf, pagesize=A4, rightMargin=1.8*cm, leftMargin=1.8*cm, topMargin=1.5*cm, bottomMargin=1.5*cm) try: doc.build([stats]) print('FIXED stats OK') except Exception as e: print('FAIL:', e) EOF