~/neet-pg-microbiology/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, PageBreak, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import ListFlowable, ListItem
OUTPUT = "/tmp/workspace/neet-pg-microbiology/Culture_Media_NEET_PG.pdf"
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
rightMargin=1.8*cm,
leftMargin=1.8*cm,
topMargin=2*cm,
bottomMargin=2*cm
)
# ── Colour palette ──────────────────────────────────────────────────────────
DARK_BLUE = colors.HexColor("#1a3a5c")
MED_BLUE = colors.HexColor("#2563a8")
LIGHT_BLUE = colors.HexColor("#dbeafe")
ACCENT = colors.HexColor("#e65c00")
YELLOW_BG = colors.HexColor("#fffbeb")
GREEN_BG = colors.HexColor("#f0fdf4")
GREEN_DARK = colors.HexColor("#166534")
TABLE_HEAD = colors.HexColor("#1e40af")
ROW_ALT = colors.HexColor("#f0f7ff")
WHITE = colors.white
GREY_TEXT = colors.HexColor("#374151")
LIGHT_GREY = colors.HexColor("#f3f4f6")
RED_BG = colors.HexColor("#fff1f2")
RED_DARK = colors.HexColor("#9b1c1c")
styles = getSampleStyleSheet()
# Custom styles
title_style = ParagraphStyle(
"Title", parent=styles["Normal"],
fontSize=22, fontName="Helvetica-Bold",
textColor=WHITE, alignment=TA_CENTER, spaceAfter=4
)
subtitle_style = ParagraphStyle(
"Subtitle", parent=styles["Normal"],
fontSize=11, fontName="Helvetica",
textColor=colors.HexColor("#bfdbfe"), alignment=TA_CENTER, spaceAfter=2
)
h1 = ParagraphStyle(
"H1", parent=styles["Normal"],
fontSize=14, fontName="Helvetica-Bold",
textColor=WHITE, spaceBefore=8, spaceAfter=4,
leftIndent=0, leading=18
)
h2 = ParagraphStyle(
"H2", parent=styles["Normal"],
fontSize=11, fontName="Helvetica-Bold",
textColor=DARK_BLUE, spaceBefore=10, spaceAfter=4,
leftIndent=0, leading=14
)
h3 = ParagraphStyle(
"H3", parent=styles["Normal"],
fontSize=10, fontName="Helvetica-Bold",
textColor=MED_BLUE, spaceBefore=6, spaceAfter=3,
leftIndent=0, leading=13
)
body = ParagraphStyle(
"Body", parent=styles["Normal"],
fontSize=9, fontName="Helvetica",
textColor=GREY_TEXT, spaceBefore=2, spaceAfter=2,
leftIndent=0, leading=13
)
body_bold = ParagraphStyle(
"BodyBold", parent=body,
fontName="Helvetica-Bold", textColor=DARK_BLUE
)
mnemonic_style = ParagraphStyle(
"Mnemonic", parent=styles["Normal"],
fontSize=9.5, fontName="Helvetica-Bold",
textColor=GREEN_DARK, spaceBefore=3, spaceAfter=3,
leftIndent=8, leading=14
)
tip_style = ParagraphStyle(
"Tip", parent=styles["Normal"],
fontSize=9, fontName="Helvetica-Oblique",
textColor=RED_DARK, spaceBefore=2, spaceAfter=2,
leftIndent=8, leading=13
)
tbl_header = ParagraphStyle(
"TblHeader", parent=styles["Normal"],
fontSize=9, fontName="Helvetica-Bold",
textColor=WHITE, alignment=TA_CENTER, leading=12
)
tbl_cell = ParagraphStyle(
"TblCell", parent=styles["Normal"],
fontSize=8.5, fontName="Helvetica",
textColor=GREY_TEXT, alignment=TA_LEFT, leading=11
)
tbl_cell_bold = ParagraphStyle(
"TblCellBold", parent=tbl_cell,
fontName="Helvetica-Bold", textColor=DARK_BLUE
)
story = []
# ── Helper functions ─────────────────────────────────────────────────────────
def section_banner(title, color=DARK_BLUE):
"""A coloured banner for section headings."""
data = [[Paragraph(title, h1)]]
tbl = Table(data, colWidths=[17.4*cm])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), color),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
("ROUNDEDCORNERS", [4, 4, 4, 4]),
]))
return tbl
def make_table(headers, rows, col_widths=None):
"""Styled table with alternating row colours."""
header_row = [Paragraph(h, tbl_header) for h in headers]
data = [header_row]
for i, row in enumerate(rows):
styled = []
for j, cell in enumerate(row):
if j == 0:
styled.append(Paragraph(cell, tbl_cell_bold))
else:
styled.append(Paragraph(cell, tbl_cell))
data.append(styled)
if col_widths is None:
w = 17.4 / len(headers)
col_widths = [w*cm] * len(headers)
tbl = Table(data, colWidths=col_widths, repeatRows=1)
style_cmds = [
("BACKGROUND", (0,0), (-1,0), TABLE_HEAD),
("ROWBACKGROUNDS", (0,1), (-1,-1), [WHITE, ROW_ALT]),
("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#c7d7f0")),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
]
tbl.setStyle(TableStyle(style_cmds))
return tbl
def mnemonic_box(lines):
"""Green highlighted mnemonic box."""
content = [Paragraph("💡 MNEMONIC / RECALL", ParagraphStyle(
"MH", parent=styles["Normal"], fontSize=9, fontName="Helvetica-Bold",
textColor=GREEN_DARK, leading=12
))]
for line in lines:
content.append(Paragraph("• " + line, mnemonic_style))
data = [[content]]
tbl = Table([[c] for c in content], colWidths=[17.4*cm])
# Use single table with all content
all_content = [Paragraph("💡 MNEMONIC / RECALL", ParagraphStyle(
"MH", parent=styles["Normal"], fontSize=9, fontName="Helvetica-Bold",
textColor=GREEN_DARK, leading=12, spaceBefore=2
))]
for line in lines:
all_content.append(Paragraph(" • " + line, mnemonic_style))
outer = Table([[all_content]], colWidths=[17.4*cm])
outer.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), GREEN_BG),
("BOX", (0,0), (-1,-1), 1, GREEN_DARK),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
]))
return outer
def tip_box(lines, title="⚠️ EXAM TIPS"):
all_content = [Paragraph(title, ParagraphStyle(
"TH", parent=styles["Normal"], fontSize=9, fontName="Helvetica-Bold",
textColor=RED_DARK, leading=12, spaceBefore=2
))]
for line in lines:
all_content.append(Paragraph(" • " + line, tip_style))
outer = Table([[all_content]], colWidths=[17.4*cm])
outer.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), RED_BG),
("BOX", (0,0), (-1,-1), 1, RED_DARK),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
]))
return outer
# ═══════════════════════════════════════════════════════════════════════════
# COVER PAGE
# ═══════════════════════════════════════════════════════════════════════════
cover_data = [[
Paragraph("Culture Media &<br/>Culture Methods", title_style),
Paragraph("NEET PG High-Yield Revision Guide", subtitle_style),
Paragraph("Microbiology | Complete Rapid Revision", ParagraphStyle(
"S2", parent=styles["Normal"], fontSize=9.5,
textColor=colors.HexColor("#93c5fd"), alignment=TA_CENTER
)),
]]
cover = Table([[
Paragraph("Culture Media & Culture Methods", title_style),
]], colWidths=[17.4*cm])
cover.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), DARK_BLUE),
("TOPPADDING", (0,0), (-1,-1), 30),
("BOTTOMPADDING", (0,0), (-1,-1), 10),
("LEFTPADDING", (0,0), (-1,-1), 20),
("RIGHTPADDING", (0,0), (-1,-1), 20),
]))
story.append(cover)
sub_cover = Table([[
Paragraph("NEET PG High-Yield Revision Guide", subtitle_style),
]], colWidths=[17.4*cm])
sub_cover.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), DARK_BLUE),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 20),
("RIGHTPADDING", (0,0), (-1,-1), 20),
]))
story.append(sub_cover)
badge_data = Table([[
Paragraph("Microbiology | Complete Rapid Revision | All Culture Media Tables", ParagraphStyle(
"badge", parent=styles["Normal"], fontSize=9,
textColor=DARK_BLUE, alignment=TA_CENTER, fontName="Helvetica-Bold"
))
]], colWidths=[17.4*cm])
badge_data.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), LIGHT_BLUE),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
]))
story.append(badge_data)
story.append(Spacer(1, 0.5*cm))
# ═══════════════════════════════════════════════════════════════════════════
# SECTION 1 – HOW TO REVISE
# ═══════════════════════════════════════════════════════════════════════════
story.append(section_banner("PART 1 | How to Revise This Topic Effectively", MED_BLUE))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("The 3-Column Master Strategy", h2))
story.append(Paragraph(
"Make a table with three columns: <b>Organism | Medium | Key Feature / Reason</b>. "
"This single table covers ~90% of NEET PG questions on this topic. "
"Group by organism type: Bacteria → Fungi → Viruses → Parasites.", body))
story.append(Spacer(1, 0.2*cm))
strategy_rows = [
["Day 1", "Read the Master Table (Part 3) once fully"],
["Day 2", "Close book; write Organism → Medium from memory"],
["Day 3", "Solve 20-30 MCQs on culture media only"],
["Day 7", "Rapid recall: colony morphology buzzwords + transport media"],
["Final Week", "Only mnemonics + Past Year Question (PYQ) patterns"],
]
story.append(make_table(["Day", "Activity"], strategy_rows, [4*cm, 13.4*cm]))
story.append(Spacer(1, 0.3*cm))
story.append(mnemonic_box([
"Always ask WHY a medium is used - e.g. alkaline pH for Vibrio because it tolerates high pH.",
"Reasoning helps answer unfamiliar MCQ variants without memorising every detail.",
"Pair tables with Dr. Mamta Jawa / Apurba Sastry video lectures for visual memory."
]))
story.append(Spacer(1, 0.4*cm))
# ═══════════════════════════════════════════════════════════════════════════
# SECTION 2 – CLASSIFICATION
# ═══════════════════════════════════════════════════════════════════════════
story.append(section_banner("PART 2 | Classification of Culture Media"))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("A. By Physical State", h2))
phys_rows = [
["Liquid (Broth)", "Nutrient broth, Robertson's Cooked Meat, Alkaline Peptone Water"],
["Semisolid", "Hugh-Leifson medium (motility testing)"],
["Solid", "Nutrient agar, Blood agar, MacConkey agar"],
]
story.append(make_table(["Type", "Examples"], phys_rows, [5*cm, 12.4*cm]))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("B. By Nutritional Composition (Most Tested in NEET PG)", h2))
nutri_rows = [
["Simple / Basal", "Supports most non-fastidious organisms", "Nutrient agar, Peptone water"],
["Enriched", "Basal + growth factors (blood/serum) for fastidious organisms", "Blood agar, Chocolate agar, Löffler's serum slope"],
["Enrichment", "Suppresses commensals; favours pathogen in mixed specimens", "Selenite F broth (Salmonella), Alkaline peptone water (Vibrio)"],
["Selective", "Inhibits commensals; isolates target organism", "MacConkey, Thayer-Martin, TCBS, Mannitol salt agar"],
["Differential", "Distinguishes organisms by colony appearance", "MacConkey (LF vs NLF), CLED, XLD"],
["Indicator", "Contains pH indicator that changes colour", "MacConkey (neutral red), CLED (bromothymol blue)"],
["Transport", "Preserves viability during transit to lab", "Stuart's, Amies, Cary-Blair, VR medium"],
]
story.append(make_table(["Type", "Definition", "Examples"], nutri_rows,
[3.5*cm, 7*cm, 6.9*cm]))
story.append(Spacer(1, 0.3*cm))
story.append(tip_box([
"Enrichment vs Selective: Enrichment is LIQUID (broth); Selective is SOLID (agar). This distinction is a common MCQ trap.",
"Indicator medium is a sub-type of differential medium - it uses a pH indicator dye.",
]))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════════════
# SECTION 3 – MASTER TABLE: BACTERIA
# ═══════════════════════════════════════════════════════════════════════════
story.append(section_banner("PART 3 | Master Table: Bacteria → Media (HIGH YIELD)"))
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("3A. Gram-Positive Bacteria", h2))
gpos_rows = [
["Corynebacterium diphtheriae",
"Löffler's Serum Slope",
"BEST for metachromatic granules; rapid growth in 6-8 h"],
["Corynebacterium diphtheriae",
"McLeod's / Hoyle's Tellurite",
"Black colonies; SELECTIVE medium"],
["Corynebacterium diphtheriae",
"Tinsdale Agar",
"Black colonies with brown halo (tellurite + cystine)"],
["Staphylococcus aureus",
"Mannitol Salt Agar (7.5% NaCl)",
"Yellow colonies (mannitol fermentation); SELECTIVE"],
["Staphylococcus aureus",
"Baird-Parker Agar",
"Black shiny colonies + opaque (egg yolk) halo"],
["Streptococcus pneumoniae",
"Blood Agar",
"Alpha-haemolysis (green); draughtsman/coin/concentric ring colonies"],
["Streptococcus pyogenes",
"Blood Agar",
"Beta-haemolysis; dew-drop colonies"],
["Clostridium perfringens",
"Nagler's Medium (Egg yolk agar)",
"Nagler reaction - opalescence due to lecithinase"],
["Clostridia (anaerobes)",
"Robertson's Cooked Meat (RCM) / Thioglycolate broth",
"Anaerobic enrichment medium"],
["Lactobacillus",
"Rogosa SL Agar",
"Acidic pH (pH 5.5); selective for lactobacilli"],
["Actinomyces",
"Brain Heart Infusion (BHI)",
"Anaerobic; sulfur granules in pus (not cultured on simple media)"],
]
story.append(make_table(["Organism", "Medium", "Key Detail / Trick"],
gpos_rows, [5.5*cm, 5.5*cm, 6.4*cm]))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("3B. Gram-Negative Bacteria", h2))
gneg_rows = [
["Vibrio cholerae",
"TCBS (Thiosulphate Citrate Bile Salt Sucrose)",
"Yellow colonies (sucrose fermenter); SELECTIVE-DIFFERENTIAL"],
["Vibrio cholerae",
"Alkaline Peptone Water (APW), pH 8.6",
"ENRICHMENT broth; Vibrio survives high pH"],
["Vibrio cholerae",
"Monsur's Tellurite Taurocholate Gelatin",
"Grey colonies with turbid halo"],
["Salmonella typhi",
"Bismuth Sulphite Agar (Wilson-Blair)",
"Black colonies + metallic green/black sheen; HIGHLY selective"],
["Salmonella (non-typhi)",
"XLD (Xylose Lysine Deoxycholate)",
"Pink with black centre (H2S); Shigella: pink without black"],
["Salmonella / Shigella",
"Selenite F Broth",
"ENRICHMENT; Salmonella >> Shigella inhibited"],
["Salmonella / Shigella",
"DCA (Deoxycholate Citrate Agar)",
"SELECTIVE-DIFFERENTIAL for enteric pathogens"],
["Salmonella / Shigella",
"SS Agar",
"Salmonella-Shigella agar; used in routine labs"],
["E. coli / Coliforms",
"MacConkey Agar",
"Lactose fermenter → pink/red colonies; NLF are colourless"],
["E. coli",
"EMB Agar (Eosin Methylene Blue)",
"Metallic green sheen (rapid LF); NLF are pink"],
["E. coli / Urine",
"CLED Agar",
"Prevents Proteus swarming; electrolyte-deficient"],
["Neisseria gonorrhoeae",
"Thayer-Martin Agar",
"Contains VCN: Vancomycin, Colistin, Nystatin"],
["Neisseria meningitidis",
"Chocolate Agar",
"Heated blood = releases X and V factors; fastidious organisms"],
["H. influenzae",
"Levinthal's Agar",
"Iridescence (satellite phenomenon)"],
["H. influenzae",
"Fildes Agar",
"Enriched with peptic digest of blood (X+V factors)"],
["Bordetella pertussis",
"Bordet-Gengou (BG) Agar",
"Mercury drop / bisected pearl colonies; 50% blood"],
["Bordetella pertussis",
"Regan-Lowe Agar",
"Charcoal-based; more sensitive than BG"],
["Campylobacter",
"Skirrow's Medium",
"Selective; incubated 42°C, microaerophilic (5% O2)"],
["H. pylori",
"Skirrow's / BHIB Agar",
"Urease positive; microaerophilic"],
["Pseudomonas aeruginosa",
"Cetrimide Agar",
"Selective; produces fluorescent pigments (pyocyanin, pyoverdin)"],
["Brucella",
"Castaneda's Medium",
"Diphasic medium (liquid + solid); CO2 required (B. abortus)"],
["Leptospira",
"Fletcher's / EMJH Medium",
"Semisolid; dark-field microscopy used to confirm"],
["Yersinia pestis",
"MacConkey / Nutrient Agar",
"Stalactite growth in broth; hammered metal appearance on agar"],
["Legionella",
"BCYE Agar (Buffered Charcoal Yeast Extract)",
"Requires L-cysteine and iron; cannot grow on blood agar"],
]
story.append(make_table(["Organism", "Medium", "Key Detail / Trick"],
gneg_rows, [5.5*cm, 5.5*cm, 6.4*cm]))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("3C. Mycobacteria", h2))
myco_rows = [
["Mycobacterium tuberculosis",
"Löwenstein-Jensen (LJ) Medium",
"Rough Raised Buff-colored (RRBC) colonies; 6-8 weeks"],
["Mycobacterium tuberculosis",
"Middlebrook 7H10 / 7H11",
"Transparent agar; faster than LJ; for drug susceptibility"],
["Mycobacterium tuberculosis",
"BACTEC / MGIT (Mycobacteria Growth Indicator Tube)",
"FASTEST; radiometric/fluorescent; ~2 weeks"],
["Mycobacterium leprae",
"Cannot be cultured on artificial media",
"Cultured in armadillo footpad / mouse footpad only"],
["Atypical Mycobacteria (NTM)",
"LJ at 25°C, 37°C, 42°C",
"Growth temperature helps in species identification"],
]
story.append(make_table(["Organism", "Medium", "Key Detail"],
myco_rows, [5.5*cm, 5.5*cm, 6.4*cm]))
story.append(Spacer(1, 0.3*cm))
story.append(tip_box([
"BACTEC/MGIT = FASTEST for MTB culture (NEET PG favourite).",
"M. leprae = CANNOT be cultured on any artificial medium (armadillo footpad = only in-vivo model).",
"LJ medium contains malachite green (inhibits other bacteria) + egg (solidifying agent).",
]))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════════════
# SECTION 4 – FUNGI
# ═══════════════════════════════════════════════════════════════════════════
story.append(section_banner("PART 4 | Fungi - Culture Media", colors.HexColor("#6d28d9")))
story.append(Spacer(1, 0.2*cm))
fungi_rows = [
["All fungi (standard)", "Sabouraud's Dextrose Agar (SDA)", "pH 5.6; cycloheximide + chloramphenicol added; 25°C"],
["Cryptococcus neoformans", "Birdseed / Niger Seed Agar", "Brown colonies - phenol oxidase enzyme; urease positive"],
["Candida albicans", "Corn Meal Agar", "Chlamydospores (terminal); germ tube test at 37°C"],
["Candida albicans", "Chrome Agar", "Green colonies for C. albicans; other Candida spp. differ"],
["Dermatophytes", "Dermatophyte Test Medium (DTM)", "Red colour change (alkaline pH) in 10-14 days"],
["Dimorphic fungi (all)", "SDA at 25°C = Mould form", "Mould at room temp; Yeast at body temp (37°C)"],
["Aspergillus", "SDA / Czapek-Dox Agar", "Conidiophores; species identified by colony colour"],
["Malassezia furfur", "SDA + olive oil overlay", "Lipophilic; requires exogenous lipids to grow"],
]
story.append(make_table(["Organism", "Medium", "Key Detail"],
fungi_rows, [5.5*cm, 5.5*cm, 6.4*cm]))
story.append(Spacer(1, 0.3*cm))
story.append(mnemonic_box([
"SDA = Standard for ALL fungi (pH 5.6 = acidic, inhibits bacteria)",
"Birdseed agar → Cryptococcus → Brown (phenol oxidase = melanin production)",
"Dimorphic = Dual form: Cold (25°C) = Mould; Warm (37°C) = Yeast → 'Cold = Mould; Warm = Yeast'",
"Malassezia = Lipophilic = needs olive oil on SDA",
]))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════════════
# SECTION 5 – VIRUSES
# ═══════════════════════════════════════════════════════════════════════════
story.append(section_banner("PART 5 | Virus Culture Methods", colors.HexColor("#b45309")))
story.append(Spacer(1, 0.2*cm))
virus_rows = [
["Cell Culture (most common method)",
"Cytopathic Effect (CPE) observed",
"Most viruses; HSV, CMV, Adenovirus, Poliovirus"],
["Embryonated Egg - CAM route",
"Pocks on CAM",
"Poxviruses (smallpox, vaccinia)"],
["Embryonated Egg - Amniotic route",
"Haemagglutination",
"Influenza (primary isolation)"],
["Embryonated Egg - Allantoic route",
"HA in allantoic fluid",
"Influenza, Mumps (propagation)"],
["Embryonated Egg - Yolk sac",
"Growth in yolk sac",
"Chlamydia, Rickettsia, Arboviruses"],
["Animal Inoculation",
"Signs in animal",
"Rabies (mouse intracerebral), Arboviruses, Coxsackie A"],
["Cannot be cultured",
"No growth on any artificial medium",
"Hep B, Hep C, Parvovirus B19, Norovirus"],
]
story.append(make_table(["Method", "Indicator of Growth", "Key Viruses"],
virus_rows, [5*cm, 5.5*cm, 6.9*cm]))
story.append(Spacer(1, 0.3*cm))
story.append(mnemonic_box([
"CAM = Chorioallantoic Membrane → Pocks → POXvirus",
"Influenza: Amniotic (primary isolation) → Allantoic (propagation)",
"Rabies → Mouse intracerebral → Negri bodies in hippocampus (Ammon's horn)",
]))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════════════
# SECTION 6 – TRANSPORT MEDIA
# ═══════════════════════════════════════════════════════════════════════════
story.append(section_banner("PART 6 | Transport Media"))
story.append(Spacer(1, 0.2*cm))
transport_rows = [
["Stuart's Medium", "General bacteria; Gonococci (without charcoal)"],
["Amies Medium", "Gonococci (with charcoal); general bacteria"],
["Cary-Blair Medium", "Vibrio cholerae, Campylobacter, enteric organisms (faecal specimens)"],
["VR Medium (Venkatraman-Ramakrishnan)", "Vibrio cholerae (alkaline, pH 9.2)"],
["Pike's Medium", "Streptococci from throat swabs"],
["Buffered Glycerol Saline", "Shigella (in stool specimens)"],
["Alkaline Glycerol Saline", "Shigella (alternative)"],
["Loeffler's Medium", "Corynebacterium diphtheriae (also an enriched medium)"],
["Liquid Nitrogen / Glycerol broth", "Long-term storage of cultures"],
]
story.append(make_table(["Medium", "Organism / Specimen"], transport_rows, [8*cm, 9.4*cm]))
story.append(Spacer(1, 0.3*cm))
story.append(tip_box([
"VR medium = ONLY for Vibrio cholerae transport (alkaline pH 9.2).",
"Stuart's vs Amies: Stuart's has no charcoal; Amies has charcoal (charcoal absorbs toxic metabolites for fastidious organisms).",
"Buffered Glycerol Saline = Shigella in stool - a common MCQ question.",
]))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════════════
# SECTION 7 – SPECIAL CULTURE CONDITIONS
# ═══════════════════════════════════════════════════════════════════════════
story.append(section_banner("PART 7 | Special Culture Conditions & Methods"))
story.append(Spacer(1, 0.2*cm))
conditions_rows = [
["Capnophilic (5-10% CO2)",
"CO2 incubator / candle jar",
"H. influenzae, Neisseria, Brucella abortus, Streptococcus pneumoniae"],
["Microaerophilic (5% O2, 10% CO2)",
"GasPak jar / specific generators",
"Campylobacter (42°C), H. pylori, Helicobacter spp."],
["Anaerobic culture (0% O2)",
"Anaerobic jar / glove box",
"Clostridia, Bacteroides, Fusobacterium, Actinomyces"],
["Candle jar",
"Simple CO2 source (~3%)",
"Neisseria, H. influenzae (field / resource-limited settings)"],
["BACTEC / MGIT",
"Automated radiometric / fluorescent",
"MTB - fastest culture method (~2 weeks)"],
["Cell culture",
"CPE / immunofluorescence",
"Viruses, Chlamydia, Rickettsia (obligate intracellular)"],
["Hanging drop preparation",
"Dark-field / phase contrast microscopy",
"Motility of Vibrio cholerae - darting (shooting star) motility"],
["Armadillo footpad",
"In vivo model",
"M. leprae (only viable model for cultivation)"],
]
story.append(make_table(["Condition / Method", "Technique", "Organisms"],
conditions_rows, [5*cm, 5*cm, 7.4*cm]))
story.append(Spacer(1, 0.3*cm))
# ═══════════════════════════════════════════════════════════════════════════
# SECTION 8 – COLONY MORPHOLOGY BUZZWORDS
# ═══════════════════════════════════════════════════════════════════════════
story.append(section_banner("PART 8 | Colony Morphology Buzzwords (Very High Yield)"))
story.append(Spacer(1, 0.2*cm))
colony_rows = [
["Mercury drop / Bisected pearl", "Bordetella pertussis on Bordet-Gengou agar"],
["Medusa head / Inverted fir tree", "Bacillus anthracis on nutrient agar"],
["String of pearls (gelatin stab)", "Bacillus anthracis"],
["Draughtsman / Coin / Concentric rings", "Streptococcus pneumoniae on blood agar"],
["Dew drop", "Streptococcus pyogenes on blood agar"],
["Beaten copper / Cauliflower", "Actinomyces israelii"],
["Black colonies + metallic sheen", "Salmonella typhi on Bismuth Sulphite (Wilson-Blair) agar"],
["Metallic green sheen", "E. coli on EMB agar"],
["Fried egg", "Mycoplasma pneumoniae (tiny, needs 2-3 weeks)"],
["Breadcrumb", "Nocardia asteroides"],
["Yellow sulfur granules in pus", "Actinomyces israelii (not cultured but seen in specimen)"],
["Mushroom / Umbrella (in gelatin)", "Proteus vulgaris"],
["Stalactite growth (in broth)", "Yersinia pestis"],
["Oil paint appearance", "Pseudomonas aeruginosa on agar"],
["Swarming growth", "Proteus mirabilis / vulgaris on blood agar"],
["Satellite phenomenon", "H. influenzae around S. aureus (provides X+V factors)"],
["Wedge-shaped / Tenacious", "Bacillus anthracis - non-haemolytic, non-motile"],
]
story.append(make_table(["Colony Appearance", "Organism / Medium"],
colony_rows, [8*cm, 9.4*cm]))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════════════
# SECTION 9 – MNEMONICS
# ═══════════════════════════════════════════════════════════════════════════
story.append(section_banner("PART 9 | Key Mnemonics for Rapid Recall", colors.HexColor("#065f46")))
story.append(Spacer(1, 0.2*cm))
mnemonics = [
("TCBS = Yellow for Vibrio",
"Vibrio causes rice-water diarrhoea → think yellow watery stools → YELLOW colonies on TCBS"),
("LJ for MTB = BRR (Buff, Rough, Raised)",
"BRR = 'Brrr it's cold and takes LONG' → 6-8 weeks, like winter"),
("Thayer-Martin = VCN",
"V = Vancomycin (blocks Gram+ve), C = Colistin (blocks Gram-ve), N = Nystatin (blocks fungi)"),
("MacConkey = Pink = Lactose Fermenters",
"PICK = Pink Is Coliforms using Ketones (LF) → E. coli, Klebsiella, Enterobacter"),
("CLED = No Creep",
"CLED prevents Proteus swarming → 'Cled says No Creep allowed'"),
("Cold = Mould; Warm = Yeast (Dimorphic fungi)",
"25°C → Mould (in nature); 37°C → Yeast (in body) → Mnemonic: 'Moulds in the Cold'"),
("Cannot culture on artificial media",
"TRC = Treponema pallidum, Rickettsia, Chlamydia + M. leprae → all OBLIGATE intracellular / specialized"),
("Enrichment media = BROTH (Liquid)",
"Enrichment = ENRICH the target in BROTH before plating on selective solid agar"),
("Bordet-Gengou = Bordetella",
"Both start with 'Bord' → easy recall"),
("Wilson-Blair = Salmonella typhi ONLY",
"W-B = Black sheen = Typhoid → 'Black flag for Typhoid'"),
("BCYE for Legionella",
"B = Buffered, C = Charcoal, Y = Yeast extract, E = Requires L-cysteine → 'BCYE for Battlefield Legionnaire'"),
]
for mnem, explanation in mnemonics:
box_content = [
Paragraph(mnem, ParagraphStyle("MH2", parent=styles["Normal"], fontSize=10,
fontName="Helvetica-Bold", textColor=GREEN_DARK, leading=13)),
Paragraph(explanation, ParagraphStyle("ME2", parent=styles["Normal"], fontSize=9,
fontName="Helvetica", textColor=GREY_TEXT,
leading=12, leftIndent=10))
]
m_tbl = Table([[box_content]], colWidths=[17.4*cm])
m_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), GREEN_BG),
("BOX", (0,0), (-1,-1), 0.8, GREEN_DARK),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
]))
story.append(m_tbl)
story.append(Spacer(1, 0.15*cm))
story.append(PageBreak())
# ═══════════════════════════════════════════════════════════════════════════
# SECTION 10 – PYQ PATTERNS
# ═══════════════════════════════════════════════════════════════════════════
story.append(section_banner("PART 10 | Past Year NEET PG Question Patterns", ACCENT))
story.append(Spacer(1, 0.2*cm))
pyq_rows = [
["1", "Medium for Vibrio cholerae isolation", "TCBS agar (yellow colonies)"],
["2", "Enrichment broth for Vibrio cholerae", "Alkaline Peptone Water (pH 8.6)"],
["3", "Transport medium for V. cholerae", "VR Medium / Cary-Blair"],
["4", "FASTEST method for MTB culture", "BACTEC / MGIT"],
["5", "Medium for Bordetella pertussis", "Bordet-Gengou (primary) / Regan-Lowe"],
["6", "Colony description of B. pertussis", "Mercury drop / Bisected pearl on BG agar"],
["7", "Cannot be cultured on artificial media", "Treponema pallidum, M. leprae"],
["8", "Enrichment medium for Salmonella", "Selenite F Broth"],
["9", "Selective medium for Neisseria", "Thayer-Martin (VCN)"],
["10", "Fried egg colony organism", "Mycoplasma pneumoniae"],
["11", "Medium for urine culture (standard)", "CLED Agar (no Proteus swarming)"],
["12", "Medium for C. diphtheriae (granules)", "Löffler's Serum Slope"],
["13", "Selective medium for C. diphtheriae", "McLeod's Tellurite (black colonies)"],
["14", "Black metallic sheen on Bismuth sulphite", "Salmonella typhi"],
["15", "Metallic green sheen on EMB", "E. coli"],
["16", "Organism needing olive oil on SDA", "Malassezia furfur"],
["17", "Brown colonies on birdseed agar", "Cryptococcus neoformans"],
["18", "Dimorphic fungi temperature rule", "25°C = Mould; 37°C = Yeast"],
["19", "Temperature for Campylobacter culture", "42°C, microaerophilic"],
["20", "Medium requiring L-cysteine + iron", "BCYE agar → Legionella"],
]
story.append(make_table(["#", "Question Theme", "Answer"],
pyq_rows, [1*cm, 9.4*cm, 7*cm]))
story.append(Spacer(1, 0.5*cm))
story.append(HRFlowable(width="100%", thickness=1, color=MED_BLUE))
story.append(Spacer(1, 0.2*cm))
footer_style = ParagraphStyle("footer", parent=styles["Normal"],
fontSize=8.5, fontName="Helvetica", textColor=colors.HexColor("#6b7280"),
alignment=TA_CENTER, leading=12)
story.append(Paragraph(
"Culture Media & Culture Methods | NEET PG High-Yield Revision Guide | "
"Based on Apurba Sastry Microbiology & Standard NEET PG Curriculum",
footer_style))
# ── Build PDF ────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF created successfully: {OUTPUT}")