Ihc studies in lymphoma

Reading File
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Loading Image
Loading Image
I now have all the information needed for a comprehensive answer. Here is the full synthesis:

IHC Studies in Lymphoma

Immunohistochemistry (IHC) is the cornerstone of lymphoma diagnosis and classification. It confirms lymphoid lineage, determines B-cell vs. T-cell origin, identifies specific subtypes, guides treatment decisions (e.g., rituximab eligibility), and in some cases provides prognostic information.

1. Core Lineage Markers (Initial Panel)

MarkerLineage/RoleKey Notes
CD45 (LCA)Pan-leukocytePositive in NHL; negative in classic HL (Reed-Sternberg cells)
CD20B-cell markerAll mature B-cell lymphomas; therapeutic target for rituximab
CD79aB-cell markerMore sensitive than CD20 in some B-cell lymphomas
PAX5B-cell transcription factorPresent on Reed-Sternberg cells in classic HL (weak)
CD3Pan-T-cell markerT-cell lymphomas
CD5T-cell/subset B-cellAlso positive in CLL/SLL and mantle cell lymphoma
CD10Follicle center markerFollicular lymphoma, DLBCL (GCB type), Burkitt
Ki-67Proliferation indexVery high (>95%) in Burkitt lymphoma; helps grade

2. Hodgkin Lymphoma (HL)

Classic HL (Nodular Sclerosis, Mixed Cellularity, Lymphocyte-Rich, Lymphocyte-Depleted)

Reed-Sternberg (RS) cells have a characteristic immunophenotype:
  • CD30+ (nearly 100%) - large membranous/Golgi staining
  • CD15+ (75-85%) - specific for classic RS cells
  • PAX5+ (weak) - confirms B-cell origin
  • CD45- (negative - key distinction from NHL)
  • CD20-, CD79a- (usually negative)
  • EBV (LMP-1)+ in ~70% Mixed-Cellularity, >90% Lymphocyte-Depleted
The RS cells have a characteristic phenotype: CD30+, CD15+, PAX5 (weak)+, CD45-, with lack of B-cell and T-cell markers. - Robbins, Cotran & Kumar Pathologic Basis of Disease

Nodular Lymphocyte Predominant HL (NLPHL) - distinct entity

The "popcorn cells" (L&H variants) differ from classic RS cells:
  • CD20+, BCL6+ (germinal center B-cell phenotype)
  • CD15-, CD30- (usually)
  • CD45+
  • EBV rarely associated
NLPHL vs. Classic HL distinction by IHC is critical, as NLPHL has a different clinical course and treatment.

3. B-Cell Non-Hodgkin Lymphomas

A. Diffuse Large B-Cell Lymphoma (DLBCL) - most common NHL

Basic panel: CD20+, CD79a+, PAX5+, CD45+
Subtyping by Hans Algorithm (IHC):
StepMarkerInterpretation
1CD10If >30% positive → GCB type
2BCL6If CD10-, BCL6- → non-GCB (ABC)
3MUM1If BCL6+, MUM1+ → non-GCB (ABC); MUM1- → GCB
Full IHC combination table:
CD10BCL6MUM1Phenotype
++-GCB
+--GCB
-+-GCB
-++non-GCB (ABC)
--+non-GCB (ABC)
Additional markers:
  • BCL2+ in 25-80% of DLBCLs (especially GCB via t(14;18))
  • MYC rearrangement in ~10%; concurrent BCL2 rearrangement = "double-hit lymphoma" (HGBL) - extremely poor prognosis
  • BCL6 rearranged in more ABC cases
- Harrison's Principles of Internal Medicine 22E; Quick Compendium of Clinical Pathology 5th ed.

B. Follicular Lymphoma (FL)

  • CD20+, CD10+, BCL6+, BCL2+ (overexpressed due to t(14;18))
  • CD5-, cyclin D1-, CD23- (negative panel distinguishes from MCL and CLL)
  • CD21+ FDC meshwork highlights follicular architecture
  • BCL2 positivity in neoplastic follicles vs. negative in reactive follicles is diagnostically useful

C. Mantle Cell Lymphoma (MCL)

  • CD20+, CD5+, cyclin D1+ (hallmark - due to t(11;14))
  • CD10-, CD23-, BCL6-
  • SOX11+ (most cases, helps identify cyclin D1-negative MCL)
  • Ki-67 high in blastoid variant

D. Burkitt Lymphoma

  • CD20+, CD10+, BCL6+, sIg+
  • Ki-67 ~100% (near 100% proliferative rate)
  • BCL2- (key: BCL2 is negative, unlike FL)
  • c-MYC rearrangement (t(8;14) in 80%, t(2;8) or t(8;22) in others)
- Sleisenger & Fordtran's Gastrointestinal and Liver Disease

E. MALT Lymphoma (Marginal Zone Lymphoma)

  • CD20+, CD79a+
  • CD5-, CD10-, CD23-, cyclin D1-, BCL6- (negative panel rules out CLL, MCL, FL)
  • BCL2+ may be present but is not diagnostic
  • Forms lymphoepithelial lesions
- Murray & Nadel's Textbook of Respiratory Medicine

F. Small Lymphocytic Lymphoma (SLL)/CLL

  • CD20+ (dim), CD5+, CD23+
  • CD10-, cyclin D1-
  • CD23+ differentiates from MCL (CD23-)

G. T-Cell/Histiocyte-Rich Large B-Cell Lymphoma (TCRBCL)

  • Large B cells: CD20+, CD10+, BCL6+ (pan-B markers)
  • Background small T cells: CD3+, CD8+ predominantly
  • Histiocytes: CD68+
  • Large B cells: CD15-, CD30-, EBV-
TCRBCL IHC panel showing CD3+ background T cells (panel d), CD68+ histiocytes (panel e), and CD20+/CD10+ large B cells (panels f,g)

4. T-Cell / NK-Cell Lymphomas

LymphomaKey IHC Profile
Peripheral T-cell lymphoma NOSCD3+, CD4+ or CD8+, variable loss of CD5/CD7
Anaplastic Large Cell Lymphoma (ALCL)CD30+, ALK+ (ALK+ has better prognosis), CD3 often negative
Angioimmunoblastic T-cell Lymphoma (AITL)CD3+, CD4+, PD-1+, CXCL13+, CD10+, CD21+ FDC expanded meshwork
NK/T-cell Lymphoma, nasal typeCD2+, CD56+, cytoplasmic CD3+, EBV+, granzyme B+
Hepatosplenic T-cell LymphomaCD3+, TCRγδ+, CD4-, CD8- (double negative), CD56+
Adult T-cell Leukemia/Lymphoma (ATLL)CD3+, CD4+, CD25+, CD7 often lost; HTLV-1+
Key tip: In T-cell lymphomas, look for aberrant loss of pan-T markers (CD3, CD5, CD7) - this suggests neoplasia. - Henry's Clinical Diagnosis and Management by Laboratory Methods

5. Summary: Quick Reference IHC Panel by Lymphoma Type

LymphomaCD20CD5CD10CD23Cyclin D1CD30CD15BCL2Ki-67
SLL/CLLdim++-+---+low
MCL++--+--+variable
FL+-+----+low-mod
DLBCL+-+/-----+/-high
Burkitt+-+-----~100%
MALT MZL+------+/-low
Classic HL (RS)-----++--
NLPHL (L&H)+--------
ALCL-----+--high

6. Role of IHC in Specific Contexts

  • Undifferentiated tumor workup: CD45 (lymphoma vs. carcinoma vs. melanoma) is the first step. A CD45+ large cell tumor prompts a full lymphoma panel.
  • Double-hit lymphoma: MYC + BCL2 (and/or BCL6) IHC positivity, confirmed by FISH - poor prognosis DLBCL.
  • CNS lymphoma: Perivascular CD20+ large cells are characteristic of primary CNS DLBCL.
  • Skin lymphomas: CD30 is key for lymphomatoid papulosis and ALCL; CD8 for cytotoxic T-cell lymphomas.
  • Burkitt vs. DLBCL: Ki-67 ~100% + BCL2 negativity favors Burkitt; MYC FISH is confirmatory.
DLBCL - primary CNS lymphoma showing tight perivascular aggregates of large lymphocytes with strong CD20 expression (panel d)

Key sources: Robbins, Cotran & Kumar Pathologic Basis of Disease; Harrison's Principles of Internal Medicine 22E; Quick Compendium of Clinical Pathology 5th ed.; Henry's Clinical Diagnosis and Management by Laboratory Methods; Murray & Nadel's Textbook of Respiratory Medicine.

Generate a quick reference PDF for lymphoma IHC stain interpretation

Reading File
Reading File
Running Command

ls /home/daytona/workspace/ && python3 -c "import reportlab; print('reportlab ok…

Running Command

mkdir -p /home/daytona/workspace/lymphoma-ihc

Writing File

~/lymphoma-ihc/generate_pdf.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether, PageBreak
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate
from reportlab.lib.colors import HexColor

OUTPUT = "/home/daytona/workspace/lymphoma-ihc/Lymphoma_IHC_Quick_Reference.pdf"

# ── Colour palette ──────────────────────────────────────────────────────────
NAVY      = HexColor("#1B3A6B")
TEAL      = HexColor("#1A7A8A")
AMBER     = HexColor("#E67E22")
LIGHT_BG  = HexColor("#F0F4F8")
HEADER_BG = HexColor("#1B3A6B")
ROW_ALT   = HexColor("#E8F0F7")
WHITE     = colors.white
BLACK     = colors.black
POS_GREEN = HexColor("#1E7E34")
NEG_RED   = HexColor("#C0392B")
VAR_AMBER = HexColor("#D4860B")

# ── Styles ───────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()

TITLE_STYLE = ParagraphStyle("Title", fontName="Helvetica-Bold", fontSize=22,
                              textColor=WHITE, alignment=TA_CENTER, spaceAfter=4)
SUBTITLE_STYLE = ParagraphStyle("Subtitle", fontName="Helvetica", fontSize=11,
                                 textColor=HexColor("#B8D4E8"), alignment=TA_CENTER, spaceAfter=2)
DATE_STYLE = ParagraphStyle("Date", fontName="Helvetica-Oblique", fontSize=9,
                              textColor=HexColor("#B8D4E8"), alignment=TA_CENTER)

SECTION_STYLE = ParagraphStyle("Section", fontName="Helvetica-Bold", fontSize=13,
                                textColor=WHITE, alignment=TA_LEFT,
                                leftIndent=6, spaceAfter=0, spaceBefore=0)

BODY_STYLE = ParagraphStyle("Body", fontName="Helvetica", fontSize=8.5,
                              textColor=BLACK, spaceAfter=3, leading=12)
BODY_BOLD  = ParagraphStyle("BodyBold", fontName="Helvetica-Bold", fontSize=8.5,
                              textColor=BLACK, spaceAfter=3, leading=12)
CAPTION    = ParagraphStyle("Caption", fontName="Helvetica-Oblique", fontSize=7.5,
                              textColor=HexColor("#555555"), spaceAfter=4)
FOOTNOTE   = ParagraphStyle("Footnote", fontName="Helvetica-Oblique", fontSize=7,
                              textColor=HexColor("#666666"), spaceAfter=2)

# cell styles
TH_STYLE = ParagraphStyle("TH", fontName="Helvetica-Bold", fontSize=8,
                            textColor=WHITE, alignment=TA_CENTER, leading=10)
TD_STYLE = ParagraphStyle("TD", fontName="Helvetica", fontSize=7.8,
                            textColor=BLACK, alignment=TA_CENTER, leading=10)
TD_LEFT  = ParagraphStyle("TDL", fontName="Helvetica", fontSize=7.8,
                            textColor=BLACK, alignment=TA_LEFT, leading=10)
TD_BOLD  = ParagraphStyle("TDB", fontName="Helvetica-Bold", fontSize=7.8,
                            textColor=BLACK, alignment=TA_LEFT, leading=10)

def pos(text="+"):  return Paragraph(f'<font color="#1E7E34"><b>{text}</b></font>', TD_STYLE)
def neg(text="−"):  return Paragraph(f'<font color="#C0392B"><b>{text}</b></font>', TD_STYLE)
def var(text="+/−"): return Paragraph(f'<font color="#D4860B"><b>{text}</b></font>', TD_STYLE)
def th(text):        return Paragraph(f"<b>{text}</b>", TH_STYLE)
def td(text):        return Paragraph(text, TD_STYLE)
def tdl(text):       return Paragraph(text, TD_LEFT)
def tdb(text):       return Paragraph(f"<b>{text}</b>", TD_BOLD)

def section_bar(title):
    """Returns a coloured section header bar."""
    data = [[Paragraph(f"<b>{title}</b>", SECTION_STYLE)]]
    t = Table(data, colWidths=[17.7*cm])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), TEAL),
        ("TOPPADDING",    (0,0), (-1,-1), 5),
        ("BOTTOMPADDING", (0,0), (-1,-1), 5),
        ("LEFTPADDING",   (0,0), (-1,-1), 8),
        ("ROUNDEDCORNERS", [3]),
    ]))
    return t

def base_table_style(header_rows=1):
    return [
        ("BACKGROUND",    (0,0),  (-1, header_rows-1), NAVY),
        ("TEXTCOLOR",     (0,0),  (-1, header_rows-1), WHITE),
        ("FONTNAME",      (0,0),  (-1, header_rows-1), "Helvetica-Bold"),
        ("FONTSIZE",      (0,0),  (-1,-1), 8),
        ("ROWBACKGROUNDS",(0, header_rows), (-1,-1), [WHITE, ROW_ALT]),
        ("GRID",          (0,0),  (-1,-1), 0.4, HexColor("#AAAAAA")),
        ("TOPPADDING",    (0,0),  (-1,-1), 4),
        ("BOTTOMPADDING", (0,0),  (-1,-1), 4),
        ("LEFTPADDING",   (0,0),  (-1,-1), 4),
        ("RIGHTPADDING",  (0,0),  (-1,-1), 4),
        ("VALIGN",        (0,0),  (-1,-1), "MIDDLE"),
    ]

# ── Header / footer callbacks ────────────────────────────────────────────────
def on_first_page(canvas, doc):
    canvas.saveState()
    w, h = A4
    # navy banner
    canvas.setFillColor(NAVY)
    canvas.rect(0, h-3.8*cm, w, 3.8*cm, fill=1, stroke=0)
    # teal accent stripe
    canvas.setFillColor(TEAL)
    canvas.rect(0, h-4.1*cm, w, 0.3*cm, fill=1, stroke=0)
    canvas.restoreState()

def on_later_pages(canvas, doc):
    canvas.saveState()
    w, h = A4
    # slim top bar
    canvas.setFillColor(NAVY)
    canvas.rect(0, h-1.2*cm, w, 1.2*cm, fill=1, stroke=0)
    canvas.setFont("Helvetica-Bold", 8)
    canvas.setFillColor(WHITE)
    canvas.drawString(1.5*cm, h-0.85*cm, "LYMPHOMA IHC — QUICK REFERENCE")
    canvas.drawRightString(w-1.5*cm, h-0.85*cm, f"Page {doc.page}")
    # footer
    canvas.setFillColor(NAVY)
    canvas.rect(0, 0, w, 0.8*cm, fill=1, stroke=0)
    canvas.setFont("Helvetica-Oblique", 7)
    canvas.setFillColor(HexColor("#B8D4E8"))
    canvas.drawCentredString(w/2, 0.28*cm,
        "Sources: Robbins Pathology · Harrison's Internal Medicine 22E · Quick Compendium of Clinical Pathology 5e · Henry's Lab Methods")
    canvas.restoreState()

# ── Build document ────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    leftMargin=1.5*cm, rightMargin=1.5*cm,
    topMargin=4.5*cm, bottomMargin=1.5*cm,
    title="Lymphoma IHC Quick Reference",
    author="Orris Medical AI",
)

story = []

# ── Cover header content ──────────────────────────────────────────────────────
story.append(Spacer(1, 0.2*cm))
story.append(Paragraph("LYMPHOMA IHC", TITLE_STYLE))
story.append(Paragraph("Quick Reference Guide for Immunohistochemical Stain Interpretation", SUBTITLE_STYLE))
story.append(Paragraph("Based on WHO Classification · Robbins Pathology · Harrison's 22E · Quick Compendium 5e", DATE_STYLE))
story.append(Spacer(1, 0.6*cm))

# ── LEGEND ────────────────────────────────────────────────────────────────────
legend_data = [
    [th("Symbol"), th("Meaning")],
    [pos("+"),  tdl("Positive / Expressed")],
    [neg("−"),  tdl("Negative / Not expressed")],
    [var("+/−"),tdl("Variable / Inconsistent expression")],
    [pos("dim+"),tdl("Weakly / dimly positive")],
    [td("~100%"),tdl("Near-100% proliferative index (Ki-67)")],
]
legend_table = Table(legend_data, colWidths=[2.5*cm, 6*cm])
legend_table.setStyle(TableStyle(base_table_style()))

story.append(KeepTogether([
    section_bar("LEGEND"),
    Spacer(1, 0.15*cm),
    legend_table,
    Spacer(1, 0.5*cm),
]))

# ── SECTION 1: CORE LINEAGE PANEL ────────────────────────────────────────────
lineage_data = [
    [th("Marker"), th("Lineage / Role"), th("Key Diagnostic Use")],
    [tdb("CD45 (LCA)"), tdl("Pan-leukocyte"), tdl("ALL lymphomas +; Negative in classic Reed-Sternberg cells (HL)")],
    [tdb("CD20"),       tdl("B-cell"),       tdl("Mature B-cell lymphomas; rituximab therapeutic target")],
    [tdb("CD79a"),      tdl("B-cell"),       tdl("Sensitive B-cell marker; positive when CD20 lost (e.g. post-rituximab)")],
    [tdb("PAX5"),       tdl("B-cell TF"),    tdl("Weak + in Reed-Sternberg cells; confirms B origin in classic HL")],
    [tdb("CD3"),        tdl("Pan-T-cell"),   tdl("T-cell lymphomas; surface loss suggests neoplasia")],
    [tdb("CD5"),        tdl("T-cell + B subset"), tdl("CLL/SLL and MCL among B-cell lymphomas; absent in FL/DLBCL")],
    [tdb("CD10"),       tdl("Follicle center"), tdl("FL, DLBCL-GCB, Burkitt, AITL; absent in MCL/MZL/CLL")],
    [tdb("BCL6"),       tdl("GC B-cell TF"), tdl("FL, DLBCL-GCB; AITL (T-cells); NLPHL L&H cells")],
    [tdb("MUM1/IRF4"),  tdl("Post-GC/plasma cell"), tdl("DLBCL-ABC subtype; plasma cell myeloma; ALCL")],
    [tdb("BCL2"),       tdl("Anti-apoptotic"), tdl("FL (t14;18), DLBCL; Negative in Burkitt (key distinction)")],
    [tdb("Cyclin D1"),  tdl("Cell cycle"),   tdl("Hallmark of MCL t(11;14); also hairy cell leukemia")],
    [tdb("CD30"),       tdl("Activation marker"), tdl("Classic HL RS cells, ALCL, lymphomatoid papulosis")],
    [tdb("CD15"),       tdl("Granulocyte/RS"), tdl("Classic HL RS cells 75–85%; absent in NLPHL")],
    [tdb("Ki-67"),      tdl("Proliferation"), tdl("~100% Burkitt; high in DLBCL/ALCL; low in FL/SLL/MCL")],
    [tdb("EBV (LMP-1)"),tdl("Viral marker"), tdl("HL mixed-cellularity 70%, lymphocyte-depleted >90%; NK/T lymphoma")],
]
lineage_table = Table(lineage_data, colWidths=[2.6*cm, 3.1*cm, 12*cm])
lineage_table.setStyle(TableStyle(base_table_style()))

story.append(KeepTogether([
    section_bar("1 · CORE LINEAGE & DIAGNOSTIC MARKERS"),
    Spacer(1, 0.15*cm),
    lineage_table,
    Spacer(1, 0.5*cm),
]))

# ── SECTION 2: MASTER IHC TABLE ──────────────────────────────────────────────
# Columns: Lymphoma | CD20 | CD5 | CD10 | CD23 | CycD1 | BCL2 | BCL6 | CD30 | CD15 | CD45 | Ki-67
master_headers = [th(x) for x in [
    "Lymphoma", "CD20","CD5","CD10","CD23","CyclinD1","BCL2","BCL6","CD30","CD15","CD45","Ki-67"
]]
master_data = [master_headers,
    [tdb("SLL / CLL"),    pos("dim+"), pos(), neg(),  pos(),  neg(),   pos(),   neg(),  neg(),  neg(),  pos(),  td("Low")],
    [tdb("MCL"),          pos(),       pos(), neg(),  neg(),  pos("✓"),pos(),   neg(),  neg(),  neg(),  pos(),  td("Var")],
    [tdb("Follicular"),   pos(),       neg(), pos(),  neg(),  neg(),   pos("✓"),pos(),  neg(),  neg(),  pos(),  td("Low")],
    [tdb("MALT/MZL"),     pos(),       neg(), neg(),  neg(),  neg(),   var(),   neg(),  neg(),  neg(),  pos(),  td("Low")],
    [tdb("DLBCL-GCB"),    pos(),       neg(), pos(),  neg(),  neg(),   var(),   pos(),  neg(),  neg(),  pos(),  td("High")],
    [tdb("DLBCL-ABC"),    pos(),       neg(), neg(),  neg(),  neg(),   var(),   neg(),  neg(),  neg(),  pos(),  td("High")],
    [tdb("Burkitt"),      pos(),       neg(), pos(),  neg(),  neg(),   neg("✓"),pos(),  neg(),  neg(),  pos(),  td("~100%")],
    [tdb("Classic HL"),   neg(),       neg(), neg(),  neg(),  neg(),   neg(),   neg(),  pos("✓"),pos("✓"),neg("✓"),td("Var")],
    [tdb("NLPHL"),        pos("✓"),    neg(), neg(),  neg(),  neg(),   neg(),   pos(),  neg(),  neg(),  pos(),  td("Low")],
    [tdb("ALCL (ALK+)"),  neg(),       neg(), neg(),  neg(),  neg(),   neg(),   neg(),  pos("✓"),neg(),  pos(),  td("High")],
    [tdb("PTCL-NOS"),     neg(),       neg(), neg(),  neg(),  neg(),   neg(),   neg(),  neg(),  neg(),  pos(),  td("High")],
    [tdb("NK/T-cell"),    neg(),       neg(), neg(),  neg(),  neg(),   neg(),   neg(),  neg(),  neg(),  pos(),  td("High")],
]

# Highlight special "key" cells
col_widths = [2.8*cm, 1.3*cm, 1.1*cm, 1.1*cm, 1.15*cm, 1.5*cm, 1.15*cm, 1.15*cm, 1.15*cm, 1.15*cm, 1.15*cm, 1.3*cm]
master_table = Table(master_data, colWidths=col_widths)
ts = base_table_style()
# mark key diagnostics with light gold
key_cells = [
    (5,2),(5,3),(5,4),(5,5),   # MCL cyclin D1
    (6,3),(6,7),                # FL CD10, BCL2
    (9,11),                     # Burkitt Ki67
    (8,9),(8,10),(8,11),        # Classic HL CD30 CD15 CD45
    (9,8),                      # NLPHL CD20
    (10,9),                     # ALCL CD30
]
for (row,col) in key_cells:
    ts.append(("BACKGROUND", (col,row), (col,row), HexColor("#FFF3CD")))

master_table.setStyle(TableStyle(ts))

story.append(KeepTogether([
    section_bar("2 · MASTER IHC PROFILE TABLE"),
    Spacer(1, 0.15*cm),
    master_table,
    Spacer(1, 0.15*cm),
    Paragraph("✓ = hallmark/diagnostic marker  |  Highlighted cells = key distinguishing markers", CAPTION),
    Spacer(1, 0.4*cm),
]))

# ── SECTION 3: HODGKIN LYMPHOMA ───────────────────────────────────────────────
hl_data = [
    [th("Subtype"), th("% of HL"), th("RS Cell Variant"), th("IHC Profile"), th("EBV"), th("Notes")],
    [tdb("Nodular Sclerosis"),     td("65–70%"), tdl("Lacunar cells"),           tdl("CD30+, CD15+, PAX5+w, CD45−"), td("Rare"),   tdl("Young adults; mediastinal disease")],
    [tdb("Mixed Cellularity"),     td("20–25%"), tdl("Classic RS cells"),        tdl("CD30+, CD15+, PAX5+w, CD45−"), td("~70%"),   tdl("Older males; advanced stage")],
    [tdb("Lymphocyte-Rich"),       td("~5%"),    tdl("Mononuclear variants"),    tdl("CD30+, CD15+, PAX5+w, CD45−"), td("~40%"),   tdl("Good prognosis")],
    [tdb("Lymphocyte-Depleted"),   td("<5%"),    tdl("Pleomorphic RS"),          tdl("CD30+, CD15+, PAX5+w, CD45−"), td(">90%"),   tdl("Poorest prognosis; rule out ALCL")],
    [tdb("NLPHL (non-classic)"),   td("~5%"),    tdl("Popcorn/L&H cells"),       tdl("CD20+, BCL6+, CD30−, CD15−, CD45+"), td("Rare"), tdl("Different entity; better prognosis")],
]
hl_table = Table(hl_data, colWidths=[3.4*cm, 1.6*cm, 2.8*cm, 4.8*cm, 1.2*cm, 3.9*cm])
hl_ts = base_table_style()
# NLPHL row highlight in amber background
for col in range(6):
    hl_ts.append(("BACKGROUND", (col, 5), (col, 5), HexColor("#FFF3CD")))
hl_table.setStyle(TableStyle(hl_ts))

story.append(KeepTogether([
    section_bar("3 · HODGKIN LYMPHOMA — SUBTYPE IHC"),
    Spacer(1, 0.15*cm),
    hl_table,
    Spacer(1, 0.15*cm),
    Paragraph("w = weakly positive  |  NLPHL = Nodular Lymphocyte Predominant HL (highlighted — distinct from classic HL)", CAPTION),
    Spacer(1, 0.4*cm),
]))

# ── SECTION 4: DLBCL SUBTYPING — HANS ALGORITHM ─────────────────────────────
hans_data = [
    [th("Step"), th("Marker"), th("Threshold"), th("Result")],
    [td("1"), tdb("CD10"), tdl("> 30% positive"), tdl("→ GCB type (stop)")],
    [td("2"), tdb("BCL6"), tdl("Positive"), tdl("→ Proceed to step 3; if negative → non-GCB (ABC)")],
    [td("3"), tdb("MUM1"), tdl("Positive"), tdl("→ non-GCB (ABC); if negative → GCB")],
]
hans_table = Table(hans_data, colWidths=[1.5*cm, 2.5*cm, 4.5*cm, 9.2*cm])
hans_table.setStyle(TableStyle(base_table_style()))

combo_data = [
    [th("CD10"), th("BCL6"), th("MUM1"), th("Phenotype"), th("Common Genetics"), th("Prognosis")],
    [pos(), pos(), neg(), tdb("GCB"),       tdl("t(14;18) BCL2; BCL6 rare"), tdl("Better (R-CHOP sensitive)")],
    [pos(), neg(), neg(), tdb("GCB"),       tdl("t(14;18) BCL2"),            tdl("Better")],
    [neg(), pos(), neg(), tdb("GCB"),       tdl("BCL6 rearrangement"),       tdl("Better")],
    [neg(), pos(), pos(), tdb("non-GCB (ABC)"), tdl("BCL6 t(3;X)"),         tdl("Worse")],
    [neg(), neg(), pos(), tdb("non-GCB (ABC)"), tdl("NF-κB activation"),    tdl("Worse")],
]
combo_table = Table(combo_data, colWidths=[1.8*cm, 1.8*cm, 1.8*cm, 3.2*cm, 5.5*cm, 3.6*cm])
combo_table.setStyle(TableStyle(base_table_style()))

story.append(KeepTogether([
    section_bar("4 · DLBCL SUBTYPING — HANS ALGORITHM (IHC)"),
    Spacer(1, 0.15*cm),
    Paragraph("<b>Step-wise evaluation:</b>", BODY_BOLD),
    Spacer(1, 0.1*cm),
    hans_table,
    Spacer(1, 0.25*cm),
    Paragraph("<b>Full combination matrix:</b>", BODY_BOLD),
    Spacer(1, 0.1*cm),
    combo_table,
    Spacer(1, 0.15*cm),
    Paragraph(
        "Double-hit lymphoma: MYC rearrangement + BCL2 and/or BCL6 rearrangement — confirm by FISH. "
        "Extremely poor prognosis (median OS 12–18 months). MYC protein >40% + BCL2 >50% by IHC = "
        '"double-expressor" — also adverse even without rearrangements.',
        BODY_STYLE),
    Spacer(1, 0.4*cm),
]))

# ── SECTION 5: T-CELL / NK-CELL LYMPHOMAS ────────────────────────────────────
tcell_data = [
    [th("Lymphoma"), th("Key Positive Markers"), th("Key Negative"), th("Special Marker"), th("Notes")],
    [tdb("PTCL-NOS"),    tdl("CD3, CD4 or CD8"), tdl("No single defining marker"), tdl("Aberrant T-cell Ag loss"), tdl("Diagnosis of exclusion")],
    [tdb("ALCL ALK+"),   tdl("CD30 (strong), EMA"), tdl("CD3 often −"), tdl("ALK (nuclear+cytoplasmic)"), tdl("Better prognosis; t(2;5) NPM-ALK")],
    [tdb("ALCL ALK−"),   tdl("CD30 (strong), EMA"), tdl("ALK−"),        tdl("DUSP22 or TP63 by FISH"), tdl("Worse prognosis")],
    [tdb("AITL"),        tdl("CD3, CD4, PD-1, CXCL13, CD10"), tdl("CD8"), tdl("CD21+ expanded FDC meshwork, EBER+"), tdl("TFH cell origin")],
    [tdb("NK/T-cell"),   tdl("CD56, CD2, cytoCD3, Granzyme B"), tdl("sCD3−, CD5−"), tdl("EBV (EBER) in situ hybridisation +"), tdl("Nasal type; aggressive")],
    [tdb("Hepatosplenic"), tdl("CD3, CD56"), tdl("CD4−, CD8−"), tdl("TCRγδ+"), tdl("Young males; sinusoidal")],
    [tdb("ATLL"),        tdl("CD3, CD4, CD25"), tdl("CD7 (often lost)"), tdl("HTLV-1 serology"), tdl("FoxP3+ (regulatory T-cell)")],
    [tdb("MF / Sézary"), tdl("CD3, CD4"), tdl("CD7, CD26 loss"), tdl("CD4:CD8 ratio >10 in blood"), tdl("Epidermotropic; indolent")],
]
tcell_table = Table(tcell_data, colWidths=[2.8*cm, 4.2*cm, 2.5*cm, 4.4*cm, 3.8*cm])
tcell_table.setStyle(TableStyle(base_table_style()))

story.append(KeepTogether([
    section_bar("5 · T-CELL & NK-CELL LYMPHOMAS"),
    Spacer(1, 0.15*cm),
    tcell_table,
    Spacer(1, 0.15*cm),
    Paragraph("AITL = Angioimmunoblastic T-cell Lymphoma  |  ALCL = Anaplastic Large Cell Lymphoma  |  MF = Mycosis Fungoides  |  TFH = T follicular helper", CAPTION),
    Spacer(1, 0.4*cm),
]))

# ── PAGE 2: DIFFERENTIAL DIAGNOSIS PANELS ────────────────────────────────────
story.append(PageBreak())

# ── SECTION 6: KEY DIFFERENTIALS ──────────────────────────────────────────────
diff_data = [
    [th("Differential"), th("CD5"), th("CD10"), th("CD23"), th("Cyclin D1"), th("BCL2"), th("SOX11"), th("Key Distinguisher")],
    [tdb("CLL/SLL"),   pos("dim"), neg(), pos(), neg(), pos(), neg(), tdl("CD23+, CD5+, dim CD20, dim sIg")],
    [tdb("MCL"),       pos(),      neg(), neg(), pos("✓"),pos(),pos("✓"),tdl("Cyclin D1+ (FISH if negative); SOX11+")],
    [tdb("FL"),        neg(),      pos(), neg(), neg(), pos("✓"),neg(),tdl("CD10+, BCL2+, follicular pattern, t(14;18)")],
    [tdb("MZL/MALT"),  neg(),      neg(), neg(), neg(), var(), neg(), tdl("All negative — diagnosis by exclusion + morphology")],
]
diff_table = Table(diff_data, colWidths=[2.6*cm, 1.4*cm, 1.4*cm, 1.5*cm, 2.2*cm, 1.4*cm, 1.5*cm, 6.2*cm])
diff_table.setStyle(TableStyle(base_table_style()))

story.append(KeepTogether([
    section_bar("6 · DIFFERENTIAL: SMALL B-CELL LYMPHOMAS"),
    Spacer(1, 0.15*cm),
    diff_table,
    Spacer(1, 0.4*cm),
]))

# ── Burkitt vs DLBCL ──────────────────────────────────────────────────────────
bvd_data = [
    [th("Feature"),        th("Burkitt Lymphoma"),               th("DLBCL")],
    [tdb("CD20"),          pos(),                                pos()],
    [tdb("CD10"),          pos(),                                var()],
    [tdb("BCL6"),          pos(),                                var()],
    [tdb("BCL2"),          neg("✓ negative"),                    var()],
    [tdb("MUM1"),          neg(),                                var()],
    [tdb("Ki-67"),         td("~100% ✓"),                        td("60–90%")],
    [tdb("MYC"),           tdl("Rearranged (FISH) 100%"),        tdl("~10% rearranged")],
    [tdb("Morphology"),    tdl('"Starry sky" — tingible-body macrophages'), tdl("Large atypical cells, necrosis")],
    [tdb("Translocation"), tdl("t(8;14), t(2;8), t(8;22)"),     tdl("t(14;18) in GCB; BCL6 in ABC")],
]
bvd_table = Table(bvd_data, colWidths=[3.2*cm, 7.25*cm, 7.25*cm])
bvd_table.setStyle(TableStyle(base_table_style()))

story.append(KeepTogether([
    section_bar("7 · DIFFERENTIAL: BURKITT vs DLBCL"),
    Spacer(1, 0.15*cm),
    bvd_table,
    Spacer(1, 0.4*cm),
]))

# ── Classic HL vs NLPHL ────────────────────────────────────────────────────────
hl_diff_data = [
    [th("Feature"),    th("Classic HL"),                     th("NLPHL")],
    [tdb("RS/Tumor cell"), tdl("Classic RS, lacunar, mononuclear"), tdl("Popcorn/L&H cells")],
    [tdb("CD20"),      neg(),                                pos("✓")],
    [tdb("CD45"),      neg("✓"),                             pos()],
    [tdb("CD15"),      pos("✓"),                             neg("✓")],
    [tdb("CD30"),      pos("✓"),                             neg("rare+")],
    [tdb("PAX5"),      pos("weak"),                          pos("strong")],
    [tdb("BCL6"),      neg(),                                pos("✓")],
    [tdb("EBV"),       var("+/− (subtype dependent)"),       neg("Rare")],
    [tdb("EMA"),       neg(),                                pos("+/−")],
    [tdb("Background"),tdl("T-cells, eosinophils, plasma cells"), tdl("B-cell-rich nodules, FDC meshwork")],
    [tdb("Prognosis"), tdl("Excellent with chemo-RT"),      tdl("Excellent; late relapses possible")],
]
hl_diff_table = Table(hl_diff_data, colWidths=[3.2*cm, 7.25*cm, 7.25*cm])
hl_diff_table.setStyle(TableStyle(base_table_style()))

story.append(KeepTogether([
    section_bar("8 · DIFFERENTIAL: CLASSIC HL vs NLPHL"),
    Spacer(1, 0.15*cm),
    hl_diff_table,
    Spacer(1, 0.4*cm),
]))

# ── SECTION 9: PRACTICAL TIPS ─────────────────────────────────────────────────
tips = [
    ("<b>CD45 first:</b> A CD45-negative large cell tumour raises HL, germ cell tumour, carcinoma, or melanoma "
     "before NHL. Always confirm with CD30/CD15 (HL) or keratins/PLAP (carcinoma/GCT)."),
    ("<b>BCL2 in follicular lymphoma:</b> BCL2+ in neoplastic follicles vs. BCL2− in reactive follicles. "
     "Confirm t(14;18) by FISH when in doubt."),
    ("<b>Burkitt BCL2:</b> BCL2 negativity with Ki-67 ~100% virtually excludes DLBCL and is a red flag for Burkitt. "
     "Always confirm MYC rearrangement by FISH."),
    ("<b>Double-expressor DLBCL:</b> MYC >40% + BCL2 >50% by IHC without FISH-confirmed rearrangement still "
     "confers adverse prognosis but does not define 'double-hit lymphoma'. FISH is needed for the latter."),
    ("<b>ALK in ALCL:</b> ALK+ ALCL (t(2;5), NPM-ALK fusion) — nuclear+cytoplasmic staining. "
     "ALK− ALCL — identical morphology and CD30 positivity but ALK absent; worse prognosis."),
    ("<b>CD5+ B-cell lymphoma:</b> MCL (cyclin D1+, SOX11+) vs CLL/SLL (CD23+, dim sIg). "
     "Rarely, DLBCL can be CD5+ — aggressive behaviour."),
    ("<b>T-cell marker loss:</b> In T-cell lymphomas, aberrant loss of CD3, CD5, or CD7 supports neoplasia. "
     "Normal T-cells express all three."),
    ("<b>EBV in NK/T-cell lymphoma:</b> EBER (EBV-encoded RNA) by in situ hybridisation is the preferred method "
     "— more sensitive than LMP-1 by IHC."),
    ("<b>Hairy Cell Leukaemia:</b> CD20+, CD11c+, CD25+, CD103+ (TRAP+). CD5−, CD23−. "
     "BRAF V600E IHC (VE1 antibody) positive in >95%."),
]

tips_story = [
    section_bar("9 · PRACTICAL DIAGNOSTIC TIPS"),
    Spacer(1, 0.15*cm),
]
for i, tip in enumerate(tips, 1):
    tips_story.append(Paragraph(f"<b>{i}.</b>  {tip}", BODY_STYLE))

story.append(KeepTogether(tips_story))
story.append(Spacer(1, 0.5*cm))

# ── SECTION 10: QUICK ALGORITHM BOXES ─────────────────────────────────────────
algo_data = [
    [th("Clinical Scenario"), th("First IHC Panel"), th("Decision")],
    [tdl("Undifferentiated large cell"), tdl("CD45, CK, S100, CD30"), tdl("CD45+ → lymphoma panel | CD45− → carcinoma/melanoma/HL")],
    [tdl("Small B-cell lymphoma"), tdl("CD5, CD10, CD23, Cyclin D1"), tdl("See Section 6 algorithm above")],
    [tdl("Large B-cell lymphoma"), tdl("CD20, CD10, BCL6, MUM1, BCL2, Ki-67"), tdl("Apply Hans algorithm; add MYC IHC if high grade")],
    [tdl("Mediastinal mass"), tdl("CD20, CD30, CD15, CD45, PAX5"), tdl("HL vs PMBCL (CD20+ CD23+ BCL6+ MAL+) vs T-LBL")],
    [tdl("Suspect Burkitt"), tdl("CD20, CD10, BCL6, BCL2, Ki-67, MYC FISH"), tdl("BCL2−, Ki-67 ~100%, MYC FISH+ = Burkitt")],
    [tdl("Suspect T-cell NHL"), tdl("CD3, CD4, CD8, CD5, CD7, CD30, ALK"), tdl("Loss of CD5/CD7 supports neoplasia; CD30+ → ALCL panel")],
    [tdl("Skin lymphoma"), tdl("CD3, CD4, CD8, CD20, CD30, CD56"), tdl("CD4+ epidermotropic = MF; CD30+ = lymphomatoid papulosis/pcALCL")],
]
algo_table = Table(algo_data, colWidths=[4.0*cm, 5.5*cm, 8.2*cm])
algo_table.setStyle(TableStyle(base_table_style()))

story.append(KeepTogether([
    section_bar("10 · CLINICAL SCENARIO — PANEL SELECTION GUIDE"),
    Spacer(1, 0.15*cm),
    algo_table,
    Spacer(1, 0.4*cm),
]))

# ── FOOTER DISCLAIMER ─────────────────────────────────────────────────────────
story.append(HRFlowable(width="100%", thickness=0.5, color=NAVY))
story.append(Spacer(1, 0.15*cm))
story.append(Paragraph(
    "This quick-reference document is intended for educational and clinical support purposes. "
    "IHC interpretation must always be correlated with morphology, clinical context, and molecular findings. "
    "Sources: Robbins, Cotran & Kumar Pathologic Basis of Disease; Harrison's Principles of Internal Medicine 22E; "
    "Quick Compendium of Clinical Pathology 5th Edition; Henry's Clinical Diagnosis and Management by Laboratory Methods; "
    "Murray & Nadel's Textbook of Respiratory Medicine. WHO Classification of Tumours of Haematopoietic and Lymphoid Tissues.",
    FOOTNOTE))

# ── Build PDF ─────────────────────────────────────────────────────────────────
doc.build(story,
          onFirstPage=on_first_page,
          onLaterPages=on_later_pages)

print(f"PDF generated: {OUTPUT}")
Running Command

python3 /home/daytona/workspace/lymphoma-ihc/generate_pdf.py 2>&1

Running Command

ls -lh /home/daytona/workspace/lymphoma-ihc/Lymphoma_IHC_Quick_Reference.pdf

Your PDF is ready:

Lymphoma IHC Quick Reference

PDF Document · PDF


Here's what's included across the 2-page document:
SectionContents
LegendSymbol key: +, −, +/−, dim+, ~100%
1. Core Lineage MarkersCD45, CD20, CD79a, PAX5, CD3, CD5, CD10, BCL6, MUM1, BCL2, Cyclin D1, CD30, CD15, Ki-67, EBV
2. Master IHC Profile Table12 lymphoma types across 11 markers - with highlighted hallmark cells
3. Hodgkin Lymphoma SubtypesAll 5 HL subtypes with RS cell variant, IHC profile, EBV association
4. DLBCL Hans AlgorithmStep-wise CD10/BCL6/MUM1 subtyping table + full combination matrix + double-hit note
5. T-cell & NK-cell LymphomasPTCL, ALCL ALK+/−, AITL, NK/T, Hepatosplenic, ATLL, MF/Sézary
6. Small B-cell DifferentialCLL vs MCL vs FL vs MALT comparison
7. Burkitt vs DLBCL9-point IHC + genetics comparison
8. Classic HL vs NLPHLSide-by-side IHC distinction table
9. Practical Diagnostic Tips9 high-yield pearls (BCL2, double-expressor, ALK, CD5, etc.)
10. Panel Selection GuideScenario-based first-line panel recommendations
Color-coded throughout with navy/teal headers, green + / red − symbols, and gold highlighting for hallmark markers.
This is a shared conversation. Sign in to Orris to start your own chat.