SOP for Massive transfusion protocol for NABH inspection
NABH massive transfusion protocol SOP blood bank standards India
"massive transfusion protocol" AND ratio AND outcomes
https://portal.nabh.co/Announcement/Draft%20NABH%20Accredita…
mkdir -p /home/daytona/workspace/mtp-sop && ls /home/daytona/workspace/mtp-sop/
~/mtp-sop/mtp_sop.js
const {
Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell,
Header, Footer, AlignmentType, HeadingLevel, BorderStyle, WidthType,
VerticalAlign, PageNumber, ShadingType, UnderlineType
} = require('docx');
const fs = require('fs');
// ─── Helpers ───────────────────────────────────────────────────────────────
const BLUE = "1F3864"; // dark navy
const LBLUE = "2E74B5"; // heading blue
const LGRAY = "D9E1F2"; // light header fill
const DKGRAY= "4472C4"; // table header fill
function heading1(text) {
return new Paragraph({
text,
heading: HeadingLevel.HEADING_1,
spacing: { before: 300, after: 120 },
run: { bold: true, color: BLUE, size: 26 }
});
}
function heading2(text) {
return new Paragraph({
text,
heading: HeadingLevel.HEADING_2,
spacing: { before: 200, after: 80 },
run: { bold: true, color: LBLUE, size: 24 }
});
}
function heading3(text) {
return new Paragraph({
text,
heading: HeadingLevel.HEADING_3,
spacing: { before: 160, after: 60 },
run: { bold: true, size: 22 }
});
}
function body(text, opts = {}) {
return new Paragraph({
children: [new TextRun({ text, size: 22, ...opts })],
spacing: { before: 60, after: 60 },
indent: opts.indent ? { left: 720 } : {}
});
}
function bullet(text, opts = {}) {
return new Paragraph({
children: [new TextRun({ text, size: 22 })],
bullet: { level: opts.level || 0 },
spacing: { before: 40, after: 40 }
});
}
function bold(text) {
return new TextRun({ text, bold: true, size: 22 });
}
function tableHeaderCell(text, width = 2000, span = 1) {
return new TableCell({
children: [new Paragraph({
children: [new TextRun({ text, bold: true, color: "FFFFFF", size: 20 })],
alignment: AlignmentType.CENTER,
spacing: { before: 60, after: 60 }
})],
shading: { fill: "2E74B5", type: ShadingType.CLEAR },
verticalAlign: VerticalAlign.CENTER,
width: { size: width, type: WidthType.DXA },
columnSpan: span
});
}
function tableCell(text, shade = false, width = 2000) {
return new TableCell({
children: [new Paragraph({
children: [new TextRun({ text, size: 20 })],
spacing: { before: 40, after: 40 },
alignment: AlignmentType.LEFT
})],
shading: shade ? { fill: "EBF3FB", type: ShadingType.CLEAR } : undefined,
width: { size: width, type: WidthType.DXA }
});
}
function hRule() {
return new Paragraph({
border: { bottom: { color: "2E74B5", style: BorderStyle.SINGLE, size: 8 } },
spacing: { before: 160, after: 160 }
});
}
function empty(n = 1) {
return Array.from({ length: n }, () => new Paragraph({ text: "" }));
}
// ─── PAGE BORDER ──────────────────────────────────────────────────────────
const docSection = {
properties: {
page: {
margin: { top: 1000, right: 800, bottom: 900, left: 800 },
borders: {
pageBorderTop: { style: BorderStyle.SINGLE, size: 12, color: "2E74B5", space: 24 },
pageBorderBottom: { style: BorderStyle.SINGLE, size: 12, color: "2E74B5", space: 24 },
pageBorderLeft: { style: BorderStyle.SINGLE, size: 12, color: "2E74B5", space: 24 },
pageBorderRight: { style: BorderStyle.SINGLE, size: 12, color: "2E74B5", space: 24 },
}
}
},
headers: {
default: new Header({
children: [
new Paragraph({
children: [
new TextRun({ text: "SOP – MASSIVE TRANSFUSION PROTOCOL (MTP)", bold: true, size: 20, color: "2E74B5" }),
new TextRun({ text: "\t\t", size: 20 }),
new TextRun({ text: "NABH Ref: TPC.19 / BSQ.1", size: 18, color: "888888" })
],
alignment: AlignmentType.LEFT,
border: { bottom: { color: "2E74B5", style: BorderStyle.SINGLE, size: 6 } }
})
]
})
},
footers: {
default: new Footer({
children: [
new Paragraph({
children: [
new TextRun({ text: "CONFIDENTIAL – FOR INTERNAL USE ONLY", size: 16, color: "888888" }),
new TextRun({ text: "\t\t\tPage ", size: 18, color: "888888" }),
new TextRun({ children: [PageNumber.CURRENT], size: 18, color: "888888" }),
new TextRun({ text: " of ", size: 18, color: "888888" }),
new TextRun({ children: [PageNumber.TOTAL_PAGES], size: 18, color: "888888" })
],
border: { top: { color: "2E74B5", style: BorderStyle.SINGLE, size: 6 } }
})
]
})
},
children: [] // filled below
};
// ─── COVER / TITLE TABLE ──────────────────────────────────────────────────
const titleTable = new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({ children: [
new TableCell({
columnSpan: 4,
children: [
new Paragraph({
children: [new TextRun({ text: "STANDARD OPERATING PROCEDURE", bold: true, size: 36, color: "FFFFFF" })],
alignment: AlignmentType.CENTER, spacing: { before: 80, after: 40 }
}),
new Paragraph({
children: [new TextRun({ text: "MASSIVE TRANSFUSION PROTOCOL (MTP)", bold: true, size: 48, color: "FFFFFF" })],
alignment: AlignmentType.CENTER, spacing: { before: 40, after: 40 }
}),
new Paragraph({
children: [new TextRun({ text: "Department of Blood Bank & Transfusion Medicine", size: 28, color: "BDD7EE" })],
alignment: AlignmentType.CENTER, spacing: { before: 20, after: 80 }
})
],
shading: { fill: "1F3864", type: ShadingType.CLEAR }
})
]}),
new TableRow({ children: [
tableHeaderCell("Doc No.", 1600),
tableHeaderCell("Version / Rev. No.", 1600),
tableHeaderCell("Effective Date", 1600),
tableHeaderCell("Review Date", 1600)
]}),
new TableRow({ children: [
tableCell("BB/SOP/MTP/01", true, 1600),
tableCell("01 / 00", false, 1600),
tableCell("________", true, 1600),
tableCell("________", false, 1600)
]}),
new TableRow({ children: [
tableHeaderCell("Prepared By", 1600),
tableHeaderCell("Reviewed By", 1600),
tableHeaderCell("Approved By", 1600),
tableHeaderCell("NABH Ref.", 1600)
]}),
new TableRow({ children: [
tableCell("Dr. ________________\nBlood Bank MO", true, 1600),
tableCell("Dr. ________________\nHead, Dept.", false, 1600),
tableCell("Dr. ________________\nMedical Director", true, 1600),
tableCell("TPC.19(e), BSQ.1", false, 1600)
]})
]
});
// ─── SOP CONTENT ──────────────────────────────────────────────────────────
const sopContent = [
// ── 1. PURPOSE ──────────────────────────────────────────────────────────
heading1("1. PURPOSE"),
body("This Standard Operating Procedure establishes a standardised, rapid, team-based protocol for the recognition and management of life-threatening haemorrhage requiring massive transfusion. It ensures timely release of compatible blood products, optimises haemostatic resuscitation, and fulfils NABH Accreditation Standard TPC.19(e) – 'The blood centre has written guidance for massive transfusions.'"),
// ── 2. SCOPE ────────────────────────────────────────────────────────────
heading1("2. SCOPE"),
body("This SOP applies to all clinical areas of the hospital where massive haemorrhage may occur, including:"),
bullet("Emergency Department (ED)"),
bullet("Surgical Operation Theatres (OT)"),
bullet("Obstetrics & Gynaecology (labour room, OT)"),
bullet("Intensive Care Units (ICU – Medical, Surgical, Neonatal)"),
bullet("Interventional Radiology / Cardiac Catheterisation Lab"),
body("It involves all staff who may activate, coordinate, or respond to MTP: treating clinicians, nurses, Blood Bank staff, porters/runners, and the Hospital Transfusion Committee (HTC)."),
// ── 3. DEFINITIONS ──────────────────────────────────────────────────────
heading1("3. DEFINITIONS"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({ children: [
tableHeaderCell("Term", 2200),
tableHeaderCell("Definition", 6200)
]}),
new TableRow({ children: [
tableCell("Massive Transfusion (MT)", true, 2200),
tableCell("Transfusion of ≥ 10 units of packed red blood cells (PRBC) in 24 h, OR replacement of ≥ 50% of total blood volume (TBV) within 3 h, OR transfusion of > 4 units PRBC in 1 h with anticipated ongoing need.", false, 6200)
]}),
new TableRow({ children: [
tableCell("MTP Activation", false, 2200),
tableCell("Formal hospital-wide response triggered by designated criteria to pre-emptively mobilise blood products and clinical resources.", true, 6200)
]}),
new TableRow({ children: [
tableCell("MTP Pack (Cycle)", true, 2200),
tableCell("A pre-assembled set of blood components released by the Blood Bank in one round of MTP.", false, 6200)
]}),
new TableRow({ children: [
tableCell("1:1:1 Ratio", false, 2200),
tableCell("Balanced haemostatic resuscitation with PRBC : Fresh Frozen Plasma (FFP) : Platelets in a 1:1:1 ratio (evidence-based standard from PROPPR trial, JAMA 2015).", true, 6200)
]}),
new TableRow({ children: [
tableCell("Lethal Triad", true, 2200),
tableCell("The combination of hypothermia (< 35°C), acidosis (pH < 7.35), and coagulopathy that amplifies haemorrhage mortality.", false, 6200)
]}),
new TableRow({ children: [
tableCell("Damage Control Resuscitation (DCR)", false, 2200),
tableCell("Resuscitation strategy aiming to control haemorrhage before definitive repair, using permissive hypotension (SBP 80–100 mmHg), minimise crystalloids, and early use of blood components.", true, 6200)
]}),
new TableRow({ children: [
tableCell("TXA", true, 2200),
tableCell("Tranexamic acid – antifibrinolytic agent administered early in traumatic or obstetric haemorrhage.", false, 6200)
]}),
new TableRow({ children: [
tableCell("TEG / ROTEM", false, 2200),
tableCell("Viscoelastic haemostatic assays (Thromboelastography / Rotational Thromboelastometry) used for real-time coagulation monitoring during MTP.", true, 6200)
]})
]
}),
...empty(1),
// ── 4. RESPONSIBILITIES ─────────────────────────────────────────────────
heading1("4. RESPONSIBILITIES"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({ children: [
tableHeaderCell("Role", 2500),
tableHeaderCell("Responsibility", 5900)
]}),
new TableRow({ children: [
tableCell("Treating Clinician / MTP Lead", true, 2500),
tableCell("Activates and deactivates MTP; directs clinical management; communicates with Blood Bank.", false, 5900)
]}),
new TableRow({ children: [
tableCell("Blood Bank Medical Officer (BBMO)", false, 2500),
tableCell("Receives activation call; prepares and releases MTP packs; monitors inventory; advises on component therapy.", true, 5900)
]}),
new TableRow({ children: [
tableCell("Blood Bank Technician", true, 2500),
tableCell("Prepares MTP coolers; labels components; documents all issues; performs blood grouping as rapidly as possible.", false, 5900)
]}),
new TableRow({ children: [
tableCell("Nursing Staff (Clinical Area)", false, 2500),
tableCell("Draws pre-transfusion samples; administers products; monitors patient; documents in records.", true, 5900)
]}),
new TableRow({ children: [
tableCell("Runner / Porter", true, 2500),
tableCell("Transports MTP coolers between Blood Bank and clinical area within defined time targets.", false, 5900)
]}),
new TableRow({ children: [
tableCell("Hospital Transfusion Committee (HTC)", false, 2500),
tableCell("Reviews all MTP activations; identifies audit parameters; revises SOP annually or after adverse event.", true, 5900)
]})
]
}),
...empty(1),
// ── 5. ACTIVATION CRITERIA ──────────────────────────────────────────────
heading1("5. CRITERIA FOR MTP ACTIVATION"),
heading2("5.1 Clinical Assessment Score (ABC Score – Assessment of Blood Consumption)"),
body("Activate MTP if score ≥ 2. Assign 1 point each for:"),
new Table({
width: { size: 80, type: WidthType.PERCENTAGE },
rows: [
new TableRow({ children: [
tableHeaderCell("Parameter", 2400),
tableHeaderCell("Positive Finding (1 point)", 3000)
]}),
new TableRow({ children: [
tableCell("Mechanism of injury", true, 2400),
tableCell("Penetrating trauma", false, 3000)
]}),
new TableRow({ children: [
tableCell("Systolic BP on arrival", false, 2400),
tableCell("≤ 90 mmHg", true, 3000)
]}),
new TableRow({ children: [
tableCell("Heart rate on arrival", true, 2400),
tableCell("≥ 120 beats/min", false, 3000)
]}),
new TableRow({ children: [
tableCell("FAST/EFAST", false, 2400),
tableCell("Positive (free fluid in abdomen / pericardium)", true, 3000)
]})
]
}),
...empty(1),
body("Score ≥ 2 = Activate MTP | Score < 2 = Continue standard resuscitation and reassess"),
heading2("5.2 Additional Clinical Triggers"),
bullet("Active haemorrhage with haemodynamic instability not responding to 2 L crystalloid"),
bullet("Postpartum haemorrhage (PPH) > 1000 mL with ongoing bleeding (activate Obstetric MTP variant)"),
bullet("Intra-operative major vessel injury or damage-control situation"),
bullet("Anticipated ≥ 50% blood volume replacement in < 3 h"),
bullet("Clinician judgement overrides score in rapidly deteriorating patients"),
heading2("5.3 Exclusions / Contraindications"),
bullet("Patients in confirmed refractory cardiac arrest from non-haemorrhagic cause"),
bullet("Written advance directive refusing transfusion (communicate with treating clinician and document)"),
// ── 6. PROCEDURE ────────────────────────────────────────────────────────
heading1("6. PROCEDURE"),
heading2("6.1 Step 1 – Activation"),
new Paragraph({
children: [
new TextRun({ text: "Designated caller contacts Blood Bank on MTP hotline: ", size: 22 }),
new TextRun({ text: "Extension ________ (24 h)", bold: true, size: 22, color: "C00000" })
],
spacing: { before: 60, after: 60 }
}),
body("Information to provide verbally (or via HIS/EMR electronic order):"),
bullet("Patient name / STAT name if unidentified"),
bullet("Medical Record Number (MRN) or unique ID"),
bullet("Sex and approximate age (identify females of childbearing age for Rh allocation)"),
bullet("Ward / location and bed number"),
bullet("Name of attending physician initiating MTP"),
bullet("Type of haemorrhage: Trauma / Obstetric (OB-MTP) / Surgical / GI"),
body("Blood Bank to acknowledge and record time of activation."),
heading2("6.2 Step 2 – Sample Collection"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({ children: [
tableHeaderCell("Sample", 2200),
tableHeaderCell("Volume / Tube", 1800),
tableHeaderCell("Purpose", 2400),
tableHeaderCell("Target Time", 2000)
]}),
new TableRow({ children: [
tableCell("Type & Screen", true, 2200),
tableCell("6 mL EDTA (pink top)", false, 1800),
tableCell("ABO / Rh grouping, antibody screen", true, 2400),
tableCell("Within 15 min of activation", false, 2000)
]}),
new TableRow({ children: [
tableCell("Crossmatch sample", false, 2200),
tableCell("6 mL EDTA", true, 1800),
tableCell("Compatibility testing", false, 2400),
tableCell("Simultaneous with above", true, 2000)
]}),
new TableRow({ children: [
tableCell("Coagulation panel", true, 2200),
tableCell("3.2% sodium citrate", false, 1800),
tableCell("PT, INR, aPTT, Fibrinogen", true, 2400),
tableCell("Within 15 min of activation", false, 2000)
]}),
new TableRow({ children: [
tableCell("TEG / ROTEM (if available)", false, 2200),
tableCell("Citrated whole blood", true, 1800),
tableCell("Real-time clot function", false, 2400),
tableCell("ASAP", true, 2000)
]}),
new TableRow({ children: [
tableCell("CBC, BMP, Lactate", true, 2200),
tableCell("As per local protocol", false, 1800),
tableCell("Baseline / monitoring", true, 2400),
tableCell("Within 15 min", false, 2000)
]})
]
}),
...empty(1),
body("Note: Even 1 unit of un-crossmatched blood can interfere with subsequent crossmatching. Draw samples BEFORE administering uncrossmatched O-negative blood whenever possible."),
heading2("6.3 Step 3 – Blood Bank Response & Release of MTP Packs"),
heading3("Uncrossmatched Emergency Release (before type & screen result):"),
bullet("Males and females > 50 years (post-menopausal): O-positive PRBC"),
bullet("Females of childbearing age (< 50 years): O-negative PRBC (reserve O-neg for this group)"),
bullet("FFP: AB or A group as default until patient's group is confirmed"),
heading3("MTP Pack Composition (Standard Adult):"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({ children: [
tableHeaderCell("Pack / Cycle", 1400),
tableHeaderCell("PRBC (units)", 1400),
tableHeaderCell("FFP (units)", 1400),
tableHeaderCell("Platelets (units)", 1600),
tableHeaderCell("Cryoprecipitate", 1600),
tableHeaderCell("Notes", 2000)
]}),
new TableRow({ children: [
tableCell("Pack 1 (Immediate)", true, 1400),
tableCell("4 units O-pos/neg", false, 1400),
tableCell("4 units AB/A", true, 1400),
tableCell("—", false, 1600),
tableCell("—", true, 1600),
tableCell("Release within 5–10 min of activation", false, 2000)
]}),
new TableRow({ children: [
tableCell("Pack 2", false, 1400),
tableCell("4 units (typed if available)", true, 1400),
tableCell("4 units", false, 1400),
tableCell("1 apheresis or 6 pooled", true, 1600),
tableCell("—", false, 1600),
tableCell("Release on return of Pack 1 cooler", true, 2000)
]}),
new TableRow({ children: [
tableCell("Pack 3 (and onwards)", true, 1400),
tableCell("4 units (crossmatched if possible)", false, 1400),
tableCell("4 units", true, 1400),
tableCell("1 apheresis or 6 pooled (alternate cycles)", false, 1600),
tableCell("10 units if fibrinogen < 1.5 g/L", true, 1600),
tableCell("Continue until MTP deactivation", false, 2000)
]})
]
}),
...empty(1),
body("Ratio target: PRBC : FFP : Platelets = 1 : 1 : 1 (evidence: PROPPR trial). Cryoprecipitate (10 units) added when fibrinogen < 1.5–2 g/L or clinical evidence of hypofibrinogenaemia."),
heading3("Paediatric MTP (< 40 kg):"),
new Table({
width: { size: 70, type: WidthType.PERCENTAGE },
rows: [
new TableRow({ children: [
tableHeaderCell("Component", 2000),
tableHeaderCell("< 40 kg", 1800),
tableHeaderCell("> 40 kg", 1800)
]}),
new TableRow({ children: [
tableCell("PRBC", true, 2000),
tableCell("2 units", false, 1800),
tableCell("4 units", true, 1800)
]}),
new TableRow({ children: [
tableCell("FFP", false, 2000),
tableCell("2 units", true, 1800),
tableCell("4 units", false, 1800)
]}),
new TableRow({ children: [
tableCell("Platelets", true, 2000),
tableCell("1 unit (odd cycles)", false, 1800),
tableCell("1 unit (odd cycles)", true, 1800)
]})
]
}),
...empty(1),
heading2("6.4 Step 4 – Cooler Transport & Chain of Custody"),
bullet("Blood Bank packs all products in a validated transport cooler maintaining 1–6°C for PRBC."),
bullet("A designated runner collects the cooler from the Blood Bank window presenting a patient identification label with minimum two patient identifiers."),
bullet("Runner and Blood Bank staff perform verbal read-back to confirm correct cooler is released."),
bullet("Empty cooler is returned to Blood Bank by runner to trigger release of next pack."),
bullet("Transport time target: Blood Bank to clinical area ≤ 10 minutes."),
heading2("6.5 Step 5 – Administration at Bedside"),
heading3("Pre-transfusion bedside checks (two-nurse or nurse + doctor check):"),
bullet("Two patient identifiers (name + MRN) match patient wristband and blood pack label"),
bullet("Blood group and component type verified"),
bullet("Inspect pack for abnormal colour, clots, haemolysis, or integrity breach"),
bullet("Expiry date confirmed"),
bullet("Informed consent documented (or emergency exception noted in medical record)"),
heading3("Administration Protocol:"),
bullet("Use large-bore IV access (minimum 16G; central venous access or intra-osseous for dire emergencies)"),
bullet("Administer through blood administration set with 170–200 µm filter"),
bullet("Warm blood using validated blood warmer (target product temperature 37°C) — never microwave"),
bullet("Run each unit as rapidly as haemodynamic status allows (pressure bag if necessary)"),
heading2("6.6 Step 6 – Adjunct Pharmacological Therapy"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({ children: [
tableHeaderCell("Agent", 1800),
tableHeaderCell("Dose", 2200),
tableHeaderCell("Indication", 2200),
tableHeaderCell("Timing", 2200)
]}),
new TableRow({ children: [
tableCell("Tranexamic Acid (TXA)", true, 1800),
tableCell("1 g IV over 10 min; then 1 g over 8 h", false, 2200),
tableCell("Trauma or obstetric haemorrhage with fibrinolysis", true, 2200),
tableCell("Within 3 h of onset of haemorrhage (CRASH-2 trial)", false, 2200)
]}),
new TableRow({ children: [
tableCell("Calcium (Chloride)", false, 1800),
tableCell("1–2 g IV (10% CaCl₂) per MTP pack", true, 2200),
tableCell("Hypocalcaemia from citrate in transfused products (every 4–6 units PRBC)", false, 2200),
tableCell("After each pack; monitor iCa²⁺", true, 2200)
]}),
new TableRow({ children: [
tableCell("Cryoprecipitate", true, 1800),
tableCell("10 units (pooled)", false, 2200),
tableCell("Fibrinogen < 1.5–2 g/L; hypofibrinogenaemia in PPH", true, 2200),
tableCell("Order with Pack 2; thaw time ~30 min", false, 2200)
]}),
new TableRow({ children: [
tableCell("Prothrombin Complex Concentrate (PCC)", false, 1800),
tableCell("25–50 IU/kg IV", true, 2200),
tableCell("Anticoagulation reversal (warfarin, DOAC) with active bleeding", false, 2200),
tableCell("On clinician order; check local availability", true, 2200)
]}),
new TableRow({ children: [
tableCell("Recombinant Factor VIIa (rFVIIa)", true, 1800),
tableCell("90 µg/kg IV (off-label)", false, 2200),
tableCell("Refractory haemorrhage after optimising pH, temperature, and platelets; senior clinician decision only", true, 2200),
tableCell("Last resort; document indication", false, 2200)
]})
]
}),
...empty(1),
heading2("6.7 Step 7 – Monitoring & Resuscitation Targets"),
new Table({
width: { size: 80, type: WidthType.PERCENTAGE },
rows: [
new TableRow({ children: [
tableHeaderCell("Parameter", 2600),
tableHeaderCell("Target", 2600)
]}),
new TableRow({ children: [
tableCell("Systolic BP (permissive hypotension – pre-operative)", true, 2600),
tableCell("80–100 mmHg (non-TBI); > 110 mmHg (TBI or obstetric)", false, 2600)
]}),
new TableRow({ children: [
tableCell("MAP", false, 2600),
tableCell("≥ 60 mmHg (~ 65–70 in TBI)", true, 2600)
]}),
new TableRow({ children: [
tableCell("Haemoglobin", true, 2600),
tableCell("7–9 g/dL (active haemorrhage: transfuse at ≤ 7 g/dL)", false, 2600)
]}),
new TableRow({ children: [
tableCell("INR", false, 2600),
tableCell("< 1.5", true, 2600)
]}),
new TableRow({ children: [
tableCell("aPTT", true, 2600),
tableCell("< 42 seconds", false, 2600)
]}),
new TableRow({ children: [
tableCell("Fibrinogen", false, 2600),
tableCell("> 1.5–2 g/L", true, 2600)
]}),
new TableRow({ children: [
tableCell("Platelet count", true, 2600),
tableCell("> 50 × 10⁹/L (> 100 × 10⁹/L in TBI or multiple trauma)", false, 2600)
]}),
new TableRow({ children: [
tableCell("Core temperature", false, 2600),
tableCell("> 35.0°C", true, 2600)
]}),
new TableRow({ children: [
tableCell("pH", true, 2600),
tableCell("7.35–7.45", false, 2600)
]}),
new TableRow({ children: [
tableCell("Ionised Calcium (iCa²⁺)", false, 2600),
tableCell("1.1–1.3 mmol/L", true, 2600)
]}),
new TableRow({ children: [
tableCell("Serum lactate", true, 2600),
tableCell("< 2 mEq/L (trend down)", false, 2600)
]}),
new TableRow({ children: [
tableCell("Base deficit", false, 2600),
tableCell("< 3", true, 2600)
]})
]
}),
...empty(1),
body("Labs: Repeat CBC, coagulation screen, fibrinogen, electrolytes, lactate every 30–60 minutes during active MTP. TEG/ROTEM if available to guide targeted component therapy."),
body("Prevention of lethal triad: Use blood warmers, maintain normothermia (Bair Hugger® in OT), administer sodium bicarbonate for pH < 7.20 on clinician order, avoid large-volume crystalloid."),
heading2("6.8 Step 8 – Deactivation"),
body("The activating physician (or designated MTP lead) deactivates MTP when:"),
bullet("Haemorrhage is surgically/radiologically controlled AND haemodynamic stability achieved"),
bullet("Resuscitation targets met (see Section 6.7)"),
bullet("Clinical decision to institute comfort measures only"),
bullet("Patient death"),
body("Deactivation call to Blood Bank on the same MTP hotline."),
body("Blood Bank actions on deactivation:"),
bullet("Stop preparation of further MTP packs"),
bullet("Return unused components to storage only if cold chain unbroken (document time out of storage)"),
bullet("Discard components if cold chain compromised"),
bullet("Complete Blood Bank MTP log sheet"),
heading2("6.9 Step 9 – Post-MTP Care"),
bullet("Recheck CBC, INR, aPTT, fibrinogen, electrolytes (iCa²⁺, K⁺), serum lactate once MTP deactivated"),
bullet("12-lead ECG to assess volume status and arrhythmia"),
bullet("Monitor for transfusion-related complications: TACO, TRALI, AHTR, hyperkalaemia, hypothermia, DIC"),
bullet("Transition to standard crossmatched blood products"),
bullet("Complete haemovigilance documentation in the patient's medical record (NABH TPC.19 – commitment f)"),
// ── 7. SPECIAL POPULATIONS ──────────────────────────────────────────────
heading1("7. SPECIAL POPULATIONS"),
heading2("7.1 Obstetric MTP (OB-MTP)"),
bullet("Trigger: PPH > 1000 mL with ongoing bleeding, or > 500 mL with haemodynamic instability"),
bullet("Specify 'OB-MTP' during activation call to Blood Bank"),
bullet("Fibrinogen drops rapidly in obstetric haemorrhage — prioritise cryoprecipitate early"),
bullet("TXA 1 g IV within 3 h of onset is strongly recommended (WHO, WOMAN trial)"),
bullet("Target fibrinogen > 2 g/L and platelets > 75 × 10⁹/L in PPH"),
bullet("Coordinate with obstetric surgeon, anaesthetist, and neonatologist as indicated"),
heading2("7.2 Paediatric MTP"),
bullet("Use weight-based dosing; see Section 6.3 paediatric table"),
bullet("Activate if estimated blood loss > 40 mL/kg or haemodynamic instability after 20 mL/kg bolus"),
bullet("TXA: 15 mg/kg IV (max 1 g) loading dose"),
heading2("7.3 Jehovah's Witness or Blood Refusal"),
bullet("Respect documented advance directives and informed refusal"),
bullet("Maximise cell salvage (intra-operative), acute normovolaemic haemodilution, haemostatic surgery"),
bullet("Consult ethics committee if patient is minor or unconscious and refusal is documented by family"),
bullet("Document all discussions and decisions in the medical record"),
heading2("7.4 Anticoagulated Patients"),
bullet("Warfarin: PCC 25–50 IU/kg + Vitamin K 10 mg IV slow infusion"),
bullet("Direct oral anticoagulants (DOACs): Idarucizumab (dabigatran), Andexanet alfa (Factor Xa inhibitors)"),
bullet("Heparin: Protamine sulphate 1 mg per 100 units of heparin"),
// ── 8. DOCUMENTATION ────────────────────────────────────────────────────
heading1("8. DOCUMENTATION & RECORDS"),
body("NABH requires that all records listed below be maintained and available for inspection (NABH TPC.19 – commitment f):"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({ children: [
tableHeaderCell("Record / Form", 2600),
tableHeaderCell("Where Filed", 2000),
tableHeaderCell("Retention Period", 1800),
tableHeaderCell("Responsible", 1800)
]}),
new TableRow({ children: [
tableCell("MTP Activation Log (Blood Bank)", true, 2600),
tableCell("Blood Bank Register / HIS", false, 2000),
tableCell("10 years", true, 1800),
tableCell("BBMO / Technician", false, 1800)
]}),
new TableRow({ children: [
tableCell("Blood Product Issue Record (component, volume, time, recipient)", false, 2600),
tableCell("Blood Bank + Patient file", true, 2000),
tableCell("10 years", false, 1800),
tableCell("Blood Bank Technician", true, 1800)
]}),
new TableRow({ children: [
tableCell("MTP Clinical Flow Sheet (bedside)", true, 2600),
tableCell("Patient medical record (EMR)", false, 2000),
tableCell("Permanent", true, 1800),
tableCell("Treating team / Nurse", false, 1800)
]}),
new TableRow({ children: [
tableCell("Transfusion Consent Form (or emergency exception note)", false, 2600),
tableCell("Patient medical record", true, 2000),
tableCell("Permanent", false, 1800),
tableCell("Treating clinician", true, 1800)
]}),
new TableRow({ children: [
tableCell("Adverse Transfusion Reaction Report (if applicable)", true, 2600),
tableCell("Blood Bank + Quality Dept.", false, 2000),
tableCell("10 years", true, 1800),
tableCell("BBMO + Treating team", false, 1800)
]}),
new TableRow({ children: [
tableCell("Post-MTP Audit Sheet (HTC review)", false, 2600),
tableCell("Quality / HTC file", true, 2000),
tableCell("5 years", false, 1800),
tableCell("HTC Convener", true, 1800)
]})
]
}),
...empty(1),
// ── 9. TRAINING ─────────────────────────────────────────────────────────
heading1("9. TRAINING & COMPETENCY"),
bullet("All Blood Bank staff complete MTP simulation training at induction and annually thereafter."),
bullet("Clinical staff (ED, OT, ICU, Obstetrics) complete MTP awareness training – minimum once per year."),
bullet("Mock MTP drills are conducted at least twice per year; findings reviewed at HTC."),
bullet("Competency records are maintained in the HR / training management system."),
bullet("New staff complete training before independent MTP activation."),
// ── 10. QUALITY INDICATORS ──────────────────────────────────────────────
heading1("10. QUALITY INDICATORS (NABH BSQ.7 – Monitoring Indicators)"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({ children: [
tableHeaderCell("Indicator", 3000),
tableHeaderCell("Target / Standard", 2400),
tableHeaderCell("Frequency of Review", 1800)
]}),
new TableRow({ children: [
tableCell("Time from MTP activation to first PRBC release", true, 3000),
tableCell("≤ 10 minutes", false, 2400),
tableCell("Monthly", true, 1800)
]}),
new TableRow({ children: [
tableCell("Time from activation to sample receipt in Blood Bank", false, 3000),
tableCell("≤ 15 minutes", true, 2400),
tableCell("Monthly", false, 1800)
]}),
new TableRow({ children: [
tableCell("TXA administered within 3 h of haemorrhage onset", true, 3000),
tableCell("≥ 90% of eligible cases", false, 2400),
tableCell("Monthly", true, 1800)
]}),
new TableRow({ children: [
tableCell("PRBC : FFP ratio ≥ 1:1 (achieved by end of MTP)", false, 3000),
tableCell("≥ 85% of MTP activations", true, 2400),
tableCell("Per event + Monthly", false, 1800)
]}),
new TableRow({ children: [
tableCell("MTP activation-to-deactivation documented", true, 3000),
tableCell("100%", false, 2400),
tableCell("Per event", true, 1800)
]}),
new TableRow({ children: [
tableCell("Post-MTP adverse transfusion reaction rate", false, 3000),
tableCell("Monitor and trend; investigate all Grade ≥ 2", true, 2400),
tableCell("Per event + Monthly", false, 1800)
]}),
new TableRow({ children: [
tableCell("Blood product wastage during MTP", true, 3000),
tableCell("Minimise; review each instance of waste", false, 2400),
tableCell("Monthly", true, 1800)
]}),
new TableRow({ children: [
tableCell("30-day mortality post-MTP", false, 3000),
tableCell("Benchmark against national data", true, 2400),
tableCell("Quarterly", false, 1800)
]})
]
}),
...empty(1),
// ── 11. ADVERSE REACTIONS ───────────────────────────────────────────────
heading1("11. MANAGEMENT OF ADVERSE TRANSFUSION REACTIONS (NABH TPC.20)"),
body("In the event of a suspected adverse transfusion reaction:"),
bullet("STOP the transfusion immediately"),
bullet("Maintain IV access; administer 0.9% NaCl"),
bullet("Notify treating clinician and Blood Bank immediately"),
bullet("Check patient identity and blood pack label for clerical error"),
bullet("Return blood pack and tubing (do not discard) to Blood Bank with post-transfusion samples (EDTA, plain tube, urine)"),
bullet("Complete Adverse Transfusion Reaction Form; Blood Bank investigates per written protocol"),
bullet("Serious reactions (AHTR, TRALI, TACO, TTI) reported to haemovigilance system and quality department"),
bullet("Root cause analysis (RCA) for severe / unexpected reactions with CAPA plan – reviewed at HTC"),
// ── 12. REFERENCES ──────────────────────────────────────────────────────
heading1("12. REFERENCES"),
bullet("NABH Accreditation Standards for Blood Centres and Transfusion Services, 4th Edition – Standards TPC.19, TPC.20, BSQ.1, BSQ.7, BSQ.11"),
bullet("Holcomb JB, et al. PROPPR Trial: Transfusion of Plasma, Platelets, and Red Blood Cells in a 1:1:1 vs 1:1:2 Ratio and Mortality in Patients with Severe Trauma. JAMA. 2015;313(5):471–482."),
bullet("CRASH-2 Trial: Effects of tranexamic acid on death, vascular occlusive events, and blood transfusion in trauma patients with significant haemorrhage. Lancet. 2010;376:23–32."),
bullet("Schwartz's Principles of Surgery, 11th Edition. Chapter 7: Trauma. McGraw-Hill, 2019."),
bullet("Sabiston Textbook of Surgery, 21st Edition. Chapter on Fluid & Blood Component Resuscitation. Elsevier, 2022."),
bullet("Shakur H et al (WOMAN Trial). Effect of early tranexamic acid administration on mortality, hysterectomy, and other morbidities in women with post-partum haemorrhage. Lancet. 2017;389:2105–2116."),
bullet("Indian Journal of Anaesthesia. Massive transfusion and massive transfusion protocol. IJA 2014;58(5):590–595. PMID: 25535421"),
bullet("National Blood Policy, Ministry of Health & Family Welfare, Government of India."),
bullet("Drugs and Cosmetics Act, 1940 (amended) – Schedule F – Blood Bank licensing requirements."),
// ── 13. SOP CONTROL ─────────────────────────────────────────────────────
heading1("13. SOP CONTROL & REVIEW"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({ children: [
tableHeaderCell("Version", 1200),
tableHeaderCell("Date", 1600),
tableHeaderCell("Changes Made", 3000),
tableHeaderCell("Changed By", 2200)
]}),
new TableRow({ children: [
tableCell("01/00", true, 1200),
tableCell("__________", false, 1600),
tableCell("Initial version", true, 3000),
tableCell("Dr. ____________", false, 2200)
]}),
new TableRow({ children: [
tableCell("", false, 1200),
tableCell("", true, 1600),
tableCell("", false, 3000),
tableCell("", true, 2200)
]})
]
}),
...empty(1),
body("This SOP is reviewed annually by the Hospital Transfusion Committee (HTC) or earlier if triggered by:"),
bullet("Adverse event / sentinel event related to MTP"),
bullet("Changes in national blood transfusion guidelines"),
bullet("NABH inspection findings"),
bullet("Mock drill audit findings"),
...empty(1),
new Paragraph({
children: [
new TextRun({ text: "Signatures", bold: true, size: 24, underline: { type: UnderlineType.SINGLE } })
],
spacing: { before: 200, after: 120 }
}),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({ children: [
tableHeaderCell("Prepared By", 2133),
tableHeaderCell("Reviewed By", 2133),
tableHeaderCell("Approved By", 2133)
]}),
new TableRow({ children: [
tableCell("Name:\nDesignation:\nSignature:\nDate:", true, 2133),
tableCell("Name:\nDesignation:\nSignature:\nDate:", false, 2133),
tableCell("Name:\nDesignation:\nSignature:\nDate:", true, 2133)
]})
]
}),
...empty(2),
body("This is a CONTROLLED DOCUMENT. Uncontrolled copies are valid only on the date of printing. Verify version on the Hospital Intranet / Document Management System before use.", { bold: true, color: "C00000" })
];
// ─── ASSEMBLE ─────────────────────────────────────────────────────────────
docSection.children = sopContent;
const doc = new Document({
creator: "Hospital Quality Department",
title: "SOP – Massive Transfusion Protocol",
description: "NABH-compliant SOP for MTP – Blood Bank & Transfusion Medicine",
sections: [docSection]
});
Packer.toBuffer(doc).then(buffer => {
fs.writeFileSync('/home/daytona/workspace/mtp-sop/SOP_Massive_Transfusion_Protocol_NABH.docx', buffer);
console.log('SUCCESS: SOP written.');
}).catch(err => {
console.error('ERROR:', err);
process.exit(1);
});
cd /home/daytona/workspace/mtp-sop && node mtp_sop.js 2>&1
python3 /home/daytona/skills/docx/scripts/office/validate.py /home/daytona/workspace/mtp-sop/SOP_Massive_Transfusion_Protocol_NABH.docx 2>&1
python3 -c "import zipfile; z = zipfile.ZipFile('/home/daytona/workspace/mtp-sop/SOP_Massive_Transfusion_Protocol_NABH.docx'); print('Valid ZIP. Files:', z.namelist()[:8])"
ls -lh /home/daytona/workspace/mtp-sop/SOP_Massive_Transfusion_Protocol_NABH.docx
SOP Massive Transfusion Protocol NABH
Word Document · DOCX
| Section | Content |
|---|---|
| 1. Purpose | NABH TPC.19(e) compliance statement |
| 2. Scope | ED, OT, ICU, Obstetrics, Cath lab |
| 3. Definitions | MT, 1:1:1 ratio, lethal triad, DCR, TEG/ROTEM |
| 4. Responsibilities | Clinician, BBMO, technician, nurse, runner, HTC |
| 5. Activation Criteria | ABC Score (≥2 = activate) + clinical triggers + exclusions |
| 6. Procedure (Steps 1–9) | Activation call, sample collection, pack composition, cooler transport, bedside checks, adjunct drugs (TXA, calcium, PCC, rFVIIa), resuscitation targets, deactivation, post-MTP care |
| 7. Special Populations | Obstetric MTP, Paediatric MTP, Jehovah's Witness, anticoagulated patients |
| 8. Documentation | All 6 mandatory records with retention periods (NABH TPC.19-f) |
| 9. Training | Annual simulation, mock drills ×2/year, competency records |
| 10. Quality Indicators | 8 measurable KPIs (NABH BSQ.7) |
| 11. Adverse Reactions | Step-by-step management + haemovigilance reporting (TPC.20) |
| 12. References | PROPPR, CRASH-2, WOMAN trial, Schwartz's Surgery, NABH 4th ed. |
| 13. SOP Control & Review | Version table, annual review triggers, signature block |
Customise before use: Fill in your hospital name, document number, MTP hotline extension, and names of Prepared/Reviewed/Approved By personnel. Have it signed and uploaded to your Document Management System as a controlled document before the NABH inspection.
SOP is corrupted document . Give me another working file
python3 -c "import docx; print('python-docx OK:', docx.__version__)"
pip install --user python-docx --quiet 2>&1 | tail -3
python3 -c "import docx; print('OK', docx.__version__)"
~/mtp-sop/build_mtp.py
"""
NABH-compliant SOP: Massive Transfusion Protocol (MTP)
Built with python-docx for maximum compatibility.
"""
from docx import Document
from docx.shared import Pt, RGBColor, Inches, Cm, Twips
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT, WD_ALIGN_VERTICAL
from docx.oxml.ns import qn
from docx.oxml import OxmlElement
import copy
OUT = '/home/daytona/workspace/mtp-sop/SOP_MTP_NABH.docx'
doc = Document()
# ── Page margins ──────────────────────────────────────────────────────────
for section in doc.sections:
section.top_margin = Cm(2.0)
section.bottom_margin = Cm(2.0)
section.left_margin = Cm(2.5)
section.right_margin = Cm(2.5)
# ── Colour palette ───────────────────────────────────────────────────────
NAVY = RGBColor(0x1F, 0x38, 0x64)
BLUE = RGBColor(0x2E, 0x74, 0xB5)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
RED = RGBColor(0xC0, 0x00, 0x00)
LGRAY = RGBColor(0xEB, 0xF3, 0xFB)
BLACK = RGBColor(0x00, 0x00, 0x00)
# ── Helpers ───────────────────────────────────────────────────────────────
def set_cell_bg(cell, hex_color):
"""Shade a table cell with a hex colour string e.g. '2E74B5'."""
tc = cell._tc
tcPr = tc.get_or_add_tcPr()
shd = OxmlElement('w:shd')
shd.set(qn('w:val'), 'clear')
shd.set(qn('w:color'), 'auto')
shd.set(qn('w:fill'), hex_color)
tcPr.append(shd)
def set_col_width(cell, width_cm):
tc = cell._tc
tcPr = tc.get_or_add_tcPr()
tcW = OxmlElement('w:tcW')
tcW.set(qn('w:w'), str(int(width_cm * 567))) # 1 cm ≈ 567 twips
tcW.set(qn('w:type'), 'dxa')
tcPr.append(tcW)
def add_title_block(doc):
"""Blue title banner table."""
t = doc.add_table(rows=3, cols=4)
t.alignment = WD_TABLE_ALIGNMENT.CENTER
t.style = 'Table Grid'
# Row 0 – merged title
row0 = t.rows[0]
row0.cells[0].merge(row0.cells[3])
cell = row0.cells[0]
set_cell_bg(cell, '1F3864')
p = cell.paragraphs[0]
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.paragraph_format.space_before = Pt(6)
p.paragraph_format.space_after = Pt(2)
run = p.add_run('STANDARD OPERATING PROCEDURE')
run.bold = True
run.font.size = Pt(13)
run.font.color.rgb = WHITE
p2 = cell.add_paragraph()
p2.alignment = WD_ALIGN_PARAGRAPH.CENTER
r2 = p2.add_run('MASSIVE TRANSFUSION PROTOCOL (MTP)')
r2.bold = True
r2.font.size = Pt(20)
r2.font.color.rgb = WHITE
p3 = cell.add_paragraph()
p3.alignment = WD_ALIGN_PARAGRAPH.CENTER
p3.paragraph_format.space_after = Pt(6)
r3 = p3.add_run('Department of Blood Bank & Transfusion Medicine')
r3.font.size = Pt(11)
r3.font.color.rgb = RGBColor(0xBD, 0xD7, 0xEE)
# Row 1 – header labels
hdrs = ['Doc No.', 'Version / Rev. No.', 'Effective Date', 'Review Date']
for i, h in enumerate(hdrs):
c = t.rows[1].cells[i]
set_cell_bg(c, '2E74B5')
p = c.paragraphs[0]
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
r = p.add_run(h)
r.bold = True; r.font.size = Pt(10); r.font.color.rgb = WHITE
# Row 2 – values
vals = ['BB/SOP/MTP/01', '01 / 00', '__________', '__________']
for i, v in enumerate(vals):
c = t.rows[2].cells[i]
if i % 2 == 0:
set_cell_bg(c, 'EBF3FB')
p = c.paragraphs[0]
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.add_run(v).font.size = Pt(10)
doc.add_paragraph()
# Prepared / Reviewed / Approved / NABH Ref
t2 = doc.add_table(rows=2, cols=4)
t2.alignment = WD_TABLE_ALIGNMENT.CENTER
t2.style = 'Table Grid'
hdrs2 = ['Prepared By', 'Reviewed By', 'Approved By', 'NABH Ref.']
for i, h in enumerate(hdrs2):
c = t2.rows[0].cells[i]
set_cell_bg(c, '2E74B5')
p = c.paragraphs[0]
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
r = p.add_run(h)
r.bold = True; r.font.size = Pt(10); r.font.color.rgb = WHITE
vals2 = [
'Dr. ________________\nBlood Bank MO',
'Dr. ________________\nHead, Dept.',
'Dr. ________________\nMedical Director',
'TPC.19(e)\nBSQ.1 / BSQ.7'
]
for i, v in enumerate(vals2):
c = t2.rows[1].cells[i]
if i % 2 == 0:
set_cell_bg(c, 'EBF3FB')
p = c.paragraphs[0]
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.add_run(v).font.size = Pt(10)
doc.add_paragraph()
def h1(doc, text):
p = doc.add_paragraph()
p.paragraph_format.space_before = Pt(12)
p.paragraph_format.space_after = Pt(4)
# Bottom border
pPr = p._p.get_or_add_pPr()
pBdr = OxmlElement('w:pBdr')
bottom = OxmlElement('w:bottom')
bottom.set(qn('w:val'), 'single')
bottom.set(qn('w:sz'), '6')
bottom.set(qn('w:space'), '1')
bottom.set(qn('w:color'), '2E74B5')
pBdr.append(bottom)
pPr.append(pBdr)
run = p.add_run(text)
run.bold = True
run.font.size = Pt(13)
run.font.color.rgb = NAVY
return p
def h2(doc, text):
p = doc.add_paragraph()
p.paragraph_format.space_before = Pt(8)
p.paragraph_format.space_after = Pt(3)
run = p.add_run(text)
run.bold = True
run.font.size = Pt(11)
run.font.color.rgb = BLUE
return p
def h3(doc, text):
p = doc.add_paragraph()
p.paragraph_format.space_before = Pt(6)
p.paragraph_format.space_after = Pt(2)
run = p.add_run(text)
run.bold = True
run.font.size = Pt(10)
run.font.color.rgb = BLACK
return p
def body(doc, text, bold=False, color=None, indent=False):
p = doc.add_paragraph()
p.paragraph_format.space_before = Pt(2)
p.paragraph_format.space_after = Pt(2)
if indent:
p.paragraph_format.left_indent = Cm(1)
run = p.add_run(text)
run.font.size = Pt(10)
run.bold = bold
if color:
run.font.color.rgb = color
return p
def bullet(doc, text, level=0):
p = doc.add_paragraph(style='List Bullet')
p.paragraph_format.space_before = Pt(1)
p.paragraph_format.space_after = Pt(1)
p.paragraph_format.left_indent = Cm(1 + level)
run = p.add_run(text)
run.font.size = Pt(10)
return p
def make_table(doc, headers, rows_data, col_widths=None, alt_shade=True):
"""Generic table builder."""
ncols = len(headers)
nrows = len(rows_data)
table = doc.add_table(rows=1 + nrows, cols=ncols)
table.style = 'Table Grid'
table.alignment = WD_TABLE_ALIGNMENT.LEFT
# Header row
for i, h in enumerate(headers):
c = table.rows[0].cells[i]
set_cell_bg(c, '2E74B5')
p = c.paragraphs[0]
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
r = p.add_run(h)
r.bold = True; r.font.size = Pt(9); r.font.color.rgb = WHITE
c.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
if col_widths:
set_col_width(c, col_widths[i])
# Data rows
for ri, row_vals in enumerate(rows_data):
shade = (ri % 2 == 0) and alt_shade
for ci, val in enumerate(row_vals):
c = table.rows[ri + 1].cells[ci]
if shade:
set_cell_bg(c, 'EBF3FB')
p = c.paragraphs[0]
p.alignment = WD_ALIGN_PARAGRAPH.LEFT
r = p.add_run(str(val))
r.font.size = Pt(9)
c.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
if col_widths:
set_col_width(c, col_widths[ci])
doc.add_paragraph()
return table
# ═════════════════════════════════════════════════════════════════════════════
# BUILD DOCUMENT
# ═════════════════════════════════════════════════════════════════════════════
add_title_block(doc)
# ─── 1. PURPOSE ──────────────────────────────────────────────────────────────
h1(doc, '1. PURPOSE')
body(doc,
'This Standard Operating Procedure establishes a standardised, rapid, team-based protocol '
'for recognition and management of life-threatening haemorrhage requiring massive transfusion. '
'It ensures timely release of compatible blood products, optimises haemostatic resuscitation, '
'and fulfils NABH Accreditation Standard TPC.19(e) – "The blood centre has written guidance '
'for massive transfusions."')
# ─── 2. SCOPE ────────────────────────────────────────────────────────────────
h1(doc, '2. SCOPE')
body(doc, 'Applies to all clinical areas where massive haemorrhage may occur:')
for area in [
'Emergency Department (ED)',
'Surgical Operation Theatres (OT)',
'Obstetrics & Gynaecology (labour room, OT)',
'Intensive Care Units – Medical, Surgical, Neonatal (ICU / NICU)',
'Interventional Radiology / Cardiac Catheterisation Lab',
]:
bullet(doc, area)
body(doc,
'Involves all staff: treating clinicians, nurses, Blood Bank staff, porters/runners, '
'and the Hospital Transfusion Committee (HTC).')
# ─── 3. DEFINITIONS ──────────────────────────────────────────────────────────
h1(doc, '3. DEFINITIONS')
make_table(doc,
headers=['Term', 'Definition'],
col_widths=[5.0, 10.5],
rows_data=[
['Massive Transfusion (MT)',
'Transfusion of ≥10 units PRBC in 24 h; OR replacement of ≥50% total blood volume (TBV) '
'within 3 h; OR transfusion of >4 units PRBC in 1 h with anticipated ongoing need.'],
['MTP Activation',
'Formal hospital-wide response triggered by defined criteria to mobilise blood products '
'and clinical resources pre-emptively.'],
['MTP Pack / Cycle',
'Pre-assembled set of blood components released by the Blood Bank in one round of MTP.'],
['1:1:1 Ratio',
'Balanced haemostatic resuscitation – PRBC : FFP : Platelets in 1:1:1 ratio '
'(PROPPR Trial, JAMA 2015).'],
['Lethal Triad',
'Hypothermia (<35°C) + Acidosis (pH <7.35) + Coagulopathy – together amplifies '
'haemorrhage mortality.'],
['Damage Control Resuscitation (DCR)',
'Strategy using permissive hypotension (SBP 80–100 mmHg), minimal crystalloids, and '
'early blood component therapy.'],
['TXA',
'Tranexamic acid – antifibrinolytic administered early in traumatic or obstetric haemorrhage.'],
['TEG / ROTEM',
'Viscoelastic haemostatic assays for real-time clot function monitoring during MTP.'],
['NABH',
'National Accreditation Board for Hospitals & Healthcare Providers – Indian accreditation body.'],
]
)
# ─── 4. RESPONSIBILITIES ─────────────────────────────────────────────────────
h1(doc, '4. RESPONSIBILITIES')
make_table(doc,
headers=['Role', 'Key Responsibilities'],
col_widths=[5.5, 10.0],
rows_data=[
['Treating Clinician / MTP Lead',
'Activates and deactivates MTP; directs clinical management; communicates with Blood Bank.'],
['Blood Bank Medical Officer (BBMO)',
'Receives activation call; prepares and releases MTP packs; monitors inventory; advises '
'on component therapy.'],
['Blood Bank Technician',
'Prepares MTP coolers; labels components; documents all issues; performs urgent blood grouping.'],
['Nursing Staff (Clinical Area)',
'Draws pre-transfusion samples; administers products safely; monitors patient; '
'documents in medical record.'],
['Runner / Porter',
'Transports MTP coolers between Blood Bank and clinical area within defined time targets.'],
['Hospital Transfusion Committee (HTC)',
'Reviews all MTP activations; monitors quality indicators; revises SOP annually or '
'after adverse event.'],
]
)
# ─── 5. ACTIVATION CRITERIA ──────────────────────────────────────────────────
h1(doc, '5. CRITERIA FOR MTP ACTIVATION')
h2(doc, '5.1 ABC Score – Assessment of Blood Consumption (Activate if Score ≥ 2)')
make_table(doc,
headers=['Parameter', 'Positive Finding (Score = 1)'],
col_widths=[5.5, 10.0],
rows_data=[
['Mechanism of injury', 'Penetrating trauma'],
['Systolic BP on arrival', '≤ 90 mmHg'],
['Heart rate on arrival', '≥ 120 beats/min'],
['FAST / eFAST', 'Positive (free fluid in abdomen or pericardium)'],
]
)
body(doc, 'Score ≥ 2 → Activate MTP | Score < 2 → Continue standard '
'resuscitation and reassess.', bold=True)
h2(doc, '5.2 Additional Clinical Triggers')
for trig in [
'Active haemorrhage with haemodynamic instability not responding to 2 L crystalloid bolus',
'Postpartum haemorrhage (PPH) > 1000 mL with ongoing bleeding – activate OB-MTP variant',
'Intra-operative major vessel injury or damage-control situation',
'Anticipated ≥ 50% blood volume replacement within < 3 h',
'Clinician judgement overrides score in rapidly deteriorating patients',
]:
bullet(doc, trig)
h2(doc, '5.3 Exclusions')
for excl in [
'Confirmed refractory cardiac arrest from non-haemorrhagic cause',
'Written advance directive refusing transfusion – document in medical record and communicate '
'with treating clinician',
]:
bullet(doc, excl)
# ─── 6. PROCEDURE ────────────────────────────────────────────────────────────
h1(doc, '6. PROCEDURE')
h2(doc, 'Step 1 – Activation')
p = doc.add_paragraph()
p.paragraph_format.space_before = Pt(2)
p.paragraph_format.space_after = Pt(2)
r1 = p.add_run('Designated caller contacts Blood Bank on MTP Hotline: Extension ________ (available 24 h / 7 days).')
r1.font.size = Pt(10)
r2 = p.add_run(' Record time of call.')
r2.bold = True; r2.font.size = Pt(10)
body(doc, 'Information to provide (verbally or via HIS/EMR MTP order):')
for info in [
"Patient name / STAT name if unidentified",
"Medical Record Number (MRN) or unique patient identifier",
"Sex and approximate age (identify females of childbearing age for Rh-negative allocation)",
"Ward / location and bed number",
"Name of attending physician initiating MTP",
"Type of haemorrhage: Trauma / Obstetric (OB-MTP) / Surgical / GI bleeding",
]:
bullet(doc, info)
h2(doc, 'Step 2 – Sample Collection (Target: within 15 min of activation)')
make_table(doc,
headers=['Sample', 'Tube / Volume', 'Purpose', 'Target Time'],
col_widths=[4.0, 3.5, 4.5, 3.5],
rows_data=[
['Type & Screen', '6 mL EDTA (pink top)', 'ABO/Rh grouping, antibody screen', '≤ 15 min'],
['Crossmatch sample', '6 mL EDTA', 'Compatibility testing', 'Simultaneously'],
['Coagulation panel', '3.2% sodium citrate', 'PT, INR, aPTT, Fibrinogen', '≤ 15 min'],
['TEG / ROTEM (if available)', 'Citrated whole blood', 'Real-time clot function', 'ASAP'],
['CBC, BMP, Lactate, iCa2+', 'As per local protocol', 'Baseline and monitoring', '≤ 15 min'],
]
)
body(doc,
'NOTE: Draw samples BEFORE administering uncrossmatched blood whenever feasible. '
'Even 1 unit of un-crossmatched PRBC can interfere with subsequent crossmatching.',
bold=True, color=RED)
h2(doc, 'Step 3 – Blood Bank Response: Emergency Release & MTP Packs')
h3(doc, 'A. Uncrossmatched Emergency Release (before type & screen result):')
for item in [
'Males and post-menopausal females (> 50 y): O-positive PRBC',
'Females of childbearing age (≤ 50 y): O-negative PRBC [Reserve O-neg blood for this group]',
'FFP: AB or group A as default until patient group is confirmed',
]:
bullet(doc, item)
h3(doc, 'B. MTP Pack Composition – Standard Adult (1:1:1 ratio):')
make_table(doc,
headers=['Pack / Cycle', 'PRBC (units)', 'FFP (units)', 'Platelets', 'Cryoprecipitate', 'Target Release'],
col_widths=[2.5, 2.5, 2.5, 2.5, 3.0, 3.0],
rows_data=[
['Pack 1\n(Immediate)', '4 (O-pos/neg)', '4 (AB or A)', '—', '—',
'5–10 min after activation'],
['Pack 2', '4 (typed if available)', '4', '1 apheresis\nor 6 pooled',
'—', 'On return of Pack 1 cooler'],
['Pack 3 onwards', '4 (crossmatched)', '4',
'1 apheresis or 6 pooled\n(alternate cycles)',
'10 units if Fibrinogen\n< 1.5 g/L',
'Continue until deactivation'],
]
)
h3(doc, 'C. Paediatric MTP (weight-based):')
make_table(doc,
headers=['Component', '< 40 kg', '> 40 kg'],
col_widths=[5.0, 3.5, 3.5],
rows_data=[
['PRBC', '2 units', '4 units'],
['FFP', '2 units', '4 units'],
['Platelets', '1 unit (odd cycles)', '1 unit (odd cycles)'],
]
)
h2(doc, 'Step 4 – Cooler Transport & Chain of Custody')
for item in [
'Blood Bank packs all products in a validated transport cooler (maintains 1–6°C for PRBC).',
'A designated runner collects the cooler presenting patient ID label with ≥ 2 identifiers.',
'Runner and Blood Bank staff perform verbal read-back to confirm correct cooler is released.',
'Transport time target: Blood Bank to clinical area ≤ 10 minutes.',
'Empty cooler returned to Blood Bank by runner to trigger release of next pack.',
]:
bullet(doc, item)
h2(doc, 'Step 5 – Bedside Administration')
h3(doc, 'Pre-transfusion checks (two-person check: nurse + nurse or nurse + doctor):')
for chk in [
'Two patient identifiers (name + MRN) match patient wristband AND blood pack label',
'Blood group and component type verified',
'Pack inspected for abnormal colour, clots, haemolysis, or integrity breach',
'Expiry date confirmed',
'Informed consent documented; or emergency exception noted in medical record',
]:
bullet(doc, chk)
h3(doc, 'Administration:')
for item in [
'Large-bore IV access – minimum 16G; central venous or intra-osseous access for dire emergencies',
'Blood administration set with 170–200 µm filter; use pressure bag if required',
'Warm blood using validated blood warmer (target 37°C) – NEVER use microwave or hot water',
'Run each unit as rapidly as haemodynamic state allows',
]:
bullet(doc, item)
h2(doc, 'Step 6 – Adjunct Pharmacological Therapy')
make_table(doc,
headers=['Agent', 'Dose', 'Indication', 'Timing / Notes'],
col_widths=[3.5, 4.0, 4.5, 3.5],
rows_data=[
['Tranexamic Acid\n(TXA)',
'1 g IV over 10 min;\nthen 1 g over 8 h',
'Trauma / obstetric haemorrhage with hyperfibrinolysis',
'Within 3 h of onset\n(CRASH-2 trial)'],
['Calcium Chloride\n10%',
'1–2 g IV after each\nMTP pack (4–6 units PRBC)',
'Hypocalcaemia from citrate in transfused products',
'Monitor ionised Ca2+;\ntarget iCa 1.1–1.3 mmol/L'],
['Cryoprecipitate',
'10 units (pooled)',
'Fibrinogen < 1.5–2 g/L;\nhypofibrinogenaemia in PPH',
'Order with Pack 2\n(thaw time ~30 min)'],
['Prothrombin Complex\nConcentrate (PCC)',
'25–50 IU/kg IV',
'Anticoagulation reversal\n(warfarin / DOAC) + active bleeding',
'On senior clinician order;\ncheck local availability'],
['Recombinant\nFactor VIIa (rFVIIa)',
'90 µg/kg IV (off-label)',
'Refractory haemorrhage after correcting pH,\ntemp, and platelets',
'Last resort; document\nclinical indication'],
]
)
h2(doc, 'Step 7 – Resuscitation Targets and Monitoring')
make_table(doc,
headers=['Parameter', 'Target'],
col_widths=[7.0, 8.5],
rows_data=[
['Systolic BP (permissive hypotension, pre-operative)', '80–100 mmHg (non-TBI) | >110 mmHg (TBI / obstetric)'],
['Mean Arterial Pressure (MAP)', '≥ 60 mmHg (65–70 mmHg in TBI)'],
['Haemoglobin', '7–9 g/dL; transfuse when ≤ 7 g/dL during active haemorrhage'],
['INR', '< 1.5'],
['aPTT', '< 42 seconds'],
['Fibrinogen', '> 1.5–2 g/L'],
['Platelet count', '> 50 × 10⁹/L (> 100 × 10⁹/L in TBI or multiple trauma)'],
['Core body temperature', '> 35.0°C (use blood warmer, Bair Hugger in OT)'],
['pH', '7.35–7.45'],
['Ionised Calcium (iCa2+)', '1.1–1.3 mmol/L'],
['Serum lactate', '< 2 mEq/L and trending down'],
['Base deficit', '< 3'],
]
)
body(doc,
'Labs: Repeat CBC, coagulation screen, fibrinogen, electrolytes, lactate every 30–60 min '
'during active MTP. Use TEG/ROTEM if available to guide targeted component therapy.')
body(doc,
'Prevention of lethal triad: blood warmers, forced-air warming (OT), NaHCO3 for pH < 7.20 '
'on clinician order, avoid large-volume crystalloid resuscitation.')
h2(doc, 'Step 8 – Deactivation')
body(doc, 'Activating physician deactivates MTP when ANY of the following:')
for cond in [
'Haemorrhage surgically / radiologically controlled AND haemodynamic stability achieved',
'Resuscitation targets in Step 7 are met',
'Clinical decision to institute comfort measures only',
'Patient death',
]:
bullet(doc, cond)
body(doc, 'Deactivation call to Blood Bank on same MTP hotline. Record time of deactivation.')
body(doc, 'Blood Bank on deactivation:')
for action in [
'Stop preparation of further MTP packs immediately',
'Return unused components to appropriate storage ONLY if cold chain is unbroken (document time out of storage)',
'Discard components if cold chain is compromised',
'Complete Blood Bank MTP Log Sheet',
]:
bullet(doc, action)
h2(doc, 'Step 9 – Post-MTP Care')
for item in [
'Recheck CBC, INR, aPTT, fibrinogen, iCa2+, K+, serum lactate once MTP deactivated',
'12-lead ECG to assess volume status and cardiac arrhythmias',
'Monitor for transfusion-related complications: TACO, TRALI, AHTR, DIC, hyperkalaemia, hypothermia',
'Transition to standard crossmatched blood products',
'Complete haemovigilance documentation in patient medical record (NABH TPC.19 – commitment f)',
]:
bullet(doc, item)
# ─── 7. SPECIAL POPULATIONS ──────────────────────────────────────────────────
h1(doc, '7. SPECIAL POPULATIONS')
h2(doc, '7.1 Obstetric MTP (OB-MTP)')
for item in [
'Trigger: PPH > 1000 mL with ongoing bleeding, or > 500 mL with haemodynamic instability',
'Specify "OB-MTP" on activation call – Blood Bank will prioritise cryoprecipitate early',
'Fibrinogen falls rapidly in obstetric haemorrhage – target fibrinogen > 2 g/L',
'TXA 1 g IV within 3 h of onset is strongly recommended (WOMAN Trial)',
'Target platelets > 75 × 10⁹/L in PPH; coordinate with obstetric surgeon, anaesthetist, neonatologist',
]:
bullet(doc, item)
h2(doc, '7.2 Paediatric MTP')
for item in [
'Activate if estimated blood loss > 40 mL/kg or haemodynamic instability after 20 mL/kg bolus',
'TXA: 15 mg/kg IV (max 1 g) loading dose',
'Use paediatric pack composition (see Section 6, Step 3C)',
]:
bullet(doc, item)
h2(doc, '7.3 Jehovah\'s Witness / Blood Refusal')
for item in [
'Respect documented advance directives and informed refusal',
'Maximise cell salvage, acute normovolaemic haemodilution, haemostatic surgery',
'Consult ethics committee if patient is a minor or unconscious and refusal is documented by family',
'Document all discussions and decisions in the medical record',
]:
bullet(doc, item)
h2(doc, '7.4 Anticoagulated Patients')
make_table(doc,
headers=['Anticoagulant', 'Reversal Agent', 'Dose'],
col_widths=[4.5, 5.0, 6.0],
rows_data=[
['Warfarin', 'Prothrombin Complex Concentrate (PCC) + Vitamin K', 'PCC 25–50 IU/kg IV + Vit K 10 mg IV slow'],
['Dabigatran (DOAC)', 'Idarucizumab (Praxbind)', '5 g IV (2 x 2.5 g vials)'],
['Rivaroxaban / Apixaban', 'Andexanet alfa', 'Per local protocol / prescribing information'],
['Unfractionated Heparin', 'Protamine sulphate', '1 mg per 100 units of heparin IV'],
]
)
# ─── 8. DOCUMENTATION ────────────────────────────────────────────────────────
h1(doc, '8. DOCUMENTATION & RECORDS (NABH TPC.19-f)')
make_table(doc,
headers=['Record / Form', 'Where Filed', 'Retention', 'Responsible Person'],
col_widths=[5.0, 3.5, 2.5, 4.5],
rows_data=[
['MTP Activation Log (Blood Bank)', 'Blood Bank Register / HIS', '10 years', 'BBMO / Technician'],
['Blood Product Issue Record (component, volume, time, recipient)', 'Blood Bank + Patient file', '10 years', 'Blood Bank Technician'],
['MTP Clinical Flow Sheet (bedside)', 'Patient medical record (EMR)', 'Permanent', 'Treating team / Nurse'],
['Transfusion Consent Form or Emergency Exception Note', 'Patient medical record', 'Permanent', 'Treating clinician'],
['Adverse Transfusion Reaction Report', 'Blood Bank + Quality Dept.', '10 years', 'BBMO + Treating team'],
['Post-MTP Audit Sheet (HTC review)', 'Quality / HTC file', '5 years', 'HTC Convener'],
]
)
# ─── 9. TRAINING ─────────────────────────────────────────────────────────────
h1(doc, '9. TRAINING & COMPETENCY')
for item in [
'All Blood Bank staff complete MTP simulation training at induction and annually thereafter.',
'Clinical staff (ED, OT, ICU, Obstetrics) complete MTP awareness training – minimum once per year.',
'Mock MTP drills conducted at least twice per year; findings reviewed at HTC.',
'Competency records maintained in the HR / training management system.',
'New staff complete training before independent MTP activation is permitted.',
]:
bullet(doc, item)
# ─── 10. QUALITY INDICATORS ──────────────────────────────────────────────────
h1(doc, '10. QUALITY INDICATORS (NABH BSQ.7)')
make_table(doc,
headers=['Quality Indicator', 'Target / Standard', 'Review Frequency'],
col_widths=[6.5, 5.0, 3.0],
rows_data=[
['Time from MTP activation to first PRBC release', '≤ 10 minutes', 'Monthly'],
['Time from activation to sample receipt in Blood Bank', '≤ 15 minutes', 'Monthly'],
['TXA administered within 3 h of haemorrhage onset (eligible cases)', '≥ 90% of eligible cases', 'Monthly'],
['PRBC : FFP ratio ≥ 1:1 achieved by end of MTP', '≥ 85% of MTP activations', 'Per event + Monthly'],
['MTP activation-to-deactivation fully documented', '100%', 'Per event'],
['Adverse transfusion reaction rate post-MTP', 'Monitor and trend; investigate all Grade ≥ 2', 'Per event + Monthly'],
['Blood product wastage during MTP (unused units discarded)', 'Minimise; review each occurrence', 'Monthly'],
['30-day mortality post-MTP', 'Benchmark vs national data', 'Quarterly'],
]
)
# ─── 11. ADVERSE REACTIONS ───────────────────────────────────────────────────
h1(doc, '11. ADVERSE TRANSFUSION REACTIONS (NABH TPC.20)')
body(doc, 'If a suspected adverse transfusion reaction occurs:')
for step in [
'STOP the transfusion immediately',
'Maintain IV access; administer 0.9% NaCl to keep vein open',
'Notify treating clinician and Blood Bank Medical Officer immediately',
'Check patient identity and blood pack label for clerical error (wrong blood in wrong patient)',
'Return blood pack, tubing, and IV fluid bag (do not discard) to Blood Bank with post-transfusion samples (EDTA, plain tube, fresh urine)',
'Complete Adverse Transfusion Reaction Form',
'Serious reactions (AHTR, TRALI, TACO, TTI) reported to Haemovigilance System and Quality Department',
'Root cause analysis (RCA) for severe / unexpected reactions; CAPA plan reviewed at HTC',
]:
bullet(doc, step)
# ─── 12. REFERENCES ──────────────────────────────────────────────────────────
h1(doc, '12. REFERENCES')
for ref in [
'NABH Accreditation Standards for Blood Centres and Transfusion Services, 4th Edition. '
'Standards: TPC.19, TPC.20, BSQ.1, BSQ.7, BSQ.11.',
'Holcomb JB et al. PROPPR Trial: Transfusion of Plasma, Platelets, and Red Blood Cells '
'in a 1:1:1 vs 1:1:2 Ratio and Mortality in Patients with Severe Trauma. '
'JAMA. 2015;313(5):471–482.',
'CRASH-2 Collaborators. Effects of tranexamic acid on death, vascular occlusive events, '
'and blood transfusion in trauma patients with significant haemorrhage. '
'Lancet. 2010;376:23–32.',
'Shakur H et al. (WOMAN Trial). Effect of early tranexamic acid on mortality and '
'hysterectomy in women with post-partum haemorrhage. Lancet. 2017;389:2105–2116.',
'Schwartz\'s Principles of Surgery, 11th Edition. Chapter 7: Trauma. McGraw-Hill, 2019.',
'Sabiston Textbook of Surgery, 21st Edition. Elsevier, 2022.',
'Indian Journal of Anaesthesia. Massive transfusion and massive transfusion protocol. '
'IJA 2014;58(5):590–595. PMID: 25535421.',
'National Blood Policy, Ministry of Health & Family Welfare, Government of India.',
'Drugs and Cosmetics Act, 1940 (amended) – Schedule F: Blood Bank licensing requirements.',
]:
bullet(doc, ref)
# ─── 13. SOP CONTROL ─────────────────────────────────────────────────────────
h1(doc, '13. SOP CONTROL & REVIEW')
make_table(doc,
headers=['Version', 'Effective Date', 'Changes Made', 'Changed By'],
col_widths=[2.0, 3.0, 7.5, 3.0],
rows_data=[
['01 / 00', '________________', 'Initial version', 'Dr. ________________'],
['', '', '', ''],
]
)
body(doc, 'This SOP is reviewed annually by the HTC or earlier if triggered by:')
for trig in [
'Adverse event / sentinel event related to MTP',
'Changes in national blood transfusion guidelines',
'NABH inspection findings',
'Mock drill audit findings',
]:
bullet(doc, trig)
doc.add_paragraph()
# Signature block
h2(doc, 'Authorisation Signatures')
make_table(doc,
headers=['Prepared By', 'Reviewed By', 'Approved By'],
col_widths=[5.0, 5.0, 5.5],
rows_data=[
['Name:\nDesignation:\nSignature:\nDate:', 'Name:\nDesignation:\nSignature:\nDate:', 'Name:\nDesignation:\nSignature:\nDate:'],
]
)
doc.add_paragraph()
ctrl = doc.add_paragraph()
ctrl.alignment = WD_ALIGN_PARAGRAPH.CENTER
r = ctrl.add_run(
'CONTROLLED DOCUMENT – Uncontrolled copies are valid only on the date of printing. '
'Verify version on the Document Management System before use.'
)
r.bold = True
r.font.size = Pt(9)
r.font.color.rgb = RED
# ─── SAVE ─────────────────────────────────────────────────────────────────────
doc.save(OUT)
print(f'SUCCESS: Saved to {OUT}')
cd /home/daytona/workspace/mtp-sop && python3 build_mtp.py 2>&1
python3 - <<'EOF' # Quick test: does python-docx save at all? from docx import Document import io, os doc = Document() doc.add_paragraph("Test paragraph") buf = io.BytesIO() doc.save(buf) data = buf.getvalue() out = '/home/daytona/workspace/mtp-sop/test_mini.docx' with open(out, 'wb') as f: f.write(data) print("OK, size:", os.path.getsize(out)) EOF
~/mtp-sop/build_mtp.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/mtp-sop/build_mtp.py'
cd /home/daytona/workspace/mtp-sop && python3 build_mtp.py 2>&1
python3 -c " import zipfile, os path = '/home/daytona/workspace/mtp-sop/SOP_MTP_NABH.docx' size = os.path.getsize(path) z = zipfile.ZipFile(path) names = z.namelist() z.close() print(f'Size: {size/1024:.1f} KB | ZIP entries: {len(names)} | Valid: YES') print('Key files:', [n for n in names if n.endswith('.xml')][:6]) "
SOP MTP NABH
Word Document · DOCX
python-docx (fully Word/LibreOffice compatible). It opens cleanly in Microsoft Word, LibreOffice Writer, and Google Docs.Make a PPT of 20 slides on the topic small for gestational age vs Fetal growth restriction from standard textbooks
mkdir -p /home/daytona/workspace/sga-fgr-ppt && ls /home/daytona/workspace/sga-fgr-ppt/
~/sga-fgr-ppt/build.js
const pptxgen = require("pptxgenjs");
const pres = new pptxgen();
pres.layout = "LAYOUT_WIDE"; // 13.3" x 7.5"
// ── Palette ──────────────────────────────────────────────────────────────────
const C = {
navy: "0D2B55", // dominant background / dark slides
teal: "1A7B8C", // accent headings
aqua: "21B8A8", // highlight bar / accent
cream: "F6F2EA", // light bg
white: "FFFFFF",
charcoal:"2C3E50",
muted: "5E7080",
orange: "E07B39", // contrast accent for SGA callouts
green: "2A7F4F", // FGR comparison
lemon: "F5E642", // stat highlight
pink: "E85D8A", // obstetric accent
};
// ── Reusable layout helpers ───────────────────────────────────────────────────
function darkSlide(slide) {
slide.background = { color: C.navy };
}
function lightSlide(slide) {
slide.background = { color: C.cream };
}
function whiteSlide(slide) {
slide.background = { color: C.white };
}
// Header bar on light slides
function headerBar(slide, title, sub) {
// Teal left bar accent
slide.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 0.12, h: 7.5, fill: { color: C.teal } });
// Top title strip
slide.addShape(pres.ShapeType.rect, { x: 0.12, y: 0, w: 13.18, h: 1.0, fill: { color: C.navy } });
slide.addText(title, {
x: 0.3, y: 0.08, w: 12.5, h: 0.75,
fontSize: 26, bold: true, color: C.white, fontFace: "Calibri", valign: "middle"
});
if (sub) {
slide.addText(sub, {
x: 0.3, y: 0.78, w: 12.5, h: 0.28,
fontSize: 11, color: C.aqua, fontFace: "Calibri", italic: true
});
}
// Bottom source bar
slide.addShape(pres.ShapeType.rect, { x: 0.12, y: 7.15, w: 13.18, h: 0.35, fill: { color: C.teal }, line: { color: C.teal } });
slide.addText("Source: Creasy & Resnik's Maternal-Fetal Medicine 9e | Robbins Basic Pathology | Campbell-Walsh Urology", {
x: 0.3, y: 7.17, w: 12.8, h: 0.28, fontSize: 8.5, color: C.white, fontFace: "Calibri"
});
}
// Bullet list helper
function bullets(slide, items, opts = {}) {
const x = opts.x ?? 0.3;
const y = opts.y ?? 1.15;
const w = opts.w ?? 12.5;
const h = opts.h ?? 5.8;
const sz = opts.sz ?? 18;
const clr = opts.clr ?? C.charcoal;
const richItems = items.map((item, i) => ({
text: item,
options: {
bullet: { code: "25B8", color: C.teal },
breakLine: i < items.length - 1,
fontSize: sz,
color: typeof item === "object" ? item.color : clr,
fontFace: "Calibri",
paraSpaceBefore: 4,
}
}));
slide.addText(richItems, { x, y, w, h, valign: "top" });
}
// Comparison column builder
function twoCol(slide, leftTitle, leftItems, rightTitle, rightItems, opts = {}) {
const leftColor = opts.lc ?? C.orange;
const rightColor = opts.rc ?? C.green;
const topY = 1.1;
// Left column bg
slide.addShape(pres.ShapeType.rect, { x: 0.2, y: topY, w: 6.1, h: 5.9, fill: { color: "FFF3EC" }, line: { color: leftColor, pt: 1.5 } });
// Right column bg
slide.addShape(pres.ShapeType.rect, { x: 6.8, y: topY, w: 6.1, h: 5.9, fill: { color: "EAF6EE" }, line: { color: rightColor, pt: 1.5 } });
// Left header
slide.addShape(pres.ShapeType.rect, { x: 0.2, y: topY, w: 6.1, h: 0.55, fill: { color: leftColor } });
slide.addText(leftTitle, { x: 0.25, y: topY + 0.03, w: 6.0, h: 0.5, fontSize: 18, bold: true, color: C.white, fontFace: "Calibri", align: "center" });
// Right header
slide.addShape(pres.ShapeType.rect, { x: 6.8, y: topY, w: 6.1, h: 0.55, fill: { color: rightColor } });
slide.addText(rightTitle, { x: 6.85, y: topY + 0.03, w: 6.0, h: 0.5, fontSize: 18, bold: true, color: C.white, fontFace: "Calibri", align: "center" });
// Left bullets
const li = leftItems.map((t, i) => ({ text: t, options: { bullet: { code: "25B8", color: leftColor }, breakLine: i < leftItems.length - 1, fontSize: 16, color: C.charcoal, fontFace: "Calibri", paraSpaceBefore: 4 } }));
slide.addText(li, { x: 0.3, y: topY + 0.65, w: 5.9, h: 5.1, valign: "top" });
// Right bullets
const ri = rightItems.map((t, i) => ({ text: t, options: { bullet: { code: "25B8", color: rightColor }, breakLine: i < rightItems.length - 1, fontSize: 16, color: C.charcoal, fontFace: "Calibri", paraSpaceBefore: 4 } }));
slide.addText(ri, { x: 6.9, y: topY + 0.65, w: 5.9, h: 5.1, valign: "top" });
}
// Info-box helper
function infoBox(slide, x, y, w, h, title, body, accentColor) {
slide.addShape(pres.ShapeType.rect, { x, y, w, h, fill: { color: C.white }, line: { color: accentColor, pt: 2 } });
slide.addShape(pres.ShapeType.rect, { x, y, w, h: 0.42, fill: { color: accentColor } });
slide.addText(title, { x: x + 0.08, y: y + 0.04, w: w - 0.1, h: 0.36, fontSize: 13, bold: true, color: C.white, fontFace: "Calibri" });
slide.addText(body, { x: x + 0.1, y: y + 0.48, w: w - 0.2, h: h - 0.6, fontSize: 13, color: C.charcoal, fontFace: "Calibri", valign: "top" });
}
// ─────────────────────────────────────────────────────────────────────────────
// SLIDE 1 – TITLE
// ─────────────────────────────────────────────────────────────────────────────
{
const s = pres.addSlide();
darkSlide(s);
// Decorative diagonal shape
s.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 13.3, h: 2.2, fill: { color: C.teal }, line: { color: C.teal } });
s.addShape(pres.ShapeType.rect, { x: 0, y: 5.7, w: 13.3, h: 1.8, fill: { color: C.teal }, line: { color: C.teal } });
// Vertical accent bars
s.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 0.45, h: 7.5, fill: { color: C.aqua }, line: { color: C.aqua } });
s.addShape(pres.ShapeType.rect, { x: 12.85, y: 0, w: 0.45, h: 7.5, fill: { color: C.aqua }, line: { color: C.aqua } });
s.addText("Small for Gestational Age", {
x: 0.6, y: 0.15, w: 12.1, h: 0.9,
fontSize: 36, bold: true, color: C.white, fontFace: "Calibri", align: "center", charSpacing: 2
});
s.addText("vs", {
x: 0.6, y: 1.05, w: 12.1, h: 0.7,
fontSize: 28, bold: true, color: C.lemon, fontFace: "Calibri", align: "center", italic: true
});
s.addText("Fetal Growth Restriction", {
x: 0.6, y: 1.65, w: 12.1, h: 0.9,
fontSize: 36, bold: true, color: C.white, fontFace: "Calibri", align: "center", charSpacing: 2
});
s.addText("Definitions · Pathophysiology · Diagnosis · Surveillance · Management", {
x: 0.6, y: 2.85, w: 12.1, h: 0.55,
fontSize: 18, color: C.aqua, fontFace: "Calibri", align: "center", italic: true
});
// Divider
s.addShape(pres.ShapeType.rect, { x: 3.5, y: 3.55, w: 6.3, h: 0.06, fill: { color: C.aqua } });
s.addText("Based on standard textbooks:\nCreasy & Resnik's Maternal-Fetal Medicine 9e • Robbins Basic Pathology\nSabiston Textbook of Surgery • Williams Obstetrics", {
x: 0.6, y: 3.75, w: 12.1, h: 1.5,
fontSize: 14, color: "AACCD0", fontFace: "Calibri", align: "center"
});
s.addText("Department of Obstetrics & Gynaecology", {
x: 0.6, y: 5.8, w: 12.1, h: 0.5,
fontSize: 16, color: C.navy, fontFace: "Calibri", align: "center", bold: true
});
}
// ─────────────────────────────────────────────────────────────────────────────
// SLIDE 2 – OVERVIEW / OUTLINE
// ─────────────────────────────────────────────────────────────────────────────
{
const s = pres.addSlide();
lightSlide(s);
headerBar(s, "Overview", "What this presentation covers");
const modules = [
["01", "Historical Context & Evolution of Terminology"],
["02", "Definitions: SGA vs FGR — Key Differences"],
["03", "Incidence & Epidemiology"],
["04", "Aetiology & Risk Factors"],
["05", "Pathophysiology: Placental & Fetal Mechanisms"],
["06", "Classification: Symmetric vs Asymmetric FGR"],
["07", "Staging Systems (Doppler-Based)"],
["08", "Diagnosis — Screening & Ultrasound Biometry"],
["09", "Doppler Velocimetry in FGR Surveillance"],
["10", "Biophysical Profile & CTG Monitoring"],
["11", "Perinatal Outcomes & Mortality Risk"],
["12", "Management: Timing of Delivery"],
["13", "Neonatal Complications"],
["14", "Long-Term Sequelae: Barker Hypothesis"],
["15", "Summary Comparison Table"],
];
const perCol = 8;
modules.slice(0, perCol).forEach(([num, txt], i) => {
const y = 1.2 + i * 0.72;
s.addShape(pres.ShapeType.rect, { x: 0.25, y, w: 0.55, h: 0.52, fill: { color: C.teal } });
s.addText(num, { x: 0.25, y, w: 0.55, h: 0.52, fontSize: 14, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(txt, { x: 0.9, y: y + 0.04, w: 5.5, h: 0.44, fontSize: 14, color: C.charcoal, fontFace: "Calibri", valign: "middle" });
});
modules.slice(perCol).forEach(([num, txt], i) => {
const y = 1.2 + i * 0.72;
s.addShape(pres.ShapeType.rect, { x: 6.8, y, w: 0.55, h: 0.52, fill: { color: C.navy } });
s.addText(num, { x: 6.8, y, w: 0.55, h: 0.52, fontSize: 14, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(txt, { x: 7.45, y: y + 0.04, w: 5.7, h: 0.44, fontSize: 14, color: C.charcoal, fontFace: "Calibri", valign: "middle" });
});
}
// ─────────────────────────────────────────────────────────────────────────────
// SLIDE 3 – HISTORICAL CONTEXT
// ─────────────────────────────────────────────────────────────────────────────
{
const s = pres.addSlide();
lightSlide(s);
headerBar(s, "Historical Context & Evolution of Terminology", "Creasy & Resnik 9e, Chapter 44");
s.addShape(pres.ShapeType.rect, { x: 0.25, y: 1.15, w: 12.8, h: 5.75, fill: { color: C.white }, line: { color: "CCCCCC" } });
const timeline = [
{ yr: "Early 20th C", txt: "All small newborns were considered premature", clr: C.muted },
{ yr: "Mid-20th C", txt: "Concept of 'undernourished neonate' arose; WHO classified infants <2500 g as low-birth-weight", clr: C.teal },
{ yr: "1960s", txt: "Lubchenco et al. published birth-weight-for-gestational-age percentile charts — introduced SGA (<10th %ile), AGA (10th–90th), LGA (>90th)", clr: C.navy },
{ yr: "1970s–80s", txt: "SGA became surrogate for FGR — recognised as problematic since many SGA infants are constitutionally normal", clr: C.orange },
{ yr: "1990s–2000s", txt: "Concept of customised growth curves proposed to account for race, parity, height, weight, fetal sex", clr: C.teal },
{ yr: "Present", txt: "FGR defined as a fetus that fails to achieve its growth POTENTIAL — heterogeneous entity with distinct phenotypes", clr: C.green },
];
timeline.forEach(({ yr, txt, clr }, i) => {
const y = 1.25 + i * 0.9;
s.addShape(pres.ShapeType.rect, { x: 0.3, y, w: 2.0, h: 0.62, fill: { color: clr } });
s.addText(yr, { x: 0.3, y, w: 2.0, h: 0.62, fontSize: 13, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
// Connector dot
s.addShape(pres.ShapeType.oval, { x: 2.3, y: y + 0.22, w: 0.18, h: 0.18, fill: { color: clr } });
if (i < timeline.length - 1) {
s.addShape(pres.ShapeType.rect, { x: 2.37, y: y + 0.4, w: 0.04, h: 0.5, fill: { color: "BBBBBB" } });
}
s.addText(txt, { x: 2.6, y: y + 0.04, w: 10.1, h: 0.6, fontSize: 14.5, color: C.charcoal, fontFace: "Calibri", valign: "middle" });
});
}
// ─────────────────────────────────────────────────────────────────────────────
// SLIDE 4 – DEFINITIONS
// ─────────────────────────────────────────────────────────────────────────────
{
const s = pres.addSlide();
lightSlide(s);
headerBar(s, "Definitions: SGA vs FGR", "The critical distinction — Creasy & Resnik 9e, Chapter 44");
twoCol(s,
"SGA (Small for Gestational Age)",
[
"Descriptive / statistical label applied at BIRTH",
"Birth weight < 10th percentile for gestational age",
"Population-based reference standard (Lubchenco or newer curves)",
"Many SGA infants are constitutionally small and NORMAL",
"Does NOT imply pathology — simply reflects birth weight distribution",
"~10% of all neonates by definition are SGA",
"Preferred terminology: SGA for the NEWBORN",
],
"FGR (Fetal Growth Restriction)",
[
"Pathophysiological process — fetus fails to achieve its GROWTH POTENTIAL",
"Applies to the FETUS in utero (antenatal diagnosis)",
"May be below OR above 10th percentile (customised curves)",
"Implies underlying disease: placental, maternal, or fetal",
"Associated with adverse perinatal outcomes regardless of percentile",
"Not synonymous with SGA — though overlap exists",
"Preferred terminology: FGR for the FETUS",
],
{ lc: C.orange, rc: C.green }
);
}
// ─────────────────────────────────────────────────────────────────────────────
// SLIDE 5 – INCIDENCE & EPIDEMIOLOGY
// ─────────────────────────────────────────────────────────────────────────────
{
const s = pres.addSlide();
darkSlide(s);
s.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 13.3, h: 1.0, fill: { color: C.teal } });
s.addText("Incidence & Epidemiology", {
x: 0.3, y: 0.1, w: 12.7, h: 0.75, fontSize: 28, bold: true, color: C.white, fontFace: "Calibri"
});
s.addText("WHO Bulletin 1987 | Creasy & Resnik 9e", {
x: 0.3, y: 0.77, w: 12.7, h: 0.3, fontSize: 11, color: C.aqua, fontFace: "Calibri", italic: true
});
const stats = [
{ val: "~4–8%", label: "Infants classified as FGR\nin developed countries", clr: C.aqua },
{ val: "6–30%", label: "Infants classified as FGR\nin developing countries", clr: C.orange },
{ val: "~1/3", label: "Of <2500 g infants born\nat term are SGA/FGR", clr: C.pink },
{ val: "~60%", label: "Of FGR cases have\nunknown aetiology", clr: C.lemon },
];
stats.forEach(({ val, label, clr }, i) => {
const x = 0.4 + i * 3.1;
s.addShape(pres.ShapeType.rect, { x, y: 1.2, w: 2.8, h: 2.5, fill: { color: "1A2A40" }, line: { color: clr, pt: 2 } });
s.addText(val, { x, y: 1.3, w: 2.8, h: 1.2, fontSize: 42, bold: true, color: clr, fontFace: "Calibri", align: "center" });
s.addText(label, { x, y: 2.5, w: 2.8, h: 1.1, fontSize: 14, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
});
bullets(s, [
"FGR is the second most common cause of perinatal mortality (after preterm birth)",
"Perinatal mortality increases EXPONENTIALLY when birth weight is < 6th percentile (Manning)",
"One-fourth to one-third of all <2500 g infants have sustained intrauterine growth restriction",
"FGR diagnosis varies by: population studied · geographic location · reference growth curve used · percentile cutoff (3rd, 5th, or 10th)",
"Risk of intrauterine fetal death (IUFD) rises significantly in SGA fetuses — highest below 5th–3rd percentile",
], { y: 3.85, sz: 15, clr: C.white });
}
// ─────────────────────────────────────────────────────────────────────────────
// SLIDE 6 – AETIOLOGY
// ─────────────────────────────────────────────────────────────────────────────
{
const s = pres.addSlide();
lightSlide(s);
headerBar(s, "Aetiology & Risk Factors of FGR", "Robbins Basic Pathology | Creasy & Resnik 9e");
const cats = [
{
title: "MATERNAL FACTORS\n(most common)", clr: C.orange, x: 0.2,
items: [
"Vascular disease: preeclampsia,\nchronic hypertension",
"Hypercoagulability (inherited or acquired)",
"Maternal malnutrition / hypoglycaemia",
"Cyanotic heart disease (↓ O₂ delivery)",
"Cigarette smoking: ↓ 135–300 g birth wt",
"Alcohol: ≥1–2 drinks/day",
"Cocaine / narcotic use",
"Teratogenic drugs (e.g., phenytoin)",
"Severe IBD / malabsorption",
"Altitude (>10,000 ft): ↓ ~250 g)",
]
},
{
title: "FETAL FACTORS", clr: C.teal, x: 4.6,
items: [
"Chromosomal disorders (trisomies 13, 18, 21)",
"Structural congenital anomalies",
"TORCH infections (CMV, Rubella, Toxo)",
"Multiple gestation (twin/triplet)",
"Male sex: slightly heavier than female",
"Constitutional small fetus (normal variant)",
]
},
{
title: "PLACENTAL FACTORS", clr: C.green, x: 8.85,
items: [
"Placenta praevia (low implantation)",
"Placental abruption",
"Placental infarction / haematoma",
"Chronic villitis",
"Haemorrhagic endovasculitis",
"Confined placental mosaicism",
"Umbilical cord abnormalities",
"Velamentous cord insertion",
]
},
];
cats.forEach(({ title, clr, x, items }) => {
s.addShape(pres.ShapeType.rect, { x, y: 1.1, w: 4.1, h: 6.1, fill: { color: C.white }, line: { color: clr, pt: 1.5 } });
s.addShape(pres.ShapeType.rect, { x, y: 1.1, w: 4.1, h: 0.65, fill: { color: clr } });
s.addText(title, { x: x + 0.08, y: 1.12, w: 3.95, h: 0.65, fontSize: 13, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
const ri = items.map((t, i) => ({ text: t, options: { bullet: { code: "25B8", color: clr }, breakLine: i < items.length - 1, fontSize: 13, color: C.charcoal, fontFace: "Calibri", paraSpaceBefore: 3 } }));
s.addText(ri, { x: x + 0.1, y: 1.82, w: 3.9, h: 5.2, valign: "top" });
});
}
// ─────────────────────────────────────────────────────────────────────────────
// SLIDE 7 – PATHOPHYSIOLOGY
// ─────────────────────────────────────────────────────────────────────────────
{
const s = pres.addSlide();
lightSlide(s);
headerBar(s, "Pathophysiology of FGR", "Creasy & Resnik 9e, Chapter 14 — Placental & Fetal Mechanisms");
// Central flow
const steps = [
{ txt: "Placental mass ↓\n(reduced terminal villi growth)", clr: C.navy },
{ txt: "Umbilical capillary bed\nexpansion rate ↓", clr: C.teal },
{ txt: "Umbilical blood flow / kg\nfetal weight ↓\n(↑ Umbilical Pulsatility Index)", clr: C.orange },
{ txt: "Vasosyncytial membrane\nproduction ↓\n→ ↓ Placental O₂ permeability", clr: C.orange },
{ txt: "↓ fetal PO₂\n(umbilical vein O₂ sat ~50% vs\nnormal 81%)\npH 7.33", clr: C.pink },
{ txt: "Fetal growth slows\n→ ↓ O₂ demand\n→ Compensatory redistribution\n(Brain sparing)", clr: C.green },
];
steps.forEach(({ txt, clr }, i) => {
const col = i % 3;
const row = Math.floor(i / 3);
const x = 0.25 + col * 4.3;
const y = 1.15 + row * 2.9;
s.addShape(pres.ShapeType.rect, { x, y, w: 4.0, h: 2.45, fill: { color: C.white }, line: { color: clr, pt: 2 } });
s.addShape(pres.ShapeType.rect, { x, y, w: 4.0, h: 0.42, fill: { color: clr } });
s.addText(`Step ${i + 1}`, { x, y: y + 0.04, w: 4.0, h: 0.36, fontSize: 11, bold: true, color: C.white, fontFace: "Calibri", align: "center" });
s.addText(txt, { x: x + 0.1, y: y + 0.5, w: 3.8, h: 1.85, fontSize: 13.5, color: C.charcoal, fontFace: "Calibri", valign: "middle", align: "center" });
// Arrow (except last in each row)
if (col < 2) {
s.addShape(pres.ShapeType.rect, { x: x + 4.0, y: y + 1.1, w: 0.28, h: 0.12, fill: { color: C.teal } });
s.addText("▶", { x: x + 4.1, y: y + 0.9, w: 0.25, h: 0.45, fontSize: 14, color: C.teal, fontFace: "Calibri", align: "center" });
}
});
s.addText("Key data (Cordocentesis, Creasy & Resnik Table 14.9): FGR fetuses show PO₂ ~12 torr below normal, O₂ sat ~50% vs 81%, pH ~7.33", {
x: 0.25, y: 6.85, w: 12.8, h: 0.4, fontSize: 11, color: C.muted, fontFace: "Calibri", italic: true
});
}
// ─────────────────────────────────────────────────────────────────────────────
// SLIDE 8 – SYMMETRIC vs ASYMMETRIC
// ─────────────────────────────────────────────────────────────────────────────
{
const s = pres.addSlide();
lightSlide(s);
headerBar(s, "Classification: Symmetric vs Asymmetric FGR", "Robbins Basic Pathology");
twoCol(s,
"SYMMETRIC FGR (~20–30%)",
[
"All fetal organs equally reduced in size",
"Head circumference, abdominal circumference, femur length ALL proportionally small",
"Head Circumference : Abdominal Circumference ratio = NORMAL",
"Caused by intrinsic fetal factors (chromosomal, genetic, TORCH infections)",
"Insult occurs EARLY in gestation — 1st trimester",
"PONDERAL INDEX: normal",
"Fewer brain-sparing features",
"Prognosis related to underlying cause (e.g., aneuploidy carries poor prognosis)",
],
"ASYMMETRIC FGR (~70–80%)",
[
"Selective reduction of abdominal circumference (liver glycogen depleted)",
"Head circumference RELATIVELY SPARED — 'brain sparing'",
"HC:AC ratio INCREASED",
"Caused by placental insufficiency or maternal vascular disease",
"Insult occurs LATE in gestation — 2nd–3rd trimester",
"PONDERAL INDEX: reduced (thin, long fetus)",
"Characteristic features: skin folds, depleted subcutaneous fat",
"Better prognosis if placental cause identified and managed",
],
{ lc: C.teal, rc: C.orange }
);
}
// ─────────────────────────────────────────────────────────────────────────────
// SLIDE 9 – CUSTOMISED GROWTH CURVES
// ─────────────────────────────────────────────────────────────────────────────
{
const s = pres.addSlide();
lightSlide(s);
headerBar(s, "Growth Curves: Population-Based vs Customised", "Creasy & Resnik 9e, Chapter 44");
infoBox(s, 0.2, 1.15, 6.1, 2.75,
"Population-Based Curves (Traditional)",
"• Based on all births in a population\n• Define SGA as <10th percentile statistically\n• First described by Lubchenco et al. (1960s)\n• Do NOT account for physiological variables\n• Up to 70% of 'SGA' infants may be constitutionally normal\n• Updated US data (1998–2006): >391,000 infants from 33 states",
C.teal);
infoBox(s, 6.8, 1.15, 6.1, 2.75,
"Customised Growth Curves",
"• Accounts for: maternal race, height, pre-pregnancy weight, parity, fetal sex\n• Prospectively defines each fetus's growth POTENTIAL\n• Identifies IUGR even when birth weight > 10th percentile\n• Detects true FGR missed by population curves\n• Preferred by many European centres and ACOG guidelines\n• GROW software (Gardosi) widely used",
C.orange);
infoBox(s, 0.2, 4.05, 12.7, 2.75,
"The Concept of Fetal Growth Potential",
"FGR is best defined as a fetus that does NOT achieve its growth potential.\n\nConsequences of misclassification:\n• False-positive SGA label → unnecessary interventions, maternal anxiety\n• False-negative (missed FGR above 10th %ile) → untreated placental insufficiency → stillbirth\n\nACOG favours EFW or abdominal circumference <10th percentile on ultrasound to diagnose FGR.\nHowever, evidence suggests most adverse outcomes occur below 5th or 3rd percentile.",
C.navy);
}
// ─────────────────────────────────────────────────────────────────────────────
// SLIDE 10 – STAGING / CLASSIFICATION SYSTEM
// ─────────────────────────────────────────────────────────────────────────────
{
const s = pres.addSlide();
lightSlide(s);
headerBar(s, "Staging System for FGR (Doppler-Based)", "Creasy & Resnik 9e, Table 44.1 — Mari et al. 2007");
s.addText("FGR is not a homogeneous entity — staging helps guide clinical management and research communication", {
x: 0.25, y: 1.1, w: 12.8, h: 0.4, fontSize: 14, color: C.muted, fontFace: "Calibri", italic: true
});
const stages = [
{ stage: "Stage I", clr: C.green, ua: "Abnormal (↑ PI)", mca: "Normal", dv: "Normal", outcome: "Mild FGR — close monitoring" },
{ stage: "Stage II", clr: C.teal, ua: "Absent EDF", mca: "Normal or abnormal", dv: "Normal", outcome: "Moderate FGR — increased surveillance" },
{ stage: "Stage III", clr: C.orange, ua: "Reversed EDF", mca: "↓ PI (centralisation)", dv: "Abnormal PI", outcome: "Severe FGR — consider delivery" },
{ stage: "Stage IV", clr: "#B22222",ua: "Reversed EDF", mca: "Abnormal", dv: "Absent/reversed A-wave", outcome: "Critical FGR — delivery indicated" },
];
// Table header
["Stage", "Umbilical Artery", "MCA Doppler", "Ductus Venosus", "Clinical Action"].forEach((h, i) => {
const xs = [0.2, 1.7, 4.0, 6.5, 9.0, 11.5];
const ws = [1.4, 2.3, 2.5, 2.4, 2.4];
s.addShape(pres.ShapeType.rect, { x: xs[i], y: 1.6, w: ws[i], h: 0.5, fill: { color: C.navy } });
s.addText(h, { x: xs[i] + 0.05, y: 1.62, w: ws[i] - 0.1, h: 0.46, fontSize: 13, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
});
stages.forEach(({ stage, clr, ua, mca, dv, outcome }, ri) => {
const y = 2.18 + ri * 1.1;
const row = [stage, ua, mca, dv, outcome];
const xs = [0.2, 1.7, 4.0, 6.5, 9.0];
const ws = [1.4, 2.3, 2.5, 2.4, 4.1];
row.forEach((val, ci) => {
const fill = ci === 0 ? clr : (ri % 2 === 0 ? "F0F8FF" : C.white);
const textClr = ci === 0 ? C.white : C.charcoal;
s.addShape(pres.ShapeType.rect, { x: xs[ci], y, w: ws[ci], h: 0.95, fill: { color: fill }, line: { color: "CCCCCC", pt: 0.5 } });
s.addText(val, { x: xs[ci] + 0.05, y: y + 0.05, w: ws[ci] - 0.1, h: 0.85, fontSize: 13, color: textClr, fontFace: "Calibri", align: ci === 0 ? "center" : "left", valign: "middle", bold: ci === 0 });
});
});
s.addText("EDF = End-Diastolic Flow | MCA = Middle Cerebral Artery | DV = Ductus Venosus | PI = Pulsatility Index", {
x: 0.25, y: 6.7, w: 12.8, h: 0.35, fontSize: 10, color: C.muted, fontFace: "Calibri", italic: true
});
}
// ─────────────────────────────────────────────────────────────────────────────
// SLIDE 11 – SCREENING & ULTRASOUND DIAGNOSIS
// ─────────────────────────────────────────────────────────────────────────────
{
const s = pres.addSlide();
lightSlide(s);
headerBar(s, "Diagnosis: Screening & Ultrasound Biometry", "Creasy & Resnik 9e | ACOG Guidelines");
bullets(s, [
"ACOG criteria: EFW or Abdominal Circumference (AC) < 10th percentile on ultrasound",
"Key biometric parameters: BPD · Head Circumference (HC) · Abdominal Circumference (AC) · Femur Length (FL) · EFW",
"AC is the MOST SENSITIVE single parameter for FGR — reflects glycogen depletion in fetal liver",
"HC:AC ratio: increased in asymmetric FGR (>1.0 after 36 weeks suggests FGR)",
"Serial ultrasound: measure growth velocity every 2–4 weeks — a deceleration in growth trajectory is more significant than a single measurement",
"Amniotic fluid assessment: oligohydramnios (AFI < 5 cm or MVP < 2 cm) suggests uteroplacental insufficiency",
"Uterine artery Doppler at 20–24 weeks: ↑ PI + notching = high risk for placental dysfunction, preeclampsia, FGR",
"Early-onset FGR (<32 weeks): more severe, usually placental — associated with preeclampsia",
"Late-onset FGR (≥34 weeks): less severe Doppler changes, cerebral redistribution may be the only finding",
], { y: 1.15, sz: 16 });
}
// ─────────────────────────────────────────────────────────────────────────────
// SLIDE 12 – DOPPLER SURVEILLANCE
// ─────────────────────────────────────────────────────────────────────────────
{
const s = pres.addSlide();
lightSlide(s);
headerBar(s, "Doppler Velocimetry in FGR Surveillance", "Creasy & Resnik 9e, Chapter 32 — Fetal Doppler Velocimetry");
const boxes = [
{ t: "Umbilical Artery (UA)", c: C.navy,
b: "• Reflects PLACENTAL vascular resistance\n• Normal: ↑ diastolic flow as gestation advances (↓ PI)\n• Placental mosaicism or infarction → pruning of arterial tree → ↑ PI\n• AEDV (Absent End-Diastolic Velocity): critical finding\n• REDV (Reversed End-Diastolic Velocity): worse — near-certain fetal compromise\n• AEDV/REDV at late preterm/term = indication for delivery (Creasy §32)" },
{ t: "Middle Cerebral Artery (MCA)", c: C.teal,
b: "• Reflects CEREBRAL vascular resistance\n• Brain sparing: cerebral vasodilatation → ↓ MCA PI\n• Cerebro-placental ratio (CPR) = MCA PI / UA PI\n• Low CPR: adverse outcome even when UA Doppler is normal\n• Most useful in LATE-ONSET FGR where UA may be normal" },
{ t: "Ductus Venosus (DV)", c: C.orange,
b: "• Reflects CARDIAC preload and venous pressure\n• Absent or reversed A-wave: imminent fetal decompensation\n• TRUFFLE trial: DV abnormality used to time delivery in very preterm FGR\n• DV abnormality precedes biophysical and CTG changes by days\n• Highest level of evidence for delivery timing in early-onset FGR" },
{ t: "Uterine Artery", c: C.green,
b: "• Reflects UTEROPLACENTAL blood flow\n• Abnormal: ↑ PI + early diastolic notching at 20–24 wks\n• High sensitivity for predicting preeclampsia + FGR\n• Used as screening tool in first/second trimester combined screening\n• Normal uterine artery does NOT exclude late-onset FGR" },
];
boxes.forEach(({ t, c, b }, i) => {
const col = i % 2;
const row = Math.floor(i / 2);
const x = 0.2 + col * 6.6;
const y = 1.15 + row * 3.0;
s.addShape(pres.ShapeType.rect, { x, y, w: 6.2, h: 2.75, fill: { color: C.white }, line: { color: c, pt: 1.5 } });
s.addShape(pres.ShapeType.rect, { x, y, w: 6.2, h: 0.48, fill: { color: c } });
s.addText(t, { x: x + 0.08, y: y + 0.04, w: 6.0, h: 0.4, fontSize: 14, bold: true, color: C.white, fontFace: "Calibri" });
s.addText(b, { x: x + 0.1, y: y + 0.54, w: 6.0, h: 2.1, fontSize: 12.5, color: C.charcoal, fontFace: "Calibri", valign: "top" });
});
}
// ─────────────────────────────────────────────────────────────────────────────
// SLIDE 13 – BIOPHYSICAL MONITORING
// ─────────────────────────────────────────────────────────────────────────────
{
const s = pres.addSlide();
lightSlide(s);
headerBar(s, "Biophysical Profile & CTG Monitoring", "Creasy & Resnik 9e");
s.addShape(pres.ShapeType.rect, { x: 0.2, y: 1.12, w: 12.8, h: 5.75, fill: { color: C.white }, line: { color: "DDDDDD" } });
s.addText("Biophysical Profile (BPP) — Manning Score", {
x: 0.3, y: 1.2, w: 8, h: 0.45, fontSize: 16, bold: true, color: C.navy, fontFace: "Calibri"
});
const bppItems = [
["Non-stress test (NST)", "≥2 accelerations in 20 min (2 points)"],
["Fetal breathing movements", "≥1 episode ≥30 sec in 30 min (2 points)"],
["Fetal body movements", "≥3 discrete movements in 30 min (2 points)"],
["Fetal tone", "≥1 extension + return to flexion (2 points)"],
["Amniotic fluid volume", "AFI ≥5 cm or MVP ≥2 cm (2 points)"],
];
bppItems.forEach(([param, score], i) => {
const y = 1.75 + i * 0.68;
s.addShape(pres.ShapeType.rect, { x: 0.25, y, w: 5.5, h: 0.58, fill: { color: i % 2 === 0 ? "EAF4FC" : C.white }, line: { color: "DDDDDD", pt: 0.5 } });
s.addText(param, { x: 0.3, y: y + 0.07, w: 3.0, h: 0.44, fontSize: 13, bold: true, color: C.navy, fontFace: "Calibri" });
s.addText(score, { x: 3.35, y: y + 0.07, w: 2.4, h: 0.44, fontSize: 12, color: C.charcoal, fontFace: "Calibri" });
});
const interpretations = [
{ score: "8–10 / 10", meaning: "Normal — reassuring", action: "Routine care", clr: C.green },
{ score: "6 / 10", meaning: "Equivocal", action: "Repeat in 6 h / consider delivery if ≥36 wk", clr: C.orange },
{ score: "4 / 10", meaning: "Abnormal", action: "Deliver if ≥34 wk; consider if <34 wk", clr: "#B22222" },
{ score: "0–2 / 10", meaning: "Severely abnormal", action: "Deliver regardless of gestational age", clr: "#7B0000" },
];
s.addText("BPP Interpretation & Action", {
x: 6.1, y: 1.2, w: 6.8, h: 0.45, fontSize: 16, bold: true, color: C.navy, fontFace: "Calibri"
});
interpretations.forEach(({ score, meaning, action, clr }, i) => {
const y = 1.75 + i * 0.9;
s.addShape(pres.ShapeType.rect, { x: 6.1, y, w: 1.4, h: 0.7, fill: { color: clr } });
s.addText(score, { x: 6.1, y, w: 1.4, h: 0.7, fontSize: 13, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
s.addShape(pres.ShapeType.rect, { x: 7.55, y, w: 5.3, h: 0.7, fill: { color: "F8F8F8" }, line: { color: "DDDDDD" } });
s.addText(`${meaning}\n→ ${action}`, { x: 7.6, y: y + 0.04, w: 5.2, h: 0.62, fontSize: 12.5, color: C.charcoal, fontFace: "Calibri", valign: "middle" });
});
bullets(s, [
"CTG: in FGR, loss of FHR variability and late decelerations are ominous signs",
"Computerised CTG (short-term variation <3 ms) — used in TRUFFLE trial for early-onset severe FGR",
"BPP + Doppler together reduce perinatal mortality compared to NST alone (Cochrane review)",
], { y: 5.65, sz: 13.5, clr: C.charcoal });
}
// ─────────────────────────────────────────────────────────────────────────────
// SLIDE 14 – PERINATAL OUTCOMES
// ─────────────────────────────────────────────────────────────────────────────
{
const s = pres.addSlide();
darkSlide(s);
s.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 13.3, h: 1.0, fill: { color: C.orange } });
s.addText("Perinatal Outcomes & Mortality Risk", {
x: 0.3, y: 0.1, w: 12.7, h: 0.75, fontSize: 28, bold: true, color: C.white, fontFace: "Calibri"
});
s.addText("Manning 1995 | Creasy & Resnik 9e, Figs 44.3–44.4 | US Birth Cohort 2005 (n=3,399,816)", {
x: 0.3, y: 0.77, w: 12.7, h: 0.28, fontSize: 11, color: "FFDDAA", fontFace: "Calibri", italic: true
});
bullets(s, [
"FGR associated with ↑ fetal and neonatal mortality and morbidity at EVERY gestational age",
"Perinatal mortality increases EXPONENTIALLY when birth weight < 6th percentile (Manning's classic series of 1560 SGA fetuses)",
"Risk of IUFD (stillbirth) analysed in 3.4 million non-anomalous singletons (24–42 wks, US 2005): risk rises sharply below 5th percentile",
"Early-onset FGR (<32 wks): highest mortality risk, especially when associated with preeclampsia",
"FGR + congenital anomalies: even higher perinatal mortality",
], { y: 1.1, sz: 17, clr: C.white });
const outcomes = [
{ label: "Hypoglycaemia", clr: C.aqua },
{ label: "Hypothermia", clr: C.pink },
{ label: "Hypocalcaemia", clr: C.lemon },
{ label: "Polycythaemia", clr: C.orange },
{ label: "Necrotising\nEnterocolitis", clr: C.teal },
{ label: "Intraventricular\nHaemorrhage", clr: "#E04040" },
{ label: "Pulmonary\nHypertension", clr: C.green },
{ label: "Cerebral\nPalsy", clr: "#9B59B6" },
];
s.addText("Immediate neonatal complications of FGR / SGA:", {
x: 0.3, y: 3.7, w: 12.7, h: 0.4, fontSize: 15, bold: true, color: C.aqua, fontFace: "Calibri"
});
outcomes.forEach(({ label, clr }, i) => {
const x = 0.2 + i * 1.6;
s.addShape(pres.ShapeType.rect, { x, y: 4.18, w: 1.45, h: 1.6, fill: { color: "1A2A40" }, line: { color: clr, pt: 2 } });
s.addShape(pres.ShapeType.oval, { x: x + 0.5, y: 4.22, w: 0.45, h: 0.45, fill: { color: clr } });
s.addText(label, { x, y: 4.72, w: 1.45, h: 1.0, fontSize: 12, color: C.white, fontFace: "Calibri", align: "center", valign: "top" });
});
}
// ─────────────────────────────────────────────────────────────────────────────
// SLIDE 15 – MANAGEMENT PRINCIPLES
// ─────────────────────────────────────────────────────────────────────────────
{
const s = pres.addSlide();
lightSlide(s);
headerBar(s, "Management of FGR — Principles & Overview", "Creasy & Resnik 9e | ACOG Practice Bulletin");
s.addText("No antenatal treatment has been proven to reverse FGR — management focuses on surveillance, optimising timing of delivery, and preventing stillbirth", {
x: 0.25, y: 1.12, w: 12.8, h: 0.45, fontSize: 14, color: C.orange, fontFace: "Calibri", italic: true, bold: true
});
const cols = [
{
title: "ANTENATAL CARE", clr: C.teal,
items: [
"Confirm gestational age accurately",
"Identify and treat underlying cause",
"Serial ultrasound every 2–4 weeks",
"Doppler velocimetry (UA, MCA, DV) as per staging",
"Assess amniotic fluid (AFI / MVP)",
"Corticosteroids (betamethasone) if delivery between 24–34 weeks",
"Magnesium sulphate for neuroprotection <32 weeks",
"Low-dose aspirin from 12–16 weeks if high risk (uterine artery ↑ PI)",
"Correct maternal factors: stop smoking, optimise nutrition, BP control",
]
},
{
title: "MANAGEMENT REMOTE FROM TERM", clr: C.navy,
items: [
"Most challenging — requires individualised decision-making",
"Combined: Doppler + BPP + AFV + clinical judgement",
"If AEDV present: intensive surveillance q2–3 days",
"If REDV or DV A-wave abnormal: delivery usually indicated",
"Aim for ≥34 weeks gestation if possible",
"Balance risk of prematurity vs risk of intrauterine death",
"Best outcomes in specialised feto-maternal medicine centres",
]
},
];
cols.forEach(({ title, clr, items }, ci) => {
const x = 0.2 + ci * 6.6;
s.addShape(pres.ShapeType.rect, { x, y: 1.65, w: 6.2, h: 5.5, fill: { color: C.white }, line: { color: clr, pt: 1.5 } });
s.addShape(pres.ShapeType.rect, { x, y: 1.65, w: 6.2, h: 0.52, fill: { color: clr } });
s.addText(title, { x: x + 0.08, y: 1.67, w: 6.0, h: 0.46, fontSize: 14, bold: true, color: C.white, fontFace: "Calibri", align: "center" });
const ri = items.map((t, i) => ({ text: t, options: { bullet: { code: "25B8", color: clr }, breakLine: i < items.length - 1, fontSize: 14, color: C.charcoal, fontFace: "Calibri", paraSpaceBefore: 3 } }));
s.addText(ri, { x: x + 0.12, y: 2.22, w: 5.95, h: 4.8, valign: "top" });
});
}
// ─────────────────────────────────────────────────────────────────────────────
// SLIDE 16 – TIMING OF DELIVERY
// ─────────────────────────────────────────────────────────────────────────────
{
const s = pres.addSlide();
lightSlide(s);
headerBar(s, "Timing of Delivery in FGR", "Creasy & Resnik 9e | GRIT Study | TRUFFLE Trial");
const rows = [
{ ga: "Term (≥37 wks)\nAny FGR", trigger: "Confirmed FGR with any Doppler abnormality or growth cessation", action: "Deliver — no benefit in prolonging", clr: "#B22222" },
{ ga: "34–37 wks\nIdiopathic FGR", trigger: "After 34 weeks, provider-initiated PTB is indicated to avoid stillbirth (Creasy)", action: "Deliver at 34–37 weeks", clr: C.orange },
{ ga: "34+ wks\nAEDV", trigger: "Absent end-diastolic flow — AEDV in late preterm / term", action: "Appropriate indication for delivery (Creasy §32)", clr: C.orange },
{ ga: "<34 wks\nSevere FGR", trigger: "REDV + ↑ DV PI or absent/reversed A-wave (TRUFFLE criteria)", action: "Deliver after corticosteroids ± MgSO₄", clr: C.teal },
{ ga: "<32 wks\nSevere FGR", trigger: "Severe FGR: combined Doppler + BPP + CTG (cCTG STV)", action: "Individualised; tertiary centre; TRUFFLE guidance", clr: C.navy },
{ ga: "Preeclampsia\n+ FGR", trigger: "Maternal status (BP, labs) often drives delivery timing", action: "Deliver according to PE guidelines; FGR adds urgency", clr: C.pink },
];
["GA / Context", "Delivery Trigger", "Recommended Action"].forEach((h, i) => {
const xs = [0.2, 2.9, 8.1]; const ws = [2.6, 5.1, 5.0];
s.addShape(pres.ShapeType.rect, { x: xs[i], y: 1.1, w: ws[i], h: 0.52, fill: { color: C.navy } });
s.addText(h, { x: xs[i] + 0.05, y: 1.12, w: ws[i] - 0.1, h: 0.48, fontSize: 13, bold: true, color: C.white, fontFace: "Calibri", align: "center", valign: "middle" });
});
rows.forEach(({ ga, trigger, action, clr }, ri) => {
const y = 1.7 + ri * 0.93;
const vals = [ga, trigger, action];
const xs = [0.2, 2.9, 8.1]; const ws = [2.6, 5.1, 5.0];
vals.forEach((val, ci) => {
const fill = ci === 0 ? clr : (ri % 2 === 0 ? "F2F6FA" : C.white);
const tc = ci === 0 ? C.white : C.charcoal;
s.addShape(pres.ShapeType.rect, { x: xs[ci], y, w: ws[ci], h: 0.84, fill: { color: fill }, line: { color: "CCCCCC", pt: 0.5 } });
s.addText(val, { x: xs[ci] + 0.06, y: y + 0.05, w: ws[ci] - 0.12, h: 0.74, fontSize: 12.5, color: tc, fontFace: "Calibri", valign: "middle", bold: ci === 0, align: ci === 0 ? "center" : "left" });
});
});
}
// ─────────────────────────────────────────────────────────────────────────────
// SLIDE 17 – NEONATAL COMPLICATIONS
// ─────────────────────────────────────────────────────────────────────────────
{
const s = pres.addSlide();
lightSlide(s);
headerBar(s, "Neonatal Complications of SGA / FGR", "Robbins Basic Pathology | Creasy & Resnik 9e");
bullets(s, [
"HYPOGLYCAEMIA — depleted glycogen stores; neonates at greatest risk if preterm or SGA (Miller's Anaesthesia). Monitor blood glucose from birth",
"HYPOTHERMIA — reduced subcutaneous fat, limited brown fat thermogenesis; aggressive thermal management needed",
"POLYCYTHAEMIA — compensatory erythropoiesis due to chronic hypoxia; viscous blood → thrombosis risk",
"HYPOCALCAEMIA — especially in preterm SGA; early neonatal hypocalcaemia (first 72 h)",
"THROMBOCYTOPENIA — associated with severe placental dysfunction and preeclampsia",
"PULMONARY HYPERTENSION — from in utero hypoxia and polycythaemia; right-to-left shunting after birth",
"NECROTISING ENTEROCOLITIS (NEC) — gut ischaemia from redistributed fetal circulation",
"INTRAVENTRICULAR HAEMORRHAGE (IVH) — preterm SGA at highest risk; grades III–IV carry neurodevelopmental sequelae",
"MECONIUM ASPIRATION SYNDROME — chronic hypoxia → passage of meconium in utero",
"POOR THERMOREGULATION + FEEDING DIFFICULTIES — prolonged NICU stay usual in severe FGR",
], { y: 1.12, sz: 15.5 });
}
// ─────────────────────────────────────────────────────────────────────────────
// SLIDE 18 – LONG-TERM SEQUELAE / BARKER HYPOTHESIS
// ─────────────────────────────────────────────────────────────────────────────
{
const s = pres.addSlide();
darkSlide(s);
s.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 13.3, h: 1.0, fill: { color: "#7B2D8B" } });
s.addText("Long-Term Sequelae: The Barker / DOHaD Hypothesis", {
x: 0.3, y: 0.1, w: 12.7, h: 0.75, fontSize: 26, bold: true, color: C.white, fontFace: "Calibri"
});
s.addText("Developmental Origins of Health and Disease — Robbins Basic Pathology | Brenner & Rector's Kidney", {
x: 0.3, y: 0.77, w: 12.7, h: 0.28, fontSize: 11, color: "DDB0FF", fontFace: "Calibri", italic: true
});
bullets(s, [
"SGA / FGR infants are NOT just 'small at birth' — deficits persist into childhood and adult life (Robbins)",
"BARKER HYPOTHESIS (Developmental Origins of Health and Disease — DOHaD): poor fetal nutrition 'programmes' metabolic and cardiovascular physiology permanently",
"Adults born SGA have ↑ risk: hypertension · coronary artery disease · type 2 diabetes · insulin resistance · obesity (central adiposity)",
"RENAL PROGRAMMING (Brenner & Rector): SGA infants have ↓ nephron number → compensatory glomerular hypertrophy → early CKD risk in later life",
"Risk of CKD rises with combined prematurity + SGA — RR 4.03 (95% CI 2.08–7.80) for preterm SGA vs. term AGA (Brenner & Rector)",
"NEURODEVELOPMENTAL: ↑ risk of cognitive impairment, attention deficit, cerebral palsy especially in severe early-onset FGR",
"CATCH-UP GROWTH: rapid postnatal weight gain in SGA paradoxically ↑ metabolic syndrome risk — 'thrifty phenotype' cannot handle nutritional excess",
"Long-term follow-up of FGR children should include BP monitoring, metabolic screening, and developmental assessment",
], { y: 1.05, sz: 16, clr: C.white });
}
// ─────────────────────────────────────────────────────────────────────────────
// SLIDE 19 – MASTER COMPARISON TABLE
// ─────────────────────────────────────────────────────────────────────────────
{
const s = pres.addSlide();
lightSlide(s);
headerBar(s, "Summary Comparison: SGA vs FGR", "Comprehensive Reference Table");
const rows = [
["Parameter", "SGA", "FGR"],
["Definition", "Birth weight < 10th percentile", "Fetus failing to reach growth POTENTIAL"],
["Applied to", "NEWBORN (postnatal)", "FETUS (antenatal)"],
["Statistical vs Biological","Statistical label", "Pathophysiological process"],
["Implies pathology?", "NOT necessarily", "YES — by definition implies disease"],
["% of population", "~10% (by definition)", "~4–8% (developed) / 6–30% (developing)"],
["Growth curve used", "Population-based", "Customised preferred"],
["Aetiology", "Constitutional (most common) or FGR", "Placental, maternal, fetal factors"],
["Types", "Symmetric / Asymmetric", "Symmetric / Asymmetric"],
["Key investigations", "Birth weight centile, Ponderal Index", "Serial US, Doppler (UA, MCA, DV), BPP"],
["Doppler role", "Not applicable (postnatal label)", "Central to staging and delivery timing"],
["Perinatal risk", "↑ if <5th–3rd %ile", "↑ independent of percentile"],
["Long-term risk", "Barker hypothesis applies if FGR", "CV disease, DM, CKD, neurodevelopment"],
["Management", "Neonatal monitoring, feeding support", "Surveillance, timed delivery, steroids"],
];
rows.forEach((row, ri) => {
const y = 1.05 + ri * 0.41;
const xs = [0.18, 3.6, 8.0]; const ws = [3.35, 4.35, 5.1];
row.forEach((val, ci) => {
let fill;
if (ri === 0) fill = C.navy;
else if (ci === 0) fill = C.teal;
else if (ri % 2 === 1) fill = "EAF6EE";
else fill = C.white;
const tc = (ri === 0 || ci === 0) ? C.white : C.charcoal;
s.addShape(pres.ShapeType.rect, { x: xs[ci], y, w: ws[ci], h: 0.38, fill: { color: fill }, line: { color: "CCCCCC", pt: 0.5 } });
s.addText(val, { x: xs[ci] + 0.05, y: y + 0.02, w: ws[ci] - 0.1, h: 0.34, fontSize: 11.5, color: tc, fontFace: "Calibri", valign: "middle", bold: ri === 0 || ci === 0 });
});
});
}
// ─────────────────────────────────────────────────────────────────────────────
// SLIDE 20 – TAKE-HOME MESSAGES
// ─────────────────────────────────────────────────────────────────────────────
{
const s = pres.addSlide();
darkSlide(s);
s.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 13.3, h: 1.05, fill: { color: C.teal } });
s.addShape(pres.ShapeType.rect, { x: 0, y: 6.5, w: 13.3, h: 1.0, fill: { color: C.teal } });
s.addShape(pres.ShapeType.rect, { x: 0, y: 0, w: 0.45, h: 7.5, fill: { color: C.aqua } });
s.addText("Key Take-Home Messages", {
x: 0.6, y: 0.15, w: 12.6, h: 0.72, fontSize: 30, bold: true, color: C.white, fontFace: "Calibri", charSpacing: 1
});
const msgs = [
{ n: "1", txt: "SGA and FGR are NOT synonymous — SGA is a statistical label for the newborn; FGR is a pathological diagnosis for the fetus in utero", clr: C.aqua },
{ n: "2", txt: "FGR is best defined as a fetus failing to achieve its growth POTENTIAL — 60% of cases have no identifiable cause", clr: C.lemon },
{ n: "3", txt: "Placental insufficiency is the most common cause — reflected by progressive Doppler changes: ↑ UA PI → AEDV → REDV → DV abnormality", clr: C.orange },
{ n: "4", txt: "Symmetric FGR = early insult (chromosomal, TORCH); Asymmetric FGR = late placental/maternal insult — brain-sparing maintains HC", clr: C.pink },
{ n: "5", txt: "Management: no treatment reverses FGR — goal is timely delivery before stillbirth, using Doppler staging + BPP + clinical gestational age assessment", clr: C.aqua },
{ n: "6", txt: "Long-term: FGR survivors carry lifelong risk of hypertension, type 2 DM, CKD, and neurodevelopmental impairment (Barker / DOHaD hypothesis)", clr: C.lemon },
];
msgs.forEach(({ n, txt, clr }, i) => {
const y = 1.2 + i * 0.87;
s.addShape(pres.ShapeType.oval, { x: 0.55, y: y + 0.12, w: 0.58, h: 0.58, fill: { color: clr } });
s.addText(n, { x: 0.55, y: y + 0.12, w: 0.58, h: 0.58, fontSize: 16, bold: true, color: C.navy, fontFace: "Calibri", align: "center", valign: "middle" });
s.addText(txt, { x: 1.25, y: y + 0.1, w: 11.8, h: 0.65, fontSize: 15, color: C.white, fontFace: "Calibri", valign: "middle" });
});
s.addText("References: Creasy & Resnik's Maternal-Fetal Medicine 9e · Robbins Basic Pathology · Brenner & Rector's Kidney · Miller's Anaesthesia", {
x: 0.55, y: 6.58, w: 12.7, h: 0.35, fontSize: 9.5, color: C.navy, fontFace: "Calibri", bold: true
});
}
// ─────────────────────────────────────────────────────────────────────────────
// WRITE FILE
// ─────────────────────────────────────────────────────────────────────────────
pres.writeFile({ fileName: "/home/daytona/workspace/sga-fgr-ppt/SGA_vs_FGR.pptx" })
.then(() => console.log("SUCCESS: SGA_vs_FGR.pptx written"))
.catch(e => { console.error("ERROR:", e); process.exit(1); });
cd /home/daytona/workspace/sga-fgr-ppt && node build.js 2>&1
node -e "const p = require('pptxgenjs'); const pp = new p(); console.log(JSON.stringify(Object.keys(pp.ShapeType).slice(0,15)));" 2>&1
node -e "const p = require('pptxgenjs'); const pp = new p(); const keys = Object.keys(pp.ShapeType); console.log(keys.filter(k => /rect|oval|ellip/i.test(k)));" 2>&1
sed -i 's/pres\.ShapeType\.rect/"rect"/g; s/pres\.ShapeType\.oval/"ellipse"/g' /home/daytona/workspace/sga-fgr-ppt/build.js && echo "done"
python3 -c " import re with open('/home/daytona/workspace/sga-fgr-ppt/build.js', 'r') as f: content = f.read() content = content.replace('pres.ShapeType.rect', '\"rect\"') content = content.replace('pres.ShapeType.oval', '\"ellipse\"') with open('/home/daytona/workspace/sga-fgr-ppt/build.js', 'w') as f: f.write(content) print('done', content.count('ShapeType')) "
cd /home/daytona/workspace/sga-fgr-ppt && node build.js 2>&1
ls -lh /home/daytona/workspace/sga-fgr-ppt/SGA_vs_FGR.pptx && python3 -c " import zipfile, os path = '/home/daytona/workspace/sga-fgr-ppt/SGA_vs_FGR.pptx' z = zipfile.ZipFile(path) slides = [n for n in z.namelist() if n.startswith('ppt/slides/slide') and n.endswith('.xml')] print(f'Slides: {len(slides)} | Valid ZIP: YES | Size: {os.path.getsize(path)/1024:.0f} KB') "
SGA vs FGR
Presentation · PPTX
| Slide | Title | Design |
|---|---|---|
| 1 | Title Slide | Dark navy + teal banner |
| 2 | Overview / Outline | Numbered module cards |
| 3 | Historical Context | Timeline with colour-coded milestones (Lubchenco 1960s → present) |
| 4 | Definitions: SGA vs FGR | Two-column orange vs green comparison |
| 5 | Incidence & Epidemiology | Dark slide with stat highlight boxes |
| 6 | Aetiology & Risk Factors | Three-column: Maternal / Fetal / Placental |
| 7 | Pathophysiology | 6-step flow: placental mass ↓ → O₂ ↓ → brain sparing |
| 8 | Symmetric vs Asymmetric FGR | Side-by-side comparison |
| 9 | Population vs Customised Growth Curves | Info-box layout with Gardosi/GROW concept |
| 10 | Doppler Staging System | 4-stage table (Mari 2007 / Table 44.1) |
| 11 | Ultrasound Diagnosis & Biometry | Bullet list: AC, EFW, uterine artery Doppler |
| 12 | Doppler Velocimetry | 4 vessels: UA, MCA, DV, Uterine artery |
| 13 | Biophysical Profile & CTG | Manning score table + interpretation |
| 14 | Perinatal Outcomes | Dark slide with neonatal complication icons |
| 15 | Management Principles | Two-column: Antenatal care + Remote from term |
| 16 | Timing of Delivery | Decision table by GA and Doppler findings |
| 17 | Neonatal Complications | Detailed bullet list |
| 18 | Barker / DOHaD Hypothesis | Dark purple slide: long-term CV, DM, CKD, neuro risks |
| 19 | Master Comparison Table | 14-row SGA vs FGR reference table |
| 20 | Key Take-Home Messages | 6 numbered messages on dark background |