Partograph explain basics to clinic
partograph basics clinical use WHO cervical dilation alert action line explained
https://medicalguidelines.msf.org/en/viewport/ONC/english/5-…
partograph sections fetal heart rate descent of head maternal observations complete guide clinical

| Parameter | How to Record | Normal Range / Alert |
|---|---|---|
| Fetal Heart Rate (FHR) | Auscultate every 30 min (1st stage) / every 5 min (2nd stage); plot as a dot | 110-160 bpm; alarm lines at 100 and 180 |
| Amniotic Fluid | Record at each vaginal exam | I = intact; C = clear; M = meconium; B = blood |
| Moulding of skull | Overlap of skull bones at each VE | 0 = none; 1+ = bones appose; 2+ = overlap, reducible; 3+ = fixed overlap (danger) |
| Parameter | Frequency |
|---|---|
| Oxytocin (units/L, drops/min) | Every 30 min if in use |
| Drugs / IV fluids | As given |
| Pulse (dot •) | Every 30 min |
| Blood pressure (arrows ↕) | Every 4 hours |
| Temperature | Every 4 hours |
| Urine - protein, acetone, volume | Each void |
10 | / Action
| / Alert
9 | / /
| / /
7 | / /
| / /
5 |/ /
|_____________ Hours →
0 1 2 3 4
| Line | What It Means | When Crossed |
|---|---|---|
| Alert Line | Expected minimum progress = 1 cm/hour dilatation from 4 cm to 10 cm | Dilatation is slower than expected - reassess, consider transfer or closer monitoring |
| Action Line | Parallel to Alert line, 4 hours to the right | Definitive action required: augmentation (oxytocin/ARM), or caesarean section |
| Grade | Finding | Significance |
|---|---|---|
| 0 | Bones separated, sutures felt | Normal |
| 1+ | Bones just touching | Mild |
| 2+ | Bones overlap, can be separated | Moderate - watch closely |
| 3+ | Fixed overlap | Severe - cephalopelvic disproportion, act urgently |
| Grade | Appearance | Action |
|---|---|---|
| Grade 1 (thin) | Slightly green/yellow | Increase FHR monitoring |
| Grade 2 (moderate) | Clearly green | Prepare for neonatal resuscitation |
| Grade 3 (thick) | Thick pea-soup | Fetal distress likely - expedite delivery |
| Feature | Traditional Partograph | WHO LCG (2020) |
|---|---|---|
| Active phase starts | 4 cm | 5 cm |
| Alert/Action lines | Single fixed 1 cm/hr slope | Per-centimetre time thresholds (evidence-based) |
| 2nd stage monitoring | Limited | Explicit section added |
| Supportive care | Not recorded | Companionship, oral fluids, position documented |
| Philosophy | Detect abnormal labour | Woman-centred, holistic |
Generate a visual poster of moulding grades and meconium staining
A clean, professional medical education poster titled "Intrapartum Monitoring: Moulding Grades & Meconium Staining" for clinical use. TOP HALF - MOULDING GRADES section with a teal/green header: Four side-by-side diagrams of fetal skull cross-sections showing skull bones and sutures, labeled Grade 0 through Grade 3+: - Grade 0: Bones well separated, sutures easily felt, labeled "Normal - No overlap" - Grade 1+: Bones just touching at suture lines, labeled "Mild - Bones apposed, sutures felt" - Grade 2+: Bones overlapping but reducible with pressure, labeled "Moderate - Overlap, reducible. Watch closely" - Grade 3+: Fixed bony overlap that cannot be reduced, red warning border, labeled "SEVERE - Fixed overlap. Suspect CPD. Act urgently" Each diagram shows simplified oval skull shapes with suture lines between them, illustrated in a clean anatomical style. BOTTOM HALF - MECONIUM STAINING section with a dark blue header: Three amniotic fluid sample illustrations in test tubes or fluid droplets side by side: - Grade 1 (Thin): Light yellowish-green fluid, labeled "Thin/Scanty - Slightly green or yellow - Increase FHR monitoring" - Grade 2 (Moderate): Medium green fluid, labeled "Moderate - Clearly green - Prepare neonatal resuscitation team" - Grade 3 (Thick): Dark thick pea-soup brown-green fluid with a red warning symbol, labeled "THICK 'Pea Soup' - Dark green/brown - Likely fetal distress - Expedite delivery NOW" Each grade has a colored severity indicator: green dot for Grade 1, orange dot for Grade 2, red dot for Grade 3. Footer text: "Partograph Monitoring Guide | Intrapartum Care" Clean white background, bold headers, medical illustration style, easy to read at a glance in a clinical setting.

Create a quick reference PDF checklist for partograph documentation
ls /home/daytona/workspace/ 2>/dev/null || echo "workspace empty or not found"
mkdir -p /home/daytona/workspace/partograph && python3 -c "from reportlab.lib.pa…
~/partograph/build_checklist.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Circle
from reportlab.graphics import renderPDF
OUTPUT = "/home/daytona/workspace/partograph/Partograph_Checklist.pdf"
# ── Colours ──────────────────────────────────────────────────────────────────
TEAL = colors.HexColor("#006D77")
TEAL_LT = colors.HexColor("#83C5BE")
TEAL_BG = colors.HexColor("#EDF6F9")
ORANGE = colors.HexColor("#E29578")
RED = colors.HexColor("#C1121F")
RED_LT = colors.HexColor("#FFDDD2")
GREEN = colors.HexColor("#2D6A4F")
GREEN_LT = colors.HexColor("#D8F3DC")
AMBER = colors.HexColor("#F4A261")
AMBER_LT = colors.HexColor("#FFF3E0")
GREY_BG = colors.HexColor("#F8F9FA")
GREY_LINE = colors.HexColor("#DEE2E6")
WHITE = colors.white
BLACK = colors.HexColor("#212529")
HEADER_BG = colors.HexColor("#004E57")
# ── Document ──────────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=1.5*cm, rightMargin=1.5*cm,
topMargin=1.5*cm, bottomMargin=1.5*cm,
title="Partograph Quick Reference Checklist",
author="Clinical Reference Tool"
)
W, H = A4
CONTENT_W = W - 3*cm
styles = getSampleStyleSheet()
def ps(name, **kw):
return ParagraphStyle(name, **kw)
# Custom styles
TITLE_S = ps("title_s", fontSize=20, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=24)
SUB_S = ps("sub_s", fontSize=9, textColor=TEAL_LT, fontName="Helvetica", alignment=TA_CENTER, leading=12)
SECT_S = ps("sect_s", fontSize=10, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_LEFT, leading=13)
BODY_S = ps("body_s", fontSize=8, textColor=BLACK, fontName="Helvetica", alignment=TA_LEFT, leading=11)
BOLD_S = ps("bold_s", fontSize=8, textColor=BLACK, fontName="Helvetica-Bold", alignment=TA_LEFT, leading=11)
SMALL_S = ps("small_s", fontSize=7, textColor=colors.HexColor("#555555"), fontName="Helvetica", alignment=TA_LEFT, leading=10)
WARN_S = ps("warn_s", fontSize=8, textColor=RED, fontName="Helvetica-Bold", alignment=TA_LEFT, leading=11)
GREEN_S = ps("green_s", fontSize=8, textColor=GREEN, fontName="Helvetica-Bold", alignment=TA_LEFT, leading=11)
LABEL_S = ps("label_s", fontSize=7.5,textColor=TEAL, fontName="Helvetica-Bold", alignment=TA_LEFT, leading=10)
CENTER_S = ps("center_s", fontSize=8, textColor=BLACK, fontName="Helvetica", alignment=TA_CENTER, leading=11)
FOOT_S = ps("foot_s", fontSize=6.5,textColor=colors.HexColor("#888888"), fontName="Helvetica", alignment=TA_CENTER, leading=9)
story = []
# ═══════════════════════════════════════════════════════════════════════════════
# HEADER BANNER
# ═══════════════════════════════════════════════════════════════════════════════
header_data = [[
Paragraph("PARTOGRAPH", TITLE_S),
Paragraph("Quick Reference Checklist for Labour Monitoring", SUB_S),
Paragraph("WHO / MSF Standard", ps("r_s", fontSize=8, textColor=TEAL_LT, fontName="Helvetica", alignment=TA_RIGHT, leading=11)),
]]
header_tbl = Table(header_data, colWidths=[CONTENT_W*0.3, CONTENT_W*0.45, CONTENT_W*0.25])
header_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), HEADER_BG),
("TOPPADDING", (0,0), (-1,-1), 10),
("BOTTOMPADDING", (0,0), (-1,-1), 10),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("ROUNDEDCORNERS", [6]),
]))
story.append(header_tbl)
story.append(Spacer(1, 6))
# ── Helper: section header row ────────────────────────────────────────────────
def section_header(text, color=TEAL, icon=""):
label = f"{icon} {text}" if icon else text
t = Table([[Paragraph(label, SECT_S)]], colWidths=[CONTENT_W])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), color),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 8),
("ROUNDEDCORNERS", [4]),
]))
return t
def checkbox_row(label, note="", warn=False):
box = "☐"
sty = WARN_S if warn else BODY_S
note_sty = ps("n", fontSize=7, textColor=colors.HexColor("#777777"), fontName="Helvetica-Oblique", leading=9)
row = [[
Paragraph(box, ps("ck", fontSize=10, fontName="Helvetica", leading=12)),
Paragraph(f"<b>{label}</b>" if warn else label, sty),
Paragraph(note, note_sty) if note else Paragraph("", note_sty),
]]
t = Table(row, colWidths=[0.5*cm, CONTENT_W*0.52, CONTENT_W*0.41])
t.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 2),
("BOTTOMPADDING", (0,0), (-1,-1), 2),
("LEFTPADDING", (0,0), (-1,-1), 3),
]))
return t
# ═══════════════════════════════════════════════════════════════════════════════
# ROW 1 (two columns): WHEN TO START | PATIENT IDENTIFIERS
# ═══════════════════════════════════════════════════════════════════════════════
start_checks = [
("Active labour confirmed (≥4-5 cm dilatation)", "Start plotting at 5 cm (or 4 cm if induced)"),
("Regular uterine contractions present", "≥2 contractions per 10 min"),
("Membranes status noted (intact / ruptured)", "Record hours since rupture"),
("Admission vitals recorded", "BP, Pulse, Temp, Urine"),
("Fetal presentation confirmed cephalic", "Transverse/breech = refer"),
]
ident_fields = [
"Name / ID number",
"Gravida & Para",
"Date & Time of admission",
"Hours since membrane rupture",
"Hospital number / ward",
"EDD / Gestational age",
]
left_items = [section_header("BEFORE YOU START", TEAL)]
for lbl, note in start_checks:
left_items.append(checkbox_row(lbl, note))
right_items = [section_header("PATIENT IDENTIFIERS", TEAL)]
for f in ident_fields:
right_items.append(checkbox_row(f))
# Pad to same length
while len(left_items) < len(right_items):
left_items.append(Spacer(1, 5))
while len(right_items) < len(left_items):
right_items.append(Spacer(1, 5))
two_col = Table(
[[left_items, right_items]],
colWidths=[CONTENT_W*0.52, CONTENT_W*0.48]
)
two_col.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("LEFTPADDING", (0,0), (-1,-1), 0),
("RIGHTPADDING", (0,0), (0,-1), 4),
("TOPPADDING", (0,0), (-1,-1), 0),
("BOTTOMPADDING", (0,0), (-1,-1), 0),
]))
story.append(two_col)
story.append(Spacer(1, 5))
# ═══════════════════════════════════════════════════════════════════════════════
# MONITORING FREQUENCY TABLE
# ═══════════════════════════════════════════════════════════════════════════════
story.append(section_header("MONITORING FREQUENCY — What to Record & When", TEAL))
story.append(Spacer(1, 3))
freq_data = [
[
Paragraph("Parameter", BOLD_S),
Paragraph("Symbol", BOLD_S),
Paragraph("1st Stage\n(Active)", BOLD_S),
Paragraph("2nd Stage", BOLD_S),
Paragraph("Normal Range / Alert", BOLD_S),
],
# Fetal
[Paragraph("Fetal Heart Rate (FHR)", BODY_S), Paragraph("Dot •", CENTER_S),
Paragraph("Every 30 min\n(during + after contraction)", SMALL_S),
Paragraph("Every 5 min", SMALL_S),
Paragraph("110-160 bpm\n⚠ <100 or >180 = fetal distress", SMALL_S)],
[Paragraph("Amniotic Fluid", BODY_S), Paragraph("I/C/M/B", CENTER_S),
Paragraph("Each VE", SMALL_S), Paragraph("Each VE", SMALL_S),
Paragraph("I=Intact C=Clear M=Meconium B=Blood", SMALL_S)],
[Paragraph("Skull Moulding", BODY_S), Paragraph("0/1+/2+/3+", CENTER_S),
Paragraph("Each VE (4-hrly)", SMALL_S), Paragraph("Each VE", SMALL_S),
Paragraph("0-1+ normal; 2+ watch; 3+ act urgently", SMALL_S)],
# Labour progress
[Paragraph("Cervical Dilatation", BODY_S), Paragraph("X", CENTER_S),
Paragraph("Every 4 hours\n(or earlier if concern)", SMALL_S),
Paragraph("N/A", SMALL_S),
Paragraph("≥1 cm/hr; right of alert line = act", SMALL_S)],
[Paragraph("Descent of Head", BODY_S), Paragraph("O", CENTER_S),
Paragraph("Every 4 hours\n(abdominal palpation)", SMALL_S),
Paragraph("Each push\nassessment", SMALL_S),
Paragraph("5/5 → 0/5 (fifths above symphysis)", SMALL_S)],
[Paragraph("Uterine Contractions", BODY_S), Paragraph("Shading", CENTER_S),
Paragraph("Every 30 min\n(count per 10 min)", SMALL_S),
Paragraph("Every 5 min", SMALL_S),
Paragraph("≥3 per 10 min, each >40 sec (solid box)", SMALL_S)],
# Maternal
[Paragraph("Pulse", BODY_S), Paragraph("• (dot)", CENTER_S),
Paragraph("Every 30 min", SMALL_S), Paragraph("Every 30 min", SMALL_S),
Paragraph("60-100 bpm; >120 = tachycardia", SMALL_S)],
[Paragraph("Blood Pressure", BODY_S), Paragraph("↕ (arrows)", CENTER_S),
Paragraph("Every 4 hours", SMALL_S), Paragraph("Every 4 hours", SMALL_S),
Paragraph("⚠ ≥140/90 = hypertension", SMALL_S)],
[Paragraph("Temperature", BODY_S), Paragraph("°C", CENTER_S),
Paragraph("Every 4 hours", SMALL_S), Paragraph("Every 4 hours", SMALL_S),
Paragraph("36.5-37.5°C; >38°C = pyrexia", SMALL_S)],
[Paragraph("Urine (protein/acetone/vol)", BODY_S), Paragraph("+/-", CENTER_S),
Paragraph("Each void", SMALL_S), Paragraph("Each void", SMALL_S),
Paragraph("Protein 2+ = pre-eclampsia risk", SMALL_S)],
[Paragraph("Oxytocin (if augmenting)", BODY_S), Paragraph("U/L, drops", CENTER_S),
Paragraph("Every 30 min", SMALL_S), Paragraph("Every 30 min", SMALL_S),
Paragraph("Document dose, rate changes, response", SMALL_S)],
]
col_w = [CONTENT_W*0.22, CONTENT_W*0.10, CONTENT_W*0.17, CONTENT_W*0.13, CONTENT_W*0.38]
freq_tbl = Table(freq_data, colWidths=col_w, repeatRows=1)
row_colors = []
for i in range(1, len(freq_data)):
bg = GREY_BG if i % 2 == 0 else WHITE
row_colors.append(("BACKGROUND", (0,i), (-1,i), bg))
freq_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL_LT),
("TEXTCOLOR", (0,0), (-1,0), HEADER_BG),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("GRID", (0,0), (-1,-1), 0.4, GREY_LINE),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 4),
("VALIGN", (0,0), (-1,-1), "TOP"),
# Fetal rows background
("BACKGROUND", (0,1), (-1,3), colors.HexColor("#F0FAFA")),
# Labour rows background
("BACKGROUND", (0,4), (-1,6), colors.HexColor("#F5F5FF")),
# Maternal rows background
("BACKGROUND", (0,7), (-1,-1), colors.HexColor("#FFF9F0")),
# Row group labels
("FONTNAME", (0,1), (0,3), "Helvetica-BoldOblique"),
("TEXTCOLOR", (0,1), (0,3), TEAL),
("FONTNAME", (0,4), (0,6), "Helvetica-BoldOblique"),
("TEXTCOLOR", (0,4), (0,6), colors.HexColor("#3D405B")),
("FONTNAME", (0,7), (0,-1), "Helvetica-BoldOblique"),
("TEXTCOLOR", (0,7), (0,-1), ORANGE),
]))
story.append(freq_tbl)
story.append(Spacer(1, 5))
# ═══════════════════════════════════════════════════════════════════════════════
# ROW 2 (three columns): ALERT/ACTION | MOULDING | MECONIUM
# ═══════════════════════════════════════════════════════════════════════════════
# ── Alert / Action Lines ──────────────────────────────────────────────────────
alert_rows = [
[Paragraph("Line", BOLD_S), Paragraph("Meaning", BOLD_S), Paragraph("Action", BOLD_S)],
[Paragraph("Alert\nLine", ps("al", fontSize=7.5, textColor=GREEN, fontName="Helvetica-Bold", leading=10)),
Paragraph("Dilatation < 1 cm/hr\nCurve crosses right", SMALL_S),
Paragraph("Re-assess. Transfer if at BEmONC. Closer monitoring at CEmONC.", SMALL_S)],
[Paragraph("Action\nLine", ps("acl", fontSize=7.5, textColor=RED, fontName="Helvetica-Bold", leading=10)),
Paragraph("4 hrs right of alert\nNo progress", SMALL_S),
Paragraph("DECIDE: Augment (oxytocin/ARM) OR caesarean section.", SMALL_S)],
]
alert_tbl = Table(alert_rows, colWidths=[1.4*cm, 3.2*cm, 4.0*cm])
alert_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), colors.HexColor("#2D6A4F")),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("GRID", (0,0), (-1,-1), 0.4, GREY_LINE),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 4),
("VALIGN", (0,0), (-1,-1), "TOP"),
("BACKGROUND", (0,1), (-1,1), GREEN_LT),
("BACKGROUND", (0,2), (-1,2), RED_LT),
]))
# ── Moulding ─────────────────────────────────────────────────────────────────
mould_rows = [
[Paragraph("Grade", BOLD_S), Paragraph("Finding", BOLD_S), Paragraph("Action", BOLD_S)],
[Paragraph("0", SMALL_S), Paragraph("Bones separated", SMALL_S), Paragraph("Normal", SMALL_S)],
[Paragraph("1+", SMALL_S), Paragraph("Bones just touching", SMALL_S), Paragraph("Monitor closely", SMALL_S)],
[Paragraph("2+", SMALL_S), Paragraph("Overlap, reducible", SMALL_S), Paragraph("Watch; may need intervention", SMALL_S)],
[Paragraph("3+", ps("w3", fontSize=7.5, textColor=RED, fontName="Helvetica-Bold", leading=10)),
Paragraph("Fixed overlap", SMALL_S),
Paragraph("URGENT — suspect CPD", ps("urgm", fontSize=7, textColor=RED, fontName="Helvetica-Bold", leading=10))],
]
mould_tbl = Table(mould_rows, colWidths=[0.9*cm, 2.8*cm, 2.8*cm])
mould_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("GRID", (0,0), (-1,-1), 0.4, GREY_LINE),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 4),
("VALIGN", (0,0), (-1,-1), "TOP"),
("BACKGROUND", (0,4), (-1,4), RED_LT),
]))
# ── Meconium ──────────────────────────────────────────────────────────────────
mec_rows = [
[Paragraph("Grade", BOLD_S), Paragraph("Appearance", BOLD_S), Paragraph("Action", BOLD_S)],
[Paragraph("1\nThin", ps("g1", fontSize=7, textColor=GREEN, fontName="Helvetica-Bold", leading=10)),
Paragraph("Slight yellow/green", SMALL_S), Paragraph("Increase FHR monitoring", SMALL_S)],
[Paragraph("2\nModerate", ps("g2", fontSize=7, textColor=AMBER, fontName="Helvetica-Bold", leading=10)),
Paragraph("Clearly green", SMALL_S), Paragraph("Prepare NICU/resus team", SMALL_S)],
[Paragraph("3\nThick", ps("g3", fontSize=7, textColor=RED, fontName="Helvetica-Bold", leading=10)),
Paragraph("Thick pea-soup", SMALL_S),
Paragraph("FETAL DISTRESS — expedite delivery", ps("urg", fontSize=7, textColor=RED, fontName="Helvetica-Bold", leading=10))],
]
mec_tbl = Table(mec_rows, colWidths=[1.1*cm, 2.5*cm, 3.0*cm])
mec_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), colors.HexColor("#78350F")),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("GRID", (0,0), (-1,-1), 0.4, GREY_LINE),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 4),
("VALIGN", (0,0), (-1,-1), "TOP"),
("BACKGROUND", (0,1), (-1,1), GREEN_LT),
("BACKGROUND", (0,2), (-1,2), AMBER_LT),
("BACKGROUND", (0,3), (-1,3), RED_LT),
]))
# Combine three tables in a row
three_col_hdr = Table(
[[section_header("ALERT & ACTION LINES", GREEN),
section_header("SKULL MOULDING GRADES", TEAL),
section_header("MECONIUM GRADING", colors.HexColor("#78350F"))]],
colWidths=[CONTENT_W*0.36, CONTENT_W*0.33, CONTENT_W*0.31]
)
three_col_hdr.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("LEFTPADDING", (0,0), (-1,-1), 0),
("RIGHTPADDING", (0,0), (0,-1), 4),
("RIGHTPADDING", (0,0), (1,-1), 4),
("TOPPADDING", (0,0), (-1,-1), 0),
("BOTTOMPADDING", (0,0), (-1,-1), 2),
]))
three_col_data = Table(
[[alert_tbl, mould_tbl, mec_tbl]],
colWidths=[CONTENT_W*0.36, CONTENT_W*0.33, CONTENT_W*0.31]
)
three_col_data.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("LEFTPADDING", (0,0), (-1,-1), 0),
("RIGHTPADDING", (0,0), (0,-1), 4),
("RIGHTPADDING", (0,0), (1,-1), 4),
("TOPPADDING", (0,0), (-1,-1), 0),
("BOTTOMPADDING", (0,0), (-1,-1), 0),
]))
story.append(three_col_hdr)
story.append(three_col_data)
story.append(Spacer(1, 5))
# ═══════════════════════════════════════════════════════════════════════════════
# CONTRACTION SHADING KEY
# ═══════════════════════════════════════════════════════════════════════════════
story.append(section_header("CONTRACTION DOCUMENTATION KEY", colors.HexColor("#3D405B")))
story.append(Spacer(1, 3))
cont_data = [
[Paragraph("Symbol", BOLD_S), Paragraph("Duration", BOLD_S), Paragraph("Box Shading", BOLD_S), Paragraph("Interpretation", BOLD_S)],
[Paragraph("Dotted / Stippled", BODY_S), Paragraph("< 20 seconds", SMALL_S),
Paragraph("Dots", SMALL_S), Paragraph("Weak / Inefficient contractions", SMALL_S)],
[Paragraph("Hatched / Diagonal lines", BODY_S), Paragraph("20-40 seconds", SMALL_S),
Paragraph("Diagonal hatching", SMALL_S), Paragraph("Moderate contractions", SMALL_S)],
[Paragraph("Solid / Filled black", BODY_S), Paragraph("> 40 seconds", SMALL_S),
Paragraph("Solid fill", SMALL_S), Paragraph("Strong / Effective contractions (desired in active labour)", SMALL_S)],
]
cont_tbl = Table(cont_data, colWidths=[CONTENT_W*0.25, CONTENT_W*0.17, CONTENT_W*0.18, CONTENT_W*0.40])
cont_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), colors.HexColor("#3D405B")),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("GRID", (0,0), (-1,-1), 0.4, GREY_LINE),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 4),
("VALIGN", (0,0), (-1,-1), "TOP"),
("BACKGROUND", (0,1), (-1,1), GREY_BG),
("BACKGROUND", (0,2), (-1,2), WHITE),
("BACKGROUND", (0,3), (-1,3), GREY_BG),
]))
story.append(cont_tbl)
story.append(Spacer(1, 5))
# ═══════════════════════════════════════════════════════════════════════════════
# RED FLAGS / DANGER SIGNS
# ═══════════════════════════════════════════════════════════════════════════════
story.append(section_header("⚠ RED FLAGS — Act Immediately", RED))
story.append(Spacer(1, 3))
flags = [
("FHR < 100 or > 180 bpm", "Fetal distress — change position, O₂, IV fluids, prepare for delivery"),
("Dilatation curve crosses ACTION line", "Augment or proceed to caesarean section NOW"),
("Moulding Grade 3+", "Fixed skull overlap — suspect cephalopelvic disproportion"),
("Thick meconium (Grade 3)", "Expedite delivery; NICU alert; suction at perineum"),
("Maternal BP ≥ 160/110 mmHg", "Severe hypertension — antihypertensives, consider MgSO₄"),
("Maternal temperature > 38°C", "Chorioamnionitis — antibiotics, senior review, may need delivery"),
("Proteinuria 2+ or more", "Pre-eclampsia screen — check reflexes, headache, visual changes"),
("Absent or very weak contractions + no progress","Consider augmentation; rule out obstruction before giving oxytocin"),
("Sudden severe pain between contractions", "Uterine rupture — EMERGENCY laparotomy"),
("Bleeding per vaginum (fresh blood)", "Placenta praevia / abruption — immediate senior review"),
]
flag_rows = [[
Paragraph("Red Flag", ps("rfh", fontSize=7.5, textColor=WHITE, fontName="Helvetica-Bold", leading=10)),
Paragraph("Immediate Response", ps("rfa", fontSize=7.5, textColor=WHITE, fontName="Helvetica-Bold", leading=10)),
]]
for f, a in flags:
flag_rows.append([
Paragraph(f"⚠ {f}", WARN_S),
Paragraph(a, BODY_S),
])
flag_tbl = Table(flag_rows, colWidths=[CONTENT_W*0.40, CONTENT_W*0.60])
flag_style = [
("BACKGROUND", (0,0), (-1,0), RED),
("GRID", (0,0), (-1,-1), 0.4, GREY_LINE),
("TOPPADDING", (0,0), (-1,-1), 2),
("BOTTOMPADDING", (0,0), (-1,-1), 2),
("LEFTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "TOP"),
]
for i in range(1, len(flag_rows)):
bg = RED_LT if i % 2 == 1 else WHITE
flag_style.append(("BACKGROUND", (0,i), (-1,i), bg))
flag_tbl.setStyle(TableStyle(flag_style))
story.append(flag_tbl)
story.append(Spacer(1, 5))
# ═══════════════════════════════════════════════════════════════════════════════
# STEP-BY-STEP WORKFLOW
# ═══════════════════════════════════════════════════════════════════════════════
story.append(section_header("STEP-BY-STEP WORKFLOW", TEAL))
story.append(Spacer(1, 3))
steps = [
("1", "ADMISSION ASSESSMENT",
"Confirm active labour (≥4-5 cm). Document gravida/para, EDD, vitals, membrane status, FHR, presentation."),
("2", "PLOT FIRST POINT",
"Place first X on the ALERT LINE at the current cervical dilatation. Note the time."),
("3", "EVERY 30 MINUTES",
"Auscultate FHR (during + after contraction). Count and shade contractions. Record pulse."),
("4", "EVERY 4 HOURS",
"Vaginal examination: cervical dilatation (X) + skull moulding + amniotic fluid. Abdominal palpation: descent of head (O). Record BP and temperature."),
("5", "CHECK THE CURVE",
"Is the dilatation curve to the LEFT of the Alert line? ✓ Good — continue. Has it crossed RIGHT of Alert? Reassess, consider transfer. Has it reached Action line? ACT NOW."),
("6", "DOCUMENT ALL INTERVENTIONS",
"Oxytocin rate, IV fluids, medications — write in the partograph in real time."),
("7", "SECOND STAGE",
"Switch to FHR every 5 min. Monitor maternal pushing effort. Document time of full dilatation and time of delivery."),
("8", "IMMEDIATE POSTPARTUM",
"Record time of placenta delivery, estimated blood loss, maternal vitals at 15 min and 1 hour postpartum."),
]
step_rows = []
for num, title, desc in steps:
step_rows.append([
Paragraph(num, ps("sn", fontSize=12, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER, leading=15)),
Paragraph(title, LABEL_S),
Paragraph(desc, SMALL_S),
])
step_tbl = Table(step_rows, colWidths=[0.7*cm, CONTENT_W*0.22, CONTENT_W*0.72])
step_style = [
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5),
("RIGHTPADDING", (0,0), (-1,-1), 5),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("GRID", (0,0), (-1,-1), 0.4, GREY_LINE),
]
for i, (num, _, _) in enumerate(steps):
bg = TEAL if i % 2 == 0 else TEAL_LT
step_style.append(("BACKGROUND", (0,i), (0,i), bg))
row_bg = colors.HexColor("#F0FAFA") if i % 2 == 0 else WHITE
step_style.append(("BACKGROUND", (1,i), (-1,i), row_bg))
step_tbl.setStyle(TableStyle(step_style))
story.append(step_tbl)
story.append(Spacer(1, 5))
# ═══════════════════════════════════════════════════════════════════════════════
# COMMON ERRORS
# ═══════════════════════════════════════════════════════════════════════════════
story.append(section_header("COMMON DOCUMENTATION ERRORS — Avoid These", ORANGE))
story.append(Spacer(1, 3))
errors = [
"Starting partograph in the latent phase (< 4 cm) — leads to unnecessary interventions",
"Not starting on the alert line — placing first X anywhere other than on the alert line",
"Auscultating FHR only between contractions — must listen during AND after",
"Confusing descent scale (0-5 fifths) with dilatation scale on the same graph",
"Failing to act when the alert line is crossed",
"Delaying VE once action line is reached",
"Omitting contraction duration from shading (just recording number, not duration)",
"Not documenting membrane rupture time — critical for infection risk calculation",
"Forgetting to update oxytocin dose changes in real time",
]
err_data = [[Paragraph("✗ " + e, BODY_S)] for e in errors]
err_tbl = Table(err_data, colWidths=[CONTENT_W])
err_style = [
("TOPPADDING", (0,0), (-1,-1), 2),
("BOTTOMPADDING", (0,0), (-1,-1), 2),
("LEFTPADDING", (0,0), (-1,-1), 8),
("GRID", (0,0), (-1,-1), 0.4, GREY_LINE),
]
for i in range(len(err_data)):
bg = AMBER_LT if i % 2 == 0 else WHITE
err_style.append(("BACKGROUND", (0,i), (-1,i), bg))
err_style.append(("TEXTCOLOR", (0,i), (-1,i), colors.HexColor("#7C2D12")))
err_tbl.setStyle(TableStyle(err_style))
story.append(err_tbl)
story.append(Spacer(1, 5))
# ═══════════════════════════════════════════════════════════════════════════════
# FOOTER
# ═══════════════════════════════════════════════════════════════════════════════
story.append(HRFlowable(width=CONTENT_W, thickness=0.5, color=GREY_LINE))
story.append(Spacer(1, 3))
footer_data = [[
Paragraph("Based on: WHO Labour Care Guide (2020) | MSF Essential Obstetric Care Guidelines | Park's Preventive & Social Medicine", FOOT_S),
Paragraph("For clinical reference only — always follow local institutional protocols", ps("fr", fontSize=6.5, textColor=RED, fontName="Helvetica-Oblique", alignment=TA_RIGHT, leading=9)),
]]
footer_tbl = Table(footer_data, colWidths=[CONTENT_W*0.65, CONTENT_W*0.35])
footer_tbl.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("LEFTPADDING", (0,0), (-1,-1), 0),
("TOPPADDING", (0,0), (-1,-1), 0),
]))
story.append(footer_tbl)
# ── Build ─────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF created: {OUTPUT}")
cd /home/daytona/workspace/partograph && python3 build_checklist.py 2>&1
ls -lh /home/daytona/workspace/partograph/Partograph_Checklist.pdf
Partograph Checklist
PDF Document · PDF
| Section | Contents |
|---|---|
| Header | Title banner with WHO/MSF reference |
| Before You Start | 5 admission checkboxes + Patient identifier fields (2-column layout) |
| Monitoring Frequency Table | All parameters (FHR, amniotic fluid, moulding, cervix, descent, contractions, BP, pulse, temp, urine, oxytocin) with symbol, frequency per stage, and normal range |
| Alert & Action Lines | Side-by-side tables: what each line means + required action |
| Skull Moulding Grades | Grade 0 to 3+ with colour-coded actions (green → red) |
| Meconium Grading | Grade 1 (thin) to Grade 3 (thick) with responses |
| Contraction Shading Key | Dotted / hatched / solid with duration and meaning |
| Red Flags | 10 danger signs with immediate responses (red background) |
| Step-by-Step Workflow | 8 numbered steps from admission through postpartum |
| Common Errors | 9 documentation mistakes to avoid (amber background) |
| Footer | Source citations + "for reference only" disclaimer |