~/infection-pathology-pdf/generate_pdf.py
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether, PageBreak
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import cm, mm
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus.flowables import Flowable
# ── Color palette ──────────────────────────────────────────────────────────────
DARK_BLUE = colors.HexColor("#1A2E4A")
MID_BLUE = colors.HexColor("#2C5282")
ACCENT_BLUE = colors.HexColor("#3182CE")
LIGHT_BLUE = colors.HexColor("#EBF8FF")
TEAL = colors.HexColor("#2B6CB0")
RED_ACCENT = colors.HexColor("#C53030")
ORANGE = colors.HexColor("#DD6B20")
GREEN = colors.HexColor("#276749")
LIGHT_GRAY = colors.HexColor("#F7FAFC")
MID_GRAY = colors.HexColor("#E2E8F0")
DARK_GRAY = colors.HexColor("#4A5568")
WHITE = colors.white
BLACK = colors.HexColor("#1A202C")
PAGE_W, PAGE_H = A4
MARGIN = 1.8 * cm
# ── Document ───────────────────────────────────────────────────────────────────
output_path = "/tmp/workspace/infection-pathology-pdf/Pathogenic_Mechanisms_Immune_Evasion.pdf"
doc = SimpleDocTemplate(
output_path,
pagesize=A4,
leftMargin=MARGIN, rightMargin=MARGIN,
topMargin=MARGIN, bottomMargin=MARGIN,
title="Pathogenic Mechanisms & Immune Evasion – Quick Reference",
author="Orris Medical Library",
)
# ── Styles ─────────────────────────────────────────────────────────────────────
base = getSampleStyleSheet()
def S(name, **kw):
return ParagraphStyle(name, **kw)
styles = {
"cover_title": S("cover_title",
fontSize=26, leading=32, fontName="Helvetica-Bold",
textColor=WHITE, alignment=TA_CENTER, spaceAfter=6),
"cover_sub": S("cover_sub",
fontSize=13, leading=18, fontName="Helvetica",
textColor=colors.HexColor("#BEE3F8"), alignment=TA_CENTER, spaceAfter=4),
"cover_note": S("cover_note",
fontSize=9, leading=12, fontName="Helvetica-Oblique",
textColor=colors.HexColor("#90CDF4"), alignment=TA_CENTER),
"section_title": S("section_title",
fontSize=13, leading=17, fontName="Helvetica-Bold",
textColor=WHITE, spaceBefore=4, spaceAfter=6),
"sub_heading": S("sub_heading",
fontSize=10.5, leading=14, fontName="Helvetica-Bold",
textColor=MID_BLUE, spaceBefore=8, spaceAfter=3),
"body": S("body",
fontSize=9, leading=13, fontName="Helvetica",
textColor=BLACK, spaceAfter=3, alignment=TA_JUSTIFY),
"body_bold": S("body_bold",
fontSize=9, leading=13, fontName="Helvetica-Bold",
textColor=BLACK, spaceAfter=2),
"bullet": S("bullet",
fontSize=9, leading=13, fontName="Helvetica",
textColor=BLACK, spaceAfter=2,
leftIndent=14, firstLineIndent=-10),
"source": S("source",
fontSize=7.5, leading=10, fontName="Helvetica-Oblique",
textColor=DARK_GRAY, alignment=TA_CENTER, spaceBefore=4),
"table_hdr": S("table_hdr",
fontSize=8.5, leading=11, fontName="Helvetica-Bold",
textColor=WHITE, alignment=TA_CENTER),
"table_cell": S("table_cell",
fontSize=8, leading=11, fontName="Helvetica",
textColor=BLACK, alignment=TA_LEFT),
"table_cell_c": S("table_cell_c",
fontSize=8, leading=11, fontName="Helvetica",
textColor=BLACK, alignment=TA_CENTER),
"tag_blue": S("tag_blue",
fontSize=7.5, leading=10, fontName="Helvetica-Bold",
textColor=WHITE, backColor=ACCENT_BLUE, alignment=TA_CENTER),
"tag_red": S("tag_red",
fontSize=7.5, leading=10, fontName="Helvetica-Bold",
textColor=WHITE, backColor=RED_ACCENT, alignment=TA_CENTER),
"tag_green": S("tag_green",
fontSize=7.5, leading=10, fontName="Helvetica-Bold",
textColor=WHITE, backColor=GREEN, alignment=TA_CENTER),
"tag_orange": S("tag_orange",
fontSize=7.5, leading=10, fontName="Helvetica-Bold",
textColor=WHITE, backColor=ORANGE, alignment=TA_CENTER),
"key_concept": S("key_concept",
fontSize=9, leading=13, fontName="Helvetica",
textColor=DARK_BLUE, spaceAfter=2,
leftIndent=10, backColor=LIGHT_BLUE),
}
# ── Helper: colored section banner ────────────────────────────────────────────
def section_banner(text, bg=MID_BLUE, number=None):
label = f"<b>{number}. {text}</b>" if number else f"<b>{text}</b>"
cell = Paragraph(label, styles["section_title"])
tbl = Table([[cell]], colWidths=[PAGE_W - 2*MARGIN])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("ROUNDEDCORNERS", [4, 4, 4, 4]),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
("TOPPADDING", (0,0), (-1,-1), 7),
("BOTTOMPADDING",(0,0), (-1,-1), 7),
]))
return tbl
def key_box(text, bg=LIGHT_BLUE, border=ACCENT_BLUE):
p = Paragraph(text, styles["key_concept"])
tbl = Table([[p]], colWidths=[PAGE_W - 2*MARGIN])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("LINEAFTER", (0,0), (0,-1), 2, border),
("LINEBEFORE", (0,0), (0,-1), 4, border),
("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 tbl
def hr(color=MID_GRAY, thickness=0.5):
return HRFlowable(width="100%", thickness=thickness, color=color, spaceAfter=4, spaceBefore=4)
def P(text, style="body"):
return Paragraph(text, styles[style])
def B(text):
return Paragraph(f"• {text}", styles["bullet"])
def SP(n=4):
return Spacer(1, n)
# ── COVER PAGE ─────────────────────────────────────────────────────────────────
def build_cover():
elements = []
# Full-page header block
cover_data = [[
Paragraph("GENERAL PATHOLOGY", styles["cover_sub"]),
]]
cover_tbl = Table(cover_data, colWidths=[PAGE_W - 2*MARGIN])
cover_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), DARK_BLUE),
("TOPPADDING", (0,0), (-1,-1), 28),
("BOTTOMPADDING",(0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 20),
("RIGHTPADDING", (0,0), (-1,-1), 20),
]))
elements.append(cover_tbl)
title_data = [[
Paragraph("Pathogenic Mechanisms<br/>& Immune Evasion", styles["cover_title"]),
]]
title_tbl = Table(title_data, colWidths=[PAGE_W - 2*MARGIN])
title_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), DARK_BLUE),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING",(0,0), (-1,-1), 24),
("LEFTPADDING", (0,0), (-1,-1), 20),
("RIGHTPADDING", (0,0), (-1,-1), 20),
]))
elements.append(title_tbl)
sub_data = [[
Paragraph("QUICK REFERENCE • Based on Robbins & Kumar Pathologic Basis of Disease", styles["cover_note"]),
]]
sub_tbl = Table(sub_data, colWidths=[PAGE_W - 2*MARGIN])
sub_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), MID_BLUE),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING",(0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
]))
elements.append(sub_tbl)
elements.append(SP(18))
# Contents card
toc_items = [
("1", "How Microbes Cause Disease – Overview", ACCENT_BLUE),
("2", "Direct Cytopathic Effects", GREEN),
("3", "Toxin-Mediated Mechanisms", ORANGE),
("4", "Host Immune-Mediated Injury", RED_ACCENT),
("5", "Spectrum of Inflammatory Responses", MID_BLUE),
("6", "Immune Evasion Strategies", TEAL),
("7", "Infections in Immunocompromised Hosts", DARK_BLUE),
("8", "Key Concepts Summary", DARK_GRAY),
]
rows = []
for num, title, col in toc_items:
num_p = Paragraph(f"<b>{num}</b>", ParagraphStyle("n", fontSize=11, fontName="Helvetica-Bold", textColor=col, alignment=TA_CENTER))
title_p = Paragraph(title, ParagraphStyle("t", fontSize=10, fontName="Helvetica", textColor=BLACK))
rows.append([num_p, title_p])
toc_tbl = Table(rows, colWidths=[1.2*cm, PAGE_W - 2*MARGIN - 1.5*cm])
toc_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), LIGHT_GRAY),
("ROWBACKGROUNDS",(0,0),(-1,-1), [WHITE, LIGHT_GRAY]),
("LINEBELOW", (0,0), (-1,-2), 0.3, MID_GRAY),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING",(0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
elements.append(toc_tbl)
elements.append(SP(14))
elements.append(P("Source: Robbins, Cotran & Kumar – Pathologic Basis of Disease, Chapter 8", "source"))
elements.append(PageBreak())
return elements
# ── PAGE 2: Overview + Direct Cytopathic Effects ──────────────────────────────
def build_page2():
elements = []
# Section 1
elements.append(section_banner("How Microbes Cause Disease – Overview", MID_BLUE, "1"))
elements.append(SP(6))
elements.append(P(
"Infectious diseases result from interplay between <b>microbial virulence factors</b> and <b>host responses</b>. "
"Pathogens cause harm through three main mechanisms: direct cell injury, toxin release, and induction of damaging immune responses. "
"The same organism may produce very different pathology depending on host immune status.", "body"))
elements.append(SP(4))
elements.append(key_box(
"<b>Core principle:</b> A pathogen establishes infection if its virulence factors overcome normal host defenses OR if host defenses are compromised."))
elements.append(SP(8))
# Three mechanism boxes side by side
mech_headers = [
Paragraph("<b>Direct Cytopathic</b>", styles["table_hdr"]),
Paragraph("<b>Toxin-Mediated</b>", styles["table_hdr"]),
Paragraph("<b>Immune-Mediated</b>", styles["table_hdr"]),
]
mech_bodies = [
Paragraph("Viruses kill host cells by:\n• Disrupting metabolism\n• Inhibiting protein synthesis\n• Inducing apoptosis", styles["table_cell"]),
Paragraph("Bacteria release:\n• Endotoxins (LPS)\n• Exotoxins (A-B toxins)\n• Superantigens", styles["table_cell"]),
Paragraph("Host immunity damages:\n• Granulomas (TB)\n• Immune complexes (GN)\n• Molecular mimicry (RHD)", styles["table_cell"]),
]
col_w = (PAGE_W - 2*MARGIN - 0.6*cm) / 3
mech_tbl = Table(
[mech_headers, mech_bodies],
colWidths=[col_w]*3
)
mech_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), MID_BLUE),
("BACKGROUND", (0,1), (0,1), LIGHT_BLUE),
("BACKGROUND", (1,1), (1,1), colors.HexColor("#FFFAF0")),
("BACKGROUND", (2,1), (2,1), colors.HexColor("#FFF5F5")),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("TOPPADDING", (0,0), (-1,-1), 7),
("BOTTOMPADDING",(0,0), (-1,-1), 7),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("ALIGN", (0,0), (-1,0), "CENTER"),
("VALIGN", (0,0), (-1,-1), "TOP"),
("GRID", (0,0), (-1,-1), 0.5, MID_GRAY),
]))
elements.append(mech_tbl)
elements.append(SP(12))
# Section 2
elements.append(section_banner("Direct Cytopathic Effects", colors.HexColor("#276749"), "2"))
elements.append(SP(6))
cyto_data = [
[Paragraph("<b>Mechanism</b>", styles["table_hdr"]),
Paragraph("<b>Pathogens</b>", styles["table_hdr"]),
Paragraph("<b>Result</b>", styles["table_hdr"])],
[P("Lytic destruction of host cell", "table_cell"),
P("Poliovirus, adenovirus", "table_cell"),
P("Cell death, tissue damage", "table_cell")],
[P("Inhibition of host protein synthesis", "table_cell"),
P("HSV, influenza virus", "table_cell"),
P("Cellular dysfunction → necrosis", "table_cell")],
[P("Induction of apoptosis", "table_cell"),
P("HIV, Adenovirus, HBV", "table_cell"),
P("Programmed cell death", "table_cell")],
[P("Multinucleation (syncytia)", "table_cell"),
P("Measles, HSV, RSV", "table_cell"),
P("Giant cells; impaired function", "table_cell")],
[P("Viral inclusion bodies", "table_cell"),
P("CMV (owl-eye), rabies (Negri)", "table_cell"),
P("Diagnostic histologic feature", "table_cell")],
[P("Cell transformation/proliferation", "table_cell"),
P("HPV, EBV, HTLV-1", "table_cell"),
P("Neoplasia / cancer", "table_cell")],
]
col_ws = [5.8*cm, 5.5*cm, 5.5*cm]
cyto_tbl = Table(cyto_data, colWidths=col_ws, repeatRows=1)
cyto_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), GREEN),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1), (-1,-1), [WHITE, LIGHT_GRAY]),
("GRID", (0,0), (-1,-1), 0.4, MID_GRAY),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("ALIGN", (0,0), (-1,0), "CENTER"),
]))
elements.append(cyto_tbl)
elements.append(SP(8))
elements.append(P("Source: Robbins & Kumar Pathologic Basis of Disease, Ch. 8", "source"))
elements.append(PageBreak())
return elements
# ── PAGE 3: Toxin-Mediated + Immune-Mediated ──────────────────────────────────
def build_page3():
elements = []
# Section 3 – Toxins
elements.append(section_banner("Toxin-Mediated Mechanisms", ORANGE, "3"))
elements.append(SP(6))
# 3A: Endotoxin
elements.append(P("3A • Endotoxin (Lipopolysaccharide – LPS)", "sub_heading"))
endo_rows = [
[Paragraph("<b>Feature</b>", styles["table_hdr"]), Paragraph("<b>Detail</b>", styles["table_hdr"])],
[P("Source", "table_cell"), P("Outer membrane of <b>gram-negative</b> bacteria", "table_cell")],
[P("Component", "table_cell"), P("Lipid A (toxic moiety) + O antigen polysaccharide", "table_cell")],
[P("Receptor", "table_cell"), P("TLR4/MD-2 complex on macrophages and monocytes", "table_cell")],
[P("Low doses", "table_cell"), P("Fever, complement activation, macrophage priming", "table_cell")],
[P("High doses", "table_cell"), P("Septic shock, DIC, multiorgan failure", "table_cell")],
[P("Key mediators", "table_cell"), P("TNF-α, IL-1, IL-6, IL-12, nitric oxide", "table_cell")],
[P("Examples", "table_cell"), P("E. coli, Neisseria meningitidis, Klebsiella, Salmonella", "table_cell")],
]
endo_tbl = Table(endo_rows, colWidths=[4.5*cm, PAGE_W - 2*MARGIN - 4.8*cm], repeatRows=1)
endo_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), ORANGE),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, colors.HexColor("#FFF8F0")]),
("GRID", (0,0), (-1,-1), 0.4, MID_GRAY),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("ALIGN", (0,0), (-1,0), "CENTER"),
]))
elements.append(endo_tbl)
elements.append(SP(8))
# 3B: Exotoxins
elements.append(P("3B • Exotoxins – Types & Mechanisms", "sub_heading"))
exo_rows = [
[Paragraph("<b>Type</b>", styles["table_hdr"]),
Paragraph("<b>Mechanism</b>", styles["table_hdr"]),
Paragraph("<b>Examples</b>", styles["table_hdr"]),
Paragraph("<b>Disease</b>", styles["table_hdr"])],
[P("Membrane-disrupting\n(Pore-forming)", "table_cell"),
P("Lyse RBCs and leukocytes by inserting pores into cell membranes", "table_cell"),
P("Staphylococcal α-toxin, Streptolysins", "table_cell"),
P("Tissue necrosis, hemolysis", "table_cell")],
[P("A-B Toxins\n(binary)", "table_cell"),
P("B subunit binds receptor; A subunit enters cell and disrupts signaling", "table_cell"),
P("Cholera toxin (↑cAMP), Anthrax toxin, Diphtheria toxin (blocks EF-2)", "table_cell"),
P("Cholera, anthrax, diphtheria", "table_cell")],
[P("Neurotoxins\n(A-B type)", "table_cell"),
P("Inhibit release of neurotransmitters at synaptic junctions", "table_cell"),
P("Botulinum toxin (blocks Ach), Tetanus toxin (blocks GABA/glycine)", "table_cell"),
P("Flaccid paralysis; spastic paralysis. Both → respiratory failure", "table_cell")],
[P("Superantigens", "table_cell"),
P("Bind MHC-II AND T-cell receptor outside antigen groove → mass T-cell activation", "table_cell"),
P("TSST-1 (S. aureus), Streptococcal pyrogenic exotoxins", "table_cell"),
P("Toxic Shock Syndrome; cytokine storm → SIRS/shock", "table_cell")],
]
col_ws = [3.0*cm, 5.5*cm, 4.2*cm, 4.1*cm]
exo_tbl = Table(exo_rows, colWidths=col_ws, repeatRows=1)
exo_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), ORANGE),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, colors.HexColor("#FFF8F0")]),
("GRID", (0,0), (-1,-1), 0.4, MID_GRAY),
("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), "MIDDLE"),
("ALIGN", (0,0), (-1,0), "CENTER"),
("FONTSIZE", (0,1), (-1,-1), 8),
]))
elements.append(exo_tbl)
elements.append(SP(8))
# Section 4 – Immune-mediated
elements.append(section_banner("Host Immune-Mediated Injury", RED_ACCENT, "4"))
elements.append(SP(6))
imm_rows = [
[Paragraph("<b>Mechanism</b>", styles["table_hdr"]),
Paragraph("<b>Organism</b>", styles["table_hdr"]),
Paragraph("<b>Disease</b>", styles["table_hdr"])],
[P("Granulomatous inflammation → necrosis + fibrosis", "table_cell"),
P("M. tuberculosis", "table_cell"),
P("Pulmonary TB with caseating granulomas", "table_cell")],
[P("T-cell killing of infected hepatocytes", "table_cell"),
P("HBV, HCV", "table_cell"),
P("Viral hepatitis; cirrhosis", "table_cell")],
[P("Molecular mimicry – anti-M protein Ab cross-reacts with cardiac proteins", "table_cell"),
P("Streptococcus pyogenes", "table_cell"),
P("Rheumatic heart disease (RHD)", "table_cell")],
[P("Immune complex deposition in glomeruli", "table_cell"),
P("S. pyogenes antigens", "table_cell"),
P("Post-streptococcal glomerulonephritis (PSGN)", "table_cell")],
[P("Cytokine storm (TNF, IL-6, IL-1 excess)", "table_cell"),
P("SARS-CoV-2, influenza", "table_cell"),
P("Severe COVID-19, ARDS, multiorgan failure", "table_cell")],
[P("Chronic inflammation → carcinogenesis", "table_cell"),
P("H. pylori, HBV, HCV", "table_cell"),
P("Gastric cancer, hepatocellular carcinoma", "table_cell")],
]
col_ws2 = [6.2*cm, 4.0*cm, 6.6*cm]
imm_tbl = Table(imm_rows, colWidths=col_ws2, repeatRows=1)
imm_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), RED_ACCENT),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, colors.HexColor("#FFF5F5")]),
("GRID", (0,0), (-1,-1), 0.4, MID_GRAY),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("ALIGN", (0,0), (-1,0), "CENTER"),
]))
elements.append(imm_tbl)
elements.append(SP(8))
elements.append(P("Source: Robbins & Kumar Pathologic Basis of Disease, Ch. 8", "source"))
elements.append(PageBreak())
return elements
# ── PAGE 4: Spectrum of Inflammatory Responses ────────────────────────────────
def build_page4():
elements = []
elements.append(section_banner("Spectrum of Inflammatory Responses to Infection", MID_BLUE, "5"))
elements.append(SP(6))
elements.append(P(
"Despite vast molecular diversity of microbes, only a limited number of histologic response patterns exist. "
"The pattern depends on both the <b>pathogen type</b> and the <b>host immune status</b>. "
"The same organism can produce different morphology in immunocompetent vs. immunocompromised hosts.", "body"))
elements.append(SP(4))
elements.append(key_box(
"<b>Classic example:</b> M. tuberculosis in an immunocompetent host → well-formed granulomas with few bacilli. "
"In AIDS patient → bacilli multiply profusely in macrophages; <i>no granulomas form</i>."))
elements.append(SP(8))
spec_rows = [
[Paragraph("<b>Response Type</b>", styles["table_hdr"]),
Paragraph("<b>Key Features</b>", styles["table_hdr"]),
Paragraph("<b>Dominant Cells</b>", styles["table_hdr"]),
Paragraph("<b>Classic Examples</b>", styles["table_hdr"])],
[P("Suppurative\n(Purulent)", "table_cell"),
P("↑ vascular permeability, pus formation, liquefactive necrosis", "table_cell"),
P("Neutrophils (PMNs)", "table_cell"),
P("S. aureus abscess\nStrep pneumoniae\nGram-neg rods", "table_cell")],
[P("Mononuclear &\nGranulomatous", "table_cell"),
P("Chronic mononuclear infiltrate; granuloma = epithelioid macrophages ± giant cells ± central necrosis", "table_cell"),
P("Macrophages\nLymphocytes\nPlasma cells", "table_cell"),
P("TB (caseous granulomas)\nSyphilis (plasma cells)\nHistoplasma", "table_cell")],
[P("Cytopathic-\nCytoproliferative", "table_cell"),
P("Cell necrosis OR proliferation; viral inclusions; multinucleation; may link to neoplasia", "table_cell"),
P("Virus-infected cells\n(no classic inflammation)", "table_cell"),
P("HPV (warts, cervical Ca)\nHerpes/chicken pox\nCMV (owl-eye cells)\nEBV (mononucleosis)", "table_cell")],
[P("Tissue Necrosis", "table_cell"),
P("Rapid destructive process; toxin- or enzyme-mediated; few inflammatory cells", "table_cell"),
P("Minimal/absent\ninfiltrate", "table_cell"),
P("C. perfringens gas gangrene\nFulminant hepatitis B\nNecrotizing fasciitis", "table_cell")],
[P("Chronic\nInflammation/\nScarring", "table_cell"),
P("Repetitive injury → fibrosis, loss of parenchyma, architectural distortion", "table_cell"),
P("Fibroblasts\nMononuclear cells", "table_cell"),
P("Hepatitis B/C → cirrhosis\nSchistosomiasis → liver/bladder fibrosis", "table_cell")],
[P("No Reaction\n(Absent response)", "table_cell"),
P("Organisms proliferate unchecked; no inflammatory cells recruited; seen in severe immunocompromise", "table_cell"),
P("None", "table_cell"),
P("M. avium in untreated AIDS\nMucormycosis in neutropenic BMT patients", "table_cell")],
]
col_ws = [3.1*cm, 5.8*cm, 3.2*cm, 4.7*cm]
spec_tbl = Table(spec_rows, colWidths=col_ws, repeatRows=1)
spec_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), MID_BLUE),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, LIGHT_BLUE]),
("GRID", (0,0), (-1,-1), 0.4, MID_GRAY),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
("ALIGN", (0,0), (-1,0), "CENTER"),
("FONTSIZE", (0,1), (-1,-1), 8),
]))
elements.append(spec_tbl)
elements.append(SP(10))
# Side-by-side note boxes
note1 = Table([[
Paragraph("<b>Suppurative notes:</b> Destructiveness depends on location and organism. "
"S. pneumoniae spares alveolar walls → resolves. S. aureus/Klebsiella destroy walls → abscesses + scars.", styles["table_cell"]),
]], colWidths=[(PAGE_W - 2*MARGIN)/2 - 0.3*cm])
note1.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), LIGHT_BLUE),
("LINEBEFORE", (0,0), (0,-1), 3, ACCENT_BLUE),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING",(0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
]))
note2 = Table([[
Paragraph("<b>Granuloma notes:</b> Plasma cells dominant in syphilis. Lymphocytes dominant in HBV. "
"Macrophages filled with organisms (no granuloma) in M. avium + AIDS.", styles["table_cell"]),
]], colWidths=[(PAGE_W - 2*MARGIN)/2 - 0.3*cm])
note2.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), colors.HexColor("#F0FFF4")),
("LINEBEFORE", (0,0), (0,-1), 3, GREEN),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING",(0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
]))
notes_row = Table([[note1, note2]], colWidths=[
(PAGE_W - 2*MARGIN)/2 - 0.1*cm,
(PAGE_W - 2*MARGIN)/2 - 0.1*cm,
])
notes_row.setStyle(TableStyle([
("LEFTPADDING", (0,0), (-1,-1), 0),
("RIGHTPADDING", (0,0), (-1,-1), 4),
("TOPPADDING", (0,0), (-1,-1), 0),
("BOTTOMPADDING",(0,0), (-1,-1), 0),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
elements.append(notes_row)
elements.append(SP(8))
elements.append(P("Source: Robbins & Kumar – Table 8.3, Pathologic Basis of Disease", "source"))
elements.append(PageBreak())
return elements
# ── PAGE 5: Immune Evasion ─────────────────────────────────────────────────────
def build_page5():
elements = []
elements.append(section_banner("Immune Evasion Strategies", TEAL, "6"))
elements.append(SP(6))
elements.append(P(
"After bypassing physical barriers, pathogens must also evade innate and adaptive immunity to proliferate "
"and be transmitted to the next host. The following strategies are used:", "body"))
elements.append(SP(6))
evasion_rows = [
[Paragraph("<b>Strategy</b>", styles["table_hdr"]),
Paragraph("<b>Mechanism</b>", styles["table_hdr"]),
Paragraph("<b>Pathogens</b>", styles["table_hdr"]),
Paragraph("<b>Clinical Impact</b>", styles["table_hdr"])],
[P("Antigenic Variation", "table_cell"),
P("Continuous alteration of surface antigens so antibodies from prior infection/vaccine are ineffective", "table_cell"),
P("Influenza (hemagg./neuraminidase), HIV (gp120), Trypanosoma (VSG), N. gonorrhoeae (pili)", "table_cell"),
P("Annual flu vaccine needed; HIV vaccine challenge; relapsing fever", "table_cell")],
[P("Inactivating Ab or Complement", "table_cell"),
P("Secrete IgA proteases; produce complement inhibitors; absorb host complement regulatory proteins", "table_cell"),
P("N. meningitidis, S. pneumoniae, H. influenzae (IgA protease)", "table_cell"),
P("Allows mucosal colonization despite secretory IgA", "table_cell")],
[P("Resisting Phagocytosis", "table_cell"),
P("Polysaccharide capsule prevents opsonization; inhibit phagosome-lysosome fusion", "table_cell"),
P("S. pneumoniae, Klebsiella, H. influenzae (capsule)\nMycobacteria (phagosome evasion)", "table_cell"),
P("Bacteremia in asplenic patients; intracellular persistence of mycobacteria", "table_cell")],
[P("Inhibiting MHC-I\nPresentation", "table_cell"),
P("Downregulate MHC-I on infected cells to avoid CD8+ T-cell killing; block antigen processing", "table_cell"),
P("CMV (encodes MHC-I decoy), EBV, HSV (ICP47 blocks TAP)", "table_cell"),
P("Infected cells escape CTL surveillance; viral persistence", "table_cell")],
[P("Latency", "table_cell"),
P("Virus integrates into host genome or persists episomally in a transcriptionally silent state", "table_cell"),
P("HSV (dorsal root ganglia), VZV, CMV, EBV (memory B cells), HIV (resting CD4 T cells)", "table_cell"),
P("Reactivation during immunosuppression; lifelong carriage; reservoir problem for HIV cure", "table_cell")],
[P("Suppressing Cytokine\nSignaling", "table_cell"),
P("Encode cytokine analogs, decoy receptors, or inhibitors of JAK-STAT/NF-κB pathways", "table_cell"),
P("EBV (IL-10 homolog vIL-10), Poxviruses (soluble cytokine receptors)", "table_cell"),
P("Blunts Th1 response; promotes viral persistence", "table_cell")],
[P("Infecting/Killing\nImmune Cells", "table_cell"),
P("Directly target cells key to adaptive immunity; deplete CD4+ T-helpers", "table_cell"),
P("HIV (CD4+ T cells), EBV (B cells), measles (lymphocytes → transient immunosuppression)", "table_cell"),
P("AIDS (HIV); secondary infections post-measles; B-cell lymphoma (EBV)", "table_cell")],
[P("Intracellular Life", "table_cell"),
P("Survive within host cells (macrophages, epithelial cells) beyond reach of antibodies", "table_cell"),
P("Mycobacteria, Listeria, Salmonella typhi, Brucella, Leishmania", "table_cell"),
P("Antibiotics must penetrate cells; T-cell immunity required for clearance", "table_cell")],
]
col_ws = [3.0*cm, 5.5*cm, 4.5*cm, 3.8*cm]
ev_tbl = Table(evasion_rows, colWidths=col_ws, repeatRows=1)
ev_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, colors.HexColor("#E6FFFA")]),
("GRID", (0,0), (-1,-1), 0.4, MID_GRAY),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
("ALIGN", (0,0), (-1,0), "CENTER"),
("FONTSIZE", (0,1), (-1,-1), 7.8),
]))
elements.append(ev_tbl)
elements.append(SP(10))
elements.append(P("Source: Robbins & Kumar – Pathologic Basis of Disease, Ch. 8 (Immune Evasion by Microbes)", "source"))
elements.append(PageBreak())
return elements
# ── PAGE 6: Immunocompromised + Key Concepts ──────────────────────────────────
def build_page6():
elements = []
# Section 7
elements.append(section_banner("Infections in Immunocompromised Hosts", DARK_BLUE, "7"))
elements.append(SP(6))
elements.append(P(
"The type of immune defect determines which pathogens predominate. "
"Infections may present atypically, with minimal inflammation and absent hallmark features.", "body"))
elements.append(SP(5))
ic_rows = [
[Paragraph("<b>Immune Defect</b>", styles["table_hdr"]),
Paragraph("<b>Cause</b>", styles["table_hdr"]),
Paragraph("<b>Vulnerable Pathogens</b>", styles["table_hdr"]),
Paragraph("<b>Key Notes</b>", styles["table_hdr"])],
[P("B-cell / Antibody\ndeficiency", "table_cell"),
P("X-linked agammaglobulinemia\nCommon variable ID", "table_cell"),
P("Extracellular bacteria\n(S. pneumoniae, H. influenzae, S. aureus)\nRotavirus, enteroviruses", "table_cell"),
P("Opsonization and neutralization fail; no mucosal IgA", "table_cell")],
[P("Complement deficiency\n(early C1–C4)", "table_cell"),
P("Inherited or acquired", "table_cell"),
P("Encapsulated bacteria:\nS. pneumoniae, H. influenzae", "table_cell"),
P("Classical pathway activation impaired", "table_cell")],
[P("Complement deficiency\n(late C5–C9, MAC)", "table_cell"),
P("Inherited", "table_cell"),
P("Neisseria spp.\n(N. meningitidis, N. gonorrhoeae)", "table_cell"),
P("Cannot form membrane attack complex to lyse gram-negatives", "table_cell")],
[P("T-cell deficiency\n(cell-mediated)", "table_cell"),
P("HIV/AIDS, DiGeorge\nImmunosuppressants", "table_cell"),
P("M. tuberculosis/avium, PCP,\nCryptococcus, Toxoplasma,\nCMV, HSV, VZV, Candida", "table_cell"),
P("No granuloma in AIDS. Organisms multiply unchecked in macrophages", "table_cell")],
[P("Neutrophil deficiency\n(neutropenia)", "table_cell"),
P("Chemotherapy, leukemia\nBMT (aplastic phase)", "table_cell"),
P("Aspergillus, Candida,\nPseudomonas, S. aureus,\nMucormycosis", "table_cell"),
P("Bacterial sepsis with little exudation; invasive mold infections", "table_cell")],
[P("Splenic dysfunction", "table_cell"),
P("Sickle cell disease\nSplenectomy", "table_cell"),
P("Encapsulated bacteria: S. pneumoniae, H. influenzae, N. meningitidis", "table_cell"),
P("Loss of splenic filtering and opsonization (IgM)", "table_cell")],
[P("Barrier disruption", "table_cell"),
P("Burns, IV lines, trauma\nCystic fibrosis (CFTR)", "table_cell"),
P("P. aeruginosa (burns + CF)\nB. cepacia (CF)\nCoNS (IV catheters)", "table_cell"),
P("Primary defense (skin/mucosa) bypassed or defective", "table_cell")],
]
col_ws = [3.2*cm, 3.0*cm, 5.2*cm, 5.4*cm]
ic_tbl = Table(ic_rows, colWidths=col_ws, repeatRows=1)
ic_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, LIGHT_BLUE]),
("GRID", (0,0), (-1,-1), 0.4, MID_GRAY),
("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"),
("ALIGN", (0,0), (-1,0), "CENTER"),
("FONTSIZE", (0,1), (-1,-1), 8),
]))
elements.append(ic_tbl)
elements.append(SP(10))
# Section 8 – Key Concepts
elements.append(section_banner("Key Concepts Summary", DARK_GRAY, "8"))
elements.append(SP(6))
concepts = [
("<b>1. Three damage mechanisms:</b>", "Direct cytopathic effects, toxin-mediated (endotoxin/exotoxin/superantigen), immune-mediated injury"),
("<b>2. Histologic patterns:</b>", "Only ~6 patterns regardless of organism: suppurative, granulomatous, cytopathic, necrosis, scarring, none"),
("<b>3. Immune status is determinant:</b>", "Same pathogen → different morphology in immunocompetent vs. immunocompromised host"),
("<b>4. Superantigen mechanism:</b>", "Binds MHC-II + TCR outside antigen groove → mass T-cell activation → cytokine storm → SIRS/TSS"),
("<b>5. A-B toxins:</b>", "B binds receptor; A enters cell and enzymatically disrupts signaling. All major bacterial toxins follow this model"),
("<b>6. Capsule = antiphagocytic:</b>", "Polysaccharide capsule prevents opsonization; asplenic patients especially vulnerable"),
("<b>7. Latency:</b>", "Herpesviruses and HIV persist silently in host cells; reactivate during immunosuppression"),
("<b>8. Microbiome disruption:</b>", "Dysbiosis predisposes to opportunistic infections; normal flora is a key defense layer"),
("<b>9. Oncogenic infections:</b>", "HPV (cervical/anogenital Ca), EBV (Burkitt/Hodgkin lymphoma), HBV/HCV (HCC), H. pylori (gastric Ca) – via chronic inflammation or direct oncogene activation"),
("<b>10. Neutropenic host:</b>", "Pyogenic bacteria cause necrosis with little leukocyte exudate (no neutrophils to recruit); molds (Aspergillus, Mucor) proliferate unchecked"),
]
for label, text in concepts:
row_tbl = Table([[
Paragraph(label, styles["body_bold"]),
Paragraph(text, styles["body"]),
]], colWidths=[5.2*cm, PAGE_W - 2*MARGIN - 5.5*cm])
row_tbl.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING",(0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 0),
("RIGHTPADDING", (0,0), (-1,-1), 0),
("LINEBELOW", (0,0), (-1,-1), 0.3, MID_GRAY),
]))
elements.append(row_tbl)
elements.append(SP(14))
footer_text = (
"Source: Robbins, Cotran & Kumar – Pathologic Basis of Disease (10th ed.), Chapter 8: Infectious Diseases, pp. 305–330. "
"Quick Reference compiled by Orris Medical Library • July 2026"
)
elements.append(P(footer_text, "source"))
return elements
# ── BUILD ──────────────────────────────────────────────────────────────────────
story = []
story += build_cover()
story += build_page2()
story += build_page3()
story += build_page4()
story += build_page5()
story += build_page6()
doc.build(story)
print(f"PDF created: {output_path}")