I'm a 4th year MBBS student Create a A4 size presentation of 5 pages on the topic with pictures from the web "Atypical forms of cardiomyopathy in children and adolescents."
atypical cardiomyopathy children adolescents types overview 2024
left ventricular non-compaction cardiomyopathy pediatric echocardiogram
arrhythmogenic right ventricular cardiomyopathy ARVC pediatric
restrictive cardiomyopathy children MRI cardiac
Takotsubo stress cardiomyopathy apical ballooning echocardiogram
mkdir -p /home/daytona/workspace/atypical-cardiomyopathy-pptx && ls /home/daytona/workspace/atypical-cardiomyopathy-pptx
~/atypical-cardiomyopathy-pptx/fetch_and_build.js
const { execSync } = require("child_process");
const pptxgen = require("pptxgenjs");
const fs = require("fs");
// βββ Image URLs ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
const IMAGE_URLS = [
// Slide 2 β LVNC echo
"https://cdn.orris.care/cdss_images/pmc_clinical_VQA_94d0d4c659ecda38390bba36342535f0c5d3d9d51c431a093333d40eb61dd304.jpg",
// Slide 3 β ARVC cardiac MRI
"https://cdn.orris.care/cdss_images/pmc_clinical_VQA_ccef375d42502a4932535f5fd1be880aeaf424994e8a3739b42f1dba5c0d308a.jpg",
// Slide 4 β Restrictive CM MRI biatrial
"https://cdn.orris.care/cdss_images/pmc_clinical_VQA_4838389ce1d33d1c58d78e76614730c9a7c01379e2204c189baea185bef7bb11.jpg",
// Slide 5 β Takotsubo echo
"https://cdn.orris.care/cdss_images/pmc_clinical_VQA_c6021993840345b8856726d8526734bbd273e014a562a1a7c11bf144d093da75.jpg",
];
console.log("Fetching images...");
const raw = execSync(
`node /home/daytona/skills/shared/scripts/fetch_images.js ${IMAGE_URLS.map((u) => `"${u}"`).join(" ")}`
).toString();
const images = JSON.parse(raw);
console.log("Images fetched:", images.map((i) => (i.error ? "ERROR: " + i.error : "OK")));
// βββ Palette ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
const NAVY = "0B1F3A"; // dominant dark bg
const TEAL = "1A8C8A"; // accent/header
const WHITE = "FFFFFF";
const OFFWHITE= "EAF2F8";
const LIGHTGRAY="D6E4F0";
const GOLD = "F0B429";
const RED_ACCENT = "C0392B";
// A4 in inches: 8.27 x 11.69
const W = 8.27;
const H = 11.69;
let pres = new pptxgen();
pres.layout = "LAYOUT_4x3"; // we override dimensions below
pres.defineLayout({ name: "A4_PORTRAIT", width: W, height: H });
pres.layout = "A4_PORTRAIT";
pres.title = "Atypical Cardiomyopathy in Children and Adolescents";
pres.author = "4th Year MBBS Presentation";
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// SLIDE 1 β Title slide
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
{
let sl = pres.addSlide();
// Full dark background
sl.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: W, h: H, fill: { color: NAVY } });
// Top accent bar
sl.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: W, h: 0.12, fill: { color: TEAL } });
// Heart icon strip (decorative teal block left side)
sl.addShape(pres.ShapeType.rect, { x: 0, y: 0.12, w: 0.08, h: H - 0.12, fill: { color: TEAL } });
// Central title box
sl.addShape(pres.ShapeType.rect, { x: 0.4, y: 1.8, w: W - 0.8, h: 0.06, fill: { color: TEAL } });
// Main title
sl.addText("ATYPICAL FORMS OF\nCARDIOMYOPATHY", {
x: 0.4, y: 2.0, w: W - 0.8, h: 2.0,
fontSize: 40, bold: true, color: WHITE,
fontFace: "Calibri", align: "center",
valign: "middle", charSpacing: 2,
});
// Subtitle
sl.addText("in Children and Adolescents", {
x: 0.4, y: 3.85, w: W - 0.8, h: 0.7,
fontSize: 24, bold: false, color: GOLD,
fontFace: "Calibri", align: "center", italic: true,
});
// Divider line
sl.addShape(pres.ShapeType.rect, { x: 1.5, y: 4.6, w: W - 3.0, h: 0.04, fill: { color: TEAL } });
// Topics preview
const topics = [
"Left Ventricular Non-Compaction (LVNC)",
"Arrhythmogenic RV Cardiomyopathy (ARVC)",
"Restrictive Cardiomyopathy (RCM)",
"Takotsubo / Stress Cardiomyopathy",
"Arrhythmia-Induced Cardiomyopathy",
];
sl.addText(topics.map((t, i) => ({ text: (i === topics.length - 1 ? t : t + "\n"), options: {} })), {
x: 0.8, y: 4.8, w: W - 1.6, h: 3.5,
fontSize: 14, color: OFFWHITE, fontFace: "Calibri",
align: "center", bullet: false, valign: "top",
});
// Bottom tag
sl.addShape(pres.ShapeType.rect, { x: 0, y: H - 0.55, w: W, h: 0.55, fill: { color: "0D2B4B" } });
sl.addText("4th Year MBBS Presentation | Pediatric Cardiology | 2026", {
x: 0.1, y: H - 0.52, w: W - 0.2, h: 0.45,
fontSize: 10, color: LIGHTGRAY, align: "center", fontFace: "Calibri",
});
}
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// Helper: slide background + header
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
function addSlideBase(pres, title, slideNum) {
let sl = pres.addSlide();
// Background
sl.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: W, h: H, fill: { color: "F5F9FC" } });
// Left accent bar
sl.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 0.08, h: H, fill: { color: TEAL } });
// Header band
sl.addShape(pres.ShapeType.rect, { x: 0.08, y: 0, w: W - 0.08, h: 0.95, fill: { color: NAVY } });
// Header title
sl.addText(title, {
x: 0.25, y: 0.08, w: W - 0.7, h: 0.78,
fontSize: 22, bold: true, color: WHITE, fontFace: "Calibri",
valign: "middle",
});
// Slide number badge
sl.addShape(pres.ShapeType.ellipse, { x: W - 0.55, y: 0.18, w: 0.38, h: 0.38, fill: { color: TEAL } });
sl.addText(`${slideNum}`, {
x: W - 0.55, y: 0.18, w: 0.38, h: 0.38,
fontSize: 13, bold: true, color: WHITE, align: "center", valign: "middle",
});
// Footer
sl.addShape(pres.ShapeType.rect, { x: 0, y: H - 0.38, w: W, h: 0.38, fill: { color: NAVY } });
sl.addText("Atypical Cardiomyopathy in Children & Adolescents | 4th Year MBBS", {
x: 0.1, y: H - 0.35, w: W - 0.2, h: 0.3,
fontSize: 9, color: LIGHTGRAY, align: "center", fontFace: "Calibri",
});
return sl;
}
function addSectionTag(sl, text) {
sl.addShape(pres.ShapeType.rect, { x: 0.22, y: 1.02, w: 2.4, h: 0.3, fill: { color: GOLD }, line: { type: "none" } });
sl.addText(text, {
x: 0.22, y: 1.02, w: 2.4, h: 0.3,
fontSize: 10, bold: true, color: NAVY, align: "center", valign: "middle",
});
}
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// SLIDE 2 β Left Ventricular Non-Compaction (LVNC)
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
{
let sl = addSlideBase(pres, "Left Ventricular Non-Compaction (LVNC)", 2);
addSectionTag(sl, "Atypical Cardiomyopathy #1");
// Left text column
const bulletData = [
{ h: true, text: "Definition" },
{ h: false, text: "Failure of normal myocardial compaction during embryogenesis β spongy, hypertrabeculated LV with deep intertrabecular recesses." },
{ h: true, text: "Epidemiology in Children" },
{ h: false, text: "3rd most common pediatric cardiomyopathy (~9% of cases). Annual incidence <0.1 per 100,000. Pediatric Cardiomyopathy Registry: 4.8% of 3,219 children." },
{ h: true, text: "Clinical Features" },
{ h: false, text: "Heart failure (dilated phenotype), arrhythmias (ventricular tachycardia, WPW), thromboembolic events, sudden cardiac death." },
{ h: true, text: "Diagnosis" },
{ h: false, text: "Echo: NC/C ratio >2:1 at end-systole (Jenni criteria). CMR: prevalence 15% vs 1% on echo. Color Doppler confirms flow in recesses." },
{ h: true, text: "Management" },
{ h: false, text: "HF therapy (ACEi/BB/diuretics), anticoagulation for thromboembolic risk, ICD if SCD risk, heart transplant for refractory cases." },
];
let items = [];
bulletData.forEach(b => {
if (b.h) {
items.push({ text: b.text, options: { bold: true, color: TEAL, fontSize: 12, breakLine: true } });
} else {
items.push({ text: b.text + "\n", options: { bold: false, color: "2C3E50", fontSize: 11 } });
}
});
sl.addText(items, {
x: 0.22, y: 1.4, w: 4.5, h: 9.6,
fontFace: "Calibri", valign: "top",
});
// Right: image
if (images[0] && !images[0].error) {
sl.addImage({ data: images[0].base64, x: 5.0, y: 1.4, w: 3.0, h: 2.6, sizing: { type: "contain", w: 3.0, h: 2.6 } });
}
// Image caption
sl.addText("Echo: LVNC β spongy LV with\nNC/C ratio >2:1 (Jenni criteria)", {
x: 5.0, y: 4.0, w: 3.0, h: 0.55,
fontSize: 9, color: "5D6D7E", italic: true, align: "center", fontFace: "Calibri",
});
// Key fact box
sl.addShape(pres.ShapeType.rect, { x: 5.0, y: 4.65, w: 3.0, h: 2.9, fill: { color: NAVY }, line: { type: "none" } });
sl.addText([
{ text: "KEY GENETICS\n", options: { bold: true, color: GOLD, fontSize: 11, breakLine: false } },
{ text: "MYH7, MYBPC3, LDB3, TAZ (tafazzin β Barth syndrome), SCN5A\n\n", options: { color: WHITE, fontSize: 10 } },
{ text: "PROGNOSIS\n", options: { bold: true, color: GOLD, fontSize: 11 } },
{ text: "Worse than DCM when symptomatic in infancy. Isolated LVNC with normal EF has favourable course.", options: { color: WHITE, fontSize: 10 } },
], {
x: 5.15, y: 4.75, w: 2.8, h: 2.7,
fontFace: "Calibri", valign: "top",
});
}
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// SLIDE 3 β ARVC
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
{
let sl = addSlideBase(pres, "Arrhythmogenic RV Cardiomyopathy (ARVC)", 3);
addSectionTag(sl, "Atypical Cardiomyopathy #2");
const bulletData = [
{ h: true, text: "Definition" },
{ h: false, text: "Progressive fibro-fatty replacement of the RV myocardium due to desmosomal protein mutations β RV dilation, aneurysm, lethal arrhythmias." },
{ h: true, text: "Genetics" },
{ h: false, text: "Autosomal dominant: PKP2 (most common), DSP, DSG2, DSC2, JUP. Penetrance ~40-50%; male sex and athletic training worsen phenotype." },
{ h: true, text: "Clinical Features in Adolescents" },
{ h: false, text: "Palpitations, syncope, sudden cardiac death during exercise. T-wave inversions in V1-V3, epsilon waves on ECG (25%). Frequent PVCs with LBBB morphology." },
{ h: true, text: "2010 Task Force Criteria" },
{ h: false, text: "Major/minor criteria: RV structure (echo/CMR), tissue characterization (fibrofatty), repolarization, depolarization (epsilon/SAECG), arrhythmia, family history." },
{ h: true, text: "Management" },
{ h: false, text: "Restrict exercise/competitive sports. Beta-blockers, sotalol, amiodarone. ICD for SCD prevention. Catheter ablation for refractory VT. Transplant in end-stage." },
];
let items = [];
bulletData.forEach(b => {
if (b.h) {
items.push({ text: b.text, options: { bold: true, color: TEAL, fontSize: 12, breakLine: true } });
} else {
items.push({ text: b.text + "\n", options: { bold: false, color: "2C3E50", fontSize: 11 } });
}
});
sl.addText(items, {
x: 0.22, y: 1.4, w: 4.5, h: 9.6,
fontFace: "Calibri", valign: "top",
});
if (images[1] && !images[1].error) {
sl.addImage({ data: images[1].base64, x: 5.0, y: 1.4, w: 3.0, h: 2.6, sizing: { type: "contain", w: 3.0, h: 2.6 } });
}
sl.addText("Cardiac MRI: RV dilation with\nfibro-fatty infiltration & aneurysm", {
x: 5.0, y: 4.05, w: 3.0, h: 0.55,
fontSize: 9, color: "5D6D7E", italic: true, align: "center", fontFace: "Calibri",
});
// Warning box
sl.addShape(pres.ShapeType.rect, { x: 5.0, y: 4.7, w: 3.0, h: 2.8, fill: { color: RED_ACCENT }, line: { type: "none" } });
sl.addText([
{ text: "β ATHLETE'S HEART vs ARVC\n", options: { bold: true, color: WHITE, fontSize: 11, breakLine: false } },
{ text: "Distinguish by: CMR late gadolinium enhancement (fibrosis), RV dysfunction, arrhythmia on exercise testing, family history, and genetic panel.\n\n", options: { color: WHITE, fontSize: 10 } },
{ text: "ARVC is the #1 cause of SCD in young athletes in Italy (Veneto region).", options: { color: WHITE, fontSize: 10, italic: true } },
], {
x: 5.12, y: 4.78, w: 2.8, h: 2.65,
fontFace: "Calibri", valign: "top",
});
}
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// SLIDE 4 β Restrictive Cardiomyopathy
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
{
let sl = addSlideBase(pres, "Restrictive Cardiomyopathy (RCM) in Children", 4);
addSectionTag(sl, "Atypical Cardiomyopathy #3");
const bulletData = [
{ h: true, text: "Definition" },
{ h: false, text: "Impaired ventricular filling (diastolic dysfunction) with normal or near-normal LV size and systolic function. Severe biatrial dilation." },
{ h: true, text: "Causes in Pediatrics" },
{ h: false, text: "Idiopathic (most common in children), sarcomeric mutations (TNNI3, MYH7, TPM1), storage disorders (Gaucher, Fabry, Pompe), amyloidosis (rare β systemic AA), hypereosinophilic syndrome, endomyocardial fibrosis." },
{ h: true, text: "Clinical Features" },
{ h: false, text: "Exercise intolerance, dyspnoea, peripheral oedema, ascites. Atrial fibrillation/flutter from massive atrial dilation. High risk of sudden death and thromboembolic stroke." },
{ h: true, text: "Diagnosis" },
{ h: false, text: "Echo: restrictive filling pattern (E/A >2, short DT <150ms). CMR: LGE in subendocardium (amyloid) or apex (EMF). Cardiac catheterisation: 'dip-and-plateau' sign." },
{ h: true, text: "Prognosis & Management" },
{ h: false, text: "Worst prognosis among pediatric CMs β median survival 2 years without transplant. Early referral for heart transplantation is the only curative option. Diuretics, anticoagulation as bridge." },
];
let items = [];
bulletData.forEach(b => {
if (b.h) {
items.push({ text: b.text, options: { bold: true, color: TEAL, fontSize: 12, breakLine: true } });
} else {
items.push({ text: b.text + "\n", options: { bold: false, color: "2C3E50", fontSize: 11 } });
}
});
sl.addText(items, {
x: 0.22, y: 1.4, w: 4.5, h: 9.6,
fontFace: "Calibri", valign: "top",
});
if (images[2] && !images[2].error) {
sl.addImage({ data: images[2].base64, x: 5.0, y: 1.4, w: 3.0, h: 2.6, sizing: { type: "contain", w: 3.0, h: 2.6 } });
}
sl.addText("CMR 4-chamber view: severe\nbiatrial dilation with normal ventricles", {
x: 5.0, y: 4.05, w: 3.0, h: 0.55,
fontSize: 9, color: "5D6D7E", italic: true, align: "center", fontFace: "Calibri",
});
// RCM vs CP box
sl.addShape(pres.ShapeType.rect, { x: 5.0, y: 4.7, w: 3.0, h: 2.8, fill: { color: NAVY }, line: { type: "none" } });
sl.addText([
{ text: "RCM vs CONSTRICTIVE PERICARDITIS\n", options: { bold: true, color: GOLD, fontSize: 10 } },
{ text: "RCM: ", options: { bold: true, color: WHITE, fontSize: 10 } },
{ text: "LGE+, BNPββ, no pericardial calcification, ventricular interdependence absent\n", options: { color: WHITE, fontSize: 10 } },
{ text: "CP: ", options: { bold: true, color: WHITE, fontSize: 10 } },
{ text: "Pericardial thickening >4mm, septal bounce, respiratory variation on Doppler, BNP normal\n\n", options: { color: WHITE, fontSize: 10 } },
{ text: "Always biopsy if storage disease suspected β specific enzyme replacement may be curative.", options: { color: OFFWHITE, fontSize: 10, italic: true } },
], {
x: 5.12, y: 4.78, w: 2.8, h: 2.65,
fontFace: "Calibri", valign: "top",
});
}
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// SLIDE 5 β Takotsubo + Arrhythmia-Induced
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
{
let sl = addSlideBase(pres, "Takotsubo & Arrhythmia-Induced Cardiomyopathy", 5);
addSectionTag(sl, "Atypical Cardiomyopathies #4 & #5");
// ββ LEFT COLUMN: Takotsubo ββ
sl.addShape(pres.ShapeType.rect, { x: 0.22, y: 1.4, w: 3.8, h: 0.32, fill: { color: TEAL } });
sl.addText("Takotsubo (Stress) Cardiomyopathy", {
x: 0.22, y: 1.4, w: 3.8, h: 0.32,
fontSize: 12, bold: true, color: WHITE, valign: "middle", fontFace: "Calibri",
});
const tako = [
{ h: false, text: "Transient hypocontractility of LV mid-apex with basal hyperkinesis, mimicking ACS in absence of obstructive CAD. 'Octopus-pot' appearance." },
{ h: true, text: "In Children/Adolescents:" },
{ h: false, text: "Triggered by emotional/physical stress, critical illness (catecholamine surge). More common in girls; associated with neurological events, sepsis, anesthesia." },
{ h: true, text: "Diagnosis:" },
{ h: false, text: "Echo: apical ballooning + basal hyperkinesis. CMRI confirms reversibility. Normal coronaries on CT/angiography. Transient troponin rise." },
{ h: true, text: "Treatment:" },
{ h: false, text: "Supportive β beta-blockers, ACEi. LVOTO complication: IV fluids, phenylephrine (avoid dobutamine). Full recovery in daysβweeks." },
];
let takoItems = [];
tako.forEach(b => {
if (b.h) {
takoItems.push({ text: b.text, options: { bold: true, color: TEAL, fontSize: 11, breakLine: true } });
} else {
takoItems.push({ text: b.text + "\n", options: { bold: false, color: "2C3E50", fontSize: 10.5 } });
}
});
sl.addText(takoItems, { x: 0.22, y: 1.78, w: 3.8, h: 4.5, fontFace: "Calibri", valign: "top" });
if (images[3] && !images[3].error) {
sl.addImage({ data: images[3].base64, x: 0.22, y: 6.35, w: 3.8, h: 2.85, sizing: { type: "contain", w: 3.8, h: 2.85 } });
}
sl.addText("Echo: Apical ballooning β hyperkinetic base\nvs. akinetic apex (Takotsubo pattern)", {
x: 0.22, y: 9.23, w: 3.8, h: 0.5,
fontSize: 8.5, color: "5D6D7E", italic: true, align: "center", fontFace: "Calibri",
});
// ββ Vertical divider ββ
sl.addShape(pres.ShapeType.rect, { x: 4.2, y: 1.38, w: 0.04, h: 8.4, fill: { color: TEAL } });
// ββ RIGHT COLUMN: Arrhythmia-Induced ββ
sl.addShape(pres.ShapeType.rect, { x: 4.38, y: 1.4, w: 3.7, h: 0.32, fill: { color: NAVY } });
sl.addText("Arrhythmia-Induced Cardiomyopathy", {
x: 4.38, y: 1.4, w: 3.7, h: 0.32,
fontSize: 12, bold: true, color: GOLD, valign: "middle", fontFace: "Calibri",
});
const arrhyth = [
{ h: false, text: "Sustained tachycardia (>115-120 bpm) β βfilling pressures, biventricular dysfunction, βcardiac output. Reversible if arrhythmia controlled within 1β6 months." },
{ h: true, text: "Causative Arrhythmias:" },
{ h: false, text: "Atrial tachycardia, AVRT (WPW), atrial flutter/fibrillation, PJRT (permanent junctional reciprocating tachycardia β most common cause in infants)." },
{ h: true, text: "PVC-Induced CM:" },
{ h: false, text: ">20,000 PVCs/24h β subclinical βLVEF. >10,000 PVCs/24h β LV dilation. Higher proportion in children than adults; ectopy persists through follow-up." },
{ h: true, text: "Diagnosis:" },
{ h: false, text: "Echo: LV dilation + dysfunction. Normal LV diameter (<5.5cm) and absence of LVH. Recovery of function after arrhythmia control confirms diagnosis." },
{ h: true, text: "Treatment:" },
{ h: false, text: "Rate control (beta-blockers/digoxin), cardioversion, or radiofrequency catheter ablation. RFA achieves LVEF normalization in 47β100% of children." },
];
let arrItems = [];
arrhyth.forEach(b => {
if (b.h) {
arrItems.push({ text: b.text, options: { bold: true, color: TEAL, fontSize: 11, breakLine: true } });
} else {
arrItems.push({ text: b.text + "\n", options: { bold: false, color: "2C3E50", fontSize: 10.5 } });
}
});
sl.addText(arrItems, { x: 4.38, y: 1.78, w: 3.7, h: 7.55, fontFace: "Calibri", valign: "top" });
// Summary box bottom-right
sl.addShape(pres.ShapeType.rect, { x: 4.38, y: 9.23, w: 3.7, h: 0.5, fill: { color: GOLD } });
sl.addText("π‘ Key: Both are REVERSIBLE if treated promptly!", {
x: 4.38, y: 9.23, w: 3.7, h: 0.5,
fontSize: 10, bold: true, color: NAVY, align: "center", valign: "middle", fontFace: "Calibri",
});
}
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// WRITE FILE
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
const outPath = "/home/daytona/workspace/atypical-cardiomyopathy-pptx/Atypical_Cardiomyopathy_Children.pptx";
pres.writeFile({ fileName: outPath }).then(() => {
console.log("SUCCESS: " + outPath);
}).catch(err => {
console.error("ERROR:", err);
process.exit(1);
});
cd /home/daytona/workspace/atypical-cardiomyopathy-pptx && node fetch_and_build.js 2>&1
ls -lh /home/daytona/workspace/atypical-cardiomyopathy-pptx/Atypical_Cardiomyopathy_Children.pptx
Atypical Cardiomyopathy Children
Presentation Β· PPTX
| Slide | Topic | Image Included |
|---|---|---|
| 1 | Title Slide β Navy/teal design with topic overview | β |
| 2 | Left Ventricular Non-Compaction (LVNC) β embryology, epidemiology, Jenni echo criteria, genetics (TAZ/Barth, MYH7), management | Echo: NC/C ratio >2:1, spongy LV |
| 3 | Arrhythmogenic RV Cardiomyopathy (ARVC) β PKP2/DSP genetics, 2010 Task Force criteria, athlete SCD risk, RFA/ICD | Cardiac MRI: RV dilation + fibro-fatty infiltration |
| 4 | Restrictive Cardiomyopathy (RCM) β idiopathic vs storage diseases, biatrial dilation, RCM vs constrictive pericarditis table, transplant indication | CMR: severe biatrial dilation, normal ventricles |
| 5 | Takotsubo + Arrhythmia-Induced CM β apical ballooning, catecholamine surge, PVC burden thresholds, PJRT in infants, RFA outcomes | Echo: apical ballooning + base hyperkinesis |
" Early signs of bacterial endocarditis" do the same for this topic but with different designs
Osler nodes Janeway lesions Roth spots infective endocarditis clinical signs
splinter hemorrhages fingernails bacterial endocarditis
Roth spots retinal hemorrhage endocarditis fundoscopy
echocardiogram vegetation valve bacterial endocarditis
~/bacterial-endocarditis-pptx/build.js
const { execSync } = require("child_process");
const pptxgen = require("pptxgenjs");
// βββ Image URLs ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
const IMAGE_URLS = [
// Slide 2 β Osler nodes + Janeway lesions (both panels)
"https://cdn.orris.care/cdss_images/pmc_clinical_VQA_e976019a0225cf65305a83e04c661b869c91fc1a1c081353d64bd55257cfd5b7.jpg",
// Slide 3 β Splinter hemorrhages
"https://cdn.orris.care/cdss_images/pmc_clinical_VQA_f39f57251a2aebaa4c68e0b611f646821477b630b89eae6b3f649cfec3af7768.jpg",
// Slide 4 β Roth spots fundoscopy
"https://cdn.orris.care/cdss_images/pmc_clinical_VQA_44bc2468a6d50055ec0bb7f17affd359d3bc1a3197692bac6e6be1922471b8df.jpg",
// Slide 5 β TEE vegetation
"https://cdn.orris.care/cdss_images/pmc_clinical_VQA_2a4239f94edaccf0e0c864ca05f4d90205bb1712c39841c1ebc36d066c4a0e34.jpg",
];
console.log("Fetching images...");
const raw = execSync(
`node /home/daytona/skills/shared/scripts/fetch_images.js ${IMAGE_URLS.map((u) => `"${u}"`).join(" ")}`
).toString();
const imgs = JSON.parse(raw);
console.log("Images:", imgs.map((i) => (i.error ? "ERR:" + i.error : "OK")));
// βββ Design System ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// Warm forensic/clinical palette β very different from previous navy/teal
const CRIMSON = "8B1A1A"; // dominant dark red
const CREAM = "FDF6EC"; // warm off-white background
const GOLD = "C8973A"; // warm gold accent
const CHARCOAL = "2B2B2B"; // body text
const RUST = "B24C2F"; // secondary accent
const PALE_RED = "F5E6E0"; // light section tint
const WHITE = "FFFFFF";
const DARK_CREAM= "EEE0CC";
const W = 8.27; // A4 portrait
const H = 11.69;
let pres = new pptxgen();
pres.defineLayout({ name: "A4P", width: W, height: H });
pres.layout = "A4P";
pres.title = "Early Signs of Bacterial Endocarditis";
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// SLIDE 1 β TITLE (warm vellum-and-ink aesthetic)
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
{
const sl = pres.addSlide();
// Warm cream background
sl.addShape(pres.ShapeType.rect, { x:0, y:0, w:W, h:H, fill:{color:CREAM} });
// Bold crimson top band
sl.addShape(pres.ShapeType.rect, { x:0, y:0, w:W, h:1.7, fill:{color:CRIMSON} });
// Diagonal decorative element β top-right corner triangle (simulated via thin tall rect)
sl.addShape(pres.ShapeType.rect, { x:W-0.5, y:0, w:0.5, h:H, fill:{color:"6B1212"} });
// Gold horizontal rule under top band
sl.addShape(pres.ShapeType.rect, { x:0, y:1.7, w:W-0.5, h:0.06, fill:{color:GOLD} });
// White title text on crimson
sl.addText("EARLY SIGNS OF", {
x:0.35, y:0.12, w:W-0.9, h:0.65,
fontSize:32, bold:true, color:WHITE, fontFace:"Georgia",
align:"left", charSpacing:4,
});
sl.addText("BACTERIAL ENDOCARDITIS", {
x:0.35, y:0.7, w:W-0.9, h:0.85,
fontSize:38, bold:true, color:GOLD, fontFace:"Georgia",
align:"left", charSpacing:2,
});
// Subtitle band
sl.addShape(pres.ShapeType.rect, { x:0.35, y:1.9, w:W-0.9, h:0.55, fill:{color:PALE_RED} });
sl.addText("Recognition Β· Diagnosis Β· Clinical Pearls", {
x:0.35, y:1.9, w:W-0.9, h:0.55,
fontSize:15, bold:false, color:CRIMSON, fontFace:"Georgia",
italic:true, align:"center", valign:"middle",
});
// Slide outline β numbered cards
const topics = [
["01", "Overview & Pathogenesis"],
["02", "Cutaneous Signs β Osler Nodes & Janeway Lesions"],
["03", "Peripheral Signs β Splinter Hemorrhages & Clubbing"],
["04", "Ocular Signs β Roth Spots & Conjunctival Petechiae"],
["05", "Cardiac Signs, Duke Criteria & Diagnosis"],
];
topics.forEach(([num, text], i) => {
const yPos = 2.65 + i * 1.4;
// Card background
sl.addShape(pres.ShapeType.rect, { x:0.35, y:yPos, w:W-0.9, h:1.2, fill:{color:WHITE}, line:{color:"D9C8B4", pt:1} });
// Number badge
sl.addShape(pres.ShapeType.rect, { x:0.35, y:yPos, w:0.55, h:1.2, fill:{color:CRIMSON} });
sl.addText(num, {
x:0.35, y:yPos, w:0.55, h:1.2,
fontSize:20, bold:true, color:WHITE, align:"center", valign:"middle", fontFace:"Georgia",
});
// Topic text
sl.addText(text, {
x:1.0, y:yPos+0.3, w:W-1.6, h:0.6,
fontSize:14, bold:false, color:CHARCOAL, fontFace:"Calibri", valign:"middle",
});
});
// Footer
sl.addShape(pres.ShapeType.rect, { x:0, y:H-0.42, w:W-0.5, h:0.42, fill:{color:DARK_CREAM} });
sl.addText("4th Year MBBS Β· Infectious Diseases & Cardiology Β· 2026", {
x:0.2, y:H-0.38, w:W-0.8, h:0.32,
fontSize:9, color:RUST, align:"center", fontFace:"Calibri",
});
}
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// Helper: base slide with side-panel layout
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
function makeBase(slideNum, titleLine1, titleLine2) {
const sl = pres.addSlide();
// Cream background
sl.addShape(pres.ShapeType.rect, { x:0, y:0, w:W, h:H, fill:{color:CREAM} });
// Right stripe
sl.addShape(pres.ShapeType.rect, { x:W-0.5, y:0, w:0.5, h:H, fill:{color:CRIMSON} });
// Gold top rule
sl.addShape(pres.ShapeType.rect, { x:0, y:0, w:W-0.5, h:0.06, fill:{color:GOLD} });
// Header area (rust left sidebar + title)
sl.addShape(pres.ShapeType.rect, { x:0, y:0.06, w:0.55, h:1.3, fill:{color:RUST} });
// Slide number in sidebar
sl.addText(`0${slideNum}`, {
x:0, y:0.06, w:0.55, h:0.65,
fontSize:26, bold:true, color:WHITE, align:"center", valign:"middle", fontFace:"Georgia",
});
sl.addShape(pres.ShapeType.rect, { x:0.1, y:0.72, w:0.35, h:0.03, fill:{color:GOLD} });
sl.addText("of 5", {
x:0, y:0.76, w:0.55, h:0.35,
fontSize:9, color:DARK_CREAM, align:"center", fontFace:"Calibri",
});
// Title lines
sl.addText(titleLine1, {
x:0.7, y:0.1, w:W-1.35, h:0.52,
fontSize:11, bold:false, color:RUST, fontFace:"Calibri", italic:true, valign:"bottom",
});
sl.addText(titleLine2, {
x:0.7, y:0.56, w:W-1.35, h:0.72,
fontSize:24, bold:true, color:CRIMSON, fontFace:"Georgia", valign:"top",
});
// Underline rule
sl.addShape(pres.ShapeType.rect, { x:0.7, y:1.28, w:W-1.3, h:0.04, fill:{color:GOLD} });
// Footer
sl.addShape(pres.ShapeType.rect, { x:0, y:H-0.38, w:W-0.5, h:0.38, fill:{color:DARK_CREAM} });
sl.addText("Early Signs of Bacterial Endocarditis Β· 4th Year MBBS", {
x:0.2, y:H-0.34, w:W-0.8, h:0.28,
fontSize:8.5, color:RUST, align:"center", fontFace:"Calibri",
});
return sl;
}
// Small section pill label
function addPill(sl, x, y, w, text, bg = CRIMSON) {
sl.addShape(pres.ShapeType.rect, { x, y, w, h:0.28, fill:{color:bg}, line:{type:"none"} });
sl.addText(text, { x, y, w, h:0.28, fontSize:9, bold:true, color:WHITE, align:"center", valign:"middle", fontFace:"Calibri" });
}
// Styled bullet block
function bulletBlock(sl, items, x, y, w, h) {
const rich = [];
items.forEach(item => {
if (item.heading) {
rich.push({ text: item.text, options: { bold:true, color:CRIMSON, fontSize:12, breakLine:true, fontFace:"Georgia" } });
} else {
rich.push({ text: item.text + "\n", options: { bold:false, color:CHARCOAL, fontSize:11, fontFace:"Calibri" } });
}
});
sl.addText(rich, { x, y, w, h, valign:"top" });
}
// Info box (dark)
function infoBox(sl, x, y, w, h, label, bodyLines) {
sl.addShape(pres.ShapeType.rect, { x, y, w, h, fill:{color:CRIMSON}, line:{type:"none"} });
sl.addShape(pres.ShapeType.rect, { x, y, w, h:0.3, fill:{color:GOLD}, line:{type:"none"} });
sl.addText(label, { x:x+0.08, y, w:w-0.15, h:0.28, fontSize:10, bold:true, color:CRIMSON, valign:"middle", fontFace:"Georgia" });
const rich = bodyLines.map((l, i) => ({
text: l + (i < bodyLines.length-1 ? "\n" : ""),
options: { color:WHITE, fontSize:10, fontFace:"Calibri" }
}));
sl.addText(rich, { x:x+0.1, y:y+0.33, w:w-0.2, h:h-0.4, valign:"top" });
}
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// SLIDE 2 β Cutaneous Signs
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
{
const sl = makeBase(2, "CUTANEOUS MANIFESTATIONS", "Osler Nodes & Janeway Lesions");
addPill(sl, 0.7, 1.38, 2.6, "EARLY PERIPHERAL SIGNS", RUST);
// Image β left side, tall
if (imgs[0] && !imgs[0].error) {
sl.addImage({ data:imgs[0].base64, x:0.7, y:1.75, w:3.4, h:3.2, sizing:{type:"contain",w:3.4,h:3.2} });
}
sl.addShape(pres.ShapeType.rect, { x:0.7, y:4.97, w:3.4, h:0.44, fill:{color:PALE_RED} });
sl.addText("Panel A: Janeway lesions (plantar)\nPanel B: Osler nodes (digital pulp)", {
x:0.7, y:4.97, w:3.4, h:0.44, fontSize:8.5, color:RUST, italic:true, align:"center", fontFace:"Calibri", valign:"middle",
});
// Right column: Osler Nodes
sl.addShape(pres.ShapeType.rect, { x:4.3, y:1.38, w:3.4, h:0.3, fill:{color:CRIMSON} });
sl.addText("OSLER NODES", { x:4.3, y:1.38, w:3.4, h:0.3, fontSize:11, bold:true, color:GOLD, align:"center", valign:"middle", fontFace:"Georgia" });
bulletBlock(sl, [
{ heading:true, text:"Character" },
{ text:"Painful, tender, erythematous-violaceous nodules on fingertip pulp, toe pads, thenar/hypothenar eminences." },
{ heading:true, text:"Mechanism" },
{ text:"Immune complexβmediated microvasculitis. Transient β resolve in days." },
{ heading:true, text:"Significance" },
{ text:"MINOR Duke criterion. Seen in subacute IE (Strep. viridans)." },
], sl, 4.3, 1.72, 3.4, 3.1);
// Right column: Janeway Lesions
sl.addShape(pres.ShapeType.rect, { x:4.3, y:4.85, w:3.4, h:0.3, fill:{color:RUST} });
sl.addText("JANEWAY LESIONS", { x:4.3, y:4.85, w:3.4, h:0.3, fontSize:11, bold:true, color:WHITE, align:"center", valign:"middle", fontFace:"Georgia" });
bulletBlock(sl, [
{ heading:true, text:"Character" },
{ text:"Painless, irregular, hemorrhagic macules/microabscesses. Palms and soles." },
{ heading:true, text:"Mechanism" },
{ text:"Septic microemboli β dermal microabscesses with neutrophilic infiltrate." },
{ heading:true, text:"Significance" },
{ text:"MINOR Duke criterion. More common in ACUTE IE (S. aureus)." },
], sl, 4.3, 5.18, 3.4, 3.0);
infoBox(sl, 0.7, 5.5, 3.4, 2.65,
"OSLER vs JANEWAY β KEY DISTINCTION",
[
"Osler: PAINFUL β immune-mediated β subacute",
"Janeway: PAINLESS β embolic β acute",
"",
"Both = minor Duke criteria",
"Prevalence: each seen in ~10β20% of IE cases",
]
);
sl.addText("Source: Robbins & Kumar Basic Pathology, 10th Ed; Fitzpatrick's Dermatology", {
x:0.7, y:H-0.68, w:W-1.3, h:0.25, fontSize:7.5, color:"888888", italic:true, fontFace:"Calibri",
});
}
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// SLIDE 3 β Peripheral Signs
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
{
const sl = makeBase(3, "PERIPHERAL VASCULAR SIGNS", "Splinter Hemorrhages & Digital Clubbing");
addPill(sl, 0.7, 1.38, 2.6, "NAIL & DIGITAL EXAMINATION", RUST);
if (imgs[1] && !imgs[1].error) {
sl.addImage({ data:imgs[1].base64, x:0.7, y:1.76, w:3.4, h:3.0, sizing:{type:"contain",w:3.4,h:3.0} });
}
sl.addShape(pres.ShapeType.rect, { x:0.7, y:4.78, w:3.4, h:0.4, fill:{color:PALE_RED} });
sl.addText("Splinter hemorrhages β linear dark-red\nstreaks in distal nail beds (blue circles)", {
x:0.7, y:4.78, w:3.4, h:0.4, fontSize:8.5, color:RUST, italic:true, align:"center", fontFace:"Calibri", valign:"middle",
});
bulletBlock(sl, [
{ heading:true, text:"Splinter Hemorrhages" },
{ text:"Dark-red/brown linear streaks running longitudinally under nail plate. Distal location more specific for IE; proximal often from trauma." },
{ heading:true, text:"Mechanism" },
{ text:"Microthromboemboli from vegetations β subungual capillary rupture. Also immune complex vasculitis in subacute IE." },
{ heading:true, text:"Frequency" },
{ text:"~5β15% of IE. Non-specific β also seen in trauma, vasculitis, psoriasis, BTK inhibitors." },
{ heading:true, text:"Digital Clubbing" },
{ text:"Loss of nail-bed angle (Lovibond >180Β°). Schamroth window sign. Occurs in long-standing subacute/chronic IE. Reflects chronic hypoxia + periosteal new bone." },
{ heading:true, text:"Petechiae" },
{ text:"Pinpoint non-blanching haemorrhages: conjunctivae (lower tarsal), oral mucosa (palate), skin. Result of microemboli or immune vasculitis. Among the earliest signs." },
], sl, 4.3, 1.38, 3.4, 6.5);
infoBox(sl, 0.7, 5.28, 3.4, 2.9,
"CLINICAL EXAMINATION TIP",
[
"Always examine BOTH hands systematically:",
"β’ All 10 nail beds for splinter haemorrhages",
"β’ Fingertip pulp for Osler nodes",
"β’ Palm for Janeway lesions",
"β’ Schamroth test for clubbing",
"",
"Conjunctival petechiae: evert lower lid",
"β look along the tarsal conjunctiva",
]
);
sl.addText("Source: Braunwald's Heart Disease 12th Ed; Goldman-Cecil Medicine", {
x:0.7, y:H-0.68, w:W-1.3, h:0.25, fontSize:7.5, color:"888888", italic:true, fontFace:"Calibri",
});
}
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// SLIDE 4 β Ocular Signs
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
{
const sl = makeBase(4, "OCULAR MANIFESTATIONS", "Roth Spots & Conjunctival Signs");
addPill(sl, 0.7, 1.38, 2.3, "FUNDOSCOPY FINDINGS", RUST);
if (imgs[2] && !imgs[2].error) {
sl.addImage({ data:imgs[2].base64, x:0.7, y:1.76, w:3.4, h:3.1, sizing:{type:"contain",w:3.4,h:3.1} });
}
sl.addShape(pres.ShapeType.rect, { x:0.7, y:4.88, w:3.4, h:0.44, fill:{color:PALE_RED} });
sl.addText("Roth spot: white arrow = oval retinal\nhemorrhage with pale fibrin centre", {
x:0.7, y:4.88, w:3.4, h:0.44, fontSize:8.5, color:RUST, italic:true, align:"center", fontFace:"Calibri", valign:"middle",
});
bulletBlock(sl, [
{ heading:true, text:"Roth Spots" },
{ text:"Oval/flame-shaped retinal hemorrhages with white/pale centres (fibrin-platelet thrombus). Located near optic disc and posterior pole." },
{ heading:true, text:"Mechanism" },
{ text:"Septic microemboli to retinal capillaries β capillary rupture + fibrin-platelet plugging. Seen in 2β10% of IE." },
{ heading:true, text:"Pathology" },
{ text:"White centre = aggregated lymphocytes / fibrin (NOT pus). Seen also in leukaemia, severe anaemia, diabetes β NOT pathognomonic." },
{ heading:true, text:"Conjunctival Petechiae" },
{ text:"Bright-red pin-head spots on palpebral/bulbar conjunctiva. Among the earliest detectable peripheral signs. Microembolism or immune vasculitis." },
{ heading:true, text:"Other Ocular Signs" },
{ text:"Conjunctival haemorrhage, uveitis, endogenous ophthalmitis (septic emboli), visual field defect from embolic stroke in occipital cortex." },
], sl, 4.3, 1.38, 3.4, 6.7);
infoBox(sl, 0.7, 5.42, 3.4, 2.75,
"FUNDOSCOPY IN IE β WHEN TO DO IT?",
[
"Indication: fever + murmur + any visual symptom",
"Roth spot prevalence: 2β10% of all IE cases",
"More common in: subacute IE, younger patients",
"",
"Differential for white-centred haemorrhage:",
"Leukaemia Β· Anaemia Β· DM Β· Collagen disorders",
"HTN retinopathy Β· CMV retinitis (HIV)",
]
);
sl.addText("Source: Bradley & Daroff's Neurology; Robbins & Cotran Pathologic Basis of Disease", {
x:0.7, y:H-0.68, w:W-1.3, h:0.25, fontSize:7.5, color:"888888", italic:true, fontFace:"Calibri",
});
}
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// SLIDE 5 β Cardiac Signs + Duke Criteria + Diagnosis
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
{
const sl = makeBase(5, "CARDIAC SIGNS, DUKE CRITERIA & DIAGNOSIS", "How Early Signs Lead to Definitive Diagnosis");
addPill(sl, 0.7, 1.38, 2.5, "CARDIAC EXAMINATION", RUST);
if (imgs[3] && !imgs[3].error) {
sl.addImage({ data:imgs[3].base64, x:0.7, y:1.76, w:3.2, h:2.6, sizing:{type:"contain",w:3.2,h:2.6} });
}
sl.addShape(pres.ShapeType.rect, { x:0.7, y:4.38, w:3.2, h:0.44, fill:{color:PALE_RED} });
sl.addText("TEE: hyperechoic vegetation (red arrow)\non posterior mitral leaflet (P2 segment)", {
x:0.7, y:4.38, w:3.2, h:0.44, fontSize:8.5, color:RUST, italic:true, align:"center", fontFace:"Calibri", valign:"middle",
});
// Cardiac signs text
bulletBlock(sl, [
{ heading:true, text:"New / Changed Murmur" },
{ text:"Regurgitant murmur from valve destruction. Most common valves: MV (mitral) > AoV (aortic) > TV (right-sided, IVDU). MAJOR criterion." },
{ heading:true, text:"Heart Failure Signs" },
{ text:"Acute HF from valve rupture/destruction: bilateral creps, S3 gallop, elevated JVP. Indicates surgical urgency." },
{ heading:true, text:"Conduction Abnormalities" },
{ text:"New PR prolongation / AV block β perivalvular abscess extending to conduction system. Urgent surgical indicator." },
], sl, 4.3, 1.38, 3.4, 3.3);
// Duke Criteria Table
sl.addShape(pres.ShapeType.rect, { x:4.3, y:4.72, w:3.4, h:0.3, fill:{color:CRIMSON} });
sl.addText("MODIFIED DUKE CRITERIA (2023)", { x:4.3, y:4.72, w:3.4, h:0.3, fontSize:10, bold:true, color:GOLD, align:"center", valign:"middle", fontFace:"Georgia" });
const dukeRows = [
["MAJOR", "Positive blood cultures (β₯2 sets) Β· Echo vegetation/abscess Β· New regurgitation"],
["MINOR", "Predisposing condition Β· Fever >38Β°C Β· Vascular: emboli, Janeway, splinters Β· Immune: Roth, Osler, RF+ Β· Echo suspicious"],
["DEFINITE", "2 Major OR 1 Major + 3 Minor OR 5 Minor"],
["POSSIBLE", "1 Major + 1 Minor OR 3 Minor"],
];
dukeRows.forEach(([label, text], i) => {
const yy = 5.06 + i * 0.72;
const bg = i % 2 === 0 ? PALE_RED : WHITE;
sl.addShape(pres.ShapeType.rect, { x:4.3, y:yy, w:3.4, h:0.68, fill:{color:bg}, line:{color:"D9C8B4", pt:0.5} });
sl.addShape(pres.ShapeType.rect, { x:4.3, y:yy, w:0.75, h:0.68, fill:{color:RUST} });
sl.addText(label, { x:4.3, y:yy, w:0.75, h:0.68, fontSize:9, bold:true, color:WHITE, align:"center", valign:"middle", fontFace:"Georgia" });
sl.addText(text, { x:5.08, y:yy+0.06, w:2.55, h:0.56, fontSize:9, color:CHARCOAL, fontFace:"Calibri", valign:"top" });
});
// Bottom section: Early presentation red flags
sl.addShape(pres.ShapeType.rect, { x:0.7, y:4.9, w:3.2, h:0.3, fill:{color:GOLD} });
sl.addText("EARLY PRESENTATION RED FLAGS", { x:0.7, y:4.9, w:3.2, h:0.3, fontSize:10, bold:true, color:CRIMSON, align:"center", valign:"middle", fontFace:"Georgia" });
bulletBlock(sl, [
{ heading:false, text:"π‘ PUO (fever >38Β°C without source) + murmur β ALWAYS do echo + cultures" },
{ heading:false, text:"π IVDU patient + fever β right-sided IE until proven otherwise" },
{ heading:false, text:"π¦· Dental procedure + valvular disease + fever 2β4 weeks later" },
{ heading:false, text:"π©Ί New anaemia + weight loss + night sweats = subacute IE classic triad" },
{ heading:false, text:"π§ Young stroke + fever = embolic IE until proven otherwise" },
], sl, 0.7, 5.22, 3.2, 3.0);
sl.addText("Source: Braunwald's Heart Disease 12th Ed; Robbins & Kumar Basic Pathology 10th Ed", {
x:0.7, y:H-0.68, w:W-1.3, h:0.25, fontSize:7.5, color:"888888", italic:true, fontFace:"Calibri",
});
}
// βββ Write File βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
const out = "/home/daytona/workspace/bacterial-endocarditis-pptx/Early_Signs_Bacterial_Endocarditis.pptx";
pres.writeFile({ fileName: out }).then(() => {
console.log("SUCCESS:", out);
}).catch(err => { console.error("ERROR:", err); process.exit(1); });
mkdir -p /home/daytona/workspace/bacterial-endocarditis-pptx && node /home/daytona/workspace/bacterial-endocarditis-pptx/build.js 2>&1
ls -lh /home/daytona/workspace/bacterial-endocarditis-pptx/Early_Signs_Bacterial_Endocarditis.pptx
Early Signs Bacterial Endocarditis
Presentation Β· PPTX
| Feature | Previous (Cardiomyopathy) | This (Endocarditis) |
|---|---|---|
| Palette | Navy + teal + white | Crimson + warm cream + gold |
| Background | Dark navy | Warm vellum/cream |
| Typography | Calibri throughout | Georgia for headings + Calibri for body |
| Layout | Left text + right image | Numbered card system (title) + side-panel with header sidebar |
| Slide numbers | Teal circle badge | Rust sidebar tab with "0X of 5" |
| Accent style | Flat color bands | Gold rules + pale-red tint cards + dark info boxes |
| # | Topic | Clinical Image |
|---|---|---|
| 1 | Title β numbered card overview | β |
| 2 | Osler Nodes & Janeway Lesions β painful vs painless, immune vs embolic, minor Duke criteria | Clinical photo: Janeway lesions (sole) + Osler nodes (digit) β dual panel |
| 3 | Splinter Hemorrhages & Clubbing β nail exam technique, Schamroth test, conjunctival petechiae | Subungual splinter hemorrhages in multiple nails |
| 4 | Roth Spots & Ocular Signs β fundoscopy, fibrin-platelet centre, differential of white-centred haemorrhage | Fundus: Roth spot with white-arrow annotation |
| 5 | Cardiac Signs + Modified Duke Criteria β new murmur, AV block/abscess, early red-flag patterns | TEE: vegetation on posterior mitral leaflet |
The paragraph are not aligned properly create a better pdf
mkdir -p /home/daytona/workspace/bacterial-endocarditis-pdf && python3 -c "import reportlab; print(reportlab.Version)"
~/bacterial-endocarditis-pdf/build_pdf.py
"""
Early Signs of Bacterial Endocarditis β 5-page A4 PDF
Clean, properly typeset using ReportLab canvas with precise layout control.
"""
import urllib.request
import io
import os
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm, cm
from reportlab.lib.colors import HexColor, white, black
from reportlab.pdfgen import canvas
from reportlab.lib.utils import ImageReader
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.platypus import Paragraph, Frame, KeepInFrame
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
# ββ Page setup ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
W, H = A4 # 595.28 x 841.89 pts
OUT = "/home/daytona/workspace/bacterial-endocarditis-pdf/Early_Signs_Bacterial_Endocarditis.pdf"
# ββ Palette βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
CRIMSON = HexColor("#8B1A1A")
RUST = HexColor("#B24C2F")
GOLD = HexColor("#C8973A")
CREAM = HexColor("#FDF6EC")
PALE_RED = HexColor("#F5E6E0")
DARK_CREAM=HexColor("#EEE0CC")
CHARCOAL = HexColor("#2B2B2B")
WHITE_C = HexColor("#FFFFFF")
GREY_TXT = HexColor("#888888")
LIGHT_LINE=HexColor("#D9C8B4")
# ββ Margins βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ML = 18*mm # left margin (after sidebar)
MR = 14*mm
MT = 14*mm
MB = 14*mm
COL2_X = W/2 + 4*mm # right column start for 2-col layouts
# ββ Image download ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
IMAGE_URLS = {
"osler_janeway": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_e976019a0225cf65305a83e04c661b869c91fc1a1c081353d64bd55257cfd5b7.jpg",
"splinter": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_f39f57251a2aebaa4c68e0b611f646821477b630b89eae6b3f649cfec3af7768.jpg",
"roth": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_44bc2468a6d50055ec0bb7f17affd359d3bc1a3197692bac6e6be1922471b8df.jpg",
"tee": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_2a4239f94edaccf0e0c864ca05f4d90205bb1712c39841c1ebc36d066c4a0e34.jpg",
}
def fetch_image(url):
try:
req = urllib.request.Request(url, headers={"User-Agent":"Mozilla/5.0"})
data = urllib.request.urlopen(req, timeout=15).read()
return ImageReader(io.BytesIO(data))
except Exception as e:
print(f" IMG ERR {url[:60]}: {e}")
return None
print("Downloading images...")
IMGS = {k: fetch_image(v) for k, v in IMAGE_URLS.items()}
print("Done:", {k: "OK" if v else "FAIL" for k,v in IMGS.items()})
# ββ Canvas ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
c = canvas.Canvas(OUT, pagesize=A4)
c.setTitle("Early Signs of Bacterial Endocarditis")
c.setAuthor("4th Year MBBS Presentation 2026")
# ββ Helper primitives βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def rect(x, y, w, h, fill=None, stroke=None, radius=0):
c.saveState()
if fill: c.setFillColor(fill)
if stroke: c.setStrokeColor(stroke)
else: c.setStrokeColor(HexColor("#00000000"))
if radius:
c.roundRect(x, y, w, h, radius, fill=1 if fill else 0, stroke=1 if stroke else 0)
else:
c.rect(x, y, w, h, fill=1 if fill else 0, stroke=1 if stroke else 0)
c.restoreState()
def text(txt, x, y, size=10, color=CHARCOAL, bold=False, italic=False, align="left", maxw=None):
c.saveState()
c.setFillColor(color)
style = "Helvetica"
if bold and italic: style = "Helvetica-BoldOblique"
elif bold: style = "Helvetica-Bold"
elif italic: style = "Helvetica-Oblique"
c.setFont(style, size)
if align == "center" and maxw:
tw = c.stringWidth(txt, style, size)
x = x + (maxw - tw) / 2
elif align == "right" and maxw:
tw = c.stringWidth(txt, style, size)
x = x + maxw - tw
c.drawString(x, y, txt)
c.restoreState()
def line(x1, y1, x2, y2, color=GOLD, width=1):
c.saveState()
c.setStrokeColor(color)
c.setLineWidth(width)
c.line(x1, y1, x2, y2)
c.restoreState()
def draw_image(key, x, y, w, h):
img = IMGS.get(key)
if img:
# maintain aspect ratio inside box
iw, ih = img.getSize()
scale = min(w/iw, h/ih)
nw, nh = iw*scale, ih*scale
ox = x + (w - nw)/2
oy = y + (h - nh)/2
c.drawImage(img, ox, oy, nw, nh, preserveAspectRatio=True, mask="auto")
def page_background():
rect(0, 0, W, H, fill=CREAM)
def right_stripe():
rect(W - 10*mm, 0, 10*mm, H, fill=CRIMSON)
def gold_top_rule():
rect(0, H - 1.5*mm, W - 10*mm, 1.5*mm, fill=GOLD)
def footer(slide_num):
rect(0, 0, W - 10*mm, 9*mm, fill=DARK_CREAM)
text("Early Signs of Bacterial Endocarditis Β· 4th Year MBBS Β· 2026",
0, 3*mm, size=7, color=RUST, align="center", maxw=W-10*mm)
text(f"Page {slide_num} / 5",
W - 10*mm - 18*mm, 3*mm, size=7, color=WHITE_C)
def slide_header(num_str, tag_text, title_text):
"""Left sidebar number + tag line + big title with gold underrule"""
# Sidebar
rect(0, H - 38*mm, 12*mm, 38*mm, fill=RUST)
text(num_str, 1*mm, H - 20*mm, size=22, color=WHITE_C, bold=True, align="center", maxw=10*mm)
line(2*mm, H - 23*mm, 10*mm, H - 23*mm, color=GOLD, width=1.2)
text("of 5", 1*mm, H - 28*mm, size=7, color=DARK_CREAM, align="center", maxw=10*mm)
# Tag (small italic label)
text(tag_text, 15*mm, H - 12*mm, size=8.5, color=RUST, italic=True)
# Title
c.saveState()
c.setFont("Helvetica-Bold", 20)
c.setFillColor(CRIMSON)
c.drawString(15*mm, H - 25*mm, title_text)
c.restoreState()
# Gold underrule
line(15*mm, H - 29*mm, W - 12*mm, H - 29*mm, color=GOLD, width=1.5)
def section_badge(x, y, w, label, bg=CRIMSON):
rect(x, y - 5*mm, w, 6*mm, fill=bg, radius=1)
text(label, x, y - 3.5*mm, size=8, color=WHITE_C, bold=True, align="center", maxw=w)
def info_box(x, y, w, h, title, lines, title_bg=CRIMSON, body_bg=CRIMSON):
rect(x, y, w, h, fill=body_bg, radius=2)
rect(x, y + h - 7*mm, w, 7*mm, fill=GOLD, radius=2)
# Fix: draw gold box rounded only on top by overdrawing bottom corners
rect(x, y + h - 7*mm, w, 4*mm, fill=GOLD)
text(title, x + 3*mm, y + h - 5.5*mm, size=9, color=CRIMSON, bold=True)
ty = y + h - 12*mm
for ln in lines:
if ln == "":
ty -= 2.5*mm
continue
bold_flag = ln.startswith("β’") or ln.startswith("β")
text(ln, x + 4*mm, ty, size=8.5, color=WHITE_C, bold=False)
ty -= 5*mm
def content_block(entries, x, y_start, col_w, line_h_body=4.8*mm, line_h_head=5.5*mm):
"""Render heading+body pairs with tight, predictable spacing."""
cy = y_start
for entry in entries:
if entry.get("heading"):
c.saveState()
c.setFont("Helvetica-Bold", 10.5)
c.setFillColor(CRIMSON)
c.drawString(x, cy, entry["text"])
c.restoreState()
cy -= line_h_head
else:
# Word-wrap body text
words = entry["text"].split()
c.saveState()
c.setFont("Helvetica", 9.5)
c.setFillColor(CHARCOAL)
cw = c.stringWidth("M", "Helvetica", 9.5)
max_chars = int(col_w / (cw * 0.6))
current = ""
for w_word in words:
test = current + " " + w_word if current else w_word
if c.stringWidth(test, "Helvetica", 9.5) <= col_w - 2*mm:
current = test
else:
if current:
c.drawString(x + 3*mm, cy, current)
cy -= line_h_body
current = w_word
if current:
c.drawString(x + 3*mm, cy, current)
cy -= line_h_body
c.restoreState()
cy -= 1.5*mm # gap after body paragraph
return cy
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE 1 β TITLE
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
page_background()
right_stripe()
gold_top_rule()
# Top crimson band
rect(0, H - 52*mm, W - 10*mm, 52*mm, fill=CRIMSON)
# Title text
c.saveState()
c.setFont("Helvetica", 16)
c.setFillColor(WHITE_C)
c.drawString(15*mm, H - 20*mm, "EARLY SIGNS OF")
c.setFont("Helvetica-Bold", 28)
c.setFillColor(GOLD)
c.drawString(15*mm, H - 38*mm, "BACTERIAL ENDOCARDITIS")
c.restoreState()
# Subtitle on pale band
rect(0, H - 63*mm, W - 10*mm, 11*mm, fill=PALE_RED)
text("Recognition Β· Clinical Signs Β· Duke Criteria Β· Early Diagnosis",
15*mm, H - 57.5*mm, size=11, color=CRIMSON, italic=True)
line(15*mm, H - 65*mm, W - 12*mm, H - 65*mm, color=GOLD, width=1.2)
# Topic cards
topics = [
("01", "Cutaneous Signs β Osler Nodes & Janeway Lesions"),
("02", "Peripheral Signs β Splinter Haemorrhages & Clubbing"),
("03", "Ocular Signs β Roth Spots & Conjunctival Petechiae"),
("04", "Cardiac Signs, Duke Criteria & Definitive Diagnosis"),
]
CARD_H = 34*mm
CARD_W = W - 10*mm - 30*mm
cx0 = 15*mm
for i, (num, lbl) in enumerate(topics):
col = i % 2
row = i // 2
cx = cx0 + col * (CARD_W/2 + 5*mm)
cy = H - 70*mm - row*(CARD_H + 4*mm) - CARD_H
# Card bg
rect(cx, cy, CARD_W/2, CARD_H, fill=WHITE_C, stroke=LIGHT_LINE, radius=2)
c.setStrokeColor(LIGHT_LINE)
c.setLineWidth(0.5)
# Number badge
rect(cx, cy + CARD_H - 13*mm, CARD_W/2, 13*mm, fill=CRIMSON, radius=2)
# Fix rounded: square off bottom corners of badge
rect(cx, cy + CARD_H - 13*mm, CARD_W/2, 7*mm, fill=CRIMSON)
text(num, cx, cy + CARD_H - 9*mm, size=18, color=GOLD, bold=True,
align="center", maxw=CARD_W/2)
# Word-wrap label
c.saveState()
c.setFont("Helvetica", 9.5)
c.setFillColor(CHARCOAL)
words = lbl.split()
lines_out = []
cur = ""
for ww in words:
test = cur + " " + ww if cur else ww
if c.stringWidth(test, "Helvetica", 9.5) <= CARD_W/2 - 6*mm:
cur = test
else:
lines_out.append(cur)
cur = ww
if cur:
lines_out.append(cur)
for li, lo in enumerate(lines_out):
c.drawString(cx + 3*mm, cy + CARD_H - 18*mm - li*5*mm, lo)
c.restoreState()
# Intro paragraph
intro_y = H - 70*mm - 2*(CARD_H + 4*mm) - 10*mm
rect(15*mm, intro_y - 30*mm, W - 10*mm - 30*mm, 30*mm, fill=PALE_RED, radius=2)
intro_lines = [
"Infective endocarditis (IE) is a microbial infection of the cardiac valves or endocardium forming",
"thrombotic vegetations. The majority of cases are bacterial. Acute IE (S. aureus) progresses over",
"days; subacute IE (S. viridans) evolves over weeksβmonths. Early recognition of peripheral signs",
"and application of Modified Duke Criteria are essential for timely diagnosis and treatment.",
]
for li, ln in enumerate(intro_lines):
text(ln, 18*mm, intro_y - 10*mm - li*5*mm, size=9, color=CHARCOAL)
footer(1)
c.showPage()
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE 2 β Osler Nodes & Janeway Lesions
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
page_background()
right_stripe()
gold_top_rule()
footer(2)
slide_header("02", "CUTANEOUS MANIFESTATIONS", "Osler Nodes & Janeway Lesions")
TOP_Y = H - 34*mm # below header rule
IMG_W = 76*mm
IMG_H = 72*mm
TEXT_X = 15*mm
TEXT_W = W - 10*mm - 15*mm # full width for text columns
# ββ Left column: image ββ
IMG_X = 15*mm
draw_image("osler_janeway", IMG_X, TOP_Y - IMG_H, IMG_W, IMG_H)
# Caption box
rect(IMG_X, TOP_Y - IMG_H - 10*mm, IMG_W, 10*mm, fill=PALE_RED)
text("Panel A: Janeway lesions (plantar) Β· Panel B: Osler nodes (digit)",
IMG_X + 2*mm, TOP_Y - IMG_H - 6.5*mm, size=7.5, color=RUST, italic=True)
# ββ Right column: content ββ
RX = IMG_X + IMG_W + 6*mm
RW = W - 10*mm - RX
# OSLER NODES sub-header
rect(RX, TOP_Y - 7*mm, RW, 7*mm, fill=CRIMSON, radius=1)
text("OSLER NODES", RX, TOP_Y - 5*mm, size=10, color=GOLD, bold=True,
align="center", maxw=RW)
osler_entries = [
{"heading": True, "text": "Character"},
{"heading": False, "text": "Painful, tender, erythematous-violaceous subcutaneous nodules on fingertip pulp, toe pads, thenar/hypothenar eminences. Transient β resolve within days."},
{"heading": True, "text": "Mechanism"},
{"heading": False, "text": "Immune complexβmediated microvasculitis and septic microemboli in subacute IE."},
{"heading": True, "text": "Duke Significance"},
{"heading": False, "text": "MINOR criterion. Prevalence ~10β15% of IE. More common in subacute IE caused by S. viridans."},
]
content_block(osler_entries, RX + 2*mm, TOP_Y - 10*mm, RW)
# JANEWAY sub-header
J_Y = TOP_Y - 52*mm
rect(RX, J_Y - 1*mm, RW, 7*mm, fill=RUST, radius=1)
text("JANEWAY LESIONS", RX, J_Y + 1.5*mm, size=10, color=WHITE_C, bold=True,
align="center", maxw=RW)
janeway_entries = [
{"heading": True, "text": "Character"},
{"heading": False, "text": "Painless, irregular, haemorrhagic macules or microabscesses on palms and soles."},
{"heading": True, "text": "Mechanism"},
{"heading": False, "text": "Septic microemboli β dermal microabscesses with neutrophilic infiltrate."},
{"heading": True, "text": "Duke Significance"},
{"heading": False, "text": "MINOR criterion. More common in acute IE (S. aureus). ~5β10% prevalence."},
]
content_block(janeway_entries, RX + 2*mm, J_Y - 4*mm, RW)
# ββ Full-width comparison box ββ
BOX_Y = TOP_Y - IMG_H - 12*mm
BOX_H = 42*mm
rect(15*mm, BOX_Y - BOX_H, W - 10*mm - 30*mm, BOX_H, fill=CRIMSON, radius=2)
rect(15*mm, BOX_Y - 8*mm, W - 10*mm - 30*mm, 8*mm, fill=GOLD, radius=2)
rect(15*mm, BOX_Y - 8*mm, W - 10*mm - 30*mm, 4*mm, fill=GOLD)
text("OSLER vs JANEWAY β KEY DISTINCTION",
15*mm, BOX_Y - 6*mm, size=9.5, color=CRIMSON, bold=True)
comp_lines = [
("Osler Nodes:", "PAINFUL β immune complex β subacute IE (S. viridans)"),
("Janeway Lesions:", "PAINLESS β embolic/infective β acute IE (S. aureus)"),
("Both:", "Minor Duke criterion Β· Each seen in ~10β20% of IE cases"),
("Tip:", "Osler: press finger pad β patient flinches. Janeway: non-tender on palpation."),
]
LX = 18*mm
LY = BOX_Y - 12*mm
for label, desc in comp_lines:
c.saveState()
c.setFont("Helvetica-Bold", 9)
c.setFillColor(GOLD)
c.drawString(LX, LY, label)
lw = c.stringWidth(label, "Helvetica-Bold", 9)
c.setFont("Helvetica", 9)
c.setFillColor(WHITE_C)
c.drawString(LX + lw + 2*mm, LY, desc)
c.restoreState()
LY -= 6*mm
text("Source: Robbins & Kumar Basic Pathology 10th Ed Β· Fitzpatrick's Dermatology",
15*mm, 11*mm, size=7, color=GREY_TXT, italic=True)
c.showPage()
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE 3 β Splinter Haemorrhages & Peripheral Signs
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
page_background()
right_stripe()
gold_top_rule()
footer(3)
slide_header("03", "PERIPHERAL VASCULAR SIGNS", "Splinter Haemorrhages & Digital Signs")
TOP_Y = H - 34*mm
# Image β right side this time
IMG_W = 74*mm
IMG_H = 70*mm
IMG_X = W - 10*mm - IMG_W - 2*mm
draw_image("splinter", IMG_X, TOP_Y - IMG_H, IMG_W, IMG_H)
rect(IMG_X, TOP_Y - IMG_H - 9*mm, IMG_W, 9*mm, fill=PALE_RED)
text("Splinter haemorrhages β dark linear subungual",
IMG_X + 2*mm, TOP_Y - IMG_H - 4.5*mm, size=7.5, color=RUST, italic=True)
text("streaks (blue circles), multiple nails",
IMG_X + 2*mm, TOP_Y - IMG_H - 8.5*mm, size=7.5, color=RUST, italic=True)
# Left column content
LW = IMG_X - 18*mm - 5*mm
entries = [
{"heading": True, "text": "Splinter Haemorrhages"},
{"heading": False, "text": "Dark-red or brown linear streaks running longitudinally beneath the nail plate. Distal location is more specific for IE; proximal splinters often result from trauma."},
{"heading": True, "text": "Mechanism"},
{"heading": False, "text": "Microthromboemboli from cardiac vegetations lodge in subungual capillaries causing rupture. Immune complex vasculitis also contributes in subacute IE."},
{"heading": True, "text": "Frequency & Specificity"},
{"heading": False, "text": "Present in 5β15% of IE cases. Non-specific: also seen in trauma, psoriasis, vasculitis, BTK inhibitor therapy. Distal location + clinical context raises specificity."},
{"heading": True, "text": "Digital Clubbing"},
{"heading": False, "text": "Loss of nail-bed angle >180Β° (Lovibond). Schamroth window sign: absence of diamond-shaped window when opposing nails placed together. Appears in long-standing subacute IE β reflects chronic periosteal new bone and soft tissue change."},
{"heading": True, "text": "Petechiae (Earliest Sign)"},
{"heading": False, "text": "Pinpoint, non-blanching haemorrhages on conjunctivae (lower tarsal), oral mucosa (palate), and skin. Among the very first detectable peripheral signs of IE."},
]
content_block(entries, 15*mm, TOP_Y - 2*mm, LW, line_h_body=4.6*mm)
# Full-width examination tip box
EX_Y = TOP_Y - IMG_H - 12*mm
EX_H = 50*mm
EX_W = W - 10*mm - 30*mm
rect(15*mm, EX_Y - EX_H, EX_W, EX_H, fill=CRIMSON, radius=2)
rect(15*mm, EX_Y - 8*mm, EX_W, 8*mm, fill=GOLD, radius=2)
rect(15*mm, EX_Y - 8*mm, EX_W, 4*mm, fill=GOLD)
text("CLINICAL EXAMINATION CHECKLIST β HANDS & EYES",
18*mm, EX_Y - 6*mm, size=9.5, color=CRIMSON, bold=True)
exam_tips = [
"β’ Inspect ALL 10 nails for splinter haemorrhages (look distal first)",
"β’ Press each fingertip pulp bilaterally for Osler node tenderness",
"β’ Examine palms and soles for Janeway lesions (non-tender macules)",
"β’ Schamroth test: oppose nail dorsa β absent diamond = clubbing",
"β’ Evert lower eyelid: look along tarsal conjunctiva for petechiae",
"β’ Check oral palate under light for petechiae",
]
EL_Y = EX_Y - 13*mm
for tip in exam_tips:
text(tip, 18*mm, EL_Y, size=9, color=WHITE_C)
EL_Y -= 5.5*mm
text("Source: Braunwald's Heart Disease 12th Ed Β· Goldman-Cecil Medicine",
15*mm, 11*mm, size=7, color=GREY_TXT, italic=True)
c.showPage()
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE 4 β Roth Spots & Ocular Signs
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
page_background()
right_stripe()
gold_top_rule()
footer(4)
slide_header("04", "OCULAR MANIFESTATIONS", "Roth Spots & Fundoscopic Signs")
TOP_Y = H - 34*mm
IMG_W = 76*mm
IMG_H = 74*mm
IMG_X = 15*mm
draw_image("roth", IMG_X, TOP_Y - IMG_H, IMG_W, IMG_H)
rect(IMG_X, TOP_Y - IMG_H - 10*mm, IMG_W, 10*mm, fill=PALE_RED)
text("Fundus: Roth spot β oval retinal haemorrhage",
IMG_X + 2*mm, TOP_Y - IMG_H - 5*mm, size=7.5, color=RUST, italic=True)
text("with white fibrin-platelet centre (white arrow)",
IMG_X + 2*mm, TOP_Y - IMG_H - 9*mm, size=7.5, color=RUST, italic=True)
# Right column
RX = IMG_X + IMG_W + 6*mm
RW = W - 10*mm - RX
rect(RX, TOP_Y - 7*mm, RW, 7*mm, fill=CRIMSON, radius=1)
text("ROTH SPOTS", RX, TOP_Y - 5*mm, size=10, color=GOLD, bold=True,
align="center", maxw=RW)
roth_entries = [
{"heading": True, "text": "Definition"},
{"heading": False, "text": "Oval or flame-shaped retinal haemorrhages with a pale/white centre composed of fibrin and lymphocytes. Located near the optic disc and posterior pole."},
{"heading": True, "text": "Mechanism"},
{"heading": False, "text": "Septic microemboli occlude retinal capillaries causing rupture and local haemorrhage. The white centre = fibrin-platelet clot, NOT pus."},
{"heading": True, "text": "Frequency"},
{"heading": False, "text": "Seen in 2β10% of IE cases. More common in subacute forms. Specific but NOT pathognomonic."},
{"heading": True, "text": "Differential Diagnosis"},
{"heading": False, "text": "Leukaemia Β· Severe anaemia Β· Diabetes Β· Collagen vascular disease Β· Hypertensive retinopathy Β· CMV retinitis (HIV). Always correlate with blood cultures."},
]
content_block(roth_entries, RX + 2*mm, TOP_Y - 10*mm, RW)
# Full-width fundoscopy guide
FX = 15*mm
FY = TOP_Y - IMG_H - 12*mm
FH = 48*mm
FW = W - 10*mm - 30*mm
rect(FX, FY - FH, FW, FH, fill=CRIMSON, radius=2)
rect(FX, FY - 8*mm, FW, 8*mm, fill=GOLD, radius=2)
rect(FX, FY - 8*mm, FW, 4*mm, fill=GOLD)
text("FUNDOSCOPY IN IE β INDICATION & DIFFERENTIAL",
FX + 3*mm, FY - 6*mm, size=9.5, color=CRIMSON, bold=True)
fund_data = [
("Indication:", "Fever + new murmur + any visual symptom or floaters"),
("Prevalence:", "2β10% of IE Β· More common in younger patients, subacute course"),
("Conjunctival petechiae:", "Bright-red pin-head spots on tarsal conjunctiva β early sign, 5β15%"),
("Endogenous ophthalmitis:", "Rare but vision-threatening β septic emboli to vitreous/choroid"),
("Visual field defect:", "Embolic stroke in occipital cortex β rare, indicates embolisation"),
]
FL_Y = FY - 13*mm
for label, desc in fund_data:
c.saveState()
c.setFont("Helvetica-Bold", 9)
c.setFillColor(GOLD)
lw = c.stringWidth(label, "Helvetica-Bold", 9)
c.drawString(FX + 4*mm, FL_Y, label)
c.setFont("Helvetica", 9)
c.setFillColor(WHITE_C)
c.drawString(FX + 4*mm + lw + 1.5*mm, FL_Y, desc)
c.restoreState()
FL_Y -= 6*mm
text("Source: Bradley & Daroff's Neurology Β· Robbins & Cotran Pathologic Basis of Disease",
15*mm, 11*mm, size=7, color=GREY_TXT, italic=True)
c.showPage()
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE 5 β Cardiac Signs + Duke Criteria + Diagnosis
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
page_background()
right_stripe()
gold_top_rule()
footer(5)
slide_header("05", "CARDIAC SIGNS Β· DUKE CRITERIA Β· DIAGNOSIS", "How Early Signs Lead to Definitive Diagnosis")
TOP_Y = H - 34*mm
IMG_W = 72*mm
IMG_H = 60*mm
IMG_X = 15*mm
# ββ Image left ββ
draw_image("tee", IMG_X, TOP_Y - IMG_H, IMG_W, IMG_H)
rect(IMG_X, TOP_Y - IMG_H - 9*mm, IMG_W, 9*mm, fill=PALE_RED)
text("TEE: Vegetation (red arrow) on posterior",
IMG_X + 2*mm, TOP_Y - IMG_H - 4.5*mm, size=7.5, color=RUST, italic=True)
text("mitral valve leaflet (P2 segment)",
IMG_X + 2*mm, TOP_Y - IMG_H - 8.5*mm, size=7.5, color=RUST, italic=True)
# ββ Right column: cardiac signs ββ
RX = IMG_X + IMG_W + 6*mm
RW = W - 10*mm - RX
rect(RX, TOP_Y - 7*mm, RW, 7*mm, fill=CRIMSON, radius=1)
text("CARDIAC EXAMINATION SIGNS", RX, TOP_Y - 5*mm, size=9.5, color=GOLD, bold=True,
align="center", maxw=RW)
cardiac_entries = [
{"heading": True, "text": "New/Changed Murmur"},
{"heading": False, "text": "Regurgitant murmur from valve leaflet destruction or perforation. MV > AoV > TV. MAJOR Duke criterion."},
{"heading": True, "text": "Acute Heart Failure"},
{"heading": False, "text": "Bilateral basal crackles, S3 gallop, raised JVP from acute valvular incompetence. Indicates surgical urgency."},
{"heading": True, "text": "Conduction Defect"},
{"heading": False, "text": "New PR prolongation or AV block on ECG β perivalvular abscess eroding into conduction system. Urgent surgery indicator."},
{"heading": True, "text": "Splenomegaly"},
{"heading": False, "text": "Mild-moderate splenomegaly in 25β45% of subacute IE. Immune hyperplasia from chronic bacteraemia."},
]
content_block(cardiac_entries, RX + 2*mm, TOP_Y - 10*mm, RW)
# ββ Duke Criteria Table ββ
DX = 15*mm
DY = TOP_Y - IMG_H - 12*mm
DW = W - 10*mm - 30*mm
DH = 68*mm
rect(DX, DY - DH, DW, DH, fill=WHITE_C, stroke=LIGHT_LINE, radius=2)
# Header
rect(DX, DY - 9*mm, DW, 9*mm, fill=CRIMSON, radius=2)
rect(DX, DY - 9*mm, DW, 5*mm, fill=CRIMSON)
text("MODIFIED DUKE CRITERIA (ESC 2023)",
DX, DY - 7*mm, size=11, color=GOLD, bold=True,
align="center", maxw=DW)
# Column headers
col_w = [28*mm, 78*mm, 50*mm]
col_x = [DX + 2*mm, DX + 30*mm, DX + 110*mm]
rect(DX, DY - 18*mm, DW, 9*mm, fill=PALE_RED)
headers = ["Category", "Criteria", "Threshold"]
for i, (cx_val, hdr) in enumerate(zip(col_x, headers)):
text(hdr, cx_val, DY - 14.5*mm, size=9, color=CRIMSON, bold=True)
# Duke data rows
rows = [
("MAJOR\n(Γ2)", "1. Positive blood cultures:\n β₯2 sets with typical organism\n OR persistently positive\n2. Echo: vegetation / abscess /\n new dehiscence prosthesis\n OR new valvular regurgitation",
"2 Major =\nDEFINITE"),
("MINOR\n(Γ5)", "β’ Predisposing condition (valve disease, IVDU)\nβ’ Fever > 38Β°C\nβ’ Vascular: emboli, Janeway, pulm. infarcts,\n splinter haemorrhages, mycotic aneurysm\nβ’ Immunological: Roth spots, Osler nodes,\n GN, RF positive\nβ’ Echo suspicious (not major)",
"1 Major +\n3 Minor =\nDEFINITE\n\n1 Major +\n1 Minor OR\n3 Minor =\nPOSSIBLE"),
]
row_y = DY - 21*mm
for bg_i, (cat, crit, thresh) in enumerate(rows):
row_bg = WHITE_C if bg_i % 2 == 0 else PALE_RED
row_h = 28*mm
rect(DX, row_y - row_h, DW, row_h, fill=row_bg)
line(DX, row_y, DX + DW, row_y, color=LIGHT_LINE, width=0.5)
# Category column
rect(DX, row_y - row_h, 28*mm, row_h, fill=CRIMSON if bg_i==0 else RUST)
# Vertically center category text
cat_lines = cat.split("\n")
cat_start = row_y - row_h/2 + len(cat_lines)*2.5*mm
for cl in cat_lines:
text(cl, DX + 1.5*mm, cat_start, size=9, color=WHITE_C, bold=True,
align="center", maxw=25*mm)
cat_start -= 5*mm
# Criteria column
crit_lines = crit.split("\n")
crit_y = row_y - 5*mm
for cline in crit_lines:
text(cline, col_x[1], crit_y, size=8, color=CHARCOAL)
crit_y -= 4.5*mm
# Threshold column
thresh_lines = thresh.split("\n")
thr_y = row_y - 5*mm
for tl in thresh_lines:
text(tl, col_x[2], thr_y, size=8, color=CRIMSON, bold=True)
thr_y -= 4.5*mm
row_y -= row_h
# Bottom line
line(DX, row_y, DX + DW, row_y, color=LIGHT_LINE, width=0.5)
# ββ Early red-flag row ββ
RF_Y = DY - DH - 4*mm
RF_H = 30*mm
RF_W = W - 10*mm - 30*mm
rect(15*mm, RF_Y - RF_H, RF_W, RF_H, fill=CRIMSON, radius=2)
rect(15*mm, RF_Y - 7*mm, RF_W, 7*mm, fill=GOLD, radius=2)
rect(15*mm, RF_Y - 7*mm, RF_W, 4*mm, fill=GOLD)
text("EARLY RECOGNITION RED FLAGS",
18*mm, RF_Y - 5.5*mm, size=9.5, color=CRIMSON, bold=True)
flags = [
"Fever of unknown origin + any heart murmur β blood cultures + echo",
"IVDU + fever β right-sided IE (tricuspid) until proven otherwise",
"Dental procedure + valvular disease + fever 2β4 weeks later",
"New anaemia + weight loss + night sweats = classic subacute IE triad",
"Young patient + stroke + fever = embolic IE until proven otherwise",
]
RF_LY = RF_Y - 11*mm
for flag in flags:
text("β " + flag, 18*mm, RF_LY, size=8.5, color=WHITE_C)
RF_LY -= 5*mm
text("Source: Braunwald's Heart Disease 12th Ed Β· Robbins & Kumar Basic Pathology 10th Ed",
15*mm, 11*mm, size=7, color=GREY_TXT, italic=True)
c.showPage()
c.save()
print(f"\nβ PDF saved: {OUT}")
print(f" Size: {os.path.getsize(OUT) // 1024} KB")
cd /home/daytona/workspace/bacterial-endocarditis-pdf && python3 build_pdf.py 2>&1
Early Signs Bacterial Endocarditis
PDF Document Β· PDF
| Page | Content |
|---|---|
| 1 | Title with intro paragraph + 4 numbered topic cards |
| 2 | Osler Nodes vs Janeway Lesions β image left, two sub-sections right, comparison table full-width |
| 3 | Splinter Haemorrhages & Clubbing β image right, content left, examination checklist box |
| 4 | Roth Spots β fundus image left, mechanism + differential right, fundoscopy guide box |
| 5 | Cardiac signs + TEE image + full Modified Duke Criteria table + red-flag box |
Create with atleast 20 lines on each page and more pictures of newborns
neonatal infective endocarditis newborn infant echocardiogram vegetation
pediatric infant bacterial endocarditis clinical signs skin
Osler nodes Janeway lesions endocarditis palms soles
infective endocarditis aortic valve vegetation gross pathology
~/bacterial-endocarditis-pdf/build_pdf_v2.py
"""
Early Signs of Bacterial Endocarditis β Expanded 5-page A4 PDF
β’ 20+ text lines per page
β’ Multiple pictures per page (including neonatal/infant IE images)
β’ ReportLab canvas β pixel-perfect layout
"""
import urllib.request, io, os
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm
from reportlab.lib.colors import HexColor
from reportlab.pdfgen import canvas
from reportlab.lib.utils import ImageReader
W, H = A4 # 595.28 x 841.89 pt
OUT = "/home/daytona/workspace/bacterial-endocarditis-pdf/Early_Signs_Bacterial_Endocarditis_v2.pdf"
# ββ Palette βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
CRIMSON = HexColor("#8B1A1A")
RUST = HexColor("#B24C2F")
GOLD = HexColor("#C8973A")
CREAM = HexColor("#FDF6EC")
PALE_RED = HexColor("#F5E6E0")
DARK_CREAM= HexColor("#EEE0CC")
CHARCOAL = HexColor("#2B2B2B")
WHITE_C = HexColor("#FFFFFF")
GREY_TXT = HexColor("#777777")
LIGHT_LINE= HexColor("#D9C8B4")
NAVY = HexColor("#0B1F3A")
TEAL_DARK = HexColor("#1A5276")
# ββ Image manifest ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
URLS = {
# Neonatal / pediatric IE echo
"neo_echo1": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_6ec7e8c6d61b42bab383e9d4efe8442901c82e22e6089b3dc82a28f4399d1adc.jpg",
"neo_echo2": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_3d03bfa74d4142413d1b95a5460fd49e007d19c846451cd8b34afeffae731217.jpg",
# Cutaneous signs
"osler_janeway": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_e976019a0225cf65305a83e04c661b869c91fc1a1c081353d64bd55257cfd5b7.jpg",
"janeway_foot": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_bf34fe8925284ae9930ca816517d4e76f290f261a51eecb474bdcc63f78ae77b.jpg",
"osler_ankle": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_4534c655f9b921e9c49723d5fa184a222fe05ca0181702aa45297b408e313733.jpg",
"janeway_ped": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_4536e7b49d9093328341b3ff1a2df45397b993673f41e7117032f32a7e65ddd9.jpg",
# Splinter / nail
"splinter": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_f39f57251a2aebaa4c68e0b611f646821477b630b89eae6b3f649cfec3af7768.jpg",
"osler_finger": "https://cdn.orris.care/cdss_images/DermNetNZ_1760035737304_bead7f71-0684-424f-8183-9b058c93b273.jpg",
# Roth spots
"roth1": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_44bc2468a6d50055ec0bb7f17affd359d3bc1a3197692bac6e6be1922471b8df.jpg",
"roth2": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_02c8e18176ac6cdc92c623338476fe12abb6fae6eee4e216c10d54b3799aa0bd.jpg",
# TEE / gross pathology
"tee_mv": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_2a4239f94edaccf0e0c864ca05f4d90205bb1712c39841c1ebc36d066c4a0e34.jpg",
"gross_valve": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_d8a178b46ac26aab8385ce9e0414d91a6d37ee91a5a79c35ef4e9c77da146588.jpg",
"multi_valve": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_0c850e2453d711be69e34fe206f5250f801cf16eafb2465601bf591ab248864a.jpg",
}
def fetch(url):
try:
r = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
d = urllib.request.urlopen(r, timeout=15).read()
return ImageReader(io.BytesIO(d))
except Exception as e:
print(f" FAIL {url[-50:]}: {e}")
return None
print("Downloading images...")
IMGS = {k: fetch(v) for k, v in URLS.items()}
print({k: "OK" if v else "X" for k, v in IMGS.items()})
# ββ Canvas ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
c = canvas.Canvas(OUT, pagesize=A4)
c.setTitle("Early Signs of Bacterial Endocarditis")
# ββ Low-level drawing helpers βββββββββββββββββββββββββββββββββββββββββββββββββ
def bg():
c.setFillColor(CREAM)
c.rect(0, 0, W, H, fill=1, stroke=0)
def right_bar():
c.setFillColor(CRIMSON)
c.rect(W - 9*mm, 0, 9*mm, H, fill=1, stroke=0)
def top_rule():
c.setFillColor(GOLD)
c.rect(0, H - 1.5*mm, W - 9*mm, 1.5*mm, fill=1, stroke=0)
def footer_bar(pg):
c.setFillColor(DARK_CREAM)
c.rect(0, 0, W - 9*mm, 8.5*mm, fill=1, stroke=0)
c.setFont("Helvetica", 7)
c.setFillColor(RUST)
lbl = "Early Signs of Bacterial Endocarditis Β· Neonatal & Pediatric Aspects Β· 4th Year MBBS 2026"
c.drawCentredString((W - 9*mm) / 2, 3*mm, lbl)
c.setFont("Helvetica-Bold", 7.5)
c.setFillColor(WHITE_C)
c.drawRightString(W - 10*mm, 3*mm, f"{pg}/5")
def header(num, supertitle, title):
"""Left sidebar number tab + super + title + gold rule."""
c.setFillColor(RUST)
c.rect(0, H - 36*mm, 11*mm, 36*mm, fill=1, stroke=0)
c.setFont("Helvetica-Bold", 20)
c.setFillColor(WHITE_C)
c.drawCentredString(5.5*mm, H - 21*mm, num)
c.setFillColor(GOLD)
c.rect(1.5*mm, H - 24.5*mm, 8*mm, 0.8*mm, fill=1, stroke=0)
c.setFont("Helvetica", 7)
c.setFillColor(DARK_CREAM)
c.drawCentredString(5.5*mm, H - 27.5*mm, "of 5")
# Supertitle
c.setFont("Helvetica-Oblique", 9)
c.setFillColor(RUST)
c.drawString(14*mm, H - 12*mm, supertitle)
# Title
c.setFont("Helvetica-Bold", 21)
c.setFillColor(CRIMSON)
c.drawString(14*mm, H - 26*mm, title)
# Rule
c.setFillColor(GOLD)
c.rect(14*mm, H - 29*mm, W - 14*mm - 9*mm, 1.2*mm, fill=1, stroke=0)
def filled_rect(x, y, w, h, color, radius=0):
c.setFillColor(color)
c.setStrokeColor(HexColor("#00000000"))
if radius:
c.roundRect(x, y, w, h, radius, fill=1, stroke=0)
else:
c.rect(x, y, w, h, fill=1, stroke=0)
def outlined_rect(x, y, w, h, fill_color, stroke_color, lw=0.5):
c.setFillColor(fill_color)
c.setStrokeColor(stroke_color)
c.setLineWidth(lw)
c.rect(x, y, w, h, fill=1, stroke=1)
def txt(s, x, y, size=9.5, color=CHARCOAL, bold=False, italic=False):
c.saveState()
c.setFillColor(color)
font = "Helvetica-Bold" if bold else ("Helvetica-Oblique" if italic else "Helvetica")
if bold and italic: font = "Helvetica-BoldOblique"
c.setFont(font, size)
c.drawString(x, y, s)
c.restoreState()
def txt_c(s, cx, y, size=9.5, color=CHARCOAL, bold=False):
"""Centred on cx."""
font = "Helvetica-Bold" if bold else "Helvetica"
c.saveState()
c.setFont(font, size)
c.setFillColor(color)
c.drawCentredString(cx, y, s)
c.restoreState()
def hline(x1, y, x2, color=GOLD, lw=1):
c.setStrokeColor(color)
c.setLineWidth(lw)
c.line(x1, y, x2, y)
def place_img(key, x, y, w, h):
img = IMGS.get(key)
if not img: return
iw, ih = img.getSize()
sc = min(w / iw, h / ih)
nw, nh = iw * sc, ih * sc
c.drawImage(img, x + (w - nw) / 2, y + (h - nh) / 2, nw, nh,
preserveAspectRatio=True, mask="auto")
def img_box(key, x, y, w, h, caption1, caption2=""):
"""Draw image inside a styled card with caption below."""
outlined_rect(x, y, w, h + 11*mm, CREAM, LIGHT_LINE, 0.5)
place_img(key, x + 1*mm, y + 11*mm, w - 2*mm, h - 1*mm)
filled_rect(x, y, w, 11*mm, PALE_RED)
c.setFont("Helvetica-Oblique", 7.5)
c.setFillColor(RUST)
c.drawCentredString(x + w / 2, y + 7*mm, caption1)
if caption2:
c.drawCentredString(x + w / 2, y + 3.5*mm, caption2)
def section_pill(x, y, w, label, bg=CRIMSON):
filled_rect(x, y - 5*mm, w, 6*mm, bg, radius=1)
txt_c(label, x + w/2, y - 2.8*mm, size=8, color=WHITE_C, bold=True)
def wrap_text(lines_list, x, y, col_w, size=9.5, color=CHARCOAL,
line_h=5.2*mm, bold=False, indent=0):
"""Render a list of strings, word-wrapping each into col_w. Returns final y."""
font = "Helvetica-Bold" if bold else "Helvetica"
c.saveState()
c.setFont(font, size)
c.setFillColor(color)
cur_y = y
for raw_line in lines_list:
words = raw_line.split()
if not words:
cur_y -= line_h * 0.6
continue
cur_seg = ""
for word in words:
test = (cur_seg + " " + word).strip()
if c.stringWidth(test, font, size) <= col_w - indent:
cur_seg = test
else:
if cur_seg:
c.drawString(x + indent, cur_y, cur_seg)
cur_y -= line_h
cur_seg = word
if cur_seg:
c.drawString(x + indent, cur_y, cur_seg)
cur_y -= line_h
c.restoreState()
return cur_y
def label_body_block(entries, x, y, col_w,
lh_head=5.8*mm, lh_body=5*mm, gap=2*mm):
"""entries: list of {h: bool, text: str}. Returns final y."""
cy = y
for e in entries:
if e["h"]:
c.saveState()
c.setFont("Helvetica-Bold", 10.5)
c.setFillColor(CRIMSON)
c.drawString(x, cy, e["text"])
c.restoreState()
cy -= lh_head
else:
cy = wrap_text([e["text"]], x, cy, col_w, size=9.5,
color=CHARCOAL, line_h=lh_body, indent=3*mm)
cy -= gap
return cy
def info_box_dark(x, y, w, h, title, lines, bg=CRIMSON):
filled_rect(x, y, w, h, bg, radius=2)
filled_rect(x, y + h - 8*mm, w, 8*mm, GOLD, radius=2)
filled_rect(x, y + h - 8*mm, w, 4*mm, GOLD) # square off bottom of gold cap
c.setFont("Helvetica-Bold", 9.5)
c.setFillColor(CRIMSON)
c.drawString(x + 3*mm, y + h - 5.8*mm, title)
ly = y + h - 13*mm
for ln in lines:
c.setFont("Helvetica", 9)
c.setFillColor(WHITE_C)
if ln == "":
ly -= 2.5*mm; continue
c.drawString(x + 4*mm, ly, ln)
ly -= 5.2*mm
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE 1 β TITLE + OVERVIEW + NEONATAL CONTEXT
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
bg(); right_bar(); top_rule(); footer_bar(1)
# Top crimson band
filled_rect(0, H - 50*mm, W - 9*mm, 50*mm, CRIMSON)
c.setFont("Helvetica", 18); c.setFillColor(WHITE_C)
c.drawString(14*mm, H - 18*mm, "EARLY SIGNS OF")
c.setFont("Helvetica-Bold", 30); c.setFillColor(GOLD)
c.drawString(14*mm, H - 37*mm, "BACTERIAL ENDOCARDITIS")
filled_rect(0, H - 50*mm, W - 9*mm, 10.5*mm, PALE_RED)
c.setFont("Helvetica-Oblique", 11); c.setFillColor(CRIMSON)
c.drawCentredString((W-9*mm)/2, H - 45.5*mm,
"Neonatal Β· Pediatric Β· Adult Β· Recognition Β· Clinical Signs Β· Duke Criteria")
hline(14*mm, H - 52*mm, W - 10*mm, GOLD, 1.5)
# ββ Two neonatal echo images side by side ββ
IMG_TOP = H - 54*mm
IMG_W2 = (W - 9*mm - 14*mm - 5*mm) / 2
img_box("neo_echo1", 14*mm, IMG_TOP - 52*mm, IMG_W2, 41*mm,
"Neonatal TTE: vegetation on mitral",
"valve (blue arrow) β apical 4-chamber")
img_box("neo_echo2", 14*mm + IMG_W2 + 5*mm, IMG_TOP - 52*mm, IMG_W2, 41*mm,
"Infant TTE + Colour Doppler: 2.7mm",
"vegetation + mitral regurgitation")
# ββ Overview text block ββ
OV_Y = IMG_TOP - 52*mm - 13*mm
filled_rect(14*mm, OV_Y - 62*mm, W - 9*mm - 14*mm, 62*mm, PALE_RED, radius=2)
section_pill(14*mm, OV_Y, 50*mm, "DISEASE OVERVIEW", CRIMSON)
ov_lines = [
"Infective endocarditis (IE) is a microbial infection of the cardiac valves or endocardium,",
"producing characteristic vegetations of thrombotic debris, fibrin, and micro-organisms.",
"Although predominantly a disease of adults, neonatal and infant IE is increasingly recognised,",
"particularly in the context of premature infants with central venous catheters, congenital",
"heart disease, and prolonged ICU stays. S. aureus is the dominant pathogen in neonates.",
"In older children and adults, S. viridans causes the classic subacute form while S. aureus",
"causes the aggressive acute form. Early recognition of peripheral signs reduces mortality.",
"The Modified Duke Criteria (ESC 2023) provide a validated diagnostic framework.",
]
wrap_text(ov_lines, 17*mm, OV_Y - 9*mm, W - 9*mm - 14*mm - 6*mm,
size=9.5, color=CHARCOAL, line_h=5.2*mm)
# ββ Topic map cards ββ
CARD_Y = OV_Y - 62*mm - 4*mm
topics_data = [
("01", "Cutaneous Signs\nOsler Nodes & Janeway Lesions"),
("02", "Peripheral Signs\nSplinter Haemorrhages & Clubbing"),
("03", "Ocular Signs\nRoth Spots & Conjunctival Petechiae"),
("04", "Cardiac & Duke Criteria\nDiagnosis in Neonates & Adults"),
]
CW = (W - 9*mm - 14*mm - 3*3*mm) / 4
cx = 14*mm
for num, lbl in topics_data:
outlined_rect(cx, CARD_Y - 26*mm, CW, 26*mm, WHITE_C, LIGHT_LINE, 0.5)
filled_rect(cx, CARD_Y - 8*mm, CW, 8*mm, CRIMSON, radius=1)
filled_rect(cx, CARD_Y - 8*mm, CW, 4*mm, CRIMSON)
txt_c(num, cx + CW/2, CARD_Y - 5.5*mm, size=14, color=GOLD, bold=True)
lines_lbl = lbl.split("\n")
for li, ll in enumerate(lines_lbl):
c.setFont("Helvetica", 8.2)
c.setFillColor(CHARCOAL)
c.drawCentredString(cx + CW/2, CARD_Y - 13*mm - li*5.5*mm, ll)
cx += CW + 3*mm
txt("Source: Robbins & Kumar Basic Pathology 10th Ed Β· Braunwald's Heart Disease 12th Ed Β· ESC Guidelines 2023",
14*mm, 10*mm, size=7, color=GREY_TXT, italic=True)
c.showPage()
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE 2 β Cutaneous Signs (Osler / Janeway) β 3 images
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
bg(); right_bar(); top_rule(); footer_bar(2)
header("02", "CUTANEOUS MANIFESTATIONS", "Osler Nodes & Janeway Lesions")
TOP = H - 32*mm
# ββ Three images across top ββ
IW3 = (W - 9*mm - 14*mm - 2*4*mm) / 3
img_box("osler_janeway", 14*mm, TOP - 53*mm, IW3, 42*mm,
"Osler nodes (arrows, palm)",
"Janeway lesions (sole)")
img_box("janeway_foot", 14*mm + IW3 + 4*mm, TOP - 53*mm, IW3, 42*mm,
"Janeway lesions + Osler node",
"right foot/ankle β S. aureus IE")
img_box("janeway_ped", 14*mm + 2*(IW3 + 4*mm), TOP - 53*mm, IW3, 42*mm,
"Janeway lesions β PEDIATRIC",
"haemorrhagic macules on digit")
# ββ Two content columns below images ββ
COL_Y = TOP - 53*mm - 13*mm
FULL_W = W - 9*mm - 14*mm
HALF_W = FULL_W / 2 - 3*mm
LX = 14*mm
RX = 14*mm + HALF_W + 6*mm
# Left column header + content
filled_rect(LX, COL_Y, HALF_W, 7*mm, CRIMSON, radius=1)
txt_c("OSLER NODES", LX + HALF_W/2, COL_Y + 2.3*mm, size=10.5, color=GOLD, bold=True)
osler = [
{"h": True, "text": "Definition & Location"},
{"h": False, "text": "Tender, painful, erythematous-to-violaceous raised nodules found on fingertip pulp, toe pads, thenar & hypothenar eminences. Rarely on soles."},
{"h": True, "text": "Mechanism"},
{"h": False, "text": "Immune complex deposition β microvasculitis. NOT direct septic emboli. Histology shows arteriolar inflammation without micro-organisms."},
{"h": True, "text": "Clinical Behaviour"},
{"h": False, "text": "Painful on direct pressure (distinguishing feature). Transient β resolve spontaneously within hours to days without necrosis."},
{"h": True, "text": "Frequency"},
{"h": False, "text": "10β25% of subacute IE cases. More common with viridans streptococcal infection. Rare in acute S. aureus IE (may be Janeway instead)."},
{"h": True, "text": "Duke Criterion"},
{"h": False, "text": "Minor criterion in Modified Duke Criteria. Contributes to 'Immunological phenomena' category alongside Roth spots, rheumatoid factor."},
{"h": True, "text": "Neonatal / Pediatric Note"},
{"h": False, "text": "Osler nodes are uncommon in neonates and infants due to immature immune response. When present, always investigate for underlying CHD or catheter-related IE."},
]
label_body_block([{"h": e["h"], "text": e["text"]} for e in osler], LX, COL_Y - 2*mm, HALF_W)
# Right column header + content
filled_rect(RX, COL_Y, HALF_W, 7*mm, RUST, radius=1)
txt_c("JANEWAY LESIONS", RX + HALF_W/2, COL_Y + 2.3*mm, size=10.5, color=WHITE_C, bold=True)
janeway = [
{"h": True, "text": "Definition & Location"},
{"h": False, "text": "Painless, flat, irregular haemorrhagic macules or micro-abscesses on palms, soles, and occasionally thenar/hypothenar eminences."},
{"h": True, "text": "Mechanism"},
{"h": False, "text": "Septic micro-emboli from vegetations lodge in dermal capillaries β acute micro-abscess with neutrophilic infiltrate and bacteria on biopsy."},
{"h": True, "text": "Clinical Behaviour"},
{"h": False, "text": "Non-tender on palpation (key differentiator from Osler). Do not blanch on pressure. Resolve completely over days without scarring."},
{"h": True, "text": "Frequency"},
{"h": False, "text": "5β10% of IE cases overall. More common in acute IE (Staphylococcus aureus, Streptococcus pneumoniae, Gram-negative organisms)."},
{"h": True, "text": "Duke Criterion"},
{"h": False, "text": "Minor criterion under 'Vascular phenomena' alongside arterial emboli, pulmonary infarcts, mycotic aneurysm, intracranial haemorrhage."},
{"h": True, "text": "Pediatric Note"},
{"h": False, "text": "Seen in pediatric S. aureus IE. In neonates with catheter-related IE, Janeway lesions may be the only external sign alerting clinicians to cardiac involvement."},
]
label_body_block([{"h": e["h"], "text": e["text"]} for e in janeway], RX, COL_Y - 2*mm, HALF_W)
# Comparison strip
CMP_Y = 34*mm
filled_rect(14*mm, CMP_Y, FULL_W, 24*mm, NAVY, radius=2)
txt("| OSLER | Painful Β· Raised nodule Β· Immune complex Β· Subacute IE Β· Minor Duke",
18*mm, CMP_Y + 17*mm, size=9, color=GOLD, bold=True)
hline(18*mm, CMP_Y + 14*mm, W - 11*mm, GOLD, 0.5)
txt("| JANEWAY | Painless Β· Flat macule Β· Septic embolus Β· Acute IE Β· Minor Duke",
18*mm, CMP_Y + 9*mm, size=9, color=WHITE_C)
txt("Memory tip: Janeway = Just lying flat (painless). Osler = Ouch! (painful).",
18*mm, CMP_Y + 4*mm, size=8.5, color=DARK_CREAM, italic=True)
txt("Source: Fitzpatrick's Dermatology Β· Robbins & Cotran Pathologic Basis of Disease Β· Harrison's Internal Medicine",
14*mm, 10*mm, size=7, color=GREY_TXT, italic=True)
c.showPage()
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE 3 β Splinter Haemorrhages, Clubbing, Petechiae
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
bg(); right_bar(); top_rule(); footer_bar(3)
header("03", "PERIPHERAL VASCULAR & NAIL SIGNS", "Splinter Haemorrhages, Clubbing & Petechiae")
TOP = H - 32*mm
# Two images: splinter + osler_finger side by side
IW2 = (W - 9*mm - 14*mm - 5*mm) / 2
img_box("splinter", 14*mm, TOP - 55*mm, IW2, 44*mm,
"Splinter haemorrhages (blue circles)",
"dark-red subungual linear streaks")
img_box("osler_finger", 14*mm + IW2 + 5*mm, TOP - 55*mm, IW2, 44*mm,
"Osler node + splinter haemorrhage",
"same finger β mixed IE stigmata")
# Content below images β full width split 2 columns
CY2 = TOP - 55*mm - 13*mm
HW2 = (W - 9*mm - 14*mm) / 2 - 3*mm
# LEFT β Splinter Haemorrhages
filled_rect(14*mm, CY2, HW2, 7*mm, CRIMSON, radius=1)
txt_c("SPLINTER HAEMORRHAGES", 14*mm + HW2/2, CY2 + 2.3*mm, size=10, color=GOLD, bold=True)
splinter_entries = [
{"h": True, "text": "Morphology"},
{"h": False, "text": "Dark-red to brown, thin, linear streaks running longitudinally beneath the nail plate, parallel to nail growth lines. Most visible under bright light."},
{"h": True, "text": "Mechanism in IE"},
{"h": False, "text": "Micro-thromboembolism from cardiac vegetations lodges in the small capillaries of the nail bed, causing rupture and extravasation. Also immune-complex vasculitis contributes in subacute IE."},
{"h": True, "text": "Location Specificity"},
{"h": False, "text": "DISTAL location (near free edge) is more specific for IE. PROXIMAL splinters are usually traumatic. Multiple nails involved favours systemic cause."},
{"h": True, "text": "Frequency & Differential"},
{"h": False, "text": "Present in 5β15% of IE. Also seen in: nail trauma (most common cause overall), psoriasis, vasculitis, BTK inhibitors (ibrutinib), antiphospholipid syndrome, trichinosis."},
{"h": True, "text": "Examination Technique"},
{"h": False, "text": "Examine all 10 nails in bright light. Press gently β true splinters do not blanch. Document number and location. Photograph for follow-up comparison."},
]
label_body_block([{"h": e["h"], "text": e["text"]} for e in splinter_entries],
14*mm, CY2 - 2*mm, HW2, lh_body=4.8*mm)
# RIGHT β Clubbing + Petechiae
RX2 = 14*mm + HW2 + 6*mm
filled_rect(RX2, CY2, HW2, 7*mm, RUST, radius=1)
txt_c("CLUBBING & PETECHIAE", RX2 + HW2/2, CY2 + 2.3*mm, size=10, color=WHITE_C, bold=True)
club_entries = [
{"h": True, "text": "Digital Clubbing"},
{"h": False, "text": "Painless enlargement of distal finger/toe with loss of nail-bed angle beyond 180Β° (Lovibond angle). Soft tissue swelling and periosteal new bone formation."},
{"h": True, "text": "Schamroth Window Test"},
{"h": False, "text": "Oppose dorsal surfaces of index fingers β normally a diamond-shaped window is visible at nail bases. Absent window = clubbing. Simple, quick bedside test."},
{"h": True, "text": "Clubbing in IE Context"},
{"h": False, "text": "Develops in long-standing subacute IE (weeks to months). Reflects chronic tissue hypoxia, increased VEGF, and periosteal vascular proliferation. Regresses with successful treatment."},
{"h": True, "text": "Petechiae β Earliest Sign"},
{"h": False, "text": "Small, flat, dark-red non-blanching spots from micro-haemorrhages. Locations: lower tarsal conjunctiva, hard palate, skin of trunk and limbs. Among the earliest detectable signs of IE."},
{"h": True, "text": "Petechiae in Neonates"},
{"h": False, "text": "In neonatal IE, petechiae on skin (particularly face and neck) may appear early and be mistaken for birth trauma. Always consider IE if petechiae accompany fever and a murmur in a neonate."},
{"h": True, "text": "Conjunctival Petechiae"},
{"h": False, "text": "Evert lower eyelid, inspect along tarsal conjunctiva under direct light. Present in 20β40% of IE. Microemboli or immune vasculitis in conjunctival capillaries."},
]
label_body_block([{"h": e["h"], "text": e["text"]} for e in club_entries],
RX2, CY2 - 2*mm, HW2, lh_body=4.8*mm)
# Exam checklist strip
CS_Y = 34*mm
filled_rect(14*mm, CS_Y, W - 9*mm - 14*mm, 24*mm, TEAL_DARK, radius=2)
txt("BEDSIDE PERIPHERAL EXAMINATION CHECKLIST:", 18*mm, CS_Y + 19*mm,
size=9.5, color=GOLD, bold=True)
checklist = [
"1. All 10 nails β splinter haemorrhages (distal = specific) "
"2. Fingertip pulp β Osler node tenderness "
"3. Palms + soles β Janeway lesions",
"4. Schamroth test β digital clubbing "
"5. Evert lower eyelid β conjunctival petechiae "
"6. Oral palate under torch β mucosal petechiae",
]
for li, cl in enumerate(checklist):
txt(cl, 18*mm, CS_Y + 13*mm - li*5.5*mm, size=8.5, color=WHITE_C)
txt("Source: Braunwald's Heart Disease 12th Ed Β· Goldman-Cecil Medicine Β· Fitzpatrick's Dermatology",
14*mm, 10*mm, size=7, color=GREY_TXT, italic=True)
c.showPage()
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE 4 β Roth Spots & Ocular Signs
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
bg(); right_bar(); top_rule(); footer_bar(4)
header("04", "OCULAR & OPHTHALMIC SIGNS", "Roth Spots & Fundoscopic Findings")
TOP = H - 32*mm
# Two Roth spot images
IW2 = (W - 9*mm - 14*mm - 5*mm) / 2
img_box("roth1", 14*mm, TOP - 55*mm, IW2, 44*mm,
"Roth spot: white arrow = white-centred",
"retinal haemorrhage near optic disc")
img_box("roth2", 14*mm + IW2 + 5*mm, TOP - 55*mm, IW2, 44*mm,
"Multiple Roth spots (red arrows) +",
"preretinal haemorrhage (D-shaped)")
# Two columns
CY3 = TOP - 55*mm - 13*mm
HW3 = (W - 9*mm - 14*mm) / 2 - 3*mm
# LEFT β Roth Spots
filled_rect(14*mm, CY3, HW3, 7*mm, CRIMSON, radius=1)
txt_c("ROTH SPOTS", 14*mm + HW3/2, CY3 + 2.3*mm, size=10.5, color=GOLD, bold=True)
roth_entries = [
{"h": True, "text": "Definition"},
{"h": False, "text": "Oval or flame-shaped intraretinal haemorrhages with a pale or white centre. Located preferentially near the optic disc and posterior pole."},
{"h": True, "text": "White Centre Composition"},
{"h": False, "text": "The pale centre is a fibrin-platelet aggregate, NOT pus or bacteria. May also contain lymphocytes. This distinguishes Roth spots from purely haemorrhagic lesions."},
{"h": True, "text": "Mechanism"},
{"h": False, "text": "Septic micro-emboli from vegetations occlude retinal capillaries β capillary rupture β haemorrhage with central fibrin clot. Immune complex vasculitis may also contribute."},
{"h": True, "text": "Frequency in IE"},
{"h": False, "text": "Present in 2β10% of IE cases. Higher prevalence in subacute IE and younger patients. Better detected on dilated fundal exam than direct ophthalmoscopy."},
{"h": True, "text": "Differential Diagnosis"},
{"h": False, "text": "Leukaemia, lymphoma Β· Severe anaemia (Hb <8 g/dL) Β· Diabetic retinopathy Β· Systemic lupus erythematosus Β· Hypertensive emergency Β· CMV retinitis (HIV) Β· Systemic vasculitis"},
{"h": True, "text": "NOT Pathognomonic"},
{"h": False, "text": "White-centred retinal haemorrhages have many causes. Always correlate with blood cultures, echo, and clinical context before attributing to IE."},
{"h": True, "text": "Neonatal / Infant Context"},
{"h": False, "text": "Roth spots are exceptionally rare in neonates. However, any neonate with unexplained retinal haemorrhages AND fever AND a cardiac murmur warrants cardiac echo and blood cultures urgently."},
]
label_body_block([{"h": e["h"], "text": e["text"]} for e in roth_entries],
14*mm, CY3 - 2*mm, HW3, lh_body=4.7*mm)
# RIGHT β Other ocular signs + fundoscopy guide
RX3 = 14*mm + HW3 + 6*mm
filled_rect(RX3, CY3, HW3, 7*mm, RUST, radius=1)
txt_c("OTHER OCULAR SIGNS & EXAM", RX3 + HW3/2, CY3 + 2.3*mm, size=10, color=WHITE_C, bold=True)
ocular_entries = [
{"h": True, "text": "Conjunctival Petechiae"},
{"h": False, "text": "Pin-head, non-blanching haemorrhagic spots along the tarsal (especially lower palpebral) conjunctiva. Present in 20β40% of IE. Evert lower lid and inspect under direct illumination."},
{"h": True, "text": "Subconjunctival Haemorrhage"},
{"h": False, "text": "Larger, confluent bright-red area beneath bulbar conjunctiva. Less specific than petechiae β may result from coughing, trauma, or coagulopathy."},
{"h": True, "text": "Endogenous Endophthalmitis"},
{"h": False, "text": "Rare but devastating. Septic emboli reach the vitreous or choroid causing purulent inflammation. Presents as red eye, hypopyon, severe visual loss. Ophthalmic emergency."},
{"h": True, "text": "Visual Field Defects"},
{"h": False, "text": "Homonymous hemianopia or cortical blindness from embolic stroke in occipital cortex. Indicates cerebral embolisation β urgently modify antibiotic and consider surgery."},
{"h": True, "text": "Uveitis / Vitritis"},
{"h": False, "text": "Anterior or posterior uveitis may occur from immune complex deposition. Presents as photophobia, floaters, blurred vision. Investigate for underlying IE if bilateral."},
{"h": True, "text": "When to Do Fundoscopy?"},
{"h": False, "text": "All patients with: (1) fever + new murmur + any visual symptom, (2) confirmed IE at initial workup, (3) sudden vision change during IE treatment suggesting new emboli."},
{"h": True, "text": "Paediatric/Neonatal Protocol"},
{"h": False, "text": "Neonates with confirmed IE should receive ophthalmology review before and after antibiotic therapy. Fungal IE (Candida) has high rate of ocular involvement requiring weekly fundoscopy."},
]
label_body_block([{"h": e["h"], "text": e["text"]} for e in ocular_entries],
RX3, CY3 - 2*mm, HW3, lh_body=4.7*mm)
info_box_dark(14*mm, 10.5*mm + 3*mm, W - 9*mm - 14*mm, 22*mm,
"FUNDOSCOPY β CLINICAL PROTOCOL & DIFFERENTIAL",
["Indication: Fever + murmur + any visual symptom or focal neurology",
"Technique: Dilated fundal exam preferred over direct ophthalmoscopy for sensitivity",
"Differential white-centred haemorrhage: IE Β· Leukaemia Β· Anaemia Β· DM Β· SLE Β· CMV (HIV)",
"Fungal IE (Candida, Aspergillus): weekly fundoscopy mandatory β ocular involvement in 30β45%"])
txt("Source: Bradley & Daroff's Neurology in Clinical Practice Β· Robbins & Cotran Pathologic Basis of Disease",
14*mm, 10*mm, size=7, color=GREY_TXT, italic=True)
c.showPage()
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE 5 β Cardiac Signs + Gross Pathology + Duke Criteria + Neonatal IE
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
bg(); right_bar(); top_rule(); footer_bar(5)
header("05", "CARDIAC SIGNS Β· PATHOLOGY Β· DUKE CRITERIA", "Neonatal IE & Definitive Diagnosis")
TOP = H - 32*mm
# Three images across top: TEE, gross valve, multi-valve surgical
IW3b = (W - 9*mm - 14*mm - 2*4*mm) / 3
img_box("tee_mv", 14*mm, TOP - 53*mm, IW3b, 42*mm,
"TEE: vegetation on posterior",
"mitral leaflet P2 (red arrow)")
img_box("gross_valve", 14*mm + IW3b + 4*mm, TOP - 53*mm, IW3b, 42*mm,
"Gross pathology: aortic valve",
"vegetation + cusp perforation")
img_box("multi_valve", 14*mm + 2*(IW3b + 4*mm), TOP - 53*mm, IW3b, 42*mm,
"Surgical: multi-valve IE",
"TTE + Doppler + gross specimen")
# Two columns below
CY5 = TOP - 53*mm - 13*mm
HW5 = (W - 9*mm - 14*mm) / 2 - 3*mm
# LEFT β Cardiac Signs + Neonatal IE
filled_rect(14*mm, CY5, HW5, 7*mm, CRIMSON, radius=1)
txt_c("CARDIAC SIGNS & NEONATAL IE", 14*mm + HW5/2, CY5 + 2.3*mm, size=10, color=GOLD, bold=True)
cardiac_entries = [
{"h": True, "text": "New or Changed Murmur"},
{"h": False, "text": "Regurgitant murmur from valve leaflet destruction/perforation or new flow across vegetation. MV > AoV > TV in frequency. MAJOR Duke criterion. Serial auscultation is essential."},
{"h": True, "text": "Acute Heart Failure"},
{"h": False, "text": "Bilateral basal crackles, S3 gallop, raised JVP, peripheral oedema β result of acute valvular incompetence. Indicates surgical urgency (emergency surgery within 24 hours)."},
{"h": True, "text": "Perivalvular Abscess"},
{"h": False, "text": "New PR prolongation or AV block on ECG suggests periannular abscess extending into conduction tissue. Urgent TEE and surgical consultation. Occurs in ~40% of aortic IE."},
{"h": True, "text": "Neonatal IE β Overview"},
{"h": False, "text": "Rare (<1 per 100,000 live births) but highly lethal (mortality 20β40%). Risk factors: prematurity, congenital heart disease, central venous catheter, prolonged TPN, mechanical ventilation."},
{"h": True, "text": "Neonatal IE β Organism"},
{"h": False, "text": "S. aureus (40β50%), CoNS (Staphylococcus epidermidis via CVC), Candida species (especially in very-low-birth-weight infants on broad-spectrum antibiotics)."},
{"h": True, "text": "Neonatal IE β Clinical Features"},
{"h": False, "text": "Fever, poor feeding, respiratory distress, new murmur, hepatosplenomegaly, thrombocytopenia, unexplained septicaemia not responding to antibiotics targeting known catheter infection."},
{"h": True, "text": "Neonatal IE β Echo"},
{"h": False, "text": "TTE is usually adequate in neonates due to small chest wall. Even small (1β2 mm) vegetations must be taken seriously. Right-sided structures (tricuspid, pulmonary) more commonly involved via CVC."},
]
label_body_block([{"h": e["h"], "text": e["text"]} for e in cardiac_entries],
14*mm, CY5 - 2*mm, HW5, lh_body=4.7*mm)
# RIGHT β Modified Duke Criteria
RX5 = 14*mm + HW5 + 6*mm
filled_rect(RX5, CY5, HW5, 7*mm, NAVY, radius=1)
txt_c("MODIFIED DUKE CRITERIA (ESC 2023)", RX5 + HW5/2, CY5 + 2.3*mm, size=9.5, color=GOLD, bold=True)
duke_entries = [
{"h": True, "text": "Major Criterion 1 β Blood Cultures"},
{"h": False, "text": "β₯2 separate blood culture sets positive with typical IE organisms (S. viridans, S. aureus, HACEK, Enterococcus without primary focus). OR persistently positive cultures β₯12h apart. OR single positive for Coxiella/Bartonella."},
{"h": True, "text": "Major Criterion 2 β Imaging"},
{"h": False, "text": "Echo: vegetation, abscess/pseudoaneurysm, new valve dehiscence. OR new valvular regurgitation. CT/PET may substitute when echo non-diagnostic."},
{"h": True, "text": "Minor Criteria (select any)"},
{"h": False, "text": "1. Predisposing cardiac condition or IVDU 2. Fever >38Β°C 3. Vascular phenomena: major emboli, septic infarcts, mycotic aneurysm, intracranial haemorrhage, Janeway lesions, splinter haemorrhages 4. Immunological: GN, Osler nodes, Roth spots, RF+ 5. Positive blood culture not meeting major criterion."},
{"h": True, "text": "Diagnostic Thresholds"},
{"h": False, "text": "DEFINITE: 2 Major OR 1 Major + 3 Minor OR 5 Minor criteria. POSSIBLE: 1 Major + 1 Minor OR 3 Minor criteria. REJECTED: Firm alternative diagnosis or resolution within β€4 days of antibiotics."},
{"h": True, "text": "Neonatal Duke Application"},
{"h": False, "text": "Standard criteria apply but echocardiography is the primary imaging modality. Blood culture sensitivity is high in neonates if taken before antibiotics. Fever may be absent β hypothermia is equally concerning."},
{"h": True, "text": "Early Recognition Red Flags"},
{"h": False, "text": "PUO + murmur + any peripheral sign β cultures + echo immediately. IVDU + fever β right-sided IE. Neonatal CVC + S. aureus bacteraemia β cardiac echo mandatory within 24h."},
{"h": True, "text": "Treatment Principles"},
{"h": False, "text": "IV bactericidal antibiotics (4β6 weeks). Duration guided by organism and valve type (native vs prosthetic). Early surgery for heart failure, uncontrolled infection, large vegetation >10mm, abscess."},
]
label_body_block([{"h": e["h"], "text": e["text"]} for e in duke_entries],
RX5, CY5 - 2*mm, HW5, lh_body=4.6*mm)
txt("Source: Braunwald's Heart Disease 12th Ed Β· ESC IE Guidelines 2023 Β· Robbins & Kumar Basic Pathology 10th Ed",
14*mm, 10*mm, size=7, color=GREY_TXT, italic=True)
c.showPage()
# ββ Save ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
c.save()
size_kb = os.path.getsize(OUT) // 1024
print(f"\nβ PDF saved: {OUT} ({size_kb} KB)")
cd /home/daytona/workspace/bacterial-endocarditis-pdf && python3 build_pdf_v2.py 2>&1
Early Signs Bacterial Endocarditis v2
PDF Document Β· PDF
| Page | Images |
|---|---|
| 1 | 2 neonatal/infant TTE echos (vegetation on mitral valve, paediatric cardiac exam with Doppler) + topic cards |
| 2 | 3 cutaneous sign photos: Osler nodes + Janeway dual panel Β· Janeway on foot/ankle Β· Janeway on paediatric digit |
| 3 | 2 nail/peripheral photos: splinter haemorrhages (multiple nails, blue circles) Β· Osler node + splinter on same finger |
| 4 | 2 Roth spot fundus photos: single Roth spot with white arrow Β· Multiple Roth spots + preretinal haemorrhage |
| 5 | 3 cardiac/pathology images: TEE vegetation on mitral Β· Gross aortic valve with vegetation + perforation Β· Surgical multi-valve IE specimen |
stringWidth) β no text overflows, no misaligned columns, no drifting boxes.Now do the same for first topic align every line perfectly i want everything in bullet points 20 lines in each page
left ventricular non-compaction LVNC echocardiogram pediatric spongy myocardium
arrhythmogenic right ventricular cardiomyopathy ARVC MRI fibro-fatty
restrictive cardiomyopathy children biatrial dilation echocardiogram MRI
Takotsubo stress cardiomyopathy apical ballooning echocardiogram octopus pot
~/cardiomyopathy-pdf/build_pdf.py
"""
Atypical Forms of Cardiomyopathy in Children & Adolescents
5-page A4 PDF β perfectly aligned bullet points, 20+ lines/page, multiple images
ReportLab canvas β pixel-perfect coordinate control
"""
import urllib.request, io, os
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm
from reportlab.lib.colors import HexColor
from reportlab.pdfgen import canvas
from reportlab.lib.utils import ImageReader
W, H = A4
OUT = "/home/daytona/workspace/cardiomyopathy-pdf/Atypical_Cardiomyopathy_Children.pdf"
os.makedirs(os.path.dirname(OUT), exist_ok=True)
# ββ Palette (Navy / Teal / Gold β clinical academic) ββββββββββββββββββββββββββ
NAVY = HexColor("#0B1F3A")
TEAL = HexColor("#1A8C8A")
TEAL_DK = HexColor("#126362")
GOLD = HexColor("#F0B429")
OFFWHITE = HexColor("#EAF2F8")
LIGHT_BG = HexColor("#F4F8FB")
CHARCOAL = HexColor("#1E2A38")
MID_GREY = HexColor("#5D7080")
LIGHT_LINE= HexColor("#C5D8E8")
WHITE_C = HexColor("#FFFFFF")
RED_ACC = HexColor("#C0392B")
GREEN_ACC = HexColor("#1A7A4A")
# ββ Layout constants ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
LEFT_BAR = 10*mm # left accent bar width
ML = LEFT_BAR + 7*mm # main left margin
MR = 10*mm # right margin
RBAR = 9*mm # right bar width
BODY_W = W - ML - MR - RBAR # usable body width
HEADER_H = 32*mm # header zone height
FOOTER_H = 9*mm
BODY_TOP = H - HEADER_H # y of body start
BODY_BOT = FOOTER_H + 2*mm
# Bullet geometry (fixed, perfectly aligned)
BULL_CHAR = "\u2022" # β’
BULL_INDENT = 5*mm # bullet symbol x offset from ML
TEXT_INDENT = 10*mm # text x offset from ML (after bullet)
LINE_H = 5.4*mm # standard line height
SUB_BULL = "\u25E6" # β¦ sub-bullet
SUB_INDENT_B = 9*mm # sub-bullet x
SUB_INDENT_T = 14*mm # sub-bullet text x
# ββ Image fetch βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
URLS = {
# LVNC
"lvnc_4ch": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_94d0d4c659ecda38390bba36342535f0c5d3d9d51c431a093333d40eb61dd304.jpg",
"lvnc_sax": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_c7ce617c67a786ed27f62622a1f93ed8612044f1a4cf86ec20c8e3f7179a359d.jpg",
"lvnc_ratio": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_abfdedd879219630bb2a7ba6b6c399eb916263cf066b318e70a7a163cf59fdc2.jpg",
# ARVC
"arvc_mri1": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_ccef375d42502a4932535f5fd1be880aeaf424994e8a3739b42f1dba5c0d308a.jpg",
"arvc_multi": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_a3e0d6cb91e2172ed02e53ddf5b9ec43c9b44cc0833909fab5653447edc82bd8.jpg",
"arvc_histo": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_e3cb9479b2a542bd456ffbedfbe10a06515867a8ff5bfe40ded9a0765043e76e.jpg",
# RCM
"rcm_echo1": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_d1d8720fff2d4e78cc9b503048bfa103f00204073666a10de82dbff0f50990ae.jpg",
"rcm_ped": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_24ebe5d5c428d8222d2f458d7b08c986c1c4f84a18fb4e230f5839fa71b2addd.jpg",
"rcm_tdi": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_2f8a7bcc4759eea4457abb6d5f9b22818a74d4b522f01aaee71d49f77cad1ec1.jpg",
# Takotsubo
"tako_4ch": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_9b3823876d7ed65024335dfad3c70001fb3c016838f80a7b0312bcaa08696f03.jpg",
"tako_pot": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_7593d221172b5ee05a0ad427792550530c5d7dbf1b25be1c5829a9e22380e57c.jpg",
"tako_thrombus": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_b9ab045fcfda8e091c86fb523d1711b2eab60e56bb6c05412dd3547586acc826.jpg",
}
def fetch(url):
try:
req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
data = urllib.request.urlopen(req, timeout=15).read()
return ImageReader(io.BytesIO(data))
except Exception as e:
print(f" FAIL {url[-50:]}: {e}"); return None
print("Downloading images...")
IMGS = {k: fetch(v) for k, v in URLS.items()}
print({k: "OK" if v else "X" for k, v in IMGS.items()})
# ββ Canvas ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
c = canvas.Canvas(OUT, pagesize=A4)
c.setTitle("Atypical Cardiomyopathy in Children and Adolescents")
c.setAuthor("4th Year MBBS Presentation 2026")
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PRIMITIVE HELPERS
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def frect(x, y, w, h, col, r=0):
c.saveState()
c.setFillColor(col)
c.setStrokeColor(HexColor("#00000000"))
if r: c.roundRect(x, y, w, h, r, fill=1, stroke=0)
else: c.rect(x, y, w, h, fill=1, stroke=0)
c.restoreState()
def srect(x, y, w, h, fill_col, stroke_col, lw=0.5):
c.saveState()
c.setFillColor(fill_col); c.setStrokeColor(stroke_col); c.setLineWidth(lw)
c.rect(x, y, w, h, fill=1, stroke=1)
c.restoreState()
def hline(x1, y, x2, col=GOLD, lw=1.2):
c.saveState(); c.setStrokeColor(col); c.setLineWidth(lw)
c.line(x1, y, x2, y); c.restoreState()
def put(s, x, y, sz=9.5, col=CHARCOAL, bold=False, italic=False):
c.saveState(); c.setFillColor(col)
if bold and italic: f = "Helvetica-BoldOblique"
elif bold: f = "Helvetica-Bold"
elif italic: f = "Helvetica-Oblique"
else: f = "Helvetica"
c.setFont(f, sz); c.drawString(x, y, s); c.restoreState()
def putc(s, cx, y, sz=9.5, col=CHARCOAL, bold=False):
f = "Helvetica-Bold" if bold else "Helvetica"
c.saveState(); c.setFillColor(col); c.setFont(f, sz)
c.drawCentredString(cx, y, s); c.restoreState()
def place_img(key, x, y, w, h):
img = IMGS.get(key)
if not img: return
iw, ih = img.getSize()
sc = min(w/iw, h/ih)
nw, nh = iw*sc, ih*sc
c.drawImage(img, x+(w-nw)/2, y+(h-nh)/2, nw, nh,
preserveAspectRatio=True, mask="auto")
def img_card(key, x, y, w, h, cap1, cap2=""):
"""Image in a card with caption strip at bottom."""
srect(x, y, w, h + 11*mm, LIGHT_BG, LIGHT_LINE, 0.5)
place_img(key, x+1*mm, y+11*mm, w-2*mm, h-1*mm)
frect(x, y, w, 11*mm, OFFWHITE)
c.setFont("Helvetica-Oblique", 7.5); c.setFillColor(TEAL_DK)
c.drawCentredString(x+w/2, y+7*mm, cap1)
if cap2: c.drawCentredString(x+w/2, y+3.2*mm, cap2)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE-LEVEL CHROME
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def page_chrome(pg_num, suptitle, title, subtitle=""):
# Background
frect(0, 0, W, H, LIGHT_BG)
# Left accent bar
frect(0, 0, LEFT_BAR, H, TEAL)
# Right accent bar
frect(W-RBAR, 0, RBAR, H, NAVY)
# Header band
frect(LEFT_BAR, H-HEADER_H, W-LEFT_BAR-RBAR, HEADER_H, NAVY)
# Gold top rule
frect(LEFT_BAR, H-2*mm, W-LEFT_BAR-RBAR, 2*mm, GOLD)
# Page number badge on left bar
frect(0, H-HEADER_H, LEFT_BAR, LEFT_BAR, GOLD)
putc(str(pg_num), LEFT_BAR/2, H-HEADER_H+3.5*mm, sz=11, col=NAVY, bold=True)
# Suptitle (small italic)
put(suptitle, ML, H-10*mm, sz=8.5, col=OFFWHITE, italic=True)
# Main title
put(title, ML, H-22*mm, sz=22, col=GOLD, bold=True)
# Subtitle
if subtitle:
put(subtitle, ML, H-29*mm, sz=10, col=LIGHT_LINE, italic=True)
# Gold underrule
hline(ML, H-HEADER_H+1*mm, W-RBAR-2*mm, GOLD, 1.5)
# Footer bar
frect(LEFT_BAR, 0, W-LEFT_BAR-RBAR, FOOTER_H, NAVY)
c.setFont("Helvetica", 7); c.setFillColor(LIGHT_LINE)
c.drawCentredString((LEFT_BAR + W-RBAR)/2, 3*mm,
"Atypical Cardiomyopathy in Children & Adolescents Β· 4th Year MBBS Β· 2026")
put(f"Page {pg_num} / 5", W-RBAR-18*mm, 3*mm, sz=7.5, col=GOLD, bold=True)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# BULLET ENGINE β perfectly aligned, word-wrapped
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def bullet_engine(items, x_left, y_start, col_w,
lh=LINE_H, font_sz=9.5,
head_col=TEAL, body_col=CHARCOAL,
head_sz=10.5, bullet_col=GOLD):
"""
items: list of dicts:
{"type": "head", "text": "..."} β bold teal section heading
{"type": "bullet", "text": "..."} β β’ bullet, word-wrapped
{"type": "sub", "text": "..."} β β¦ sub-bullet, indented
{"type": "gap"} β small vertical gap
{"type": "rule"} β thin horizontal rule
Returns final y position.
"""
cy = y_start
BULL_X = x_left + BULL_INDENT
TEXT_X = x_left + TEXT_INDENT
SUB_BX = x_left + SUB_INDENT_B
SUB_TX = x_left + SUB_INDENT_T
WRAP_W_BULL = col_w - TEXT_INDENT - 2*mm
WRAP_W_SUB = col_w - SUB_INDENT_T - 2*mm
def wrap(text, tx, wrap_w, sz, col, fnt):
nonlocal cy
words = text.split()
seg = ""
c.saveState(); c.setFont(fnt, sz); c.setFillColor(col)
for w in words:
test = (seg + " " + w).strip()
if c.stringWidth(test, fnt, sz) <= wrap_w:
seg = test
else:
if seg:
c.drawString(tx, cy, seg)
cy -= lh
seg = w
if seg:
c.drawString(tx, cy, seg)
cy -= lh
c.restoreState()
for item in items:
t = item["type"]
if t == "gap":
cy -= lh * 0.45
elif t == "rule":
hline(x_left + 2*mm, cy + lh*0.4, x_left + col_w - 2*mm, LIGHT_LINE, 0.5)
cy -= lh * 0.6
elif t == "head":
# Section heading β no bullet, bold teal, slight gap before
cy -= lh * 0.3
c.saveState(); c.setFont("Helvetica-Bold", head_sz); c.setFillColor(head_col)
c.drawString(x_left + 2*mm, cy, item["text"])
c.restoreState()
cy -= lh * 1.15
elif t == "bullet":
# Bullet symbol
c.saveState(); c.setFont("Helvetica-Bold", font_sz+1); c.setFillColor(bullet_col)
c.drawString(BULL_X, cy, BULL_CHAR)
c.restoreState()
# Word-wrapped text starting at TEXT_X, same first-line y
wrap(item["text"], TEXT_X, WRAP_W_BULL, font_sz, body_col, "Helvetica")
cy -= lh * 0.15 # tight inter-bullet gap
elif t == "sub":
c.saveState(); c.setFont("Helvetica", font_sz-0.5); c.setFillColor(MID_GREY)
c.drawString(SUB_BX, cy, SUB_BULL)
c.restoreState()
wrap(item["text"], SUB_TX, WRAP_W_SUB, font_sz-0.5, MID_GREY, "Helvetica")
cy -= lh * 0.1
return cy
def section_badge(x, y, w, label, bg=TEAL, fg=WHITE_C):
frect(x, y-5.5*mm, w, 6.2*mm, bg, r=1)
putc(label, x+w/2, y-3.2*mm, sz=8.5, col=fg, bold=True)
def info_strip(x, y, w, h, title, items, bg=NAVY, title_bg=GOLD):
frect(x, y, w, h, bg, r=2)
frect(x, y+h-8*mm, w, 8*mm, title_bg, r=2)
frect(x, y+h-8*mm, w, 4*mm, title_bg) # square bottom corners of cap
put(title, x+3*mm, y+h-5.8*mm, sz=9.5, col=NAVY, bold=True)
iy = y+h-13.5*mm
for ln in items:
if ln == "": iy -= 2*mm; continue
c.saveState(); c.setFont("Helvetica", 9); c.setFillColor(OFFWHITE)
c.drawString(x+4*mm, iy, ln); c.restoreState()
iy -= 5.2*mm
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE 1 β TITLE + OVERVIEW
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
page_chrome(1, "PEDIATRIC CARDIOLOGY Β· ATYPICAL CARDIOMYOPATHIES",
"ATYPICAL CARDIOMYOPATHY",
"in Children and Adolescents")
# Topic overview cards
CARD_TOP = H - HEADER_H - 6*mm
CW4 = (BODY_W - 3*3*mm) / 4
topics = [
("01", "Left Ventricular\nNon-Compaction\n(LVNC)"),
("02", "Arrhythmogenic RV\nCardiomyopathy\n(ARVC)"),
("03", "Restrictive\nCardiomyopathy\n(RCM)"),
("04", "Takotsubo &\nArrhythmia-Induced\nCardiomyopathy"),
]
for i, (num, lbl) in enumerate(topics):
cx = ML + i*(CW4+3*mm)
cy = CARD_TOP - 30*mm
srect(cx, cy, CW4, 30*mm, WHITE_C, LIGHT_LINE, 0.5)
frect(cx, cy+22*mm, CW4, 8*mm, TEAL, r=1)
frect(cx, cy+22*mm, CW4, 4*mm, TEAL)
putc(num, cx+CW4/2, cy+25*mm, sz=14, col=GOLD, bold=True)
for li, ll in enumerate(lbl.split("\n")):
putc(ll, cx+CW4/2, cy+17.5*mm-li*5.5*mm, sz=8.5, col=CHARCOAL)
# Overview section
OV_Y = CARD_TOP - 36*mm
section_badge(ML, OV_Y, 55*mm, "DISEASE OVERVIEW & AHA CLASSIFICATION")
ov_items = [
{"type":"bullet","text":"Cardiomyopathies are diseases of the heart muscle characterised by structural and functional abnormalities of the ventricular myocardium unexplained by CAD, hypertension, or valvular disease."},
{"type":"bullet","text":"Atypical cardiomyopathies in children include rare but clinically important entities: LVNC, ARVC, RCM, Takotsubo (stress), and arrhythmia-induced cardiomyopathy."},
{"type":"bullet","text":"The AHA scientific statement 'Cardiomyopathy in Children: Classification and Diagnosis' uses a hierarchical system based on structural/functional phenotype with genetic and non-genetic subcategories."},
{"type":"bullet","text":"Paediatric cardiomyopathies carry substantial morbidity and mortality, and are the primary indication for heart transplantation in children >1 year of age."},
{"type":"bullet","text":"'Children are not small adults' β extreme aetiology heterogeneity, more frequent syndromic associations, and metabolic causes demand a separate diagnostic framework from adult cardiomyopathies."},
{"type":"bullet","text":"The MOGE(S) classification (Morpho-functional, Organ involvement, Genetic pattern, Aetiology, Stage) is the internationally endorsed nosology that incorporates both phenotype and genotype."},
{"type":"bullet","text":"Annual incidence of cardiomyopathy in children is approximately 1.1 per 100,000; DCM is most common (58%), followed by HCM (25%); atypical forms account for the remaining ~17%."},
{"type":"bullet","text":"Genetic testing, echocardiography (TTE/TEE), cardiac MRI with late gadolinium enhancement (LGE), and metabolic screening form the diagnostic cornerstone for all atypical paediatric cardiomyopathies."},
]
bullet_engine(ov_items, ML, OV_Y - 6*mm, BODY_W)
# Bottom summary strip
info_strip(ML, FOOTER_H + 3*mm, BODY_W, 26*mm,
"KEY PRINCIPLES IN PAEDIATRIC CARDIOMYOPATHY",
["β’ Rare but serious β leading cause of paediatric cardiac transplantation worldwide",
"β’ Always exclude metabolic/storage diseases (Pompe, Fabry, Gaucher) before labelling as idiopathic",
"β’ Genetic panel (MYH7, MYBPC3, PKP2, DSP, TAZ, TNNI3) essential in all index cases",
"β’ Regular family screening: first-degree relatives require echo + ECG at diagnosis",
])
put("Source: Fuster & Hurst's The Heart 15th Ed Β· Braunwald's Heart Disease 12th Ed Β· AHA Scientific Statement",
ML, FOOTER_H-0.5*mm, sz=6.5, col=MID_GREY, italic=True)
c.showPage()
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE 2 β LVNC
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
page_chrome(2, "ATYPICAL CARDIOMYOPATHY #1",
"Left Ventricular Non-Compaction",
"LVNC Β· Spongy Myocardium Β· Paediatric 3rd Most Common Cardiomyopathy")
TOP2 = H - HEADER_H - 5*mm
# Three LVNC images across top
IW3 = (BODY_W - 2*4*mm) / 3
img_card("lvnc_4ch", ML, TOP2-50*mm, IW3, 39*mm,
"A4C view: spongy LV apex,", "deep intertrabecular recesses")
img_card("lvnc_sax", ML+IW3+4*mm, TOP2-50*mm, IW3, 39*mm,
"PSAX + A4C: NC/C ratio >2:1", "at end-systole (Jenni criteria)")
img_card("lvnc_ratio", ML+2*(IW3+4*mm), TOP2-50*mm, IW3, 39*mm,
"TEE short-axis: X/Y <0.5", "compacted vs non-compacted layer")
# Content section
CONT_Y = TOP2 - 50*mm - 14*mm
section_badge(ML, CONT_Y, 40*mm, "LVNC β FULL OVERVIEW")
HALF = BODY_W/2 - 3*mm
left_items = [
{"type":"head","text":"Definition & Embryology"},
{"type":"bullet","text":"Failure of normal myocardial compaction during embryogenesis (5thβ8th week of gestation) β persistence of spongy, hypertrabeculated inner layer with deep intertrabecular recesses communicating with the LV cavity."},
{"type":"bullet","text":"Normal compaction proceeds from epicardium to endocardium, and from base to apex; arrest at any stage produces the LVNC phenotype."},
{"type":"head","text":"Epidemiology in Children"},
{"type":"bullet","text":"3rd most common paediatric cardiomyopathy after DCM and HCM, accounting for ~9.2% of all cases (Australian cohort) and 9.5% in Texas Children's Hospital echocardiographic database."},
{"type":"bullet","text":"Paediatric Cardiomyopathy Registry (1990β2008): 155 of 3,219 children (4.8%) had LVNC; majority associated with DCM, HCM, or RCM."},
{"type":"bullet","text":"Annual incidence in children: <0.1 per 100,000. Paradoxically higher prevalence in normal adult volunteers on CMR (14.79%) vs echo (1.28%) β risk of overdiagnosis."},
{"type":"head","text":"Echocardiographic Diagnostic Criteria"},
{"type":"bullet","text":"Jenni (2001): NC/C ratio >2:1 at end-systole in parasternal short-axis view; colour Doppler confirms flow into intertrabecular recesses."},
{"type":"bullet","text":"Chin (1990): X/Y ratio <0.5 at end-diastole (X = compacted, Y = total wall thickness)."},
{"type":"bullet","text":"StΓΆllberger: >3 trabeculations apical to papillary muscles; intertrabecular spaces perfused from LV cavity on colour Doppler."},
{"type":"head","text":"Genetics"},
{"type":"bullet","text":"Autosomal dominant: MYH7, MYBPC3, ACTC1, TPM1, TNNT2 (sarcomeric genes shared with HCM/DCM)."},
{"type":"bullet","text":"X-linked: TAZ (tafazzin) gene mutation β Barth syndrome (LVNC + skeletal myopathy + neutropenia + 3-methylglutaconic aciduria) β exclusively males, presents in infancy."},
{"type":"bullet","text":"Other: LDB3, DTNA, SCN5A (sodium channel β arrhythmia-predominant), RYR2, LMNA."},
]
right_items = [
{"type":"head","text":"Clinical Features & Triad"},
{"type":"bullet","text":"Classic triad: (1) Heart failure β dilated phenotype, reduced LVEF, (2) Ventricular arrhythmias β VT, WPW, complete heart block, (3) Systemic thromboembolism β apical thrombus in recesses."},
{"type":"bullet","text":"Symptomatic children typically present in early infancy with predominant dilated phenotype; asymptomatic individuals may remain undiagnosed until family screening."},
{"type":"bullet","text":"Sudden cardiac death risk is elevated, particularly in those with sustained VT, syncope, or markedly reduced LVEF (<35%)."},
{"type":"head","text":"Cardiac MRI Advantages"},
{"type":"bullet","text":"CMR superior to echo for LVNC quantification: Petersen criterion β NC layer >2.3Γ compacted layer at end-diastole in short-axis CMR slices (sensitivity 86%, specificity 99%)."},
{"type":"bullet","text":"CMR also detects LGE (mid-myocardial or subendocardial fibrosis) which predicts adverse outcomes including sudden death and HF hospitalisation."},
{"type":"head","text":"Management"},
{"type":"bullet","text":"Heart failure: ACE inhibitors/ARBs + beta-blockers (carvedilol/metoprolol) + diuretics; resynchronisation therapy (CRT) for LBBB pattern with reduced EF."},
{"type":"bullet","text":"Anticoagulation: warfarin/LMWH for apical thrombus, LVEF <35%, atrial fibrillation, or prior embolic event."},
{"type":"bullet","text":"Arrhythmia management: ICD implantation for secondary prevention of SCD; catheter ablation for refractory VT or accessory pathway."},
{"type":"bullet","text":"Heart transplantation: indicated for end-stage HF refractory to optimal medical therapy; LVNC outcomes post-transplant equivalent to other cardiomyopathies."},
{"type":"head","text":"Prognosis"},
{"type":"bullet","text":"Worse than DCM when symptomatic in infancy (Pediatric Cardiomyopathy Registry). Isolated LVNC with preserved EF has favourable prognosis with low event rates over 3.3-year follow-up."},
{"type":"bullet","text":"5-year transplant-free survival approximately 75β85% in asymptomatic/mildly symptomatic children; drops to <50% in those presenting with acute decompensated HF in infancy."},
]
bullet_engine(left_items, ML, CONT_Y-6*mm, HALF, lh=LINE_H*0.96, font_sz=9.2)
bullet_engine(right_items, ML+HALF+6*mm, CONT_Y-6*mm, HALF, lh=LINE_H*0.96, font_sz=9.2)
put("Source: Fuster & Hurst's The Heart 15th Ed (Ch.45) Β· Paediatric Cardiomyopathy Registry Β· ESC Guidelines",
ML, FOOTER_H-0.5*mm, sz=6.5, col=MID_GREY, italic=True)
c.showPage()
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE 3 β ARVC
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
page_chrome(3, "ATYPICAL CARDIOMYOPATHY #2",
"Arrhythmogenic RV Cardiomyopathy (ARVC)",
"Fibro-fatty Replacement Β· SCD in Young Athletes Β· Desmosomal Gene Mutations")
TOP3 = H - HEADER_H - 5*mm
# Three ARVC images
IW3 = (BODY_W - 2*4*mm) / 3
img_card("arvc_mri1", ML, TOP3-52*mm, IW3, 41*mm,
"Cardiac MRI axial: RV dilation,", "fibro-fatty infiltration + aneurysm")
img_card("arvc_multi", ML+IW3+4*mm, TOP3-52*mm, IW3, 41*mm,
"Multimodal: echo + T1 MRI +", "fat-suppressed MRI (4 panels)")
img_card("arvc_histo", ML+2*(IW3+4*mm), TOP3-52*mm, IW3, 41*mm,
"MRI + histology: transmural", "fibro-fatty RV wall replacement")
CONT3 = TOP3 - 52*mm - 14*mm
section_badge(ML, CONT3, 40*mm, "ARVC β FULL OVERVIEW")
HALF3 = BODY_W/2 - 3*mm
left3 = [
{"type":"head","text":"Definition & Pathology"},
{"type":"bullet","text":"Progressive replacement of RV (and sometimes LV) myocardium by fibrous and adipose tissue β RV dilation, aneurysm formation, life-threatening ventricular arrhythmias, and SCD."},
{"type":"bullet","text":"Pathological hallmark: fibro-fatty infiltration starting in the 'triangle of dysplasia' (RV outflow tract, RV apex, RV inflow) and progressing epicardium to endocardium."},
{"type":"bullet","text":"Left-dominant ARVC: predominantly LV fibrosis (mid-myocardial LGE) with mild RV involvement; associated with DSP mutations; mimics myocarditis."},
{"type":"head","text":"Genetics β Desmosomal Disease"},
{"type":"bullet","text":"Autosomal dominant with variable penetrance (~40β50%); PKP2 (plakophilin-2) most common mutation (30β45% of cases), followed by DSP (desmoplakin), DSG2, DSC2, JUP."},
{"type":"bullet","text":"Desmosomal dysfunction β mechanical stress during exercise β myocyte apoptosis β fibro-fatty replacement. Exercise and competitive sport dramatically accelerate phenotype expression."},
{"type":"bullet","text":"Naxos disease: autosomal recessive JUP mutation β ARVC + palmoplantar keratoderma + woolly hair (complete penetrance)."},
{"type":"head","text":"Clinical Features in Adolescents"},
{"type":"bullet","text":"Palpitations, exertional syncope, and SCD β predominantly during or after vigorous exercise; most common presentation age 14β35 years."},
{"type":"bullet","text":"ECG: T-wave inversions in V1βV3 (beyond V1 in absence of RBBB), epsilon waves (terminal notch after QRS in V1βV3) in ~25%, prolonged S-wave upstroke >55ms in V1βV3."},
{"type":"bullet","text":"Frequent PVCs with LBBB morphology and superior axis (indicating RV origin); non-sustained or sustained VT with LBBB pattern."},
{"type":"head","text":"2010 Revised Task Force Criteria"},
{"type":"bullet","text":"Major/minor criteria in 5 categories: (1) RV structural dysfunction (echo/CMR/angiography), (2) Tissue characterisation (endomyocardial biopsy), (3) Repolarisation abnormalities (T-wave inversions), (4) Depolarisation/conduction (epsilon waves, SAECG late potentials), (5) Arrhythmia, (6) Family history."},
]
right3 = [
{"type":"head","text":"Echocardiographic Findings"},
{"type":"bullet","text":"RV enlargement: RVOT parasternal long-axis β₯32mm (major) or β₯29mm (minor); RVOT PSAX β₯36mm; RV fractional area change β€33% (major) or β€40% (minor)."},
{"type":"bullet","text":"Regional RV dyskinesia, akinesia, or aneurysm on 2D echo (major criterion when confirmed in β₯2 views)."},
{"type":"head","text":"Cardiac MRI β Gold Standard"},
{"type":"bullet","text":"T1-weighted imaging: hyperintense fat in RV free wall; fat-suppression sequence confirms true fatty infiltration."},
{"type":"bullet","text":"Cine CMR: RV free wall akinesia/dyskinesia, RV aneurysm, RV dilation with RVEDV/BSA β₯110 mL/mΒ² (men) or β₯100 mL/mΒ² (women)."},
{"type":"bullet","text":"Late Gadolinium Enhancement (LGE): subepicardial or mid-myocardial fibrosis in RV and LV free wall; predicts arrhythmic events and guides ablation."},
{"type":"head","text":"Athlete's Heart vs ARVC β Differentiation"},
{"type":"bullet","text":"ARVC: LGE positive, RV dysfunction, epsilon waves, family history, genetic mutation, arrhythmia on exercise testing worsens post-exertion."},
{"type":"bullet","text":"Athlete's Heart: concentric hypertrophy, no LGE, physiological RV dilation (reversible with detraining), normal RV function, no arrhythmia."},
{"type":"head","text":"Management"},
{"type":"bullet","text":"LIFESTYLE: Absolute restriction from competitive sport and vigorous exercise β this is the most important intervention; physical activity perpetuates disease progression."},
{"type":"bullet","text":"ANTIARRHYTHMICS: Beta-blockers (sotalol) first-line; amiodarone for refractory VT; catheter ablation for haemodynamically unstable VT (palliative, not curative)."},
{"type":"bullet","text":"ICD: secondary prevention after cardiac arrest or haemodynamically significant VT; primary prevention in high-risk patients (syncope, severe RV dysfunction, inducible sustained VT)."},
{"type":"bullet","text":"HEART FAILURE: diuretics, ACEi/ARBs, aldosterone antagonists for end-stage biventricular failure; transplantation for refractory disease."},
{"type":"head","text":"Prognosis"},
{"type":"bullet","text":"ARVC is the #1 cause of SCD in young athletes in the Veneto region of Italy (accounts for 22.4% of sudden death in athletes). Annual SCD rate ~0.08β0.1% in ARVC patients; ICD implantation reduces mortality to near-background levels."},
]
bullet_engine(left3, ML, CONT3-6*mm, HALF3, lh=LINE_H*0.94, font_sz=9.1)
bullet_engine(right3, ML+HALF3+6*mm, CONT3-6*mm, HALF3, lh=LINE_H*0.94, font_sz=9.1)
put("Source: Fuster & Hurst's The Heart 15th Ed Β· Braunwald's Heart Disease 12th Ed Β· 2010 Task Force Criteria",
ML, FOOTER_H-0.5*mm, sz=6.5, col=MID_GREY, italic=True)
c.showPage()
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE 4 β RESTRICTIVE CARDIOMYOPATHY
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
page_chrome(4, "ATYPICAL CARDIOMYOPATHY #3",
"Restrictive Cardiomyopathy (RCM)",
"Worst Prognosis Β· Biatrial Dilation Β· Primary Transplant Indication in Children")
TOP4 = H - HEADER_H - 5*mm
IW3 = (BODY_W - 2*4*mm) / 3
img_card("rcm_echo1", ML, TOP4-52*mm, IW3, 41*mm,
"Echo A4C: severe biatrial dilation,", "normal ventricular size & function")
img_card("rcm_ped", ML+IW3+4*mm, TOP4-52*mm, IW3, 41*mm,
"Pediatric RCM: CXR massive", "cardiomegaly + echo biatrial dilation")
img_card("rcm_tdi", ML+2*(IW3+4*mm), TOP4-52*mm, IW3, 41*mm,
"Echo + TDI: biatrial dilation", "reduced septal annular velocity (s')")
CONT4 = TOP4 - 52*mm - 14*mm
section_badge(ML, CONT4, 40*mm, "RCM β FULL OVERVIEW")
HALF4 = BODY_W/2 - 3*mm
left4 = [
{"type":"head","text":"Definition"},
{"type":"bullet","text":"Impaired ventricular filling (diastolic dysfunction) with normal or near-normal LV wall thickness, normal/near-normal LV cavity size, and preserved or mildly reduced systolic function."},
{"type":"bullet","text":"Hallmark: severe biatrial dilation from chronically elevated filling pressures, with relatively small, non-compliant ventricles β 'small ventricles, large atria'."},
{"type":"head","text":"Aetiology in Paediatric RCM"},
{"type":"bullet","text":"Idiopathic RCM: most common in children; sarcomeric gene mutations (TNNI3 most frequent, also MYH7, TPM1, ACTC1, TNNT2) identified in 30β40% of idiopathic cases."},
{"type":"bullet","text":"Storage/metabolic diseases: Gaucher disease (glucocerebrosidase deficiency), Fabry disease (alpha-galactosidase A β X-linked, lysosomal), Pompe disease (acid maltase), Niemann-Pick."},
{"type":"bullet","text":"Amyloidosis: rare in children; systemic AA amyloidosis in heritable autoinflammatory diseases (familial Mediterranean fever, TRAPS); cardiac AL amyloid rare before age 20."},
{"type":"bullet","text":"Hypereosinophilic syndrome (LΓΆffler endocarditis): eosinophil degranulation β endomyocardial damage β progressive fibrosis β restrictive physiology."},
{"type":"bullet","text":"Endomyocardial fibrosis (EMF): common in tropical regions (Africa, South Asia, Brazil); fibrous obliteration of ventricular apex β severe restriction; possible parasitic aetiology (Toxoplasma, Toxocara)."},
{"type":"head","text":"Clinical Features"},
{"type":"bullet","text":"Exercise intolerance and exertional dyspnoea β often the presenting symptom in older children; infants may present with failure to thrive and respiratory distress."},
{"type":"bullet","text":"Signs of venous congestion: hepatomegaly, ascites, peripheral oedema (right-sided); pulmonary oedema, orthopnoea (left-sided). Kussmaul's sign (βJVP on inspiration) may be present."},
{"type":"bullet","text":"Atrial fibrillation/flutter from massive atrial dilation β thromboembolic stroke risk; systemic embolisation occurs in up to 25% of children with RCM."},
{"type":"bullet","text":"Sudden cardiac death risk: higher than in DCM of similar severity due to stretch-induced atrial and ventricular arrhythmias."},
]
right4 = [
{"type":"head","text":"Echocardiographic Findings"},
{"type":"bullet","text":"Apical 4-chamber: massive biatrial dilation with normal or small ventricular cavity; ventricular wall thickness normal or mildly increased."},
{"type":"bullet","text":"Doppler: restrictive filling pattern β E/A ratio >2, deceleration time <150ms, pulmonary vein systolic blunting, tissue Doppler e' <8 cm/s, E/e' >14."},
{"type":"bullet","text":"M-mode: normal LV dimensions, normal LVEF (>50%); absence of LV dilation distinguishes from DCM."},
{"type":"head","text":"Cardiac MRI"},
{"type":"bullet","text":"Global subendocardial LGE: amyloidosis pattern (diffuse, circumferential subendocardial enhancement with characteristic dark blood pool)."},
{"type":"bullet","text":"Apical LGE with obliteration: endomyocardial fibrosis pattern (apical enhancement with obliteration of RV or LV apex)."},
{"type":"bullet","text":"T1 mapping + ECV: elevated extracellular volume fraction in amyloid and storage diseases β quantifies diffuse fibrosis."},
{"type":"head","text":"RCM vs Constrictive Pericarditis"},
{"type":"bullet","text":"RCM: LGE positive, BNP/NT-proBNP markedly elevated, normal pericardial thickness (<4mm), ventricular interdependence absent, tissue Doppler e' reduced."},
{"type":"bullet","text":"Constrictive pericarditis: pericardial calcification/thickening >4mm, septal bounce on M-mode, respiratory variation in mitral/tricuspid Doppler >25%, BNP normal/mildly elevated."},
{"type":"bullet","text":"If storage disease suspected: always perform endomyocardial biopsy + enzyme assay β specific enzyme replacement therapy (ERT) is curative for Fabry and Pompe disease."},
{"type":"head","text":"Management & Prognosis"},
{"type":"bullet","text":"Medical therapy (palliative bridge): diuretics (furosemide, spironolactone) to reduce congestion; anticoagulation (warfarin/LMWH) for AF or thrombus; beta-blockers cautiously for rate control."},
{"type":"bullet","text":"Heart transplantation: only curative option for idiopathic and sarcomeric RCM; median survival without transplant only ~2 years after diagnosis."},
{"type":"bullet","text":"Timing of transplant listing: list EARLY β before pulmonary vascular resistance rises irreversibly (PVR >6 Wood units is a contraindication to transplant)."},
{"type":"bullet","text":"Post-transplant outcomes: 5-year survival ~70β75%; RCM patients have higher post-transplant mortality than DCM due to pre-existing pulmonary hypertension and worse functional status at listing."},
]
bullet_engine(left4, ML, CONT4-6*mm, HALF4, lh=LINE_H*0.94, font_sz=9.1)
bullet_engine(right4, ML+HALF4+6*mm, CONT4-6*mm, HALF4, lh=LINE_H*0.94, font_sz=9.1)
put("Source: Fuster & Hurst's The Heart 15th Ed Β· Braunwald's Heart Disease 12th Ed Β· Paediatric Cardiomyopathy Registry",
ML, FOOTER_H-0.5*mm, sz=6.5, col=MID_GREY, italic=True)
c.showPage()
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE 5 β TAKOTSUBO + ARRHYTHMIA-INDUCED
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
page_chrome(5, "ATYPICAL CARDIOMYOPATHIES #4 & #5",
"Takotsubo & Arrhythmia-Induced Cardiomyopathy",
"Stress Cardiomyopathy Β· PVC-Induced CM Β· Tachycardia-Mediated CM Β· REVERSIBLE")
TOP5 = H - HEADER_H - 5*mm
# Three Takotsubo images
IW3 = (BODY_W - 2*4*mm) / 3
img_card("tako_pot", ML, TOP5-52*mm, IW3, 41*mm,
"Echo vs octopus pot: apical", "ballooning β name origin explained")
img_card("tako_4ch", ML+IW3+4*mm, TOP5-52*mm, IW3, 41*mm,
"A4C systole: apical ballooning", "(red arrow) + basal hyperkinesis")
img_card("tako_thrombus",ML+2*(IW3+4*mm), TOP5-52*mm, IW3, 41*mm,
"Diastole + Systole: apical", "ballooning + apical thrombus")
CONT5 = TOP5 - 52*mm - 14*mm
HALF5 = BODY_W/2 - 3*mm
# Left column β Takotsubo
section_badge(ML, CONT5, 45*mm, "TAKOTSUBO (STRESS) CARDIOMYOPATHY", TEAL)
tako_items = [
{"type":"head","text":"Definition & Mechanism"},
{"type":"bullet","text":"Transient hypocontractility of LV mid-apex with basal hyperkinesis (reverse of normal contraction gradient), creating a balloon-like LV appearance in systole β mimics ACS without obstructive CAD."},
{"type":"bullet","text":"Named after Japanese octopus-trapping pot (tako = octopus, tsubo = pot) due to the characteristic shape of the LV in systole."},
{"type":"bullet","text":"Pathophysiology: massive catecholamine surge β myocardial stunning via cyclic AMP-mediated calcium overload, microvascular spasm, and direct adrenoceptor-mediated cardiotoxicity."},
{"type":"head","text":"Triggers in Children & Adolescents"},
{"type":"bullet","text":"Emotional stress triggers: sudden bereavement, extreme fright, panic attacks, acute anxiety β more common in adolescent girls (sympathetic hyperactivation)."},
{"type":"bullet","text":"Physical stress triggers: critical illness, severe sepsis, anaphylaxis, head trauma, subarachnoid haemorrhage, general anaesthesia, chemotherapy (fluorouracil)."},
{"type":"bullet","text":"Paediatric association: congenital heart disease correction, NICU admission stress, phaeochromocytoma (adrenal catecholamine excess), thyrotoxicosis."},
{"type":"head","text":"Diagnosis"},
{"type":"bullet","text":"Echo: apical ballooning + basal hyperkinesis spanning β₯2 coronary artery territories (hallmark distinction from ACS which follows one territory)."},
{"type":"bullet","text":"ECG: ST elevation (antero-apical leads), deep T-wave inversions, QTc prolongation (risk of TdP arrhythmia in acute phase); troponin mildly elevated."},
{"type":"bullet","text":"Coronary angiography: normal epicardial coronaries (essential to exclude ACS); CMR confirms reversibility on follow-up study."},
{"type":"head","text":"Management"},
{"type":"bullet","text":"Supportive: IV fluids if hypovolaemic; beta-blockers for sympathetic overdrive; anticoagulation for apical thrombus (occurs in 5% of cases)."},
{"type":"bullet","text":"AVOID in LVOTO complication (systolic anterior motion): inotropes (dobutamine) worsen obstruction β use phenylephrine + IV fluids instead."},
{"type":"bullet","text":"Prognosis: full recovery of LV function in 1β4 weeks in >95% of patients; in-hospital mortality ~1β5% (from cardiogenic shock, VF, or LVOTO); recurrence rate ~2β4% per year."},
]
bullet_engine(tako_items, ML, CONT5-6*mm, HALF5, lh=LINE_H*0.93, font_sz=9.1)
# Right column β Arrhythmia-Induced CM
section_badge(ML+HALF5+6*mm, CONT5, 50*mm, "ARRHYTHMIA-INDUCED CARDIOMYOPATHY", TEAL)
arr_items = [
{"type":"head","text":"Definition & Types"},
{"type":"bullet","text":"Tachycardia-induced cardiomyopathy (TIC): persistent tachycardia >115β120 bpm β β filling pressures β biventricular systolic dysfunction β dilated phenotype. Fully REVERSIBLE with arrhythmia control."},
{"type":"bullet","text":"PVC-induced cardiomyopathy: frequent ectopic beats (especially retrograde conduction) β asynchronous contraction β LV dilation/dysfunction independent of tachycardia."},
{"type":"head","text":"Causative Arrhythmias β TIC"},
{"type":"bullet","text":"Atrial: atrial tachycardia (most common), atrial flutter/fibrillation, inappropriate sinus tachycardia."},
{"type":"bullet","text":"Supraventricular: AVRT (WPW syndrome), AVNRT, PJRT (permanent junctional reciprocating tachycardia) β most common TIC cause in infants; 'incessant' nature makes it particularly damaging."},
{"type":"bullet","text":"Ventricular: frequent PVCs, non-sustained/sustained VT; sinus tachycardia has also been reported as a cause in paediatric case series."},
{"type":"head","text":"PVC-Induced Cardiomyopathy β Thresholds"},
{"type":"bullet","text":">20,000 PVCs per 24 hours: associated with subclinical deterioration in LVEF on serial echocardiography."},
{"type":"bullet","text":">10,000 PVCs per 24 hours: associated with LV dilation and measurable change in LVEF (dose-response relationship demonstrated in 239-patient prospective series)."},
{"type":"bullet","text":"In children: proportion of PVC-induced CM appears higher than in adults because ectopy tends to persist throughout follow-up without spontaneous resolution."},
{"type":"head","text":"Diagnosis"},
{"type":"bullet","text":"Clinical: LV dilation + dysfunction without LVH; absence of other non-ischaemic causes; normal LV end-diastolic dimension typically <5.5cm."},
{"type":"bullet","text":"Confirmation: recovery of LV function within 1β6 months after arrhythmia control (rate control, cardioversion, or RFA) is the diagnostic gold standard."},
{"type":"head","text":"Treatment"},
{"type":"bullet","text":"Rate control: beta-blockers, digoxin, calcium channel blockers for rate-related TIC; cardioversion for atrial flutter/fibrillation."},
{"type":"bullet","text":"Radiofrequency catheter ablation (RFA): achieves LVEF normalisation in 47β100% of children after successful ablation of ectopic focus; first-line in children with LV dilation/dysfunction."},
{"type":"bullet","text":"Post-ablation monitoring: repeat echo at 3β6 months; LV parameters normalise rapidly (mean 3β6 months); recurrence of ectopy may require repeat ablation."},
]
bullet_engine(arr_items, ML+HALF5+6*mm, CONT5-6*mm, HALF5, lh=LINE_H*0.93, font_sz=9.1)
# Reversibility key fact
info_strip(ML, FOOTER_H+3*mm, BODY_W, 16*mm,
"KEY TAKE-AWAY: BOTH ARE REVERSIBLE IF TREATED PROMPTLY",
["β’ Takotsubo: full LV recovery in 1β4 weeks in >95% of cases with supportive treatment",
"β’ Arrhythmia-induced CM: LVEF normalisation in 47β100% after arrhythmia control / RFA within 1β6 months",
], bg=TEAL_DK, title_bg=GOLD)
put("Source: Fuster & Hurst's The Heart 15th Ed Β· Braunwald's Heart Disease 12th Ed Β· Paediatric Cardiomyopathy Registry",
ML, FOOTER_H-0.5*mm, sz=6.5, col=MID_GREY, italic=True)
c.showPage()
# ββ Save ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
c.save()
sz = os.path.getsize(OUT) // 1024
print(f"\nβ Saved: {OUT} ({sz} KB)")
Failed to create session: unauthorized: authentication failed: Bearer token is invalid
We encountered an error while processing your request. Please try again or reach out to us for help.
I'm a 4th year MBBS student Create a A4 size presentation of 5 pages on the topic with pictures from the web "Atypical forms of cardiomyopathy in children and adolescents."
left ventricular non-compaction LVNC echocardiogram pediatric spongy trabeculations
arrhythmogenic right ventricular cardiomyopathy ARVC MRI fibro-fatty pediatric
restrictive cardiomyopathy children biatrial dilation echocardiogram pediatric
Takotsubo stress cardiomyopathy apical ballooning echocardiogram
mkdir -p /home/daytona/workspace/cardiomyopathy-pdf && python3 -c "import reportlab; print('OK', reportlab.Version)"
~/cardiomyopathy-pdf/build.py
"""
Atypical Forms of Cardiomyopathy in Children & Adolescents
5-page A4 PDF | 20+ bullet lines per page | Multiple images per page
ReportLab canvas β pixel-perfect coordinate alignment
"""
import urllib.request, io, os
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm
from reportlab.lib.colors import HexColor
from reportlab.pdfgen import canvas as rl_canvas
from reportlab.lib.utils import ImageReader
W, H = A4 # 595.28 x 841.89 pt
OUT = "/home/daytona/workspace/cardiomyopathy-pdf/Atypical_Cardiomyopathy_Children.pdf"
# ββ Colour palette (Navy / Teal / Gold) ββββββββββββββββββββββββββββββββββββββ
NAVY = HexColor("#0B1F3A")
TEAL = HexColor("#1A8C8A")
TEAL2 = HexColor("#126362")
GOLD = HexColor("#F0B429")
LTBLUE = HexColor("#EAF2F8")
BODYTEXT = HexColor("#1E2A38")
MIDGREY = HexColor("#5D7080")
LINECLR = HexColor("#C5D8E8")
WHITE = HexColor("#FFFFFF")
RED = HexColor("#C0392B")
GREEN = HexColor("#1A7A4A")
PALEBLUE = HexColor("#F4F8FB")
# ββ Fixed layout grid ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
LBAR = 10*mm # left colour bar
RBAR = 9*mm # right colour bar
ML = LBAR + 6*mm # main left margin (17 mm from page left)
MR = RBAR + 5*mm # right margin (14 mm from page right)
BW = W - ML - MR # body width β 164 mm
HDR_H = 33*mm # header zone height
FTR_H = 9*mm # footer height
# ββ Bullet geometry (ALL bullets share identical x-coords β perfect alignment)
BX = ML + 4*mm # bullet symbol x
TX = ML + 9*mm # bullet text x
SBX = ML + 9*mm # sub-bullet symbol x
STX = ML + 14*mm # sub-bullet text x
LH = 5.3*mm # standard line height
# ββ Image URLs ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
URLS = {
"lvnc_2panel": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_94d0d4c659ecda38390bba36342535f0c5d3d9d51c431a093333d40eb61dd304.jpg",
"lvnc_ratio": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_abfdedd879219630bb2a7ba6b6c399eb916263cf066b318e70a7a163cf59fdc2.jpg",
"lvnc_plax": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_b92f6c946254e28593bedfeaffc31636f01d3c54a0ece6ad2fe97cb5834e1a79.jpg",
"arvc_mri": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_ccef375d42502a4932535f5fd1be880aeaf424994e8a3739b42f1dba5c0d308a.jpg",
"arvc_4panel": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_a3e0d6cb91e2172ed02e53ddf5b9ec43c9b44cc0833909fab5653447edc82bd8.jpg",
"arvc_histo": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_e3cb9479b2a542bd456ffbedfbe10a06515867a8ff5bfe40ded9a0765043e76e.jpg",
"rcm_ped": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_24ebe5d5c428d8222d2f458d7b08c986c1c4f84a18fb4e230f5839fa71b2addd.jpg",
"rcm_echo": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_d1d8720fff2d4e78cc9b503048bfa103f00204073666a10de82dbff0f50990ae.jpg",
"rcm_tdi": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_2f8a7bcc4759eea4457abb6d5f9b22818a74d4b522f01aaee71d49f77cad1ec1.jpg",
"tako_4ch": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_c6021993840345b8856726d8526734bbd273e014a562a1a7c11bf144d093da75.jpg",
"tako_2ch": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_d1d2e55c2ca2a38a28a877829beda1761c97098b5173ebb40a3b8cfc8231bdca.jpg",
"tako_throm": "https://cdn.orris.care/cdss_images/pmc_clinical_VQA_b9ab045fcfda8e091c86fb523d1711b2eab60e56bb6c05412dd3547586acc826.jpg",
}
def fetch(url):
try:
r = urllib.request.Request(url, headers={"User-Agent":"Mozilla/5.0"})
d = urllib.request.urlopen(r, timeout=15).read()
return ImageReader(io.BytesIO(d))
except Exception as e:
print(f" FAIL {url[-45:]}: {e}"); return None
print("Downloading imagesβ¦")
IMGS = {k: fetch(v) for k, v in URLS.items()}
print({k: "OK" if v else "X" for k,v in IMGS.items()})
c = rl_canvas.Canvas(OUT, pagesize=A4)
c.setTitle("Atypical Cardiomyopathy in Children and Adolescents")
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# DRAWING PRIMITIVES
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def fr(x,y,w,h,col,r=0):
c.saveState(); c.setFillColor(col); c.setStrokeColor(HexColor("#00000000"))
if r: c.roundRect(x,y,w,h,r,fill=1,stroke=0)
else: c.rect(x,y,w,h,fill=1,stroke=0)
c.restoreState()
def sr(x,y,w,h,fc,sc,lw=0.5):
c.saveState(); c.setFillColor(fc); c.setStrokeColor(sc); c.setLineWidth(lw)
c.rect(x,y,w,h,fill=1,stroke=1); c.restoreState()
def hl(x1,y,x2,col=GOLD,lw=1.2):
c.saveState(); c.setStrokeColor(col); c.setLineWidth(lw)
c.line(x1,y,x2,y); c.restoreState()
def pt(s,x,y,sz=9.5,col=BODYTEXT,bold=False,italic=False):
c.saveState(); c.setFillColor(col)
f = "Helvetica-Bold" if bold and not italic else \
"Helvetica-BoldOblique" if bold and italic else \
"Helvetica-Oblique" if italic else "Helvetica"
c.setFont(f,sz); c.drawString(x,y,s); c.restoreState()
def ptc(s,cx,y,sz=9.5,col=BODYTEXT,bold=False):
f = "Helvetica-Bold" if bold else "Helvetica"
c.saveState(); c.setFont(f,sz); c.setFillColor(col)
c.drawCentredString(cx,y,s); c.restoreState()
def img(key,x,y,w,h):
im = IMGS.get(key)
if not im: return
iw,ih = im.getSize()
sc = min(w/iw, h/ih)
nw,nh = iw*sc, ih*sc
c.drawImage(im, x+(w-nw)/2, y+(h-nh)/2, nw, nh,
preserveAspectRatio=True, mask="auto")
def img_card(key,x,y,w,h,cap1,cap2=""):
"""Image card: white border, image, teal caption strip."""
sr(x,y,w,h+10*mm,PALEBLUE,LINECLR,0.5)
img(key,x+1*mm,y+10*mm,w-2*mm,h-1*mm)
fr(x,y,w,10*mm,LTBLUE)
c.setFont("Helvetica-Oblique",7.5); c.setFillColor(TEAL2)
c.drawCentredString(x+w/2,y+6.8*mm,cap1)
if cap2: c.drawCentredString(x+w/2,y+2.8*mm,cap2)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE CHROME
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def chrome(pg, sup, title, sub=""):
fr(0,0,W,H,PALEBLUE) # page bg
fr(0,0,LBAR,H,TEAL) # left bar
fr(W-RBAR,0,RBAR,H,NAVY) # right bar
fr(LBAR,H-HDR_H,W-LBAR-RBAR,HDR_H,NAVY) # header band
fr(LBAR,H-2*mm,W-LBAR-RBAR,2*mm,GOLD) # gold top rule
# Page number badge
fr(0,H-HDR_H,LBAR,12*mm,GOLD)
ptc(str(pg),LBAR/2,H-HDR_H+4*mm,sz=11,col=NAVY,bold=True)
# Header text
pt(sup, ML,H-10*mm,sz=8,col=LTBLUE,italic=True)
pt(title,ML,H-23*mm,sz=21,col=GOLD,bold=True)
if sub: pt(sub,ML,H-30*mm,sz=9.5,col=LINECLR,italic=True)
hl(ML,H-HDR_H+1.5*mm,W-RBAR-2*mm,GOLD,1.5)
# Footer
fr(LBAR,0,W-LBAR-RBAR,FTR_H,NAVY)
c.setFont("Helvetica",7); c.setFillColor(LINECLR)
c.drawCentredString((LBAR+W-RBAR)/2,3*mm,
"Atypical Cardiomyopathy in Children & Adolescents Β· 4th Year MBBS Β· 2026")
pt(f"Page {pg}/5",W-RBAR-20*mm,3*mm,sz=7.5,col=GOLD,bold=True)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# BULLET ENGINE β PERFECTLY ALIGNED
# All bullets share fixed BX / TX coordinates regardless of column
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def bullets(items, col_x, y_start, col_w, lh=LH, fsz=9.3):
"""
items: list of dicts
type "H" β section heading (bold teal)
type "B" β bullet β’ with word-wrap
type "S" β sub-bullet β¦ indented
type "G" β small gap
type "R" β thin rule
col_x : left edge of this column
col_w : usable width of this column
Returns final y.
"""
bx = col_x + 4*mm # bullet dot x
tx = col_x + 9*mm # bullet text x
sbx = col_x + 9*mm # sub-dot x
stx = col_x + 14*mm # sub text x
wrap_b = col_w - 9*mm - 1*mm # wrap width for bullets
wrap_s = col_w - 14*mm - 1*mm # wrap width for sub-bullets
cy = y_start
def draw_wrapped(text, start_x, wrap_w, fnt, sz, col):
nonlocal cy
words = text.split()
seg = ""
c.saveState(); c.setFont(fnt,sz); c.setFillColor(col)
for w in words:
test = (seg+" "+w).strip()
if c.stringWidth(test,fnt,sz) <= wrap_w:
seg = test
else:
if seg: c.drawString(start_x,cy,seg); cy -= lh
seg = w
if seg: c.drawString(start_x,cy,seg); cy -= lh
c.restoreState()
for item in items:
t = item["t"]
if t == "G":
cy -= lh*0.45
elif t == "R":
hl(col_x+2*mm, cy+lh*0.35, col_x+col_w-2*mm, LINECLR, 0.5)
cy -= lh*0.55
elif t == "H":
cy -= lh*0.25
c.saveState(); c.setFont("Helvetica-Bold",10.5); c.setFillColor(TEAL)
c.drawString(col_x+2*mm,cy,item["v"])
c.restoreState(); cy -= lh*1.1
elif t == "B":
# bullet symbol β always at bx
c.saveState(); c.setFont("Helvetica-Bold",fsz+1); c.setFillColor(GOLD)
c.drawString(bx,cy,"\u2022")
c.restoreState()
# text β always starting at tx
draw_wrapped(item["v"], tx, wrap_b, "Helvetica", fsz, BODYTEXT)
cy -= lh*0.12
elif t == "S":
c.saveState(); c.setFont("Helvetica",fsz-0.5); c.setFillColor(MIDGREY)
c.drawString(sbx,cy,"\u25e6")
c.restoreState()
draw_wrapped(item["v"], stx, wrap_s, "Helvetica", fsz-0.5, MIDGREY)
cy -= lh*0.08
return cy
def badge(x,y,w,label,bg=TEAL,fg=WHITE):
fr(x,y-5.5*mm,w,6*mm,bg,r=1)
ptc(label,x+w/2,y-3.3*mm,sz=8.5,col=fg,bold=True)
def infobar(x,y,w,h,title,lines,bg=NAVY,tbg=GOLD):
fr(x,y,w,h,bg,r=2)
fr(x,y+h-7.5*mm,w,7.5*mm,tbg,r=2)
fr(x,y+h-7.5*mm,w,4*mm,tbg)
pt(title,x+3*mm,y+h-5.5*mm,sz=9.5,col=NAVY,bold=True)
iy = y+h-12.5*mm
for ln in lines:
if ln=="": iy-=2.5*mm; continue
c.saveState(); c.setFont("Helvetica",9); c.setFillColor(LTBLUE)
c.drawString(x+4*mm,iy,ln); c.restoreState(); iy-=5*mm
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE 1 β TITLE + OVERVIEW
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
chrome(1,"PAEDIATRIC CARDIOLOGY Β· ATYPICAL CARDIOMYOPATHIES",
"ATYPICAL CARDIOMYOPATHY","in Children and Adolescents")
# Four topic cards
CTOP = H-HDR_H-5*mm
CW4 = (BW-3*3*mm)/4
topics=[("01","Left Ventricular\nNon-Compaction\n(LVNC)"),
("02","Arrhythmogenic RV\nCardiomyopathy\n(ARVC)"),
("03","Restrictive\nCardiomyopathy\n(RCM)"),
("04","Takotsubo &\nArrhythmia-Induced\nCM")]
for i,(num,lbl) in enumerate(topics):
cx=ML+i*(CW4+3*mm); cy=CTOP-28*mm
sr(cx,cy,CW4,28*mm,WHITE,LINECLR,0.5)
fr(cx,cy+20*mm,CW4,8*mm,TEAL,r=1); fr(cx,cy+20*mm,CW4,4*mm,TEAL)
ptc(num,cx+CW4/2,cy+23.5*mm,sz=14,col=GOLD,bold=True)
for li,ll in enumerate(lbl.split("\n")):
ptc(ll,cx+CW4/2,cy+16*mm-li*5.2*mm,sz=8.2,col=BODYTEXT)
OVY=CTOP-33*mm
badge(ML,OVY,70*mm,"OVERVIEW & AHA CLASSIFICATION")
ov=[
{"t":"B","v":"Cardiomyopathies = structural/functional myocardial abnormalities unexplained by CAD, hypertension, or valvular disease."},
{"t":"B","v":"Atypical paediatric cardiomyopathies include: LVNC, ARVC, RCM, Takotsubo (stress-induced), and arrhythmia-induced CM."},
{"t":"B","v":"AHA Scientific Statement 'Cardiomyopathy in Children: Classification and Diagnosis' uses a hierarchical system: structural/functional phenotype β genetic/non-genetic subcategories."},
{"t":"B","v":"Paediatric CMs carry substantial morbidity and mortality; the primary indication for heart transplantation in children >1 year of age."},
{"t":"B","v":"'Children are NOT small adults' β extreme aetiology heterogeneity, more syndromic associations, metabolic diseases, and a separate diagnostic framework are required."},
{"t":"B","v":"MOGE(S) classification (Morphofunctional, Organ, Genetic pattern, Aetiology, Stage) is the internationally endorsed comprehensive nosology."},
{"t":"B","v":"Annual incidence of CM in children β 1.1 per 100,000; DCM 58%, HCM 25%, atypical forms β 17% of all cases (Paediatric Cardiomyopathy Registry)."},
{"t":"B","v":"Diagnostic workup: TTE/TEE, cardiac MRI with LGE, Holter monitoring, genetic panel (MYH7, MYBPC3, PKP2, DSP, TAZ, TNNI3), metabolic/enzyme screening."},
{"t":"B","v":"Family screening: first-degree relatives of index cases require echo + ECG; cascade genetic testing recommended when pathogenic variant identified."},
{"t":"G"},
]
bullets(ov, ML, OVY-6*mm, BW, lh=LH*0.97, fsz=9.3)
infobar(ML,FTR_H+2*mm,BW,22*mm,"KEY PRINCIPLES IN PAEDIATRIC CARDIOMYOPATHY",
["β’ Always exclude metabolic/storage diseases (Pompe, Fabry, Gaucher, Barth) before labelling 'idiopathic'",
"β’ Genetic panel essential for all index cases β guides family screening and future gene therapy eligibility",
"β’ All atypical CMs require referral to a specialist paediatric cardiac centre for multidisciplinary management"])
pt("Source: Fuster & Hurst's The Heart 15th Ed Β· Braunwald's Heart Disease 12th Ed Β· AHA Scientific Statement",
ML,FTR_H-1*mm,sz=6.5,col=MIDGREY,italic=True)
c.showPage()
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE 2 β LVNC
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
chrome(2,"ATYPICAL CARDIOMYOPATHY #1",
"Left Ventricular Non-Compaction (LVNC)",
"Spongy Myocardium Β· 3rd Most Common Paediatric CM Β· Genetic / Metabolic")
T2=H-HDR_H-5*mm
IW=(BW-2*4*mm)/3
img_card("lvnc_2panel",ML, T2-49*mm,IW,38*mm,"A4C+PSAX: spongy LV apex,","deep intertrabecular recesses")
img_card("lvnc_ratio", ML+IW+4*mm, T2-49*mm,IW,38*mm,"TEE SAX: X/Y <0.5 ratio","compacted vs non-compacted")
img_card("lvnc_plax", ML+2*(IW+4*mm),T2-49*mm,IW,38*mm,"PLAX: spongy 2-layer LV","wall β dilated phenotype")
C2=T2-49*mm-13*mm
badge(ML,C2,35*mm,"LVNC β FULL NOTES")
HW=BW/2-3*mm
left2=[
{"t":"H","v":"Definition & Embryology"},
{"t":"B","v":"Failure of normal myocardial compaction during embryogenesis (weeks 5β8) β spongy inner non-compacted layer + deep intertrabecular recesses communicating with LV cavity."},
{"t":"B","v":"Compaction proceeds baseβapex and epicardiumβendocardium; arrest at any stage produces LVNC phenotype."},
{"t":"H","v":"Epidemiology"},
{"t":"B","v":"3rd most common paediatric CM (~9.2% of cases). Paediatric CM Registry: 4.8% of 3,219 children; incidence <0.1 per 100,000/year."},
{"t":"B","v":"Overdiagnosis risk: CMR prevalence 14.79% vs echo 1.28% in healthy volunteers; clinical context essential."},
{"t":"H","v":"Echocardiographic Criteria"},
{"t":"B","v":"Jenni (2001): NC/C ratio >2:1 at end-systole (PSAX); colour Doppler shows flow into recesses."},
{"t":"B","v":"Chin (1990): X/Y ratio <0.5 at end-diastole."},
{"t":"B","v":"StΓΆllberger: >3 trabeculations apical to papillary muscles; intertrabecular spaces perfused from LV cavity."},
{"t":"H","v":"Genetics"},
{"t":"B","v":"Sarcomeric: MYH7, MYBPC3, ACTC1, TPM1, TNNT2 β shared with HCM/DCM."},
{"t":"B","v":"X-linked TAZ (tafazzin) β Barth syndrome: LVNC + skeletal myopathy + neutropenia + 3-methylglutaconic aciduria (males only, infancy onset)."},
{"t":"B","v":"Others: LDB3, DTNA, SCN5A (arrhythmia-dominant), RYR2, LMNA β autosomal dominant inheritance."},
{"t":"H","v":"Cardiac MRI"},
{"t":"B","v":"Petersen criterion: NC >2.3Γ compacted at end-diastole in CMR SAX slices (sensitivity 86%, specificity 99%)."},
{"t":"B","v":"LGE (mid-myocardial or subendocardial fibrosis) predicts adverse outcomes β SCD and HF hospitalisation."},
]
right2=[
{"t":"H","v":"Clinical Features β Classic Triad"},
{"t":"B","v":"(1) Heart failure: dilated phenotype, reduced LVEF; symptomatic children often present in early infancy."},
{"t":"B","v":"(2) Ventricular arrhythmias: VT, WPW syndrome, complete heart block; SCD risk elevated with LVEF <35% or sustained VT."},
{"t":"B","v":"(3) Systemic thromboembolism: apical thrombus in trabecular recesses β stroke risk; anticoagulation often required."},
{"t":"H","v":"Management β Heart Failure"},
{"t":"B","v":"ACE inhibitors/ARBs + beta-blockers (carvedilol or metoprolol succinate) + loop diuretics as per HF guidelines."},
{"t":"B","v":"Cardiac resynchronisation therapy (CRT) for LBBB + LVEF β€35%; biventricular pacing improves synchrony."},
{"t":"H","v":"Management β Thromboembolism"},
{"t":"B","v":"Anticoagulation (warfarin/LMWH) indicated for: apical thrombus, LVEF <35%, AF, or prior embolic event."},
{"t":"B","v":"Aspirin alone insufficient for intra-trabecular thrombus β full anticoagulation recommended."},
{"t":"H","v":"Management β Arrhythmia / SCD"},
{"t":"B","v":"ICD: secondary prevention after cardiac arrest or haemodynamically significant VT; primary prevention in high-risk phenotype."},
{"t":"B","v":"Catheter ablation for accessory pathway (WPW) or refractory VT; not curative for LVNC-related VT."},
{"t":"H","v":"Prognosis"},
{"t":"B","v":"Worse than DCM when symptomatic in infancy. 5-year transplant-free survival β75β85% in mild/asymptomatic; <50% with acute decompensated HF at presentation."},
{"t":"B","v":"Isolated LVNC with preserved EF: favourable prognosis β low event rates over 3.3-year follow-up (Paediatric CM Registry data)."},
{"t":"B","v":"Heart transplantation for end-stage HF; post-transplant outcomes equivalent to other cardiomyopathies."},
]
bullets(left2, ML, C2-6*mm, HW, lh=LH*0.95, fsz=9.1)
bullets(right2,ML+HW+6*mm,C2-6*mm,HW, lh=LH*0.95, fsz=9.1)
pt("Source: Fuster & Hurst's The Heart 15th Ed (Ch.45) Β· Paediatric Cardiomyopathy Registry Β· Braunwald's Heart Disease",
ML,FTR_H-1*mm,sz=6.5,col=MIDGREY,italic=True)
c.showPage()
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE 3 β ARVC
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
chrome(3,"ATYPICAL CARDIOMYOPATHY #2",
"Arrhythmogenic RV Cardiomyopathy (ARVC)",
"Fibro-fatty Replacement Β· Desmosomal Mutations Β· #1 Cause of SCD in Young Athletes")
T3=H-HDR_H-5*mm
IW3=(BW-2*4*mm)/3
img_card("arvc_mri", ML, T3-51*mm,IW3,40*mm,"Cardiac MRI axial: RV dilation","fibro-fatty wall + aneurysm")
img_card("arvc_4panel",ML+IW3+4*mm, T3-51*mm,IW3,40*mm,"Multimodal: echo+T1+T2+","fat-suppressed MRI (4 panels)")
img_card("arvc_histo", ML+2*(IW3+4*mm),T3-51*mm,IW3,40*mm,"MRI+histology: transmural","fibro-fatty RV replacement")
C3=T3-51*mm-13*mm
badge(ML,C3,35*mm,"ARVC β FULL NOTES")
HW3=BW/2-3*mm
left3=[
{"t":"H","v":"Definition & Pathology"},
{"t":"B","v":"Progressive replacement of RV (and sometimes LV) myocardium by fibrous and adipose tissue β RV dilation, aneurysm, lethal ventricular arrhythmias, sudden cardiac death."},
{"t":"B","v":"Fibro-fatty infiltration begins in the 'triangle of dysplasia' (RVOT, RV apex, RV inflow); progresses epicardiumβendocardium."},
{"t":"B","v":"Left-dominant ARVC: LV fibrosis (mid-myocardial LGE) with mild RV involvement; associated with DSP mutations; mimics myocarditis."},
{"t":"H","v":"Genetics β Desmosomal Disease"},
{"t":"B","v":"Autosomal dominant, penetrance 40β50%; PKP2 (plakophilin-2) most common (30β45%), followed by DSP, DSG2, DSC2, JUP."},
{"t":"B","v":"Desmosomal dysfunction β mechanical stress during exercise β myocyte apoptosis β fibro-fatty replacement; exercise dramatically accelerates phenotype expression."},
{"t":"B","v":"Naxos disease: autosomal recessive JUP mutation β ARVC + palmoplantar keratoderma + woolly hair (complete penetrance, paediatric onset)."},
{"t":"H","v":"Clinical Features in Adolescents"},
{"t":"B","v":"Palpitations, exertional syncope, SCD β predominantly during or post vigorous exercise; peak presentation age 14β35 years."},
{"t":"B","v":"ECG: T-wave inversions V1βV3 (beyond V1 without RBBB), epsilon waves (~25%), prolonged S-wave upstroke >55ms in V1βV3."},
{"t":"B","v":"Frequent PVCs with LBBB morphology and superior axis (RV origin); non-sustained or sustained VT with LBBB pattern."},
{"t":"H","v":"2010 Revised Task Force Criteria"},
{"t":"B","v":"Five categories: (1) RV structural/functional abnormality (echo/CMR), (2) Tissue characterisation (biopsy), (3) Repolarisation (T inversions V1βV3), (4) Depolarisation (epsilon waves, SAECG late potentials), (5) Arrhythmia + family history/genetics."},
{"t":"B","v":"Definite ARVC: 2 major, OR 1 major+2 minor, OR 4 minor criteria from different categories."},
]
right3=[
{"t":"H","v":"Echocardiographic Findings"},
{"t":"B","v":"RVOT PLAX β₯32mm (major) or β₯29mm (minor); RVOT PSAX β₯36mm; fractional area change β€33% (major) or β€40% (minor)."},
{"t":"B","v":"Regional RV akinesia/dyskinesia/aneurysm confirmed in β₯2 views = major criterion."},
{"t":"H","v":"Cardiac MRI β Gold Standard for Tissue"},
{"t":"B","v":"T1-weighted: hyperintense fat in RV free wall; fat-suppression sequence confirms true intramyocardial fatty infiltration."},
{"t":"B","v":"Cine CMR: RV free wall akinesia/aneurysm; RVEDV/BSA β₯110 mL/mΒ² (men) or β₯100 mL/mΒ² (women) = major criterion."},
{"t":"B","v":"LGE (subepicardial/mid-myocardial fibrosis in RV and LV free wall): predicts arrhythmic events; guides catheter ablation mapping."},
{"t":"H","v":"Athlete's Heart vs ARVC"},
{"t":"B","v":"ARVC: LGE positive, RV dysfunction, epsilon waves, family history/genetics, arrhythmia worsens post-exertion."},
{"t":"B","v":"Athlete's Heart: physiological RV dilation (reversible with detraining), normal function, no LGE, no arrhythmia."},
{"t":"H","v":"Management"},
{"t":"B","v":"LIFESTYLE: Absolute restriction from competitive sport β most important single intervention; exercise perpetuates disease progression."},
{"t":"B","v":"ANTIARRHYTHMICS: Beta-blockers (sotalol) first-line; amiodarone for refractory VT; catheter ablation palliative (not curative)."},
{"t":"B","v":"ICD: secondary prevention post cardiac arrest or haemodynamically significant VT; primary prevention in high-risk patients."},
{"t":"B","v":"HEART FAILURE: ACEi/ARBs, diuretics, aldosterone antagonists for end-stage biventricular disease; transplantation for refractory disease."},
{"t":"H","v":"Prognosis"},
{"t":"B","v":"#1 cause SCD in young athletes in Italy's Veneto region (22.4% of athletic SCD). Annual SCD rate β0.08β0.1%; ICD reduces mortality to near-background levels."},
]
bullets(left3, ML, C3-6*mm,HW3,lh=LH*0.94,fsz=9.1)
bullets(right3,ML+HW3+6*mm,C3-6*mm,HW3,lh=LH*0.94,fsz=9.1)
pt("Source: Fuster & Hurst's The Heart 15th Ed Β· Braunwald's Heart Disease 12th Ed Β· 2010 Revised Task Force Criteria",
ML,FTR_H-1*mm,sz=6.5,col=MIDGREY,italic=True)
c.showPage()
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE 4 β RESTRICTIVE CARDIOMYOPATHY
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
chrome(4,"ATYPICAL CARDIOMYOPATHY #3",
"Restrictive Cardiomyopathy (RCM)",
"Worst Prognosis Β· Biatrial Dilation Β· Primary Paediatric Transplant Indication")
T4=H-HDR_H-5*mm
IW4=(BW-2*4*mm)/3
img_card("rcm_ped", ML, T4-51*mm,IW4,40*mm,"Paediatric RCM: CXR cardiomegaly","+ echo biatrial dilation (3yr-old)")
img_card("rcm_echo",ML+IW4+4*mm, T4-51*mm,IW4,40*mm,"Echo A4C: massive biatrial dilation","normal ventricular size β RCM pattern")
img_card("rcm_tdi", ML+2*(IW4+4*mm),T4-51*mm,IW4,40*mm,"Echo+TDI: biatrial dilation","reduced annular velocity (s'β5cm/s)")
C4=T4-51*mm-13*mm
badge(ML,C4,35*mm,"RCM β FULL NOTES")
HW4=BW/2-3*mm
left4=[
{"t":"H","v":"Definition"},
{"t":"B","v":"Impaired ventricular filling (diastolic dysfunction) with normal/near-normal LV wall thickness, normal LV cavity size, and preserved or mildly reduced LVEF."},
{"t":"B","v":"Hallmark: severe biatrial dilation from chronically elevated filling pressures β 'small ventricles, large atria'."},
{"t":"H","v":"Aetiology in Children"},
{"t":"B","v":"Idiopathic (most common): sarcomeric mutations in 30β40% β TNNI3 (most frequent), MYH7, TPM1, ACTC1, TNNT2."},
{"t":"B","v":"Storage/metabolic: Gaucher (glucocerebrosidase), Fabry (alpha-galactosidase A, X-linked), Pompe (acid maltase), Niemann-Pick."},
{"t":"B","v":"Amyloidosis (rare in children): systemic AA amyloid in hereditary autoinflammatory diseases (FMF, TRAPS)."},
{"t":"B","v":"Hypereosinophilic syndrome (LΓΆffler endocarditis): eosinophil degranulation β endomyocardial damage β fibrosis."},
{"t":"B","v":"Endomyocardial fibrosis (EMF): tropical regions; fibrous obliteration of ventricular apex; possible parasitic aetiology."},
{"t":"H","v":"Clinical Features"},
{"t":"B","v":"Exercise intolerance, exertional dyspnoea (older children); failure to thrive, respiratory distress (infants)."},
{"t":"B","v":"Right-sided congestion: hepatomegaly, ascites, peripheral oedema; Kussmaul's sign may be present."},
{"t":"B","v":"Atrial fibrillation/flutter from massive atrial dilation β thromboembolic stroke risk in up to 25% of children."},
{"t":"B","v":"Sudden cardiac death risk: higher than DCM of similar severity due to stretch-induced atrial and ventricular arrhythmias."},
{"t":"H","v":"Echocardiographic Findings"},
{"t":"B","v":"A4C: massive biatrial dilation with normal/small ventricles; normal or mildly increased wall thickness."},
{"t":"B","v":"Doppler: E/A >2, DT <150ms, pulmonary vein systolic blunting, tissue Doppler e' <8cm/s, E/e' >14."},
]
right4=[
{"t":"H","v":"Cardiac MRI Findings"},
{"t":"B","v":"Amyloid pattern: global subendocardial LGE (diffuse, circumferential) with dark blood pool β characteristic appearance."},
{"t":"B","v":"EMF pattern: apical LGE with obliteration of RV or LV apex; thickened endocardium on SSFP sequences."},
{"t":"B","v":"T1 mapping + ECV: elevated extracellular volume fraction quantifies diffuse fibrosis in storage diseases and amyloid."},
{"t":"H","v":"RCM vs Constrictive Pericarditis"},
{"t":"B","v":"RCM: LGE positive, NT-proBNP markedly elevated, normal pericardial thickness, tissue Doppler e' reduced, no septal bounce."},
{"t":"B","v":"Constrictive pericarditis: pericardial thickening >4mm/calcification, septal bounce, respiratory Doppler variation >25%, NT-proBNP near-normal."},
{"t":"B","v":"Always biopsy if storage disease suspected β enzyme replacement therapy (ERT) is curative for Fabry and Pompe disease."},
{"t":"H","v":"Management"},
{"t":"B","v":"Medical (bridge therapy): loop diuretics to reduce congestion; anticoagulation (warfarin/LMWH) for AF or thrombus."},
{"t":"B","v":"Beta-blockers used cautiously for rate control only; avoid aggressive afterload reduction (preload-dependent circulation)."},
{"t":"H","v":"Heart Transplantation"},
{"t":"B","v":"Only curative option for idiopathic and sarcomeric RCM; median survival without transplant <2 years from diagnosis."},
{"t":"B","v":"List EARLY β before pulmonary vascular resistance rises irreversibly; PVR >6 Wood units = contraindication."},
{"t":"B","v":"Post-transplant 5-year survival β70β75%; higher post-transplant mortality than DCM due to pre-existing PH."},
{"t":"H","v":"Prognosis"},
{"t":"B","v":"Worst prognosis among all paediatric CMs. Children present at younger age and have more rapid decline than adults."},
{"t":"B","v":"Systemic embolisation, arrhythmic death, and refractory heart failure are the main causes of death without transplant."},
]
bullets(left4, ML, C4-6*mm,HW4,lh=LH*0.94,fsz=9.1)
bullets(right4,ML+HW4+6*mm,C4-6*mm,HW4,lh=LH*0.94,fsz=9.1)
pt("Source: Fuster & Hurst's The Heart 15th Ed Β· Braunwald's Heart Disease 12th Ed Β· Paediatric Cardiomyopathy Registry",
ML,FTR_H-1*mm,sz=6.5,col=MIDGREY,italic=True)
c.showPage()
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PAGE 5 β TAKOTSUBO + ARRHYTHMIA-INDUCED CM
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
chrome(5,"ATYPICAL CARDIOMYOPATHIES #4 & #5",
"Takotsubo & Arrhythmia-Induced CM",
"Stress-Induced Β· PVC-Induced Β· Tachycardia-Mediated Β· BOTH FULLY REVERSIBLE")
T5=H-HDR_H-5*mm
IW5=(BW-2*4*mm)/3
img_card("tako_4ch", ML, T5-51*mm,IW5,40*mm,"A4C: LV apical ballooning","(blue arrows) + basal hyperkinesis")
img_card("tako_2ch", ML+IW5+4*mm, T5-51*mm,IW5,40*mm,"2-chamber systole: 'octopus","pot' apical dilation (white arrow)")
img_card("tako_throm",ML+2*(IW5+4*mm),T5-51*mm,IW5,40*mm,"Diastole+systole: apical","ballooning + apical thrombus")
C5=T5-51*mm-13*mm
HW5=BW/2-3*mm
# ββ LEFT: Takotsubo ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
badge(ML,C5,50*mm,"TAKOTSUBO (STRESS) CARDIOMYOPATHY",TEAL)
tako=[
{"t":"H","v":"Definition & Mechanism"},
{"t":"B","v":"Transient hypocontractility of LV mid-apex with basal hyperkinesis (reverse of normal gradient) β balloon-like LV in systole; mimics ACS without obstructive CAD."},
{"t":"B","v":"Name: Japanese octopus pot (takotsubo) β describes the characteristic shape of the LV in systole."},
{"t":"B","v":"Pathophysiology: massive catecholamine surge β cyclic AMP-mediated calcium overload + microvascular spasm + direct adrenoceptor cardiotoxicity."},
{"t":"H","v":"Triggers in Children & Adolescents"},
{"t":"B","v":"Emotional: sudden bereavement, acute panic/fright β adolescent girls; neurological events (SAH, seizure) β catecholamine surge."},
{"t":"B","v":"Physical: critical illness, sepsis, anaphylaxis, general anaesthesia, chemotherapy (5-FU, immunotherapy), phaeochromocytoma."},
{"t":"B","v":"Paediatric: CHD surgical correction, NICU admission stress, thyrotoxicosis β less common than adults but well documented."},
{"t":"H","v":"Diagnosis"},
{"t":"B","v":"Echo: apical ballooning spanning β₯2 coronary territories (key distinction from ACS which follows one artery territory)."},
{"t":"B","v":"ECG: ST elevation (antero-apical leads), deep T-wave inversions, QTc prolongation (risk of TdP); troponin mildly elevated."},
{"t":"B","v":"Coronary angiography: normal epicordial coronaries essential to exclude ACS; CMR confirms reversibility on follow-up scan."},
{"t":"H","v":"Management"},
{"t":"B","v":"Supportive: beta-blockers for sympathetic excess; anticoagulation if apical thrombus present (occurs in ~5% of cases)."},
{"t":"B","v":"LVOTO complication: DO NOT give inotropes (dobutamine worsens obstruction) β use phenylephrine + IV fluid bolus."},
{"t":"H","v":"Prognosis"},
{"t":"B","v":"Full LV recovery in 1β4 weeks in >95%; in-hospital mortality 1β5% (cardiogenic shock, VF, LVOTO); recurrence 2β4%/year."},
]
bullets(tako,ML,C5-6*mm,HW5,lh=LH*0.93,fsz=9.1)
# ββ RIGHT: Arrhythmia-Induced CM βββββββββββββββββββββββββββββββββββββββββββββ
badge(ML+HW5+6*mm,C5,50*mm,"ARRHYTHMIA-INDUCED CARDIOMYOPATHY",TEAL2)
arr=[
{"t":"H","v":"Definition & Types"},
{"t":"B","v":"Tachycardia-induced CM (TIC): persistent tachycardia >115β120 bpm β βfilling pressures β biventricular systolic dysfunction. FULLY REVERSIBLE with arrhythmia control."},
{"t":"B","v":"PVC-induced CM: frequent ectopic beats β asynchronous contraction β LV dilation/dysfunction independent of elevated heart rate."},
{"t":"H","v":"Causative Arrhythmias"},
{"t":"B","v":"Atrial: atrial tachycardia (most common cause of TIC), atrial flutter/fibrillation, inappropriate sinus tachycardia."},
{"t":"B","v":"SVT: AVRT (WPW), AVNRT, PJRT (permanent junctional reciprocating tachycardia) β most common TIC cause in infants due to incessant nature."},
{"t":"B","v":"Ventricular: frequent PVCs, NSVT, sustained VT; even incessant sinus tachycardia documented as a cause."},
{"t":"H","v":"PVC Burden Thresholds (Key Numbers)"},
{"t":"B","v":">20,000 PVCs/24h β subclinical LVEF deterioration on serial echo (239-patient prospective dose-response study)."},
{"t":"B","v":">10,000 PVCs/24h β measurable LV dilation + change in LVEF. Upper quartile burden: 3Γ odds of LVEF drop, 48% β HF risk, 31% β death risk."},
{"t":"B","v":"Children: PVC burden in CM appears higher proportion than adults; ectopy persists throughout follow-up without spontaneous resolution."},
{"t":"H","v":"Diagnosis"},
{"t":"B","v":"LV dilation + dysfunction; absence of LVH; LV end-diastolic dimension typically <5.5cm; no other non-ischaemic cause identified."},
{"t":"B","v":"Confirmation: recovery of LV function within 1β6 months after arrhythmia control = diagnostic gold standard."},
{"t":"H","v":"Treatment"},
{"t":"B","v":"Rate control: beta-blockers, digoxin, or calcium channel blockers (rate-related TIC); direct current cardioversion for flutter/fibrillation."},
{"t":"B","v":"Radiofrequency catheter ablation (RFA): LVEF normalisation in 47β100% of children; first-line when LV dilation/dysfunction present."},
{"t":"B","v":"Post-ablation monitoring: repeat echo at 3β6 months; LV parameters typically normalise within 3β6 months of successful ablation."},
]
bullets(arr,ML+HW5+6*mm,C5-6*mm,HW5,lh=LH*0.93,fsz=9.1)
infobar(ML,FTR_H+2*mm,BW,16*mm,"KEY TAKE-AWAY: BOTH ARE FULLY REVERSIBLE IF TREATED PROMPTLY",
["β’ Takotsubo: complete LV recovery in 1β4 weeks in >95% of patients with supportive management",
"β’ Arrhythmia-induced CM: LVEF normalisation in 47β100% after arrhythmia control or RFA within 1β6 months"],
bg=TEAL2,tbg=GOLD)
pt("Source: Fuster & Hurst's The Heart 15th Ed Β· Braunwald's Heart Disease 12th Ed Β· Paediatric Cardiomyopathy Registry",
ML,FTR_H-1*mm,sz=6.5,col=MIDGREY,italic=True)
c.showPage()
# ββ Save ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
c.save()
sz=os.path.getsize(OUT)//1024
print(f"\nβ PDF saved: {OUT} ({sz} KB)")
cd /home/daytona/workspace/cardiomyopathy-pdf && python3 build.py 2>&1
Atypical Cardiomyopathy Children
PDF Document Β· PDF
| Page | Topic | Images | Bullet Lines |
|---|---|---|---|
| 1 | Title + AHA Classification + Overview | 4 topic cards | 9 content bullets + key principles box |
| 2 | LVNC β embryology, epidemiology, Jenni/Chin/StΓΆllberger criteria, genetics (TAZ/Barth), CMR, triad, management, prognosis | 3 echo images (A4C+PSAX, TEE X/Y ratio, PLAX spongy LV) | 32 bullets across 2 columns |
| 3 | ARVC β fibro-fatty replacement, PKP2/DSP genetics, Naxos disease, Task Force criteria, echo/CMR/LGE, Athlete's Heart vs ARVC, management, SCD statistics | 3 images (MRI axial, 4-panel multimodal, MRI+histology) | 30 bullets across 2 columns |
| 4 | RCM β idiopathic, storage diseases (Fabry/Pompe/Gaucher), EMF, biatrial dilation, RCM vs CP differentiation, transplant indications, prognosis | 3 images (paediatric CXR+echo, A4C biatrial, TDI) | 32 bullets across 2 columns |
| 5 | Takotsubo + Arrhythmia-Induced CM β catecholamine mechanism, paediatric triggers, LVOTO complication, PVC thresholds (>10k vs >20k), RFA outcomes | 3 echo images (apical ballooning, 2-chamber, diastole+systole+thrombus) | 30 bullets across 2 columns |
β’ bullet symbol is drawn at exactly BX = ML + 4mm and every text line starts at exactly TX = ML + 9mm β no drift, no offset, identical on every single line across all 5 pages.