~/make_compact_pdf.py
#!/usr/bin/env python3
"""
Generate a compact quick-revision PDF from the pathology content.
Uses ReportLab with small fonts, tight spacing, 2-column layout.
"""
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm
from reportlab.lib.styles import ParagraphStyle
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_LEFT, TA_CENTER
from reportlab.pdfbase import pdfmetrics
from reportlab.platypus.flowables import BalancedColumns
PAGE_W, PAGE_H = A4
MARGIN = 10 * mm
# ── Styles ──────────────────────────────────────────────────────────────────
def make_styles():
h1 = ParagraphStyle('H1', fontName='Helvetica-Bold', fontSize=9,
textColor=colors.white, backColor=colors.HexColor('#1a3a5c'),
spaceBefore=3, spaceAfter=1, leading=11,
leftIndent=2, rightIndent=2)
h2 = ParagraphStyle('H2', fontName='Helvetica-Bold', fontSize=8,
textColor=colors.HexColor('#1a3a5c'),
spaceBefore=2, spaceAfter=1, leading=10,
borderPad=1)
h3 = ParagraphStyle('H3', fontName='Helvetica-Bold', fontSize=7.5,
textColor=colors.HexColor('#c0392b'),
spaceBefore=1, spaceAfter=0, leading=9)
body = ParagraphStyle('Body', fontName='Helvetica', fontSize=7,
spaceBefore=0, spaceAfter=0, leading=9,
leftIndent=4)
bullet = ParagraphStyle('Bullet', fontName='Helvetica', fontSize=7,
spaceBefore=0, spaceAfter=0, leading=9,
leftIndent=8, bulletIndent=4)
label = ParagraphStyle('Label', fontName='Helvetica-Bold', fontSize=7,
spaceBefore=0, spaceAfter=0, leading=9,
textColor=colors.HexColor('#2c3e50'))
note = ParagraphStyle('Note', fontName='Helvetica-Oblique', fontSize=6.5,
textColor=colors.HexColor('#555555'),
spaceBefore=0, spaceAfter=0, leading=8)
return h1, h2, h3, body, bullet, label, note
H1, H2, H3, BODY, BULLET, LABEL, NOTE = make_styles()
def sec(title):
"""Section header (system heading)."""
return [Paragraph(f" {title}", H1), Spacer(1, 1)]
def sub(title):
return [Paragraph(title, H2)]
def q(title):
return Paragraph(f"► {title}", H3)
def p(text):
return Paragraph(text, BODY)
def b(text):
return Paragraph(f"• {text}", BULLET)
def lbl(k, v):
return Paragraph(f"<b>{k}:</b> {v}", BODY)
def hr():
return HRFlowable(width="100%", thickness=0.3, color=colors.HexColor('#aaaaaa'),
spaceAfter=1, spaceBefore=1)
def tbl(headers, rows, col_widths=None):
"""Build a compact table."""
W = PAGE_W - 2 * MARGIN
if col_widths is None:
n = len(headers)
col_widths = [W / n] * n
data = [headers] + rows
t = Table(data, colWidths=col_widths, repeatRows=1)
style = TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#2c3e50')),
('TEXTCOLOR', (0, 0), (-1, 0), colors.white),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('FONTSIZE', (0, 0), (-1, -1), 6.5),
('LEADING', (0, 0), (-1, -1), 8),
('ROWBACKGROUNDS', (0, 1), (-1, -1), [colors.HexColor('#f4f6f9'), colors.white]),
('GRID', (0, 0), (-1, -1), 0.3, colors.HexColor('#cccccc')),
('TOPPADDING', (0, 0), (-1, -1), 1.5),
('BOTTOMPADDING', (0, 0), (-1, -1), 1.5),
('LEFTPADDING', (0, 0), (-1, -1), 2),
('RIGHTPADDING', (0, 0), (-1, -1), 2),
('VALIGN', (0, 0), (-1, -1), 'TOP'),
])
t.setStyle(style)
return t
def sp(h=2):
return Spacer(1, h)
# ── Content ─────────────────────────────────────────────────────────────────
def build_story():
story = []
W = PAGE_W - 2 * MARGIN
# ── TITLE ──
story.append(Paragraph(
"<b>PATHOLOGY QUICK REVISION</b> | Robbins & Cotran",
ParagraphStyle('Title', fontName='Helvetica-Bold', fontSize=11,
alignment=TA_CENTER, textColor=colors.HexColor('#1a3a5c'),
spaceBefore=0, spaceAfter=2)
))
story.append(HRFlowable(width="100%", thickness=1, color=colors.HexColor('#1a3a5c'),
spaceAfter=3))
# ══════════════════════════════════════════════════════════════════════
# 1. MALE REPRODUCTIVE SYSTEM
# ══════════════════════════════════════════════════════════════════════
story += sec("1. MALE REPRODUCTIVE SYSTEM")
story += [q("Teratoma of Testis"), sp(1)]
story += [
lbl("Def", "GCT with tissues from all 3 germ layers; benign in children <2 yr, malignant in adults"),
lbl("Gross", "Large lobulated mass; multicystic spaces (mucoid/keratin/hair); hemorrhage + necrosis"),
lbl("Micro", "Mature: skin, cartilage, bone, neural tissue haphazardly arranged"),
lbl("", "Immature: primitive neuroectodermal tissue, fetal cartilage"),
sp(2)
]
story += [q("Seminoma"), sp(1)]
story += [
lbl("Gross", "Most common GCT (40-50%); homogeneous gray-white 'fish-flesh'; NO hemorrhage/necrosis; tunica intact"),
lbl("Micro", "Large round cells, clear glycogen-rich cytoplasm, 'fried egg'; fibrous septa; lymphocytic infiltrate; granulomas 20%"),
lbl("Markers", "PLAP+, CD117+; β-hCG occasionally (syncytiotrophoblasts)"),
lbl("Spread", "Lymphatic → para-aortic nodes (L1-L2) FIRST; then hematogenous (lung, liver, bone)"),
lbl("Prognosis", "Radiosensitive; excellent 5-yr survival >95%"),
sp(2)
]
story.append(q("Classification of Testicular Tumors"))
story.append(sp(1))
story.append(tbl(
['Type', 'Subtypes / Notes'],
[
['GCT 95%', 'Seminoma (classical, spermatocytic)'],
['NSGCT', 'Embryonal Ca, Yolk sac tumor (AFP↑), Choriocarcinoma (β-hCG↑), Teratoma, Mixed GCT'],
['Sex cord-stromal 4-5%', 'Leydig cell (most common), Sertoli cell'],
['Other', 'Lymphoma (most common in men >60 yr), Metastases'],
],
[W*0.28, W*0.72]
))
story.append(sp(2))
story += [q("Yolk Sac Tumor (Endodermal Sinus Tumor)"), sp(1)]
story += [
lbl("Who", "Most common GCT in infants/children; AFP markedly elevated"),
lbl("Micro", "Schiller-Duval bodies (perivascular pseudorosettes); PAS+ hyaline globules (AFP-containing)"),
sp(2)
]
story += [q("Extragonadal Teratoma Sites"), sp(1)]
story += [b("Anterior mediastinum (most common), Retroperitoneum, Sacrococcygeal (neonates), Pineal, Base of skull"), sp(2)]
story.append(hr())
# ══════════════════════════════════════════════════════════════════════
# 2. FEMALE GENITAL TRACT
# ══════════════════════════════════════════════════════════════════════
story += sec("2. FEMALE GENITAL TRACT")
story += [q("Fibroid Uterus (Leiomyoma)"), sp(1)]
story += [
lbl("Gross", "Multiple firm rubbery whorled nodules; pseudocapsule; locations: intramural > subserosal > submucosal"),
lbl("Micro", "Interlacing fascicles of smooth muscle, cigar-shaped nuclei, no mitoses; hyalinization"),
lbl("Degen.", "Hyaline (most common) > Cystic > Calcific > Red/carneous (pregnancy) > Myxoid"),
]
story.append(tbl(
['Complication', 'Details'],
[
['Menorrhagia', 'Most common symptom → anemia'],
['Pressure symptoms', 'Urinary frequency, constipation'],
['Pregnancy', 'Infertility, preterm, obstructed labor, red degeneration'],
['Malignant change', 'Leiomyosarcoma <1% (rare)'],
],
[W*0.3, W*0.7]
))
story.append(sp(2))
story += [q("Dysgerminoma (Ovarian GCT)"), sp(1)]
story += [
lbl("Def", "Counterpart of testicular seminoma; most common malignant GCT of ovary; young women"),
lbl("Gross", "Solid, lobulated, gray-white; unilateral 90%"),
lbl("Micro", "Large clear cells with glycogen; fibrous septa + lymphocytic infiltrate (identical to seminoma)"),
lbl("Markers", "LDH↑, Placental ALP↑"),
lbl("Prognosis", "Radiosensitive; 5-yr survival >90%"),
sp(2)
]
story.append(hr())
# ══════════════════════════════════════════════════════════════════════
# 3. BREAST
# ══════════════════════════════════════════════════════════════════════
story += sec("3. BREAST")
story += [q("Fibroadenoma"), sp(1)]
story += [
lbl("Who", "Most common benign tumor <35 yr; solitary, mobile 'breast mouse'"),
lbl("Gross", "Firm, rubbery, encapsulated, glistening gray-white; clefts on cut section"),
lbl("Micro", "Intracanalicular: stroma compresses ducts → slit-like; Pericanalicular: stroma around open rounded ducts"),
sp(2)
]
story += [q("Prognostic & Predictive Factors in Breast Carcinoma"), sp(1)]
story.append(tbl(
['Factor', 'Type', 'Notes'],
[
['LN status', 'Prognostic', 'Single most important prognostic factor'],
['Tumor size', 'Prognostic', ''],
['Grade (SBR)', 'Prognostic', 'Tubule + nuclear pleomorphism + mitoses'],
['LVI', 'Prognostic', 'Lymphovascular invasion'],
['ER/PR status', 'Predictive', 'Response to tamoxifen/aromatase inhibitors'],
['HER2/neu', 'Predictive', 'Response to trastuzumab (Herceptin)'],
['Ki-67', 'Predictive', 'Proliferation index; high = aggressive'],
],
[W*0.3, W*0.2, W*0.5]
))
story.append(sp(1))
story.append(tbl(
['Subtype', 'ER', 'PR', 'HER2', 'Prognosis'],
[
['Luminal A', '+', '+', '-', 'Best'],
['Luminal B', '+', '+', '+/-', 'Intermediate'],
['HER2-enriched', '-', '-', '+', 'Poor (↑ with Rx)'],
['Triple Negative (TNBC)', '-', '-', '-', 'Worst'],
],
[W*0.32, W*0.12, W*0.12, W*0.12, W*0.32]
))
story.append(sp(2))
story += [q("Invasive Ductal Carcinoma (NST) - LAQ"), sp(1)]
story += [
lbl("Frequency", "70-80% of all breast carcinomas"),
lbl("Gross", "Firm gritty irregular stellate mass; chalky white streaks (elastosis); retracts on cut – 'scirrhous'"),
lbl("Micro", "Cords/nests/trabeculae of malignant cells; desmoplastic stroma; variable tubule formation"),
lbl("Grading (SBR/Nottingham)", "Score 3-9: G1 (3-5), G2 (6-7), G3 (8-9)"),
lbl("Spread", "Axillary LN → lung → bone → liver → brain"),
]
story.append(sp(2))
story.append(hr())
# ══════════════════════════════════════════════════════════════════════
# 4. SKIN
# ══════════════════════════════════════════════════════════════════════
story += sec("4. SKIN")
story += [q("Squamous Cell Carcinoma of Skin"), sp(1)]
story += [
lbl("Pathogenesis", "UVB → pyrimidine dimers → p53 mutation; chronic scars (Marjolin's ulcer); HPV 16/18; arsenics; XP"),
lbl("Precursor", "Actinic keratosis"),
lbl("Gross", "Ulcerated indurated nodule, everted edges; sun-exposed sites"),
lbl("Micro", "Malignant keratinocytes invading dermis; CANCER PEARLS (keratin pearls); intercellular bridges; individual dyskeratosis"),
sp(2)
]
story += [q("Melanoma of Skin"), sp(1)]
story.append(tbl(
['Type', 'Feature', 'Prognosis'],
[
['Superficial spreading', 'Most common (70%); pagetoid spread', 'Good if caught early'],
['Lentigo maligna', 'Elderly, sun-exposed face; long radial phase', 'Best'],
['Nodular', 'No radial phase; vertical growth from onset', 'Worst'],
['Acral lentiginous', 'Palms/soles/nails; dark-skinned persons', 'Variable'],
],
[W*0.3, W*0.45, W*0.25]
))
story += [
sp(1),
lbl("Key prognostic factor", "Breslow thickness (depth in mm) – most important"),
lbl("ABCDE", "Asymmetry, Border irregular, Color variegated, Diameter >6mm, Evolution"),
lbl("Mutation", "BRAF V600E 60% → targeted by vemurafenib"),
sp(2)
]
story.append(hr())
# ══════════════════════════════════════════════════════════════════════
# 5. ENDOCRINE SYSTEM
# ══════════════════════════════════════════════════════════════════════
story += sec("5. ENDOCRINE SYSTEM")
story += [q("MEN Syndromes"), sp(1)]
story.append(tbl(
['Feature', 'MEN 1 (Wermer)', 'MEN 2A (Sipple)', 'MEN 2B'],
[
['Gene', 'MEN1 (menin, chr 11)', 'RET', 'RET'],
['Parathyroid', 'Hyperplasia/adenoma 95%', 'Hyperplasia 50%', 'Absent'],
['Pancreas', 'Gastrinoma, insulinoma', '-', '-'],
['Pituitary', 'Adenoma (prolactinoma)', '-', '-'],
['Thyroid', '-', 'Medullary Ca 100%', 'Medullary Ca 100%'],
['Adrenal', '-', 'Pheo 50%', 'Pheo'],
['Other', '-', '-', 'Mucosal neuromas, marfanoid'],
],
[W*0.24, W*0.26, W*0.26, W*0.24]
))
story.append(sp(2))
story += [q("OGTT - Indications & Interpretation"), sp(1)]
story += [
lbl("Indications", "GDM screening; borderline FPG (100-125); IGT workup; high-risk (obesity, FH, PCOS, prev GDM)"),
lbl("Method", "75g glucose after 8-10 hr fast; measure FPG + 2-hr post-load"),
]
story.append(tbl(
['Category', 'Fasting (mg/dL)', '2-hr post-load (mg/dL)'],
[
['Normal', '<100', '<140'],
['IFG', '100-125', '-'],
['IGT', '-', '140-199'],
['Diabetes', '≥126', '≥200'],
],
[W*0.4, W*0.3, W*0.3]
))
story.append(sp(2))
story += [q("Thyroid Tumors Classification"), sp(1)]
story.append(tbl(
['Type', 'Cell', 'Key Feature', 'Prognosis'],
[
['Papillary Ca (80-85%)', 'Follicular', "Orphan Annie nuclei, psammoma bodies, 'ground-glass'", 'Excellent'],
['Follicular Ca', 'Follicular', 'Vascular + capsular invasion; RAS/PAX8-PPARγ', 'Good'],
['Medullary Ca', 'C-cells', 'Calcitonin↑; amyloid stroma; MEN2', 'Moderate'],
['Anaplastic Ca', 'Dediff.', 'Rapid growth; most aggressive', 'Worst'],
],
[W*0.28, W*0.15, W*0.37, W*0.2]
))
story += [
sp(1),
lbl("Colloid Goitre", "Iodine deficiency; large colloid-filled follicles lined by flat inactive epithelium; gelatinous brown gross appearance"),
sp(2)
]
story += [q("HbA1c (Glycosylated Hemoglobin)"), sp(1)]
story += [
lbl("Def", "Glucose irreversibly attached to N-terminal valine of Hb-β chain; reflects mean glucose over 2-3 months"),
lbl("Values", "Normal <5.7% | Pre-DM 5.7-6.4% | DM ≥6.5% | Target in DM <7%"),
lbl("False LOW", "Hemolytic anemia, pregnancy, blood transfusion"),
lbl("False HIGH", "Iron deficiency anemia, splenectomy"),
sp(2)
]
story += [q("Hashimoto's Thyroiditis"), sp(1)]
story += [
lbl("Gross", "Diffusely enlarged, firm, rubbery, pale, lobulated; capsule intact"),
lbl("Micro", "Lymphocytic infiltration + germinal centers; Hurthle (oxyphilic) cell change; atrophic follicles with scant colloid; late fibrosis"),
lbl("Path", "Anti-TPO + anti-thyroglobulin Ab; CD8+ T-cell mediated destruction"),
lbl("Complications", "Hypothyroidism (main outcome); Primary thyroid MALT lymphoma; slight↑ risk papillary Ca"),
sp(2)
]
story += [q("Diabetes Mellitus – LAQ"), sp(1)]
story += [
lbl("Diagnostic criteria (any one)", "FPG ≥126 | 2-hr OGTT ≥200 | Random ≥200 + symptoms | HbA1c ≥6.5%"),
]
story.append(tbl(
['Type', 'Mechanism', 'Key Features'],
[
['Type 1', 'Autoimmune β-cell destruction', 'HLA-DR3/DR4; anti-islet Ab; absolute deficiency; ketosis-prone; young'],
['Type 2', 'Insulin resistance + relative deficiency', 'Obesity; multifactorial; 90-95% of DM'],
['MODY', 'Monogenic AD', 'Young lean; multiple types (HNF, GCK mutations)'],
['Secondary', 'Various', 'Pancreatitis, hemochromatosis, Cushing, acromegaly, drugs'],
],
[W*0.18, W*0.32, W*0.5]
))
story += [
sp(1),
lbl("Kimmelstiel-Wilson (DM nephropathy)",
"Diffuse glomerulosclerosis (common) + Nodular glomerulosclerosis (pathognomonic ovoid K-W nodules); "
"GBM thickening (earliest); efferent AND afferent arteriolar hyalinosis (DM-specific); → ESRD"),
sp(2)
]
story.append(hr())
# ══════════════════════════════════════════════════════════════════════
# 6. MUSCULOSKELETAL
# ══════════════════════════════════════════════════════════════════════
story += sec("6. MUSCULOSKELETAL SYSTEM")
story += [q("Osteosarcoma (Osteogenic Sarcoma)"), sp(1)]
story += [
lbl("Site", "Distal femur metaphysis > proximal tibia > proximal humerus; age 10-20 yr (2nd peak: elderly + Paget)"),
lbl("X-ray", "Codman's triangle (periosteal elevation) + Sunburst pattern; mixed lytic/sclerotic"),
lbl("Gross", "Gritty gray-white mass in metaphysis; destroys cortex; soft tissue extension"),
lbl("Micro", "MALIGNANT OSTEOID laid by pleomorphic sarcomatous cells = HALLMARK; giant cells; variable cartilage/fibrous areas"),
lbl("Subtypes", "Osteoblastic (most common), Chondroblastic, Fibroblastic, Telangiectatic"),
lbl("Markers", "ALP↑, LDH↑"),
lbl("Treatment", "Surgery + neoadjuvant chemotherapy; 5-yr survival ~65-70%"),
sp(2)
]
story += [q("Rheumatoid Arthritis"), sp(1)]
story += [
lbl("Key lesion", "PANNUS = granulation tissue of synovium invading/destroying articular cartilage and bone"),
lbl("Stages", "Synovial edema (neutrophils) → Synovial hyperplasia (lymphocytes, plasma cells) → Pannus formation → Fibrous/bony ankylosis"),
lbl("Micro", "Synovial lining hyperplasia; lymphoid follicles; fibrinous exudate; neovascularization"),
lbl("RA nodule", "Central fibrinoid necrosis + palisading macrophages + outer fibrosis (subcut, lung, heart)"),
sp(2)
]
story += [q("Osteomyelitis"), sp(1)]
story += [
lbl("Causative organisms", "S. aureus (most common) | Salmonella (sickle cell) | H. influenzae (<2 yr) | Pseudomonas (IVDU)"),
lbl("Gross terms", "Sequestrum (dead bone) | Involucrum (reactive new bone sheath) | Cloaca (pus drainage opening) | Subperiosteal abscess"),
lbl("Micro", "Acute: neutrophil infiltration, vascular congestion, necrosis | Chronic: lymphocytes, plasma cells, fibrosis"),
lbl("Complications", "Septicemia, pathological #, secondary amyloidosis (AA), osteosarcoma in chronic OM, Brodie's abscess"),
sp(2)
]
story.append(hr())
# ══════════════════════════════════════════════════════════════════════
# 7. NERVOUS SYSTEM
# ══════════════════════════════════════════════════════════════════════
story += sec("7. NERVOUS SYSTEM")
story += [q("CSF Differences – Meningitis"), sp(1)]
story.append(tbl(
['Feature', 'Pyogenic (Bacterial)', 'Tuberculous', 'Viral'],
[
['Appearance', 'Turbid/purulent', 'Clear, cobweb clot', 'Clear'],
['Pressure', 'Markedly raised', 'Moderately raised', 'Normal/mild'],
['Cells', 'Neutrophils (100s-1000s)', 'Lymphocytes (100-500)', 'Lymphocytes (100-500)'],
['Protein', 'Markedly raised (>100)', 'Raised (100-500)', 'Normal/mild'],
['Glucose', 'Very low (<40)', 'Low', 'Normal'],
['Chloride', 'Decreased', 'Markedly decreased', 'Normal'],
['Other', 'Gram stain/culture +', 'ZN stain; ADA >10 U/L', 'PCR for virus'],
],
[W*0.2, W*0.27, W*0.27, W*0.26]
))
story.append(sp(2))
story += [q("Meningioma"), sp(1)]
story += [
lbl("Origin", "Meningothelial (arachnoid cap) cells"),
lbl("Sites", "Parasagittal, sphenoid wing, olfactory groove, CPA"),
lbl("Gross", "Well-circumscribed, lobulated, rubbery, gray-white; attached to dura ('dural tail'); compresses not invades brain"),
lbl("Micro", "Syncytial whorls of meningothelial cells; PSAMMOMA BODIES (concentric calcifications) – pathognomonic"),
lbl("IHC", "Vimentin+, EMA+; WHO Grade I (benign 80%), II (atypical), III (malignant)"),
sp(2)
]
story += [q("Acute Purulent Leptomeningitis"), sp(1)]
story += [
lbl("Gross", "Creamy yellow-green exudate over convexities; swollen gyri; base cisterns filled with pus; engorged vessels"),
lbl("Micro", "Neutrophil-rich exudate in subarachnoid space; Virchow-Robin space extension"),
lbl("W-F Syndrome", "N. meningitidis → bilateral adrenal hemorrhage + petechiae/purpura"),
]
story.append(tbl(
['Age Group', 'Common Organisms'],
[
['Neonates', 'Group B Strep, E. coli, Listeria'],
['Children 1-23 months', 'S. pneumoniae, N. meningitidis, H. influenzae'],
['Adults', 'S. pneumoniae (most common), N. meningitidis'],
['Elderly/Immunocompromised', 'Listeria, Gram-negatives'],
],
[W*0.4, W*0.6]
))
story.append(sp(2))
story.append(hr())
# ══════════════════════════════════════════════════════════════════════
# 8. CELL INJURY & ADAPTATION
# ══════════════════════════════════════════════════════════════════════
story += sec("8. CELL INJURY, ADAPTATION & AGING")
story += [q("Fatty Liver (Hepatic Steatosis)"), sp(1)]
story += [
lbl("Causes", "Alcohol, Obesity/NAFLD, DM, Kwashiorkor, Drugs (tetracycline, valproate, amiodarone), Reye syndrome, Acute fatty liver of pregnancy"),
lbl("Pathogenesis", "↑ FFA delivery + ↑ FA synthesis + ↓ β-oxidation + ↓ VLDL export → TG accumulation"),
lbl("Gross", "Enlarged, yellow, greasy, soft liver"),
lbl("Micro", "Macrovesicular: large vacuole displaces nucleus (alcohol, obesity) | Microvesicular: multiple small vacuoles (Reye, AFLP, tetracycline)"),
sp(2)
]
story += [q("Pigments & Melanin Disorders"), sp(1)]
story.append(tbl(
['Pigment', 'Type', 'Feature'],
[
['Lipofuscin', 'Endogenous', '"Wear & tear" aging pigment; brown lysosomal granules; heart, liver'],
['Hemosiderin', 'Endogenous', 'Iron-containing; Prussian blue +; hemolysis, hemochromatosis'],
['Bilirubin', 'Endogenous', 'Heme degradation; jaundice'],
['Melanin', 'Endogenous', 'Tyrosine-derived; DOPA oxidase +'],
['Anthracosis', 'Exogenous', 'Carbon dust; lung (coal workers)'],
],
[W*0.28, W*0.2, W*0.52]
))
story += [
sp(1),
lbl("Hypo-pigmentation", "Albinism (tyrosinase def; no melanin); Vitiligo (autoimmune melanocyte destruction); PKU"),
lbl("Hyper-pigmentation", "Addison's (↑ACTH→↑MSH→bronzing); Café-au-lait (NF1); Peutz-Jeghers (perioral + hamartous polyps)"),
sp(2)
]
story.append(hr())
# ══════════════════════════════════════════════════════════════════════
# 9. IMMUNOPATHOLOGY / AMYLOIDOSIS
# ══════════════════════════════════════════════════════════════════════
story += sec("9. IMMUNOPATHOLOGY INCLUDING AMYLOIDOSIS")
story += [q("Classification of Amyloidosis"), sp(1)]
story += [lbl("Key stain", "Congo red → apple-green birefringence under polarized light; beta-pleated sheet configuration"), sp(1)]
story.append(tbl(
['Type', 'Protein (Fibril)', 'Associated Condition'],
[
['Primary (AL)', 'Ig light chains (λ>κ)', 'Multiple myeloma, MGUS, plasma cell dyscrasia'],
['Secondary/Reactive (AA)', 'Serum amyloid A', 'Chronic infxn (TB, OM), RA, IBD, FMF'],
['Dialysis-related', 'β2-microglobulin', 'Long-term hemodialysis; carpal tunnel syndrome'],
['Familial (ATTR)', 'Transthyretin (mutant)', 'Familial amyloid polyneuropathy; cardiac'],
['Senile', 'Transthyretin (normal)', 'Elderly; cardiac'],
["Alzheimer's (Aβ)", 'APP-derived Aβ', "Alzheimer's, Down syndrome"],
['Medullary thyroid Ca', 'Procalcitonin (ACal)', 'Amyloid stroma = characteristic feature'],
],
[W*0.25, W*0.3, W*0.45]
))
story.append(sp(2))
story.append(hr())
# ══════════════════════════════════════════════════════════════════════
# 10. INFLAMMATION AND HEALING
# ══════════════════════════════════════════════════════════════════════
story += sec("10. INFLAMMATION AND HEALING")
story += [q("Acute vs Chronic Inflammation"), sp(1)]
story.append(tbl(
['Feature', 'Acute', 'Chronic'],
[
['Onset', 'Rapid (min-hours)', 'Slow (days-months)'],
['Predominant cells', 'Neutrophils', 'Lymphocytes, macrophages, plasma cells'],
['Vascular changes', 'Prominent (vasodilation, ↑ permeability)', 'Less prominent'],
['Tissue destruction', 'Mild-moderate', 'Often severe; fibrosis'],
['Mediators', 'Histamine, PG, complement, kinins', 'IL-1, TNF, IFN-γ, cytokines'],
['Exudate', 'Serous/fibrinous/suppurative', 'Absent/minimal'],
['Examples', 'Acute appendicitis, acute pneumonia', 'TB, RA, chronic cholecystitis'],
],
[W*0.25, W*0.375, W*0.375]
))
story.append(sp(2))
story += [q("Pulmonary Tuberculosis – Morphological Features"), sp(1)]
story += [
lbl("Primary complex (Ghon)", "Peripheral caseating granuloma + hilar LN enlargement = Ghon complex / Ranke complex"),
lbl("Hallmark lesion", "Caseating granuloma: central caseous necrosis + epithelioid cells + Langhans giant cells (peripheral horseshoe nuclei) + lymphocytic cuff + outer fibrosis"),
lbl("Caseous necrosis", "Acellular, cheese-like, amorphous eosinophilic material; lost architecture"),
lbl("Secondary/post-primary TB", "Apical fibrocavitary disease; Rasmussen aneurysm (PA erosion → hemoptysis); miliary TB (1-2mm millet-seed granulomas hematogenous spread)"),
sp(2)
]
story.append(hr())
# ══════════════════════════════════════════════════════════════════════
# 11. NEOPLASIA
# ══════════════════════════════════════════════════════════════════════
story += sec("11. NEOPLASIA")
story += [q("Paraneoplastic Syndromes"), sp(1)]
story.append(tbl(
['Syndrome', 'Tumor', 'Mechanism'],
[
['Hypercalcemia (most common)', 'SCC lung, RCC, breast', 'PTHrP'],
['SIADH', 'Small cell lung Ca', 'Ectopic ADH'],
['Cushing syndrome', 'Small cell lung Ca', 'Ectopic ACTH'],
['Polycythemia', 'RCC, HCC', 'Ectopic EPO'],
['Eaton-Lambert', 'Small cell lung Ca', 'Anti-VGCC antibodies'],
['Migratory thrombophlebitis (Trousseau)', 'Pancreatic, GI Ca', 'Procoagulant tumor products'],
['Acanthosis nigricans', 'Gastric Ca, lung', 'TGF-α, EGF-like factors'],
['Hypertrophic osteoarthropathy', 'Lung Ca', 'Unknown'],
],
[W*0.35, W*0.3, W*0.35]
))
story.append(sp(2))
story += [q("Utility of Frozen Sections"), sp(1)]
story += [
lbl("Uses", "1) Intraoperative benign vs malignant diagnosis 2) Margin adequacy 3) Tissue identification (parathyroid, LN) 4) Sentinel node biopsy"),
lbl("Limitations", "Freezing artefacts; not for fatty/bony tissue; not definitive alone; 10-15 min turnaround"),
sp(2)
]
story += [q("Etiopathogenesis of Neoplasia – LAQ"), sp(1)]
story.append(tbl(
['Category', 'Gene/Agent', 'Examples / Cancer'],
[
['Proto-oncogene → oncogene (GOF)', 'RAS (most common, 30%)', 'Pancreatic, lung, colorectal Ca'],
['', 'HER2/ErbB2', 'Breast Ca'],
['', 'MYC', 'Burkitt lymphoma, neuroblastoma'],
['', 'ABL (BCR-ABL)', 'CML'],
['Tumor suppressor (LOF)', 'TP53 (most common, 50%+)', 'Li-Fraumeni; almost all cancers'],
['', 'RB1', 'Retinoblastoma, osteosarcoma'],
['', 'BRCA1/2', 'Breast, ovarian Ca'],
['', 'APC', 'Colorectal Ca (FAP)'],
['Chemical carcinogens', 'Benzopyrene (smoking)', 'Lung SCC'],
['', 'Aflatoxin B1', 'Hepatocellular Ca'],
['', 'Aromatic amines', 'Bladder Ca'],
['Viral', 'HPV 16/18 (E6→p53, E7→Rb)', 'Cervical, oropharyngeal Ca'],
['', 'EBV', 'Burkitt lymphoma, NPC, HL'],
['', 'HBV/HCV', 'Hepatocellular Ca'],
['', 'HTLV-1', 'Adult T-cell leukemia'],
['', 'HHV-8', 'Kaposi sarcoma'],
],
[W*0.3, W*0.3, W*0.4]
))
story.append(sp(2))
story.append(hr())
# ══════════════════════════════════════════════════════════════════════
# 12. LYMPHORETICULAR
# ══════════════════════════════════════════════════════════════════════
story += sec("12. DISORDERS OF LEUCOCYTES & LYMPHORETICULAR TISSUES")
story += [q("Hodgkin's Lymphoma"), sp(1)]
story.append(tbl(
['Subtype', 'Freq', 'RS Cells', 'Infiltrate', 'Prognosis'],
[
['Nodular Sclerosis', '65-70%', 'Lacunar cells', 'Bands of sclerosis, eosinophils', 'Good'],
['Mixed Cellularity', '20-25%', 'Classic RS cells (numerous)', 'Mixed: eos, plasma cells, neut, lymphs', 'Intermediate'],
['Lymphocyte-rich', '5%', 'Few RS cells', 'Many lymphocytes', 'Best (cHL)'],
['Lymphocyte-depleted', '1%', 'Many RS cells', 'Few lymphocytes; fibrosis', 'Worst'],
['NLPHL (B-cell)', '5%', 'Popcorn/LP cells', 'Background nodular lymphocytes', 'Indolent'],
],
[W*0.26, W*0.08, W*0.2, W*0.3, W*0.16]
))
story += [
sp(1),
lbl("Reed-Sternberg cell",
"Large binucleated; OWL-EYE nucleoli (prominent eosinophilic); CD30+ CD15+ CD20- CD45-; origin = germinal center B cell"),
lbl("RS variants",
"Lacunar cell (NS type; formalin retraction) | Mummified (pyknotic, apoptotic) | Popcorn/LP cell (NLPHL)"),
lbl("Mixed Cellularity key features",
"1. Classic RS cells numerous & easily found 2. Heterogeneous background (eosinophils, plasma cells, neutrophils, lymphocytes, histiocytes) – NO sclerosis"),
lbl("Ann Arbor Staging",
"I=single LN region | II=2+ regions same side | III=both sides diaphragm | IV=disseminated (liver/BM/lung) | B symptoms (fever, night sweats, wt loss >10%) = worse prognosis"),
sp(2)
]
# Footer
story.append(HRFlowable(width="100%", thickness=0.5, color=colors.HexColor('#1a3a5c'),
spaceBefore=4, spaceAfter=2))
story.append(Paragraph(
"Quick Revision Pathology | Based on Robbins & Cotran Pathologic Basis of Disease",
ParagraphStyle('Footer', fontName='Helvetica-Oblique', fontSize=6,
alignment=TA_CENTER, textColor=colors.HexColor('#888888'))
))
return story
# ── Build PDF ────────────────────────────────────────────────────────────────
import os
os.makedirs('/home/daytona/workspace/output', exist_ok=True)
output_path = '/home/daytona/workspace/output/Pathology_Quick_Revision.pdf'
doc = SimpleDocTemplate(
output_path,
pagesize=A4,
leftMargin=MARGIN,
rightMargin=MARGIN,
topMargin=8 * mm,
bottomMargin=8 * mm,
title="Pathology Quick Revision",
author="Orris AI"
)
story = build_story()
doc.build(story)
print(f"PDF created: {output_path}")
# Count pages
from pypdf import PdfReader
r = PdfReader(output_path)
print(f"Total pages: {len(r.pages)}")
import os
size_kb = os.path.getsize(output_path) // 1024
print(f"File size: {size_kb} KB")