Diphtheria , pulmonary TB , typical and Atypical pneumonia for all these only lab diagnosis And other questions like opportunistic fungal infections , antigenic shift and drift , MMR Vaccine , satellitism ,EBV, quellung reaction - pneumococcus answer for 6 marks refer apurva sastry 4th edition and gimme a picture format explanation in pdf
mkdir -p /tmp/workspace/microbiology-notes && ls /tmp/workspace/microbiology-notes/
~/microbiology-notes/generate_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus import PageBreak
# ── OUTPUT ──────────────────────────────────────────────────────────────────
OUTPUT = "/tmp/workspace/microbiology-notes/Microbiology_6mark_Notes.pdf"
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=1.5*cm, rightMargin=1.5*cm,
topMargin=2*cm, bottomMargin=2*cm,
title="Microbiology 6-Mark Notes",
author="Apurva Sastry 4e Reference"
)
W = A4[0] - 3*cm # usable width
# ── COLOUR PALETTE ───────────────────────────────────────────────────────────
C_HEAD = colors.HexColor("#1A3C5E") # deep navy
C_SUB = colors.HexColor("#2E7D9B") # teal
C_BOX_BG = colors.HexColor("#EAF4FB") # light blue box
C_WARN = colors.HexColor("#FFF3CD") # warning yellow
C_PINK = colors.HexColor("#FCE4EC") # pink highlight
C_GREEN = colors.HexColor("#E8F5E9") # green highlight
C_ORANGE = colors.HexColor("#FFF8E1") # orange highlight
C_PURPLE = colors.HexColor("#F3E5F5") # purple highlight
C_BORDER = colors.HexColor("#2E7D9B")
C_WHITE = colors.white
C_BLACK = colors.HexColor("#1A1A1A")
C_RED = colors.HexColor("#C62828")
C_GOLD = colors.HexColor("#F57F17")
# ── STYLES ───────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()
def S(name, **kw):
base = styles.get(name, styles["Normal"])
ns = ParagraphStyle(f"custom_{id(kw)}", parent=base, **kw)
return ns
TITLE_S = S("Normal", fontSize=22, textColor=C_WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER, spaceAfter=4, leading=26)
CHAP_S = S("Normal", fontSize=15, textColor=C_WHITE, fontName="Helvetica-Bold", alignment=TA_LEFT, spaceAfter=4, leading=18)
HEAD2_S = S("Normal", fontSize=12, textColor=C_HEAD, fontName="Helvetica-Bold", alignment=TA_LEFT, spaceBefore=6, spaceAfter=2, leading=14)
HEAD3_S = S("Normal", fontSize=10.5, textColor=C_SUB, fontName="Helvetica-Bold", alignment=TA_LEFT, spaceBefore=4, spaceAfter=2, leading=13)
BODY_S = S("Normal", fontSize=9.5, textColor=C_BLACK, fontName="Helvetica", alignment=TA_JUSTIFY, spaceAfter=3, leading=13)
BULLET_S = S("Normal", fontSize=9.5, textColor=C_BLACK, fontName="Helvetica", leftIndent=14, spaceAfter=2, leading=13)
SMALL_S = S("Normal", fontSize=8.5, textColor=colors.HexColor("#555555"), fontName="Helvetica", spaceAfter=2, leading=11)
BOLD_S = S("Normal", fontSize=9.5, textColor=C_BLACK, fontName="Helvetica-Bold", spaceAfter=2, leading=13)
KEY_S = S("Normal", fontSize=9, textColor=C_RED, fontName="Helvetica-Bold", spaceAfter=2, leading=12)
WARN_S = S("Normal", fontSize=9, textColor=C_GOLD, fontName="Helvetica-Bold", spaceAfter=2, leading=12)
TABLE_HD = S("Normal", fontSize=9, textColor=C_WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=11)
TABLE_BD = S("Normal", fontSize=8.5, textColor=C_BLACK, fontName="Helvetica", alignment=TA_LEFT, leading=11)
CENT_S = S("Normal", fontSize=9.5, textColor=C_BLACK, fontName="Helvetica", alignment=TA_CENTER, spaceAfter=2, leading=13)
# ── HELPER BUILDERS ──────────────────────────────────────────────────────────
def chapter_banner(text):
tbl = Table([[Paragraph(text, CHAP_S)]], colWidths=[W])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), C_HEAD),
("TOPPADDING", (0,0), (-1,-1), 7),
("BOTTOMPADDING", (0,0), (-1,-1), 7),
("LEFTPADDING", (0,0), (-1,-1), 10),
("ROUNDEDCORNERS", [4,4,4,4]),
]))
return tbl
def section_header(text):
tbl = Table([[Paragraph(text, HEAD2_S)]], colWidths=[W])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), C_BOX_BG),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 8),
("LINEBELOW", (0,0), (-1,-1), 1.5, C_BORDER),
]))
return tbl
def info_box(title, items, bg=C_BOX_BG, title_color=C_SUB):
rows = [[Paragraph(f"<b><font color='#{title_color.hexval()[1:]}'>🔬 {title}</font></b>", BODY_S)]]
for it in items:
rows.append([Paragraph(f"• {it}", BULLET_S)])
tbl = Table(rows, colWidths=[W-2*mm])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("BOX", (0,0), (-1,-1), 1, C_BORDER),
("ROUNDEDCORNERS", [4,4,4,4]),
]))
return tbl
def two_col_table(headers, rows, col_widths=None, bg=C_HEAD):
if col_widths is None:
col_widths = [W*0.4, W*0.6]
data = [[Paragraph(h, TABLE_HD) for h in headers]]
for r in rows:
data.append([Paragraph(str(c), TABLE_BD) for c in r])
tbl = Table(data, colWidths=col_widths)
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), bg),
("BACKGROUND", (0,1), (-1,-1), C_WHITE),
("ROWBACKGROUNDS",(0,1), (-1,-1), [C_WHITE, C_BOX_BG]),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#B0BEC5")),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
return tbl
def key_point_box(text, bg=C_WARN):
tbl = Table([[Paragraph(f"⭐ KEY POINT: {text}", KEY_S)]], colWidths=[W])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 10),
("BOX", (0,0), (-1,-1), 1, C_GOLD),
]))
return tbl
def mnemonic_box(text):
tbl = Table([[Paragraph(f"📝 MNEMONIC: {text}", WARN_S)]], colWidths=[W])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), colors.HexColor("#E8F5E9")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 10),
("BOX", (0,0), (-1,-1), 1, colors.HexColor("#2E7D32")),
]))
return tbl
def SP(n=4):
return Spacer(1, n)
def HR():
return HRFlowable(width="100%", thickness=0.5, color=colors.HexColor("#B0BEC5"), spaceAfter=4, spaceBefore=4)
# ─────────────────────────────────────────────────────────────────────────────
# BUILD DOCUMENT
# ─────────────────────────────────────────────────────────────────────────────
story = []
# ══════════════════════════════════════════════════════════════════
# COVER PAGE
# ══════════════════════════════════════════════════════════════════
cover_bg = Table(
[[Paragraph("MICROBIOLOGY", TITLE_S)],
[Paragraph("6-Mark Picture Notes", TITLE_S)],
[Paragraph("Based on Apurva Sastry 4th Edition", SMALL_S)],
[Spacer(1,8)],
[Paragraph("Lab Diagnosis | Fungal Infections | Virology | Bacteriology", SMALL_S)]],
colWidths=[W]
)
cover_bg.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), C_HEAD),
("TOPPADDING", (0,0), (-1,-1), 18),
("BOTTOMPADDING", (0,0), (-1,-1), 18),
("LEFTPADDING", (0,0), (-1,-1), 20),
("RIGHTPADDING", (0,0), (-1,-1), 20),
("ALIGN", (0,0), (-1,-1), "CENTER"),
]))
story.append(cover_bg)
story.append(SP(20))
# Topics index
topics = [
"1. Diphtheria - Lab Diagnosis",
"2. Pulmonary Tuberculosis - Lab Diagnosis",
"3. Typical Pneumonia (Streptococcus pneumoniae) - Lab Diagnosis",
"4. Atypical Pneumonia - Lab Diagnosis",
"5. Opportunistic Fungal Infections",
"6. Antigenic Shift and Drift (Influenza)",
"7. MMR Vaccine",
"8. Satellitism",
"9. EBV (Epstein-Barr Virus) / Infectious Mononucleosis",
"10. Quellung Reaction (Pneumococcus)",
]
idx_data = [[Paragraph(t, BODY_S)] for t in topics]
idx_tbl = Table(idx_data, colWidths=[W])
idx_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), C_BOX_BG),
("ROWBACKGROUNDS",(0,0), (-1,-1), [C_WHITE, C_BOX_BG]),
("GRID", (0,0), (-1,-1), 0.3, colors.HexColor("#B0BEC5")),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 10),
]))
story.append(Paragraph("TOPICS COVERED", HEAD2_S))
story.append(SP(4))
story.append(idx_tbl)
story.append(PageBreak())
# ══════════════════════════════════════════════════════════════════
# 1. DIPHTHERIA - LAB DIAGNOSIS
# ══════════════════════════════════════════════════════════════════
story.append(chapter_banner("1. DIPHTHERIA - LABORATORY DIAGNOSIS"))
story.append(SP(6))
story.append(Paragraph("Causative Organism: Corynebacterium diphtheriae", BOLD_S))
story.append(SP(4))
# Flowchart-style table
story.append(section_header("Step-by-Step Lab Approach"))
story.append(SP(4))
steps = [
["STEP 1", "Specimen Collection",
"Throat + nasopharyngeal swabs (BOTH sites)\nAlso from membrane/pseudomembrane"],
["STEP 2", "Microscopy",
"Gram stain: Gram-positive pleomorphic rods\nAlbert's stain / Ponder's stain: Metachromatic granules (Babes-Ernst bodies)\nChinese letter / cuneiform arrangement\nNOTE: Unreliable for diagnosis alone"],
["STEP 3", "Culture Media",
"• Loeffler's serum slope - best for rapid growth (6-8 hrs); shows metachromatic granules\n• Tellurite media (CTBA / Tinsdale medium) - SELECTIVE; reduces tellurite → gray-black colonies\n• Blood agar - non-selective\n• Tinsdale medium: best recovery; brown halo due to cysteinase activity"],
["STEP 4", "Colony Morphology",
"On Tellurite media: Gray-to-black colonies\nTinsdale: Brown halo around colonies\n3 biotypes: gravis (large, irregular), mitis (small, smooth), intermedius"],
["STEP 5", "Biochemical Tests",
"Catalase: POSITIVE\nCystinase: POSITIVE\nPyrazinamidase: NEGATIVE (key differentiator)\nFerments glucose + maltose; does NOT ferment sucrose"],
["STEP 6", "Toxigenicity Testing",
"ELEK TEST (Gold Standard): In vitro immunodiffusion test\n→ Filter paper strip soaked in antitoxin placed on plate\n→ Toxigenic strains: precipitation line at 45° angle\n\nPCR: Detects tox gene (faster; used directly on swab)\nVero cell cytotoxicity assay (rarely used)"],
]
step_data = []
for s in steps:
step_data.append([
Paragraph(f"<b>{s[0]}</b>", TABLE_HD),
Paragraph(f"<b>{s[1]}</b>", TABLE_HD),
Paragraph(s[2], TABLE_BD)
])
step_tbl = Table(step_data, colWidths=[W*0.10, W*0.25, W*0.65])
step_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), C_HEAD),
("BACKGROUND", (0,0), (0,-1), colors.HexColor("#1A3C5E")),
("BACKGROUND", (1,0), (1,-1), C_SUB),
("BACKGROUND", (2,0), (2,-1), C_WHITE),
("ROWBACKGROUNDS",(2,0), (2,-1), [C_WHITE, C_BOX_BG]),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#B0BEC5")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TEXTCOLOR", (0,0), (0,-1), C_WHITE),
("TEXTCOLOR", (1,0), (1,-1), C_WHITE),
("FONTNAME", (0,0), (1,-1), "Helvetica-Bold"),
]))
story.append(step_tbl)
story.append(SP(8))
story.append(key_point_box("ELEK TEST = Gold standard for toxigenicity. Tinsdale = Best culture medium."))
story.append(SP(4))
story.append(mnemonic_box("'TELL ELEKTRicity' → TELLurite for culture + ELEK for toxin detection"))
story.append(SP(4))
story.append(section_header("Media Comparison Chart"))
story.append(SP(4))
media_rows = [
["Loeffler's serum slope", "Rapid growth (6-8h)", "Metachromatic granules visible", "NOT selective"],
["Tellurite blood agar", "Selective (inhibits commensals)", "Gray-black colonies", "CTBA variant: long shelf life"],
["Tinsdale medium", "BEST recovery", "Gray-black + brown halo", "Short shelf life; needs horse serum"],
["Blood agar", "Non-selective", "Hemolysis seen", "Used alongside selective media"],
]
story.append(two_col_table(
["Medium", "Advantage", "Colony Appearance", "Note"],
media_rows,
col_widths=[W*0.22, W*0.25, W*0.28, W*0.25]
))
story.append(PageBreak())
# ══════════════════════════════════════════════════════════════════
# 2. PULMONARY TUBERCULOSIS - LAB DIAGNOSIS
# ══════════════════════════════════════════════════════════════════
story.append(chapter_banner("2. PULMONARY TUBERCULOSIS - LABORATORY DIAGNOSIS"))
story.append(SP(6))
story.append(Paragraph("Causative Organism: Mycobacterium tuberculosis (Acid Fast Bacillus - AFB)", BOLD_S))
story.append(SP(4))
story.append(section_header("Specimens"))
story.append(SP(3))
story.append(info_box("Specimen Types", [
"Sputum (most common) - early morning, 3 consecutive days",
"Gastric lavage / aspirate (children, unable to expectorate)",
"Bronchial washing / BAL (bronchoscopy cases)",
"Pleural fluid, CSF, urine, tissue biopsy as appropriate",
"At least 2 sputum samples needed for conclusive diagnosis",
], bg=C_BOX_BG))
story.append(SP(6))
story.append(section_header("Lab Methods - Step by Step"))
story.append(SP(4))
tb_steps = [
["MICROSCOPY\n(Fastest)",
"ZN Stain (Ziehl-Neelsen): Heat-fixed AFBs stain RED on blue background\nAuramine-Rhodamine (Fluorescent): More sensitive; AFBs glow yellow-green\nGrading: 1+ to 3+ based on bacilli per HPF\n\nGRADING (WHO): Scanty = 1-9 AFBs/100 HPF; 1+ = 10-99/100 HPF; 2+ = 1-10/HPF; 3+ = >10/HPF"],
["CULTURE\n(Gold standard)",
"Solid media: Lowenstein-Jensen (LJ) medium - buff/cream colonies in 6-8 weeks\nLiquid media: BACTEC MGIT (Mycobacteria Growth Indicator Tube) - 1-3 weeks\nMBBacT system (automated)\nDecontamination before culture: NALC-NaOH or 4% H2SO4 method"],
["MOLECULAR\n(Rapid)",
"GeneXpert MTB/RIF (CBNAAT): Detects MTB + RIF resistance in 2 hours\nLine Probe Assay (LPA): Detects INH + RIF resistance; strips methodology\nWhole genome sequencing (WGS): Comprehensive DST\nIS6110-based PCR: Specific for MTB complex"],
["SEROLOGY &\nIMMUNOLOGY",
"Tuberculin Skin Test (TST/Mantoux): Delayed hypersensitivity; 5 TU PPD\n→ Read at 48-72h; induration ≥10mm = positive\nIGRAs (Interferon-Gamma Release Assays): QuantiFERON-TB Gold, T-SPOT.TB\n→ Measures IFN-γ from sensitized T-cells; more specific than TST"],
["ANIMAL\nINOCULATION\n(Historical)",
"Guinea pig inoculation (now obsolete)\nReplaced by molecular methods"],
]
tb_data = []
for r in tb_steps:
tb_data.append([Paragraph(r[0], S("Normal", fontSize=9, textColor=C_WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=11)),
Paragraph(r[1], TABLE_BD)])
tb_tbl = Table(tb_data, colWidths=[W*0.18, W*0.82])
tb_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (0,-1), C_HEAD),
("ROWBACKGROUNDS",(1,0), (1,-1), [C_WHITE, C_BOX_BG]),
("BACKGROUND", (1,0), (1,-1), C_WHITE),
("BACKGROUND", (1,1), (1,1), C_BOX_BG),
("BACKGROUND", (1,3), (1,3), C_BOX_BG),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#B0BEC5")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("VALIGN", (1,0), (1,-1), "TOP"),
]))
story.append(tb_tbl)
story.append(SP(8))
story.append(key_point_box("GeneXpert MTB/RIF = Rapid, sensitive, detects RIF resistance simultaneously. LJ medium = Gold standard culture but slow."))
story.append(SP(4))
story.append(mnemonic_box("'ZAP-NG' → ZN stain, Auramine, PCR/GeneXpert, NALC decontamination"))
story.append(SP(4))
story.append(section_header("ZN Staining Steps"))
story.append(SP(3))
zn = [
["1", "Heat fix smear"],
["2", "Apply Carbol Fuchsin (primary stain) + heat for 3 min"],
["3", "Decolorize with 25% H2SO4 (acid-fast organisms RESIST)"],
["4", "Counterstain with Methylene blue"],
["5", "AFBs = RED rods on BLUE background"],
]
story.append(two_col_table(["Step", "Action"], zn, col_widths=[W*0.1, W*0.9]))
story.append(PageBreak())
# ══════════════════════════════════════════════════════════════════
# 3. TYPICAL PNEUMONIA - LAB DIAGNOSIS
# ══════════════════════════════════════════════════════════════════
story.append(chapter_banner("3. TYPICAL PNEUMONIA - LABORATORY DIAGNOSIS"))
story.append(SP(6))
story.append(Paragraph("Causative Organism: Streptococcus pneumoniae (Pneumococcus) - most common", BOLD_S))
story.append(SP(3))
story.append(Paragraph("Other causes: Staphylococcus aureus, Klebsiella pneumoniae, Group A Strep", SMALL_S))
story.append(SP(6))
story.append(section_header("Specimens & Lab Tests"))
story.append(SP(3))
typ_data = [
[Paragraph("<b>Test</b>", TABLE_HD), Paragraph("<b>Findings / Notes</b>", TABLE_HD)],
[Paragraph("Sputum Gram Stain", TABLE_BD),
Paragraph("• >25 WBCs + <10 squamous cells per LPF = good quality sputum\n• Gram-positive diplococci (lancet-shaped) → Pneumococcus\n• Gram-positive cocci in clusters → Staph aureus\n• Gram-negative rods → Klebsiella, H. influenzae", TABLE_BD)],
[Paragraph("Sputum Culture", TABLE_BD),
Paragraph("• Blood agar: alpha-hemolytic (green/partial hemolysis)\n• Chocolate agar: for fastidious organisms\n• MacConkey: for Gram-negative rods\n• Optochin sensitivity: S. pneumoniae SENSITIVE (inhibition zone ≥14mm)\n• Bile solubility: Pneumococcus POSITIVE (lyses in bile/sodium deoxycholate)", TABLE_BD)],
[Paragraph("Blood Culture", TABLE_BD),
Paragraph("• 10% of pneumococcal pneumonia → bacteremia\n• 2 sets before antibiotic therapy\n• Bottles: aerobic + anaerobic", TABLE_BD)],
[Paragraph("Quellung Reaction", TABLE_BD),
Paragraph("• Mix organism + type-specific antiserum + methylene blue\n• Capsule SWELLS (appears to enlarge) = POSITIVE\n• Identifies capsular type (>90 serotypes)\n• Also called Neufeld's reaction / Capsule swelling reaction", TABLE_BD)],
[Paragraph("Urine Antigen Test", TABLE_BD),
Paragraph("• Binax NOW: Rapid; detects pneumococcal C-polysaccharide\n• Sensitivity ~70-80%, specificity ~90%\n• Useful when sputum culture negative", TABLE_BD)],
[Paragraph("CBC & CRP", TABLE_BD),
Paragraph("• WBC >15,000/mm³ → bacterial (pyogenic) pneumonia\n• Elevated CRP, procalcitonin", TABLE_BD)],
]
typ_tbl = Table(typ_data, colWidths=[W*0.25, W*0.75])
typ_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_HEAD),
("ROWBACKGROUNDS",(0,1), (-1,-1), [C_WHITE, C_BOX_BG]),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#B0BEC5")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(typ_tbl)
story.append(SP(8))
story.append(key_point_box("Optochin SENSITIVE + Bile soluble = S. pneumoniae. Viridans strep: Optochin RESISTANT + Bile insoluble."))
story.append(SP(4))
story.append(mnemonic_box("'OPTICS BILE' → Optochin + Bile solubility identify Pneumococcus"))
story.append(PageBreak())
# ══════════════════════════════════════════════════════════════════
# 4. ATYPICAL PNEUMONIA - LAB DIAGNOSIS
# ══════════════════════════════════════════════════════════════════
story.append(chapter_banner("4. ATYPICAL PNEUMONIA - LABORATORY DIAGNOSIS"))
story.append(SP(6))
story.append(section_header("Causative Organisms"))
story.append(SP(4))
org_data = [
[Paragraph("<b>Organism</b>", TABLE_HD), Paragraph("<b>Lab Features</b>", TABLE_HD), Paragraph("<b>Special Test</b>", TABLE_HD)],
[Paragraph("Mycoplasma pneumoniae", TABLE_BD),
Paragraph("• No cell wall (not visible on Gram stain)\n• Grows on Eaton's agar (contains cholesterol)\n• Colonies: 'Fried egg' appearance\n• Slow grower: 2-3 weeks", TABLE_BD),
Paragraph("Cold agglutinin test (IgM vs I antigen on RBCs)\n→ titer >1:64 = suggestive\nComplement fixation test\nMycoplasma IgM/IgG ELISA", TABLE_BD)],
[Paragraph("Chlamydophila pneumoniae", TABLE_BD),
Paragraph("• Obligate intracellular; cannot be cultured on ordinary media\n• Biphasic life cycle: EB (infectious) → RB (replicating)\n• Giemsa stain: intracytoplasmic inclusions", TABLE_BD),
Paragraph("Microimmunofluorescence (MIF) test: Gold standard\nCF antibody titers\nPCR (respiratory secretions)", TABLE_BD)],
[Paragraph("Legionella pneumophila", TABLE_BD),
Paragraph("• Gram-negative rod (weakly staining)\n• Grows on BCYE agar (Buffered Charcoal Yeast Extract)\n• Requires L-cysteine and iron\n• Silver stain / Dieterle stain in tissue", TABLE_BD),
Paragraph("Urinary antigen: Rapid, specific for serogroup 1\nDFA (Direct fluorescent antibody)\nPCR\nSerology: 4-fold rise in IgG", TABLE_BD)],
[Paragraph("Coxiella burnetii\n(Q Fever)", TABLE_BD),
Paragraph("• Obligate intracellular; NOT transmitted by arthropod bite\n• Phase I vs Phase II antigens\n• BSL-3 organism", TABLE_BD),
Paragraph("Weil-Felix: NEGATIVE (differentiates from rickettsia)\nIFA (Phase I & II antigens)\nPCR on blood/tissue", TABLE_BD)],
]
atyp_tbl = Table(org_data, colWidths=[W*0.22, W*0.42, W*0.36])
atyp_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_HEAD),
("ROWBACKGROUNDS",(0,1), (-1,-1), [C_WHITE, C_BOX_BG]),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#B0BEC5")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(atyp_tbl)
story.append(SP(8))
story.append(key_point_box("Mycoplasma: Cold agglutinins + Eaton's agar. Legionella: Urine antigen + BCYE agar. Chlamydia: MIF test."))
story.append(SP(4))
story.append(mnemonic_box("'MAC' → Mycoplasma (Cold agglutinin), Atypical, Chlamydia (MIF), also: ML-CQ = My Legions Chill Quietly"))
story.append(SP(4))
story.append(section_header("Typical vs Atypical Pneumonia - Quick Comparison"))
story.append(SP(3))
comp_rows = [
["Onset", "Sudden, acute", "Gradual, insidious"],
["Sputum", "Purulent, rusty", "Scanty, non-purulent"],
["Gram stain", "Shows organism", "No organism visible"],
["CXR", "Lobar/segmental consolidation", "Bilateral interstitial ('walking pneumonia')"],
["WBC", ">15,000 (neutrophilia)", "Normal or mild lymphocytosis"],
["Response to beta-lactams", "YES", "NO (no cell wall in Mycoplasma)"],
["Treatment", "Penicillin / Amoxicillin", "Macrolides / Doxycycline / Fluoroquinolones"],
]
story.append(two_col_table(["Feature", "Typical Pneumonia", "Atypical Pneumonia"], comp_rows,
col_widths=[W*0.25, W*0.35, W*0.40]))
story.append(PageBreak())
# ══════════════════════════════════════════════════════════════════
# 5. OPPORTUNISTIC FUNGAL INFECTIONS
# ══════════════════════════════════════════════════════════════════
story.append(chapter_banner("5. OPPORTUNISTIC FUNGAL INFECTIONS"))
story.append(SP(6))
story.append(Paragraph("Definition: Fungal infections occurring in immunocompromised hosts due to organisms normally non-pathogenic in healthy individuals.", BODY_S))
story.append(SP(4))
story.append(section_header("Risk Factors (Predisposing Conditions)"))
story.append(SP(3))
rf_data = [
[Paragraph("<b>Risk Factor</b>", TABLE_HD), Paragraph("<b>Common Opportunistic Pathogens</b>", TABLE_HD)],
[Paragraph("AIDS / HIV (CD4 <200)", TABLE_BD), Paragraph("Candida, Cryptococcus neoformans, Pneumocystis jirovecii", TABLE_BD)],
[Paragraph("Bone marrow / Organ transplant", TABLE_BD), Paragraph("Aspergillus, Candida, Mucor, Fusarium", TABLE_BD)],
[Paragraph("Prolonged antibiotics / steroids", TABLE_BD), Paragraph("Candida spp. (disrupts normal flora)", TABLE_BD)],
[Paragraph("Neutropenia (<500 ANC)", TABLE_BD), Paragraph("Aspergillus, Mucor, Candida", TABLE_BD)],
[Paragraph("Diabetes mellitus (DKA)", TABLE_BD), Paragraph("Mucormycosis (Rhizopus, Mucor, Rhizomucor)", TABLE_BD)],
[Paragraph("Hematologic malignancies", TABLE_BD), Paragraph("Aspergillus, Fusarium, Trichosporon", TABLE_BD)],
[Paragraph("Premature neonates", TABLE_BD), Paragraph("Candida spp.", TABLE_BD)],
]
rf_tbl = Table(rf_data, colWidths=[W*0.40, W*0.60])
rf_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_HEAD),
("ROWBACKGROUNDS",(0,1), (-1,-1), [C_WHITE, C_BOX_BG]),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#B0BEC5")),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(rf_tbl)
story.append(SP(6))
story.append(section_header("Major Opportunistic Fungi - Lab Diagnosis"))
story.append(SP(4))
fungi_data = [
[Paragraph("<b>Fungus</b>", TABLE_HD), Paragraph("<b>Morphology / Lab Features</b>", TABLE_HD), Paragraph("<b>Special Test</b>", TABLE_HD)],
[Paragraph("Candida albicans", TABLE_BD),
Paragraph("• Gram-positive yeast (budding)\n• Forms pseudohyphae + true hyphae\n• Germ tube test: POSITIVE at 37°C in serum (2h)\n• Chlamydoconidia on corn meal agar\n• Chrome agar: green colonies", TABLE_BD),
Paragraph("Germ tube test (rapid ID)\nCHROMagar Candida\nBlood culture (BACTEC)\nBeta-D-glucan (serum)", TABLE_BD)],
[Paragraph("Cryptococcus neoformans", TABLE_BD),
Paragraph("• Encapsulated yeast\n• India ink: LARGE capsule (halo around yeast)\n• Urease POSITIVE\n• Birdseed/Niger seed agar: brown colonies\n• No pseudohyphae", TABLE_BD),
Paragraph("India ink of CSF\nCryptococcal antigen (CrAg) - serum/CSF\nLatex agglutination test\nNiger seed agar", TABLE_BD)],
[Paragraph("Aspergillus fumigatus", TABLE_BD),
Paragraph("• Septate hyphae (45° angle branching)\n• Conidiophore with phialides\n• KOH mount of BAL/sputum\n• Velvety green colonies on SDA", TABLE_BD),
Paragraph("Galactomannan (serum/BAL)\nBeta-D-glucan\nCT chest: 'Halo sign' / air crescent sign\nCulture on SDA", TABLE_BD)],
[Paragraph("Mucor / Rhizopus\n(Mucormycosis)", TABLE_BD),
Paragraph("• Broad ASEPTATE hyphae (90° angle branching)\n• Ribbon-like hyphae on KOH\n• Rhizopus: has rhizoids\n• Sporangiophore with sporangium\n• Very fast growing (2-3 days)", TABLE_BD),
Paragraph("KOH mount of tissue/sputum\nHistopathology (PAS/GMS stain)\nCT: Rhino-orbital involvement\nSerology unreliable", TABLE_BD)],
[Paragraph("Pneumocystis jirovecii\n(formerly carinii)", TABLE_BD),
Paragraph("• Classified as FUNGUS (not protozoa)\n• Cannot be cultured in vitro\n• Cysts and trophic forms\n• CD4 <200 cells/μL", TABLE_BD),
Paragraph("GMS (Gomori Methenamine Silver): cysts stain black\nToluidine blue O stain\nBAL or induced sputum\nPCR (most sensitive)\nLDH markedly elevated (non-specific)", TABLE_BD)],
]
fungi_tbl = Table(fungi_data, colWidths=[W*0.18, W*0.46, W*0.36])
fungi_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_HEAD),
("ROWBACKGROUNDS",(0,1), (-1,-1), [C_WHITE, C_BOX_BG]),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#B0BEC5")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(fungi_tbl)
story.append(SP(6))
story.append(key_point_box("Mucor = ASEPTATE hyphae. Aspergillus = SEPTATE hyphae. India ink = Cryptococcus. Germ tube = Candida albicans."))
story.append(SP(4))
story.append(mnemonic_box("'ACMP' - Aspergillus (galactomannan), Candida (germ tube), Mucor (aseptate), Pneumocystis (GMS stain)"))
story.append(PageBreak())
# ══════════════════════════════════════════════════════════════════
# 6. ANTIGENIC SHIFT AND DRIFT
# ══════════════════════════════════════════════════════════════════
story.append(chapter_banner("6. ANTIGENIC SHIFT AND DRIFT (INFLUENZA VIRUS)"))
story.append(SP(6))
story.append(Paragraph("Influenza virus surface antigens: Hemagglutinin (HA) - 18 subtypes, Neuraminidase (NA) - 11 subtypes", BOLD_S))
story.append(SP(4))
compare_data = [
[Paragraph("<b>Feature</b>", TABLE_HD), Paragraph("<b>ANTIGENIC DRIFT</b>", TABLE_HD), Paragraph("<b>ANTIGENIC SHIFT</b>", TABLE_HD)],
[Paragraph("Definition", TABLE_BD), Paragraph("Gradual, minor changes in HA/NA", TABLE_BD), Paragraph("Abrupt, major change in HA/NA subtype", TABLE_BD)],
[Paragraph("Mechanism", TABLE_BD), Paragraph("Point mutations in HA/NA genes", TABLE_BD), Paragraph("Genetic REASSORTMENT between 2 different influenza strains in same host (e.g., pig)", TABLE_BD)],
[Paragraph("Change type", TABLE_BD), Paragraph("Quantitative (incremental)", TABLE_BD), Paragraph("Qualitative (completely new subtype)", TABLE_BD)],
[Paragraph("Result", TABLE_BD), Paragraph("EPIDEMICS (smaller outbreaks)", TABLE_BD), Paragraph("PANDEMICS (global spread)", TABLE_BD)],
[Paragraph("Frequency", TABLE_BD), Paragraph("Occurs continuously/yearly", TABLE_BD), Paragraph("Rare (every 10-40 years)", TABLE_BD)],
[Paragraph("Occurs in", TABLE_BD), Paragraph("ALL influenza types (A, B, C)", TABLE_BD), Paragraph("ONLY Influenza A (animal reservoir exists)", TABLE_BD)],
[Paragraph("Immunity", TABLE_BD), Paragraph("Partial immunity (some cross-protection)", TABLE_BD), Paragraph("NO immunity in population (new subtype)", TABLE_BD)],
[Paragraph("Example", TABLE_BD), Paragraph("Annual seasonal flu variations", TABLE_BD), Paragraph("1918 (H1N1 Spanish flu), 1957 (H2N2 Asian), 1968 (H3N2 Hong Kong), 2009 (H1N1 Swine flu)", TABLE_BD)],
[Paragraph("Internal proteins", TABLE_BD), Paragraph("NP, M proteins relatively stable", TABLE_BD), Paragraph("NP, M proteins relatively stable (only HA/NA change)", TABLE_BD)],
]
comp_tbl = Table(compare_data, colWidths=[W*0.22, W*0.38, W*0.40])
comp_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_HEAD),
("BACKGROUND", (1,1), (1,-1), colors.HexColor("#E3F2FD")),
("BACKGROUND", (2,1), (2,-1), colors.HexColor("#FCE4EC")),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#B0BEC5")),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(comp_tbl)
story.append(SP(8))
story.append(key_point_box("DRIFT = Small changes → Epidemics. SHIFT = Big reassortment → Pandemics. ONLY Influenza A undergoes both."))
story.append(SP(4))
story.append(mnemonic_box("'DRIFTing slowly (gradual/epidemic) vs SHIFTing suddenly (abrupt/pandemic)' | 'A-SHIFT = Animal reassortment'"))
story.append(SP(6))
story.append(section_header("Pandemic Examples"))
story.append(SP(3))
pandemic_rows = [
["1918", "H1N1", "Spanish flu", "~50 million deaths"],
["1957", "H2N2", "Asian flu", "~1-2 million deaths"],
["1968", "H3N2", "Hong Kong flu", "~1 million deaths"],
["1977", "H1N1", "Russian flu", "Re-emergence"],
["2009", "H1N1 (pdm09)", "Swine flu", "Quadruple reassortant; >18,000 deaths"],
]
story.append(two_col_table(["Year", "Subtype", "Name", "Impact"], pandemic_rows,
col_widths=[W*0.12, W*0.18, W*0.30, W*0.40]))
story.append(PageBreak())
# ══════════════════════════════════════════════════════════════════
# 7. MMR VACCINE
# ══════════════════════════════════════════════════════════════════
story.append(chapter_banner("7. MMR VACCINE"))
story.append(SP(6))
story.append(section_header("Overview"))
story.append(SP(4))
mmr_info = [
[Paragraph("<b>Feature</b>", TABLE_HD), Paragraph("<b>Details</b>", TABLE_HD)],
[Paragraph("Full form", TABLE_BD), Paragraph("Measles-Mumps-Rubella combined vaccine", TABLE_BD)],
[Paragraph("Type", TABLE_BD), Paragraph("Live attenuated vaccine", TABLE_BD)],
[Paragraph("Route", TABLE_BD), Paragraph("Subcutaneous (SC) injection, 0.5 mL", TABLE_BD)],
[Paragraph("Schedule (India)", TABLE_BD), Paragraph("1st dose: 9 months (as MR vaccine) or 12 months\n2nd dose: 15-18 months\nMMRV also available (adds Varicella)", TABLE_BD)],
[Paragraph("Schedule (USA)", TABLE_BD), Paragraph("1st dose: 12-15 months\n2nd dose: 4-6 years", TABLE_BD)],
[Paragraph("Immunity", TABLE_BD), Paragraph("~95-99% seroconversion after 2 doses", TABLE_BD)],
[Paragraph("Duration", TABLE_BD), Paragraph("Lifelong immunity (most cases)", TABLE_BD)],
[Paragraph("Storage", TABLE_BD), Paragraph("2-8°C; protect from light (light-sensitive)", TABLE_BD)],
]
mmr_tbl = Table(mmr_info, colWidths=[W*0.30, W*0.70])
mmr_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_HEAD),
("ROWBACKGROUNDS",(0,1), (-1,-1), [C_WHITE, C_BOX_BG]),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#B0BEC5")),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(mmr_tbl)
story.append(SP(6))
story.append(section_header("Individual Vaccine Components"))
story.append(SP(4))
comp_data = [
[Paragraph("<b>Component</b>", TABLE_HD), Paragraph("<b>Virus Strain Used</b>", TABLE_HD), Paragraph("<b>Key Points</b>", TABLE_HD)],
[Paragraph("MEASLES", TABLE_BD),
Paragraph("Edmonston B → Schwarz strain\nMoreaten strain (Attenuvax)", TABLE_BD),
Paragraph("Prevents rubeola; fever + maculopapular rash\nKoplik's spots pathognomonic\nMost common VPD causing death globally\nSSPE is late complication", TABLE_BD)],
[Paragraph("MUMPS", TABLE_BD),
Paragraph("Jeryl Lynn strain (used in MMR-II)\nUrabe strain (older; withdrawn)", TABLE_BD),
Paragraph("Prevents parotitis, orchitis, meningitis\nJeryl Lynn = safest strain\nUrabe withdrawn due to aseptic meningitis", TABLE_BD)],
[Paragraph("RUBELLA", TABLE_BD),
Paragraph("RA 27/3 strain", TABLE_BD),
Paragraph("Prevents congenital rubella syndrome (CRS)\nCRS: deafness, cataracts, cardiac defects (PDA, VSD)\nBlueberry muffin rash in neonates\nMost important to vaccinate WOMEN OF CHILDBEARING AGE", TABLE_BD)],
]
comp_tbl2 = Table(comp_data, colWidths=[W*0.15, W*0.28, W*0.57])
comp_tbl2.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_HEAD),
("ROWBACKGROUNDS",(0,1), (-1,-1), [C_WHITE, C_BOX_BG]),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#B0BEC5")),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(comp_tbl2)
story.append(SP(6))
story.append(section_header("Contraindications & Special Notes"))
story.append(SP(3))
story.append(info_box("Contraindications", [
"Severe immunodeficiency (HIV with CD4 <15% / AIDS, lymphoma, leukemia)",
"Pregnancy (live vaccine - teratogenic potential; avoid 1 month post-vaccination)",
"Recent blood product / IG administration (defer 3 months)",
"Known anaphylaxis to neomycin or gelatin",
"High-dose corticosteroids (>2 mg/kg/day >14 days) - defer 1 month",
"NOTE: Egg allergy is NOT a contraindication (grown in chick embryo, not egg white)",
], bg=C_PINK))
story.append(SP(4))
story.append(key_point_box("MMR = Live attenuated. Contraindicated in pregnancy and severe immunodeficiency. RA 27/3 strain used for Rubella."))
story.append(SP(4))
story.append(mnemonic_box("'MMR = Must give at Month 12 + Re-dose at 4-6 years' | 'Jeryl Lynn = Safe jerky Lynn strain for Mumps'"))
story.append(PageBreak())
# ══════════════════════════════════════════════════════════════════
# 8. SATELLITISM
# ══════════════════════════════════════════════════════════════════
story.append(chapter_banner("8. SATELLITISM"))
story.append(SP(6))
story.append(section_header("Definition"))
story.append(SP(3))
story.append(Paragraph(
"Satellitism is a phenomenon in which one bacterium (Haemophilus influenzae) grows only near or around colonies of another organism (Staphylococcus aureus) because it requires growth factors secreted by the latter.",
BODY_S))
story.append(SP(6))
story.append(section_header("Key Components"))
story.append(SP(4))
sat_info = [
[Paragraph("<b>Component</b>", TABLE_HD), Paragraph("<b>Details</b>", TABLE_HD)],
[Paragraph("Organism showing satellitism", TABLE_BD), Paragraph("Haemophilus influenzae (small, pale colonies)", TABLE_BD)],
[Paragraph("Helper organism", TABLE_BD), Paragraph("Staphylococcus aureus (or Staphylococcus epidermidis)", TABLE_BD)],
[Paragraph("Medium", TABLE_BD), Paragraph("Blood agar (H. influenzae grows only NEAR Staph colonies)", TABLE_BD)],
[Paragraph("What Staph provides", TABLE_BD), Paragraph("Factor V (NAD - nicotinamide adenine dinucleotide) released by RBC hemolysis by Staph\nAlso: Factor X present in blood agar", TABLE_BD)],
[Paragraph("Growth factors needed", TABLE_BD), Paragraph("H. influenzae requires BOTH Factor X (hemin/protoporphyrin IX) AND Factor V (NAD)\nFactor V crosses from Staph-lysed RBCs into surrounding area", TABLE_BD)],
[Paragraph("Appearance", TABLE_BD), Paragraph("H. influenzae colonies appear small and grow only in the SATELLITE zone around Staph aureus colonies", TABLE_BD)],
[Paragraph("Lab significance", TABLE_BD), Paragraph("Confirms H. influenzae; differentiates from other Haemophilus species\nH. aegyptius: needs X + V; H. ducreyi: needs only X; H. parainfluenzae: needs only V", TABLE_BD)],
]
sat_tbl = Table(sat_info, colWidths=[W*0.30, W*0.70])
sat_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_HEAD),
("ROWBACKGROUNDS",(0,1), (-1,-1), [C_WHITE, C_BOX_BG]),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#B0BEC5")),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(sat_tbl)
story.append(SP(6))
story.append(section_header("Haemophilus Growth Factor Requirements"))
story.append(SP(3))
hfac_rows = [
["H. influenzae", "YES (X)", "YES (V)", "Satellitism with Staph on blood agar"],
["H. parainfluenzae", "NO", "YES (V)", "No satellitism; grows away from Staph"],
["H. ducreyi", "YES (X)", "NO", "Chancroid; only needs hemin"],
["H. aegyptius", "YES (X)", "YES (V)", "Pink eye / Brazilian purpuric fever"],
["H. haemolyticus", "YES (X)", "YES (V)", "Beta-hemolytic on blood agar"],
]
story.append(two_col_table(["Species", "Factor X", "Factor V", "Note"], hfac_rows,
col_widths=[W*0.28, W*0.13, W*0.13, W*0.46]))
story.append(SP(6))
story.append(key_point_box("Satellitism = H. influenzae satellite colonies around S. aureus on blood agar. Both X + V factors needed."))
story.append(SP(4))
story.append(mnemonic_box("'H. influenzae Xtra 5 (V) reasons to be near Staph' → needs Factor X + V (5 in Roman)"))
story.append(PageBreak())
# ══════════════════════════════════════════════════════════════════
# 9. EBV - EPSTEIN-BARR VIRUS
# ══════════════════════════════════════════════════════════════════
story.append(chapter_banner("9. EBV - EPSTEIN-BARR VIRUS & INFECTIOUS MONONUCLEOSIS"))
story.append(SP(6))
story.append(Paragraph("Classification: Gamma-herpesvirus (HHV-4) | Envelope: dsDNA virus", BOLD_S))
story.append(SP(4))
story.append(section_header("Pathogenesis"))
story.append(SP(3))
story.append(info_box("EBV Infection Pathway", [
"EBV infects B lymphocytes via CD21 receptor (also epithelial cells)",
"2 pathways: Lytic destruction OR Latency within lymphocytes",
"Expresses EBNAs (Epstein-Barr Nuclear Antigens) → B-cell immortalization",
"CD8+ T cells expand vigorously → appear as 'Atypical lymphocytes' on smear",
"Heterophile antibodies (IgM) produced against sheep RBC surface antigens",
"Incubation period: 30-50 days",
"Seroprevalence: 90-95% adults worldwide",
], bg=C_PURPLE))
story.append(SP(6))
story.append(section_header("Clinical Triad of Infectious Mononucleosis"))
story.append(SP(3))
triad_data = [
[Paragraph("<b>FEVER</b>", S("Normal", fontSize=12, textColor=C_WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
Paragraph("<b>SORE THROAT</b>\n(Exudative pharyngitis)", S("Normal", fontSize=12, textColor=C_WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)),
Paragraph("<b>LYMPHADENOPATHY</b>\n(Posterior cervical)", S("Normal", fontSize=12, textColor=C_WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER))],
]
triad_tbl = Table(triad_data, colWidths=[W*0.33, W*0.33, W*0.34])
triad_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (0,0), colors.HexColor("#E53935")),
("BACKGROUND", (1,0), (1,0), colors.HexColor("#1E88E5")),
("BACKGROUND", (2,0), (2,0), colors.HexColor("#43A047")),
("TOPPADDING", (0,0), (-1,-1), 12),
("BOTTOMPADDING", (0,0), (-1,-1), 12),
("ALIGN", (0,0), (-1,-1), "CENTER"),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("GRID", (0,0), (-1,-1), 1, C_WHITE),
]))
story.append(triad_tbl)
story.append(SP(6))
story.append(section_header("Laboratory Diagnosis"))
story.append(SP(4))
ebv_lab = [
[Paragraph("<b>Test</b>", TABLE_HD), Paragraph("<b>Findings / Notes</b>", TABLE_HD)],
[Paragraph("CBC / Peripheral Smear", TABLE_BD),
Paragraph("• Absolute lymphocytosis (>50% lymphocytes)\n• >10% atypical lymphocytes (Downey cells - activated CD8+ T cells)\n• Mild thrombocytopenia may be present\n• Atypical lymphocytes: large, irregular nucleus, abundant cytoplasm, 'skirt-like' cytoplasm", TABLE_BD)],
[Paragraph("Monospot Test\n(Paul-Bunnell-Davidson)", TABLE_BD),
Paragraph("• Detects HETEROPHILE antibodies (IgM) against sheep/horse RBCs\n• Rapid latex agglutination card test\n• Sensitivity ~85-90% in adolescents; FALSE NEGATIVE in <4 years\n• Positive at some point in up to 90% of cases\n• Heterophile antibodies are NOT cross-reactive with EBV antigens", TABLE_BD)],
[Paragraph("EBV-Specific Serology", TABLE_BD),
Paragraph("• Anti-VCA IgM: ACUTE infection (appears first)\n• Anti-VCA IgG: Past infection / persists lifelong\n• Anti-EA (Early Antigen): Active replication\n• Anti-EBNA IgG: Appears LATE (weeks-months); confirms past infection\n\nInterpretation:\n- VCA IgM +ve, EBNA -ve = ACUTE\n- VCA IgG +ve, EBNA +ve = Past/Latent", TABLE_BD)],
[Paragraph("EBV PCR / EBER ISH", TABLE_BD),
Paragraph("• Quantitative EBV DNA PCR: monitors viral load\n• EBER in-situ hybridization: detects EBV in tissue (lymphoma, etc.)\n• Used for EBV-associated malignancies: Burkitt's lymphoma, NPC, Hodgkin's", TABLE_BD)],
[Paragraph("LFTs", TABLE_BD),
Paragraph("• Elevated liver enzymes (ALT, AST) in ~80% of cases\n• Mild hepatomegaly common", TABLE_BD)],
]
ebv_tbl = Table(ebv_lab, colWidths=[W*0.25, W*0.75])
ebv_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_HEAD),
("ROWBACKGROUNDS",(0,1), (-1,-1), [C_WHITE, C_BOX_BG]),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#B0BEC5")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(ebv_tbl)
story.append(SP(6))
story.append(section_header("EBV-Associated Malignancies"))
story.append(SP(3))
malig_rows = [
["Burkitt's Lymphoma", "EBV + translocation t(8;14) - c-MYC oncogene", "Jaw tumors; endemic Africa"],
["Nasopharyngeal Carcinoma (NPC)", "EBV + genetic/environmental factors", "Southeast Asia; raised anti-VCA titers"],
["Hodgkin's Lymphoma", "EBV in Reed-Sternberg cells (~40-50%)", "Mixed cellularity subtype most common"],
["Post-transplant lymphoproliferative disorder", "EBV-driven B-cell proliferation", "Immunosuppressed patients"],
["Hairy oral leukoplakia", "EBV replication in lateral tongue epithelium", "HIV patients", ],
]
story.append(two_col_table(["Malignancy", "EBV Link", "Note"], malig_rows,
col_widths=[W*0.32, W*0.38, W*0.30]))
story.append(SP(6))
story.append(key_point_box("Monospot = Heterophile antibodies. False -ve in children <4 yrs. VCA IgM = Acute EBV. Atypical lymphocytes = activated CD8+ T cells."))
story.append(SP(4))
story.append(mnemonic_box("'FENB' → Fever, Exudative pharyngitis, Nodes (posterior cervical), Blood (atypical lymphocytes)"))
story.append(PageBreak())
# ══════════════════════════════════════════════════════════════════
# 10. QUELLUNG REACTION
# ══════════════════════════════════════════════════════════════════
story.append(chapter_banner("10. QUELLUNG REACTION (PNEUMOCOCCUS)"))
story.append(SP(6))
story.append(section_header("Definition"))
story.append(SP(3))
story.append(Paragraph(
"The Quellung reaction (German: 'Quellung' = swelling) is a serological test used to identify encapsulated bacteria - especially Streptococcus pneumoniae - by mixing organisms with type-specific anticapsular antiserum + methylene blue dye, causing the capsule to appear to SWELL.",
BODY_S))
story.append(SP(6))
story.append(section_header("Procedure & Mechanism"))
story.append(SP(4))
quel_steps = [
["STEP 1", "Prepare fresh sputum / CSF / broth culture smear"],
["STEP 2", "Add one drop of TYPE-SPECIFIC antiserum + methylene blue dye"],
["STEP 3", "Mix and apply coverslip; observe under oil immersion"],
["STEP 4 (+)", "CAPSULE APPEARS TO SWELL (actually: Ab binds capsule → increases refractive index → appears larger)\nBackground: blue; Bacteria: dark; Capsule: large halo = POSITIVE"],
["STEP 4 (-)", "No capsular swelling = NEGATIVE (strain mismatch or non-capsulated)"],
["STEP 5", "Use to identify serotype among >90 pneumococcal capsular types"],
]
quel_data = [[Paragraph(f"<b>{r[0]}</b>", TABLE_HD), Paragraph(r[1], TABLE_BD)] for r in quel_steps]
quel_tbl = Table(quel_data, colWidths=[W*0.15, W*0.85])
quel_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (0,-1), C_HEAD),
("ROWBACKGROUNDS",(1,0), (1,-1), [C_WHITE, C_BOX_BG]),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#B0BEC5")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("VALIGN", (1,0), (1,-1), "TOP"),
]))
story.append(quel_tbl)
story.append(SP(6))
story.append(section_header("Key Facts & Applications"))
story.append(SP(3))
story.append(info_box("Important Points", [
"Also called: Neufeld's Quellung reaction / Capsule swelling test",
"Used for: S. pneumoniae (>90 serotypes), H. influenzae (6 serotypes: a-f), N. meningitidis",
"Mechanism: Antibody + capsular polysaccharide → Ag-Ab complex → Increased refractivity → APPARENT swelling",
"NOT actual swelling - it's OPTICAL change due to Ab binding",
"Omniserum: Polyvalent pooled antiserum; tests all serotypes at once",
"Diagnostic use: Serotyping of pneumococcal strains for epidemiology",
"Quellung positive = ENCAPSULATED virulent strain (capsule = virulence factor)",
"Quellung vs India ink: Both show capsule; India ink = exclusion stain; Quellung = immunological",
], bg=C_GREEN))
story.append(SP(6))
story.append(section_header("Pneumococcal Virulence & Other Tests"))
story.append(SP(4))
pneumo_data = [
[Paragraph("<b>Test</b>", TABLE_HD), Paragraph("<b>Pneumococcus Result</b>", TABLE_HD), Paragraph("<b>Significance</b>", TABLE_HD)],
[Paragraph("Gram stain", TABLE_BD), Paragraph("Gram-positive diplococci (lancet-shaped)", TABLE_BD), Paragraph("Morphology identification", TABLE_BD)],
[Paragraph("Optochin test", TABLE_BD), Paragraph("SENSITIVE (inhibition ≥14mm)", TABLE_BD), Paragraph("Differentiates from viridans strep", TABLE_BD)],
[Paragraph("Bile solubility", TABLE_BD), Paragraph("POSITIVE (lyses in bile salts)", TABLE_BD), Paragraph("Autolysin enzyme lyses own cell wall", TABLE_BD)],
[Paragraph("Quellung reaction", TABLE_BD), Paragraph("POSITIVE (capsule swelling)", TABLE_BD), Paragraph("Gold standard for serotyping", TABLE_BD)],
[Paragraph("Mouse virulence", TABLE_BD), Paragraph("POSITIVE (kills within 24-48 hrs)", TABLE_BD), Paragraph("Historically used; rarely done now", TABLE_BD)],
[Paragraph("Inulin fermentation", TABLE_BD), Paragraph("POSITIVE", TABLE_BD), Paragraph("Differentiates from other strep", TABLE_BD)],
[Paragraph("Alpha hemolysis", TABLE_BD), Paragraph("POSITIVE (green zone on blood agar)", TABLE_BD), Paragraph("Partial hemolysis by pneumolysin", TABLE_BD)],
]
pneumo_tbl = Table(pneumo_data, colWidths=[W*0.27, W*0.37, W*0.36])
pneumo_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_HEAD),
("ROWBACKGROUNDS",(0,1), (-1,-1), [C_WHITE, C_BOX_BG]),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#B0BEC5")),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(pneumo_tbl)
story.append(SP(6))
story.append(key_point_box("Quellung = Ab binds capsule → APPARENT swelling (refractive change). Identifies >90 serotypes of S. pneumoniae."))
story.append(SP(4))
story.append(mnemonic_box("'Quellung = Queen swells her CAPSULE when met with specific antibody (her royal guard)'"))
story.append(SP(8))
# Final summary page
story.append(PageBreak())
story.append(chapter_banner("QUICK REVISION SUMMARY"))
story.append(SP(8))
summary_data = [
[Paragraph("<b>Topic</b>", TABLE_HD), Paragraph("<b>Gold Standard / Key Test</b>", TABLE_HD), Paragraph("<b>Remember</b>", TABLE_HD)],
[Paragraph("Diphtheria Lab Dx", TABLE_BD), Paragraph("ELEK test (toxigenicity)", TABLE_BD), Paragraph("Tinsdale medium; gray-black + brown halo", TABLE_BD)],
[Paragraph("TB Lab Dx", TABLE_BD), Paragraph("Culture on LJ medium / MGIT", TABLE_BD), Paragraph("ZN stain (rapid); GeneXpert (RIF resistance)", TABLE_BD)],
[Paragraph("Typical Pneumonia", TABLE_BD), Paragraph("Sputum culture + Quellung", TABLE_BD), Paragraph("Optochin sensitive; bile soluble", TABLE_BD)],
[Paragraph("Atypical Pneumonia", TABLE_BD), Paragraph("Mycoplasma: Cold agglutinin", TABLE_BD), Paragraph("Legionella: Urine antigen + BCYE agar", TABLE_BD)],
[Paragraph("Opp. Fungi", TABLE_BD), Paragraph("Crypto: India ink / CrAg", TABLE_BD), Paragraph("Mucor = aseptate; Aspergillus = septate", TABLE_BD)],
[Paragraph("Antigenic Shift", TABLE_BD), Paragraph("Reassortment → Pandemic", TABLE_BD), Paragraph("Only Influenza A; animal reservoir", TABLE_BD)],
[Paragraph("Antigenic Drift", TABLE_BD), Paragraph("Point mutations → Epidemic", TABLE_BD), Paragraph("All Inf. A, B, C; annual seasonal flu", TABLE_BD)],
[Paragraph("MMR Vaccine", TABLE_BD), Paragraph("Live attenuated; 2 doses", TABLE_BD), Paragraph("RA 27/3 (Rubella); Jeryl Lynn (Mumps)", TABLE_BD)],
[Paragraph("Satellitism", TABLE_BD), Paragraph("H. influenzae + Staph aureus", TABLE_BD), Paragraph("Needs Factor X + V; grows near Staph", TABLE_BD)],
[Paragraph("EBV / Inf. Mono", TABLE_BD), Paragraph("Monospot (heterophile Ab)", TABLE_BD), Paragraph("VCA IgM = acute; atypical lymphocytes", TABLE_BD)],
[Paragraph("Quellung Reaction", TABLE_BD), Paragraph("Ab + Capsule → apparent swelling", TABLE_BD), Paragraph("Serotypes pneumococcus; also H. influenzae", TABLE_BD)],
]
summ_tbl = Table(summary_data, colWidths=[W*0.25, W*0.35, W*0.40])
summ_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), C_HEAD),
("ROWBACKGROUNDS",(0,1), (-1,-1), [C_WHITE, C_BOX_BG]),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#B0BEC5")),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(summ_tbl)
story.append(SP(10))
story.append(Paragraph("Reference: Apurva Sastry Microbiology 4th Edition | Medical Microbiology 9e (Murray) | Sherris & Ryan 8e | Jawetz 28e", SMALL_S))
# ── BUILD ────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF generated: {OUTPUT}")
cd /tmp/workspace/microbiology-notes && python generate_pdf.py 2>&1
~/microbiology-notes/generate_pdf.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/microbiology-notes/generate_pdf.py'
~/microbiology-notes/generate_pdf.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/microbiology-notes/generate_pdf.py'
~/microbiology-notes/generate_pdf.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/microbiology-notes/generate_pdf.py'
cd /tmp/workspace/microbiology-notes && python generate_pdf.py 2>&1
ls -lh /tmp/workspace/microbiology-notes/Microbiology_6mark_Notes.pdf
Microbiology 6mark Notes
PDF Document · PDF