Embryology of placenta
| Component | Origin | Tissue |
|---|---|---|
| Fetal part | Chorion frondosum (villous chorion) | Trophoblast + extraembryonic mesoderm |
| Maternal part | Decidua basalis | Modified endometrium |



The term "placental barrier" is a misnomer - most drugs, steroids, small molecules, and IgG antibodies cross freely. Only large/charged molecules (e.g., heparin) are truly excluded.
| Function | Detail |
|---|---|
| Respiration | O2/CO2 exchange by simple diffusion |
| Nutrition | Glucose (GLUT-1 facilitated diffusion), amino acids (active transport), fatty acids |
| Excretion | Fetal metabolic waste and CO2 |
| Endocrine | hCG (rescues corpus luteum, detectable from week 2), progesterone, estrogen, hPL, relaxin |
| Immunity | IgG crosses via pinocytosis; provides passive fetal immunity |
| Metabolism | Synthesizes glycogen, cholesterol, fatty acids, especially in early pregnancy |
Make a chart paper for pathology for the topic invasive breast cancer
ls /home/daytona/workspace/ 2>/dev/null && mkdir -p /home/daytona/workspace/brea…
~/breast-cancer-chart/chart.js
const pptxgen = require("pptxgenjs");
const pres = new pptxgen();
pres.layout = "LAYOUT_WIDE"; // 13.3" x 7.5" — landscape poster format
// ─── COLOR PALETTE ───────────────────────────────────────────────
const C = {
bg: "F8F0F5", // soft blush white background
header: "6B1A3A", // deep burgundy — dominant
accent1: "A63060", // rose
accent2: "D4507A", // coral pink
accent3: "C8547A", // mid-tone pink
teal: "1A6B7A", // teal for contrast sections
teal2: "247B8A",
amber: "B05A00", // amber for warnings/grading
amber2: "D4790A",
green: "1A6B3A", // for benign/favorable
green2: "2E8B57",
dark: "2D1B25", // near-black
mid: "6D4C5E", // medium text
light: "F2D9E8", // light pink for box fills
lightTeal:"D9EFF2",
lightAmb: "FFF0D9",
white: "FFFFFF",
border: "C090A8",
};
// ─── SINGLE POSTER SLIDE ─────────────────────────────────────────
const s = pres.addSlide();
// === BACKGROUND ===
s.addShape(pres.ShapeType.rect, {
x: 0, y: 0, w: 13.3, h: 7.5,
fill: { color: C.bg },
line: { color: C.bg }
});
// === TOP HEADER BAR ===
s.addShape(pres.ShapeType.rect, {
x: 0, y: 0, w: 13.3, h: 0.72,
fill: { color: C.header },
line: { color: C.header }
});
// Title
s.addText("INVASIVE BREAST CANCER — PATHOLOGY CHART", {
x: 0.15, y: 0, w: 10.5, h: 0.72,
fontSize: 20, bold: true, color: C.white,
fontFace: "Calibri", align: "left", valign: "middle", margin: 0
});
// Sub-label
s.addText("Sabiston Surgery · Robbins Pathology · Schwartz Surgery", {
x: 9.2, y: 0, w: 4.0, h: 0.72,
fontSize: 8, color: "F2C0D5", fontFace: "Calibri",
align: "right", valign: "middle", italic: true, margin: 0
});
// === BOTTOM FOOTER ===
s.addShape(pres.ShapeType.rect, {
x: 0, y: 7.3, w: 13.3, h: 0.2,
fill: { color: C.accent1 },
line: { color: C.accent1 }
});
s.addText("Pathology · Oncology · Surgery | Chart Paper: Invasive Breast Cancer | July 2026", {
x: 0, y: 7.32, w: 13.3, h: 0.16,
fontSize: 6.5, color: C.mid, fontFace: "Calibri",
align: "center", valign: "middle", italic: true, margin: 0
});
// ═══════════════════════════════════════════════════════════════════
// HELPER: draw a section box
// ═══════════════════════════════════════════════════════════════════
function sectionBox(x, y, w, h, title, fillColor, headerColor, titleColor) {
// outer border
s.addShape(pres.ShapeType.rect, {
x, y, w, h,
fill: { color: fillColor },
line: { color: headerColor, pt: 1.5 }
});
// title band
s.addShape(pres.ShapeType.rect, {
x, y, w, h: 0.27,
fill: { color: headerColor },
line: { color: headerColor }
});
// title text
s.addText(title, {
x: x + 0.06, y: y, w: w - 0.1, h: 0.27,
fontSize: 8.5, bold: true, color: titleColor || C.white,
fontFace: "Calibri", valign: "middle", margin: 0
});
}
function bodyText(textArr, x, y, w, h, size) {
s.addText(textArr, {
x, y, w, h,
fontSize: size || 7.5,
fontFace: "Calibri",
color: C.dark,
valign: "top",
margin: 4
});
}
// ═══════════════════════════════════════════════════════════════════
// COLUMN LAYOUT (3 columns, 5 rows of boxes)
// Y start = 0.78 (just below header)
// ═══════════════════════════════════════════════════════════════════
const GAP = 0.08;
const col1x = 0.08;
const col2x = 4.53;
const col3x = 9.0;
const colW = 4.2;
const TOP = 0.78;
// ──────────────────────────────────────────────────────────────────
// ROW 1: Definition | Epidemiology | Risk Factors
// ──────────────────────────────────────────────────────────────────
// BOX 1 — Definition & Basics
sectionBox(col1x, TOP, colW, 1.42, "◆ DEFINITION & OVERVIEW", C.header, C.header);
bodyText([
{ text: "Invasive (Infiltrating) Breast Carcinoma", options: { bold: true, breakLine: true, color: C.accent2 } },
{ text: "• Malignant epithelial tumor breaching the basement membrane and invading breast stroma\n", options: { breakLine: true } },
{ text: "• Lacks overall organized architecture; cells infiltrate stroma haphazardly or form monotonous sheets\n", options: { breakLine: true } },
{ text: "• Most common cancer in women (lifetime risk: 1 in 8)\n", options: { breakLine: true } },
{ text: "• 297,790 new US cases estimated in 2023; 2nd leading cause of cancer death in women\n", options: { breakLine: true } },
], col1x + 0.06, TOP + 0.30, colW - 0.12, 1.06, 7.2);
// BOX 2 — Epidemiology
sectionBox(col2x, TOP, colW, 1.42, "◆ EPIDEMIOLOGY & INCIDENCE", C.teal, C.teal);
bodyText([
{ text: "Age: ", options: { bold: true } },
{ text: "Rare <25 yrs; rises steeply after age 30\n", options: { breakLine: true } },
{ text: "Peak incidence: ", options: { bold: true } },
{ text: "50–70 yrs (luminal subtypes)\n", options: { breakLine: true } },
{ text: "Geography: ", options: { bold: true } },
{ text: "Highest in North America, N/W Europe, Australia\n", options: { breakLine: true } },
{ text: "Hormonal factors: ", options: { bold: true } },
{ text: "Postmenopausal HRT, delayed childbearing, fewer pregnancies\n", options: { breakLine: true } },
{ text: "Mammography: ", options: { bold: true } },
{ text: "Average invasive lesion detected ~1 cm; sensitivity ↑ with age\n", options: { breakLine: true } },
], col2x + 0.06, TOP + 0.30, colW - 0.12, 1.06, 7.2);
// BOX 3 — Risk Factors
sectionBox(col3x, TOP, colW, 1.42, "◆ RISK FACTORS", C.amber, C.amber);
bodyText([
{ text: "Genetic: ", options: { bold: true } },
{ text: "BRCA1 (basal-like/TNBC), BRCA2, PALB2, ATM, CHEK2\n", options: { breakLine: true } },
{ text: "Hormonal: ", options: { bold: true } },
{ text: "Early menarche, late menopause, nulliparity, OCP/HRT use\n", options: { breakLine: true } },
{ text: "Reproductive: ", options: { bold: true } },
{ text: "No breastfeeding, late first pregnancy (>30 yrs)\n", options: { breakLine: true } },
{ text: "Other: ", options: { bold: true } },
{ text: "Dense breast tissue, prior breast biopsy (atypical hyperplasia), alcohol, obesity (post-menopause), radiation exposure\n", options: { breakLine: true } },
], col3x + 0.06, TOP + 0.30, colW - 0.12, 1.06, 7.2);
// ──────────────────────────────────────────────────────────────────
// ROW 2: Histological Types (wide box spanning col1+col2) | Grading
// ──────────────────────────────────────────────────────────────────
const R2Y = TOP + 1.42 + GAP;
// BIG BOX — Histological Types (cols 1+2)
const bigW = col2x + colW - col1x;
sectionBox(col1x, R2Y, bigW, 1.95, "◆ HISTOLOGICAL TYPES OF INVASIVE BREAST CANCER", C.light, C.accent1);
// Sub-table manually: 6 types in 2 columns
const typeData = [
["Invasive Ductal Carcinoma (IDC) / No Special Type (NST)", "50–70% of all invasive BC; cohesive mass; discrete on mammogram; haphazard cells in stroma"],
["Invasive Lobular Carcinoma (ILC)", "5–15%; single-file (Indian file) pattern; loss of E-cadherin (CDH1 mutation); clinically occult; escapes mammography"],
["Tubular Carcinoma", "~2–3%; small glands lined by single bland cell layer; low grade (Grade 1); excellent prognosis"],
["Mucinous (Colloid) Carcinoma", "~2–3%; bland cells floating in lakes of mucin; low grade (Grade 1); good prognosis"],
["Medullary Carcinoma", "~5%; large bizarre cells, syncytial sheets, lymphocytic infiltrate, pushing margins; high grade; ER/PR/HER2 negative"],
["Metaplastic Carcinoma", "Rare; high grade; ER/PR/HER2 negative (TNBC); node negative but high metastatic potential; ~50% relapse"],
];
const typeStartY = R2Y + 0.30;
const typeColW1 = 3.65;
const typeColW2 = bigW - typeColW1 - 0.22;
const rowH = 0.255;
// Header row
s.addShape(pres.ShapeType.rect, {
x: col1x + 0.06, y: typeStartY, w: typeColW1, h: 0.24,
fill: { color: C.accent1 }, line: { color: C.accent1 }
});
s.addText("Histological Type", {
x: col1x + 0.08, y: typeStartY, w: typeColW1, h: 0.24,
fontSize: 7.5, bold: true, color: C.white, fontFace: "Calibri", valign: "middle", margin: 0
});
s.addShape(pres.ShapeType.rect, {
x: col1x + 0.06 + typeColW1 + 0.06, y: typeStartY, w: typeColW2, h: 0.24,
fill: { color: C.accent1 }, line: { color: C.accent1 }
});
s.addText("Key Pathological Features", {
x: col1x + 0.14 + typeColW1, y: typeStartY, w: typeColW2, h: 0.24,
fontSize: 7.5, bold: true, color: C.white, fontFace: "Calibri", valign: "middle", margin: 0
});
typeData.forEach((row, i) => {
const rowY = typeStartY + 0.24 + i * rowH;
const bg = i % 2 === 0 ? "FFFFFF" : "FAE8F2";
s.addShape(pres.ShapeType.rect, {
x: col1x + 0.06, y: rowY, w: typeColW1, h: rowH,
fill: { color: bg }, line: { color: C.border, pt: 0.5 }
});
s.addText(row[0], {
x: col1x + 0.08, y: rowY, w: typeColW1 - 0.04, h: rowH,
fontSize: 7, bold: true, color: C.header, fontFace: "Calibri", valign: "middle", margin: 0
});
s.addShape(pres.ShapeType.rect, {
x: col1x + 0.06 + typeColW1 + 0.06, y: rowY, w: typeColW2, h: rowH,
fill: { color: bg }, line: { color: C.border, pt: 0.5 }
});
s.addText(row[1], {
x: col1x + 0.14 + typeColW1, y: rowY, w: typeColW2 - 0.04, h: rowH,
fontSize: 6.8, color: C.dark, fontFace: "Calibri", valign: "middle", margin: 0
});
});
// BOX — Nottingham Grading (col3)
sectionBox(col3x, R2Y, colW, 1.95, "◆ NOTTINGHAM HISTOLOGICAL GRADE (NHG)", C.lightAmb, C.amber);
bodyText([
{ text: "3 components — each scored 1–3:\n", options: { bold: true, breakLine: true, color: C.amber } },
{ text: "1. Tubule/gland formation\n", options: { bold: true, breakLine: true } },
{ text: " >75% → 1 | 10–75% → 2 | <10% → 3\n", options: { breakLine: true } },
{ text: "2. Nuclear pleomorphism\n", options: { bold: true, breakLine: true } },
{ text: " Small uniform → 1 | Moderate → 2 | Marked → 3\n", options: { breakLine: true } },
{ text: "3. Mitotic rate (per 10 HPF)\n", options: { bold: true, breakLine: true } },
{ text: " Low → 1 | Moderate → 2 | High → 3\n\n", options: { breakLine: true } },
{ text: "SCORE 3–5 → Grade 1 (Well differentiated)\n", options: { bold: true, breakLine: true, color: C.green } },
{ text: "SCORE 6–7 → Grade 2 (Moderately differentiated)\n", options: { bold: true, breakLine: true, color: C.amber } },
{ text: "SCORE 8–9 → Grade 3 (Poorly differentiated)", options: { bold: true, color: "C0001A" } },
], col3x + 0.06, R2Y + 0.30, colW - 0.12, 1.59, 7.2);
// ──────────────────────────────────────────────────────────────────
// ROW 3: Molecular Subtypes | Biomarkers | Placental Membrane
// ──────────────────────────────────────────────────────────────────
const R3Y = R2Y + 1.95 + GAP;
// BOX — Molecular Subtypes
sectionBox(col1x, R3Y, colW, 1.75, "◆ MOLECULAR SUBTYPES (Gene Expression Profiling)", C.light, C.accent1);
const molData = [
["Luminal A", "40–60%", "ER+/PR+ high, HER2−, Ki-67 low", "Low", "Best"],
["Luminal B", "20–30%", "ER+/PR+ low, HER2−, Ki-67 high", "Int", "Good"],
["HER2-enriched","10–20%", "ER−/PR−, HER2+, Ki-67 high", "High", "Poor (tx-responsive)"],
["Basal-like (TNBC)","10–20%","ER−/PR−/HER2−, high grade, BRCA1 assoc.","High","Poor"],
];
const mstartY = R3Y + 0.30;
const mHdr = ["Subtype", "Freq", "Biomarker Profile", "Grade", "Prognosis"];
const mW = [1.42, 0.55, 1.58, 0.43, 0.6];
let mX = col1x + 0.06;
mHdr.forEach((h, i) => {
s.addShape(pres.ShapeType.rect, { x: mX, y: mstartY, w: mW[i], h: 0.22, fill: { color: C.accent1 }, line: { color: C.accent1 } });
s.addText(h, { x: mX, y: mstartY, w: mW[i], h: 0.22, fontSize: 7, bold: true, color: C.white, fontFace: "Calibri", valign: "middle", margin: 2 });
mX += mW[i] + 0.02;
});
molData.forEach((row, ri) => {
let rxStart = col1x + 0.06;
const ry = mstartY + 0.22 + ri * 0.3;
const rbg = ri % 2 === 0 ? C.white : "FAE8F2";
const progColors = ["1A6B3A","1A6B3A","B05A00","C0001A"];
row.forEach((cell, ci) => {
const cc = ci === 4 ? progColors[ri] : C.dark;
const cb = ci === 4;
s.addShape(pres.ShapeType.rect, { x: rxStart, y: ry, w: mW[ci], h: 0.295, fill: { color: rbg }, line: { color: C.border, pt: 0.5 } });
s.addText(cell, { x: rxStart, y: ry, w: mW[ci], h: 0.295, fontSize: 6.8, color: cc, bold: cb, fontFace: "Calibri", valign: "middle", margin: 2 });
rxStart += mW[ci] + 0.02;
});
});
// BOX — Biomarkers
sectionBox(col2x, R3Y, colW, 1.75, "◆ BIOMARKERS & IHC TESTING", C.lightTeal, C.teal);
bodyText([
{ text: "ER / PR (Estrogen / Progesterone Receptor)\n", options: { bold: true, breakLine: true, color: C.teal } },
{ text: "• IHC; >1% nuclear staining = positive\n 1–10% = low ER (limited endocrine benefit)\n Guides hormonal therapy (tamoxifen, aromatase inhibitors)\n\n", options: { breakLine: true } },
{ text: "HER2 (Human EGF Receptor 2)\n", options: { bold: true, breakLine: true, color: C.teal } },
{ text: "• erb-B2 gene amplified in ~20% of BCs\n IHC: 0/1+ = negative; 3+ = positive; 2+ = equivocal → ISH\n ISH: <4 copies/cell = neg; ≥6 = positive\n Guides trastuzumab, pertuzumab therapy\n\n", options: { breakLine: true } },
{ text: "Ki-67 (Proliferation Marker)\n", options: { bold: true, breakLine: true, color: C.teal } },
{ text: "• % of positive nuclei; high = aggressive tumor\n Key discriminator: Luminal A (<20%) vs Luminal B (≥20%)", options: {} },
], col2x + 0.06, R3Y + 0.30, colW - 0.12, 1.40, 7.0);
// BOX — Spread & Metastasis
sectionBox(col3x, R3Y, colW, 1.75, "◆ ROUTES OF SPREAD & METASTASIS", C.light, C.accent3);
bodyText([
{ text: "Local spread: ", options: { bold: true } },
{ text: "Direct invasion into breast stroma, skin (peau d'orange — blocked lymphatics), nipple\n\n", options: { breakLine: true } },
{ text: "Lymphatic spread: ", options: { bold: true } },
{ text: "Axillary LN (most common) → infraclavicular, supraclavicular\n Internal mammary nodes (medial tumors)\n Sentinel LN biopsy is standard staging\n\n", options: { breakLine: true } },
{ text: "Haematogenous spread: ", options: { bold: true } },
{ text: "BONES (most common — lytic) > Liver > Lungs > Brain > Adrenals\n ILC: predilection for peritoneum, GI, uterus, ovaries\n\n", options: { breakLine: true } },
{ text: "ILC pattern: ", options: { bold: true } },
{ text: "Single-file cells infiltrate widely; often underestimated clinically", options: {} },
], col3x + 0.06, R3Y + 0.30, colW - 0.12, 1.40, 7.0);
// ──────────────────────────────────────────────────────────────────
// ROW 4: TNM Staging | Pathological Features | Genomic Assays
// ──────────────────────────────────────────────────────────────────
const R4Y = R3Y + 1.75 + GAP;
// BOX — TNM Staging
sectionBox(col1x, R4Y, colW, 1.65, "◆ TNM STAGING (AJCC 8th Edition)", C.lightTeal, C.teal);
const tnmData = [
["T (Tumor)", "Tx — not assessed | T0 — no evidence\nTis — in situ | T1 — ≤2 cm | T2 — 2–5 cm\nT3 — >5 cm | T4 — chest wall/skin involvement"],
["N (Nodes)", "N0 — no regional node mets\nN1 — movable ipsilateral axillary nodes\nN2 — fixed axillary / internal mammary\nN3 — infraclavicular / supraclavicular"],
["M (Metastasis)", "M0 — no distant mets | M1 — distant mets"],
["Stages", "I: T1N0 | II: T2N0 / T1-2N1 | III: T3/N2 / T4\nIV: Any T, Any N, M1"],
];
let tnmY = R4Y + 0.30;
tnmData.forEach((row, i) => {
const rbg = i % 2 === 0 ? C.white : C.lightTeal;
s.addShape(pres.ShapeType.rect, { x: col1x + 0.06, y: tnmY, w: 0.82, h: 0.31, fill: { color: C.teal }, line: { color: C.teal } });
s.addText(row[0], { x: col1x + 0.06, y: tnmY, w: 0.82, h: 0.31, fontSize: 7.2, bold: true, color: C.white, fontFace: "Calibri", valign: "middle", margin: 2 });
s.addShape(pres.ShapeType.rect, { x: col1x + 0.92, y: tnmY, w: colW - 0.98, h: 0.31, fill: { color: rbg }, line: { color: C.border, pt: 0.5 } });
s.addText(row[1], { x: col1x + 0.94, y: tnmY, w: colW - 1.02, h: 0.31, fontSize: 6.8, color: C.dark, fontFace: "Calibri", valign: "middle", margin: 2 });
tnmY += 0.32;
});
// BOX — Gross & Micro Pathology
sectionBox(col2x, R4Y, colW, 1.65, "◆ GROSS & MICROSCOPIC PATHOLOGY", C.light, C.accent1);
bodyText([
{ text: "GROSS:\n", options: { bold: true, breakLine: true, color: C.accent1 } },
{ text: "• IDC: Hard, gritty, irregular stellate mass with spiculated edges; chalky white streaks (elastosis)\n", options: { breakLine: true } },
{ text: "• ILC: Rubbery; diffuse ill-defined thickening (no discrete mass); hard to feel and see on imaging\n", options: { breakLine: true } },
{ text: "• Mucinous: Soft, gelatinous, well-circumscribed bluish mass\n", options: { breakLine: true } },
{ text: "• Medullary: Soft, fleshy, well-circumscribed; haemorrhage ± necrosis\n\n", options: { breakLine: true } },
{ text: "MICROSCOPY:\n", options: { bold: true, breakLine: true, color: C.accent1 } },
{ text: "• IDC: Irregular nests/cords/trabeculae; desmoplastic stroma; mitoses; DCIS often coexists\n", options: { breakLine: true } },
{ text: "• ILC: Single-file infiltration; discohesive cells; targetoid periductal pattern; E-cadherin negative\n", options: { breakLine: true } },
{ text: "• Hofbauer-like inflammatory infiltrate in medullary; calcifications common in ductal\n", options: {} },
], col2x + 0.06, R4Y + 0.30, colW - 0.12, 1.30, 7.0);
// BOX — Genomic Assays
sectionBox(col3x, R4Y, colW, 1.65, "◆ GENOMIC ASSAYS & SPECIAL TESTS", C.lightAmb, C.amber);
bodyText([
{ text: "Oncotype DX (21-gene RS)\n", options: { bold: true, breakLine: true, color: C.amber } },
{ text: "Score 1–100 | Low (<26): endocrine alone | High (≥26): add chemo\nFor ER+/HER2−, 0–3 LN positive\n\n", options: { breakLine: true } },
{ text: "MammaPrint (70-gene)\n", options: { bold: true, breakLine: true, color: C.amber } },
{ text: "Low-risk / High-risk readout | ER+ or ER− tumors | Used for distant recurrence risk\n\n", options: { breakLine: true } },
{ text: "PAM50 / Prosigna\n", options: { bold: true, breakLine: true, color: C.amber } },
{ text: "Intrinsic subtype classification + ROR score\n\n", options: { breakLine: true } },
{ text: "BRCA1/2 germline testing: ", options: { bold: true } },
{ text: "BRCA1 → basal-like TNBC; BRCA2 → luminal\nIndicates prophylactic surgery ± PARP inhibitor eligibility", options: {} },
], col3x + 0.06, R4Y + 0.30, colW - 0.12, 1.30, 7.0);
// ──────────────────────────────────────────────────────────────────
// ROW 5: Placental Membrane / Clinical Features | Prognosis | Therapy Overview
// ──────────────────────────────────────────────────────────────────
const R5Y = R4Y + 1.65 + GAP;
// BOX — Clinical Features & Presentation
sectionBox(col1x, R5Y, colW, 1.42, "◆ CLINICAL FEATURES & PRESENTATION", C.light, C.header);
bodyText([
{ text: "Common presentations:\n", options: { bold: true, breakLine: true, color: C.header } },
{ text: "• Painless, hard, irregular, fixed lump (most common)\n", options: { breakLine: true } },
{ text: "• Skin dimpling / retraction (ligament of Cooper involvement)\n", options: { breakLine: true } },
{ text: "• Peau d'orange (lymphatic obstruction → skin edema)\n", options: { breakLine: true } },
{ text: "• Nipple retraction / bloody discharge (ductal involvement)\n", options: { breakLine: true } },
{ text: "• Axillary lymphadenopathy (late sign)\n", options: { breakLine: true } },
{ text: "• Inflammatory BC: Erythema, warmth, rapid enlargement (T4d — poor prognosis)\n", options: { breakLine: true } },
{ text: "Special types: ", options: { bold: true } },
{ text: "Paget's disease = nipple eczema with underlying ductal carcinoma", options: {} },
], col1x + 0.06, R5Y + 0.30, colW - 0.12, 1.06, 7.0);
// BOX — Prognostic Factors
sectionBox(col2x, R5Y, colW, 1.42, "◆ PROGNOSTIC & PREDICTIVE FACTORS", C.lightTeal, C.teal);
bodyText([
{ text: "Favorable (Good Prognosis):\n", options: { bold: true, breakLine: true, color: C.green } },
{ text: "• Small tumor size (T1) | Node-negative | Low grade (G1)\n ER+/PR+ | Low Ki-67 | Luminal A subtype\n Tubular or mucinous subtype | High TILs in TNBC\n\n", options: { breakLine: true } },
{ text: "Unfavorable (Poor Prognosis):\n", options: { bold: true, breakLine: true, color: "C0001A" } },
{ text: "• Lymph node positivity (most powerful predictor)\n High grade (G3) | Large tumor (T3/T4) | HER2+ or TNBC\n Lymphovascular invasion | High Ki-67\n Triple-negative / Basal-like | BRCA1 mutation", options: {} },
], col2x + 0.06, R5Y + 0.30, colW - 0.12, 1.06, 7.0);
// BOX — Treatment Overview
sectionBox(col3x, R5Y, colW, 1.42, "◆ TREATMENT OVERVIEW (Pathology-guided)", C.lightAmb, C.amber);
bodyText([
{ text: "Surgery: ", options: { bold: true } },
{ text: "Lumpectomy + RT (early) or Mastectomy ± reconstruction\n", options: { breakLine: true } },
{ text: "Sentinel LN biopsy → axillary dissection if positive\n\n", options: { breakLine: true } },
{ text: "Endocrine Rx (ER+): ", options: { bold: true } },
{ text: "Tamoxifen (pre-menopausal); Aromatase inhibitors (post-menopausal)\n\n", options: { breakLine: true } },
{ text: "Anti-HER2 (HER2+): ", options: { bold: true } },
{ text: "Trastuzumab + Pertuzumab + Chemotherapy\n\n", options: { breakLine: true } },
{ text: "TNBC: ", options: { bold: true } },
{ text: "Neoadjuvant chemo (anthracycline + taxane); Olaparib (BRCA+)\n Immunotherapy: Pembrolizumab + chemo (PDL-1+)", options: {} },
], col3x + 0.06, R5Y + 0.30, colW - 0.12, 1.06, 7.0);
// === WRITE FILE ===
pres.writeFile({ fileName: "/home/daytona/workspace/breast-cancer-chart/Invasive_Breast_Cancer_Pathology_Chart.pptx" })
.then(() => console.log("✅ Chart paper created successfully!"))
.catch(e => console.error("❌ Error:", e));
cd /home/daytona/workspace/breast-cancer-chart && node chart.js
ls -lh /home/daytona/workspace/breast-cancer-chart/
Invasive Breast Cancer Pathology Chart
Presentation · PPTX
| Row | Column 1 | Column 2 | Column 3 |
|---|---|---|---|
| 1 | Definition & Overview | Epidemiology & Incidence | Risk Factors |
| 2 | Histological Types Table (6 types spanning 2 cols) | Nottingham Grading (NHG) | |
| 3 | Molecular Subtypes (Luminal A/B, HER2, TNBC) | Biomarkers & IHC (ER/PR/HER2/Ki-67) | Routes of Spread & Metastasis |
| 4 | TNM Staging (AJCC 8th Ed) | Gross & Microscopic Pathology | Genomic Assays (Oncotype DX, MammaPrint) |
| 5 | Clinical Features & Presentation | Prognostic & Predictive Factors | Treatment Overview (pathology-guided) |
Make the chart in pdf presentable format so that i can print out
python3 -c "import reportlab; print(reportlab.Version)"
~/breast-cancer-chart/chart_pdf.py
from reportlab.lib.pagesizes import A2, landscape
from reportlab.lib import colors
from reportlab.lib.units import mm, cm
from reportlab.pdfgen import canvas
from reportlab.lib.colors import HexColor
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
# ── OUTPUT ──────────────────────────────────────────────────────────────
OUT = "/home/daytona/workspace/breast-cancer-chart/Invasive_Breast_Cancer_Pathology.pdf"
# ── PAGE SETUP: A2 Landscape ─────────────────────────────────────────────
W, H = landscape(A2) # 594.0 x 420.0 mm → points: 1683.78 x 1190.55
c = canvas.Canvas(OUT, pagesize=landscape(A2))
c.setTitle("Invasive Breast Cancer — Pathology Chart Paper")
# ── COLOUR PALETTE ────────────────────────────────────────────────────────
BG = HexColor("#F8F0F5")
HEADER = HexColor("#6B1A3A")
ACCENT1 = HexColor("#A63060")
ACCENT2 = HexColor("#C8547A")
TEAL = HexColor("#1A6B7A")
TEAL_LITE = HexColor("#D9EFF2")
AMBER = HexColor("#B05A00")
AMBER_L = HexColor("#FFF0D9")
GREEN = HexColor("#1A6B3A")
RED_DARK = HexColor("#C0001A")
LIGHT_PNK = HexColor("#F2D9E8")
BORDER = HexColor("#C090A8")
DARK = HexColor("#2D1B25")
MID = HexColor("#6D4C5E")
WHITE = colors.white
BLACK = colors.black
ROW_ALT = HexColor("#FAE8F2")
# ── HELPERS ───────────────────────────────────────────────────────────────
def rect(x, y, w, h, fill, stroke=None, lw=0.5):
c.saveState()
c.setFillColor(fill)
if stroke:
c.setStrokeColor(stroke)
c.setLineWidth(lw)
else:
c.setStrokeColor(fill)
c.setLineWidth(0)
c.rect(x, y, w, h, fill=1, stroke=1 if stroke else 0)
c.restoreState()
def text(txt, x, y, size=8, color=DARK, bold=False, align="left", maxw=None):
c.saveState()
c.setFillColor(color)
font = "Helvetica-Bold" if bold else "Helvetica"
c.setFont(font, size)
if align == "center" and maxw:
tw = c.stringWidth(txt, font, size)
x = x + (maxw - tw) / 2
elif align == "right" and maxw:
tw = c.stringWidth(txt, font, size)
x = x + maxw - tw
c.drawString(x, y, txt)
c.restoreState()
def section_header(x, y, w, h, title, hdr_color, txt_color=None):
rect(x, y, w, h, fill=hdr_color)
tc = txt_color or WHITE
c.saveState()
c.setFillColor(tc)
c.setFont("Helvetica-Bold", 8.5)
c.drawString(x + 5, y + h/2 - 4, title)
c.restoreState()
def box(x, y, w, h, fill, border_color, title, title_hdr_color=None):
"""Draw outer box with coloured header strip."""
HEADER_H = 14
# border
rect(x, y, w, h, fill=fill, stroke=border_color, lw=1.0)
# title band (at TOP of box, ReportLab y=bottom so top = y+h-HEADER_H)
rect(x, y + h - HEADER_H, w, HEADER_H,
fill=title_hdr_color or border_color)
# title text
c.saveState()
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 8)
c.drawString(x + 5, y + h - HEADER_H + 3.5, title)
c.restoreState()
return y + h - HEADER_H - 2 # returns inner top-y for content
def wrap_text_block(lines, x, y_top, w, size=7.2, leading=9.5, color=DARK, bold_pairs=None):
"""
lines: list of (text, bold, color_override)
Draws downward from y_top. Returns final y.
"""
cy = y_top
for (txt, bold, col) in lines:
if cy < 10:
break
c.saveState()
c.setFillColor(col or color)
font = "Helvetica-Bold" if bold else "Helvetica"
c.setFont(font, size)
# simple word-wrap
words = txt.split(" ")
line_buf = ""
for word in words:
test = (line_buf + " " + word).strip()
tw = c.stringWidth(test, font, size)
if tw > w - 8:
c.drawString(x + 4, cy, line_buf)
cy -= leading
line_buf = word
else:
line_buf = test
if line_buf:
c.drawString(x + 4, cy, line_buf)
cy -= leading
c.restoreState()
return cy
# ── PAGE BACKGROUND ──────────────────────────────────────────────────────
rect(0, 0, W, H, fill=BG)
# ── TOP HEADER BAR ───────────────────────────────────────────────────────
HDR_H = 28
rect(0, H - HDR_H, W, HDR_H, fill=HEADER)
c.saveState()
c.setFillColor(WHITE)
c.setFont("Helvetica-Bold", 17)
c.drawString(12, H - HDR_H + 8, "INVASIVE BREAST CANCER — PATHOLOGY CHART PAPER")
c.setFont("Helvetica", 7)
c.setFillColor(HexColor("#F2C0D5"))
c.drawRightString(W - 10, H - HDR_H + 9,
"Sources: Sabiston Surgery · Robbins & Cotran Pathology · Schwartz Surgery")
c.restoreState()
# ── BOTTOM FOOTER ────────────────────────────────────────────────────────
FOOT_H = 10
rect(0, 0, W, FOOT_H, fill=ACCENT1)
c.saveState()
c.setFillColor(WHITE)
c.setFont("Helvetica", 6)
c.drawCentredString(W / 2, 2,
"Pathology · Oncology · Surgery | Invasive Breast Cancer Chart Paper | July 2026 | For Educational Use")
c.restoreState()
# ── LAYOUT CONSTANTS ────────────────────────────────────────────────────
PAD = 5 # gap between boxes (pts)
MARGIN = 8 # page margin
BODY_Y_TOP = H - HDR_H - MARGIN
BODY_H = H - HDR_H - FOOT_H - MARGIN * 2
BODY_W = W - MARGIN * 2
# 3 equal columns
COL_W = (BODY_W - PAD * 2) / 3
COL1X = MARGIN
COL2X = MARGIN + COL_W + PAD
COL3X = MARGIN + (COL_W + PAD) * 2
# Row heights (must sum to BODY_H - 4*PAD)
total_available = BODY_H - 4 * PAD
R1H = total_available * 0.155
R2H = total_available * 0.215
R3H = total_available * 0.205
R4H = total_available * 0.210
R5H = total_available * 0.215
R5Y = FOOT_H + MARGIN
R4Y = R5Y + R5H + PAD
R3Y = R4Y + R4H + PAD
R2Y = R3Y + R3H + PAD
R1Y = R2Y + R2H + PAD
# ═══════════════════════════════════════════════════════════════════════════
# ROW 1 — Definition | Epidemiology | Risk Factors
# ═══════════════════════════════════════════════════════════════════════════
# --- Box 1: Definition ---
inner = box(COL1X, R1Y, COL_W, R1H, LIGHT_PNK, HEADER,
"◆ DEFINITION & OVERVIEW")
wrap_text_block([
("Invasive (Infiltrating) Breast Carcinoma", True, ACCENT1),
("Malignant epithelial tumor breaching the basement", False, None),
("membrane & invading breast stroma.", False, None),
("• Lacks organized architecture; cells infiltrate haphazardly", False, None),
("• Most common female cancer — lifetime risk 1 in 8", False, None),
("• 297,790 new US cases (2023); 2nd cancer death cause", False, None),
("• Divided broadly into ductal & lobular types", False, None),
], COL1X, inner, COL_W, size=7.5, leading=10)
# --- Box 2: Epidemiology ---
inner = box(COL2X, R1Y, COL_W, R1H, TEAL_LITE, TEAL,
"◆ EPIDEMIOLOGY & INCIDENCE")
wrap_text_block([
("Age: Rare <25 yrs; rises steeply after age 30", False, None),
("Peak incidence: 50–70 yrs (luminal/ER+ subtypes)", False, None),
("Geography: Highest in North America, N/W Europe, Australia", False, None),
("Hormonal factors: Postmenopausal HRT, delayed childbearing", False, None),
("Mammography detects avg invasive lesion at ~1 cm", False, None),
("Sensitivity & specificity of mammography ↑ with age", False, None),
], COL2X, inner, COL_W, size=7.5, leading=10)
# --- Box 3: Risk Factors ---
inner = box(COL3X, R1Y, COL_W, R1H, AMBER_L, AMBER,
"◆ RISK FACTORS")
wrap_text_block([
("Genetic: BRCA1 (→ TNBC/basal-like), BRCA2, PALB2, ATM, CHEK2", False, None),
("Hormonal: Early menarche, late menopause, OCP/HRT use", False, None),
("Reproductive: Nulliparity, no breastfeeding, late 1st pregnancy", False, None),
("Other: Dense breasts, atypical hyperplasia on biopsy, alcohol,", False, None),
("obesity (post-menopause), prior chest radiation", False, None),
], COL3X, inner, COL_W, size=7.5, leading=10)
# ═══════════════════════════════════════════════════════════════════════════
# ROW 2 — Histological Types (col1+col2 merged) | Nottingham Grading
# ═══════════════════════════════════════════════════════════════════════════
HIST_W = COL_W * 2 + PAD
inner = box(COL1X, R2Y, HIST_W, R2H, LIGHT_PNK, ACCENT1,
"◆ HISTOLOGICAL TYPES OF INVASIVE BREAST CANCER")
# Table inside
HDR_ROW_H = 13
DATA_ROW_H = (R2H - 14 - HDR_ROW_H - 8) / 6
TABLE_X = COL1X + 4
TABLE_Y = inner - 2
COL_A = 175 # type name column width
COL_B = HIST_W - COL_A - 12 # description column width
# Header row
rect(TABLE_X, TABLE_Y - HDR_ROW_H, COL_A, HDR_ROW_H, fill=ACCENT1)
rect(TABLE_X + COL_A + 2, TABLE_Y - HDR_ROW_H, COL_B, HDR_ROW_H, fill=ACCENT1)
c.saveState()
c.setFillColor(WHITE); c.setFont("Helvetica-Bold", 7.5)
c.drawString(TABLE_X + 3, TABLE_Y - HDR_ROW_H + 3.5, "Histological Type")
c.drawString(TABLE_X + COL_A + 5, TABLE_Y - HDR_ROW_H + 3.5, "Key Pathological Features")
c.restoreState()
type_data = [
("Invasive Ductal Carcinoma (IDC / NST)",
"50–70% of invasive BC; cohesive mass; discrete stellate on mammogram; haphazard nests/cords in desmoplastic stroma; DCIS often coexists"),
("Invasive Lobular Carcinoma (ILC)",
"5–15%; single-file (Indian file) & targetoid pattern; discohesive cells; CDH1 mutation → E-cadherin loss; clinically & mammographically occult"),
("Tubular Carcinoma",
"~2–3%; small glands lined by single layer of bland cells; low grade (Grade 1); excellent prognosis; angular tubules in fibrous stroma"),
("Mucinous (Colloid) Carcinoma",
"~2–3%; bland tumor cells floating in lakes of mucin; low grade (Grade 1); soft gelatinous mass; good prognosis"),
("Medullary Carcinoma",
"~5%; large bizarre syncytial cells; brisk lymphocytic infiltrate; pushing margins; no DCIS; high grade; uniformly ER/PR/HER2 negative"),
("Metaplastic Carcinoma",
"Rare; high grade; ER/PR/HER2 negative (TNBC); mostly node-negative but high metastatic potential; ~50% local/distant relapse"),
]
for i, (name, desc) in enumerate(type_data):
ry = TABLE_Y - HDR_ROW_H - (i + 1) * DATA_ROW_H
bg = WHITE if i % 2 == 0 else ROW_ALT
rect(TABLE_X, ry, COL_A, DATA_ROW_H, fill=bg, stroke=BORDER, lw=0.4)
rect(TABLE_X + COL_A + 2, ry, COL_B, DATA_ROW_H, fill=bg, stroke=BORDER, lw=0.4)
c.saveState()
c.setFont("Helvetica-Bold", 6.8); c.setFillColor(HEADER)
c.drawString(TABLE_X + 3, ry + DATA_ROW_H / 2 - 3.5, name)
c.setFont("Helvetica", 6.6); c.setFillColor(DARK)
# simple truncate for now
c.drawString(TABLE_X + COL_A + 5, ry + DATA_ROW_H / 2 - 3.5, desc[:105])
c.restoreState()
# --- Nottingham Grading ---
inner = box(COL3X, R2Y, COL_W, R2H, AMBER_L, AMBER,
"◆ NOTTINGHAM HISTOLOGICAL GRADE (NHG)")
GRADE_lines = [
("3 criteria — each scored 1 to 3 points:", True, AMBER),
("", False, None),
("1. Tubule / Gland Formation", True, DARK),
(" >75% of tumour area = 1 point", False, None),
(" 10–75% = 2 points", False, None),
(" <10% = 3 points", False, None),
("", False, None),
("2. Nuclear Pleomorphism", True, DARK),
(" Small, uniform nuclei = 1", False, None),
(" Moderate variation = 2", False, None),
(" Marked variation = 3", False, None),
("", False, None),
("3. Mitotic Rate (per 10 HPF)", True, DARK),
(" Low = 1 Moderate = 2 High = 3", False, None),
("", False, None),
("TOTAL SCORE 3–5 = Grade 1 (Well differentiated)", True, GREEN),
("TOTAL SCORE 6–7 = Grade 2 (Moderately differentiated)", True, AMBER),
("TOTAL SCORE 8–9 = Grade 3 (Poorly differentiated)", True, RED_DARK),
]
wrap_text_block(GRADE_lines, COL3X, inner, COL_W, size=7.5, leading=9.8)
# ═══════════════════════════════════════════════════════════════════════════
# ROW 3 — Molecular Subtypes | Biomarkers | Spread & Metastasis
# ═══════════════════════════════════════════════════════════════════════════
# --- Molecular Subtypes ---
inner = box(COL1X, R3Y, COL_W, R3H, LIGHT_PNK, ACCENT1,
"◆ MOLECULAR SUBTYPES (Gene Expression Profiling)")
mol_data = [
("Luminal A", "40–60%", "ER+/PR+ high, HER2−, Ki-67 low", "Grade 1–2", "BEST"),
("Luminal B", "20–30%", "ER+/PR+ low–mod, HER2−/+, Ki-67 high", "Grade 2–3", "GOOD"),
("HER2-Enriched", "10–20%", "HER2+, ER−/PR−, Ki-67 high", "Grade 3", "POOR*"),
("Basal-like (TNBC)", "10–20%", "ER−/PR−/HER2−, high grade, BRCA1 assoc.", "Grade 3", "POOR"),
]
mol_headers = ["Subtype", "Freq", "Biomarker Profile", "Grade", "Prognosis"]
mW = [115, 40, 165, 58, 58]
mX_start = COL1X + 4
mHDR_H = 13
mROW_H = (R3H - 14 - mHDR_H - 10) / 4
my = inner - 2
mx = mX_start
for i, (hdr, cw) in enumerate(zip(mol_headers, mW)):
rect(mx, my - mHDR_H, cw, mHDR_H, fill=ACCENT1)
c.saveState(); c.setFillColor(WHITE); c.setFont("Helvetica-Bold", 7)
c.drawString(mx + 2, my - mHDR_H + 3.5, hdr); c.restoreState()
mx += cw + 2
prog_colors = [GREEN, GREEN, AMBER, RED_DARK]
for ri, row in enumerate(mol_data):
ry = inner - 2 - mHDR_H - (ri + 1) * mROW_H
rbg = WHITE if ri % 2 == 0 else ROW_ALT
mx = mX_start
for ci, (cell, cw) in enumerate(zip(row, mW)):
rect(mx, ry, cw, mROW_H, fill=rbg, stroke=BORDER, lw=0.4)
cc = prog_colors[ri] if ci == 4 else (HEADER if ci == 0 else DARK)
bold = ci in (0, 4)
c.saveState()
c.setFillColor(cc)
c.setFont("Helvetica-Bold" if bold else "Helvetica", 6.8)
c.drawString(mx + 3, ry + mROW_H / 2 - 3.5, cell)
c.restoreState()
mx += cw + 2
c.saveState(); c.setFillColor(MID); c.setFont("Helvetica", 6)
c.drawString(COL1X + 4, R3Y + 4, "* HER2+ now tx-responsive with trastuzumab/pertuzumab")
c.restoreState()
# --- Biomarkers ---
inner = box(COL2X, R3Y, COL_W, R3H, TEAL_LITE, TEAL,
"◆ BIOMARKERS & IHC TESTING")
wrap_text_block([
("ER / PR (Estrogen / Progesterone Receptors)", True, TEAL),
("• IHC; >1% nuclear staining = positive", False, None),
("• 1–10% = low ER (limited endocrine benefit)", False, None),
("• Guides tamoxifen (pre-menopausal) &", False, None),
(" aromatase inhibitors (post-menopausal)", False, None),
("", False, None),
("HER2 (Human Epidermal Growth Factor Receptor 2)", True, TEAL),
("• erb-B2 amplified in ~20% of breast cancers", False, None),
("• IHC: 0/1+ neg | 2+ equivocal → ISH | 3+ positive", False, None),
("• ISH: <4 copies neg | ≥6 copies positive", False, None),
("• Guides trastuzumab + pertuzumab therapy", False, None),
("", False, None),
("Ki-67 (Proliferation Marker)", True, TEAL),
("• % of Ki-67+ nuclei; ↑Ki-67 = aggressive", False, None),
("• Discriminates Luminal A (<20%) vs B (≥20%)", False, None),
], COL2X, inner, COL_W, size=7.3, leading=9.5)
# --- Spread ---
inner = box(COL3X, R3Y, COL_W, R3H, LIGHT_PNK, ACCENT2,
"◆ ROUTES OF SPREAD & METASTASIS")
wrap_text_block([
("Local Spread", True, ACCENT1),
("• Direct invasion into stroma, skin, nipple", False, None),
("• Peau d'orange = blocked dermal lymphatics", False, None),
("• Skin dimpling = Cooper ligament involvement", False, None),
("", False, None),
("Lymphatic Spread (most clinically important)", True, ACCENT1),
("• Axillary LN (most common) — 3 levels", False, None),
("• Internal mammary (medial quadrant tumors)", False, None),
("• Infra/Supraclavicular LN (late / advanced)", False, None),
("• Sentinel LN biopsy is standard staging tool", False, None),
("", False, None),
("Haematogenous Spread", True, ACCENT1),
("• BONE (lytic, most common) > LIVER > LUNG > BRAIN", False, None),
("• ILC special: peritoneum, GI tract, uterus, ovaries", False, None),
], COL3X, inner, COL_W, size=7.3, leading=9.5)
# ═══════════════════════════════════════════════════════════════════════════
# ROW 4 — TNM Staging | Gross & Micro Pathology | Genomic Assays
# ═══════════════════════════════════════════════════════════════════════════
# --- TNM ---
inner = box(COL1X, R4Y, COL_W, R4H, TEAL_LITE, TEAL,
"◆ TNM STAGING — AJCC 8th EDITION")
tnm_data = [
("T (Tumour)",
"Tx=not assessed | T0=no evidence | Tis=in situ\nT1=≤2cm | T2=2–5cm | T3=>5cm | T4=chest wall/skin"),
("N (Nodes)",
"N0=no nodal mets | N1=movable ipsilateral axillary\nN2=fixed axillary / internal mammary | N3=infra/supraclavicular"),
("M (Mets)",
"M0 = no distant metastasis\nM1 = distant metastasis present"),
("STAGE I", "T1 N0 M0 — Excellent prognosis"),
("STAGE II", "T2N0 / T1-2N1 — Good prognosis"),
("STAGE III","T3/N2 or T4 any N — Locally advanced"),
("STAGE IV", "Any T, Any N, M1 — Distant metastatic disease"),
]
tnm_hdr_w = 90
tnm_val_w = COL_W - tnm_hdr_w - 14
tnm_row_h = (R4H - 14 - 6) / len(tnm_data)
ty = inner - 2
stage_colors = [TEAL, TEAL, TEAL, GREEN, AMBER, HexColor("#C05000"), RED_DARK]
for i, (label, val) in enumerate(tnm_data):
ry = ty - (i + 1) * tnm_row_h
rbg = TEAL_LITE if i % 2 == 0 else WHITE
rect(COL1X + 4, ry, tnm_hdr_w, tnm_row_h, fill=stage_colors[i])
rect(COL1X + 4 + tnm_hdr_w + 2, ry, tnm_val_w, tnm_row_h,
fill=rbg, stroke=BORDER, lw=0.4)
c.saveState()
c.setFillColor(WHITE); c.setFont("Helvetica-Bold", 7.2)
c.drawString(COL1X + 7, ry + tnm_row_h / 2 - 3.5, label)
c.setFillColor(DARK); c.setFont("Helvetica", 6.8)
c.drawString(COL1X + 4 + tnm_hdr_w + 5, ry + tnm_row_h / 2 - 3.5,
val.replace("\n", " "))
c.restoreState()
# --- Gross & Micro ---
inner = box(COL2X, R4Y, COL_W, R4H, LIGHT_PNK, ACCENT1,
"◆ GROSS & MICROSCOPIC PATHOLOGY")
wrap_text_block([
("GROSS APPEARANCE:", True, ACCENT1),
("IDC: Hard, gritty, irregular stellate mass; spiculated", False, None),
(" edges; chalky white streaks (elastosis); gritty cut surface", False, None),
("ILC: Rubbery diffuse thickening; no discrete mass;", False, None),
(" hard to detect clinically & mammographically", False, None),
("Mucinous: Soft, gelatinous, bluish, well-circumscribed", False, None),
("Medullary: Soft, fleshy, pushing borders ± haemorrhage", False, None),
("", False, None),
("MICROSCOPY:", True, ACCENT1),
("IDC: Irregular nests/cords/trabeculae in desmoplastic", False, None),
(" stroma; mitoses; nuclear pleomorphism; DCIS coexists", False, None),
("ILC: Single-file infiltration; targetoid periductal pattern;", False, None),
(" E-cadherin loss (IHC negative)", False, None),
("Medullary: Syncytial sheets; brisk lymphocytic infiltrate", False, None),
("Calcifications common in IDC; Hofbauer cells in villi", False, None),
], COL2X, inner, COL_W, size=7.2, leading=9.3)
# --- Genomic Assays ---
inner = box(COL3X, R4Y, COL_W, R4H, AMBER_L, AMBER,
"◆ GENOMIC ASSAYS & SPECIAL TESTS")
wrap_text_block([
("Oncotype DX — 21-Gene Recurrence Score (RS)", True, AMBER),
("Score 1–100 via RT-PCR on paraffin-embedded tissue", False, None),
("RS <26: endocrine therapy alone (low recurrence risk)", False, None),
("RS ≥26: add chemotherapy to endocrine therapy", False, None),
("Best for: ER+/HER2−, 0–3 positive LN (early stage)", False, None),
("", False, None),
("MammaPrint — 70-Gene Assay", True, AMBER),
("Simple Low-risk / High-risk readout", False, None),
("Validated for ER+ and ER− tumours", False, None),
("", False, None),
("Other Assays:", True, AMBER),
("PAM50/Prosigna — intrinsic subtype + ROR score", False, None),
("EndoPredict — ER+ HER2− breast cancer prognosis", False, None),
("", False, None),
("BRCA1/2 Germline Testing:", True, AMBER),
("BRCA1 → Basal-like TNBC; BRCA2 → Luminal type", False, None),
("Eligibility: PARP inhibitors (olaparib, talazoparib)", False, None),
], COL3X, inner, COL_W, size=7.2, leading=9.3)
# ═══════════════════════════════════════════════════════════════════════════
# ROW 5 — Clinical Features | Prognostic Factors | Treatment
# ═══════════════════════════════════════════════════════════════════════════
# --- Clinical Features ---
inner = box(COL1X, R5Y, COL_W, R5H, LIGHT_PNK, HEADER,
"◆ CLINICAL FEATURES & PRESENTATION")
wrap_text_block([
("Common Presentations:", True, HEADER),
("• Painless, hard, irregular, fixed lump (most common)", False, None),
("• Skin dimpling / retraction (Cooper ligament tethering)", False, None),
("• Peau d'orange (dermal lymphatic obstruction)", False, None),
("• Nipple retraction or bloody discharge", False, None),
("• Axillary lymphadenopathy (advanced disease)", False, None),
("", False, None),
("Special Presentations:", True, HEADER),
("• Inflammatory BC: Erythema, warmth, rapid enlargement", False, None),
(" (T4d — dermal lymphatic invasion; worst prognosis)", False, None),
("• Paget's disease: Nipple eczema + underlying DCIS/IDC", False, None),
("• ILC: Diffuse thickening, often bilateral, late presentation", False, None),
], COL1X, inner, COL_W, size=7.3, leading=9.5)
# --- Prognostic Factors ---
inner = box(COL2X, R5Y, COL_W, R5H, TEAL_LITE, TEAL,
"◆ PROGNOSTIC & PREDICTIVE FACTORS")
wrap_text_block([
("FAVOURABLE (Better Prognosis):", True, GREEN),
("• Small size (T1 ≤2cm)", False, None),
("• Node-negative (N0) — single strongest predictor", False, None),
("• Low grade (Grade 1)", False, None),
("• ER+/PR+ strongly positive | Low Ki-67", False, None),
("• Luminal A subtype", False, None),
("• Tubular or mucinous histological type", False, None),
("• High tumour-infiltrating lymphocytes (TNBC)", False, None),
("", False, None),
("UNFAVOURABLE (Worse Prognosis):", True, RED_DARK),
("• Lymph node positivity — strongest adverse predictor", False, None),
("• High grade (Grade 3) | Large tumour (T3/T4)", False, None),
("• HER2+ or Triple Negative (TNBC) subtype", False, None),
("• Lymphovascular invasion | High Ki-67 (≥30%)", False, None),
("• BRCA1 mutation | Inflammatory carcinoma (T4d)", False, None),
], COL2X, inner, COL_W, size=7.2, leading=9.3)
# --- Treatment ---
inner = box(COL3X, R5Y, COL_W, R5H, AMBER_L, AMBER,
"◆ TREATMENT OVERVIEW (Pathology-Guided)")
wrap_text_block([
("SURGERY:", True, AMBER),
("• Lumpectomy + RT (breast-conserving, early stage)", False, None),
("• Mastectomy ± reconstruction (large / multifocal)", False, None),
("• Sentinel LN biopsy → axillary dissection if positive", False, None),
("", False, None),
("ENDOCRINE (ER+/PR+):", True, AMBER),
("• Pre-menopausal: Tamoxifen (5–10 yrs)", False, None),
("• Post-menopausal: Aromatase inhibitors", False, None),
("", False, None),
("ANTI-HER2 (HER2+):", True, AMBER),
("• Trastuzumab + Pertuzumab + Taxane chemotherapy", False, None),
("• T-DM1 / T-DXd for residual/metastatic disease", False, None),
("", False, None),
("TNBC (Triple Negative):", True, AMBER),
("• Neoadjuvant: Anthracycline + Taxane ± Carboplatin", False, None),
("• BRCA+: Olaparib / Talazoparib (PARP inhibitors)", False, None),
("• PDL-1+: Pembrolizumab + Chemotherapy", False, None),
], COL3X, inner, COL_W, size=7.2, leading=9.3)
# ── VERTICAL DIVIDERS (decorative) ──────────────────────────────────────
c.saveState()
c.setStrokeColor(BORDER)
c.setLineWidth(0.5)
c.setDash(3, 3)
c.line(COL2X - PAD/2, H - HDR_H - MARGIN, COL2X - PAD/2, FOOT_H + MARGIN)
c.line(COL3X - PAD/2, H - HDR_H - MARGIN, COL3X - PAD/2, FOOT_H + MARGIN)
c.restoreState()
# ── SAVE ────────────────────────────────────────────────────────────────
c.save()
print(f"✅ PDF saved: {OUT}")
cd /home/daytona/workspace/breast-cancer-chart && python3 chart_pdf.py
ls -lh /home/daytona/workspace/breast-cancer-chart/
Invasive Breast Cancer Pathology
PDF Document · PDF
| Color | Sections |
|---|---|
| 🟥 Deep Burgundy/Rose | Definition, Clinical Features, Histological Types, Gross/Micro |
| 🟦 Teal | Epidemiology, Biomarkers (ER/PR/HER2), TNM Staging, Prognostic Factors |
| 🟧 Amber | Risk Factors, Nottingham Grading, Genomic Assays, Treatment |
Include pictures as well
node /home/daytona/skills/shared/scripts/fetch_images.js \ "https://cdn.orris.…
~/breast-cancer-chart/chart_pdf_images.py
"""
Invasive Breast Cancer — Pathology Chart Paper (with images)
A2 Landscape, print-ready PDF
"""
import subprocess, json, io, base64, os
from reportlab.lib.pagesizes import landscape, A2
from reportlab.lib.colors import HexColor, white, black
from reportlab.pdfgen import canvas
from reportlab.lib.utils import ImageReader
from PIL import Image as PILImage
# ── FETCH ALL IMAGES VIA NODE HELPER ─────────────────────────────────────
URLS = [
"https://cdn.orris.care/cdss_images/a7976dc8796d45630b8035ab7b9d9a51d19ab1a1da0a00fe3a1a2be2d02c2b2c.png", # 0: IDC histo
"https://cdn.orris.care/cdss_images/aaefa7fa0dcea9ebc4141cc11c208790e0f6056922eb4965653c88eb8ecb41ae.png", # 1: ILC single-file
"https://cdn.orris.care/cdss_images/537e98f39fad9dcd00a3efb6981773b84fb05b1cd9ee68523227206e253312b9.png", # 2: tubular
"https://cdn.orris.care/cdss_images/0c3a6313c64d0e2d44fc2c95fdc046eb79e58c3ecace88848ebfa9457ea7e556.png", # 3: mucinous
"https://cdn.orris.care/cdss_images/7ec93232f952affe9a51828a80bbacb8bad2981e4717078c0202d8fbe12ddd05.png", # 4: medullary
"https://cdn.orris.care/cdss_images/90f51bd3b37f5512daef0a02982be1e27828e6224ba01e69c220258689d5655f.png", # 5: IDC scirrhous x100/200
"https://cdn.orris.care/cdss_images/8be48acee1c45d0b5f32ee39476dfdb8cdbf608456eb387d806a63765f460454.png", # 6: ILC Indian file
"https://cdn.orris.care/cdss_images/c3182e46ed9f6473eb40224eb6404462d78bbde2b74b6941b7d44134662af03a.png", # 7: mammogram spiculated mass
]
print("Fetching images …")
result = subprocess.run(
["node", "/home/daytona/skills/shared/scripts/fetch_images.js"] + URLS,
capture_output=True, text=True, timeout=90
)
img_data = json.loads(result.stdout)
def b64_to_reader(entry):
"""Convert base64 data URI → PIL ImageReader for ReportLab."""
raw = entry["base64"].split(",", 1)[1]
buf = io.BytesIO(base64.b64decode(raw))
img = PILImage.open(buf).convert("RGB")
out = io.BytesIO()
img.save(out, format="PNG")
out.seek(0)
return ImageReader(out)
readers = [b64_to_reader(d) for d in img_data]
print("Images ready.")
# ── PAGE SETUP ────────────────────────────────────────────────────────────
OUT = "/home/daytona/workspace/breast-cancer-chart/Invasive_Breast_Cancer_With_Images.pdf"
W, H = landscape(A2) # 1683.78 × 1190.55 pts
c = canvas.Canvas(OUT, pagesize=landscape(A2))
c.setTitle("Invasive Breast Cancer — Pathology Chart Paper")
# ── COLOUR PALETTE ────────────────────────────────────────────────────────
BG = HexColor("#F8F0F5")
HEADER = HexColor("#6B1A3A")
ACCENT1 = HexColor("#A63060")
ACCENT2 = HexColor("#C8547A")
TEAL = HexColor("#1A6B7A")
TEAL_LITE = HexColor("#D9EFF2")
AMBER = HexColor("#B05A00")
AMBER_L = HexColor("#FFF0D9")
GREEN = HexColor("#1A6B3A")
RED_DARK = HexColor("#C0001A")
LIGHT_PNK = HexColor("#F2D9E8")
BORDER = HexColor("#C090A8")
DARK = HexColor("#2D1B25")
MID = HexColor("#6D4C5E")
ROW_ALT = HexColor("#FAE8F2")
IMG_FRAME = HexColor("#D4A0BE")
IMG_BG = HexColor("#FDF5FA")
# ── DRAWING HELPERS ───────────────────────────────────────────────────────
def rect(x, y, w, h, fill, stroke=None, lw=0.5):
c.saveState()
c.setFillColor(fill)
if stroke:
c.setStrokeColor(stroke); c.setLineWidth(lw)
else:
c.setStrokeColor(fill); c.setLineWidth(0)
c.rect(x, y, w, h, fill=1, stroke=1 if stroke else 0)
c.restoreState()
def draw_image(reader, x, y, w, h, caption="", cap_color=None):
"""Draw image with thin border and optional caption below."""
rect(x, y, w, h, fill=IMG_BG, stroke=IMG_FRAME, lw=1.2)
# keep aspect
try:
iw, ih = reader.getSize()
scale = min(w / iw, h / ih) * 0.97
nw, nh = iw * scale, ih * scale
ox = x + (w - nw) / 2
oy = y + (h - nh) / 2
c.drawImage(reader, ox, oy, nw, nh, mask="auto")
except Exception:
c.drawImage(reader, x, y, w, h, preserveAspectRatio=True, mask="auto")
if caption:
c.saveState()
c.setFont("Helvetica", 5.5)
c.setFillColor(cap_color or MID)
c.drawCentredString(x + w / 2, y - 7, caption)
c.restoreState()
def box(x, y, w, h, fill, border_color, title, title_hdr_color=None):
HDR_H = 14
rect(x, y, w, h, fill=fill, stroke=border_color, lw=1.0)
rect(x, y + h - HDR_H, w, HDR_H, fill=title_hdr_color or border_color)
c.saveState()
c.setFillColor(white); c.setFont("Helvetica-Bold", 8)
c.drawString(x + 5, y + h - HDR_H + 3.5, title)
c.restoreState()
return y + h - HDR_H - 2 # inner top-y
def wrap_lines(lines, x, y_top, w, size=7.2, leading=9.5):
"""lines: list of (text, bold, color_override) — draws downward."""
cy = y_top
for (txt, bold, col) in lines:
if cy < 8: break
c.saveState()
c.setFillColor(col or DARK)
font = "Helvetica-Bold" if bold else "Helvetica"
c.setFont(font, size)
words = txt.split(" ")
buf = ""
for w_word in words:
test = (buf + " " + w_word).strip()
if c.stringWidth(test, font, size) > w - 8:
if buf:
c.drawString(x + 4, cy, buf)
cy -= leading
buf = w_word
else:
buf = test
if buf:
c.drawString(x + 4, cy, buf)
cy -= leading
c.restoreState()
return cy
# ── PAGE BACKGROUND ───────────────────────────────────────────────────────
rect(0, 0, W, H, fill=BG)
# ── HEADER BAR ───────────────────────────────────────────────────────────
HDR_H = 30
rect(0, H - HDR_H, W, HDR_H, fill=HEADER)
c.saveState()
c.setFillColor(white); c.setFont("Helvetica-Bold", 18)
c.drawString(12, H - HDR_H + 9, "INVASIVE BREAST CANCER — PATHOLOGY CHART PAPER")
c.setFont("Helvetica", 7); c.setFillColor(HexColor("#F2C0D5"))
c.drawRightString(W - 10, H - HDR_H + 10,
"Sabiston Surgery · Robbins & Cotran Pathology · Schwartz Surgery")
c.restoreState()
# ── FOOTER ────────────────────────────────────────────────────────────────
FOOT_H = 10
rect(0, 0, W, FOOT_H, fill=ACCENT1)
c.saveState(); c.setFillColor(white); c.setFont("Helvetica", 6)
c.drawCentredString(W / 2, 2,
"Pathology · Oncology · Surgery | Invasive Breast Cancer Chart Paper | July 2026 | For Educational Use")
c.restoreState()
# ── LAYOUT ────────────────────────────────────────────────────────────────
PAD = 6
MARGIN = 8
BODY_TOP = H - HDR_H - MARGIN
BODY_BOT = FOOT_H + MARGIN
BODY_H = BODY_TOP - BODY_BOT
BODY_W = W - MARGIN * 2
COL_W = (BODY_W - PAD * 2) / 3
COL1X = MARGIN
COL2X = MARGIN + COL_W + PAD
COL3X = MARGIN + (COL_W + PAD) * 2
# Row heights — 6 rows now (added image strip)
total = BODY_H - 5 * PAD
R1H = total * 0.120 # Definition / Epi / Risk
R2H = total * 0.163 # Histological types + Grading
R3H = total * 0.152 # Molecular / Biomarkers / Spread
IMG_H = total * 0.148 # IMAGE STRIP
R4H = total * 0.155 # TNM / Gross+Micro / Genomics
R5H = total * 0.162 # Clinical / Prognosis / Treatment
# stack bottom up
R5Y = BODY_BOT
R4Y = R5Y + R5H + PAD
IMG_Y = R4Y + R4H + PAD
R3Y = IMG_Y + IMG_H + PAD
R2Y = R3Y + R3H + PAD
R1Y = R2Y + R2H + PAD
# ══════════════════════════════════════════════════════════════════════════
# ROW 1 — Definition | Epidemiology | Risk Factors
# ══════════════════════════════════════════════════════════════════════════
inner = box(COL1X, R1Y, COL_W, R1H, LIGHT_PNK, HEADER, "◆ DEFINITION & OVERVIEW")
wrap_lines([
("Invasive (Infiltrating) Breast Carcinoma", True, ACCENT1),
("Malignant epithelial tumour breaching the basement", False, None),
("membrane & invading breast stroma.", False, None),
("• Lacks organized architecture; infiltrates haphazardly", False, None),
("• Most common female cancer — lifetime risk 1 in 8", False, None),
("• ~298,000 new US cases (2023); 2nd cancer death cause", False, None),
("• Broadly: Ductal (IDC) vs Lobular (ILC) subtypes", False, None),
], COL1X, inner, COL_W, size=7.5, leading=10)
inner = box(COL2X, R1Y, COL_W, R1H, TEAL_LITE, TEAL, "◆ EPIDEMIOLOGY & INCIDENCE")
wrap_lines([
("Age: Rare <25 yrs; incidence rises steeply after age 30", False, None),
("Peak: 50–70 yrs (luminal/ER+ subtypes)", False, None),
("Geography: Highest in N. America, N/W Europe, Australia", False, None),
("Hormonal factors: Postmenopausal HRT, delayed childbearing", False, None),
("Mammography detects avg invasive lesion at ~1 cm", False, None),
], COL2X, inner, COL_W, size=7.5, leading=10)
inner = box(COL3X, R1Y, COL_W, R1H, AMBER_L, AMBER, "◆ RISK FACTORS")
wrap_lines([
("Genetic: BRCA1 (→TNBC/basal-like), BRCA2, PALB2, ATM", False, None),
("Hormonal: Early menarche, late menopause, OCP/HRT", False, None),
("Reproductive: Nulliparity, no breastfeeding, late pregnancy", False, None),
("Other: Dense breasts, atypical hyperplasia, alcohol,", False, None),
("obesity (post-menopause), prior chest radiation", False, None),
], COL3X, inner, COL_W, size=7.5, leading=10)
# ══════════════════════════════════════════════════════════════════════════
# ROW 2 — Histological Types (wide) | Nottingham Grading
# ══════════════════════════════════════════════════════════════════════════
HIST_W = COL_W * 2 + PAD
inner = box(COL1X, R2Y, HIST_W, R2H, LIGHT_PNK, ACCENT1,
"◆ HISTOLOGICAL TYPES OF INVASIVE BREAST CANCER")
HDR_ROW = 13
type_data = [
("IDC / NST (Invasive Ductal Carcinoma)",
"50–70%; cohesive mass; haphazard nests/cords in desmoplastic stroma; stellate on mammogram; DCIS often coexists"),
("ILC (Invasive Lobular Carcinoma)",
"5–15%; single-file 'Indian file' pattern; CDH1 mutation → E-cadherin loss; multifocal/bilateral; mammographically occult"),
("Tubular Carcinoma",
"~2–3%; small angular glands, single cell layer; low grade (G1); 10% LN mets; ~100% long-term survival"),
("Mucinous / Colloid Carcinoma",
"~2–3%; bland cells floating in mucin lakes; G1; gelatinous cut surface; >90% ER+; good prognosis"),
("Medullary Carcinoma",
"~5%; syncytial sheets of large bizarre cells; brisk lymphocytic infiltrate; pushing borders; G3; ER/PR/HER2 negative"),
("Metaplastic Carcinoma",
"Rare; G3; TNBC; mostly node-negative but high metastatic risk; ~50% local/distant relapse; poor prognosis"),
]
COL_A = 170
COL_B = HIST_W - COL_A - 14
TX = COL1X + 4
TY = inner - 2
DATA_ROW = (R2H - 14 - HDR_ROW - 8) / len(type_data)
rect(TX, TY - HDR_ROW, COL_A, HDR_ROW, fill=ACCENT1)
rect(TX + COL_A + 2, TY - HDR_ROW, COL_B, HDR_ROW, fill=ACCENT1)
for lbl, hx, ww in [("Histological Type", TX+3, COL_A), ("Key Pathological Features", TX+COL_A+5, COL_B)]:
c.saveState(); c.setFillColor(white); c.setFont("Helvetica-Bold", 7.5)
c.drawString(hx, TY - HDR_ROW + 3.5, lbl); c.restoreState()
for i, (name, desc) in enumerate(type_data):
ry = TY - HDR_ROW - (i+1)*DATA_ROW
bg = white if i % 2 == 0 else ROW_ALT
rect(TX, ry, COL_A, DATA_ROW, fill=bg, stroke=BORDER, lw=0.4)
rect(TX+COL_A+2, ry, COL_B, DATA_ROW, fill=bg, stroke=BORDER, lw=0.4)
c.saveState()
c.setFont("Helvetica-Bold", 6.8); c.setFillColor(HEADER)
c.drawString(TX+3, ry+DATA_ROW/2-3.5, name)
c.setFont("Helvetica", 6.6); c.setFillColor(DARK)
c.drawString(TX+COL_A+5, ry+DATA_ROW/2-3.5, desc[:108])
c.restoreState()
inner = box(COL3X, R2Y, COL_W, R2H, AMBER_L, AMBER, "◆ NOTTINGHAM HISTOLOGICAL GRADE (NHG)")
wrap_lines([
("3 criteria — each scored 1–3 points:", True, AMBER),
("", False, None),
("1. Tubule / Gland Formation", True, DARK),
(" >75% = 1 | 10–75% = 2 | <10% = 3", False, None),
("2. Nuclear Pleomorphism", True, DARK),
(" Small uniform = 1 | Moderate = 2 | Marked = 3", False, None),
("3. Mitotic Rate (per 10 HPF)", True, DARK),
(" Low = 1 | Moderate = 2 | High = 3", False, None),
("", False, None),
("SCORE 3–5 = Grade 1 (Well differentiated)", True, GREEN),
("SCORE 6–7 = Grade 2 (Moderately differentiated)", True, AMBER),
("SCORE 8–9 = Grade 3 (Poorly differentiated)", True, RED_DARK),
], COL3X, inner, COL_W, size=7.5, leading=9.8)
# ══════════════════════════════════════════════════════════════════════════
# ROW 3 — Molecular Subtypes | Biomarkers | Spread
# ══════════════════════════════════════════════════════════════════════════
inner = box(COL1X, R3Y, COL_W, R3H, LIGHT_PNK, ACCENT1,
"◆ MOLECULAR SUBTYPES (Gene Expression Profiling)")
mol_data = [
("Luminal A", "40–60%", "ER+/PR+ high, HER2−, Ki-67 low", "G1–2", "BEST"),
("Luminal B", "20–30%", "ER+/PR+ low, HER2−/+, Ki-67 high", "G2–3", "GOOD"),
("HER2-Enriched", "10–20%", "HER2+, ER−/PR−, Ki-67 high", "G3", "POOR*"),
("Basal-like / TNBC", "10–20%", "ER−/PR−/HER2−, BRCA1 assoc., high grade", "G3", "POOR"),
]
mW = [115, 42, 157, 40, 58]
mHDR_H = 13
mROW_H = (R3H - 14 - mHDR_H - 8) / 4
my = inner - 2
mx = COL1X + 4
for h, cw in zip(["Subtype","Freq","Biomarker Profile","Grade","Prog."], mW):
rect(mx, my-mHDR_H, cw, mHDR_H, fill=ACCENT1)
c.saveState(); c.setFillColor(white); c.setFont("Helvetica-Bold", 7)
c.drawString(mx+2, my-mHDR_H+3.5, h); c.restoreState()
mx += cw + 2
prog_c = [GREEN, GREEN, AMBER, RED_DARK]
for ri, row in enumerate(mol_data):
ry = inner - 2 - mHDR_H - (ri+1)*mROW_H
rbg = white if ri % 2 == 0 else ROW_ALT
mx = COL1X + 4
for ci, (cell, cw) in enumerate(zip(row, mW)):
rect(mx, ry, cw, mROW_H, fill=rbg, stroke=BORDER, lw=0.4)
cc = prog_c[ri] if ci == 4 else (HEADER if ci == 0 else DARK)
c.saveState(); c.setFillColor(cc)
c.setFont("Helvetica-Bold" if ci in (0,4) else "Helvetica", 6.8)
c.drawString(mx+3, ry+mROW_H/2-3.5, cell); c.restoreState()
mx += cw + 2
c.saveState(); c.setFillColor(MID); c.setFont("Helvetica", 6)
c.drawString(COL1X+4, R3Y+4, "* HER2+ now tx-responsive with trastuzumab/pertuzumab")
c.restoreState()
inner = box(COL2X, R3Y, COL_W, R3H, TEAL_LITE, TEAL, "◆ BIOMARKERS & IHC TESTING")
wrap_lines([
("ER / PR (Estrogen / Progesterone Receptors)", True, TEAL),
("• IHC; >1% nuclear staining = positive", False, None),
("• 1–10% = low ER (limited endocrine benefit)", False, None),
("• Guides tamoxifen & aromatase inhibitors", False, None),
("", False, None),
("HER2 (Human EGF Receptor 2)", True, TEAL),
("• Amplified in ~20% of BCs; IHC 0–3+", False, None),
("• 3+ = positive; 2+ equivocal → ISH confirmation", False, None),
("• Guides trastuzumab + pertuzumab therapy", False, None),
("", False, None),
("Ki-67 (Proliferation Marker)", True, TEAL),
("• % Ki-67+ nuclei; Luminal A <20% vs B ≥20%", False, None),
], COL2X, inner, COL_W, size=7.3, leading=9.5)
inner = box(COL3X, R3Y, COL_W, R3H, LIGHT_PNK, ACCENT2, "◆ ROUTES OF SPREAD & METASTASIS")
wrap_lines([
("Local:", True, ACCENT1),
("Direct invasion into stroma, skin (peau d'orange),", False, None),
("nipple; Cooper ligament tethering → skin dimpling", False, None),
("", False, None),
("Lymphatic:", True, ACCENT1),
("Axillary LN (most common, 3 levels)", False, None),
("Internal mammary (medial tumours)", False, None),
("Supra/Infraclavicular LN (advanced stage)", False, None),
("Sentinel LN biopsy = standard staging", False, None),
("", False, None),
("Haematogenous:", True, ACCENT1),
("BONE (lytic) > Liver > Lung > Brain > Adrenals", False, None),
("ILC: peritoneum, GI tract, uterus, ovaries", False, None),
], COL3X, inner, COL_W, size=7.3, leading=9.5)
# ══════════════════════════════════════════════════════════════════════════
# IMAGE STRIP — Full width, 5 histology + mammogram panels
# ══════════════════════════════════════════════════════════════════════════
IMG_FULL_W = BODY_W
IMG_X = MARGIN
IMG_Y_box = IMG_Y
rect(IMG_X, IMG_Y_box, IMG_FULL_W, IMG_H, fill=HexColor("#FDF5FA"), stroke=HEADER, lw=1.5)
# Title band
rect(IMG_X, IMG_Y_box + IMG_H - 14, IMG_FULL_W, 14, fill=HEADER)
c.saveState(); c.setFillColor(white); c.setFont("Helvetica-Bold", 8.5)
c.drawString(IMG_X+6, IMG_Y_box + IMG_H - 14 + 3.5,
"◆ HISTOPATHOLOGY & IMAGING — Invasive Breast Cancer (Sabiston Surgery, Fig 68.9 · Schwartz Surgery, Fig 17-16 & 17-17 & 17-21)")
c.restoreState()
INNER_IMG_H = IMG_H - 16 - 18 # minus title + caption space below
IMG_PAD = 5
N_PANELS = 6
panel_w = (IMG_FULL_W - (N_PANELS+1)*IMG_PAD) / N_PANELS
panel_y = IMG_Y_box + 16
# Panel definitions: (reader_index, caption)
panels = [
(0, "IDC: haphazard malignant cells in stroma"),
(5, "IDC (scirrhous) — 100× & 200×"),
(1, "ILC: single-file 'Indian file' pattern"),
(6, "ILC: lobular cells, 100×"),
(3, "Mucinous: cells in mucin lakes"),
(7, "Mammogram: spiculated mass (IDC)"),
]
for i, (ridx, cap) in enumerate(panels):
px = IMG_X + IMG_PAD + i*(panel_w + IMG_PAD)
draw_image(readers[ridx], px, panel_y, panel_w, INNER_IMG_H, caption=cap, cap_color=HEADER)
# ══════════════════════════════════════════════════════════════════════════
# ROW 4 — TNM Staging | Gross & Micro | Genomic Assays
# ══════════════════════════════════════════════════════════════════════════
inner = box(COL1X, R4Y, COL_W, R4H, TEAL_LITE, TEAL, "◆ TNM STAGING — AJCC 8th EDITION")
tnm_data = [
("T (Tumour)", "Tx/T0/Tis | T1 ≤2cm | T2 2–5cm | T3 >5cm | T4 chest wall/skin"),
("N (Nodes)", "N0 no mets | N1 movable axillary | N2 fixed/internal mammary | N3 supra/infraclavicular"),
("M (Mets)", "M0 = no distant mets | M1 = distant metastasis"),
("Stage I", "T1 N0 M0 — Excellent prognosis"),
("Stage II", "T2N0 / T1-2N1 — Good prognosis"),
("Stage III", "T3-4 / N2-3 — Locally advanced"),
("Stage IV", "Any T, Any N, M1 — Metastatic disease"),
]
tnm_hw = 90
tnm_vw = COL_W - tnm_hw - 14
tnm_rh = (R4H - 14 - 4) / len(tnm_data)
ty = inner - 2
stage_c = [TEAL, TEAL, TEAL, GREEN, AMBER, HexColor("#C05000"), RED_DARK]
for i, (lbl, val) in enumerate(tnm_data):
ry = ty - (i+1)*tnm_rh
rbg = TEAL_LITE if i%2==0 else white
rect(COL1X+4, ry, tnm_hw, tnm_rh, fill=stage_c[i])
rect(COL1X+4+tnm_hw+2, ry, tnm_vw, tnm_rh, fill=rbg, stroke=BORDER, lw=0.4)
c.saveState()
c.setFillColor(white); c.setFont("Helvetica-Bold", 7.2)
c.drawString(COL1X+7, ry+tnm_rh/2-3.5, lbl)
c.setFillColor(DARK); c.setFont("Helvetica", 6.8)
c.drawString(COL1X+4+tnm_hw+5, ry+tnm_rh/2-3.5, val)
c.restoreState()
inner = box(COL2X, R4Y, COL_W, R4H, LIGHT_PNK, ACCENT1, "◆ GROSS & MICROSCOPIC PATHOLOGY")
wrap_lines([
("GROSS:", True, ACCENT1),
("IDC: Hard, gritty, stellate mass; spiculated edges;", False, None),
("chalky white streaks (elastosis); gritty cut surface", False, None),
("ILC: Rubbery diffuse thickening; no discrete mass", False, None),
("Mucinous: Soft, gelatinous, bluish, well-circumscribed", False, None),
("Medullary: Soft, fleshy, pushing borders ± haemorrhage", False, None),
("", False, None),
("MICROSCOPY:", True, ACCENT1),
("IDC: Nests/cords in desmoplastic stroma; mitoses;", False, None),
("nuclear pleomorphism; DCIS often at periphery", False, None),
("ILC: Single-file infiltration; targetoid periductal;", False, None),
("E-cadherin negative (IHC); signet-ring cells possible", False, None),
("Medullary: Syncytial sheets; brisk lymphocytic infiltrate", False, None),
], COL2X, inner, COL_W, size=7.2, leading=9.3)
inner = box(COL3X, R4Y, COL_W, R4H, AMBER_L, AMBER, "◆ GENOMIC ASSAYS & SPECIAL TESTS")
wrap_lines([
("Oncotype DX — 21-Gene Recurrence Score (RS)", True, AMBER),
("RT-PCR on FFPE tissue; score 1–100", False, None),
("RS <26: endocrine alone | RS ≥26: add chemo", False, None),
("For ER+/HER2−, 0–3 positive LN (early stage)", False, None),
("", False, None),
("MammaPrint — 70-Gene Assay", True, AMBER),
("Low-risk / High-risk readout; ER+ or ER− tumours", False, None),
("", False, None),
("Other Assays:", True, AMBER),
("PAM50/Prosigna — intrinsic subtype + ROR score", False, None),
("EndoPredict — ER+/HER2− prognosis", False, None),
("", False, None),
("BRCA1/2 Germline Testing:", True, AMBER),
("BRCA1 → TNBC/basal-like; BRCA2 → Luminal type", False, None),
("Guides PARP inhibitors (olaparib, talazoparib)", False, None),
], COL3X, inner, COL_W, size=7.2, leading=9.3)
# ══════════════════════════════════════════════════════════════════════════
# ROW 5 — Clinical Features | Prognostic Factors | Treatment
# ══════════════════════════════════════════════════════════════════════════
inner = box(COL1X, R5Y, COL_W, R5H, LIGHT_PNK, HEADER, "◆ CLINICAL FEATURES & PRESENTATION")
wrap_lines([
("Common Presentations:", True, HEADER),
("• Painless, hard, irregular, fixed lump (most common)", False, None),
("• Skin dimpling (Cooper ligament tethering)", False, None),
("• Peau d'orange (dermal lymphatic obstruction)", False, None),
("• Nipple retraction / bloody discharge", False, None),
("• Axillary lymphadenopathy", False, None),
("", False, None),
("Special Presentations:", True, HEADER),
("• Inflammatory BC: Erythema, warmth, rapid enlargement", False, None),
(" T4d — worst prognosis; dermal lymphatic invasion", False, None),
("• Paget's disease: nipple eczema + underlying DCIS/IDC", False, None),
(" Paget cells = large pale vacuolated cells in epithelium", False, None),
("• ILC: diffuse thickening, often bilateral, late dx", False, None),
], COL1X, inner, COL_W, size=7.2, leading=9.3)
inner = box(COL2X, R5Y, COL_W, R5H, TEAL_LITE, TEAL, "◆ PROGNOSTIC & PREDICTIVE FACTORS")
wrap_lines([
("FAVOURABLE:", True, GREEN),
("• Small size T1 ≤2 cm", False, None),
("• Node-negative N0 — strongest single predictor", False, None),
("• Low grade G1 | ER+/PR+ strongly positive", False, None),
("• Low Ki-67 (<20%) | Luminal A subtype", False, None),
("• Tubular / mucinous histological type", False, None),
("• High TILs (tumour-infiltrating lymphocytes) in TNBC", False, None),
("", False, None),
("UNFAVOURABLE:", True, RED_DARK),
("• LN positivity — single strongest adverse predictor", False, None),
("• High grade G3 | Large tumour T3/T4", False, None),
("• HER2+ or TNBC subtype | High Ki-67 (≥30%)", False, None),
("• Lymphovascular invasion | BRCA1 mutation", False, None),
("• Inflammatory carcinoma T4d", False, None),
], COL2X, inner, COL_W, size=7.2, leading=9.3)
inner = box(COL3X, R5Y, COL_W, R5H, AMBER_L, AMBER, "◆ TREATMENT OVERVIEW (Pathology-Guided)")
wrap_lines([
("SURGERY:", True, AMBER),
("• Lumpectomy + RT (breast-conserving, early stage)", False, None),
("• Mastectomy ± reconstruction (large/multifocal)", False, None),
("• Sentinel LN biopsy → axillary dissection if positive", False, None),
("", False, None),
("ENDOCRINE (ER+/PR+):", True, AMBER),
("• Pre-menopausal: Tamoxifen (5–10 yrs)", False, None),
("• Post-menopausal: Aromatase inhibitors", False, None),
("", False, None),
("ANTI-HER2 (HER2+):", True, AMBER),
("• Trastuzumab + Pertuzumab + Taxane", False, None),
("• T-DM1 / T-DXd for residual/metastatic disease", False, None),
("", False, None),
("TNBC (Triple Negative):", True, AMBER),
("• Anthracycline + Taxane ± Carboplatin (neoadjuvant)", False, None),
("• BRCA+: Olaparib / Talazoparib (PARP inhibitors)", False, None),
("• PDL-1+: Pembrolizumab + Chemotherapy", False, None),
], COL3X, inner, COL_W, size=7.2, leading=9.3)
# ── VERTICAL DIVIDERS ─────────────────────────────────────────────────────
c.saveState()
c.setStrokeColor(BORDER); c.setLineWidth(0.5); c.setDash(3,3)
c.line(COL2X-PAD/2, H-HDR_H-MARGIN, COL2X-PAD/2, FOOT_H+MARGIN)
c.line(COL3X-PAD/2, H-HDR_H-MARGIN, COL3X-PAD/2, FOOT_H+MARGIN)
c.restoreState()
c.save()
print(f"✅ PDF with images saved: {OUT}")
cd /home/daytona/workspace/breast-cancer-chart && python3 chart_pdf_images.py
ls -lh /home/daytona/workspace/breast-cancer-chart/Invasive_Breast_Cancer_With_I…
Invasive Breast Cancer With Images
PDF Document · PDF
| Panel | Image |
|---|---|
| 1 | IDC (histo) — haphazard malignant cells infiltrating stroma |
| 2 | IDC scirrhous — 100× and 200× (productive fibrosis pattern) |
| 3 | ILC (histo) — classic single-file "Indian file" pattern |
| 4 | ILC 100× — small lobular cells, discohesive |
| 5 | Mucinous carcinoma — tumour cells floating in mucin lakes |
| 6 | Mammogram — spiculated mass with skin tethering (IDC) |