~/pathology_pdf/generate_pdf.py
#!/usr/bin/env python3
"""
Generate a Q&A PDF from Pathology Charts Part 1 & Part 2
"""
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.lib import colors
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.platypus import ListFlowable, ListItem
# ── Output path ──────────────────────────────────────────────────────────────
OUTPUT = "/tmp/workspace/pathology_pdf/Pathology_Charts_QA.pdf"
# ── Document setup ───────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
rightMargin=2*cm, leftMargin=2*cm,
topMargin=2.5*cm, bottomMargin=2*cm,
title="Pathology Charts – Q&A Study Guide",
author="Dr. Smrutirekha Behera"
)
# ── Colour palette ───────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1B2A4A")
TEAL = colors.HexColor("#0B6E7A")
PURPLE = colors.HexColor("#6B2D8B")
GOLD = colors.HexColor("#C8890A")
LIGHT_BLUE = colors.HexColor("#E8F4F8")
LIGHT_GREEN= colors.HexColor("#E8F5E9")
LIGHT_YELLOW = colors.HexColor("#FFFDE7")
LIGHT_RED = colors.HexColor("#FFEBEE")
WHITE = colors.white
GRAY1 = colors.HexColor("#F5F5F5")
GRAY2 = colors.HexColor("#EEEEEE")
# ── Styles ───────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()
cover_title = ParagraphStyle("cover_title",
parent=styles["Title"],
fontSize=28, textColor=NAVY, spaceAfter=10,
alignment=TA_CENTER, fontName="Helvetica-Bold")
cover_sub = ParagraphStyle("cover_sub",
parent=styles["Normal"],
fontSize=14, textColor=TEAL, spaceAfter=6,
alignment=TA_CENTER, fontName="Helvetica-Bold")
cover_author = ParagraphStyle("cover_author",
parent=styles["Normal"],
fontSize=12, textColor=PURPLE, spaceAfter=4,
alignment=TA_CENTER, fontName="Helvetica-Oblique")
part_header = ParagraphStyle("part_header",
parent=styles["Heading1"],
fontSize=18, textColor=WHITE, spaceAfter=8, spaceBefore=16,
fontName="Helvetica-Bold", alignment=TA_CENTER,
backColor=NAVY, borderPad=8)
section_header = ParagraphStyle("section_header",
parent=styles["Heading2"],
fontSize=13, textColor=WHITE, spaceAfter=6, spaceBefore=12,
fontName="Helvetica-Bold",
backColor=TEAL, borderPad=6)
case_title = ParagraphStyle("case_title",
parent=styles["Heading3"],
fontSize=12, textColor=NAVY, spaceAfter=4, spaceBefore=10,
fontName="Helvetica-Bold", borderPad=4,
backColor=LIGHT_BLUE)
q_style = ParagraphStyle("q_style",
parent=styles["Normal"],
fontSize=11, textColor=PURPLE, spaceBefore=8, spaceAfter=4,
fontName="Helvetica-Bold", leftIndent=4)
a_style = ParagraphStyle("a_style",
parent=styles["Normal"],
fontSize=10.5, textColor=colors.black, spaceAfter=4,
fontName="Helvetica", leftIndent=8, leading=15)
bullet_style = ParagraphStyle("bullet_style",
parent=styles["Normal"],
fontSize=10, textColor=colors.black, spaceAfter=2,
fontName="Helvetica", leftIndent=20, leading=14)
key_style = ParagraphStyle("key_style",
parent=styles["Normal"],
fontSize=10, textColor=colors.HexColor("#B71C1C"), spaceAfter=2,
fontName="Helvetica-Bold", leftIndent=8, leading=14)
diag_style = ParagraphStyle("diag_style",
parent=styles["Normal"],
fontSize=11, textColor=WHITE, spaceAfter=6, spaceBefore=4,
fontName="Helvetica-Bold", leftIndent=8,
backColor=PURPLE, borderPad=5)
normal_sm = ParagraphStyle("normal_sm",
parent=styles["Normal"],
fontSize=10, textColor=colors.black, spaceAfter=3,
fontName="Helvetica", leftIndent=8, leading=14)
table_header_style = ParagraphStyle("table_header_style",
parent=styles["Normal"],
fontSize=9, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER)
table_cell_style = ParagraphStyle("table_cell_style",
parent=styles["Normal"],
fontSize=9, textColor=colors.black, fontName="Helvetica",
alignment=TA_CENTER)
def P(text, style): return Paragraph(text, style)
def B(): return Spacer(1, 6)
def BB(): return Spacer(1, 12)
def HR(): return HRFlowable(width="100%", thickness=1, color=TEAL, spaceAfter=6, spaceBefore=4)
def make_table(headers, rows, col_widths=None):
"""Helper to create a styled table."""
header_row = [Paragraph(h, ParagraphStyle("th", parent=styles["Normal"],
fontSize=9, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER)) for h in headers]
data = [header_row]
for row in rows:
data.append([Paragraph(str(c), ParagraphStyle("td", parent=styles["Normal"],
fontSize=9, textColor=colors.black, fontName="Helvetica",
alignment=TA_CENTER)) for c in row])
if col_widths is None:
col_widths = [doc.width / len(headers)] * len(headers)
t = Table(data, colWidths=col_widths)
ts = TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9),
("ROWBACKGROUNDS", (0,1), (-1,-1), [GRAY1, WHITE]),
("GRID", (0,0), (-1,-1), 0.5, colors.grey),
("ALIGN", (0,0), (-1,-1), "CENTER"),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
])
t.setStyle(ts)
return t
# ── Q&A DATA ─────────────────────────────────────────────────────────────────
# Each case: dict with keys: case, section, question_lines, findings, diagnosis, explanation
# ============================================================
# PART 1
# ============================================================
part1_cases = [
# --- CASE 1 ---
dict(
case="Case 1 – 5-Year-Old Male | Repeated Blood Transfusions",
section="HAEMOGLOBINOPATHIES – HPLC",
question=[
"Q1. What is the diagnosis?",
"Q2. What does the HPLC pattern show?",
"Q3. What is the significance of the skull X-ray finding?",
],
findings=[
("Hb", "4.5 gm/dL", "Severely low"),
("Reticulocytes", "35%", "Markedly elevated"),
("HbF (HPLC)", "55.8%", "Massively elevated (N: <1%)"),
("HbA (HPLC)", "31.3%", "Reduced (N: ~97%)"),
("HbA2 (HPLC)", "4.6%", "Elevated (N: 1.5–3.5%)"),
],
diagnosis="Beta-Thalassaemia Major",
answer=[
"HPLC shows massively elevated HbF (55.8%) with drastically reduced HbA (31.3%) and elevated HbA2 (4.6%). This pattern reflects failure to produce normal beta-globin chains (beta⁰ or severe beta⁺ mutation), so the body compensates by retaining fetal haemoglobin (HbF = alpha2-gamma2).",
"Skull X-ray: Classic 'hair-on-end' / 'sun-ray' appearance due to diploic space expansion from hyperactive erythropoiesis in marrow. This is PATHOGNOMONIC of thalassaemia major.",
"Peripheral smear: Severe hypochromic microcytic anaemia, target cells, nucleated RBCs, basophilic stippling, anisocytosis and poikilocytosis.",
"Clinical: Transfusion-dependent from infancy, frontal bossing (thalassaemic facies), hepatosplenomegaly from extramedullary haematopoiesis.",
]
),
# --- CASE 2 ---
dict(
case="Case 2 – 20-Year-Old Male | Joint Pain, Leg Ulcers",
section="HAEMOGLOBINOPATHIES – HPLC",
question=[
"Q1. What is the diagnosis?",
"Q2. Interpret the HPLC and peripheral smear.",
"Q3. Why is the spleen NOT palpable despite the chronic haemolysis?",
],
findings=[
("Hb", "8 g%", "Low"),
("Reticulocytes", "25%", "Elevated – haemolytic"),
("Platelets", "206,000/µL", "Normal"),
("HbS (HPLC)", "~85–90%", "Dominant peak (N: absent)"),
("Spleen", "Not palpable", "Autosplenectomy"),
],
diagnosis="Sickle Cell Disease (HbSS – Homozygous)",
answer=[
"HPLC shows an overwhelming HbS fraction. Peripheral smear shows sickle cells (drepanocytes), target cells, and nucleated RBCs.",
"Absent spleen: Repeated vaso-occlusive infarcts progressively destroy splenic tissue – 'autosplenectomy'. This leaves the patient susceptible to encapsulated organisms (Pneumococcus, H. influenzae).",
"Complications shown: Delayed puberty/growth retardation, leg ulcers (ischaemia), gallstones (chronic haemolysis → bilirubin stones), jaundice, hepatomegaly.",
"Family history in cousin confirms autosomal recessive inheritance.",
]
),
# --- CASE 3 ---
dict(
case="Case 3 – 4-Year-Old Male | Fever, Epistaxis, Petechiae",
section="ACUTE LEUKAEMIA",
question=[
"Q1. What is the most probable diagnosis?",
"Q2. Interpret the CBC and bone marrow findings.",
"Q3. What is the significance of the cell type highlighted in red?",
],
findings=[
("Hb", "8 gm%", "Low"),
("TLC", "86,000/UL", "Markedly elevated"),
("Neutrophils", "20%", "Reduced"),
("Atypical lymphocytes (blasts)", "75%", "Markedly elevated – CRITICAL"),
("Platelet count", "25,000/UL", "Severely low"),
("Bone marrow blasts", "60%", "Infiltrated"),
],
diagnosis="Acute Lymphoblastic Leukaemia (ALL)",
answer=[
"ALL is the most common malignancy in children (<5 yrs). The 75% atypical lymphocytes in blood and 60% in bone marrow = blast crisis. Blasts are lymphoblasts – large cells with high N:C ratio, fine chromatin, prominent nucleoli.",
"The low platelet count (25,000) explains petechiae and epistaxis. Thrombocytopenia is caused by bone marrow infiltration crowding out normal haematopoiesis.",
"Hepatosplenomegaly and lymphadenopathy result from blast infiltration of these organs.",
"Treatment: Multi-agent chemotherapy (vincristine, prednisolone, asparaginase, methotrexate). Prognosis: >80% cure rate with modern protocols in children.",
]
),
# --- CASE 4 ---
dict(
case="Case 4 – 35-Year-Old Male | Bleeding Gums, Atypical Cells 80%",
section="ACUTE LEUKAEMIA",
question=[
"Q1. What is the diagnosis?",
"Q2. What are the characteristic morphological findings?",
"Q3. What does the FISH test show and why is it important?",
],
findings=[
("Hb", "9 gm%", "Low"),
("TLC", "95,000/µL", "Elevated"),
("Atypical cells (promyelocytes)", "80%", "Dominant – blasts"),
("Platelet count", "40,000/µL", "Low – DIC risk"),
("Faggot cells", "Present in marrow", "PATHOGNOMONIC"),
("FISH", "t(15;17) PML-RARα", "Confirmatory"),
],
diagnosis="Acute Promyelocytic Leukaemia (APL, AML-M3)",
answer=[
"APL is caused by t(15;17) translocation forming PML-RARα fusion gene. This blocks differentiation of promyelocytes at the promyelocyte stage.",
"Key morphological findings: (1) Hypergranular promyelocytes with kidney-shaped nuclei, (2) Auer rods (needle-like crystalline inclusions), (3) FAGGOT CELLS – cells stuffed with bundles of Auer rods – PATHOGNOMONIC of APL.",
"FISH (t15;17): Shows 1 yellow fusion signal (PML+RARα merged) + 1 green (chr15) + 1 red (chr17) = classic APL pattern.",
"Clinical emergency: APL causes DIC (disseminated intravascular coagulation) – explains bleeding gums and low platelets. Treatment: ATRA (all-trans retinoic acid) + arsenic trioxide – specific and curative in ~90%.",
]
),
# --- CASE 5 ---
dict(
case="Case 5 – 54-Year-Old Male | Massive Splenomegaly, WBC 300,000",
section="CHRONIC LEUKAEMIA",
question=[
"Q1. What is the diagnosis?",
"Q2. What is the significance of the LAP score?",
"Q3. What does the FISH cytogenetic study show?",
],
findings=[
("Hb", "9 gm%", "Low"),
("TLC", "300,000/cu mm", "Extreme leukocytosis"),
("Eosinophilia + Basophilia", "Present", "Key clue"),
("LAP score", "Decreased", "Key differentiator"),
("Splenomegaly", "Massive", "Characteristic"),
("BCR-ABL (FISH)", "Positive – t(9;22)", "Philadelphia chromosome"),
],
diagnosis="Chronic Myeloid Leukaemia (CML) – BCR-ABL Positive",
answer=[
"CML arises from the Philadelphia chromosome (Ph) – t(9;22) translocation creating BCR-ABL fusion gene, a constitutively active tyrosine kinase that drives uncontrolled myeloid proliferation.",
"Peripheral smear shows the full myeloid 'left shift' – all stages of maturation simultaneously: blasts, promyelocytes, myelocytes, metamyelocytes, bands, neutrophils, eosinophils, basophils.",
"LAP (Leukocyte Alkaline Phosphatase) score is LOW in CML – in contrast to a leukaemoid reaction (benign extreme leukocytosis) where LAP is HIGH. This is a critical diagnostic distinction.",
"FISH shows BCR-ABL yellow fusion signals. Treatment: Imatinib (Gleevec) – first BCR-ABL tyrosine kinase inhibitor. Dasatinib, nilotinib for resistance. 10-year survival >80%.",
]
),
# --- CASE 6 ---
dict(
case="Case 6 – 16-Year-Old Boy | Fatigue, Pallor, Anaemia",
section="HAEMOGLOBINOPATHIES – HPLC",
question=[
"Q1. What does the HPLC show and what is the diagnosis?",
"Q2. What is the clinical significance of this condition?",
],
findings=[
("HbF (HPLC)", "0.5%", "Normal"),
("HbA0 (HPLC)", "85.9%", "Slightly reduced"),
("HbA2 (HPLC)", "5.2%", "ELEVATED (N: 1.5–3.5%)"),
],
diagnosis="Beta-Thalassaemia Trait (Heterozygous Carrier)",
answer=[
"HbA2 >3.5% on HPLC is the DIAGNOSTIC CRITERION for Beta-Thalassaemia trait. Here HbA2 = 5.2% – clearly elevated.",
"Clinical: Mild microcytic hypochromic anaemia (not transfusion-dependent). Patient is a CARRIER of one abnormal beta-globin gene.",
"Significance: If both parents are carriers, child has 25% risk of Beta-Thalassaemia Major. Genetic counselling essential. HPLC-based newborn screening can identify carriers.",
"Do NOT give iron to this patient – iron deficiency can also cause microcytic anaemia, but iron supplementation in thalassaemia trait can cause iron overload.",
]
),
# --- CASE 7 ---
dict(
case="Case 7 – 15-Year-Old Boy | Abdominal Pain on Exertion, No Anaemia, Mild Jaundice",
section="HAEMOGLOBINOPATHIES – HPLC",
question=[
"Q1. Interpret the HPLC and give the diagnosis.",
"Q2. How does this differ from sickle cell disease?",
],
findings=[
("HbA0", "56.8%", "Reduced"),
("HbS (S-window)", "29.1%", "Significant"),
("HbA2", "3.8%*", "Mildly elevated"),
("HbF", "3.1%*", "Mildly elevated"),
],
diagnosis="HbS/Beta-Thalassaemia (Compound Heterozygote)",
answer=[
"The patient has inherited one HbS allele and one beta-thalassaemia allele – compound heterozygosity. HbS = 29.1%, HbA = 56.8% (some HbA = beta+ thalassaemia, not beta0), elevated HbA2 (>3.5%) confirms thalassaemia gene.",
"Compared to HbSS (sickle cell disease): Milder course because residual HbA (56.8%) reduces sickling tendency. No transfusion dependence. Abdominal pain episodes represent mild vaso-occlusive crises.",
"Mild jaundice = compensated haemolysis. No severe anaemia (Hb near normal).",
"Genotype: HbS/beta⁺-thalassaemia. If it were beta⁰, no HbA would be present.",
]
),
# --- CASE 8 ---
dict(
case="Case 8 – 19-Year-Old Boy | Severe Anaemia, Jaundice, Splenomegaly",
section="HAEMOGLOBINOPATHIES – HPLC",
question=[
"Q1. What does the HPLC show? What is the diagnosis?",
"Q2. Why is HbF elevated in this patient?",
],
findings=[
("HbS (S-window)", "78.1%", "Dominant"),
("HbF", "16.8%*", "Markedly elevated"),
("HbA0", "1.4%", "Near absent"),
("HbA2", "2.8%", "Normal"),
],
diagnosis="Sickle Cell Disease (HbSS) with elevated HbF",
answer=[
"HbS = 78.1% is dominant with near-absent HbA (1.4%) = homozygous sickle cell disease confirmed. The patient has inherited the HbS allele from BOTH parents.",
"HbF = 16.8% (markedly elevated for an adult): HbF is a natural disease modifier in SCD. It inhibits HbS polymerisation (prevents sickling). Patients with higher HbF have milder disease – fewer crises, less organ damage.",
"Splenomegaly at 19 years is unusual (most HbSS patients undergo autosplenectomy earlier). Elevated HbF may have protected the spleen by reducing infarcts.",
"Hydroxyurea therapy increases HbF production – its mechanism of action in SCD management.",
]
),
# --- CASE 9 ---
dict(
case="Case 9 – 3-Year-Old Child | Severe Anaemia, Growth Retardation",
section="HAEMOGLOBINOPATHIES – HPLC",
question=[
"Q1. Interpret the HPLC findings and give the diagnosis.",
"Q2. What is the long-term management?",
],
findings=[
("HbF", "95.0%", "OVERWHELMING – almost all Hb is HbF"),
("HbA0", "0.3%", "Virtually absent"),
("HbA2", "3.9%", "Slightly elevated"),
],
diagnosis="Beta-Thalassaemia Major (Homozygous beta⁰/beta⁰)",
answer=[
"HbF = 95% in a 3-year-old means the patient cannot produce functional beta-globin chains at all (beta⁰ mutation). The only Hb present is fetal Hb (alpha2-gamma2) which persists as compensation.",
"This is the most severe form: no HbA synthesis whatsoever. Growth failure, hepatosplenomegaly from extramedullary haematopoiesis, bone deformities from marrow expansion.",
"Management: (1) Regular blood transfusions every 3–4 weeks (keep Hb >9–10 g/dL), (2) Iron chelation therapy (deferoxamine/deferasirox) to prevent transfusional haemosiderosis, (3) CURATIVE: Allogeneic bone marrow/stem cell transplantation, (4) Gene therapy (emerging).",
]
),
# --- CASE 10 ---
dict(
case="Case 10 – 4-Year-Old Child | Anaemia, Jaundice, Splenomegaly",
section="HAEMOGLOBINOPATHIES – HPLC",
question=[
"Q1. Interpret the HPLC and give the diagnosis.",
"Q2. How does this differ from pure sickle cell disease?",
],
findings=[
("HbF", "15.7%", "Elevated"),
("HbA", "34.4%", "Present but reduced"),
("HbA2", "3.8%", "Mildly elevated"),
("HbS", "38.4%", "Significant"),
],
diagnosis="HbS/Beta⁺-Thalassaemia (Sickle-Beta Thalassaemia)",
answer=[
"Four fractions present: HbS (38.4%), HbA (34.4%), HbF (15.7%), HbA2 (3.8%). The presence of HbA alongside HbS – with elevated A2 and F – = Hb S/beta⁺-thalassaemia.",
"Sickle cell trait (HbAS) has ~50% HbS and ~50% HbA with normal HbA2 and F. This case has elevated A2 and F = thalassaemia gene involved.",
"Milder course than HbSS because HbA (34.4%) inhibits sickling. Splenomegaly persists (unlike HbSS autosplenectomy). Annual transcranial Doppler screening recommended.",
]
),
# --- CASE 11 ---
dict(
case="Case 11 – 58-Year-Old | Severe Back Pain, Weakness for 4 Months",
section="PLASMA CELL DYSCRASIA",
question=[
"Q1. What is the diagnosis?",
"Q2. Interpret the skull X-ray, bone marrow, and serum electrophoresis findings.",
"Q3. What is the M-spike and what does it represent?",
],
findings=[
("Skull X-ray", "Multiple punched-out lytic lesions", "PATHOGNOMONIC"),
("Bone marrow plasma cells", "Sheets of abnormal plasma cells", "Infiltration"),
("Total protein", "14.20 g/dL", "Very high (N: 6–8)"),
("Gamma globulin", "54.8% = 7.78 g/dL", "Massively elevated"),
("A/G ratio", "0.42", "Inverted (N: 2:1)"),
("Immunofixation", "IgG M-spike", "Monoclonal IgG"),
],
diagnosis="Multiple Myeloma (IgG Type)",
answer=[
"Myeloma is a malignant proliferation of plasma cells. Classic triad: (1) Bone pain with lytic lesions, (2) Monoclonal paraprotein in serum (M-spike), (3) Plasma cell infiltration of marrow (>10%).",
"Skull X-ray: 'punched-out' lesions = osteolytic destruction by myeloma cells activating osteoclasts (via RANKL). These are different from metastases (which have surrounding sclerosis).",
"Peripheral smear: Rouleaux formation (RBC stacking like coins) due to high immunoglobulin altering RBC surface charge.",
"SPEP: The M-spike (narrow tall peak in gamma region) represents a MONOCLONAL immunoglobulin from a single malignant plasma cell clone. Normal gamma is polyclonal (broad). Immunofixation identifies the heavy chain (IgG) and light chain type (kappa or lambda).",
"CRAB criteria: Hypercalcaemia, Renal failure, Anaemia, Bone lesions. Treatment: Bortezomib + lenalidomide + dexamethasone; autologous stem cell transplant.",
]
),
# --- CASE 12 ---
dict(
case="Case 12 – 52-Year-Old Male | Anaemia, Glossitis, Peripheral Neuropathy",
section="MACROCYTIC ANAEMIA",
question=[
"Q1. What is the diagnosis?",
"Q2. Interpret the CBC and bone marrow findings.",
"Q3. What differentiates B12 from folate deficiency?",
],
findings=[
("RBC", "2.69", "Severely low"),
("Hb", "10.6", "Low"),
("MCV", "117.6 fL", "MACROCYTIC (N: 80–100)"),
("MCH", "39.6 pg", "High"),
("Hypersegmented neutrophils", "Present", "PATHOGNOMONIC"),
("Bone marrow", "Megaloblastic precursors", "Nuclear-cytoplasmic dissociation"),
],
diagnosis="Megaloblastic Anaemia – Vitamin B12 Deficiency",
answer=[
"MCV 117.6 fL = macrocytic anaemia. Hypersegmented neutrophils (>5 lobes in >5% of neutrophils) are PATHOGNOMONIC of megaloblastic anaemia.",
"Bone marrow: Megaloblastic change = nuclear maturation lags behind cytoplasmic maturation. Giant metamyelocytes, macro-ovalocytes. The nucleus looks immature/open while cytoplasm is already mature.",
"B12 vs Folate: BOTH cause megaloblastosis and macrocytic anaemia. KEY DIFFERENTIATORS for B12 deficiency: (1) Peripheral neuropathy / subacute combined degeneration of spinal cord (B12 maintains myelin – folate does NOT), (2) Glossitis (smooth, beefy red tongue), (3) Knuckle pigmentation (especially in dark-skinned patients), (4) Serum B12 <200 pg/mL.",
"Causes of B12 deficiency: Pernicious anaemia (autoimmune loss of intrinsic factor), strict veganism, gastrectomy, terminal ileum disease (Crohn's).",
]
),
# --- CASE 13 ---
dict(
case="Case 13 – 32-Year-Old Female | SOB, Weakness, Koilonychia",
section="MICROCYTIC ANAEMIA",
question=[
"Q1. What is the diagnosis?",
"Q2. Interpret the CBC and peripheral smear findings.",
"Q3. What are the classic clinical signs seen?",
],
findings=[
("Hb", "9.7", "Low"),
("MCV", "69.7 fL", "MICROCYTIC (N: 80–100)"),
("MCH", "22.6 pg", "Low"),
("MCHC", "32.4", "Low"),
("RDW", "18.4%", "High – anisocytosis"),
("WBC/Plt", "Normal", ""),
],
diagnosis="Iron Deficiency Anaemia (IDA)",
answer=[
"MCV 69.7 = microcytic, MCH 22.6 = hypochromic, high RDW = wide variation in cell size (anisocytosis). Classic iron deficiency pattern.",
"Peripheral smear: Hypochromic RBCs (large area of central pallor >1/3 diameter), microcytes, pencil cells/elliptocytes, anisocytosis and poikilocytosis.",
"Clinical signs: (1) Koilonychia – spoon-shaped nails from nail plate softening, (2) Glossitis – smooth, painful tongue, (3) Angular cheilitis – cracks at mouth corners, (4) Severe pallor.",
"Iron studies (not shown but expected): Low serum ferritin (most sensitive), low serum iron, high TIBC.",
"Cause in this 32-year-old woman: Most likely chronic menorrhagia or dietary deficiency. Treatment: Oral ferrous sulphate for 3–6 months after correcting the cause.",
]
),
# --- CASE 14 ---
dict(
case="Case 14 – 20-Year-Old Male | High Fever 3 Days, Severe Headache",
section="PARASITIC INFECTION – MALARIA",
question=[
"Q1. What is the diagnosis and species?",
"Q2. Identify the key features on the peripheral smear.",
"Q3. What is the significance of hypoglycaemia and acidosis?",
],
findings=[
("Hb", "6.3 gm%", "Severe anaemia"),
("Blood pH", "7.1", "Metabolic acidosis (N: 7.35–7.45)"),
("FBS", "62 gm/dL", "Hypoglycaemia"),
("Total Bilirubin", "3 mg/dL", "Elevated – haemolytic jaundice"),
("Peripheral smear", "Ring forms + crescent gametocytes", "P. falciparum"),
],
diagnosis="Severe Falciparum Malaria (Plasmodium falciparum)",
answer=[
"Key smear features of P. falciparum: (1) Multiple ring forms per RBC (double/triple infection – SPECIFIC to P. falciparum), (2) Delicate ring forms with double chromatin dots, (3) Peripheral/appliqué position (accolé), (4) CRESCENT/BANANA-SHAPED GAMETOCYTES – PATHOGNOMONIC of P. falciparum.",
"Hypoglycaemia (62 mg/dL): P. falciparum parasites consume glucose; quinine (treatment) also stimulates insulin. Can cause coma – must be treated.",
"Metabolic acidosis (pH 7.1): Sequestered parasitised RBCs block microcirculation → tissue hypoperfusion → lactic acidosis. Indicates SEVERE malaria.",
"WHO criteria for severe malaria: cerebral involvement, severe anaemia (Hb<7), respiratory distress, hypoglycaemia, metabolic acidosis. Treatment: IV artesunate (preferred over quinine).",
]
),
# --- CASE 15 ---
dict(
case="Case 15 – 14-Year-Old Boy | Knee Haemarthrosis, Family History of Bleeding",
section="COAGULATION DISORDER",
question=[
"Q1. What is the diagnosis?",
"Q2. Interpret the coagulation profile.",
"Q3. What is the significance of normal bleeding time and PT?",
],
findings=[
("Platelet count", "50,000/cumm", "Normal-ish"),
("Bleeding Time", "5 min", "NORMAL (2–7 min)"),
("PT", "12.5 sec", "NORMAL (11–14 sec)"),
("aPTT", "95 sec", "MARKEDLY PROLONGED (N: 28–33 sec)"),
("Fibrinogen", "300 mg/dL", "Normal"),
],
diagnosis="Haemophilia A (Factor VIII Deficiency)",
answer=[
"The coagulation defect is ISOLATED aPTT prolongation with normal PT and BT. This pattern = intrinsic pathway defect (Factors VIII, IX, XI, or XII).",
"Normal BT = platelet plug formation intact (primary haemostasis is fine). Normal PT = extrinsic pathway (Factor VII) and common pathway (X, V, II, I) intact.",
"X-linked recessive inheritance + haemarthrosis + isolated aPTT prolongation = HAEMOPHILIA A (Factor VIII deficiency) – most likely. Haemophilia B (Factor IX) would give identical pattern; Factor assay distinguishes them.",
"Haemarthrosis: Bleeding into joints (knee, elbow, ankle) is the hallmark of haemophilia. Repeated bleeds cause synovitis → arthropathy.",
"Treatment: Factor VIII concentrate (recombinant), desmopressin (DDAVP) for mild cases, emicizumab (bispecific antibody bypassing Factor VIII) for prophylaxis.",
]
),
# --- CASES 16, 17, 18 – Jaundice ---
dict(
case="Case 16 – 35-Year-Old Male | Fever, Nausea, Jaundice, Dark Urine",
section="JAUNDICE – BIOCHEMICAL ANALYSIS",
question=[
"Q1. What type of jaundice is this?",
"Q2. Interpret all the laboratory parameters.",
],
findings=[
("Total Bilirubin", "9 mg/dL", "↑↑ (N: <1)"),
("Direct Bilirubin", "5.5 mg/dL", "↑↑ (N: 0.1–0.4)"),
("Indirect Bilirubin", "3.5 mg/dL", "↑ (N: 0.2–0.7)"),
("AST", "55 IU/L", "↑ (N: <40)"),
("ALT", "68 IU/L", "↑ (N: <40)"),
("ALP", "150 IU/L", "Mildly ↑ (N: 30–130)"),
("Urine Bilirubin", "Present", "Abnormal (N: absent)"),
("Urine Urobilinogen", "5 mg/24hr", "Normal"),
],
diagnosis="Hepatocellular Jaundice (Viral Hepatitis – likely HAV or HEV)",
answer=[
"Pattern: BOTH direct and indirect bilirubin elevated (mixed). AST + ALT elevated = hepatocyte damage. ALP only mildly elevated (not predominantly cholestatic). Urine bilirubin PRESENT (conjugated bilirubin is water-soluble, filtered by kidney).",
"Acute onset with fever, nausea, anorexia + jaundice in a young person = Viral Hepatitis A or E (faeco-oral route).",
"ALT > AST (ALT is more liver-specific). Transaminase elevation = hepatocyte necrosis releasing enzymes.",
"A/G ratio inverted (1:1.8 vs normal 2:1) = reduced albumin synthesis by damaged hepatocytes.",
]
),
dict(
case="Case 17 – 30-Year-Old Male | Weakness, Yellowing, Dark Urine, Pallor",
section="JAUNDICE – BIOCHEMICAL ANALYSIS",
question=[
"Q1. What type of jaundice is this?",
"Q2. Why is urine bilirubin ABSENT despite jaundice?",
],
findings=[
("Total Bilirubin", "5 mg/dL", "↑"),
("Direct Bilirubin", "0.2 mg/dL", "NORMAL"),
("Indirect Bilirubin", "4.8 mg/dL", "MARKEDLY ↑"),
("AST", "20 IU/L", "Normal"),
("ALT", "18 IU/L", "Normal"),
("ALP", "56 IU/L", "Normal"),
("Urine Urobilinogen", "17 mg/24hr", "HIGH (N: 0–7)"),
("Urine Bilirubin", "Absent", "Normal – indirect bili is insoluble"),
],
diagnosis="Pre-Hepatic (Haemolytic) Jaundice",
answer=[
"Pattern: Predominantly INDIRECT (unconjugated) bilirubin elevated. Liver enzymes NORMAL (liver not damaged). Urine bilirubin ABSENT (indirect bilirubin is bound to albumin = insoluble = cannot pass glomerulus). Urobilinogen HIGH (excess bilirubin → gut → more urobilinogen formed → excreted in urine).",
"Pallor + jaundice = haemolytic anaemia (haemolysis releases excess indirect bilirubin from broken RBCs).",
"Causes: Haemolytic anaemia, G6PD deficiency, sickle cell crisis, ABO incompatibility, malaria.",
"Comparison: Hepatocellular has both direct AND indirect elevated + raised transaminases. Obstructive has predominantly direct + raised ALP. Haemolytic has predominantly indirect + normal enzymes.",
]
),
dict(
case="Case 18 – 40-Year-Old Female | Itching, Pale Stool, Dark Urine, Jaundice",
section="JAUNDICE – BIOCHEMICAL ANALYSIS",
question=[
"Q1. What type of jaundice is this?",
"Q2. Why is ALP elevated and urobilinogen normal/low?",
],
findings=[
("Total Bilirubin", "10 mg/dL", "↑↑"),
("Direct Bilirubin", "9.5 mg/dL", "MASSIVELY ↑"),
("Indirect Bilirubin", "0.5 mg/dL", "NORMAL"),
("AST/ALT", "22/18 IU/L", "NORMAL"),
("ALP", "250 IU/L", "MARKEDLY ↑ (N: 30–130)"),
("Urine Bilirubin", "Present", "Abnormal – direct bilirubin filtered"),
("Urine Urobilinogen", "4 mg/24hr", "Normal-low"),
],
diagnosis="Post-Hepatic (Obstructive/Cholestatic) Jaundice",
answer=[
"Pattern: Predominantly DIRECT (conjugated) bilirubin elevated (9.5/10 = 95%). Liver enzymes normal (hepatocytes not damaged). ALP MARKEDLY elevated = biliary epithelium induces ALP when bile obstructs.",
"Urine bilirubin PRESENT: Conjugated bilirubin is water-soluble, regurgitates into blood → filtered by kidney → dark urine.",
"Pale/clay stool: Bile is blocked from reaching intestine → no stercobilin → stool loses colour.",
"Pruritus: Bile salt deposition in skin.",
"Causes in a 40-year-old woman: Choledocholithiasis (most common), carcinoma head of pancreas, cholangiocarcinoma, primary sclerosing cholangitis. Investigation: USG abdomen → MRCP → ERCP.",
]
),
# --- CASE 19 ---
dict(
case="Case 19 – 62-Year-Old Male | Crushing Chest Pain, BP 100/72, Sweating",
section="CARDIAC BIOMARKERS",
question=[
"Q1. What is the diagnosis?",
"Q2. Interpret the ECG finding.",
"Q3. What is the significance of the Troponin-I level?",
],
findings=[
("BP", "100/72 mmHg", "Hypotensive – cardiogenic shock"),
("Pulse", "60/min, weak", "Bradycardia"),
("ECG", "ST-segment elevation", "STEMI pattern"),
("Troponin-I", "0.213 ng/mL", "ELEVATED (N: <0.04) – 5x upper limit"),
("Total CK", "453 U/L", "Elevated (N: <300)"),
("Coronary angiogram", "90% LAD blockade", "Critical stenosis"),
],
diagnosis="Acute ST-Elevation Myocardial Infarction (STEMI) – LAD Territory",
answer=[
"Classic STEMI presentation: Risk factors (15 yrs HTN + DM) + typical crushing retrosternal pain radiating to arm + diaphoresis + nausea = 'acute coronary syndrome' until proven otherwise.",
"ECG: ST-segment elevation above the isoelectric baseline at the J-point. STEMI is defined as ST elevation in ≥2 contiguous leads. This triggers IMMEDIATE reperfusion (door-to-balloon <90 min).",
"Troponin-I = 0.213 ng/mL (5× upper limit of normal): Troponin is the GOLD STANDARD biomarker for myocardial infarction. It rises within 3–6 hrs, peaks at 24 hrs, remains elevated 7–14 days. Highly sensitive AND specific for myocardial necrosis.",
"LAD territory infarction: Anterior/anteroseptal STEMI. The LAD supplies anterior wall, apex, and interventricular septum. 90% blockade = near-total occlusion requiring urgent PCI (primary angioplasty) or thrombolysis.",
"CK-MB is less specific; troponin has replaced it as the primary biomarker.",
]
),
] # end part1_cases
# ============================================================
# PART 2
# ============================================================
part2_cases = [
# --- P2 CASE 1 ---
dict(
case="Case 1 – 7-Year-Old Child | Facial Puffiness, Massive Generalized Oedema",
section="RENAL PATHOLOGY – NEPHROTIC SYNDROME",
question=[
"Q1. What is the most probable diagnosis?",
"Q2. Explain the pathophysiology of oedema in this condition.",
"Q3. What does the urine microscopy show and what does it signify?",
],
findings=[
("Serum Albumin", "Decreased ↓", "Hypoalbuminaemia – KEY"),
("Serum Cholesterol", "Increased ↑", "Hyperlipidaemia"),
("Serum Triglycerides", "Increased ↑", ""),
("Serum Fibrinogen", "Increased ↑", ""),
("Urine Protein", "4.2 g/24 hour", "Nephrotic range (>3.5 g/day)"),
("Urine RBC/WBC", "Nil", "No haematuria (distinguishes from nephritic)"),
("Urine Casts", "Waxy casts ++", "Advanced tubular stasis"),
],
diagnosis="Nephrotic Syndrome – Most Likely Minimal Change Disease (MCD)",
answer=[
"Nephrotic syndrome: Protein >3.5g/day + hypoalbuminaemia + oedema + hyperlipidaemia. All four criteria met here.",
"Pathophysiology of oedema: Loss of glomerular charge barrier → massive urinary protein loss → serum albumin falls → oncotic pressure drops → fluid escapes capillaries → interstitial oedema, ascites, pleural effusion.",
"Hyperlipidaemia: Liver compensates for protein loss by increasing ALL protein synthesis including VLDL/LDL → hypercholesterolaemia, hypertriglyceridaemia. Fibrinogen also rises → thrombosis risk.",
"Waxy casts: Formed from breakdown products of cellular casts after prolonged tubular stasis. Seen in advanced or chronic nephrotic syndrome. Represent severe tubular dysfunction.",
"MCD (Minimal Change Disease): Most common nephrotic syndrome in children (peak 2–6 yrs). Light microscopy: NORMAL. EM: fusion/effacement of podocyte foot processes. Responds dramatically to steroids (>90% remission). Previous name: 'Nil disease' or 'Lipoid nephrosis'.",
]
),
# --- P2 CASE 2 ---
dict(
case="Case 2 – 12-Year-Old Boy | Cola-Coloured Urine, High BP after Sore Throat",
section="RENAL PATHOLOGY – GLOMERULONEPHRITIS",
question=[
"Q1. What is the diagnosis?",
"Q2. What is the significance of the ASO titre?",
"Q3. What are RBC casts and why are they important?",
],
findings=[
("Urine colour", "Cola-coloured (dark brown)", "Haematuria"),
("ASO titre", "1:1024", "MARKEDLY ELEVATED (N: <200 IU/mL)"),
("Urine Protein", "+", "Mild"),
("Urine RBCs", "+++", "Haematuria"),
("Urine Pus cells", "++", "Inflammation"),
("Urine RBC casts", "+++", "PATHOGNOMONIC of glomerulonephritis"),
("BP", "Elevated (hypertension)", "Fluid retention"),
],
diagnosis="Post-Streptococcal Glomerulonephritis (PSGN) – Nephritic Syndrome",
answer=[
"Sequence: Group A beta-haemolytic Streptococcal throat infection → 1–3 week latent period → immune complex (Ag-Ab) deposition in glomerular basement membrane → complement activation → inflammatory glomerular injury.",
"ASO titre 1:1024: Antistreptolysin O antibodies are produced against streptococcal exotoxin. Titre >200 IU/mL = recent streptococcal infection. 1:1024 = strongly positive.",
"RBC casts: A cylinder of RBCs trapped in a protein matrix, formed ONLY when bleeding occurs within the glomerulus/tubule. They are PATHOGNOMONIC of glomerulonephritis. RBCs cannot pass into tubules from vessels lower in the urinary tract.",
"Nephritic vs Nephrotic: PSGN = NEPHRITIC (haematuria, hypertension, oliguria, mild-moderate proteinuria, RBC casts). Nephrotic syndrome = massive proteinuria, no haematuria, no hypertension, waxy/fatty casts.",
"Prognosis: Excellent in children. >95% resolve spontaneously. Treat hypertension and fluid overload (diuretics). No specific anti-glomerular treatment needed.",
]
),
# --- P2 CASE 3 ---
dict(
case="Case 3 – 36-Year-Old Male | Matted Cervical Lymph Nodes × 4 Months, Night Sweats",
section="INFECTIOUS DISEASE – LYMPHADENITIS",
question=[
"Q1. What is the diagnosis?",
"Q2. Interpret the FNAC findings.",
"Q3. What is the significance of serum ADA?",
],
findings=[
("ESR", "60 mm/1st hr", "Elevated (N: <15 mm/hr for men)"),
("Serum ADA", "44.53 IU/L", "ELEVATED (cutoff for TB: >40 IU/L)"),
("FNAC", "Caseating epithelioid granulomas", "DIAGNOSTIC of TB"),
("Constitutional symptoms", "Fever + weight loss + night sweats", "Classic TB triad"),
],
diagnosis="Tuberculous Lymphadenitis (Scrofula)",
answer=[
"Matted cervical lymph nodes = multiple nodes stuck together due to periadenitis (TB inflammation extends through capsule). This matting is CHARACTERISTIC of TB lymphadenitis.",
"FNAC findings: (1) Epithelioid granulomas – tight clusters of epithelioid histiocytes (spindle-shaped, pale cells with 'shoe-print' nuclei), (2) CASEOUS NECROSIS – central area of acellular, amorphous, eosinophilic ('cheesy') necrotic material = PATHOGNOMONIC of TB, (3) Langhan's giant cells (if present) – multinucleated giant cells with peripheral 'horseshoe' arrangement of nuclei.",
"Serum ADA (Adenosine Deaminase): Enzyme released by T-lymphocytes in cell-mediated immunity. Elevated in TB infections (>40 IU/L has 83% sensitivity, 84% specificity for TB lymphadenitis).",
"Constitutional symptoms (fever, weight loss, night sweats) = 'B symptoms' of TB. ESR elevated = systemic inflammation marker.",
"Treatment: RHEZ (Rifampicin + Isoniazid + Ethambutol + Pyrazinamide) × 2 months → RH × 4 months = 6-month standard regime.",
]
),
# --- P2 CASE 4 ---
dict(
case="Case 4 – 45-Year-Old Male | Cough, Chest Pain, Peripheral Lymphadenopathy",
section="RESPIRATORY ONCOLOGY",
question=[
"Q1. What does the chest X-ray show?",
"Q2. What is the histological diagnosis from biopsy?",
"Q3. What histological feature is pathognomonic?",
],
findings=[
("Chest X-ray", "Large mass in left lower zone", "Pulmonary malignancy"),
("Biopsy – low power", "Necrotic infiltrating tumour + lymph node metastasis", ""),
("Biopsy – high power", "Keratin pearls + malignant squamous cells", "DIAGNOSTIC"),
("Biopsy – high power", "Intercellular bridges between tumour cells", "Squamous differentiation"),
],
diagnosis="Squamous Cell Carcinoma of the Lung",
answer=[
"CXR: Large irregular opacity in left lower zone with mediastinal lymphadenopathy. Red arrow points to the primary mass. CT-guided biopsy from this lesion was performed.",
"Keratin pearl (squamous pearl): A concentric whorl of keratinized eosinophilic cells at the centre of a tumour nest. This is the PATHOGNOMONIC feature of well-differentiated Squamous Cell Carcinoma.",
"Lymph node biopsy: Shows metastatic tumour replacing nodal architecture = Stage III disease at minimum.",
"SCC of lung: Strongly associated with smoking (90%). Arises centrally (main bronchi). Cavitates (central necrosis). Express squamous markers: p40, p63, CK5/6 on IHC.",
"Management: Stage-dependent. Resectable (lobectomy), unresectable (chemoradiotherapy), targeted therapy if EGFR/ALK mutation present, immunotherapy (PD-L1 positive).",
]
),
# --- P2 CASE 5 ---
dict(
case="Case 5 – 46-Year-Old Female | Heat Intolerance, Exophthalmos, Heart Failure",
section="ENDOCRINOLOGY – THYROID",
question=[
"Q1. What is the diagnosis?",
"Q2. Interpret the thyroid function tests.",
"Q3. What are the three pathognomonic clinical features of this condition?",
],
findings=[
("T3", "253 ng/dL", "Elevated (N: 80–200)"),
("T4", "4.91 ng/dL", "Elevated"),
("TSH", "0.01 mIU/L", "SUPPRESSED (N: 0.4–4.0) – primary hyperthyroid"),
("S. Calcium", "11.5 mg/dL", "Mildly elevated"),
("S. PTH", "25.81 pg/L", "Low-normal"),
("HR", "122 beats/min", "Tachycardia"),
("BP", "158/90 mmHg", "Hypertension"),
],
diagnosis="Graves' Disease (Autoimmune Hyperthyroidism)",
answer=[
"TFTs: T3 and T4 elevated + TSH suppressed = PRIMARY HYPERTHYROIDISM. TSH is suppressed because high T3/T4 exerts negative feedback on pituitary.",
"Graves' Disease = autoimmune. TSH receptor antibodies (TRAb / LATS) continuously stimulate the thyroid (mimic TSH) → hyperthyroidism + goitre.",
"MERSEBURGER TRIAD (pathognomonic of Graves'): (1) HYPERTHYROIDISM – tachycardia, hypertension, heat intolerance, weight loss, oligomenorrhoea, cardiac failure, (2) EXOPHTHALMOS (proptosis) – retroorbital glycosaminoglycan deposition by TSH-receptor-stimulated fibroblasts, (3) PRETIBIAL MYXOEDEMA – non-pitting, orange-peel skin over shins.",
"Acropachy (clubbing of fingers) = rare but specific to Graves'.",
"Histopathology: Hyperplastic follicular cells (tall columnar), scalloped colloid (rapid reabsorption), lymphocytic infiltration = Hashimoto-like background (autoimmune).",
"Treatment: (1) Antithyroid drugs (propylthiouracil/carbimazole), (2) Radioactive iodine (I-131), (3) Surgery (total thyroidectomy). Beta-blockers for symptom control.",
]
),
# --- P2 CASE 6 ---
dict(
case="Case 6 – 43-Year-Old Male | Episodic Wheeze, Cough, Dust Allergy, Atopy",
section="RESPIRATORY – BRONCHIAL ASTHMA",
question=[
"Q1. What is the diagnosis?",
"Q2. Identify and explain the two characteristic structures seen in sputum.",
"Q3. What is the pathophysiology of asthma?",
],
findings=[
("History", "Atopy + episodic cough, wheeze, SOB", "IgE-mediated Type I hypersensitivity"),
("Sputum – Image 1", "Curschmann's spiral + eosinophils", "Mucus plugging"),
("Sputum – Image 2", "Charcot-Leyden crystals + eosinophilia", "Eosinophil breakdown"),
("Trigger", "Dust exposure", "Extrinsic/atopic asthma"),
],
diagnosis="Bronchial Asthma (Atopic / Extrinsic Type)",
answer=[
"CURSCHMANN'S SPIRALS: Long, coiled mucous casts of small airways (bronchioles). Asthmatic airways produce thick, viscous mucus that takes the shape of the lumen and is expectorated as spirals. Indicates bronchial mucus plugging.",
"CHARCOT-LEYDEN CRYSTALS: Hexagonal, bipyramidal (needle/spindle-shaped) eosinophilic crystals. Formed from Galectin-10 (lysophospholipase) released during eosinophil degranulation and breakdown. Their presence in sputum confirms eosinophilic airway inflammation.",
"THREE HALLMARKS of asthma sputum: (1) Curschmann's spirals, (2) Charcot-Leyden crystals, (3) Sputum eosinophilia (>3%).",
"Pathophysiology: Allergen → IgE cross-linking on mast cells → degranulation (histamine, leukotrienes, prostaglandins) → bronchospasm + mucus hypersecretion + mucosal oedema. IL-5 recruits eosinophils → epithelial damage → airway remodelling.",
"Treatment: (1) Short-acting β2-agonists (salbutamol) – reliever, (2) Inhaled corticosteroids (ICS) – preventer, (3) Leukotriene receptor antagonists, (4) Biologics (omalizumab anti-IgE, mepolizumab anti-IL5) for severe eosinophilic asthma.",
]
),
# --- P2 CASE 7 ---
dict(
case="Case 7 – 35-Year-Old Male Alcoholic | Severe Epigastric Pain Radiating to Back",
section="PANCREATITIS",
question=[
"Q1. What is the diagnosis?",
"Q2. Interpret the key biochemical findings.",
"Q3. Why is serum calcium low? What does this signify?",
],
findings=[
("TWBC", "18,000/cumm", "Elevated – inflammation"),
("FBS", "170 mg/dL", "Elevated – insulin/glucagon imbalance"),
("Serum Calcium", "4.1 mg/dL", "CRITICALLY LOW (N: 8.5–10.5)"),
("Serum Albumin", "1.8 g/dL", "Very low (N: 3.5–5.0)"),
("Serum Amylase", "1200 IU/L", "10× elevated (N: 30–110)"),
("Serum Lipase", "840 IU/L", "5× elevated (N: 0–160)"),
("Serum AST", "60 U/L", "Mildly elevated"),
("Serum LDH", "610 U/dL", "Elevated (N: 140–280)"),
("USG abdomen", "Gallstone in CBD", "Biliary cause identified"),
],
diagnosis="Acute Pancreatitis (Gallstone + Alcohol-Induced, Severe)",
answer=[
"Acute pancreatitis diagnosed by: (1) Clinical – acute severe epigastric pain radiating to back, (2) Biochemical – Amylase AND/OR Lipase >3× ULN. Here amylase = 1200 (>10×) and lipase = 840 (>5×). Lipase is MORE specific for pancreatic injury (amylase rises in other conditions too).",
"Hypocalcaemia (4.1 mg/dL): SAPONIFICATION of fat necrosis. Pancreatic lipase breaks down peripancreatic fat → free fatty acids → bind calcium ions → form insoluble calcium soaps (chalky white fat necrosis deposits). This SEQUESTERS calcium → hypocalcaemia. Hypocalcaemia is a SEVERITY MARKER (Ranson's criteria).",
"Low albumin (1.8 g/dL): Systemic inflammatory response (SIRS) + third spacing of fluids → low effective circulating volume → low albumin.",
"Two causes simultaneously: ALCOHOL (direct acinar cell toxin) + CBD GALLSTONE (obstructs pancreatic duct → enzyme reflux). Either alone can cause pancreatitis; both together = worse severity.",
"Ranson's severity criteria: >3 criteria = severe. This patient has elevated glucose, low albumin, low calcium, elevated LDH, elevated WBC = likely scores ≥3 = SEVERE acute pancreatitis. Management: NPO, IV fluids, analgesia, ICU monitoring.",
]
),
# --- P2 CASE 8 ---
dict(
case="Case 8 – 30-Year-Old Female | Altered Sensorium, Chronic Cough, Weight Loss",
section="CSF ANALYSIS – MENINGITIS",
question=[
"Q1. What is the diagnosis?",
"Q2. Interpret the CSF examination in full.",
"Q3. What is the significance of cobweb clot formation?",
],
findings=[
("CSF Appearance", "Turbid", "Cloudy – protein/cells elevated"),
("Cobweb clot", "PRESENT (+)", "CHARACTERISTIC of TBM"),
("CSF Protein", "800 mg/dL", "Markedly elevated (N: 15–45)"),
("CSF Glucose", "40 mg/dL", "LOW (N: 50–80 mg/dL)"),
("CSF Chloride", "62 mmol/L", "Very low (N: 117–122)"),
("Total cells", "500/cumm", "Elevated (N: <5)"),
("Cell type", "Lymphocytes 92%, Macrophages 8%", "Lymphocytic pleocytosis"),
],
diagnosis="Tuberculous Meningitis (TBM)",
answer=[
"CSF triad of TBM: (1) LYMPHOCYTIC pleocytosis, (2) HIGH protein (>45 mg/dL; here 800!), (3) LOW glucose (CSF:serum ratio <0.5) with very low chloride.",
"Cobweb clot: TBM CSF contains very high fibrinogen. When the tube stands undisturbed for a few minutes, the fibrinogen forms a delicate 'cobweb' network at the top of the tube. This is NEAR PATHOGNOMONIC of TBM (also seen in bacterial but less characteristically).",
"Very low chloride (62 vs N 117–122): In TBM, bacteria consume glucose and inflammation alters transport; chloride falls as a secondary consequence. Very low chloride is a CLASSIC TBM CSF finding.",
"Clinical context: Chronic onset, pulmonary TB features (cough + weight loss), altered sensorium = TB meningitis until proven otherwise.",
"Treatment: RHEZ × 2 months + RH × 10 months (total 12 months for TBM) + IV dexamethasone (to reduce cerebral oedema and mortality).",
]
),
# --- P2 CASE 9 ---
dict(
case="Case 9 – 12-Year-Old Male | High Fever, Photophobia, Neck Stiffness, Kernig's ++",
section="CSF ANALYSIS – MENINGITIS",
question=[
"Q1. What is the diagnosis?",
"Q2. Interpret the CSF findings.",
"Q3. Name the common etiological agents.",
],
findings=[
("CSF Pressure", "600 mm H2O", "VERY HIGH (N: 80–180)"),
("CSF Appearance", "Cloudy/Turbid", "Pus/cells"),
("CSF Protein", "160 mg/dL", "Elevated"),
("CSF Glucose", "20 mg/dL", "VERY LOW (N: 50–80)"),
("CSF Chloride", "120 mmol/L", "Low-normal"),
("Total cells", "1200/cumm", "Very elevated"),
("Cell type", "Neutrophils 95%, Monocytes 5%", "PMN DOMINANT – bacterial"),
],
diagnosis="Pyogenic (Bacterial) Meningitis",
answer=[
"CSF triad of bacterial meningitis: (1) NEUTROPHILIC pleocytosis (PMN >80%), (2) HIGH protein, (3) VERY LOW glucose (bacteria actively consume CSF glucose – <40 mg/dL or CSF:serum ratio <0.3).",
"Very high opening pressure (600 mm H2O) reflects severe cerebral oedema + raised ICP. Risk of herniation – lumbar puncture must be preceded by CT to exclude mass.",
"Etiological agents for 12-year-old: Neisseria meningitidis (most common, causes meningococcal meningitis, petechial rash), Streptococcus pneumoniae (most common bacterial meningitis overall), Haemophilus influenzae type b (now rare due to vaccination).",
"Treatment: Immediate IV ceftriaxone (3rd generation cephalosporin) + dexamethasone (to reduce inflammation and hearing loss risk). Delay even 1 hour increases mortality and morbidity significantly.",
"Kernig's sign: Cannot extend knee with hip flexed (meningeal irritation). Brudzinski's sign: Neck flexion causes involuntary hip flexion. Both = meningism.",
]
),
# --- P2 CASE 10 ---
dict(
case="Case 10 – 22-Year-Old Male | Fever, Headache, Neck Stiffness + URTI Symptoms",
section="CSF ANALYSIS – MENINGITIS",
question=[
"Q1. What is the diagnosis?",
"Q2. How does this CSF profile differ from TBM and bacterial meningitis?",
"Q3. What are the common causative viruses?",
],
findings=[
("CSF Appearance", "CLEAR", "KEY – not turbid"),
("CSF Protein", "60 mg/dL", "Mildly elevated"),
("CSF Glucose", "60 mg/dL", "NORMAL (N: 50–80)"),
("CSF Chloride", "120 mmol/L", "Normal"),
("Total cells", "400/cumm", "Elevated"),
("Cell type", "Lymphocytes 92%, Monocytes 8%", "Lymphocytic – viral pattern"),
],
diagnosis="Viral (Aseptic) Meningitis",
answer=[
"The KEY distinguisher of viral meningitis from TBM is NORMAL CSF glucose. Viruses do NOT consume glucose. Protein is only mildly elevated. CSF is CLEAR (not turbid). No cobweb, no coagulum.",
"Both viral and TBM show lymphocytic pleocytosis. The glucose level decides: Normal glucose + lymphocytes = viral. Low glucose + lymphocytes = TBM.",
"CSF comparison summary: Viral (clear, lymphocytes, protein slightly ↑, glucose NORMAL), TBM (turbid/cobweb, lymphocytes, protein very ↑, glucose LOW, chloride very LOW), Bacterial (turbid, neutrophils, protein ↑, glucose VERY LOW).",
"Common viruses: Enteroviruses (Coxsackievirus, Echovirus) = most common overall. HSV-2 (genital herpes). Mumps virus. EBV, CMV (in immunocompromised). Arbovirus (mosquito-borne).",
"Treatment: Supportive (analgesics, antipyretics, hydration). If HSV suspected (temporal lobe involvement) → IV acyclovir empirically. Most viral meningitis self-limiting in 1–2 weeks.",
]
),
# --- P2 CASE 11 ---
dict(
case="Case 11 – 4-Year-Old Child | Delayed Milestones, Growth Retardation",
section="CHROMOSOMAL DISORDERS – KARYOTYPING",
question=[
"Q1. What is the diagnosis?",
"Q2. What does the karyotype show?",
"Q3. What are the key clinical features and complications?",
],
findings=[
("Karyotype", "47 chromosomes – extra chromosome 21", "Trisomy 21"),
("Clinical features", "Flat face, upslanting palpebral fissures, epicanthal folds", "Down syndrome facies"),
("Growth", "Delayed milestones, short stature", ""),
("Tone", "Hypotonia (presumed)", ""),
],
diagnosis="Down Syndrome (Trisomy 21) – 47, XX/XY, +21",
answer=[
"Karyotype: 47 chromosomes with THREE copies of chromosome 21 (trisomy 21). Arises from NON-DISJUNCTION during meiosis I (usually maternal). Risk increases with maternal age (1:1500 at age 20, 1:30 at age 45).",
"Characteristic facies: Flat facial profile, upslanting palpebral fissures (mongoloid slant), epicanthal folds, small nose, protruding tongue (macroglossia), small ears.",
"Systemic complications: (1) CARDIAC – AVSD (endocardial cushion defect) in 40–50% – most common cause of mortality, (2) Intellectual disability (IQ 25–75), (3) Hypotonia, (4) Duodenal atresia ('double bubble' sign), (5) Atlanto-axial instability, (6) Leukemia (especially ALL and transient myeloproliferative disorder), (7) Alzheimer's disease by age 40 (chromosome 21 carries APP gene).",
"Diagnosis: (1) Prenatal – amniocentesis or CVS karyotyping; NIPT (cell-free DNA) for screening, (2) Postnatal – karyotype.",
"Single palmar crease (Simian crease) + sandal gap between 1st and 2nd toes are also classic signs.",
]
),
# --- P2 CASE 12 ---
dict(
case="Case 12 – 17-Year-Old Girl | Primary Amenorrhoea, Short Stature, Webbed Neck",
section="CHROMOSOMAL DISORDERS – KARYOTYPING",
question=[
"Q1. What is the diagnosis?",
"Q2. Interpret the karyotype.",
"Q3. What are the clinical features and their causes?",
],
findings=[
("Karyotype", "45 chromosomes – only 1 X, no Y", "45, X – Monosomy X"),
("Primary amenorrhoea", "Never menstruated", "Streak gonads"),
("Short stature", "Markedly short for age", "GH deficiency / skeletal abnormality"),
("Webbed neck", "Pterygium colli", "Cystic hygroma remnant"),
("Physical features", "Short stature (A), webbed neck (B), cubitus valgus (C)", ""),
],
diagnosis="Turner Syndrome (45, X – Monosomy X)",
answer=[
"Karyotype: 45, X – only ONE X chromosome, no second sex chromosome. The most common sex chromosome disorder (1:2500 live female births). Most are 45,X; some are mosaics (45,X/46,XX).",
"Clinical features and causes: (1) SHORT STATURE – decreased SHOX gene dosage on X chromosome, (2) WEBBED NECK – lymphoedema of neck in utero (cystic hygroma) → resolves leaving webbing, (3) PRIMARY AMENORRHOEA – streak gonads (fibrous, non-functioning ovaries) → no oestrogen → no puberty → no periods → infertility, (4) CUBITUS VALGUS (wide carrying angle), (5) Shield chest + widely spaced nipples, (6) Low posterior hairline, (7) Horseshoe kidney (30%), (8) Bicuspid aortic valve / coarctation of aorta.",
"Intelligence is NORMAL (unlike Down syndrome) – but spatial reasoning and mathematical difficulties common.",
"Treatment: (1) Recombinant GH for height gain, (2) Oestrogen replacement from ~12–13 years for puberty induction + prevent osteoporosis, (3) Progesterone added for uterine protection, (4) Assisted reproduction (egg donation) for fertility.",
]
),
# --- P2 CASE 13 ---
dict(
case="Case 13 – 35-Year-Old Tall Male | Primary Infertility, Gynecomastia",
section="CHROMOSOMAL DISORDERS – KARYOTYPING",
question=[
"Q1. What is the diagnosis?",
"Q2. Interpret the karyotype and FISH.",
"Q3. What are the clinical features and their pathophysiology?",
],
findings=[
("Karyotype", "47 chromosomes – 2 X + 1 Y", "47, XXY"),
("FISH", "2 green (X) + 1 pink (Y) signals per cell", "Confirms 47, XXY"),
("Primary infertility", "Azoospermia", "Hyalinised seminiferous tubules"),
("Gynecomastia", "Bilateral breast enlargement in male", "High oestrogen:testosterone ratio"),
("Tall stature", "Above average height", "Delayed epiphyseal closure"),
],
diagnosis="Klinefelter Syndrome (47, XXY)",
answer=[
"Karyotype: 47, XXY – one extra X chromosome. Most common sex chromosome aneuploidy (1:500–1000 males). Arises from non-disjunction (50% paternal, 50% maternal). FISH confirms 2 green X signals + 1 pink Y per cell.",
"Pathophysiology of features: (1) INFERTILITY/AZOOSPERMIA – hyalinisation and fibrosis of seminiferous tubules → no sperm production. Testes small and firm. (2) GYNECOMASTIA – low testosterone + peripheral conversion of androgens to oestrogens → elevated oestrogen:testosterone ratio → breast tissue proliferation. (3) TALL STATURE – testosterone is needed for epiphyseal closure. Low testosterone → delayed fusion → longer legs/arms. (4) Sparse body/facial hair, reduced libido.",
"Testosterone is low; FSH and LH are elevated (hypergonadotrophic hypogonadism).",
"Cognitive effects: Mild intellectual disability, language difficulties, reading/learning problems (variable).",
"Associated risks: Breast cancer in males (20–50× increased risk), mediastinal germ cell tumours.",
"Treatment: Testosterone replacement therapy (injection, gel, or patch) from puberty – improves virilisation, bone density, mood, sexual function. Does NOT restore fertility. Assisted reproduction (TESE – testicular sperm extraction) possible in some.",
]
),
# GTT CASES
dict(
case="GTT Case 1 – Diabetic Glucose Tolerance Curve",
section="GLUCOSE TOLERANCE TEST (GTT) – INTERPRETATION",
question=[
"Q1. What does this GTT curve indicate?",
"Q2. How do you diagnose diabetes from GTT?",
],
findings=[
("Fasting (0 hr)", "190 mg/dL", "≥126 = DIABETIC"),
("½ hr", "225 mg/dL", "Rising"),
("1 hr (peak)", "280 mg/dL", "Far above threshold"),
("2 hr", "220 mg/dL", "≥200 = DIABETIC confirmed"),
("2½ hr", "170 mg/dL", "Still not normalized"),
("Urine sugar", "++ to +++ from ½ hr", "Glycosuria throughout"),
],
diagnosis="Diabetes Mellitus",
answer=[
"WHO GTT diagnostic criteria: DIABETES = Fasting ≥126 mg/dL OR 2-hour value ≥200 mg/dL after 75g glucose load. Both criteria met here (fasting 190, 2hr 220).",
"Interpretation: The fasting glucose is already diabetic. The curve rises steeply and fails to normalize – remaining >180 at 2½ hrs. This shows profoundly impaired glucose disposal (insulin resistance/deficiency).",
"Glycosuria from ½ hr through 2½ hr = blood glucose exceeded renal threshold (180 mg/dL) for almost the entire duration.",
"Renal threshold: Blood glucose at which glucose appears in urine. Normally ~180 mg/dL (when tubular reabsorption capacity is overwhelmed). In diabetes, it is exceeded due to persistent hyperglycaemia.",
"GTT is indicated for: Screening, diagnosis of borderline cases, gestational diabetes (75g OGTT), and research. Not needed when random glucose >200 with symptoms.",
]
),
dict(
case="GTT Case 2 – Normal Glucose Tolerance Curve",
section="GLUCOSE TOLERANCE TEST (GTT) – INTERPRETATION",
question=[
"Q1. Is this a normal GTT? Explain.",
"Q2. Why is there mild glycosuria despite blood glucose staying below 180?",
],
findings=[
("Fasting", "90 mg/dL", "Normal (<100)"),
("1 hr (peak)", "139 mg/dL", "Below 180 threshold"),
("2 hr", "90 mg/dL", "Fully normalized"),
("Urine sugar", "+/Trace at most time points", "Very mild"),
],
diagnosis="Normal Glucose Tolerance",
answer=[
"This is a NORMAL GTT: Fasting <100, 2-hr value <140 (here 90). The curve peaks below 180 mg/dL and returns completely to baseline by 2 hours. Normal insulin secretion and sensitivity.",
"Mild trace glycosuria despite blood glucose <180: Individual variation in renal threshold exists. Some people have a slightly lower threshold (~160–170 mg/dL) = 'renal glycosuria' tendency or simply borderline threshold. This is NOT diagnostic of diabetes.",
"The 75g glucose load is a standardized stress test. A normal pancreas secretes enough insulin to bring glucose back to baseline within 2 hours.",
"Prediabetes (Impaired Glucose Tolerance): Fasting 100–125 OR 2-hr 140–199. Neither criterion is met here.",
]
),
dict(
case="GTT Case 3 – Normal GTT with Reactive Hypoglycaemia",
section="GLUCOSE TOLERANCE TEST (GTT) – INTERPRETATION",
question=[
"Q1. Interpret this GTT curve.",
"Q2. What is reactive hypoglycaemia?",
],
findings=[
("Fasting", "75 mg/dL", "Normal"),
("1 hr (peak)", "150 mg/dL", "Below threshold"),
("2 hr", "76 mg/dL", "Normal"),
("2½ hr", "65 mg/dL", "Slightly LOW"),
("Urine sugar", "Nil all time points", "Normal – never exceeded 180"),
],
diagnosis="Normal GTT with Mild Reactive Hypoglycaemia",
answer=[
"Normal GTT criteria met: Fasting <100, peak <180, 2-hr <140. No glycosuria at any point.",
"The drop to 65 mg/dL at 2½ hrs = mild REACTIVE (postprandial) HYPOGLYCAEMIA. After a glucose load, an exaggerated insulin response overshoots, driving blood glucose below normal (~70 mg/dL).",
"Reactive hypoglycaemia: Symptoms may include sweating, tremor, palpitations, anxiety at 2–3 hrs post-meal. Can occur in early type 2 diabetes (exaggerated but delayed insulin response), post-gastrectomy (dumping syndrome), or idiopathically.",
"No glycosuria: Blood glucose never crossed 180 throughout the test – confirms normal renal tubular reabsorption.",
]
),
dict(
case="GTT Case 4 – Comparison: Renal Glycosuria (Curve A) vs. Lag Storage Curve (Curve B)",
section="GLUCOSE TOLERANCE TEST (GTT) – INTERPRETATION",
question=[
"Q1. Interpret Curve A.",
"Q2. Interpret Curve B.",
"Q3. How do both differ from diabetes?",
],
findings=[
("Curve A – Blood sugar", "90 → 130 → 140 → 115 → 90 → 90", "Entirely NORMAL (<180)"),
("Curve A – Urine sugar", "Nil → + → + → + → + → +", "PERSISTENT glycosuria despite normal blood sugar"),
("Curve B – Blood sugar", "80 → 225 → 185 → 115 → 85 → 70", "Early peak >180, rapid normalization"),
("Curve B – Urine sugar", "Nil → + → + → Nil → Nil → Nil", "Transient glycosuria only early"),
],
diagnosis="Curve A = Renal Glycosuria | Curve B = Lag Storage Curve (Alimentary Hyperglycaemia)",
answer=[
"CURVE A – RENAL GLYCOSURIA: Blood sugar stays ENTIRELY below 180 throughout, yet urine shows persistent glycosuria from ½hr to 2½hr. The renal tubular threshold for glucose reabsorption is ABNORMALLY LOW (due to SGLT2 transporter defect). Glucose spills into urine even at normal blood levels. This is a BENIGN condition – NOT diabetes. No treatment needed. Important to distinguish from diabetes in clinical practice (urine sugar alone can be misleading).",
"CURVE B – LAG STORAGE CURVE (Alimentary Hyperglycaemia): Blood sugar peaks VERY EARLY (at ½hr to 225 mg/dL) due to rapid gastric emptying → rapid intestinal absorption. Then glucose RAPIDLY falls back to normal by 1½ hrs. The 2-hr value is normal (<140). Brief transient glycosuria at ½hr and 1hr (when >180), then nil. Causes: Post-gastrectomy (Roux-en-Y, vagotomy), hyperthyroidism (rapid GI motility), hepatic glycogen storage defect.",
"Both conditions are NON-DIABETIC. Diabetes has sustained hyperglycaemia throughout (especially 2-hr ≥200). These curves are important differential diagnoses in patients with glycosuria.",
]
),
dict(
case="GTT Case 5 – Lag Storage Curve (Single)",
section="GLUCOSE TOLERANCE TEST (GTT) – INTERPRETATION",
question=[
"Q1. What pattern does this GTT show?",
"Q2. What conditions produce this pattern?",
],
findings=[
("Fasting", "80 mg/dL", "Normal"),
("½ hr (early peak)", "220 mg/dL", "Very high early spike – >180"),
("1 hr", "190 mg/dL", "Still above 180"),
("1½ hr", "110 mg/dL", "Rapidly falling"),
("2 hr", "80 mg/dL", "FULLY NORMALIZED – not diabetic"),
("2½ hr", "65 mg/dL", "Mild reactive dip"),
("Urine sugar", "++ at ½hr, +++ at 1hr, then Nil", "Transient glycosuria only"),
],
diagnosis="Lag Storage Curve (Alimentary Hyperglycaemia / Post-Gastrectomy Pattern)",
answer=[
"Classic LAG STORAGE CURVE: Normal fasting → sudden steep early peak (½hr = 220) → rapid fall → full normalization at 2hrs (80 mg/dL). The 2-hr value is completely normal. This is NOT diabetes.",
"Glycosuria transiently at ½hr and 1hr = blood glucose briefly exceeded 180 (renal threshold), then disappeared as glucose normalized.",
"Mechanism: Rapid gastric emptying → glucose floods intestine → rapid absorption → blood glucose spikes early → pancreas responds with insulin → rapid clearance.",
"Conditions causing lag curve: (1) Post-gastrectomy (surgery removes pylorus → rapid emptying), (2) Hyperthyroidism (increased GI motility), (3) Hepatic glycogen storage defects (glucose not stored as glycogen → rapid peripheral rise), (4) Idiopathic accelerated gastric emptying.",
"Management: Dietary modification (small frequent meals, reduced rapid sugars). Acarbose (alpha-glucosidase inhibitor) can blunt the early spike post-gastrectomy.",
]
),
] # end part2_cases
# ── BUILD FLOWABLES ──────────────────────────────────────────────────────────
story = []
# ── COVER PAGE ───────────────────────────────────────────────────────────────
story.append(Spacer(1, 3*cm))
story.append(P("PATHOLOGY CHARTS", cover_title))
story.append(P("Question & Answer Study Guide", cover_sub))
story.append(Spacer(1, 0.5*cm))
story.append(P("Part 1 & Part 2 Combined", cover_sub))
story.append(Spacer(1, 1*cm))
story.append(HRFlowable(width="60%", thickness=2, color=TEAL, hAlign="CENTER"))
story.append(Spacer(1, 0.5*cm))
story.append(P("Dr. Smrutirekha Behera", cover_author))
story.append(P("Asst. Professor, Pathology", cover_author))
story.append(Spacer(1, 2*cm))
# Summary box on cover
cover_data = [
[Paragraph("<b>Total Cases</b>", table_header_style),
Paragraph("<b>Topics Covered</b>", table_header_style)],
[Paragraph("39 Clinical Cases", table_cell_style),
Paragraph("Haematology, Oncology, Nephrology, Infectious Disease,\nEndocrinology, Neurology, Genetics, Biochemistry", table_cell_style)],
]
cover_tbl = Table(cover_data, colWidths=[5*cm, 12*cm])
cover_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("BACKGROUND", (0,1), (-1,1), LIGHT_BLUE),
("GRID", (0,0), (-1,-1), 0.5, colors.grey),
("ALIGN", (0,0), (-1,-1), "CENTER"),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
]))
story.append(cover_tbl)
story.append(PageBreak())
def add_part_header(title):
story.append(Spacer(1, 0.5*cm))
data = [[Paragraph(title, ParagraphStyle("ph", parent=styles["Normal"],
fontSize=16, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER))]]
t = Table(data, colWidths=[doc.width])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("TOPPADDING", (0,0), (-1,-1), 10),
("BOTTOMPADDING", (0,0), (-1,-1), 10),
]))
story.append(t)
story.append(BB())
def add_case(c, case_num, part):
elems = []
# Case title bar
label = f"PART {part} | CASE {case_num}"
data = [[Paragraph(label, ParagraphStyle("cl", parent=styles["Normal"],
fontSize=10, textColor=GOLD, fontName="Helvetica-Bold",
alignment=TA_LEFT)),
Paragraph(c["section"], ParagraphStyle("cs", parent=styles["Normal"],
fontSize=10, textColor=WHITE, fontName="Helvetica-BoldOblique",
alignment=TA_LEFT))]]
t = Table(data, colWidths=[4*cm, doc.width - 4*cm])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
]))
elems.append(t)
elems.append(B())
# Case subtitle
elems.append(P(c["case"], case_title))
elems.append(B())
# Questions
for q in c["question"]:
elems.append(P(q, q_style))
elems.append(B())
HR_elem = HRFlowable(width="100%", thickness=0.5, color=colors.grey, spaceAfter=4, spaceBefore=4)
elems.append(HR_elem)
# Findings table
if c.get("findings"):
elems.append(P("Key Findings:", ParagraphStyle("kf", parent=styles["Normal"],
fontSize=10, textColor=TEAL, fontName="Helvetica-Bold", spaceBefore=4, spaceAfter=4)))
f_data = [[
Paragraph("<b>Parameter</b>", ParagraphStyle("fh", parent=styles["Normal"],
fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
Paragraph("<b>Value</b>", ParagraphStyle("fh", parent=styles["Normal"],
fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
Paragraph("<b>Interpretation</b>", ParagraphStyle("fh", parent=styles["Normal"],
fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
]]
for row in c["findings"]:
f_data.append([
Paragraph(str(row[0]), ParagraphStyle("fc", parent=styles["Normal"],
fontSize=9, fontName="Helvetica-Bold", leftIndent=2)),
Paragraph(str(row[1]), ParagraphStyle("fc", parent=styles["Normal"],
fontSize=9, fontName="Helvetica", alignment=TA_CENTER)),
Paragraph(str(row[2]), ParagraphStyle("fc", parent=styles["Normal"],
fontSize=9, fontName="Helvetica-Oblique", alignment=TA_CENTER, textColor=TEAL)),
])
ft = Table(f_data, colWidths=[5.5*cm, 5.5*cm, doc.width - 11*cm])
ft.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("ROWBACKGROUNDS", (0,1), (-1,-1), [LIGHT_BLUE, WHITE]),
("GRID", (0,0), (-1,-1), 0.5, colors.lightgrey),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
]))
elems.append(ft)
elems.append(B())
# Diagnosis banner
diag_data = [[
Paragraph("DIAGNOSIS:", ParagraphStyle("db1", parent=styles["Normal"],
fontSize=11, textColor=GOLD, fontName="Helvetica-Bold")),
Paragraph(c["diagnosis"], ParagraphStyle("db2", parent=styles["Normal"],
fontSize=11, textColor=WHITE, fontName="Helvetica-Bold")),
]]
dt = Table(diag_data, colWidths=[3.5*cm, doc.width - 3.5*cm])
dt.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), PURPLE),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (0,-1), 8),
("LEFTPADDING", (1,0), (1,-1), 4),
]))
elems.append(dt)
elems.append(B())
# Answers
elems.append(P("ANSWER / EXPLANATION:", ParagraphStyle("ah", parent=styles["Normal"],
fontSize=10, textColor=TEAL, fontName="Helvetica-Bold", spaceBefore=4, spaceAfter=4)))
for i, ans in enumerate(c["answer"], 1):
bullet_data = [[
Paragraph(f"{i}.", ParagraphStyle("bn", parent=styles["Normal"],
fontSize=10, textColor=PURPLE, fontName="Helvetica-Bold",
alignment=TA_CENTER)),
Paragraph(ans, a_style),
]]
bt = Table(bullet_data, colWidths=[0.7*cm, doc.width - 0.7*cm])
bt.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 2),
("BOTTOMPADDING", (0,0), (-1,-1), 2),
("LEFTPADDING", (0,0), (0,-1), 4),
]))
elems.append(bt)
elems.append(Spacer(1, 0.4*cm))
elems.append(HRFlowable(width="100%", thickness=1.5, color=NAVY, spaceAfter=10, spaceBefore=4))
story.extend(elems)
# ── ADD PART 1 ───────────────────────────────────────────────────────────────
add_part_header("CHARTS PART 1")
for i, case in enumerate(part1_cases, 1):
add_case(case, i, 1)
if i < len(part1_cases):
story.append(PageBreak())
story.append(PageBreak())
# ── ADD PART 2 ───────────────────────────────────────────────────────────────
add_part_header("CHARTS PART 2")
for i, case in enumerate(part2_cases, 1):
add_case(case, i, 2)
if i < len(part2_cases):
story.append(PageBreak())
# ── BUILD PDF ────────────────────────────────────────────────────────────────
def on_page(canvas, doc):
canvas.saveState()
# Footer
canvas.setFont("Helvetica", 8)
canvas.setFillColor(colors.grey)
canvas.drawString(2*cm, 1.2*cm, "Pathology Charts Q&A – Dr. Smrutirekha Behera")
canvas.drawRightString(doc.pagesize[0] - 2*cm, 1.2*cm, f"Page {doc.page}")
# Top border
canvas.setStrokeColor(NAVY)
canvas.setLineWidth(2)
canvas.line(2*cm, doc.pagesize[1] - 1.5*cm, doc.pagesize[0] - 2*cm, doc.pagesize[1] - 1.5*cm)
canvas.restoreState()
doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
print(f"PDF created: {OUTPUT}")