Make flowchart - Phase 1: Screening Tests Step 1: Perform Initial Screening Overnight dexamethasone suppression test (1 mg at midnight, measure cortisol at 0900 h). OR 24-hour urinary free cortisol collection. OR Check for loss of diurnal variation (compare midnight vs. morning cortisol). Step 2: Evaluate Results Normal: Cortisol suppresses to < 50 nmol/L (or urinary cortisol < 280 nmol/24h). Abnormal: Proceed to Phase 2. Phase 2: Diagnostic Tests Step 1: Low-Dose Dexamethasone Suppression Test (LDDST) Administer 0.5 mg every 6 hours for 48 hours. If cortisol fails to suppress to < 50 nmol/L, Cushing Syndrome is confirmed. Step 2: Measure Plasma ACTH ACTH Suppressed: Adrenal disease/Non-ACTH-dependent Cushing syndrome. ACTH Normal/Raised: ACTH-dependent Cushing syndrome (Pituitary or Ectopic source). Phase 3: Localisation Studies Pathway A: If ACTH is Not Detectable Probable Cause: Adrenal Gland Tumour. Action: Perform CT or MRI of adrenal glands. If no lesion found: Proceed to adrenal vein sampling. Pathway B: If ACTH is Detectable Action: Perform High-dose suppression test (2 mg dexamethasone) or CRH test. Scenario 1: Cortisol Responds/Suppresses Diagnosis: Cushing's Disease (Pituitary cause) is likely. Next Steps: MRI of pituitary; consider bilateral inferior petrosal sinus sampling. Scenario 2: Cortisol Does NOT Respond Diagnosis: Ectopic ACTH secretion is likely (e.g., small cell lung carcinoma). Next Steps: IV contrast CT of chest, abdomen, and pelvis. Further Action: MRI of neck, thorax, and abdomen to locate source.
ls /home/daytona/workspace/ 2>/dev/null || echo "workspace empty or missing"
mkdir -p /home/daytona/workspace/cushing-flowchart
~/cushing-flowchart/flowchart.js
const pptxgen = require("pptxgenjs");
const pres = new pptxgen();
pres.layout = "LAYOUT_WIDE"; // 13.3 x 7.5 inches
// ─── Colour palette ───────────────────────────────────────────────────────
const C = {
bg: "0D1B2A", // near-black navy
phase1: "1A6B8A", // teal
phase2: "A0522D", // sienna
phase3: "2E7D32", // forest green
pathA: "5B4FCF", // purple
pathB: "B85C00", // amber-brown
normal: "2E7D32", // green text / box
abnormal: "B71C1C", // red text / box
acthSup: "5B4FCF",
acthNorm: "B85C00",
scenario1: "1565C0",
scenario2: "6A1B9A",
arrow: "90CAF9",
white: "FFFFFF",
lightGray: "CFD8DC",
bodyText: "E3F2FD",
};
// ─── Helper functions ─────────────────────────────────────────────────────
/** Rounded rectangle node */
function box(slide, { x, y, w, h, fill, text, sub, textSize = 9.5, subSize = 8, bold = false, rectType = "roundRect" }) {
slide.addShape(pres.ShapeType[rectType] || pres.ShapeType.roundRect, {
x, y, w, h,
fill: { color: fill },
line: { color: "FFFFFF", width: 0.5, transparency: 60 },
shadow: { type: "outer", blur: 6, offset: 2, angle: 45, color: "000000", opacity: 0.35 },
});
const parts = [];
if (text) {
parts.push({ text, options: { bold: bold || false, fontSize: textSize, color: C.white, breakLine: sub ? true : false } });
}
if (sub) {
parts.push({ text: sub, options: { fontSize: subSize, color: "DDEEFF", bold: false } });
}
slide.addText(parts, {
x, y, w, h,
align: "center", valign: "middle",
margin: 4,
wrap: true,
});
}
/** Diamond decision shape */
function diamond(slide, { x, y, w, h, fill, text, textSize = 9 }) {
slide.addShape(pres.ShapeType.diamond, {
x, y, w, h,
fill: { color: fill },
line: { color: C.white, width: 0.6, transparency: 50 },
shadow: { type: "outer", blur: 6, offset: 2, angle: 45, color: "000000", opacity: 0.35 },
});
slide.addText(text, {
x, y, w, h,
fontSize: textSize, color: C.white, bold: true,
align: "center", valign: "middle", margin: 4, wrap: true,
});
}
/** Downward arrow */
function arrowDown(slide, x, y1, y2) {
slide.addShape(pres.ShapeType.line, {
x, y: y1, w: 0, h: y2 - y1,
line: { color: C.arrow, width: 1.8, endArrowType: "triangle" },
});
}
/** Horizontal arrow (left-to-right or right-to-left) */
function arrowH(slide, x1, x2, y) {
slide.addShape(pres.ShapeType.line, {
x: x1, y, w: x2 - x1, h: 0,
line: { color: C.arrow, width: 1.8, endArrowType: "triangle" },
});
}
/** Elbow connector going down then right or down then left */
function elbowDR(slide, x1, y1, x2, y2) {
// draw vertical leg then horizontal leg
slide.addShape(pres.ShapeType.line, {
x: x1, y: y1, w: 0, h: y2 - y1,
line: { color: C.arrow, width: 1.4 },
});
slide.addShape(pres.ShapeType.line, {
x: Math.min(x1, x2), y: y2, w: Math.abs(x2 - x1), h: 0,
line: { color: C.arrow, width: 1.4, endArrowType: "triangle" },
});
}
/** Label beside an arrow */
function label(slide, x, y, text, color = C.lightGray, size = 7.5) {
slide.addText(text, {
x, y, w: 1.3, h: 0.25,
fontSize: size, color, bold: true, align: "center",
});
}
// ─── Background ───────────────────────────────────────────────────────────
function buildSlide() {
const slide = pres.addSlide();
// background rect
slide.addShape(pres.ShapeType.rect, {
x: 0, y: 0, w: 13.3, h: 7.5,
fill: { color: C.bg },
line: { color: C.bg },
});
// ── Title bar ──────────────────────────────────────────────────────────
slide.addShape(pres.ShapeType.rect, {
x: 0, y: 0, w: 13.3, h: 0.55,
fill: { color: "0A4A6A" },
line: { color: "0A4A6A" },
});
slide.addText("Cushing Syndrome: Investigation & Localisation Flowchart", {
x: 0.2, y: 0, w: 12.9, h: 0.55,
fontSize: 14, color: C.white, bold: true,
align: "center", valign: "middle",
});
// ── Phase headers (column banners) ────────────────────────────────────
// Phase 1: x 0.15 – 3.85
// Phase 2: x 4.1 – 6.7
// Phase 3: x 7.0 – 13.1
const phaseY = 0.62;
const phaseH = 0.32;
const phases = [
{ x: 0.15, w: 3.7, color: C.phase1, label: "PHASE 1 — Screening" },
{ x: 4.10, w: 2.7, color: C.phase2, label: "PHASE 2 — Diagnostic" },
{ x: 7.00, w: 6.15, color: C.phase3, label: "PHASE 3 — Localisation" },
];
phases.forEach(p => {
slide.addShape(pres.ShapeType.roundRect, {
x: p.x, y: phaseY, w: p.w, h: phaseH,
fill: { color: p.color },
line: { color: C.white, width: 0.3, transparency: 60 },
});
slide.addText(p.label, {
x: p.x, y: phaseY, w: p.w, h: phaseH,
fontSize: 9, bold: true, color: C.white, align: "center", valign: "middle",
});
});
// ─── PHASE 1 ──────────────────────────────────────────────────────────
// Step 1: Perform Initial Screening
box(slide, {
x: 0.18, y: 1.05, w: 3.6, h: 0.78,
fill: C.phase1,
text: "STEP 1 — Perform Initial Screening",
sub: "• Overnight DST (1 mg midnight → cortisol at 09:00 h)\n• OR 24-h Urinary Free Cortisol\n• OR Midnight vs Morning cortisol (diurnal variation)",
textSize: 8.5,
subSize: 7.5,
bold: true,
});
arrowDown(slide, 1.98, 1.83, 2.05);
// Step 2: Evaluate Results
box(slide, {
x: 0.18, y: 2.07, w: 3.6, h: 0.48,
fill: "0E3D5C",
text: "STEP 2 — Evaluate Results",
textSize: 8.5, bold: true,
});
arrowDown(slide, 1.98, 2.55, 2.72);
// Normal / Abnormal diamonds
diamond(slide, {
x: 0.18, y: 2.72, w: 3.6, h: 0.62,
fill: "104060",
text: "Cortisol suppressed?",
textSize: 9,
});
// NORMAL branch – goes down-left
arrowDown(slide, 0.62, 3.34, 3.85);
label(slide, 0.08, 3.38, "YES", C.normal, 8);
box(slide, {
x: 0.18, y: 3.85, w: 1.6, h: 0.6,
fill: "1B5E20",
text: "NORMAL",
sub: "Cortisol < 50 nmol/L\nor UFC < 280 nmol/24h",
textSize: 8.5, subSize: 7.2, bold: true,
});
// ABNORMAL branch – right then down to Phase 2
label(slide, 3.3, 3.38, "NO", C.abnormal, 8);
arrowDown(slide, 3.35, 3.34, 3.85);
box(slide, {
x: 1.95, y: 3.85, w: 2.0, h: 0.6,
fill: "7B1818",
text: "ABNORMAL",
sub: "Proceed to Phase 2",
textSize: 8.5, subSize: 7.2, bold: true,
});
// Arrow from Abnormal box rightward → Phase 2
arrowH(slide, 3.95, 4.15, 4.15);
// ─── PHASE 2 ──────────────────────────────────────────────────────────
const p2x = 4.12;
box(slide, {
x: p2x, y: 1.05, w: 2.65, h: 0.72,
fill: C.phase2,
text: "STEP 1 — Low-Dose DST (LDDST)",
sub: "0.5 mg q6h × 48 hours\nCortisol fails to suppress < 50 nmol/L\n→ Cushing Syndrome CONFIRMED",
textSize: 8.2, subSize: 7.2, bold: true,
});
arrowDown(slide, 5.445, 1.77, 2.05);
box(slide, {
x: p2x, y: 2.05, w: 2.65, h: 0.5,
fill: "5A2D00",
text: "STEP 2 — Measure Plasma ACTH",
textSize: 8.2, bold: true,
});
arrowDown(slide, 5.445, 2.55, 2.72);
diamond(slide, {
x: p2x, y: 2.72, w: 2.65, h: 0.64,
fill: "3E1F00",
text: "Plasma ACTH level?",
textSize: 9,
});
// ACTH Suppressed → left+down
arrowDown(slide, 4.55, 3.36, 3.85);
label(slide, 4.0, 3.44, "SUPPRESSED", C.acthSup, 7);
box(slide, {
x: p2x, y: 3.85, w: 1.2, h: 0.65,
fill: "3B2B8C",
text: "Adrenal Disease",
sub: "Non-ACTH-dependent\nCushing Syndrome",
textSize: 7.8, subSize: 6.8, bold: true,
});
// ACTH Normal/Raised → right+down
label(slide, 5.9, 3.44, "NORMAL/↑", C.acthNorm, 7);
arrowDown(slide, 6.35, 3.36, 3.85);
box(slide, {
x: 5.38, y: 3.85, w: 1.35, h: 0.65,
fill: "6B3300",
text: "ACTH-dependent",
sub: "Pituitary or\nEctopic source",
textSize: 7.8, subSize: 6.8, bold: true,
});
// Connect Phase 2 Abnormal result → Phase 2 Step 1
// Already connected via arrowH from Phase 1 Abnormal box
// But LDDST also connects down from Phase 1; we link top of Phase2 box
// Phase 1 abnormal box at y=3.85, arrowH goes to 4.15 at y=4.15
// Let's add a connector from Phase1 abnormal to Phase2 LDDST top
// vertical from Phase1 abnormal center up to y=1.41, then right to Phase2
// Actually let's just draw a connector from the right side of Phase1 abnormal (3.95,4.15) to Phase2 LDDST step1
// The LDDST is at y=1.05 so we need to go up
// Better: draw an elbow from (3.95, 4.15) going right then up to (4.12, 1.41)
slide.addShape(pres.ShapeType.line, {
x: 3.95, y: 4.15, w: 0.42, h: 0,
line: { color: C.arrow, width: 1.5 },
});
slide.addShape(pres.ShapeType.line, {
x: 4.37, y: 1.41, w: 0, h: 2.74,
line: { color: C.arrow, width: 1.5, endArrowType: "none" },
});
slide.addShape(pres.ShapeType.line, {
x: 4.12, y: 1.41, w: 0.25, h: 0,
line: { color: C.arrow, width: 1.5, endArrowType: "triangle" },
});
// ─── PHASE 3 ──────────────────────────────────────────────────────────
const p3x = 7.05;
const p3W = 6.1;
// "ACTH not detectable" and "ACTH detectable" arrows from phase2 adrenal/ACTH-dep boxes
// Pathway A (from Adrenal Disease box, x=4.12 w=1.2) → goes right into Phase 3 left column
arrowH(slide, 5.32, 7.1, 4.175);
label(slide, 5.82, 3.95, "Pathway A", "A8D8EA", 7);
// Pathway B (from ACTH-dep box, x=5.38 w=1.35) → goes right into Phase 3 right column
arrowH(slide, 6.73, 7.1, 4.175);
label(slide, 6.82, 3.95, "Pathway B", "FFD59E", 7);
// ── Pathway A: ACTH Not Detectable ─────────────────────────────────────
const pAx = 7.07;
const pAw = 2.8;
box(slide, {
x: pAx, y: 1.05, w: pAw, h: 0.42,
fill: C.pathA,
text: "PATHWAY A — ACTH Not Detectable",
textSize: 8, bold: true,
});
box(slide, {
x: pAx, y: 1.55, w: pAw, h: 0.45,
fill: "2A1E80",
text: "Probable Cause: Adrenal Gland Tumour",
textSize: 8, bold: false,
});
arrowDown(slide, 8.47, 2.0, 2.18);
box(slide, {
x: pAx, y: 2.18, w: pAw, h: 0.45,
fill: "1A1060",
text: "CT / MRI of Adrenal Glands",
textSize: 8,
});
arrowDown(slide, 8.47, 2.63, 2.80);
diamond(slide, {
x: pAx, y: 2.80, w: pAw, h: 0.6,
fill: "120C50",
text: "Lesion found?",
textSize: 8.5,
});
arrowDown(slide, 8.47, 3.40, 3.58);
label(slide, 8.0, 3.45, "NO", C.abnormal, 8);
box(slide, {
x: pAx, y: 3.58, w: pAw, h: 0.52,
fill: "0D0840",
text: "Adrenal Vein Sampling",
sub: "Proceed if no lesion identified on imaging",
textSize: 8, subSize: 7,
});
// Arrow from Pathway A connector (4.175) up to Pathway A header
elbowDR(slide, 7.1, 4.175, 7.07, 1.47);
// ── Pathway B: ACTH Detectable ─────────────────────────────────────────
const pBx = 10.1;
const pBw = 3.05;
box(slide, {
x: pBx, y: 1.05, w: pBw, h: 0.42,
fill: C.pathB,
text: "PATHWAY B — ACTH Detectable",
textSize: 8, bold: true,
});
box(slide, {
x: pBx, y: 1.55, w: pBw, h: 0.5,
fill: "5E2E00",
text: "High-Dose DST (2 mg dexamethasone)\nOR CRH Stimulation Test",
textSize: 8,
});
arrowDown(slide, 11.625, 2.05, 2.25);
diamond(slide, {
x: pBx, y: 2.25, w: pBw, h: 0.65,
fill: "3B1A00",
text: "Cortisol responds\n/ suppresses?",
textSize: 8.5,
});
// Scenario 1: YES → Cushing's Disease (Pituitary)
arrowDown(slide, 10.6, 2.90, 3.12);
label(slide, 10.08, 2.94, "YES", C.normal, 8);
box(slide, {
x: pBx, y: 3.12, w: 1.4, h: 0.72,
fill: "0D3D7A",
text: "Cushing's Disease",
sub: "Pituitary cause likely",
textSize: 8, subSize: 7.2, bold: true,
});
arrowDown(slide, 10.7, 3.84, 4.12);
box(slide, {
x: pBx, y: 4.12, w: 1.4, h: 0.62,
fill: "08295E",
text: "MRI Pituitary",
sub: "± Bilateral inferior petrosal\nsinus sampling",
textSize: 7.8, subSize: 7,
});
// Scenario 2: NO → Ectopic ACTH
arrowDown(slide, 12.6, 2.90, 3.12);
label(slide, 12.62, 2.94, "NO", C.abnormal, 8);
box(slide, {
x: 11.6, y: 3.12, w: 1.55, h: 0.72,
fill: "4A0070",
text: "Ectopic ACTH",
sub: "e.g. Small Cell\nLung Carcinoma",
textSize: 8, subSize: 7.2, bold: true,
});
arrowDown(slide, 12.375, 3.84, 4.12);
box(slide, {
x: 11.6, y: 4.12, w: 1.55, h: 0.72,
fill: "300050",
text: "IV Contrast CT",
sub: "Chest, abdomen & pelvis",
textSize: 7.8, subSize: 7,
});
arrowDown(slide, 12.375, 4.84, 5.1);
box(slide, {
x: 11.6, y: 5.1, w: 1.55, h: 0.62,
fill: "200038",
text: "MRI",
sub: "Neck, thorax & abdomen\nto locate source",
textSize: 7.8, subSize: 7,
});
// Arrow from Pathway B connector (4.175) up to Pathway B header
elbowDR(slide, 7.1, 4.175, 10.1, 1.47);
// ── ACTH-dep box link to Pathway B ────────────────────────────────────
// Arrow from ACTH-dep (5.38+1.35=6.73) to pathway B
// (already drawn as arrowH at y=4.175 going to 7.1 + elbow)
// ── Footer ─────────────────────────────────────────────────────────────
slide.addShape(pres.ShapeType.rect, {
x: 0, y: 7.3, w: 13.3, h: 0.2,
fill: { color: "0A4A6A" }, line: { color: "0A4A6A" },
});
slide.addText("DST = Dexamethasone Suppression Test | UFC = Urinary Free Cortisol | ACTH = Adrenocorticotrophic Hormone | CRH = Corticotropin-Releasing Hormone", {
x: 0.2, y: 7.3, w: 12.9, h: 0.2,
fontSize: 6.5, color: "90CAF9", align: "center", valign: "middle",
});
return slide;
}
buildSlide();
pres.writeFile({ fileName: "/home/daytona/workspace/cushing-flowchart/Cushing_Syndrome_Flowchart.pptx" })
.then(() => console.log("✅ Saved: Cushing_Syndrome_Flowchart.pptx"))
.catch(e => { console.error("❌ Error:", e); process.exit(1); });
cd /home/daytona/workspace/cushing-flowchart && node flowchart.js 2>&1
ls -lh /home/daytona/workspace/cushing-flowchart/ && python3 /home/daytona/skills/pptx/scripts/thumbnail.py /home/daytona/workspace/cushing-flowchart/Cushing_Syndrome_Flowchart.pptx 2>&1 | head -20
find /home/daytona/workspace/cushing-flowchart -name "*.jpg" -o -name "*.png" 2>/dev/null
Cushing Syndrome Flowchart
Presentation · PPTX
| Section | Contents |
|---|---|
| Phase 1 — Screening (teal) | Step 1: three initial screening options → Step 2: diamond decision (cortisol suppressed?) → YES → Normal box / NO → Abnormal → feeds Phase 2 |
| Phase 2 — Diagnostic (amber) | LDDST confirmation → Plasma ACTH diamond → Suppressed (Adrenal disease) vs Normal/Raised (ACTH-dependent) → feeds Phase 3 |
| Phase 3A — Pathway A (purple) | ACTH not detectable → Adrenal tumour → CT/MRI adrenals → diamond: lesion found? → No → Adrenal vein sampling |
| Phase 3B — Pathway B (forest green) | ACTH detectable → High-dose DST / CRH test → diamond: cortisol responds? → YES: Cushing's Disease → MRI pituitary ± IPSS / NO: Ectopic ACTH → CT chest/abdomen/pelvis → MRI neck/thorax/abdomen |
It's messy create pdf
~/cushing-flowchart/flowchart_pdf.py
"""
Cushing Syndrome Investigation Flowchart – clean A3 landscape PDF
Uses ReportLab only.
"""
from reportlab.lib.pagesizes import A3, landscape
from reportlab.pdfgen import canvas
from reportlab.lib.colors import HexColor, white, black
from reportlab.lib.units import mm
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
import math, os
OUT = "/home/daytona/workspace/cushing-flowchart/Cushing_Syndrome_Flowchart.pdf"
# ── Page setup ─────────────────────────────────────────────────────────────
PW, PH = landscape(A3) # 420 x 297 mm → 1191 x 842 pt
c = canvas.Canvas(OUT, pagesize=(PW, PH))
# ── Palette ────────────────────────────────────────────────────────────────
BG = HexColor("#0D1B2A")
HDR = HexColor("#0A3D5C")
PH1_COL = HexColor("#1A6B8A")
PH2_COL = HexColor("#8B4513")
PH3A_COL = HexColor("#4527A0")
PH3B_COL = HexColor("#2E7D32")
NORM_COL = HexColor("#1B5E20")
ABNORM = HexColor("#7B1818")
STEP_DARK = HexColor("#0B2D44")
DIAM_COL = HexColor("#0E3A56")
DIAM2_COL = HexColor("#3E2000")
ARROW_C = HexColor("#64B5F6")
LABEL_YES = HexColor("#A5D6A7")
LABEL_NO = HexColor("#EF9A9A")
WHITE = white
BODY_TXT = HexColor("#E3F2FD")
FAINT = HexColor("#90CAF9")
# ── Helpers ────────────────────────────────────────────────────────────────
def rounded_rect(cx, cy, w, h, r, fill, stroke=None, lw=0.5):
"""Draw rounded rectangle centred at (cx,cy)."""
x, y = cx - w/2, cy - h/2
c.setFillColor(fill)
if stroke:
c.setStrokeColor(stroke)
c.setLineWidth(lw)
else:
c.setStrokeColor(fill)
c.setLineWidth(0)
c.roundRect(x, y, w, h, r, fill=1, stroke=1 if stroke else 0)
def diamond(cx, cy, w, h, fill):
pts = [(cx, cy+h/2),(cx+w/2, cy),(cx, cy-h/2),(cx-w/2, cy)]
c.setFillColor(fill)
c.setStrokeColor(HexColor("#AAAAAA"))
c.setLineWidth(0.4)
p = c.beginPath()
p.moveTo(*pts[0])
for pt in pts[1:]: p.lineTo(*pt)
p.close()
c.drawPath(p, fill=1, stroke=1)
def text_in_box(cx, cy, lines, sizes, colors, bold_flags, line_gap=2):
"""Render multi-line centred text at (cx,cy). lines/sizes/colors/bold_flags are parallel lists."""
total_h = sum(s + line_gap for s in sizes)
y_start = cy + total_h/2 - sizes[0]
for i, (txt, sz, col, bld) in enumerate(zip(lines, sizes, colors, bold_flags)):
c.setFont("Helvetica-Bold" if bld else "Helvetica", sz)
c.setFillColor(col)
c.drawCentredString(cx, y_start - i*(sz + line_gap), txt)
def arrow(x1,y1,x2,y2, color=ARROW_C, lw=1.2):
"""Draw arrowed line from (x1,y1) to (x2,y2)."""
c.setStrokeColor(color)
c.setLineWidth(lw)
c.line(x1, y1, x2, y2)
# arrowhead
angle = math.atan2(y2-y1, x2-x1)
asz = 5
for da in (0.4, -0.4):
ex = x2 - asz*math.cos(angle-da)
ey = y2 - asz*math.sin(angle-da)
c.line(x2, y2, ex, ey)
def elbow_down_right(x1,y1, x2,y2, color=ARROW_C):
"""Go down from (x1,y1) to (x1,y2), then right to (x2,y2)."""
c.setStrokeColor(color)
c.setLineWidth(1.1)
c.line(x1, y1, x1, y2)
arrow(x1, y2, x2, y2, color)
def elbow_right_down(x1,y1, x2,y2, color=ARROW_C):
"""Go right from (x1,y1) to (x2,y1), then down to (x2,y2)."""
c.setStrokeColor(color)
c.setLineWidth(1.1)
c.line(x1, y1, x2, y1)
arrow(x2, y1, x2, y2, color)
def lbl(x, y, txt, col=FAINT, sz=6.5, bold=False):
c.setFont("Helvetica-Bold" if bold else "Helvetica", sz)
c.setFillColor(col)
c.drawCentredString(x, y, txt)
# ── Background ─────────────────────────────────────────────────────────────
c.setFillColor(BG)
c.rect(0, 0, PW, PH, fill=1, stroke=0)
# ── Title bar ──────────────────────────────────────────────────────────────
c.setFillColor(HDR)
c.rect(0, PH-28, PW, 28, fill=1, stroke=0)
c.setFont("Helvetica-Bold", 13)
c.setFillColor(WHITE)
c.drawCentredString(PW/2, PH-19, "Cushing Syndrome: Investigation & Localisation Flowchart")
# ── Footer ─────────────────────────────────────────────────────────────────
c.setFillColor(HDR)
c.rect(0, 0, PW, 14, fill=1, stroke=0)
c.setFont("Helvetica", 6)
c.setFillColor(FAINT)
c.drawCentredString(PW/2, 4,
"DST = Dexamethasone Suppression Test | UFC = Urinary Free Cortisol | "
"ACTH = Adrenocorticotrophic Hormone | CRH = Corticotropin-Releasing Hormone | "
"IPSS = Inferior Petrosal Sinus Sampling")
# ══════════════════════════════════════════════════════════════════════════════
# LAYOUT (all coords in points, origin bottom-left)
# Page: 1191 × 842 pt usable: y 14 → 814 (800 pt tall)
# Three column groups:
# Phase 1: x 15 – 290 cx 152
# Phase 2: x 305 – 530 cx 417
# Phase 3A: x 545 – 770 cx 657
# Phase 3B: x 785 – 1176 cx 980
# ══════════════════════════════════════════════════════════════════════════════
USABLE_TOP = PH - 30 # 812
USABLE_BOT = 16
# ── Phase banners ─────────────────────────────────────────────────────────
banner_y = USABLE_TOP - 20
banner_h = 16
banners = [
(15, 275, PH1_COL, "PHASE 1 — Screening"),
(305, 225, PH2_COL, "PHASE 2 — Diagnostic"),
(540, 636, PH3A_COL,"PHASE 3A — Localisation: ACTH Not Detectable"),
(785, 391, PH3B_COL,"PHASE 3B — Localisation: ACTH Detectable"),
]
for bx, bw, bc, bt in banners:
c.setFillColor(bc)
c.roundRect(bx, banner_y - banner_h, bw, banner_h, 4, fill=1, stroke=0)
c.setFont("Helvetica-Bold", 7.5)
c.setFillColor(WHITE)
c.drawCentredString(bx + bw/2, banner_y - banner_h + 5, bt)
# ─────────────────────────────────────────────────────────────────────────
# Helper: draw a standard node (rounded rect + multiline text)
# ─────────────────────────────────────────────────────────────────────────
def node(cx, cy, w, h, fill, title, body_lines=None, title_sz=8, body_sz=7, r=5):
rounded_rect(cx, cy, w, h, r, fill, stroke=HexColor("#AAAAAA"), lw=0.4)
if body_lines:
# title at top
c.setFont("Helvetica-Bold", title_sz)
c.setFillColor(WHITE)
top_y = cy + h/2 - title_sz - 3
c.drawCentredString(cx, top_y, title)
# body lines
c.setFont("Helvetica", body_sz)
c.setFillColor(BODY_TXT)
for i, bl in enumerate(body_lines):
c.drawCentredString(cx, top_y - (title_sz+2) - i*(body_sz+2), bl)
else:
c.setFont("Helvetica-Bold", title_sz)
c.setFillColor(WHITE)
c.drawCentredString(cx, cy - title_sz/2 + 1, title)
# ══════════════════════════════════════════════════════════════════════════
# PHASE 1
# ══════════════════════════════════════════════════════════════════════════
P1CX = 152
BW1 = 255 # box width
# Step 1 box
S1_CY = banner_y - 50
S1_H = 68
rounded_rect(P1CX, S1_CY, BW1, S1_H, 5, PH1_COL, HexColor("#AAAAAA"), 0.4)
c.setFont("Helvetica-Bold", 8)
c.setFillColor(WHITE)
c.drawCentredString(P1CX, S1_CY + S1_H/2 - 11, "STEP 1 — Initial Screening")
lines1 = [
"Overnight DST: 1 mg at midnight → cortisol at 09:00 h",
"OR 24-hour Urinary Free Cortisol collection",
"OR Check diurnal variation (midnight vs. morning cortisol)",
]
c.setFont("Helvetica", 7)
c.setFillColor(BODY_TXT)
for i, l in enumerate(lines1):
c.drawCentredString(P1CX, S1_CY + S1_H/2 - 25 - i*10, l)
# Arrow down
A1Y1 = S1_CY - S1_H/2
A1Y2 = A1Y1 - 12
arrow(P1CX, A1Y1, P1CX, A1Y2)
# Step 2 header
S2_CY = A1Y2 - 14
S2_H = 16
rounded_rect(P1CX, S2_CY, BW1, S2_H, 4, STEP_DARK, HexColor("#AAAAAA"), 0.4)
c.setFont("Helvetica-Bold", 7.5)
c.setFillColor(WHITE)
c.drawCentredString(P1CX, S2_CY - 3.5, "STEP 2 — Evaluate Results")
# Arrow down to diamond
A2Y1 = S2_CY - S2_H/2
DIAM1_CY = A2Y1 - 26
DIAM1_W, DIAM1_H = 200, 38
arrow(P1CX, A2Y1, P1CX, DIAM1_CY + DIAM1_H/2)
diamond(P1CX, DIAM1_CY, DIAM1_W, DIAM1_H, DIAM_COL)
c.setFont("Helvetica-Bold", 8)
c.setFillColor(WHITE)
c.drawCentredString(P1CX, DIAM1_CY + 3, "Cortisol suppressed?")
# YES branch → Normal (left)
NRM_CX = P1CX - 72
NRM_CY = DIAM1_CY - 60
NRM_W, NRM_H = 112, 44
arrow(P1CX - DIAM1_W/2, DIAM1_CY, NRM_CX + NRM_W/2, DIAM1_CY)
arrow(NRM_CX, DIAM1_CY, NRM_CX, NRM_CY + NRM_H/2)
lbl(P1CX - DIAM1_W/2 - 18, DIAM1_CY + 3, "YES", LABEL_YES, 7, True)
rounded_rect(NRM_CX, NRM_CY, NRM_W, NRM_H, 5, NORM_COL, HexColor("#AAAAAA"), 0.4)
c.setFont("Helvetica-Bold", 8.5)
c.setFillColor(WHITE)
c.drawCentredString(NRM_CX, NRM_CY + 7, "NORMAL")
c.setFont("Helvetica", 7)
c.setFillColor(BODY_TXT)
c.drawCentredString(NRM_CX, NRM_CY - 4, "Cortisol < 50 nmol/L")
c.drawCentredString(NRM_CX, NRM_CY - 14, "or UFC < 280 nmol/24h")
# NO branch → Abnormal (right of diamond)
ABN_CX = P1CX + 72
ABN_CY = DIAM1_CY - 60
ABN_W, ABN_H = 112, 36
arrow(P1CX + DIAM1_W/2, DIAM1_CY, ABN_CX + ABN_W/2, DIAM1_CY)
arrow(ABN_CX, DIAM1_CY, ABN_CX, ABN_CY + ABN_H/2)
lbl(P1CX + DIAM1_W/2 + 15, DIAM1_CY + 3, "NO", LABEL_NO, 7, True)
rounded_rect(ABN_CX, ABN_CY, ABN_W, ABN_H, 5, ABNORM, HexColor("#AAAAAA"), 0.4)
c.setFont("Helvetica-Bold", 8.5)
c.setFillColor(WHITE)
c.drawCentredString(ABN_CX, ABN_CY + 5, "ABNORMAL")
c.setFont("Helvetica", 7)
c.setFillColor(BODY_TXT)
c.drawCentredString(ABN_CX, ABN_CY - 7, "→ Proceed to Phase 2")
# Arrow from Abnormal → Phase 2
ABN_EXIT_Y = ABN_CY - ABN_H/2
P2_ENTRY_X = 305
# ══════════════════════════════════════════════════════════════════════════
# PHASE 2
# ══════════════════════════════════════════════════════════════════════════
P2CX = 417
BW2 = 200
# Connect Abnormal box → Phase 2 top
# Elbow: right from abnormal box then up to Phase2 Step1
P2_S1_CY = S1_CY # align vertically with Phase1 Step1
P2_S1_H = 68
# Right edge of abnormal box
ABN_RIGHT = ABN_CX + ABN_W/2
P2_TOP = P2_S1_CY + P2_S1_H/2
elbow_right_down(ABN_RIGHT, ABN_CY, P2CX, P2_TOP)
# LDDST box
rounded_rect(P2CX, P2_S1_CY, BW2, P2_S1_H, 5, PH2_COL, HexColor("#AAAAAA"), 0.4)
c.setFont("Helvetica-Bold", 8)
c.setFillColor(WHITE)
c.drawCentredString(P2CX, P2_S1_CY + P2_S1_H/2 - 11, "STEP 1 — Low-Dose DST (LDDST)")
lddst_lines = [
"0.5 mg dexamethasone q6h × 48 hours",
"Cortisol fails to suppress < 50 nmol/L",
"→ Cushing Syndrome CONFIRMED",
]
c.setFont("Helvetica", 7)
c.setFillColor(BODY_TXT)
for i, l in enumerate(lddst_lines):
c.drawCentredString(P2CX, P2_S1_CY + P2_S1_H/2 - 25 - i*10, l)
# Arrow down
arrow(P2CX, P2_S1_CY - P2_S1_H/2, P2CX, P2_S1_CY - P2_S1_H/2 - 10)
# Step 2 header
P2_S2_CY = P2_S1_CY - P2_S1_H/2 - 18
P2_S2_H = 16
rounded_rect(P2CX, P2_S2_CY, BW2, P2_S2_H, 4, STEP_DARK, HexColor("#AAAAAA"), 0.4)
c.setFont("Helvetica-Bold", 7.5)
c.setFillColor(WHITE)
c.drawCentredString(P2CX, P2_S2_CY - 3.5, "STEP 2 — Measure Plasma ACTH")
# Arrow to diamond
arrow(P2CX, P2_S2_CY - P2_S2_H/2, P2CX, P2_S2_CY - P2_S2_H/2 - 10)
DIAM2_CY = P2_S2_CY - P2_S2_H/2 - 30
DIAM2_W, DIAM2_H = 180, 38
diamond(P2CX, DIAM2_CY, DIAM2_W, DIAM2_H, DIAM2_COL)
c.setFont("Helvetica-Bold", 8)
c.setFillColor(WHITE)
c.drawCentredString(P2CX, DIAM2_CY + 3, "Plasma ACTH level?")
# ACTH Suppressed → left
ASUP_CX = P2CX - 65
ASUP_CY = DIAM2_CY - 60
ASUP_W, ASUP_H = 100, 48
arrow(P2CX - DIAM2_W/2, DIAM2_CY, ASUP_CX + ASUP_W/2, DIAM2_CY)
arrow(ASUP_CX, DIAM2_CY, ASUP_CX, ASUP_CY + ASUP_H/2)
lbl(P2CX - DIAM2_W/2 - 22, DIAM2_CY + 3, "SUPPRESSED", LABEL_NO, 6.5, True)
rounded_rect(ASUP_CX, ASUP_CY, ASUP_W, ASUP_H, 5, HexColor("#3B2B8C"), HexColor("#AAAAAA"), 0.4)
c.setFont("Helvetica-Bold", 7.5)
c.setFillColor(WHITE)
c.drawCentredString(ASUP_CX, ASUP_CY + 9, "Adrenal Disease")
c.setFont("Helvetica", 6.5)
c.setFillColor(BODY_TXT)
c.drawCentredString(ASUP_CX, ASUP_CY - 2, "Non-ACTH-dependent")
c.drawCentredString(ASUP_CX, ASUP_CY - 12, "Cushing Syndrome")
# ACTH Normal/Raised → right
ANRM_CX = P2CX + 65
ANRM_CY = DIAM2_CY - 60
ANRM_W, ANRM_H = 100, 48
arrow(P2CX + DIAM2_W/2, DIAM2_CY, ANRM_CX - ANRM_W/2, DIAM2_CY)
arrow(ANRM_CX, DIAM2_CY, ANRM_CX, ANRM_CY + ANRM_H/2)
lbl(P2CX + DIAM2_W/2 + 22, DIAM2_CY + 3, "NORMAL/↑", LABEL_YES, 6.5, True)
rounded_rect(ANRM_CX, ANRM_CY, ANRM_W, ANRM_H, 5, HexColor("#6B3300"), HexColor("#AAAAAA"), 0.4)
c.setFont("Helvetica-Bold", 7.5)
c.setFillColor(WHITE)
c.drawCentredString(ANRM_CX, ANRM_CY + 9, "ACTH-dependent")
c.setFont("Helvetica", 6.5)
c.setFillColor(BODY_TXT)
c.drawCentredString(ANRM_CX, ANRM_CY - 2, "Pituitary or")
c.drawCentredString(ANRM_CX, ANRM_CY - 12, "Ectopic source")
# ══════════════════════════════════════════════════════════════════════════
# PHASE 3A – ACTH Suppressed pathway (cx ~657)
# ══════════════════════════════════════════════════════════════════════════
P3A_CX = 657
BW3A = 200
P3A_ENTRY_Y = ASUP_CY - ASUP_H/2 # bottom of Adrenal Disease box
# Connector: from ASUP bottom → elbow right → Phase3A
elbow_down_right(ASUP_CX, P3A_ENTRY_Y,
P3A_CX, P3A_ENTRY_Y - 18)
# Pathway A header (at same top Y as Phase 2 LDDST)
P3A_TOP_CY = P2_S1_CY # align tops
P3A_HDR_H = 16
rounded_rect(P3A_CX, P3A_TOP_CY + P2_S1_H/2 - P3A_HDR_H/2,
BW3A, P3A_HDR_H, 4, PH3A_COL, HexColor("#AAAAAA"), 0.4)
c.setFont("Helvetica-Bold", 7.5)
c.setFillColor(WHITE)
c.drawCentredString(P3A_CX,
P3A_TOP_CY + P2_S1_H/2 - P3A_HDR_H/2 - 3.5,
"PATHWAY A — ACTH Not Detectable")
# We need to draw from entry downward; reorganise Phase 3A vertically
# Use a top-down column starting at fixed Y
P3A_Y = USABLE_TOP - 70 # same row as Step1 boxes
# Probable Cause box
PC_CY = P3A_Y - 18
PC_H = 16
rounded_rect(P3A_CX, PC_CY, BW3A, PC_H, 4, HexColor("#2A1E80"), HexColor("#AAAAAA"), 0.4)
c.setFont("Helvetica", 7)
c.setFillColor(BODY_TXT)
c.drawCentredString(P3A_CX, PC_CY - 3.5, "Probable Cause: Adrenal Gland Tumour")
arrow(P3A_CX, PC_CY - PC_H/2, P3A_CX, PC_CY - PC_H/2 - 10)
# CT/MRI Adrenal
IMG_CY = PC_CY - PC_H/2 - 22
IMG_H = 16
rounded_rect(P3A_CX, IMG_CY, BW3A, IMG_H, 4, HexColor("#1A1060"), HexColor("#AAAAAA"), 0.4)
c.setFont("Helvetica-Bold", 7.5)
c.setFillColor(WHITE)
c.drawCentredString(P3A_CX, IMG_CY - 3.5, "CT / MRI of Adrenal Glands")
arrow(P3A_CX, IMG_CY - IMG_H/2, P3A_CX, IMG_CY - IMG_H/2 - 10)
# Diamond: Lesion found?
DIAM3_CY = IMG_CY - IMG_H/2 - 28
DIAM3_W, DIAM3_H = 160, 36
diamond(P3A_CX, DIAM3_CY, DIAM3_W, DIAM3_H, HexColor("#120C50"))
c.setFont("Helvetica-Bold", 8)
c.setFillColor(WHITE)
c.drawCentredString(P3A_CX, DIAM3_CY + 3, "Lesion found?")
# YES → stops here (just label)
lbl(P3A_CX + DIAM3_W/2 + 12, DIAM3_CY + 3, "YES →", LABEL_YES, 7, True)
lbl(P3A_CX + DIAM3_W/2 + 40, DIAM3_CY + 3, "Treat accordingly", FAINT, 6.5)
# NO → Adrenal Vein Sampling
arrow(P3A_CX, DIAM3_CY - DIAM3_H/2, P3A_CX, DIAM3_CY - DIAM3_H/2 - 10)
lbl(P3A_CX - 18, DIAM3_CY - DIAM3_H/2 - 6, "NO", LABEL_NO, 7, True)
AVS_CY = DIAM3_CY - DIAM3_H/2 - 30
AVS_H = 34
rounded_rect(P3A_CX, AVS_CY, BW3A, AVS_H, 5, HexColor("#0D0840"), HexColor("#AAAAAA"), 0.4)
c.setFont("Helvetica-Bold", 8)
c.setFillColor(WHITE)
c.drawCentredString(P3A_CX, AVS_CY + 7, "Adrenal Vein Sampling")
c.setFont("Helvetica", 6.5)
c.setFillColor(BODY_TXT)
c.drawCentredString(P3A_CX, AVS_CY - 5, "If no lesion identified on imaging")
# Now draw the connector from ASUP/Phase3 entry to Pathway A header
# We'll draw from ASUP_CX bottom going right then down into P3A column at PC_CY+PC_H/2
ASUP_BOT = ASUP_CY - ASUP_H/2
PC_TOP = PC_CY + PC_H/2
c.setStrokeColor(ARROW_C)
c.setLineWidth(1.1)
c.line(ASUP_CX, ASUP_BOT, ASUP_CX, ASUP_BOT - 15)
c.line(ASUP_CX, ASUP_BOT - 15, P3A_CX, ASUP_BOT - 15)
arrow(P3A_CX, ASUP_BOT - 15, P3A_CX, PC_TOP)
# ══════════════════════════════════════════════════════════════════════════
# PHASE 3B – ACTH Normal/Raised pathway (cx ~980)
# ══════════════════════════════════════════════════════════════════════════
P3B_CX = 980
BW3B = 340
# Pathway B header
rounded_rect(P3B_CX, P3A_TOP_CY + P2_S1_H/2 - P3A_HDR_H/2,
BW3B, P3A_HDR_H, 4, PH3B_COL, HexColor("#AAAAAA"), 0.4)
c.setFont("Helvetica-Bold", 7.5)
c.setFillColor(WHITE)
c.drawCentredString(P3B_CX,
P3A_TOP_CY + P2_S1_H/2 - P3A_HDR_H/2 - 3.5,
"PATHWAY B — ACTH Detectable")
# High-dose DST / CRH box (align with Pathway A PC_CY)
HDB_CY = PC_CY
HDB_H = 28
rounded_rect(P3B_CX, HDB_CY, BW3B, HDB_H, 5, HexColor("#5E2E00"), HexColor("#AAAAAA"), 0.4)
c.setFont("Helvetica-Bold", 8)
c.setFillColor(WHITE)
c.drawCentredString(P3B_CX, HDB_CY + 5, "High-Dose DST (2 mg dexamethasone) OR CRH Stimulation Test")
c.setFont("Helvetica", 7)
c.setFillColor(BODY_TXT)
c.drawCentredString(P3B_CX, HDB_CY - 7, "Assess whether cortisol responds")
arrow(P3B_CX, HDB_CY - HDB_H/2, P3B_CX, HDB_CY - HDB_H/2 - 10)
# Diamond: Cortisol responds?
DIAM4_CY = HDB_CY - HDB_H/2 - 30
DIAM4_W, DIAM4_H = 200, 38
diamond(P3B_CX, DIAM4_CY, DIAM4_W, DIAM4_H, HexColor("#3B1A00"))
c.setFont("Helvetica-Bold", 8)
c.setFillColor(WHITE)
c.drawCentredString(P3B_CX, DIAM4_CY + 3, "Cortisol responds / suppresses?")
# ── Scenario 1: YES → Cushing's Disease (left branch) ─────────────────
SC1_CX = P3B_CX - 90
SC1_CY = DIAM4_CY - 60
SC1_W, SC1_H = 150, 44
arrow(P3B_CX - DIAM4_W/2, DIAM4_CY, SC1_CX + SC1_W/2, DIAM4_CY)
arrow(SC1_CX, DIAM4_CY, SC1_CX, SC1_CY + SC1_H/2)
lbl(P3B_CX - DIAM4_W/2 - 22, DIAM4_CY + 3, "YES", LABEL_YES, 7, True)
rounded_rect(SC1_CX, SC1_CY, SC1_W, SC1_H, 5, HexColor("#0D3D7A"), HexColor("#AAAAAA"), 0.4)
c.setFont("Helvetica-Bold", 8.5)
c.setFillColor(WHITE)
c.drawCentredString(SC1_CX, SC1_CY + 9, "Cushing's Disease")
c.setFont("Helvetica", 7)
c.setFillColor(BODY_TXT)
c.drawCentredString(SC1_CX, SC1_CY - 3, "Pituitary cause likely")
c.drawCentredString(SC1_CX, SC1_CY - 13, "(ACTH-secreting adenoma)")
arrow(SC1_CX, SC1_CY - SC1_H/2, SC1_CX, SC1_CY - SC1_H/2 - 10)
MRI_P_CY = SC1_CY - SC1_H/2 - 30
MRI_P_H = 36
rounded_rect(SC1_CX, MRI_P_CY, SC1_W, MRI_P_H, 5, HexColor("#08295E"), HexColor("#AAAAAA"), 0.4)
c.setFont("Helvetica-Bold", 7.5)
c.setFillColor(WHITE)
c.drawCentredString(SC1_CX, MRI_P_CY + 8, "MRI Pituitary Gland")
c.setFont("Helvetica", 6.5)
c.setFillColor(BODY_TXT)
c.drawCentredString(SC1_CX, MRI_P_CY - 3, "± Bilateral inferior petrosal")
c.drawCentredString(SC1_CX, MRI_P_CY - 13, "sinus sampling (IPSS)")
# ── Scenario 2: NO → Ectopic ACTH (right branch) ──────────────────────
SC2_CX = P3B_CX + 90
SC2_CY = DIAM4_CY - 60
SC2_W, SC2_H = 150, 44
arrow(P3B_CX + DIAM4_W/2, DIAM4_CY, SC2_CX - SC2_W/2, DIAM4_CY)
arrow(SC2_CX, DIAM4_CY, SC2_CX, SC2_CY + SC2_H/2)
lbl(P3B_CX + DIAM4_W/2 + 22, DIAM4_CY + 3, "NO", LABEL_NO, 7, True)
rounded_rect(SC2_CX, SC2_CY, SC2_W, SC2_H, 5, HexColor("#4A0070"), HexColor("#AAAAAA"), 0.4)
c.setFont("Helvetica-Bold", 8.5)
c.setFillColor(WHITE)
c.drawCentredString(SC2_CX, SC2_CY + 9, "Ectopic ACTH Secretion")
c.setFont("Helvetica", 7)
c.setFillColor(BODY_TXT)
c.drawCentredString(SC2_CX, SC2_CY - 3, "e.g. Small Cell Lung Carcinoma")
c.drawCentredString(SC2_CX, SC2_CY - 13, "Carcinoid, Phaeochromocytoma")
arrow(SC2_CX, SC2_CY - SC2_H/2, SC2_CX, SC2_CY - SC2_H/2 - 10)
CT_CY = SC2_CY - SC2_H/2 - 30
CT_H = 28
rounded_rect(SC2_CX, CT_CY, SC2_W, CT_H, 5, HexColor("#300050"), HexColor("#AAAAAA"), 0.4)
c.setFont("Helvetica-Bold", 7.5)
c.setFillColor(WHITE)
c.drawCentredString(SC2_CX, CT_CY + 6, "IV Contrast CT")
c.setFont("Helvetica", 7)
c.setFillColor(BODY_TXT)
c.drawCentredString(SC2_CX, CT_CY - 6, "Chest, Abdomen & Pelvis")
arrow(SC2_CX, CT_CY - CT_H/2, SC2_CX, CT_CY - CT_H/2 - 10)
MRI_T_CY = CT_CY - CT_H/2 - 28
MRI_T_H = 28
rounded_rect(SC2_CX, MRI_T_CY, SC2_W, MRI_T_H, 5, HexColor("#200038"), HexColor("#AAAAAA"), 0.4)
c.setFont("Helvetica-Bold", 7.5)
c.setFillColor(WHITE)
c.drawCentredString(SC2_CX, MRI_T_CY + 6, "MRI Neck, Thorax & Abdomen")
c.setFont("Helvetica", 7)
c.setFillColor(BODY_TXT)
c.drawCentredString(SC2_CX, MRI_T_CY - 5, "Locate ectopic ACTH source")
# Connector from ANRM to Phase 3B
ANRM_BOT = ANRM_CY - ANRM_H/2
HDB_TOP = HDB_CY + HDB_H/2
c.setStrokeColor(ARROW_C)
c.setLineWidth(1.1)
c.line(ANRM_CX, ANRM_BOT, ANRM_CX, ANRM_BOT - 15)
c.line(ANRM_CX, ANRM_BOT - 15, P3B_CX, ANRM_BOT - 15)
arrow(P3B_CX, ANRM_BOT - 15, P3B_CX, HDB_TOP)
# ── Save ───────────────────────────────────────────────────────────────────
c.showPage()
c.save()
print(f"✅ Saved: {OUT}")
cd /home/daytona/workspace/cushing-flowchart && python3 flowchart_pdf.py 2>&1
ls -lh /home/daytona/workspace/cushing-flowchart/Cushing_Syndrome_Flowchart.pdf
Cushing Syndrome Flowchart
PDF Document · PDF
| Column | Content |
|---|---|
| Phase 1 (teal) | Step 1 screening box → Step 2 evaluate → diamond (suppressed?) → Normal ✅ left / Abnormal ❌ right |
| Phase 2 (amber) | LDDST confirmation → Plasma ACTH measurement → diamond (ACTH level?) → Suppressed left / Normal-Raised right |
| Phase 3A (purple) | ACTH not detectable → Adrenal tumour → CT/MRI adrenals → diamond (lesion?) → YES treated / NO → Adrenal vein sampling |
| Phase 3B (green) | ACTH detectable → High-dose DST / CRH → diamond (responds?) → YES: Cushing's Disease → MRI pituitary ± IPSS / NO: Ectopic ACTH → CT chest/abdomen/pelvis → MRI neck/thorax/abdomen |