Ihc studies in lymphoma
| Marker | Lineage/Role | Key Notes |
|---|---|---|
| CD45 (LCA) | Pan-leukocyte | Positive in NHL; negative in classic HL (Reed-Sternberg cells) |
| CD20 | B-cell marker | All mature B-cell lymphomas; therapeutic target for rituximab |
| CD79a | B-cell marker | More sensitive than CD20 in some B-cell lymphomas |
| PAX5 | B-cell transcription factor | Present on Reed-Sternberg cells in classic HL (weak) |
| CD3 | Pan-T-cell marker | T-cell lymphomas |
| CD5 | T-cell/subset B-cell | Also positive in CLL/SLL and mantle cell lymphoma |
| CD10 | Follicle center marker | Follicular lymphoma, DLBCL (GCB type), Burkitt |
| Ki-67 | Proliferation index | Very high (>95%) in Burkitt lymphoma; helps grade |
NLPHL vs. Classic HL distinction by IHC is critical, as NLPHL has a different clinical course and treatment.
| Step | Marker | Interpretation |
|---|---|---|
| 1 | CD10 | If >30% positive → GCB type |
| 2 | BCL6 | If CD10-, BCL6- → non-GCB (ABC) |
| 3 | MUM1 | If BCL6+, MUM1+ → non-GCB (ABC); MUM1- → GCB |
| CD10 | BCL6 | MUM1 | Phenotype |
|---|---|---|---|
| + | + | - | GCB |
| + | - | - | GCB |
| - | + | - | GCB |
| - | + | + | non-GCB (ABC) |
| - | - | + | non-GCB (ABC) |

| Lymphoma | Key IHC Profile |
|---|---|
| Peripheral T-cell lymphoma NOS | CD3+, 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 type | CD2+, CD56+, cytoplasmic CD3+, EBV+, granzyme B+ |
| Hepatosplenic T-cell Lymphoma | CD3+, 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
| Lymphoma | CD20 | CD5 | CD10 | CD23 | Cyclin D1 | CD30 | CD15 | BCL2 | Ki-67 |
|---|---|---|---|---|---|---|---|---|---|
| SLL/CLL | dim+ | + | - | + | - | - | - | + | low |
| MCL | + | + | - | - | + | - | - | + | variable |
| FL | + | - | + | - | - | - | - | + | low-mod |
| DLBCL | + | - | +/- | - | - | - | - | +/- | high |
| Burkitt | + | - | + | - | - | - | - | - | ~100% |
| MALT MZL | + | - | - | - | - | - | - | +/- | low |
| Classic HL (RS) | - | - | - | - | - | + | + | - | - |
| NLPHL (L&H) | + | - | - | - | - | - | - | - | - |
| ALCL | - | - | - | - | - | + | - | - | high |

Generate a quick reference PDF for lymphoma IHC stain interpretation
ls /home/daytona/workspace/ && python3 -c "import reportlab; print('reportlab ok')" && python3 -c "from reportlab.lib import colors; print('colors ok')"
mkdir -p /home/daytona/workspace/lymphoma-ihc
~/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}")
python3 /home/daytona/workspace/lymphoma-ihc/generate_pdf.py 2>&1
ls -lh /home/daytona/workspace/lymphoma-ihc/Lymphoma_IHC_Quick_Reference.pdf
Lymphoma IHC Quick Reference
PDF Document · PDF
| Section | Contents |
|---|---|
| Legend | Symbol key: +, −, +/−, dim+, ~100% |
| 1. Core Lineage Markers | CD45, CD20, CD79a, PAX5, CD3, CD5, CD10, BCL6, MUM1, BCL2, Cyclin D1, CD30, CD15, Ki-67, EBV |
| 2. Master IHC Profile Table | 12 lymphoma types across 11 markers - with highlighted hallmark cells |
| 3. Hodgkin Lymphoma Subtypes | All 5 HL subtypes with RS cell variant, IHC profile, EBV association |
| 4. DLBCL Hans Algorithm | Step-wise CD10/BCL6/MUM1 subtyping table + full combination matrix + double-hit note |
| 5. T-cell & NK-cell Lymphomas | PTCL, ALCL ALK+/−, AITL, NK/T, Hepatosplenic, ATLL, MF/Sézary |
| 6. Small B-cell Differential | CLL vs MCL vs FL vs MALT comparison |
| 7. Burkitt vs DLBCL | 9-point IHC + genetics comparison |
| 8. Classic HL vs NLPHL | Side-by-side IHC distinction table |
| 9. Practical Diagnostic Tips | 9 high-yield pearls (BCL2, double-expressor, ALK, CD5, etc.) |
| 10. Panel Selection Guide | Scenario-based first-line panel recommendations |
Discuss NHL who classification, molecular markers and recent advances
"non-Hodgkin lymphoma" AND "WHO classification" AND "molecular"
"lymphoma" AND "molecular pathogenesis" AND "targeted therapy"
"CAR-T cell" AND "lymphoma" AND "outcomes"
"bispecific antibody" AND "large B cell lymphoma"
"5th edition WHO classification" AND "lymphoid neoplasms" AND "2022"
PMID: 38978094
PMID: 36788062
"follicular lymphoma" AND "molecular markers" AND "prognosis"
"DLBCL" AND "genetic subtypes" AND "EZB MCD BN2 N1"
"DLBCL" AND "genetic subtypes" AND "targeted therapy"
"lymphoma" AND "BTK inhibitor" AND "novel therapy" AND "2024"
WHO 5th edition 2022 lymphoma classification changes NHL new entities ICC
NHL recent advances 2024 2025 CAR-T bispecific antibody ADC tafasitamab loncastuximab polatuzumab
PMID: 41448213
| Edition | Year | Key Features |
|---|---|---|
| Working Formulation | 1982 | Low/intermediate/high grade by clinical behavior |
| REAL Classification | 1994 | Introduced disease entities (not just grade) |
| WHO 3rd edition | 2001 | Adopted cell of origin; morphology + IHC + genetics |
| WHO 4th edition | 2008 | Expanded provisional entities |
| WHO 4th revised (HAEM4R) | 2016/2017 | Added new entities; GCB/ABC DLBCL subtypes formalized |
| WHO 5th edition (HAEM5) | 2022 | Genetic-first approach; new ICC also published |
| Subtype | Key Mutations | Biology | Notes |
|---|---|---|---|
| EZB (GCB-like) | EZH2, BCL2 rearrangement | Epigenetic dysregulation | Most common GCB subtype |
| MCD (ABC-like) | MYD88 L265P, CD79B | BCR/TLR signaling | Overlaps with ABC type |
| BN2 (GCB-like) | BCL6 fusions, NOTCH2 | Marginal zone-like features | Better prognosis |
| N1 | NOTCH1 mutations | NOTCH pathway | Worse prognosis |
| ST2 | SGK1, TET2 | - | GCB-enriched |
| A53 | TP53 biallelic inactivation | Genomic instability | Adverse |
1 extranodal site
| Score | Risk Group | Approximate 5-yr OS (R-CHOP era) |
|---|---|---|
| 0-1 | Low | ~75% |
| 2 | Low-intermediate | ~65% |
| 3 | High-intermediate | ~50% |
| 4-5 | High | ~35% |
| Stage | Description |
|---|---|
| I | Single lymph node region or single extralymphatic site |
| II | ≥2 lymph node regions, same side of diaphragm |
| III | Lymph node regions on both sides of diaphragm |
| IV | Diffuse extralymphatic involvement |
| A/B | B = fever >38°C, night sweats, >10% weight loss |
| Drug | Target | Approval | Key Trial |
|---|---|---|---|
| Glofitamab | CD20×CD3 | FDA 2023 | Fixed-duration 12 cycles; CR ~35% in R/R DLBCL |
| Epcoritamab | CD20×CD3 | FDA 2023 | SC injection; CR ~39% in R/R DLBCL |
| Mosunetuzumab | CD20×CD3 | FDA 2022 | Approved for R/R follicular lymphoma |
| Drug | Target/Payload | Indication |
|---|---|---|
| Polatuzumab vedotin | Anti-CD79b + MMAE | FL (R/R); DLBCL frontline (Pola-R-CHP, POLARIX trial - improved PFS vs R-CHOP) |
| Loncastuximab tesirine | Anti-CD19 + PBD dimer | R/R DLBCL (LOTIS-2: ORR 48.3%, CR 24.1%); active post-CAR-T failure |
| Tafasitamab | Anti-CD19 (Fc-enhanced) | R/R DLBCL (with lenalidomide, L-MIND trial) |
| Brentuximab vedotin | Anti-CD30 + MMAE | ALCL, HL, CD30+ lymphomas |
| Drug | Target | NHL Application |
|---|---|---|
| Ibrutinib (1st gen BTKi) | BTK | MCL, CLL, WM, MZL; MCD-type DLBCL |
| Acalabrutinib, Zanubrutinib | BTK (more selective) | CLL, MCL; fewer off-target effects |
| Venetoclax | BCL2 | CLL (esp. del(17p)); FL, MCL (investigational/approved combinations) |
| Tazemetostat | EZH2 | FL with EZH2 mutations (FDA approved 2020) |
| Idelalisib, Duvelisib, Copanlisib | PI3K-δ/γ | FL (2nd+ line) |
| Lenalidomide + R (R²) | Immunomodulatory | FL, MCL, DLBCL |
| NHL Subtype | Defining Genetic Event | Key Signaling Pathway | Targeted Agent |
|---|---|---|---|
| CLL/SLL | IGHV status; del(17p)/TP53; NOTCH1/SF3B1 | BCR → BTK | Ibrutinib, venetoclax |
| FL | t(14;18) BCL2; EZH2 Tyr641; CREBBP | BCL2; epigenetic | Tazemetostat (EZH2+); venetoclax |
| MCL | t(11;14) Cyclin D1; TP53; ATM | Cyclin D1 / BCR | Ibrutinib/acalabrutinib; venetoclax |
| DLBCL-GCB | t(14;18) BCL2; EZH2; BCL6 | BCL2; epigenetic | Polatuzumab-R-CHP frontline |
| DLBCL-ABC | MYD88 L265P; CD79B; BCL6 t(3;X) | NF-κB; BCR/TLR | Ibrutinib (MCD subtype) |
| HGBL "DH" | MYC + BCL2/BCL6 | Proliferation + anti-apoptosis | DA-EPOCH-R; CAR-T |
| Burkitt | t(8;14) MYC | MYC overexpression | DA-EPOCH-R; high-dose regimens |
| AITL/TFH | RHOA G17V; IDH2 R172; TET2; DNMT3A | Epigenetic dysregulation | Enasidenib (IDH2i, investigational) |
| ALCL ALK+ | t(2;5) NPM-ALK | ALK kinase | Crizotinib, lorlatinib |
| T-LGLL | STAT3/STAT5B | JAK-STAT | Ruxolitinib (investigational) |
Causes of lymphadenopathy.discuss approach to the diagnosis of the lymphoma
"lymphadenopathy" AND "diagnosis" AND "approach"
PMID: 39085185
approach to diagnosis of lymphoma workup 2024 biopsy flow cytometry FISH NGS staging
| Virus | Nodes Involved | Features |
|---|---|---|
| EBV (Infectious Mononucleosis) | Cervical (posterior > anterior), generalized | Fever, pharyngitis, splenomegaly, atypical lymphocytosis |
| CMV | Generalized | Mononucleosis-like, milder pharyngitis |
| HIV | Generalized (persistent generalized lymphadenopathy - PGL) | Early HIV; axillary + cervical + inguinal |
| Rubella | Posterior auricular, suboccipital, posterior cervical | Rash, low fever |
| Measles | Cervical | Koplik spots, maculopapular rash |
| Adenovirus | Cervical | Pharyngitis, conjunctivitis |
| Herpesvirus | Regional (near site) | Vesicular lesions |
| Varicella-Zoster | Generalized | Vesicular rash |
| HHV-8 | Generalized | Castleman disease, Kaposi sarcoma |
| Organism | Nodes Involved | Features |
|---|---|---|
| Streptococcus/Staphylococcus | Cervical, regional | Tender, warm, fluctuant; acute onset |
| Mycobacterium tuberculosis | Cervical (scrofula), mediastinal, hilar | Caseating; can be matted, collar stud abscess |
| Atypical mycobacteria (NTM) | Cervical (children) | Painless, violaceous skin |
| Cat-scratch disease (Bartonella) | Axillary > cervical | Cat scratch/bite history; stellate microabscesses |
| Brucellosis | Generalized | Animal exposure, Malta fever |
| Tularemia | Regional (painful) | Rabbit/tick exposure; ulceroglandular form |
| Syphilis (primary) | Inguinal (rubbery, painless) | Primary chancre |
| Syphilis (secondary) | Generalized (painless) | Rash on palms/soles |
| Plague (Yersinia pestis) | Axillary/inguinal (bubo) | Extremely tender, rapidly enlarging |
| LGV (Chlamydia) | Inguinal (buboes) | Genital ulcer, groove sign |
| Leprosy | Regional | Thickened nerve, skin lesions |
| Diphtheria | Cervical ("bull neck") | Grey pseudomembrane |
| Parasite | Site | Key Feature |
|---|---|---|
| Toxoplasmosis | Posterior cervical (painless) | Most common specific cause of benign lymphadenopathy in adults |
| Leishmaniasis | Generalized + splenomegaly | Kala-azar |
| Trypanosomiasis | Posterior cervical (Winterbottom sign) | African sleeping sickness |
| Filariasis | Inguinal | Lymphedema, tropical |
| Condition | Pattern | Features |
|---|---|---|
| Rheumatoid arthritis | Generalized | Joint disease |
| SLE | Generalized, tender | ANA+, multi-system |
| Dermatomyositis | Generalized | Muscle weakness, heliotrope rash |
| Sjögren's syndrome | Cervical, parotid | Dry eyes/mouth; risk of MALT lymphoma |
| Serum sickness | Generalized | Drug/antigen exposure, urticaria, arthralgia |
| Drug hypersensitivity | Generalized | Diphenylhydantoin (phenytoin), hydralazine, allopurinol, carbamazepine, gold - pseudo-lymphoma |
| Angioimmunoblastic lymphadenopathy | Generalized | Polyclonal hypergammaglobulinemia; may transform to AITL |
| IgG4-related disease | Salivary glands, mediastinal | Storiform fibrosis, elevated IgG4 |
| IRIS | Generalized | Immune reconstitution in HIV on ART |
| Graft-vs-host disease | Generalized | Post-transplant |
| Autoimmune lymphoproliferative syndrome (ALPS) | Generalized | FAS mutations, failure of apoptosis |
| Juvenile idiopathic arthritis (Still's) | Generalized | Quotidian fever, salmon rash |
| Primary biliary cirrhosis | Portal, retroperitoneal |
| Region | Typical Primaries |
|---|---|
| Cervical | Head & neck, thyroid, lung, esophagus |
| Left supraclavicular (Virchow's node) | GI primaries (gastric, pancreatic, colon), lung, breast |
| Right supraclavicular | Lung, esophagus, breast |
| Axillary | Breast, melanoma, lung, upper limb |
| Inguinal | Rectum, genitalia (cervix, vulva, penis), melanoma, lower limb |
| Mediastinal | Lung, lymphoma, germ cell tumors |
| Retroperitoneal | Germ cell tumors (testicular), renal, lymphoma |
Key rule: Supraclavicular/scalene adenopathy is always pathological and carries high risk of malignancy. Retroperitoneal/intra-abdominal adenopathy is usually malignant.
| Cause | Key Feature |
|---|---|
| Sarcoidosis | Bilateral hilar adenopathy ("bat wing"), non-caseating granulomas |
| Castleman disease | Giant lymph node hyperplasia; unicentric or multicentric (HHV-8) |
| Kikuchi-Fujimoto disease | Histiocytic necrotizing lymphadenitis; young Asian women; cervical; self-limiting |
| Rosai-Dorfman disease | Sinus histiocytosis with massive lymphadenopathy; extranodal disease |
| Kawasaki disease | Cervical + fever + mucocutaneous features; children |
| Dermatopathic lymphadenitis | Draining skin with chronic dermatitis |
| Gaucher/Niemann-Pick/Fabry diseases | Lipid storage; hepatosplenomegaly > adenopathy |
| Hyperthyroidism | Cervical; rarely adenopathy |
| Congestive heart failure | Passive congestion |
| Histiocytosis X (LCH) | Children; bone/skin lesions |
| Familial Mediterranean fever | Episodic; abdominal adenopathy |
| Feature | Benign/Reactive | Suspicious for Lymphoma | Metastatic Carcinoma |
|---|---|---|---|
| Consistency | Soft, rubbery | Rubbery, firm | Hard ("stone-like") |
| Tenderness | Tender (infection) | Usually nontender | Nontender |
| Mobility | Mobile | Mobile | Fixed, matted |
| Surface | Smooth | Smooth/discrete | Irregular |
| Overlying skin | Normal or erythematous | Normal | May be inflamed |
| Size | Usually <1 cm | Often >2 cm | Variable |
| Distribution | Regional | Regional or generalized | Regional (drainage area) |
| Site | Malignant Differential |
|---|---|
| Posterior cervical | Lymphoma, head/neck malignancy, scalp lesion |
| Anterior cervical | Head/neck primary, thyroid cancer |
| Left supraclavicular | GI primary (Virchow's node), lung, lymphoma |
| Right supraclavicular | Lung, lymphoma, breast |
| Axillary | Breast cancer (women), melanoma, lymphoma |
| Mediastinal | HL (anterior), DLBCL/PMBCL, thymoma, germ cell, sarcoid, TB |
| Retroperitoneal | Testicular GCT (young men), lymphoma, renal |
| Inguinal | Rectal, cervical, penile, vulvar cancers, melanoma |
| Test | Why |
|---|---|
| CBC + peripheral smear | Atypical lymphocytes (EBV/CMV); blasts (leukemia); lymphocytosis with smudge cells (CLL); anemia/thrombocytopenia |
| ESR / CRP | Nonspecific but elevated in infection, HL, autoimmune |
| LDH | Elevated in aggressive lymphoma (also hemolysis, hepatitis) - prognostic |
| Uric acid | Elevated in high-turnover lymphomas (Burkitt); tumor lysis risk |
| Liver function tests / Alk Phos | Hepatic infiltration by lymphoma; biliary obstruction |
| Renal function | Baseline; ureteral obstruction by retroperitoneal nodes |
| Serum protein electrophoresis | Monoclonal band in myeloma, WM; polyclonal hypergammaglobulinemia in AITL |
| Chest X-ray | Mediastinal widening (HL, PMBCL); pulmonary infiltrate; hilar adenopathy |
| Test | Indication |
|---|---|
| Monospot / EBV / CMV serology | Mononucleosis syndrome |
| HIV serology (4th gen Ag/Ab) | Generalized adenopathy in risk group |
| Toxoplasma IgM/IgG | Painless posterior cervical; cat exposure |
| Mantoux / IGRA / sputum AFB | TB suspected |
| ANA, anti-dsDNA, RF, complement | Autoimmune workup |
| Beta-2 microglobulin | Prognostic in NHL/myeloma |
| Serum immunoglobulins | Myeloma, WM, CLL |
| HTLV-1 serology | ATLL suspected (endemic area, Caribbean/Japan) |
| Flow cytometry (peripheral blood) | Lymphocytosis with CLL or lymphoma in leukemic phase |
| Type | Role | Limitations |
|---|---|---|
| Excisional lymph node biopsy | Gold standard for lymphoma diagnosis | Most invasive; preserves architecture |
| Core needle biopsy (CNB) | Good alternative when excision impractical; CT/US-guided | May miss architecture; multiple cores needed |
| Fine-needle aspiration (FNA) | Adequate for metastatic carcinoma, infection culture | Inadequate for lymphoma - cannot distinguish malignant from reactive; discouraged if lymphoma is suspected |
| Incisional biopsy | Large bulky nodes | |
| Bone marrow biopsy | Staging (HL/NHL) | Trephine + aspirate |
Key principle: Face-to-face discussion between clinician and pathologist is the most effective approach for challenging cases. FNA is specifically discouraged in suspected lymphoma because it cannot assess nodal architecture, which is required for accurate classification. - Goldman-Cecil Medicine
TISSUE OBTAINED
│
├─ Histology (H&E) ──────── Architecture (follicular vs diffuse vs sinusoidal)
│ Cell morphology, size, mitotic rate
│
├─ Immunohistochemistry ─── Lineage (B vs T vs NK), subtype markers
│ (IHC) (CD20, CD3, CD10, BCL2, BCL6, MUM1, CD30, CD15, etc.)
│
├─ Flow Cytometry ────────── Light chain restriction (B-cell clonality)
│ T-cell antigen loss, NK markers
│ CD45/scatter (blasts vs mature)
│
├─ Cytogenetics (karyotype) ─ t(14;18) FL, t(11;14) MCL, t(8;14) Burkitt
│ t(2;5) ALCL, complex karyotype
│
├─ FISH ─────────────────── MYC, BCL2, BCL6 rearrangements (double/triple hit)
│ IGH-BCL2 (FL), CCND1-IGH (MCL), NPM-ALK (ALCL)
│
└─ NGS / Molecular ──────── MYD88 L265P (DLBCL-ABC/WM), EZH2 (FL/GCB)
TP53, RHOA (AITL), IDH2 (AITL)
TCR/IGH gene rearrangement (clonality PCR)
NanoString Lymph2Cx (GCB vs ABC DLBCL)
| Stage | Description |
|---|---|
| I | Single lymph node region or single extralymphatic site (IE) |
| II | ≥2 lymph node regions, same side of diaphragm; or localized extralymphatic + nodal (IIE) |
| III | Lymph node regions on both sides of diaphragm |
| IV | Diffuse/disseminated extralymphatic involvement (bone marrow, liver, lung, bone, CNS) |
| A | No B symptoms |
| B | Fever >38°C, night sweats, >10% weight loss |
| Bulky | Mass ≥10 cm (or mediastinal mass >1/3 thoracic diameter in HL) |
| Investigation | Purpose |
|---|---|
| PET/CT (whole body) | Staging, disease activity, response assessment |
| CT chest/abdomen/pelvis | Staging (if PET not available) |
| Bone marrow biopsy | Staging (in lymphomas not fully stageable by PET/CT) |
| LP + CSF cytology/flow | High-risk DLBCL (CNS IPI score ≥4), testicular/breast/adrenal involvement, Burkitt, lymphoblastic |
| Echocardiogram | Baseline before anthracycline-based therapy |
| Serum LDH | IPI scoring |
| HIV serology | All new NHL diagnoses |
| Hepatitis B surface Ag + core Ab | Before rituximab (risk of HBV reactivation) |
| Pregnancy test | Reproductive-age women |
| Fertility counseling | Before gonadotoxic chemotherapy |
Palpable lymphadenopathy
│
▼
History + Physical Examination
│
┌─────┴──────┐
Benign features Suspicious features
(tender, <1cm, (painless, >2cm, firm,
young, febrile, rubbery, supraclavicular,
no B sx) B symptoms, age >40,
│ generalized, splenomegaly)
▼ │
CBC, Monospot ▼
Observe 4-6 wks CBC + Smear, LDH, LFTs,
Antibiotics if Uric acid, CXR, HIV,
bacterial Beta-2M, SPEP
│ │
Resolved? Imaging (CT/PET-CT)
│ │
Yes → discharge ▼
No ─────────→ EXCISIONAL BIOPSY
(send fresh + fixed tissue)
│
H&E + IHC + Flow
Cytogenetics + FISH
Molecular/NGS
│
DIAGNOSIS CONFIRMED
│
STAGING + WORKUP
(bone marrow, CSF,
cardiac echo, HBV,
HIV, fertility)
│
TREATMENT PLANNING