Could you compile a case presentation on chronic liver disease from verified online sources
"chronic liver disease" diagnosis management
chronic liver disease case presentation clinical features investigations management 2024
https://www.ncbi.nlm.nih.gov/books/NBK554597
PMID: 40348684
https://www.ncbi.nlm.nih.gov/books/NBK554597
"cirrhosis" AND "MELD score" AND "prognosis"
PMID: 37751367
ls -la /home/daytona/workspace/ && mkdir -p /home/daytona/workspace/cld-case-presentation
mkdir -p /home/user/workspace/cld-case-presentation && echo "Directory created"
echo $HOME && ls -la $HOME
mkdir -p /home/daytona/cld-case && echo "OK"
/home/daytona/cld-case/build_pdf.py
#!/usr/bin/env python3
"""
Chronic Liver Disease - Full Case Presentation PDF Generator
For residents / junior doctors
Sources: Harrison's 22E, Sleisenger & Fordtran, Goldman-Cecil Medicine,
StatPearls (NCBI), AAFP AFP 2019, PubMed (MELD 3.0 review 2024,
EASL AIH guidelines 2025, Baveno VII portal hypertension review 2024)
"""
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, PageBreak, KeepTogether
)
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
import os
OUTPUT = "/home/daytona/cld-case/Chronic_Liver_Disease_Case_Presentation.pdf"
# ── Colour palette ──────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1a3a5c")
STEEL = colors.HexColor("#2e6da4")
ACCENT = colors.HexColor("#e8f0f7")
AMBER = colors.HexColor("#f5a623")
AMBER_BG = colors.HexColor("#fff8ec")
RED_DARK = colors.HexColor("#b02a2a")
RED_BG = colors.HexColor("#fdf2f2")
GREEN = colors.HexColor("#2a7a3b")
GREEN_BG = colors.HexColor("#f0faf2")
GREY = colors.HexColor("#555555")
LGREY = colors.HexColor("#dddddd")
WHITE = colors.white
# ── Page template with header/footer ────────────────────────────────────────
def make_doc(path):
doc = SimpleDocTemplate(
path,
pagesize=A4,
leftMargin=2*cm, rightMargin=2*cm,
topMargin=2.5*cm, bottomMargin=2.5*cm,
title="Chronic Liver Disease - Case Presentation",
author="Orris Medical Education",
subject="Full worked-up case for residents",
)
return doc
def header_footer(canvas, doc):
canvas.saveState()
W, H = A4
# Header bar
canvas.setFillColor(NAVY)
canvas.rect(0, H - 1.5*cm, W, 1.5*cm, fill=1, stroke=0)
canvas.setFillColor(WHITE)
canvas.setFont("Helvetica-Bold", 9)
canvas.drawString(2*cm, H - 0.95*cm, "CHRONIC LIVER DISEASE | Clinical Case Presentation")
canvas.setFont("Helvetica", 8)
canvas.drawRightString(W - 2*cm, H - 0.95*cm, "For Residents & Junior Doctors")
# Footer
canvas.setFillColor(NAVY)
canvas.rect(0, 0, W, 1*cm, fill=1, stroke=0)
canvas.setFillColor(WHITE)
canvas.setFont("Helvetica", 7.5)
canvas.drawString(2*cm, 0.35*cm,
"Sources: Harrison's 22E · Sleisenger & Fordtran · Goldman-Cecil · StatPearls · AAFP AFP 2019 · PubMed")
canvas.drawRightString(W - 2*cm, 0.35*cm, f"Page {doc.page}")
canvas.restoreState()
# ── Styles ───────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()
def S(name, **kw):
return ParagraphStyle(name, **kw)
title_style = S("Title_",
fontName="Helvetica-Bold", fontSize=22, textColor=WHITE,
alignment=TA_CENTER, leading=28)
subtitle_style = S("Subtitle_",
fontName="Helvetica", fontSize=11, textColor=WHITE,
alignment=TA_CENTER, leading=16)
section_style = S("Section_",
fontName="Helvetica-Bold", fontSize=13, textColor=WHITE,
leading=18, leftIndent=6, spaceAfter=2)
subsection_style = S("Subsection_",
fontName="Helvetica-Bold", fontSize=11, textColor=NAVY,
leading=16, spaceAfter=4, spaceBefore=8)
body_style = S("Body_",
fontName="Helvetica", fontSize=9.5, textColor=GREY,
leading=15, spaceAfter=4, alignment=TA_JUSTIFY)
body_bold = S("BodyBold_",
fontName="Helvetica-Bold", fontSize=9.5, textColor=colors.black,
leading=15, spaceAfter=2)
bullet_style = S("Bullet_",
fontName="Helvetica", fontSize=9.5, textColor=GREY,
leading=14, spaceAfter=2, leftIndent=14, bulletIndent=4)
alert_style = S("Alert_",
fontName="Helvetica-Bold", fontSize=9.5, textColor=RED_DARK,
leading=14, spaceAfter=2)
highlight_style = S("Highlight_",
fontName="Helvetica-Bold", fontSize=9.5, textColor=GREEN,
leading=14, spaceAfter=2)
small_style = S("Small_",
fontName="Helvetica", fontSize=8.5, textColor=GREY,
leading=12, spaceAfter=2)
caption_style = S("Caption_",
fontName="Helvetica-Oblique", fontSize=8, textColor=GREY,
leading=11, spaceAfter=6, alignment=TA_CENTER)
ref_style = S("Ref_",
fontName="Helvetica", fontSize=7.5, textColor=GREY,
leading=11, spaceAfter=2)
# ── Helpers ───────────────────────────────────────────────────────────────────
def section_header(text, color=NAVY):
"""Returns a navy banner with white heading text."""
tbl = Table([[Paragraph(text, section_style)]], colWidths=[17.0*cm])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), color),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("ROUNDEDCORNERS", [4,4,4,4]),
]))
return tbl
def info_box(text, bg=ACCENT, border_color=STEEL):
tbl = Table([[Paragraph(text, body_style)]], colWidths=[17.0*cm])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("BOX", (0,0), (-1,-1), 1, border_color),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
]))
return tbl
def alert_box(text, bg=RED_BG, border_color=RED_DARK):
tbl = Table([[Paragraph(text, alert_style)]], colWidths=[17.0*cm])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("BOX", (0,0), (-1,-1), 1.5, border_color),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
]))
return tbl
def green_box(text, bg=GREEN_BG, border_color=GREEN):
tbl = Table([[Paragraph(text, highlight_style)]], colWidths=[17.0*cm])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("BOX", (0,0), (-1,-1), 1.5, border_color),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
]))
return tbl
def amber_box(text, bg=AMBER_BG, border_color=AMBER):
tbl = Table([[Paragraph(text, body_bold)]], colWidths=[17.0*cm])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("BOX", (0,0), (-1,-1), 1.5, border_color),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
]))
return tbl
def two_col_table(data, col_headers=None, col_widths=None):
"""Styled 2-column table."""
if col_widths is None:
col_widths = [6*cm, 11*cm]
rows = []
if col_headers:
rows.append([Paragraph(f"<b>{col_headers[0]}</b>", body_bold),
Paragraph(f"<b>{col_headers[1]}</b>", body_bold)])
for k, v in data:
rows.append([Paragraph(k, body_bold), Paragraph(v, body_style)])
tbl = Table(rows, colWidths=col_widths)
style = [
("BACKGROUND", (0,0), (-1,0), ACCENT),
("GRID", (0,0), (-1,-1), 0.5, LGREY),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
]
if col_headers:
style += [
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
]
tbl.setStyle(TableStyle(style))
return tbl
def labresult_table(data, col_headers, col_widths=None):
"""Lab results table."""
if col_widths is None:
col_widths = [5.5*cm, 3*cm, 3.5*cm, 5*cm]
rows = [[Paragraph(f"<b>{h}</b>", body_bold) for h in col_headers]]
for row in data:
rows.append([Paragraph(str(c), body_style) for c in row])
tbl = Table(rows, colWidths=col_widths)
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("GRID", (0,0), (-1,-1), 0.5, LGREY),
("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, ACCENT]),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
return tbl
def scoring_table(title_text, rows_data, col_widths=None):
if col_widths is None:
col_widths = [5*cm, 3.5*cm, 3.5*cm, 5*cm]
header = [Paragraph(f"<b>{h}</b>", body_bold) for h in rows_data[0]]
body_rows = [[Paragraph(str(c), body_style) for c in r] for r in rows_data[1:]]
all_rows = [header] + body_rows
tbl = Table(all_rows, colWidths=col_widths)
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), STEEL),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("GRID", (0,0), (-1,-1), 0.5, LGREY),
("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, ACCENT]),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
return tbl
def bp(text):
return Paragraph(f"• {text}", bullet_style)
def p(text):
return Paragraph(text, body_style)
def pb(text):
return Paragraph(f"<b>{text}</b>", body_bold)
def ss(text):
return Paragraph(text, subsection_style)
def sp(n=4):
return Spacer(1, n*mm)
def hr():
return HRFlowable(width="100%", thickness=0.5, color=LGREY, spaceAfter=4, spaceBefore=4)
# ══════════════════════════════════════════════════════════════════════════════
# CONTENT BUILDER
# ══════════════════════════════════════════════════════════════════════════════
def build_story():
story = []
# ── TITLE PAGE ────────────────────────────────────────────────────────────
# Title block (navy background via table)
title_tbl = Table(
[[Paragraph("CHRONIC LIVER DISEASE", title_style)],
[Paragraph("Full Worked-Up Clinical Case Presentation", subtitle_style)],
[Paragraph("For Residents & Junior Doctors", subtitle_style)]],
colWidths=[17*cm]
)
title_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("TOPPADDING", (0,0), (-1,-1), 14),
("BOTTOMPADDING", (0,0), (-1,-1), 14),
("LEFTPADDING", (0,0), (-1,-1), 14),
("RIGHTPADDING", (0,0), (-1,-1), 14),
]))
story.append(sp(8))
story.append(title_tbl)
story.append(sp(6))
meta = [
["Prepared for:", "Residents and Junior Doctors"],
["Topic:", "Chronic Liver Disease - Full Clinical Case with Differentials"],
["Date:", "June 2026"],
["Sources:", "Harrison's 22E · Sleisenger & Fordtran · Goldman-Cecil · StatPearls · AAFP AFP · PubMed"],
]
meta_rows = [[Paragraph(f"<b>{k}</b>", body_bold), Paragraph(v, body_style)] for k,v in meta]
meta_tbl = Table(meta_rows, colWidths=[3.5*cm, 13.5*cm])
meta_tbl.setStyle(TableStyle([
("GRID", (0,0), (-1,-1), 0.5, LGREY),
("BACKGROUND", (0,0), (-1,-1), ACCENT),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(meta_tbl)
story.append(sp(6))
story.append(info_box(
"<b>Learning Objectives:</b> After working through this case, the reader should be able to "
"(1) take a targeted history and perform a focused examination in CLD; "
"(2) construct a prioritised differential diagnosis; "
"(3) interpret relevant investigations including non-invasive fibrosis scores, Child-Pugh and MELD 3.0 scoring; "
"(4) outline evidence-based management of complications including varices, ascites, SBP and hepatic encephalopathy; "
"and (5) know the indications for liver transplant referral."
))
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────
# SECTION 1: CASE PRESENTATION
# ─────────────────────────────────────────────────────────────────────────
story.append(section_header("SECTION 1 — CASE PRESENTATION"))
story.append(sp(4))
story.append(ss("1.1 Patient Demographics"))
demo_data = [
("Name", "Mr. Arjun Mehta (fictional)"),
("Age", "52 years"),
("Sex", "Male"),
("Occupation", "Former accountant (retired early due to ill health)"),
("Presenting to", "General Medicine Ward, tertiary hospital"),
("Referral source", "Emergency Department via GP"),
]
story.append(two_col_table(demo_data, col_widths=[4*cm, 13*cm]))
story.append(sp(5))
story.append(ss("1.2 Chief Complaint"))
story.append(info_box(
'<b>"I have had a swollen abdomen for the past three weeks and my eyes have turned yellow."</b> '
'Duration: 3 weeks (progressive). Background of known alcohol use disorder.'
))
story.append(sp(5))
story.append(ss("1.3 History of Presenting Illness"))
story.append(p(
"Mr. Mehta presents with a 3-week history of progressively worsening abdominal distension associated with "
"bilateral ankle swelling. He reports worsening fatigue, anorexia, and a 6 kg unintentional weight loss over "
"the preceding 2 months, though the abdominal distension itself has increased weight on the scales. "
"He noticed yellowing of his eyes and skin approximately 10 days ago, accompanied by dark ('Coca-Cola') urine "
"and pale stools. He has no haematemesis or melaena at this presentation, though he reports one episode of "
"blood-streaked vomitus approximately 4 months ago that resolved spontaneously."
))
story.append(sp(3))
story.append(p(
"He describes intermittent confusion over the past week - his wife notes he has been sleeping during the day "
"and restless at night, and that he wrote a cheque incorrectly twice last week. He denies fever, rigors or "
"recent travel. He reports aching right upper quadrant discomfort but no acute severe pain."
))
story.append(sp(5))
story.append(ss("1.4 Past Medical History"))
pmh = [
"Alcohol use disorder - drinking approximately 14 standard drinks per day for >20 years (now attempting abstinence x 3 weeks)",
"Type 2 diabetes mellitus - on metformin 1 g twice daily",
"Hypertension - on amlodipine 5 mg daily",
"No prior liver biopsy or formal liver disease diagnosis",
"No known viral hepatitis serology",
]
for item in pmh:
story.append(bp(item))
story.append(sp(5))
story.append(ss("1.5 Drug History & Allergies"))
drug_data = [
("Metformin", "1 g BD — for Type 2 DM (NOTE: review in hepatic impairment — risk of lactic acidosis)"),
("Amlodipine", "5 mg OD — antihypertensive"),
("Thiamine (prescribed today)", "100 mg TDS — Wernicke's prophylaxis given alcohol history"),
("Allergies", "Penicillin (rash)"),
]
story.append(two_col_table(drug_data, col_headers=["Drug / Item", "Detail / Notes"], col_widths=[3.5*cm, 13.5*cm]))
story.append(sp(5))
story.append(ss("1.6 Family & Social History"))
story.append(p("<b>Family History:</b> Father died of liver cancer at age 60 (unknown aetiology). No family history of Wilson's disease or haemochromatosis."))
story.append(p("<b>Social History:</b> Married, two adult children. Previously high-functioning. Stopped driving 1 month ago due to confusion. Non-smoker. No illicit drug use. No tattoos or blood transfusions. Born and raised in India, immigrated 25 years ago — relevant to Hepatitis B/C screening."))
story.append(sp(5))
story.append(ss("1.7 Review of Systems"))
ros = [
("Constitutional", "Fatigue, anorexia, weight loss - YES | Fever - NO"),
("GI", "Jaundice - YES | Abdominal distension - YES | Haematemesis - historical (4/12 ago) | Melaena - NO | Pruritus - mild"),
("Neurological", "Daytime somnolence - YES | Confusion / personality change - YES | Asterixis - to assess on exam"),
("Renal", "Decreased urine output - mild reduction noted over 5 days"),
("Cardiovascular", "Peripheral oedema - YES (bilateral ankles)"),
("Respiratory", "Dyspnoea on exertion - YES (attributed to tense ascites)"),
]
story.append(two_col_table(ros, col_headers=["System", "Findings"], col_widths=[3.5*cm, 13.5*cm]))
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────
# SECTION 2: PHYSICAL EXAMINATION
# ─────────────────────────────────────────────────────────────────────────
story.append(section_header("SECTION 2 — PHYSICAL EXAMINATION"))
story.append(sp(4))
story.append(ss("2.1 Vital Signs"))
vitals_data = [
["Parameter", "Value", "Normal Range", "Interpretation"],
["Temperature", "37.4°C", "36.1–37.2°C", "Low-grade — monitor for SBP"],
["Blood Pressure", "100/65 mmHg", "< 130/80 mmHg", "Hypotension — splanchnic vasodilation"],
["Heart Rate", "96 bpm", "60–100 bpm", "Upper normal — compensatory"],
["Respiratory Rate", "20/min", "12–18/min", "Mildly elevated — ascites restricting diaphragm"],
["O2 Saturation", "94% (room air)", "> 95%", "Mildly reduced — hepatopulmonary syndrome?"],
["BMI", "23.4 kg/m²", "18.5–24.9", "Normal — though muscle wasting present"],
]
story.append(scoring_table("Vital Signs", vitals_data,
col_widths=[3.5*cm, 3*cm, 3.5*cm, 7*cm]))
story.append(sp(5))
story.append(ss("2.2 General Appearance"))
story.append(p(
"Mr. Mehta appears chronically unwell, visibly jaundiced with scleral icterus. He is oriented to person "
"but slow to respond to questions (GCS 14/15, confused on orientation to date). Mild temporal wasting is "
"evident. He is comfortable at rest but breathless when lying flat."
))
story.append(sp(4))
story.append(ss("2.3 Stigmata of Chronic Liver Disease"))
story.append(p("The following features of chronic liver disease were found on systematic examination (per Harrison's 22E, Ch. 357 and AAFP AFP 2019):"))
story.append(sp(3))
stigmata_data = [
["Body Region", "Finding", "Significance"],
["Hands", "Palmar erythema, Dupuytren's contracture, leukonychia (white nails)", "Chronic liver disease markers"],
["Hands", "Asterixis (coarse flap) — POSITIVE on held dorsiflexion", "Hepatic encephalopathy — CRITICAL FINDING"],
["Arms", "Spider naevi (>5 on upper trunk/arms)", "Portal hypertension — oestrogen excess"],
["Eyes", "Scleral icterus, Kayser-Fleischer rings — ABSENT", "Jaundice; absence of KF rings reduces Wilson's likelihood"],
["Face/Mouth", "Parotid enlargement, fetor hepaticus", "Alcohol-related; sulphur compounds from portosystemic shunting"],
["Chest", "Gynaecomastia, sparse chest/axillary hair", "Hormonal imbalance in CLD"],
["Abdomen", "Grossly distended — tense ascites confirmed by shifting dullness and fluid thrill", "Portal hypertension + hypoalbuminaemia"],
["Abdomen", "Caput medusae (dilated periumbilical veins)", "Portal hypertension - portosystemic collaterals"],
["Abdomen", "Liver span 14 cm (percussion) — hepatomegaly", "Hepatomegaly — common in ALD, MASLD, viral hepatitis"],
["Abdomen", "Splenomegaly — tip palpable 4 cm below left costal margin", "Portal hypertension, hypersplenism"],
["Lower Limbs", "Bilateral pitting oedema to mid-shin", "Hypoalbuminaemia + portal hypertension"],
["Skin", "Icterus, scratch marks (pruritus)", "Cholestasis"],
["Testicular", "Testicular atrophy", "Hypogonadism in alcohol-related CLD"],
]
story.append(scoring_table("Physical Examination Findings", stigmata_data,
col_widths=[3*cm, 7*cm, 7*cm]))
story.append(sp(4))
story.append(alert_box(
"CRITICAL FINDING: Asterixis (liver flap) is present. This indicates hepatic encephalopathy "
"and requires urgent assessment with the West Haven Criteria. Precipitating factors "
"(infection, GI bleed, constipation, electrolyte imbalance, medications) must be identified immediately."
))
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────
# SECTION 3: INITIAL DIFFERENTIAL DIAGNOSIS
# ─────────────────────────────────────────────────────────────────────────
story.append(section_header("SECTION 3 — INITIAL DIFFERENTIAL DIAGNOSIS"))
story.append(sp(4))
story.append(info_box(
"At this stage (after history and examination), construct a structured differential diagnosis. "
"The most likely diagnosis is decompensated alcoholic (alcohol-related) cirrhosis, but a systematic "
"approach prevents missed diagnoses. Differentials are grouped by <b>aetiology of the underlying liver disease</b> "
"and by <b>the acute decompensation event</b>."
))
story.append(sp(4))
story.append(ss("3.1 Most Likely Diagnosis"))
story.append(green_box(
"MOST LIKELY: Alcohol-Related Liver Disease (ARLD) — Decompensated Cirrhosis\n"
"Evidence: Long-standing heavy alcohol use (>20 years), stigmata of CLD, ascites, jaundice, "
"encephalopathy, parotid enlargement, spider naevi, gynaecomastia."
))
story.append(sp(5))
story.append(ss("3.2 Structured Differential — Underlying CLD Aetiology"))
diff_data = [
["Diagnosis", "Key Supporting Features", "Against / Points to Consider"],
["Alcohol-Related Liver Disease (ARLD)", "Heavy alcohol use >20 yrs, parotid enlargement, Dupuytren's, gynaecomastia, AST:ALT ratio likely >2", "MOST LIKELY — primary working diagnosis"],
["Metabolic-Associated Steatotic Liver Disease (MASLD/MASH)", "Type 2 DM, hypertension present — metabolic risk factors", "May co-exist with ARLD; born South Asia (higher MASLD prevalence). Exclude or confirm with imaging + biopsy"],
["Chronic Hepatitis B (HBV)", "Born in India (endemic region), no prior serology", "No vaccination history known — serology essential (HBsAg, anti-HBc, HBeAg)"],
["Chronic Hepatitis C (HCV)", "No prior testing, blood exposure history unclear", "Anti-HCV and HCV RNA needed"],
["Autoimmune Hepatitis (AIH)", "Can affect any age/sex; ANA, ASMA, IgG levels", "Less likely with heavy alcohol history but must exclude; EASL 2025 guidelines"],
["Haemochromatosis", "Family history of liver cancer in father; common (~1:250 genetic susceptibility)", "HFE mutation, transferrin saturation, ferritin — exclude; age and sex fit"],
["Wilson's Disease", "Typically adolescents/young adults", "Less likely at age 52; Kayser-Fleischer rings ABSENT; ceruloplasmin, 24h urine copper needed"],
["Primary Biliary Cholangitis (PBC)", "Pruritus present, cholestatic features", "More common in middle-aged women; anti-mitochondrial antibody (AMA) needed"],
["Primary Sclerosing Cholangitis (PSC)", "Usually associated with IBD", "No IBD history — less likely; MRCP if ALP disproportionately elevated"],
["Alpha-1-Antitrypsin Deficiency", "Can present at any age", "Less common; alpha-1-AT level and phenotype if young, no clear aetiology"],
["Drug-Induced Liver Injury (DILI)", "Metformin relatively safe; amlodipine rarely hepatotoxic", "Consider detailed drug timeline — exclude any prior herbal/OTC use"],
]
story.append(scoring_table("Differential Diagnosis — CLD Aetiology", diff_data,
col_widths=[3.5*cm, 6.5*cm, 7*cm]))
story.append(sp(5))
story.append(ss("3.3 Differential — Acute Decompensation Event"))
story.append(p("In established CLD, decompensation is triggered by a specific event. Identifying the trigger determines prognosis and treatment."))
story.append(sp(3))
decomp_data = [
"Spontaneous Bacterial Peritonitis (SBP) — Must ALWAYS exclude in new-onset/worsening ascites (diagnostic paracentesis required)",
"Acute Variceal Haemorrhage — History of haematemesis 4 months ago; endoscopy urgently needed",
"Hepatic Encephalopathy — Present (asterixis, confusion, reversed sleep pattern); identify precipitant",
"Acute Kidney Injury / Hepatorenal Syndrome (HRS) — Decreasing urine output, hypotension — check creatinine trend",
"Alcoholic Hepatitis (superimposed acute component) — Discriminant Function (Maddrey's score) to guide steroid use",
"Hepatocellular Carcinoma (HCC) — Surveillance gap; AFP + triphasic CT/MRI required",
]
for item in decomp_data:
story.append(bp(item))
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────
# SECTION 4: INVESTIGATIONS
# ─────────────────────────────────────────────────────────────────────────
story.append(section_header("SECTION 4 — INVESTIGATIONS"))
story.append(sp(4))
story.append(ss("4.1 Haematology"))
haem_data = [
["Test", "Result", "Reference Range", "Interpretation"],
["Haemoglobin", "9.8 g/dL", "13.5–17.5 g/dL", "Normocytic anaemia — hypersplenism, GI blood loss, nutritional deficiency"],
["MCV", "104 fL", "80–100 fL", "Macrocytosis — alcohol toxicity, folate deficiency (B12/folate needed)"],
["WBC", "3.2 × 10⁹/L", "4.0–11.0 × 10⁹/L", "Leukopenia — hypersplenism; also raises concern for SBP if elevated"],
["Platelets", "68 × 10⁹/L", "150–400 × 10⁹/L", "Thrombocytopenia — portal hypertension, hypersplenism; ↑ bleeding risk"],
["INR", "1.9", "0.8–1.2", "Prolonged — reduced clotting factor synthesis (I, II, V, VII, X)"],
["APTT", "42 seconds", "24–36 sec", "Prolonged — clotting factor deficiency"],
]
story.append(labresult_table(haem_data, haem_data[0], col_widths=[3.5*cm, 2.5*cm, 3.5*cm, 7.5*cm]))
story.append(sp(5))
story.append(ss("4.2 Liver Function Tests & Biochemistry"))
lft_data = [
["Test", "Result", "Reference Range", "Interpretation"],
["Total Bilirubin", "98 µmol/L", "< 17 µmol/L", "Markedly elevated — hepatocellular + cholestatic component"],
["Direct (Conj.) Bilirubin", "72 µmol/L", "< 7 µmol/L", "Predominantly conjugated — hepatocellular dysfunction"],
["ALT", "62 IU/L", "7–56 IU/L", "Mildly elevated — in severe cirrhosis ALT may be near-normal (few hepatocytes left)"],
["AST", "148 IU/L", "10–40 IU/L", "More elevated than ALT — AST:ALT ratio = 2.4 (>2 strongly suggests ALD)"],
["ALP", "210 IU/L", "44–147 IU/L", "Elevated — cholestasis; if markedly elevated consider PBC/PSC"],
["GGT", "380 IU/L", "8–61 IU/L", "Markedly elevated — classic in alcohol use; also correlates with ALD severity"],
["Albumin", "22 g/L", "35–50 g/L", "Severely low — reflects poor synthetic function; contributes to ascites + oedema"],
["Sodium", "128 mmol/L", "135–145 mmol/L", "Hyponatraemia — dilutional; important for MELD-Na and MELD 3.0 calculation"],
["Creatinine", "148 µmol/L", "62–106 µmol/L", "Elevated — AKI/early HRS; monitor trend closely"],
["Urea", "12.4 mmol/L", "2.5–7.8 mmol/L", "Elevated — may reflect GI blood or AKI; low urea also possible in liver failure"],
["Blood Glucose", "4.2 mmol/L", "3.9–5.6 mmol/L", "Low-normal — impaired gluconeogenesis in cirrhosis; monitor closely"],
["Ammonia (venous)", "112 µmol/L", "< 50 µmol/L", "Elevated — supports hepatic encephalopathy diagnosis"],
["Ferritin", "680 µg/L", "12–300 µg/L", "Elevated — acute phase reactant; also consider haemochromatosis (transferrin saturation needed)"],
["Transferrin Saturation", "32%", "< 45%", "Normal — reduces haemochromatosis likelihood"],
]
story.append(labresult_table(lft_data, lft_data[0], col_widths=[3.5*cm, 2.5*cm, 3.5*cm, 7.5*cm]))
story.append(sp(5))
story.append(ss("4.3 Aetiology Workup"))
aet_data = [
["Test", "Result", "Interpretation"],
["HBsAg", "NEGATIVE", "No active Hepatitis B infection"],
["Anti-HBc (total)", "POSITIVE", "Prior HBV exposure — check anti-HBs; if anti-HBc +ve only: occult HBV possible"],
["Anti-HBs", "< 10 mIU/mL", "Not immune — was not vaccinated; discuss vaccination"],
["HCV Ab", "NEGATIVE", "Hepatitis C not detected"],
["ANA", "1:40 (weak positive)", "Non-specific at this titre; repeat if clinically suspected AIH"],
["Anti-SMA (ASMA)", "NEGATIVE", "Against Type 1 Autoimmune Hepatitis"],
["Anti-LKM1", "NEGATIVE", "Against Type 2 Autoimmune Hepatitis"],
["IgG", "18 g/L (mildly elevated)", "Non-specific; >2x ULN would strongly support AIH"],
["AMA (anti-mitochondrial)", "NEGATIVE", "Against Primary Biliary Cholangitis"],
["Ceruloplasmin", "0.22 g/L (low-normal)", "Not diagnostic of Wilson's; needs 24h urine copper if suspicion remains"],
["Alpha-1-Antitrypsin", "1.0 g/L (normal)", "Alpha-1-AT deficiency excluded"],
["AFP (Alpha-fetoprotein)", "48 µg/L (elevated)", "Elevated — HCC surveillance: triphasic CT/MRI urgently required"],
["AUDIT-C score (alcohol)", "12/12", "Severe alcohol use disorder confirmed"],
]
story.append(scoring_table("Aetiology Screen Results", aet_data,
col_widths=[4.5*cm, 3.5*cm, 9*cm]))
story.append(sp(4))
story.append(amber_box(
"NOTE: AST:ALT ratio = 2.4 (>2), GGT markedly elevated, macrocytosis — this triad is highly "
"suggestive of Alcohol-Related Liver Disease (ARLD). The negative viral and autoimmune screen "
"further supports ARLD as the primary aetiology."
))
story.append(PageBreak())
story.append(ss("4.4 Ascitic Fluid Analysis (Diagnostic Paracentesis — MANDATORY)"))
story.append(p("A diagnostic paracentesis is performed in ALL patients with new-onset or worsening ascites to exclude SBP (Sleisenger & Fordtran, Ch. 92; AAFP AFP 2019):"))
story.append(sp(3))
ascites_data = [
["Parameter", "Result", "Interpretation"],
["Appearance", "Straw-coloured, slightly turbid", "Turbidity raises concern for SBP"],
["WBC", "420 cells/µL", "ELEVATED — normal < 500 cells/µL total"],
["PMN (neutrophil count)", "320 cells/µL", "DIAGNOSTIC OF SBP (≥250 PMN/µL)"],
["Total protein", "10 g/L", "Transudate — typical in cirrhosis (< 25 g/L)"],
["Ascitic albumin", "8 g/L", "For SAAG calculation"],
["SAAG (Serum-Ascites Albumin Gradient)", "22 - 8 = 14 g/L (> 11)", "SAAG ≥ 11 g/L — PORTAL HYPERTENSION confirmed as cause of ascites"],
["Ascitic glucose", "3.8 mmol/L", "Normal — near serum level (not diagnostic of bacterial peritonitis yet)"],
["Ascitic LDH", "Normal", "LDH elevation would suggest secondary peritonitis or malignancy"],
["Gram stain", "Negative (does not exclude SBP)", "Culture sent in blood culture bottles at bedside"],
["Culture", "Escherichia coli (result at 48h)", "SBP confirmed — monomicrobial gram-negative organism"],
]
story.append(scoring_table("Ascitic Fluid Analysis", ascites_data,
col_widths=[4.5*cm, 4.5*cm, 8*cm]))
story.append(sp(4))
story.append(alert_box(
"DIAGNOSIS: SPONTANEOUS BACTERIAL PERITONITIS (SBP) — PMN count ≥ 250 cells/µL. "
"This is a life-threatening emergency. Empirical antibiotics must be started IMMEDIATELY "
"(before culture results). Start IV Cefotaxime 2g Q8H (or Piperacillin-Tazobactam if penicillin allergy). "
"Co-administer IV Albumin 1.5 g/kg at diagnosis and 1 g/kg at Day 3 to reduce risk of Hepatorenal Syndrome "
"(evidence: Sort et al. NEJM 1999; supported in Sleisenger & Fordtran guidelines)."
))
story.append(sp(5))
story.append(ss("4.5 Imaging Studies"))
imaging_data = [
("Abdominal Ultrasound (US)", "Liver: coarsened echotexture, nodular surface consistent with cirrhosis. No focal lesion > 1 cm identified on US alone. Ascites: large volume. Portal vein diameter 15 mm (dilated — normal < 13 mm). Spleen 16 cm (splenomegaly). Kidneys: no hydronephrosis."),
("CT Abdomen (Triphasic — for AFP elevation)", "Liver: cirrhotic morphology with caudate lobe hypertrophy. One 2.1 cm arterially enhancing lesion with portal venous washout in segment VI — HIGHLY SUSPICIOUS FOR HCC (LI-RADS 5). No extrahepatic metastases. Ascites confirmed. Patent portal and hepatic veins."),
("Upper GI Endoscopy (OGD)", "Large oesophageal varices (Grade III per Paquet classification) with red wale markings. No active bleeding. Mild portal hypertensive gastropathy. Gastric varices absent. Endoscopic band ligation (EBL) performed as secondary prophylaxis."),
("Transient Elastography (FibroScan)", "Not performed at this admission due to tense ascites (result unreliable). Plan for post-paracentesis assessment or MRE."),
("ECG", "Sinus tachycardia. Prolonged QTc (460 ms) — common in cirrhosis (cirrhotic cardiomyopathy)."),
]
story.append(two_col_table(imaging_data, col_headers=["Investigation", "Findings"], col_widths=[4*cm, 13*cm]))
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────
# SECTION 5: DISEASE SCORING & STAGING
# ─────────────────────────────────────────────────────────────────────────
story.append(section_header("SECTION 5 — DISEASE SEVERITY SCORING & STAGING"))
story.append(sp(4))
story.append(info_box(
"Several validated scoring systems are used in chronic liver disease. The two most important are "
"<b>Child-Pugh</b> (clinical + biochemical) and <b>MELD / MELD 3.0</b> (biochemical; used for "
"transplant prioritisation). Both are calculated for this patient. A newer update, "
"<b>MELD 3.0</b>, was validated in 2024 and adds patient sex and albumin to better predict "
"90-day mortality and reduce sex-based disparity in organ allocation "
"(Mazumder & Fontana, Ann Rev Med 2024, PMID 37751367)."
))
story.append(sp(5))
story.append(ss("5.1 Child-Pugh Score"))
cp_data = [
["Parameter", "1 Point", "2 Points", "3 Points", "Patient's Score"],
["Bilirubin (µmol/L)", "< 34", "34–51", "> 51", "3 — (Total bili 98 µmol/L)"],
["Albumin (g/L)", "> 35", "28–35", "< 28", "3 — (Albumin 22 g/L)"],
["INR", "< 1.7", "1.7–2.3", "> 2.3", "2 — (INR 1.9)"],
["Ascites", "None", "Mild/Moderate", "Tense/Refractory", "3 — (Tense ascites)"],
["Encephalopathy", "None", "Grade I–II", "Grade III–IV", "2 — (Grade II clinically)"],
["TOTAL", "", "", "", "13 / 15 = Child-Pugh Class C"],
]
story.append(scoring_table("Child-Pugh Scoring", cp_data,
col_widths=[3.5*cm, 2.5*cm, 3*cm, 2.5*cm, 5.5*cm]))
story.append(sp(3))
story.append(alert_box(
"Child-Pugh Class C (Score 13/15): Predicted 1-year survival ~45%, 2-year survival ~35%. "
"Mean survival is approximately 6 months if score ≥ 12 (StatPearls, NCBI). "
"This patient requires urgent consideration for liver transplant listing."
))
story.append(sp(5))
story.append(ss("5.2 MELD 3.0 Score"))
story.append(p("<b>MELD 3.0 Formula</b> (Mazumder & Fontana, Ann Rev Med 2024, PMID 37751367):"))
story.append(sp(2))
story.append(info_box(
"MELD 3.0 = 4.56 × ln(Bilirubin mg/dL) + 0.82 × (137 − Sodium) − 0.24 × (137 − Sodium) × ln(Bilirubin mg/dL) "
"+ 9.09 × ln(INR) + 11.14 × ln(Creatinine mg/dL) + 1.85 × (3.5 − Albumin g/dL) "
"+ 1.83 × (if female) + 7\n\n"
"Patient Values: Bilirubin = 5.7 mg/dL | Na = 128 mmol/L | INR = 1.9 | Creatinine = 1.7 mg/dL | "
"Albumin = 2.2 g/dL | Sex: Male (0 points)\n\n"
"Estimated MELD 3.0 ≈ 28 (range calculation; exact score requires validated calculator)\n\n"
"MELD 3.0 > 21 = Poor prognosis; high-priority transplant listing. "
"MELD-Na alone was previously used for waitlist prioritisation in the US; MELD 3.0 "
"now replaces this at UNOS-affiliated centres (2022 onwards) and includes albumin + sex."
))
story.append(sp(4))
story.append(ss("5.3 Hepatic Encephalopathy Grading (West Haven Criteria)"))
he_data = [
["Grade", "Clinical Features", "This Patient"],
["Grade 0 (Minimal/Covert)", "Subtle psychometric changes; normal examination", "No"],
["Grade I", "Mild confusion, anxiety, short attention span, reversed sleep-wake cycle", "Partial features"],
["Grade II (current)", "Obvious confusion, drowsiness, asterixis, slurred speech, disorientation", "YES — asterixis, daytime drowsiness, confusion re: date"],
["Grade III", "Somnolent but rousable; major disorientation; bizarre behaviour", "Not yet"],
["Grade IV (Coma)", "Unresponsive to verbal stimuli; coma", "Not yet"],
]
story.append(scoring_table("West Haven Grading of Hepatic Encephalopathy", he_data,
col_widths=[2.5*cm, 8*cm, 6.5*cm]))
story.append(sp(3))
story.append(p("<b>Precipitating factors to identify in this patient:</b>"))
he_precip = [
"SBP (CONFIRMED — treat urgently)",
"GI bleeding (historical episode — check for acute re-bleed; check haemoglobin trend)",
"Constipation — assess bowel movements",
"Medications — benzodiazepines, opiates (avoid in CLD); review drug chart",
"Electrolyte imbalance — hyponatraemia (Na 128), hypokalaemia (check K+)",
"Dehydration — check urine output, urea:creatinine ratio",
"Excessive dietary protein — unlikely cause but assess",
]
for item in he_precip:
story.append(bp(item))
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────
# SECTION 6: FINAL DIAGNOSES
# ─────────────────────────────────────────────────────────────────────────
story.append(section_header("SECTION 6 — FINAL DIAGNOSES"))
story.append(sp(4))
story.append(green_box(
"PRIMARY DIAGNOSIS:\n"
"Alcohol-Related Liver Disease (ARLD) — Decompensated Cirrhosis (Child-Pugh Class C; MELD 3.0 ~28)"
))
story.append(sp(4))
story.append(amber_box(
"ACTIVE COMPLICATIONS (requiring simultaneous treatment):\n"
"1. Spontaneous Bacterial Peritonitis (SBP) — PMN ≥ 250/µL, E. coli on culture\n"
"2. Hepatic Encephalopathy — Grade II (West Haven); precipitated by SBP\n"
"3. Acute Kidney Injury (AKI) — Creatinine 148 µmol/L; risk of progression to HRS\n"
"4. Large Oesophageal Varices (Grade III) — EBL performed; no active bleed\n"
"5. Tense Ascites — portal hypertension + hypoalbuminaemia\n"
"6. Suspected Hepatocellular Carcinoma (HCC) — LI-RADS 5 lesion on CT (2.1 cm, seg VI)\n"
"7. Hyponatraemia (Na 128 mmol/L) — dilutional\n"
"8. Prior HBV Exposure (anti-HBc positive; not immune) — vaccination needed"
))
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────
# SECTION 7: MANAGEMENT
# ─────────────────────────────────────────────────────────────────────────
story.append(section_header("SECTION 7 — EVIDENCE-BASED MANAGEMENT"))
story.append(sp(4))
story.append(info_box(
"Management follows a multidisciplinary approach targeting: (1) underlying cause correction, "
"(2) portal hypertension management, (3) complication-specific treatment, and (4) "
"liver transplant evaluation. All interventions below are evidence-based per Harrison's 22E (2025), "
"Sleisenger & Fordtran, Goldman-Cecil Medicine, StatPearls (NCBI NBK554597), and AAFP AFP 2019."
))
story.append(sp(5))
story.append(ss("7.1 Immediate / Emergency Management (First 24 Hours)"))
immediate = [
"<b>IV Access + Resuscitation:</b> Two large-bore IVs. IV fluid resuscitation with caution (avoid saline overload — worsens ascites/oedema); prefer 5% dextrose if hypoglycaemic. Monitor urine output hourly. Insert urinary catheter.",
"<b>SBP Treatment:</b> IV Cefotaxime 2g Q8H (first-line, IV, x 5 days minimum); if penicillin allergy (this patient has PCN rash) — use IV Ciprofloxacin 400mg Q12H or discuss with Microbiology. Simultaneously administer IV Human Albumin 1.5 g/kg on Day 1 and 1 g/kg on Day 3 to prevent hepatorenal syndrome (reduces AKI risk by ~40% — NEJM 1999, confirmed in multiple subsequent trials).",
"<b>Hepatic Encephalopathy:</b> Lactulose 20–30 mL orally Q6H (titrate to 2–3 soft bowel motions/day) — reduces intestinal ammonia absorption. Add Rifaximin 550 mg BD for secondary prevention (reduces HE recurrence, Goldman-Cecil; Miller's Anesthesia 10E). Hold nephrotoxic drugs. Correct precipitants (SBP being treated). Review and withhold any benzodiazepines or opiates.",
"<b>AKI Management:</b> Stop metformin immediately (risk of lactic acidosis in AKI + hepatic failure). Stop NSAIDs. Withhold ACE inhibitors/ARBs. Target urine output > 0.5 mL/kg/hr. If creatinine does not improve with treatment of SBP and fluid optimisation within 48h — suspect Hepatorenal Syndrome Type 1 (acute) and commence Terlipressin 1–2 mg IV Q4–6H + Albumin (EASL/AASLD recommendation).",
"<b>Thiamine (Vitamin B1):</b> 100–200 mg IV/IM TDS BEFORE any dextrose — prevents Wernicke's encephalopathy (routine in all alcohol-use disorder patients; note: never give dextrose first in alcohol history).",
"<b>Hyponatraemia:</b> Na 128 mmol/L — likely dilutional. Fluid restrict to 1–1.5 L/day. Do NOT correct rapidly (risk of central pontine myelinolysis). Avoid saline except in severe symptomatic hyponatraemia (Na < 120 + seizures). Reassess after paracentesis and SBP treatment.",
"<b>Nutritional Support:</b> Dietitian referral urgently. High-energy, high-protein diet (1.2–1.5 g protein/kg/day — do NOT restrict protein; old practice, no longer recommended). Small, frequent meals including a late evening snack to prevent overnight fasting-induced catabolism.",
]
for item in immediate:
story.append(bp(item))
story.append(sp(5))
story.append(ss("7.2 Ascites Management"))
ascites_mgmt = [
"<b>Therapeutic Paracentesis:</b> For tense ascites — large-volume paracentesis (LVP) of 5–10 L with simultaneous albumin infusion (8 g/L of ascites removed) to prevent paracentesis-induced circulatory dysfunction (PICD).",
"<b>Diuretics (after acute phase):</b> Spironolactone 100 mg OD (first-line; anti-aldosterone) + Furosemide 40 mg OD. Typical target ratio 100:40 to maintain normonatraemia. Titrate every 3–5 days. Monitor electrolytes, creatinine, weight (aim for ≤0.5 kg/day loss if no peripheral oedema; ≤1 kg/day if oedema present).",
"<b>Sodium restriction:</b> < 2 g sodium/day (88 mmol/day).",
"<b>TIPS (transjugular intrahepatic portosystemic shunt):</b> Consider for refractory ascites (failed maximum diuretics) or as early TIPS in selected patients with first-variceal bleed and high HVPG. Contraindicated in severe encephalopathy.",
"<b>SBP Prophylaxis (secondary):</b> Norfloxacin 400 mg OD (where available) OR Ciprofloxacin 500 mg OD long-term after first SBP episode — ALL patients with prior SBP should receive secondary prophylaxis (AAFP AFP 2019). Also indicated as primary prophylaxis if ascitic protein < 15 g/L + CPS ≥ 9 or bilirubin ≥ 51 µmol/L.",
]
for item in ascites_mgmt:
story.append(bp(item))
story.append(sp(5))
story.append(ss("7.3 Variceal Management"))
variceal_mgmt = [
"<b>Primary Prophylaxis (previously NOT on beta-blocker):</b> Non-selective beta-blocker (NSBB) — Propranolol 20–40 mg BD or Carvedilol 6.25 mg BD (Baveno VII recommendation; Mendizabal et al. Ann Hepatol 2024, PMID 37984701). Target reduction in HVPG to < 12 mmHg or ≥ 20% reduction. Alternatively: Endoscopic Band Ligation (EBL) every 2–4 weeks until eradication.",
"<b>Active Variceal Haemorrhage Protocol (not active now, but critical to know):</b> IV Terlipressin 2 mg Q4H (or Octreotide/Somatostatin) + IV Ceftriaxone 1g OD for 5 days + Urgent OGD with EBL/sclerotherapy within 12h of presentation. Early TIPS (< 72h) in Child-Pugh B/C patients with poor response.",
"<b>Secondary Prophylaxis (this patient had Grade III varices with EBL today):</b> NSBB (propranolol or carvedilol) + repeat EBL every 2–4 weeks until variceal eradication.",
"<b>Ongoing surveillance:</b> Repeat OGD in 6 months if no varices after treatment; annually if small varices persist.",
]
for item in variceal_mgmt:
story.append(bp(item))
story.append(sp(5))
story.append(ss("7.4 HCC Management — Suspected LI-RADS 5 Lesion"))
hcc_mgmt = [
"Hepatology + Oncology + Radiology MDT (multidisciplinary team) meeting urgently.",
"Confirm with MRI liver (gadoxetate contrast preferred) if CT inconclusive.",
"Barcelona Clinic Liver Cancer (BCLC) Staging: assess functional status (ECOG PS), lesion number/size, vascular invasion.",
"Child-Pugh Class C — potentially excluded from resection/ablation. Liver transplant may be primary treatment option if within Milan Criteria (1 lesion ≤ 5 cm OR ≤ 3 lesions, all ≤ 3 cm; no vascular invasion; no extrahepatic spread).",
"If transplant not immediately available and patient is optimised: bridge therapy (TACE, RFA, SBRT) may be considered per MDT recommendation.",
"SBP and encephalopathy must be controlled first before any oncological intervention.",
]
for item in hcc_mgmt:
story.append(bp(item))
story.append(sp(5))
story.append(ss("7.5 Underlying Disease — Alcohol Abstinence & Long-term Management"))
alcohol_mgmt = [
"<b>Alcohol Abstinence (ESSENTIAL):</b> The most important intervention in ARLD — even decompensated patients can improve with abstinence. Refer to addiction psychiatry/alcohol liaison team.",
"<b>Alcoholic Hepatitis (if Maddrey's DF ≥ 32):</b> Maddrey's Discriminant Function = 4.6 × (PT − control) + serum bilirubin (mg/dL). If ≥ 32 AND no infection: Prednisolone 40 mg OD × 28 days. This patient has active SBP — steroids are CONTRAINDICATED until infection is controlled.",
"<b>Hepatitis B vaccination:</b> Anti-HBc positive but non-immune — vaccinate.",
"<b>HCC surveillance:</b> Six-monthly liver ultrasound ± AFP in all patients with cirrhosis regardless of aetiology.",
"<b>Bone density (DEXA scan):</b> Osteoporosis is common in CLD — screen at diagnosis. Vitamin D and calcium supplementation.",
"<b>Medication review:</b> Metformin — HOLD in AKI and severe hepatic impairment. Reassess when renal function and CLD status stabilise. Amlodipine can be continued cautiously.",
"<b>Vaccinations:</b> HAV (Hepatitis A), HBV, Influenza, Pneumococcus, COVID-19.",
]
for item in alcohol_mgmt:
story.append(bp(item))
story.append(PageBreak())
story.append(ss("7.6 Liver Transplant Evaluation"))
story.append(p(
"Liver transplantation is the only definitive treatment for end-stage liver disease. This patient "
"has Child-Pugh Class C cirrhosis with MELD 3.0 ~28, SBP, HE Grade II, AKI, suspected HCC, "
"and large varices. Transplant team referral is appropriate. Key considerations:"
))
transplant_data = [
"MELD 3.0 ≥ 15 — standard threshold for transplant listing in most centres",
"Alcohol abstinence: Minimum 6 months abstinence required by most programmes (some flexibility if prognosis is dire)",
"HCC Milan Criteria: 2.1 cm lesion in Segment VI — within Milan Criteria, TACE bridge therapy possible while awaiting transplant",
"SBP/HE must be controlled pre-transplant",
"Psychosocial evaluation, social support assessment, addiction counselling — mandatory",
"Renal function: AKI must be addressed; if HRS persists, simultaneous liver-kidney transplant may be required",
]
for item in transplant_data:
story.append(bp(item))
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────
# SECTION 8: CLINICAL REASONING SUMMARY
# ─────────────────────────────────────────────────────────────────────────
story.append(section_header("SECTION 8 — CLINICAL REASONING & LEARNING POINTS"))
story.append(sp(4))
story.append(ss("8.1 Diagnostic Reasoning Summary"))
reasoning_steps = [
("Step 1 — Pattern Recognition", "Jaundice + ascites + encephalopathy + stigmata of CLD + heavy alcohol history = decompensated cirrhosis until proven otherwise."),
("Step 2 — Aetiology Workup", "AST:ALT > 2, GGT markedly elevated, macrocytosis, alcohol history → ARLD primary. Viral hepatitis, autoimmune, metabolic causes systematically excluded."),
("Step 3 — Complication Identification", "PMN ≥ 250 in ascites → SBP. Asterixis + elevated ammonia → HE Grade II (precipitated by SBP). Creatinine rising → AKI/pre-HRS. CT 2.1cm enhancing lesion → HCC suspicious."),
("Step 4 — Severity Staging", "Child-Pugh Class C (13/15). MELD 3.0 ~28. West Haven HE Grade II. SAAG ≥ 11 confirms portal hypertension."),
("Step 5 — Management Prioritisation", "Simultaneous management: (1) Treat SBP urgently. (2) Correct HE precipitants. (3) Protect kidneys (hold nephrotoxins, albumin). (4) EBL for varices. (5) Refer transplant team. (6) MDT for HCC."),
]
story.append(two_col_table(reasoning_steps, col_headers=["Clinical Step", "Reasoning Applied"], col_widths=[4.5*cm, 12.5*cm]))
story.append(sp(5))
story.append(ss("8.2 Key Learning Points for Residents"))
learning_points = [
"<b>Diagnostic Paracentesis is MANDATORY</b> in all patients with new or worsening ascites — SBP can be clinically silent. Threshold for diagnosis is PMN ≥ 250 cells/µL (not total WBC).",
"<b>Albumin infusion with SBP treatment</b> reduces the risk of hepatorenal syndrome by ~40% — do not omit this.",
"<b>AST:ALT ratio > 2</b> with elevated GGT and macrocytosis is a highly specific pattern for alcohol-related liver disease.",
"<b>Never restrict protein</b> in cirrhosis with encephalopathy — this is outdated practice. High-protein diet (1.2–1.5 g/kg/day) with late-night snack is recommended.",
"<b>MELD 3.0</b> has replaced MELD-Na for transplant allocation in the US (2022). It includes sex and albumin to address female sex disparity in organ allocation.",
"<b>Metformin must be stopped</b> in AKI and severe hepatic impairment — lactic acidosis risk.",
"<b>Steroids are contraindicated in alcoholic hepatitis if active infection is present</b> — treat SBP first.",
"<b>Terlipressin + Albumin</b> is the preferred treatment for Hepatorenal Syndrome Type 1 (acute HRS) — vasopressin analogue reduces splanchnic vasodilation.",
"<b>NSBB (propranolol/carvedilol)</b> are first-line for primary and secondary variceal prophylaxis — Baveno VII (2022) confirms carvedilol as preferred where tolerated.",
"<b>Six-monthly surveillance ultrasound ± AFP</b> should be performed in ALL patients with cirrhosis for HCC detection regardless of aetiology.",
"<b>Kayser-Fleischer rings absent + age 52 + normal ceruloplasmin</b> — Wilson's disease effectively excluded, but 24h urine copper if any doubt.",
"<b>Alcohol abstinence remains the single most powerful modifier of prognosis</b> in ARLD — even Child-Pugh C patients can improve significantly with 6 months of abstinence.",
]
for i, point in enumerate(learning_points, 1):
story.append(Paragraph(f"<b>{i}.</b> {point}", bullet_style))
story.append(sp(2))
story.append(PageBreak())
# ─────────────────────────────────────────────────────────────────────────
# SECTION 9: REFERENCES
# ─────────────────────────────────────────────────────────────────────────
story.append(section_header("SECTION 9 — REFERENCES & SOURCES"))
story.append(sp(4))
refs = [
("Textbooks", [
"Harrison's Principles of Internal Medicine, 22nd Edition (2025). McGraw Hill. Chapters 357 (Cirrhosis), 358 (Portal Hypertension).",
"Sleisenger and Fordtran's Gastrointestinal and Liver Disease, 11th Edition. Chapters 86 (Alcohol-Associated Liver Disease), 92 (Portal Hypertension & Varices).",
"Goldman-Cecil Medicine, International Edition. Chapter: Hepatic Encephalopathy.",
"Miller's Anesthesia, 2-Volume Set, 10th Edition. Chapter: Cirrhosis and Portal Hypertension.",
"The Washington Manual of Medical Therapeutics. Chapter: Hepatic Disorders.",
]),
("Journal Articles & Guidelines", [
"Mazumder NR, Fontana RJ. MELD 3.0 in Advanced Chronic Liver Disease. Annu Rev Med. 2024 Jan 29;75:PMID 37751367. DOI 10.1146/annurev-med-051322-122539.",
"Mendizabal M, Cancado GGL, Albillos A. Evolving portal hypertension through Baveno VII recommendations. Ann Hepatol. 2024 Jan-Feb. PMID 37984701.",
"European Association for the Study of the Liver (EASL). EASL Clinical Practice Guidelines on the management of autoimmune hepatitis. J Hepatol. 2025 Aug. PMID 40348684.",
"Juanola A, Ma AT, de Wit K et al. Novel prognostic biomarkers in decompensated cirrhosis: a systematic review and meta-analysis. Gut. 2023 Dec 7. PMID 37884354.",
"Tilg H, Petta S, Stefan N. Metabolic Dysfunction-Associated Steatotic Liver Disease in Adults: A Review. JAMA. 2026 Jan 13. PMID 41212550.",
]),
("Online / Open-Access Sources", [
"StatPearls — Chronic Liver Disease. NBK554597. NCBI Bookshelf (NIH). Continuously updated. Available: https://www.ncbi.nlm.nih.gov/books/NBK554597",
"AAFP American Family Physician — Cirrhosis: Diagnosis and Management. AFP 2019;100(12):759–770. Available: https://www.aafp.org/afp/2019/1215/p759",
"EASL Clinical Practice Guidelines Archive. Available: https://easl.eu/publication-category/clinical-practice-guidelines",
"Korean Association for the Study of the Liver (KASL) — 2024 Noninvasive Tests in Chronic Liver Disease Guidelines. Available: https://www.kasl.org/eng/guidelines/file/2024_noninvasive%20tests.pdf",
]),
]
for section_title, ref_list in refs:
story.append(pb(section_title))
for i, ref in enumerate(ref_list, 1):
story.append(Paragraph(f"{i}. {ref}", ref_style))
story.append(sp(2))
story.append(sp(4))
story.append(hr())
story.append(sp(3))
story.append(Paragraph(
"<i>This case presentation was compiled by Orris using content from verified medical textbooks "
"(Harrison's, Sleisenger & Fordtran, Goldman-Cecil, Miller's Anesthesia, Washington Manual) and "
"peer-reviewed sources (PubMed, StatPearls, AAFP). The patient described is fictional. "
"This document is for educational purposes only and does not constitute clinical advice. "
"Always consult current institutional guidelines and senior clinical supervision for patient management.</i>",
caption_style
))
return story
# ── MAIN ─────────────────────────────────────────────────────────────────────
if __name__ == "__main__":
doc = make_doc(OUTPUT)
story = build_story()
doc.build(story, onFirstPage=header_footer, onLaterPages=header_footer)
print(f"PDF saved to: {OUTPUT}")
import os
size = os.path.getsize(OUTPUT)
print(f"File size: {size:,} bytes ({size/1024:.1f} KB)")