INDUCTION OF LABOUR. When and why and methods to use
"induction of labor" indications methods
induction of labour methods oxytocin misoprostol cervical ripening Bishop score

This diagnostic image is a transvaginal ultrasound in a sagittal plane focusing on the cervix during a gynecological/obstetric evaluation. The grayscale sonogram displays the anatomical structures of the cervix, including the hypoechoic (dark) cervical canal and the internal os. A linear measurement is performed across the internal cervical os, indicated by a green dotted line with calipers. The ultrasound software overlay shows a measurement value of 'L 2.27 cm', representing the diameter of the internal os opening. This measurement is clinically significant for assessing cervical ripening or the progress of labor induction, often used in conjunction with the Bishop score to predict successful cervical maturation. The anatomical orientation shows the superior uterine cavity transitioning into the cervical canal toward the lower external os. The image serves as an educational example of sonographic cervical assessment in an obstetrical context.

Two sagittal pelvic ultrasound images demonstrate a Cook Cervical Ripening Balloon (CCRB) positioned within the lower uterine segment of a pregnant woman. Image A (Control Group) shows a roughly spherical, fluid-filled balloon with a measured diameter of 3.10 cm, corresponding to a standard 80 mL fill volume. The internal echogenicity is heterogeneous with somewhat irregular borders. Image B (Study Group) depicts the balloon after increasing the volume to approximately 120 mL, resulting in an elongated, larger structure with a measured diameter of 6.14 cm. In both images, the relationship between the mechanical balloon and the adjacent fetal presenting part is visible, illustrating how the device exerts pressure on the internal cervical os to promote cervical ripening and mechanical dilation. These images serve as educational materials for obstetric induction of labor protocols, specifically comparing traditional versus high-volume balloon dilation techniques to improve Bishop scores and successful vaginal delivery rates.

**Modality:** Magnetic Resonance Imaging (MRI) **Sequence:** Sagittal T2-weighted image **Anatomical Region:** Female pelvis, specifically focusing on the cervix and vagina. **Description:** The image demonstrates a mechanical cervical ripening device in situ. A double-balloon catheter is visible, characterized by two hyperintense (fluid-filled), spherical structures connected by a central catheter. * **Proximal/Internal Balloon:** Positioned superiorly within the lower uterine segment/internal cervical os, exerting pressure against the internal os (indicated by the arrowhead). * **Central Catheter:** Transverses the cervical canal (indicated by the thin arrow), showing the mechanical dilation of the cervix. * **Distal/External Balloon:** Positioned inferiorly within the proximal vagina, abutting the external cervical os (indicated by the thick arrow). **Clinical Context:** Findings are consistent with a Cook Cervical Ripening Balloon or similar dual-balloon catheter used for the mechanical induction of labor. The image provides high-contrast visualization of the device's placement relative to pelvic anatomy, confirming correct positioning with the cervix sandwiched between the two inflated balloons. Surroundings show the gravid uterus and adjacent pelvic structures including the bladder and rectum.
Induction is indicated if prolongation of pregnancy is dangerous for either the mother or the fetus and there are no contraindications to amniotomy or augmentation of uterine contractions. - Creasy & Resnik's MFM
| Factor | 0 | 1 | 2 | 3 |
|---|---|---|---|---|
| Dilation (cm) | 0 | 1-2 | 3-4 | 5-6 |
| Effacement (%) | 0-30 | 40-50 | 60-70 | 80 |
| Station | -3 | -2 | -1 or 0 | +1 or +2 |
| Consistency | Firm | Medium | Soft | - |
| Position | Posterior | Mid | Anterior | - |

| Method | Type | Use Case | Key Points |
|---|---|---|---|
| Misoprostol (PGE₁) | Pharmacological | Any gestation; unfavourable cervix | Cheap, oral/vaginal; caution with prior CS |
| Dinoprostone (PGE₂) | Pharmacological | Term; cervical ripening | Gel or insert; removable |
| Mifepristone + Misoprostol | Pharmacological | Mid-trimester, IUFD | RCOG/WHO protocol |
| Oxytocin IV | Pharmacological | Favourable cervix; augmentation | Titrated infusion; continuous CTG needed |
| Foley/Balloon catheter | Mechanical | Unfavourable cervix; prior CS | No systemic effects; safe in scarred uterus |
| Laminaria tents | Mechanical | Second trimester; cervical prep | Slow acting over hours |
| Amniotomy (ARM) | Surgical | Favourable cervix; adjunct to oxytocin | Cord prolapse risk |
| Membrane sweep | Preparatory | Pre/post-dates at term | Reduces formal IOL rates |
At what gestation is inducation indicated in different cases
ACOG SMFM guidelines gestational age induction labor indications 2024 postterm diabetes preeclampsia IUGR PROM
| Status | Gestational Age | Action |
|---|---|---|
| Late-term | 41+0 - 41+6 weeks | Begin antenatal surveillance; offer/consider induction |
| Postterm | ≥ 42+0 weeks | Induction recommended |
| Absolute cutoff | 42+6 weeks | Must deliver by this point |
"Induction of labor is typically recommended at or shortly after 41+0 weeks of gestation regardless of cervical status, because intervention at this time has been shown to reduce perinatal mortality without significantly increasing perinatal morbidity or cesarean delivery rates." - Creasy & Resnik's MFM
| Condition | Gestational Age | Action |
|---|---|---|
| Pre-eclampsia ≥37 weeks | ≥ 37+0 weeks | Deliver - HYPITAT trial showed maternal risk significantly reduced by delivery after 37 weeks without excess perinatal risk |
| Pre-eclampsia 34-37 weeks | 34-37 weeks | Individualise - consider planned delivery; reduces severe hypertension and maternal morbidity (trial shows 3/4 of expectantly managed women progress to severe PE); neonatal unit admissions higher but no excess respiratory morbidity |
| Severe features / HELLP / uncontrolled BP | Any gestation | Deliver regardless of gestation once stabilised (after steroids if <34 weeks) |
| Pre-eclampsia <34 weeks | <34 weeks | Expectant management with intensive monitoring if mother and fetus stable; give corticosteroids; deliver if deterioration |
| Pre-eclampsia <24 weeks | <24 weeks | Perinatal mortality >80%; termination usually recommended |
| Chronic hypertension (uncomplicated) | 38+0 - 38+6 weeks | Optimal delivery window (lowest perinatal morbidity); delivery at 36 weeks carries excess perinatal risk; delivery beyond 39 weeks increases pre-eclampsia risk |
| Condition | Gestational Age | Notes |
|---|---|---|
| Well-controlled GDM (diet only) | 40+0 - 41+0 weeks | Can await spontaneous labour; no earlier elective delivery needed |
| GDM requiring insulin/metformin, well-controlled | 38+0 - 39+0 weeks | Standard recommendation |
| Poorly controlled GDM / pre-gestational diabetes (Type 1 or 2), well-controlled | 38+0 - 39+0 weeks | ACOG/SMFM guidance |
| Pre-gestational diabetes, poorly controlled / with vascular disease | 36+0 - 37+6 weeks | Earlier delivery justified by risk of stillbirth |
| Any diabetic with fetal macrosomia, oligohydramnios, or deteriorating testing | As dictated by fetal status | Deliver promptly |
| Condition | Gestational Age | Action |
|---|---|---|
| PROM at term (≥37 weeks) | ≥ 37+0 weeks | Induction recommended - equivalent outcomes to expectant management but reduces chorioamnionitis risk; most guidelines recommend induction within 12-24 hours of rupture |
| PPROM 34-36+6 weeks | 34 - 36+6 weeks | Induction/delivery generally recommended (lung maturity sufficient; chorioamnionitis risk rises with time) |
| PPROM 32-33+6 weeks | 32 - 33+6 weeks | Individualise; corticosteroids; consider delivery if pulmonary maturity confirmed or infection develops |
| PPROM 24-31+6 weeks | 24 - 31+6 weeks | Expectant management with close monitoring; corticosteroids + magnesium sulphate (neuroprotection); deliver if infection, abruption, or fetal compromise |
| PPROM <24 weeks (previable) | <24 weeks | Counsel re. prognosis; expectant management or termination discussed; survival extremely poor |
| Severity | Gestational Age | Criteria |
|---|---|---|
| Mild FGR, normal Dopplers | 37+0 weeks | Deliver at term once maturity confirmed |
| FGR with abnormal umbilical artery (absent/reversed diastolic flow), 25-34 weeks | 34+0 weeks or earlier if fetal status deteriorates | Inpatient surveillance with daily antenatal testing |
| FGR with reversed UA flow, ductus venosus abnormal | 28-30 weeks (individualised) | Delivery may be necessary even at severe prematurity |
| FGR with reversed UA flow, >30 weeks | ≥ 30+0 weeks | Seriously consider delivery given rising risk of intrauterine death |
| UA reversed flow after 30 weeks | ≥ 30+0 weeks | Indication for delivery |
"Reversed UA flow following 30 weeks' gestation would be an indication for delivery." - Creasy & Resnik's MFM
| Severity | Gestational Age |
|---|---|
| Mild (bile acids <40 µmol/L) | 37+0 - 38+0 weeks |
| Severe (bile acids ≥40 µmol/L) | 35+0 - 37+0 weeks |
| Very severe / prior IUD history | 34+0 weeks (individualised) |
| Type | Gestational Age |
|---|---|
| Dichorionic diamniotic (DCDA) twins, uncomplicated | 38+0 weeks |
| Monochorionic diamniotic (MCDA) twins | 36+0 - 37+0 weeks (higher risk of IUFD) |
| Monochorionic monoamniotic (MCMA) twins | 32+0 - 34+0 weeks (cord entanglement risk) |
| Complicated twins (TTTS post-laser) | 34+0 - 37+0 weeks (individualised) |
| Condition | Earliest Delivery | Typical Delivery Target |
|---|---|---|
| Uncomplicated (elective) | 39+0 | 39+0 - 40+6 |
| Postterm | 41+0 | By 42+6 at absolute latest |
| Pre-eclampsia ≥37 wks | 37+0 | Prompt at 37 |
| Pre-eclampsia 34-37 wks | 34+0 | Consider delivery after 34 |
| Severe PE/HELLP | Any (after steroids if <34 wks) | Expedient |
| Chronic hypertension | 38+0 | 38+0 - 38+6 |
| GDM (well controlled, insulin) | 38+0 | 38+0 - 39+0 |
| Pre-gestational diabetes (poor control) | 36+0 | 36+0 - 37+6 |
| PROM at term | 37+0 | Within 12-24 hrs of PROM |
| PPROM 34-37 wks | 34+0 | Deliver promptly |
| Mild FGR, normal Dopplers | 37+0 | 37+0 |
| FGR + absent/reversed UA flow | 34+0 | 34+0 |
| FGR + reversed UA flow >30 wks | 30+0 | As soon as possible |
| Cholestasis (mild) | 37+0 | 37-38 |
| Cholestasis (severe, bile acids ≥40) | 35+0 | 35-37 |
| DCDA twins (uncomplicated) | 38+0 | 38+0 |
| MCDA twins | 36+0 | 36-37 |
| MCMA twins | 32+0 | 32-34 |
| IUFD | Any | Promptly on diagnosis |
Create a clinical decision flowchart PDF for induction timing by indication
ls -la /tmp/workspace/ 2>/dev/null || echo "workspace empty or missing"
mkdir -p /tmp/workspace/iol-flowchart
~/iol-flowchart/build_flowchart.py
"""
Clinical Decision Flowchart: Induction of Labour - Timing by Indication
Multi-page A4 PDF using ReportLab
"""
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
from reportlab.graphics.shapes import (
Drawing, Rect, String, Line, Polygon, Arrow,
Group, Circle
)
from reportlab.graphics import renderPDF
from reportlab.platypus import Flowable
import os
OUTPUT = "/tmp/workspace/iol-flowchart/IOL_Clinical_Decision_Flowchart.pdf"
# ─── Colour palette ────────────────────────────────────────────────────────
C_HEADER_BG = colors.HexColor("#1A3557") # deep navy
C_HEADER_TXT = colors.white
C_SECTION_A = colors.HexColor("#2166AC") # blue – hypertension
C_SECTION_B = colors.HexColor("#D6604D") # red – urgent/severe
C_SECTION_C = colors.HexColor("#4DAC26") # green – diabetes
C_SECTION_D = colors.HexColor("#7B3294") # purple – PROM
C_SECTION_E = colors.HexColor("#E08214") # orange – FGR
C_SECTION_F = colors.HexColor("#35978F") # teal – other
C_DECISION = colors.HexColor("#FFF3B0") # pale yellow – decision nodes
C_ACTION_GR = colors.HexColor("#D4EDDA") # pale green – safe/deliver
C_ACTION_OR = colors.HexColor("#FFF3CD") # pale amber – monitor
C_ACTION_RD = colors.HexColor("#F8D7DA") # pale red – urgent
C_RULE = colors.HexColor("#AAAAAA")
C_BODY_BG = colors.HexColor("#F7F9FC")
C_ALT_ROW = colors.HexColor("#EBF2FA")
C_BORDER = colors.HexColor("#CCDDEE")
# ─── Document setup ─────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=1.5*cm, rightMargin=1.5*cm,
topMargin=1.8*cm, bottomMargin=1.8*cm,
title="IOL Clinical Decision Flowchart",
author="Orris Medical Reference",
subject="Induction of Labour – Timing by Indication"
)
W, H = A4
USABLE_W = W - 3*cm
styles = getSampleStyleSheet()
def S(name, **kw):
"""Create a paragraph style."""
base = styles.get(name, styles["Normal"])
return ParagraphStyle(name + str(id(kw)), parent=base, **kw)
title_style = S("Normal", fontSize=18, leading=22, textColor=C_HEADER_TXT,
alignment=TA_CENTER, fontName="Helvetica-Bold")
sub_style = S("Normal", fontSize=10, leading=13, textColor=C_HEADER_TXT,
alignment=TA_CENTER, fontName="Helvetica")
h1_style = S("Normal", fontSize=13, leading=16, textColor=C_HEADER_TXT,
alignment=TA_LEFT, fontName="Helvetica-Bold", spaceBefore=4)
h2_style = S("Normal", fontSize=11, leading=14, textColor=colors.white,
alignment=TA_LEFT, fontName="Helvetica-Bold")
body_style = S("Normal", fontSize=9, leading=12, textColor=colors.HexColor("#1a1a1a"),
alignment=TA_LEFT, fontName="Helvetica")
small_style = S("Normal", fontSize=7.5, leading=10, textColor=colors.HexColor("#444444"),
alignment=TA_LEFT, fontName="Helvetica")
bold_style = S("Normal", fontSize=9, leading=12, textColor=colors.HexColor("#1a1a1a"),
alignment=TA_LEFT, fontName="Helvetica-Bold")
center_style = S("Normal", fontSize=9, leading=12, textColor=colors.HexColor("#1a1a1a"),
alignment=TA_CENTER, fontName="Helvetica")
warn_style = S("Normal", fontSize=8, leading=11, textColor=colors.HexColor("#7B0000"),
alignment=TA_LEFT, fontName="Helvetica-Bold")
note_style = S("Normal", fontSize=8, leading=11, textColor=colors.HexColor("#333333"),
alignment=TA_LEFT, fontName="Helvetica-Oblique")
footer_style = S("Normal", fontSize=7, leading=9, textColor=colors.HexColor("#888888"),
alignment=TA_CENTER, fontName="Helvetica")
# ─── Helper: section header banner ──────────────────────────────────────────
def section_banner(text, bg_color, text_color=colors.white, number=None):
label = f"<b>{number} {text}</b>" if number else f"<b>{text}</b>"
data = [[Paragraph(label, S("Normal", fontSize=11, leading=14,
textColor=text_color, fontName="Helvetica-Bold"))]]
t = Table(data, colWidths=[USABLE_W])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg_color),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 10),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING",(0,0), (-1,-1), 6),
("ROUNDEDCORNERS", [4]),
]))
return t
# ─── Helper: decision table (condition → timing → action → notes) ────────────
def decision_table(rows, col_widths=None, header=True):
"""
rows: list of (condition, timing, action_text, action_color, note)
"""
if col_widths is None:
col_widths = [USABLE_W*0.30, USABLE_W*0.20, USABLE_W*0.22, USABLE_W*0.28]
hdr = [
Paragraph("<b>Clinical Scenario</b>", bold_style),
Paragraph("<b>Deliver by / at</b>", bold_style),
Paragraph("<b>Action</b>", bold_style),
Paragraph("<b>Key Notes</b>", bold_style),
]
table_data = [hdr]
for i, (cond, timing, action, acolor, note) in enumerate(rows):
row = [
Paragraph(cond, body_style),
Paragraph(f"<b>{timing}</b>", S("Normal", fontSize=9, leading=12,
textColor=colors.HexColor("#1a1a1a"),
alignment=TA_CENTER, fontName="Helvetica-Bold")),
Paragraph(action, S("Normal", fontSize=8.5, leading=11,
textColor=colors.HexColor("#1a1a1a"),
alignment=TA_CENTER, fontName="Helvetica-Bold")),
Paragraph(note, small_style),
]
table_data.append(row)
t = Table(table_data, colWidths=col_widths, repeatRows=1)
style_cmds = [
("BACKGROUND", (0,0), (-1,0), C_HEADER_BG),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("GRID", (0,0), (-1,-1), 0.4, C_BORDER),
("ROWBACKGROUNDS",(0,1), (-1,-1), [C_BODY_BG, C_ALT_ROW]),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 6),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,0), 9),
]
# Colour the action column cells individually
for i, (_, _, _, acolor, _) in enumerate(rows, start=1):
style_cmds.append(("BACKGROUND", (2,i), (2,i), acolor))
t.setStyle(TableStyle(style_cmds))
return t
# ─── Helper: flowchart node drawing ─────────────────────────────────────────
class FlowNode(Flowable):
"""A simple diamond or rectangle node for flowchart."""
def __init__(self, text, width, height, shape="rect",
fill=C_DECISION, border=C_RULE, fontsize=9):
Flowable.__init__(self)
self.text = text
self.width = width
self.height = height
self.shape = shape
self.fill = fill
self.border = border
self.fontsize = fontsize
def draw(self):
c = self.canv
w, h = self.width, self.height
c.saveState()
c.setFillColor(self.fill)
c.setStrokeColor(self.border)
c.setLineWidth(1.2)
if self.shape == "diamond":
path = c.beginPath()
path.moveTo(w/2, h); path.lineTo(w, h/2)
path.lineTo(w/2, 0); path.lineTo(0, h/2)
path.close()
c.drawPath(path, fill=1, stroke=1)
else:
c.roundRect(0, 0, w, h, 6, fill=1, stroke=1)
c.setFont("Helvetica-Bold", self.fontsize)
c.setFillColor(colors.HexColor("#1a1a1a"))
# word wrap roughly
words = self.text.split()
lines, line = [], []
for w_ in words:
if len(" ".join(line + [w_])) * self.fontsize * 0.55 < self.width - 10:
line.append(w_)
else:
if line: lines.append(" ".join(line))
line = [w_]
if line: lines.append(" ".join(line))
total_h = len(lines) * (self.fontsize + 2)
y_start = (h + total_h) / 2 - self.fontsize
for i, l in enumerate(lines):
c.drawCentredString(self.width/2, y_start - i*(self.fontsize+2), l)
c.restoreState()
def wrap(self, aw, ah):
return self.width, self.height
# ─── Build the main flowchart drawing (page 2) ──────────────────────────────
def build_algorithm_drawing():
"""Draw the main decision algorithm as a ReportLab Drawing."""
dw, dh = USABLE_W, 19*cm
d = Drawing(dw, dh)
NW = USABLE_W - 10 # node width
NH = 1.1*cm # normal node height
DH = 1.4*cm # diamond height
cx = dw / 2 # centre x
fs = 8 # font size for nodes
def rect_node(x, y, w, h, text, fill, border=C_RULE, fontsize=8):
d.add(Rect(x, y, w, h, rx=5, ry=5,
fillColor=fill, strokeColor=border, strokeWidth=1.2))
# simple centred text
d.add(String(x + w/2, y + h/2 - fontsize/2 + 1, text,
fontSize=fontsize, fontName="Helvetica-Bold",
fillColor=colors.HexColor("#1a1a1a"),
textAnchor="middle"))
def arrow(x1, y1, x2, y2):
d.add(Line(x1, y1, x2, y2, strokeColor=C_RULE, strokeWidth=1.0))
# arrowhead
d.add(Polygon([x2, y2, x2-4, y2+7, x2+4, y2+7],
fillColor=C_RULE, strokeColor=C_RULE, strokeWidth=0.5))
y = dh - 0.5*cm
# ── START ──
y -= NH
rect_node(cx - NW/2, y, NW, NH,
"PATIENT REQUIRES DELIVERY DECISION", C_HEADER_BG, C_HEADER_BG, fontsize=9)
arrow(cx, y, cx, y - 0.4*cm); y -= 0.4*cm
# ── Diamond: Contraindications? ──
y -= DH
d.add(Rect(cx - NW/2, y, NW, DH, rx=5, ry=5,
fillColor=C_DECISION, strokeColor=colors.HexColor("#CC8800"), strokeWidth=1.5))
d.add(String(cx, y + DH/2 - 4, "Any ABSOLUTE CONTRAINDICATION to IOL?",
fontSize=8, fontName="Helvetica-Bold",
fillColor=colors.HexColor("#7B3800"), textAnchor="middle"))
d.add(String(cx, y + DH/2 - 14, "(Placenta praevia | Prior classical CS | Cord prolapse | Transverse lie)",
fontSize=7, fontName="Helvetica",
fillColor=colors.HexColor("#555555"), textAnchor="middle"))
# YES branch right
y_ci = y + DH/2
d.add(Line(cx + NW/2, y_ci, cx + NW/2 + 1.5*cm, y_ci,
strokeColor=C_SECTION_B, strokeWidth=1.2))
d.add(String(cx + NW/2 + 0.2*cm, y_ci + 2, "YES", fontSize=7,
fontName="Helvetica-Bold", fillColor=C_SECTION_B))
rw = 2.5*cm; rh = 0.9*cm
rx = cx + NW/2 + 1.5*cm - rw/2
d.add(Rect(rx, y_ci - rh/2, rw, rh, rx=4, ry=4,
fillColor=C_ACTION_RD, strokeColor=C_SECTION_B, strokeWidth=1))
d.add(String(rx + rw/2, y_ci - 4, "CAESAREAN SECTION",
fontSize=7.5, fontName="Helvetica-Bold",
fillColor=C_SECTION_B, textAnchor="middle"))
# NO arrow down
arrow(cx, y, cx, y - 0.35*cm)
d.add(String(cx + 4, y - 0.15*cm, "NO", fontSize=7,
fontName="Helvetica-Bold", fillColor=colors.HexColor("#1a7a1a")))
y -= 0.35*cm
# ── Diamond: Indication? ──
y -= DH*1.1
d.add(Rect(cx - NW/2, y, NW, DH*1.1, rx=5, ry=5,
fillColor=C_DECISION, strokeColor=C_RULE, strokeWidth=1.2))
d.add(String(cx, y + DH*1.1/2, "IDENTIFY PRIMARY INDICATION",
fontSize=9, fontName="Helvetica-Bold",
fillColor=colors.HexColor("#1A3557"), textAnchor="middle"))
arrow(cx, y, cx, y - 0.4*cm); y -= 0.4*cm
# ── Branch row: 4 categories ──
cats = [
("HYPERTENSIVE\nDISORDER", C_SECTION_A),
("DIABETES /\nMACROSOMIA", C_SECTION_C),
("PROM / PPROM", C_SECTION_D),
("FGR / IUGR", C_SECTION_E),
]
cat_w = NW / 4 - 4
cat_h = 1.3*cm
y -= cat_h + 0.3*cm
cat_x_start = cx - NW/2
cat_ys = []
for i, (label, col) in enumerate(cats):
bx = cat_x_start + i*(cat_w + 4) + 2
d.add(Rect(bx, y, cat_w, cat_h, rx=4, ry=4,
fillColor=col, strokeColor=col, strokeWidth=0))
lines = label.split("\n")
for j, l in enumerate(lines):
d.add(String(bx + cat_w/2, y + cat_h/2 + (len(lines)-1-j)*9 - 4,
l, fontSize=7.5, fontName="Helvetica-Bold",
fillColor=colors.white, textAnchor="middle"))
cat_ys.append((bx + cat_w/2, y))
# arrows from decision to categories
for bx_mid, by in cat_ys:
d.add(Line(cx, y + cat_h + 0.4*cm, bx_mid, by + cat_h,
strokeColor=C_RULE, strokeWidth=0.8))
arrow(cx, y + cat_h + 0.4*cm + 0.3*cm, cx, y + cat_h + 0.4*cm)
y -= 0.3*cm
# ── Sub-decision boxes per category ──
sub_font = 6.5
sub_h = 2.8*cm
y -= sub_h + 0.2*cm
sub_data = [
# HYPERTENSION
("≥37 wks → Deliver\n34-37 wks → Consider\n planned delivery\n<34 wks → Expectant\n (if stable)\nSevere/HELLP → ANY\n gestation: DELIVER",
C_SECTION_A),
# DIABETES
("Diet-controlled GDM\n→ 40-41 wks\nInsulin GDM / T1/T2\n→ 38-39 wks\nPoor control /\n vascular Dz\n→ 36-37 wks",
C_SECTION_C),
# PROM
("PROM ≥37 wks\n→ Induce <24 hrs\nPPROM 34-36+6\n→ Deliver\nPPROM 32-34 wks\n→ Individualise\nPPROM <32 wks\n→ Expectant",
C_SECTION_D),
# FGR
("Normal Dopplers\n→ 37 wks\nAbnormal UA (no ED)\n→ 37 wks, monitor\nAbsent ED flow\n→ 34 wks\nReversed ED flow\n→ ≥30 wks: DELIVER",
C_SECTION_E),
]
for i, ((text, col), (bx_mid, _)) in enumerate(zip(sub_data, cat_ys)):
bx = bx_mid - cat_w/2
d.add(Rect(bx, y, cat_w, sub_h, rx=4, ry=4,
fillColor=colors.HexColor("#F0F6FF"),
strokeColor=col, strokeWidth=1.5))
lines = text.split("\n")
for j, l in enumerate(lines):
d.add(String(bx + 4, y + sub_h - 12 - j*9.5, l,
fontSize=sub_font, fontName="Helvetica",
fillColor=colors.HexColor("#1a1a1a")))
# arrow from category box
d.add(Line(bx_mid, y + sub_h, bx_mid, y + sub_h + 0.3*cm,
strokeColor=col, strokeWidth=1))
d.add(Polygon([bx_mid, y+sub_h, bx_mid-3, y+sub_h+5, bx_mid+3, y+sub_h+5],
fillColor=col, strokeColor=col, strokeWidth=0.5))
y -= 0.6*cm
# ── "Other indications" banner ──
arrow(cx, y + 0.6*cm, cx, y + 0.15*cm)
y -= 0.9*cm
d.add(Rect(cx - NW/2, y, NW, 0.85*cm, rx=4, ry=4,
fillColor=C_SECTION_F, strokeColor=C_SECTION_F, strokeWidth=0))
others = "OTHER: Postterm ≥41+0 wks | Cholestasis: 37 wks (mild) / 35 wks (severe) | Twins (DCDA 38w, MCDA 36w, MCMA 32-34w) | IUFD: any gestation"
d.add(String(cx, y + 0.3*cm, others,
fontSize=6.8, fontName="Helvetica-Bold",
fillColor=colors.white, textAnchor="middle"))
y -= 0.55*cm
arrow(cx, y + 0.55*cm, cx, y + 0.1*cm)
# ── Bishop Score Assessment ──
y -= NH*1.1
d.add(Rect(cx - NW/2, y, NW, NH*1.1, rx=5, ry=5,
fillColor=colors.HexColor("#FFF9E6"),
strokeColor=colors.HexColor("#CC8800"), strokeWidth=1.5))
d.add(String(cx, y + NH*1.1/2 + 2,
"ASSESS CERVIX → Calculate Bishop Score",
fontSize=9, fontName="Helvetica-Bold",
fillColor=colors.HexColor("#7B4800"), textAnchor="middle"))
d.add(String(cx, y + NH*1.1/2 - 9,
"(Dilation · Effacement · Station · Consistency · Position)",
fontSize=7, fontName="Helvetica",
fillColor=colors.HexColor("#555555"), textAnchor="middle"))
arrow(cx, y, cx, y - 0.35*cm); y -= 0.35*cm
# ── Two branches: favourable vs unfavourable ──
bscore_y = y
bh = 1.2*cm; bw = NW/2 - 8
# Favourable ≥6 (left)
d.add(Line(cx, bscore_y, cx - bw/2 - 4, bscore_y - 0.3*cm,
strokeColor=C_RULE, strokeWidth=0.8))
d.add(Rect(cx - bw - 8, bscore_y - 0.3*cm - bh, bw, bh, rx=4, ry=4,
fillColor=C_ACTION_GR, strokeColor=colors.HexColor("#218c33"), strokeWidth=1.2))
d.add(String(cx - bw/2 - 8, bscore_y - 0.3*cm - bh/2 + 2,
"Bishop ≥6 (FAVOURABLE)",
fontSize=7.5, fontName="Helvetica-Bold",
fillColor=colors.HexColor("#155724"), textAnchor="middle"))
d.add(String(cx - bw/2 - 8, bscore_y - 0.3*cm - bh/2 - 6,
"Amniotomy + Oxytocin",
fontSize=7, fontName="Helvetica",
fillColor=colors.HexColor("#155724"), textAnchor="middle"))
# Unfavourable <6 (right)
d.add(Line(cx, bscore_y, cx + bw/2 + 4, bscore_y - 0.3*cm,
strokeColor=C_RULE, strokeWidth=0.8))
d.add(Rect(cx + 8, bscore_y - 0.3*cm - bh, bw, bh, rx=4, ry=4,
fillColor=C_ACTION_OR, strokeColor=colors.HexColor("#856404"), strokeWidth=1.2))
d.add(String(cx + bw/2 + 8, bscore_y - 0.3*cm - bh/2 + 2,
"Bishop <6 (UNFAVOURABLE)",
fontSize=7.5, fontName="Helvetica-Bold",
fillColor=colors.HexColor("#533f03"), textAnchor="middle"))
d.add(String(cx + bw/2 + 8, bscore_y - 0.3*cm - bh/2 - 6,
"Cervical ripening first",
fontSize=7, fontName="Helvetica",
fillColor=colors.HexColor("#533f03"), textAnchor="middle"))
y = bscore_y - 0.3*cm - bh - 0.5*cm
arrow(cx, y + 0.5*cm, cx, y + 0.15*cm)
# ── Final action bar ──
y -= 0.9*cm
d.add(Rect(cx - NW/2, y, NW, 0.85*cm, rx=4, ry=4,
fillColor=C_HEADER_BG, strokeColor=C_HEADER_BG, strokeWidth=0))
d.add(String(cx, y + 0.3*cm,
"PROCEED WITH INDUCTION · Continuous CTG · IV access · Analgesia plan · Obstetric review",
fontSize=7.5, fontName="Helvetica-Bold",
fillColor=colors.white, textAnchor="middle"))
return d
# ─── Assemble PDF story ──────────────────────────────────────────────────────
story = []
# ── PAGE 1: Cover header + Reference tables ──────────────────────────────────
# Header block
header_data = [[
Paragraph("INDUCTION OF LABOUR", title_style),
Paragraph("Clinical Decision Guide: Timing by Indication", sub_style),
Paragraph("Based on Creasy & Resnik's MFM · ACOG/SMFM Guidelines · HYPITAT Trial · ARRIVE Trial",
S("Normal", fontSize=8, textColor=colors.HexColor("#AACCEE"),
alignment=TA_CENTER, fontName="Helvetica-Oblique")),
]]
header_table = Table([[p] for p in header_data[0]], colWidths=[USABLE_W])
header_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), C_HEADER_BG),
("LEFTPADDING", (0,0), (-1,-1), 12),
("RIGHTPADDING", (0,0), (-1,-1), 12),
("TOPPADDING", (0,0), (-1,-1), 10),
("BOTTOMPADDING",(0,0), (-1,-1), 10),
("ROUNDEDCORNERS", [6]),
]))
story.append(header_table)
story.append(Spacer(1, 0.4*cm))
# ── SECTION 1: Hypertensive Disorders ────────────────────────────────────────
story.append(section_banner("HYPERTENSIVE DISORDERS OF PREGNANCY", C_SECTION_A, number="1"))
story.append(Spacer(1, 2*mm))
htn_rows = [
("Pre-eclampsia ≥37+0 wks",
"≥ 37+0 wks",
"DELIVER",
C_ACTION_RD,
"HYPITAT: maternal risk ↓ significantly after 37 wks. Induction or CS depending on cervix/fetal presentation."),
("Pre-eclampsia 34+0 – 36+6 wks",
"34–37 wks\n(consider)",
"PLAN DELIVERY",
C_ACTION_OR,
"Planned delivery ↓ severe HTN & maternal morbidity. ~75% progress to severe PE expectantly. Weigh prematurity risk. Shared decision-making."),
("Severe features / HELLP\n(any gestation)",
"URGENT\n(any gestation)",
"DELIVER\nURGENTLY",
C_ACTION_RD,
"After maternal stabilisation (MgSO₄, antihypertensives). Steroids if <34 wks and clinically safe to wait 24-48 hrs. If <24 wks: discuss prognosis."),
("Pre-eclampsia 24–33+6 wks\n(stable, no severe features)",
"Expectant\nthen 34 wks",
"EXPECTANT\nMONITOR",
C_ACTION_OR,
"Deliver if: deteriorating organ function, uncontrolled BP, non-reassuring fetal testing, abruption. Antenatal corticosteroids + MgSO₄ neuroprotection."),
("Pre-eclampsia <24 wks",
"< 24 wks",
"COUNSEL /\nTERMINATE",
C_ACTION_RD,
"Perinatal mortality >80% even with prolongation. Maternal complications common. Termination usually recommended."),
("Chronic hypertension\n(on antihypertensives, uncomplicated)",
"38+0 – 38+6 wks",
"ELECTIVE IOL",
C_ACTION_GR,
"Optimal: 38+0–38+6 (lowest perinatal morbidity). Delivery <36 wks ↑ perinatal risk. Delivery >39 wks ↑ superimposed PE risk."),
("Gestational hypertension ≥37 wks",
"≥ 37+0 wks",
"DELIVER",
C_ACTION_RD,
"Similar to pre-eclampsia guidance; aim not to exceed 41 wks."),
]
story.append(decision_table(htn_rows))
story.append(Spacer(1, 0.4*cm))
# ── SECTION 2: Diabetes ───────────────────────────────────────────────────────
story.append(section_banner("DIABETES IN PREGNANCY", C_SECTION_C, number="2"))
story.append(Spacer(1, 2*mm))
dm_rows = [
("GDM – diet controlled, well managed",
"40+0 – 41+0 wks",
"ELECTIVE IOL",
C_ACTION_GR,
"Low additional risk. Can await spontaneous labour but do not allow postterm. Fetal surveillance from 40 wks."),
("GDM – insulin or metformin,\nwell controlled",
"38+0 – 39+0 wks",
"ELECTIVE IOL",
C_ACTION_GR,
"Standard ACOG/SMFM recommendation. Reduces unexplained stillbirth risk that rises steeply after 38–39 wks."),
("Pre-gestational diabetes (T1/T2),\nwell controlled, no complications",
"38+0 – 39+0 wks",
"ELECTIVE IOL",
C_ACTION_GR,
"HbA1c target maintained. Assess for macrosomia (USS). Consider CS if EFW >4.5 kg."),
("Pre-gestational diabetes,\npoorly controlled / vascular disease",
"36+0 – 37+6 wks",
"EARLIER IOL",
C_ACTION_OR,
"Autonomic neuropathy, nephropathy, retinopathy, or suboptimal glycaemic control → earlier delivery. Individualize."),
("Any diabetic + macrosomia /\noligohydramnios / deteriorating tests",
"Promptly",
"DELIVER",
C_ACTION_RD,
"EFW >4.5 kg: discuss elective CS. Oligohydramnios or BPP decline → immediate delivery."),
]
story.append(decision_table(dm_rows))
story.append(Spacer(1, 0.4*cm))
# ── SECTION 3: PROM / PPROM ───────────────────────────────────────────────────
story.append(section_banner("PRELABOUR RUPTURE OF MEMBRANES (PROM / PPROM)", C_SECTION_D, number="3"))
story.append(Spacer(1, 2*mm))
prom_rows = [
("PROM at term ≥37+0 wks",
"Within 12–24 hrs",
"INDUCE",
C_ACTION_RD,
"Reduces chorioamnionitis & neonatal infection. Oxytocin first-line. GBS status: give prophylaxis if positive."),
("PPROM 34+0 – 36+6 wks\n(late preterm)",
"34–36+6 wks:\nDeliver",
"DELIVER",
C_ACTION_RD,
"Lung maturity generally sufficient; ongoing infection risk outweighs prematurity. Steroids may be considered."),
("PPROM 32+0 – 33+6 wks",
"Individualise\n(32–34 wks)",
"INDIVIDUALISE",
C_ACTION_OR,
"Corticosteroids. Deliver if: pulmonary maturity confirmed, infection, abruption, fetal compromise. Otherwise expectant."),
("PPROM 24+0 – 31+6 wks",
"Expectant until\n≥34 wks",
"EXPECTANT\nMONITOR",
C_ACTION_OR,
"IV antibiotics (latency – erythromycin). Antenatal corticosteroids + MgSO₄ (neuroprotection <32 wks). Daily fetal surveillance. Deliver on deterioration."),
("PPROM previable <24 wks",
"< 24 wks",
"COUNSEL",
C_ACTION_RD,
"Survival extremely poor (<50% even in tertiary centres). Offer expectant management or termination after detailed counselling. Pulmonary hypoplasia risk ~25%."),
("PROM + chorioamnionitis\n(any gestation)",
"URGENT",
"DELIVER\nPROMPTLY",
C_ACTION_RD,
"IV broad-spectrum antibiotics immediately. Deliver by most expedient route. Ongoing fetal monitoring."),
]
story.append(decision_table(prom_rows))
# ── PAGE BREAK ────────────────────────────────────────────────────────────────
from reportlab.platypus import PageBreak
story.append(PageBreak())
# Header repeat on page 2
story.append(header_table)
story.append(Spacer(1, 0.4*cm))
# ── SECTION 4: FGR / IUGR ────────────────────────────────────────────────────
story.append(section_banner("FETAL GROWTH RESTRICTION (FGR / IUGR)", C_SECTION_E, number="4"))
story.append(Spacer(1, 2*mm))
fgr_rows = [
("FGR, normal umbilical artery Dopplers",
"37+0 wks",
"ELECTIVE IOL",
C_ACTION_GR,
"Serial growth scans every 2–3 weeks. Twice-weekly antenatal testing from 36 wks. Deliver once term."),
("FGR, abnormal UA (↑ PI)\nbut end-diastolic flow present",
"37+0 wks",
"ELECTIVE IOL",
C_ACTION_GR,
"Intensify surveillance (twice weekly BPP/NST). Deliver at 37 wks or earlier if fetal status deteriorates."),
("FGR, absent end-diastolic flow\n(AEDF) in UA",
"34+0 wks",
"DELIVER",
C_ACTION_OR,
"Inpatient surveillance. Daily testing from 25 wks. Deliver at 34 wks. Earlier if BPP <4 or DV abnormal."),
("FGR, reversed end-diastolic flow\n(REDF) in UA, 25–30 wks",
"Individualise\n≥28–30 wks",
"DELIVER\n(CONSIDER)",
C_ACTION_OR,
"DV reversed a-wave or BPP ≤4 → deliver immediately regardless of gestation. Weigh extreme prematurity risks."),
("FGR, reversed UA flow >30 wks",
"≥ 30+0 wks",
"DELIVER",
C_ACTION_RD,
"Reversed UA flow after 30 wks = indication for delivery. Maximise corticosteroids before delivery if feasible."),
("FGR + abnormal MCA-PSV\n(>1.5 MoM – consider isoimmunisation)",
"34–37 wks",
"INDIVIDUALIS\nE",
C_ACTION_OR,
"Evaluate for anaemia. Cordocentesis ± IUT if before 34 wks. Deliver at 34–37 wks depending on response."),
]
story.append(decision_table(fgr_rows))
story.append(Spacer(1, 0.4*cm))
# ── SECTION 5: Other Indications ────────────────────────────────────────────
story.append(section_banner("OTHER COMMON INDICATIONS", C_SECTION_F, number="5"))
story.append(Spacer(1, 2*mm))
other_rows = [
("POSTTERM pregnancy\n(≥41+0 wks)",
"41+0 – 42+0 wks\n(by 42+6 at latest)",
"INDUCE",
C_ACTION_RD,
"Risk of stillbirth, meconium aspiration, macrosomia increases. NNT 527 at 41 wks vs 195 at 43 wks to prevent 1 death. Foetal surveillance from 41 wks."),
("Intrahepatic cholestasis –\nMild (bile acids <40 µmol/L)",
"37+0 – 38+0 wks",
"ELECTIVE IOL",
C_ACTION_GR,
"Unexplained stillbirth risk. UDCA may reduce pruritus but does not eliminate fetal risk. Do not allow postterm."),
("Intrahepatic cholestasis –\nSevere (bile acids ≥40 µmol/L)",
"35+0 – 37+0 wks",
"EARLIER IOL",
C_ACTION_OR,
"Bile acids ≥100 µmol/L: consider delivery at 35 wks. Prior IUFD history: deliver even earlier."),
("Dichorionic diamniotic (DCDA) twins\nuncomplicated",
"38+0 wks",
"ELECTIVE IOL",
C_ACTION_GR,
"Risk of IUFD rises after 38 wks. Confirm presentation of leading twin."),
("Monochorionic diamniotic (MCDA) twins\nuncomplicated",
"36+0 – 37+0 wks",
"ELECTIVE IOL",
C_ACTION_OR,
"Higher risk of IUFD from placental sharing. Weekly surveillance from 16 wks."),
("Monochorionic monoamniotic (MCMA)\ntwins",
"32+0 – 34+0 wks",
"DELIVER\n(usually CS)",
C_ACTION_RD,
"Cord entanglement risk. Inpatient surveillance from 28 wks with continuous CTG. Usually by CS."),
("Intrauterine fetal death (IUFD)",
"As soon as\nmother ready",
"INDUCE",
C_ACTION_OR,
"<28 wks: misoprostol 200–400 mcg q4h. >28 wks: misoprostol 25–50 mcg q4h OR oxytocin. Check fibrinogen if >4 wks since death (DIC risk). RhD immunoglobulin if Rh-negative."),
("Chorioamnionitis / IAI",
"URGENT",
"DELIVER",
C_ACTION_RD,
"IV antibiotics immediately (ampicillin + gentamicin). Induction for vaginal delivery preferred unless obstetric contraindication. Neonatal team alert."),
("Elective (low-risk, nulliparous\nat 39+0 wks – ARRIVE trial)",
"39+0 wks",
"OFFER IOL",
C_ACTION_GR,
"ARRIVE trial: elective IOL at 39 wks ↓ CS rate (15% vs 20%) with no adverse neonatal outcomes. Discuss with patient; not mandatory."),
]
story.append(decision_table(other_rows))
story.append(Spacer(1, 0.4*cm))
# ── SECTION 6: Absolute Contraindications Table ──────────────────────────────
story.append(section_banner("CONTRAINDICATIONS TO IOL", C_SECTION_B, number="6"))
story.append(Spacer(1, 2*mm))
contra_data = [
[Paragraph("<b>ABSOLUTE (IOL contraindicated → CS)</b>", warn_style),
Paragraph("<b>RELATIVE (individualize; senior review)</b>",
S("Normal", fontSize=8, fontName="Helvetica-Bold",
textColor=colors.HexColor("#533f03")))],
[
Paragraph(
"• Placenta praevia / vasa praevia\n"
"• Previous classical (vertical) uterine incision\n"
"• Cord presentation or prolapse\n"
"• Transverse / oblique lie\n"
"• Acute severe fetal distress requiring immediate delivery\n"
"• Floating / unengaged presenting part (floating)\n"
"• Active primary genital herpes\n"
"• Invasive cervical carcinoma",
body_style),
Paragraph(
"• Previous low-transverse CS (TOLAC may be appropriate)\n"
"• Grand multiparity (≥5 prior pregnancies >20 wks)\n"
"• Multiple pregnancy\n"
"• Suspected CPD / macrosomia\n"
"• Breech presentation\n"
"• Inability to adequately monitor FHR\n"
"• Severe oligohydramnios",
body_style),
]
]
contra_t = Table(contra_data, colWidths=[USABLE_W/2, USABLE_W/2])
contra_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (0,0), colors.HexColor("#F8D7DA")),
("BACKGROUND", (1,0), (1,0), colors.HexColor("#FFF3CD")),
("BACKGROUND", (0,1), (0,1), colors.HexColor("#FFF5F5")),
("BACKGROUND", (1,1), (1,1), colors.HexColor("#FFFDF0")),
("GRID", (0,0), (-1,-1), 0.5, C_BORDER),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
]))
story.append(contra_t)
story.append(Spacer(1, 0.4*cm))
# ── SECTION 7: Bishop Score Quick Reference ───────────────────────────────────
story.append(section_banner("BISHOP SCORE – QUICK REFERENCE", colors.HexColor("#CC8800"), number="7"))
story.append(Spacer(1, 2*mm))
bishop_data = [
[Paragraph("<b>Factor</b>", bold_style),
Paragraph("<b>0</b>", center_style),
Paragraph("<b>1</b>", center_style),
Paragraph("<b>2</b>", center_style),
Paragraph("<b>3</b>", center_style)],
["Dilation (cm)", "0", "1–2", "3–4", "5–6"],
["Effacement (%)", "0–30", "40–50", "60–70", "80"],
["Station", "−3", "−2", "−1 / 0", "+1 / +2"],
["Consistency", "Firm", "Medium", "Soft", "—"],
["Position", "Posterior", "Mid", "Anterior", "—"],
]
bishop_t = Table(bishop_data,
colWidths=[USABLE_W*0.3, USABLE_W*0.175, USABLE_W*0.175,
USABLE_W*0.175, USABLE_W*0.175])
bishop_style_cmds = [
("BACKGROUND", (0,0), (-1,0), colors.HexColor("#CC8800")),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9),
("GRID", (0,0), (-1,-1), 0.4, C_BORDER),
("ROWBACKGROUNDS",(0,1), (-1,-1), [C_BODY_BG, C_ALT_ROW]),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("ALIGN", (1,0), (-1,-1), "CENTER"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
]
bishop_t.setStyle(TableStyle(bishop_style_cmds))
# Interpretation alongside
interp_data = [
[Paragraph("<b>Score</b>", bold_style),
Paragraph("<b>Cervix</b>", bold_style),
Paragraph("<b>Management</b>", bold_style)],
["≥ 9", "Very favourable", "Amniotomy alone may be sufficient"],
["6–8", "Favourable", "Amniotomy + oxytocin"],
["< 6", "Unfavourable", "Cervical ripening required first"],
["< 4", "Unfavourable", "Mechanical (Foley balloon) or PG preferred"],
]
interp_t = Table(interp_data,
colWidths=[USABLE_W*0.12, USABLE_W*0.23, USABLE_W*0.35])
interp_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), colors.HexColor("#CC8800")),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("GRID", (0,0), (-1,-1), 0.4, C_BORDER),
("ROWBACKGROUNDS",(0,1), (-1,-1), [C_BODY_BG, C_ALT_ROW]),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
]))
bishop_row = Table([[bishop_t, Spacer(0.3*cm, 1), interp_t]],
colWidths=[USABLE_W*0.50, 0.3*cm, USABLE_W*0.70 - 0.3*cm])
bishop_row.setStyle(TableStyle([("VALIGN",(0,0),(-1,-1),"TOP"),("LEFTPADDING",(0,0),(-1,-1),0),("RIGHTPADDING",(0,0),(-1,-1),0)]))
story.append(bishop_row)
story.append(Spacer(1, 0.5*cm))
# ── PAGE 3: Algorithm Flowchart ────────────────────────────────────────────
story.append(PageBreak())
story.append(header_table)
story.append(Spacer(1, 0.3*cm))
story.append(section_banner("DECISION ALGORITHM OVERVIEW", C_HEADER_BG))
story.append(Spacer(1, 0.3*cm))
drawing = build_algorithm_drawing()
story.append(drawing)
story.append(Spacer(1, 0.4*cm))
# ── Method selection table ────────────────────────────────────────────────────
story.append(section_banner("METHOD SELECTION GUIDE", colors.HexColor("#555555")))
story.append(Spacer(1, 2*mm))
method_data = [
[Paragraph("<b>Method</b>", bold_style),
Paragraph("<b>Bishop Score</b>", bold_style),
Paragraph("<b>Prior CS?</b>", bold_style),
Paragraph("<b>Dose / Route</b>", bold_style),
Paragraph("<b>Key Caution</b>", bold_style)],
["Oxytocin IV infusion", "≥ 6 (favourable)", "Use with caution\n(no PG)",
"Start 0.5–2 mU/min; ↑ by 1–2 mU/min q15–40 min",
"Hyperstimulation; antidiuretic effect at high doses"],
["Misoprostol (PGE₁)\nvaginal / oral",
"Any (<6 preferred)", "AVOID if prior CS\n(uterine rupture ↑)",
"25–50 mcg vaginally q4–6 h\nOR 25 mcg oral q2 h",
"Do not use within 4 hrs of oxytocin; T risk uterine rupture"],
["Dinoprostone (PGE₂)\ngel / insert",
"< 6 (ripening)", "AVOID if prior CS",
"Gel 0.5 mg endocervical q6 h (max 3×)\nInsert 10 mg × 12 h",
"Remove insert if hyperstimulation; keep CTG ×30 min after"],
["Foley balloon catheter\n(mechanical)",
"Any (<6 preferred)", "SAFE\n(preferred in prior CS)",
"14–18 Fr; inflate 30–60 mL saline; leave in situ",
"No systemic effect; cord prolapse risk if head high"],
["Amniotomy (ARM)", "≥ 6", "With caution",
"Amniohook at ARM; confirm presentation first",
"Cord prolapse; do not rupture if head floating"],
["Membrane sweep", "Any", "Yes (safe)",
"Digital stretch of membranes at internal os",
"Not formal IOL; preparatory; reduces formal IOL rate"],
["Mifepristone + Misoprostol\n(mainly pre-viability / IUFD)",
"Any", "See notes",
"Mifepristone 200 mg PO then misoprostol 800 mcg\nvaginally 24–48 h later",
"RCOG/WHO protocol. For prior CS at <28 wks may use standard doses."],
]
method_t = Table(method_data,
colWidths=[USABLE_W*0.20, USABLE_W*0.13, USABLE_W*0.12,
USABLE_W*0.30, USABLE_W*0.25],
repeatRows=1)
method_t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), colors.HexColor("#555555")),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8),
("LEADING", (0,0), (-1,-1), 10),
("GRID", (0,0), (-1,-1), 0.4, C_BORDER),
("ROWBACKGROUNDS",(0,1), (-1,-1), [C_BODY_BG, C_ALT_ROW]),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
]))
story.append(method_t)
story.append(Spacer(1, 0.4*cm))
# ── Footer / disclaimer ────────────────────────────────────────────────────────
story.append(HRFlowable(width=USABLE_W, thickness=0.5, color=C_RULE))
story.append(Spacer(1, 2*mm))
story.append(Paragraph(
"Sources: Creasy & Resnik's Maternal-Fetal Medicine (8e) · Comprehensive Clinical Nephrology (7e) · Brenner & Rector's The Kidney · "
"ACOG Practice Bulletin · SMFM Consult Series · HYPITAT Trial · ARRIVE Trial (Grobman et al. NEJM 2018) | "
"This document is a clinical reference aid. Always apply local protocols and clinical judgement. August 2026.",
footer_style))
# ─── Build ───────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF created: {OUTPUT}")
print(f"Size: {os.path.getsize(OUTPUT):,} bytes")
cd /tmp/workspace/iol-flowchart && python build_flowchart.py 2>&1
~/iol-flowchart/build_flowchart.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/iol-flowchart/build_flowchart.py'
cd /tmp/workspace/iol-flowchart && python build_flowchart.py 2>&1
IOL Clinical Decision Flowchart
PDF Document · PDF