Describe Sexually Transmitted Diseases with causative micro- organisms, pathology, clinical features, investigations and management. Shastra Karma in Stree Roga - Surgical Procedures in Gynaecology a. Sterilization methods of Instruments, Equipments and Labour - OT complex. b. Garbhashaya Mukha Vistrutikarana evam Lekhana (Dilatation & Curettage). c. Garbhashaya Mukha Dahana (cauterization). d. Vandhya karana (Sterilization) – Tubectomy & Vasectomy. e. Udaramarga Garbhashaya Nirharana (Abdominal hysterectomy). f. Yonimarga Garbhashaya Nirharana (Vaginal hysterectomy). g. Arbudanirharana (Myomectomy). h. Granthinirharana (Cystectomy). i. Arshanirharana (Polypectomy). Diagnostic Tools and Techniques a. Pap smear b. Colposcopy c. Cervical biopsy d. Endometrial biopsy e. Hysterosalpingography f. Ultrasonography g. Hysteroscopy h. Laparoscopyi. Magnetic Resonance Imaging j. Computed Tomography scan Dysmenorrhoea, Pruritus Vulvae, Endometriosis, Adenomyosis, Pelvic Inflammatory Diseases, f. Pelvic organ prolapse, Cervical erosion and Ectropion, Dyspareunia, Vaginismus, Presacral neuralgia, Constitutional nymphomania, Effluvium seminis - Causes, Clinical features, Investigations and Management For 20marks for exams Do Pdf
ls /home/daytona/workspace/ 2>/dev/null || echo "workspace empty or not found"
mkdir -p /home/daytona/workspace/gynaecology-notes
Send pdf
~/gynaecology-notes/gen_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.lib import colors
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, PageBreak, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
OUTPUT = "/home/daytona/workspace/gynaecology-notes/Gynaecology_Exam_Notes.pdf"
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=2*cm, rightMargin=2*cm,
topMargin=2.2*cm, bottomMargin=2.2*cm,
title="Gynaecology – 20 Mark Exam Notes",
author="Orris Medical"
)
styles = getSampleStyleSheet()
# Custom styles
TITLE = ParagraphStyle("Title", parent=styles["Title"], fontSize=18, textColor=colors.HexColor("#1a237e"),
spaceAfter=6, spaceBefore=4, alignment=TA_CENTER, fontName="Helvetica-Bold")
SUBTITLE = ParagraphStyle("Subtitle", parent=styles["Normal"], fontSize=11, textColor=colors.HexColor("#4a148c"),
spaceAfter=4, alignment=TA_CENTER, fontName="Helvetica-Oblique")
H1 = ParagraphStyle("H1", parent=styles["Heading1"], fontSize=13, textColor=colors.white,
backColor=colors.HexColor("#1a237e"), spaceBefore=12, spaceAfter=4,
leftIndent=-6, rightIndent=-6, fontName="Helvetica-Bold",
borderPad=4)
H2 = ParagraphStyle("H2", parent=styles["Heading2"], fontSize=11, textColor=colors.HexColor("#1a237e"),
spaceBefore=8, spaceAfter=3, fontName="Helvetica-Bold",
borderWidth=0, borderColor=colors.HexColor("#1a237e"))
H3 = ParagraphStyle("H3", parent=styles["Heading3"], fontSize=10, textColor=colors.HexColor("#4a148c"),
spaceBefore=6, spaceAfter=2, fontName="Helvetica-Bold")
BODY = ParagraphStyle("Body", parent=styles["Normal"], fontSize=9.5, leading=14,
spaceAfter=3, alignment=TA_JUSTIFY, fontName="Helvetica")
BULLET = ParagraphStyle("Bullet", parent=styles["Normal"], fontSize=9.5, leading=13,
leftIndent=14, firstLineIndent=-10, spaceAfter=2,
bulletIndent=4, fontName="Helvetica")
TABLE_H = ParagraphStyle("TableH", parent=styles["Normal"], fontSize=9, fontName="Helvetica-Bold",
textColor=colors.white, alignment=TA_CENTER)
TABLE_B = ParagraphStyle("TableB", parent=styles["Normal"], fontSize=8.5, fontName="Helvetica", leading=11)
FOOTER_NOTE = ParagraphStyle("Footer", parent=styles["Normal"], fontSize=8, textColor=colors.grey,
alignment=TA_CENTER, fontName="Helvetica-Oblique")
def h1(text): return Paragraph(f" {text}", H1)
def h2(text): return Paragraph(text, H2)
def h3(text): return Paragraph(text, H3)
def p(text): return Paragraph(text, BODY)
def b(text): return Paragraph(f"• {text}", BULLET)
def sp(n=1): return Spacer(1, n*0.3*cm)
def hr(): return HRFlowable(width="100%", thickness=0.5, color=colors.HexColor("#1a237e"), spaceAfter=4, spaceBefore=2)
def make_table(headers, rows, col_widths=None):
data = [[Paragraph(h, TABLE_H) for h in headers]]
for row in rows:
data.append([Paragraph(str(c), TABLE_B) for c in row])
if col_widths is None:
col_widths = [None]*len(headers)
t = Table(data, colWidths=col_widths, hAlign='LEFT')
t.setStyle(TableStyle([
('BACKGROUND', (0,0), (-1,0), colors.HexColor("#1a237e")),
('TEXTCOLOR', (0,0), (-1,0), colors.white),
('ROWBACKGROUNDS', (0,1), (-1,-1), [colors.HexColor("#e8eaf6"), colors.white]),
('GRID', (0,0), (-1,-1), 0.4, colors.HexColor("#90caf9")),
('VALIGN', (0,0), (-1,-1), 'TOP'),
('TOPPADDING', (0,0), (-1,-1), 3),
('BOTTOMPADDING', (0,0), (-1,-1), 3),
('LEFTPADDING', (0,0), (-1,-1), 4),
('RIGHTPADDING', (0,0), (-1,-1), 4),
]))
return t
story = []
# ─── COVER ───────────────────────────────────────────────────────────────────
story += [
sp(4),
Paragraph("GYNAECOLOGY", TITLE),
Paragraph("20-Mark Exam Notes", SUBTITLE),
Paragraph("Covering: STDs • Shastra Karma (Surgical Procedures) • Diagnostic Tools • Gynaecological Conditions", SUBTITLE),
sp(1),
hr(),
sp(1),
Paragraph("Prepared for Ayurveda / BAMS / MS (Ayurveda) – Stree Roga & Prasuti Tantra", FOOTER_NOTE),
PageBreak()
]
# ═══════════════════════════════════════════════════════════
# SECTION 1: STDs
# ═══════════════════════════════════════════════════════════
story += [h1("SECTION 1: SEXUALLY TRANSMITTED DISEASES (STDs)"), sp()]
story += [
p("Sexually transmitted diseases (STDs) — also called sexually transmitted infections (STIs) — are infections passed from person to person primarily through sexual contact. They are a major global public health problem and can cause serious reproductive, neonatal, and systemic morbidity."),
sp(),
h2("Classification of STDs"),
make_table(
["Category", "Diseases"],
[
["Bacterial", "Gonorrhoea, Syphilis, Chancroid, Chlamydia, Granuloma Inguinale (Donovanosis), LGV"],
["Viral", "Herpes Genitalis (HSV-1/2), HIV/AIDS, HPV (Genital warts), Hepatitis B, Molluscum Contagiosum"],
["Protozoal", "Trichomoniasis (Trichomonas vaginalis)"],
["Fungal", "Vulvovaginal Candidiasis (Candida albicans)"],
["Parasitic", "Pubic Lice (Phthirus pubis), Scabies (Sarcoptes scabiei)"],
],
col_widths=[4*cm, 12*cm]
),
sp(),
]
# STD Table: Causative organism, pathology, clinical, investigations, management
story += [
h2("1. GONORRHOEA"),
h3("Causative Organism:"),
p("Neisseria gonorrhoeae — Gram-negative intracellular diplococcus. Infects columnar and transitional epithelium."),
h3("Pathology:"),
p("Attaches via pili to columnar epithelium → endocytosis → submucosal spread → acute purulent inflammation → neutrophilic infiltrate → if untreated, fibrosis and stricture. In females: endocervicitis, salpingitis, PID. In males: urethritis, epididymitis."),
h3("Clinical Features:"),
b("<b>Females:</b> Often asymptomatic (up to 80%); purulent/mucopurulent vaginal discharge, dysuria, intermenstrual bleeding, pelvic pain, cervicitis (friable, red cervix)."),
b("<b>Males:</b> Urethral discharge (yellowish-green, profuse), dysuria, frequency. Complications: epididymo-orchitis, urethral stricture."),
b("<b>Disseminated gonococcal infection (DGI):</b> Arthritis, dermatitis, rarely endocarditis/meningitis."),
b("<b>Neonatal ophthalmia neonatorum:</b> Purulent conjunctivitis, if untreated → corneal ulceration, blindness."),
h3("Investigations:"),
b("Gram stain of discharge: Gram-negative intracellular diplococci within PMNs (sensitivity ~70% female, ~90% male)."),
b("Culture: Thayer-Martin/chocolate agar — definitive; antibiotic sensitivity testing."),
b("NAAT (Nucleic Acid Amplification Test): Most sensitive and specific; first-void urine, swab."),
b("ELISA / Immunochromatographic tests: Rapid bedside tests."),
h3("Management:"),
b("<b>Uncomplicated urogenital:</b> Ceftriaxone 500 mg IM single dose + Azithromycin 1 g oral (or Doxycycline 100 mg BD × 7 days for chlamydial co-infection)."),
b("<b>Disseminated:</b> Ceftriaxone 1 g IV/IM daily × 7 days."),
b("<b>Ophthalmia neonatorum prophylaxis:</b> 1% silver nitrate / erythromycin eye ointment at birth."),
b("Partner notification and treatment; condom use counselling."),
sp(),
]
story += [
h2("2. SYPHILIS"),
h3("Causative Organism:"),
p("Treponema pallidum — thin, motile, corkscrew-shaped spirochaete. Cannot be cultured in vitro."),
h3("Pathology:"),
p("Obliterative endarteritis of small vessels (hallmark) with perivascular lymphoplasmacytic infiltrate. Gumma formation (tertiary). Congenital syphilis via transplacental transmission after 16th week."),
h3("Clinical Features — Stages:"),
b("<b>Primary:</b> Painless, indurated chancre at site of inoculation (genitalia, anus, lip) + painless regional lymphadenopathy. Heals in 3–6 weeks."),
b("<b>Secondary (6–8 weeks later):</b> Maculopapular rash (including palms and soles), condylomata lata, mucous patches, generalised lymphadenopathy, snail-track ulcers, alopecia."),
b("<b>Latent:</b> Asymptomatic (early <2 yr; late >2 yr). Seroreactive only."),
b("<b>Tertiary (years later):</b> Gummas (skin, bone, liver), cardiovascular syphilis (aortitis, aortic regurgitation, aortic aneurysm), neurosyphilis (tabes dorsalis, general paralysis of insane — GPI)."),
b("<b>Congenital:</b> Stillbirth, hydrops fetalis, saddle-nose deformity, interstitial keratitis, Hutchinson's teeth, sabre tibia, deafness (Hutchinson's triad)."),
h3("Investigations:"),
b("<b>Direct:</b> Dark-field microscopy of chancre exudate (spirochaetes seen)."),
b("<b>Non-treponemal (screening):</b> VDRL, RPR — titre reflects disease activity; used to monitor treatment (4-fold fall = adequate response)."),
b("<b>Treponemal (confirmatory):</b> TPHA, FTA-ABS, TPPA — remain positive lifelong."),
b("CSF VDRL for neurosyphilis; PCR; IgM ELISA for congenital."),
h3("Management:"),
b("<b>Primary/Secondary/Early latent (<1 yr):</b> Benzathine penicillin G 2.4 million units IM single dose."),
b("<b>Late latent/Tertiary:</b> Benzathine penicillin G 2.4 MU IM weekly × 3 doses."),
b("<b>Neurosyphilis:</b> Aqueous crystalline penicillin G 18–24 MU/day IV × 10–14 days."),
b("<b>Penicillin allergy:</b> Doxycycline 100 mg BD × 14 days (not in pregnancy — use penicillin desensitisation)."),
b("Jarisch-Herxheimer reaction: Fever, chills, myalgia 2–8 hrs after 1st penicillin dose — treat with antipyretics."),
sp(),
]
story += [
h2("3. CHLAMYDIA"),
h3("Causative Organism:"),
p("Chlamydia trachomatis — obligate intracellular bacterium. Serovars D–K cause genital infections; L1–L3 cause Lymphogranuloma Venereum (LGV); A–C cause trachoma."),
h3("Pathology:"),
p("Infects columnar epithelium → intracellular replication in inclusions → cell death → mucosal inflammation → scarring of fallopian tubes → infertility, ectopic pregnancy."),
h3("Clinical Features:"),
b("<b>Females (often asymptomatic ~70%):</b> Mucopurulent cervicitis, urethritis (dysuria, frequency), PID (salpingitis, endometritis), perihepatitis (Fitz-Hugh-Curtis syndrome)."),
b("<b>Males:</b> Non-gonococcal urethritis, epididymitis, Reiter's syndrome (urethritis + arthritis + uveitis)."),
b("<b>LGV:</b> Painless primary genital ulcer → painful inguinal lymphadenopathy (buboes) → ulceration, fistulae, rectal stricture."),
h3("Investigations:"),
b("NAAT (swab/urine) — gold standard; highest sensitivity."),
b("Cell culture — reference standard but impractical."),
b("Direct immunofluorescence (DIF), ELISA — less sensitive."),
h3("Management:"),
b("<b>Uncomplicated:</b> Doxycycline 100 mg BD × 7 days OR Azithromycin 1 g single dose."),
b("<b>Pregnancy:</b> Azithromycin 1 g single dose OR Amoxicillin 500 mg TDS × 7 days."),
b("<b>LGV:</b> Doxycycline 100 mg BD × 21 days."),
sp(),
]
story += [
h2("4. CHANCROID"),
h3("Causative Organism:"), p("Haemophilus ducreyi — small Gram-negative coccobacillus."),
h3("Clinical Features:"),
b("Painful soft ulcer with ragged, undermined edges on genitalia (contrast with painless syphilitic chancre)."),
b("Tender inguinal lymphadenopathy (bubo) — may suppurate."),
b("'School of fish' arrangement on Gram stain."),
h3("Management:"), b("Azithromycin 1 g single dose OR Ceftriaxone 250 mg IM single dose OR Ciprofloxacin 500 mg BD × 3 days."),
sp(),
]
story += [
h2("5. GRANULOMA INGUINALE (DONOVANOSIS)"),
h3("Causative Organism:"), p("Klebsiella granulomatis (formerly Calymmatobacterium granulomatis)."),
h3("Pathology:"), p("Donovan bodies seen in large mononuclear cells (macrophages) — encapsulated rod-shaped organisms."),
h3("Clinical Features:"),
b("Painless, progressive, beefy-red granulomatous ulcer on genitalia — bleeds on contact."),
b("No significant lymphadenopathy (unlike LGV)."),
b("Pseudo-bubo: subcutaneous granuloma in inguinal region."),
h3("Investigations:"), b("Crush preparation / tissue biopsy: Donovan bodies in Wright-Giemsa stain."),
h3("Management:"), b("Doxycycline 100 mg BD × ≥3 weeks; continue until complete healing. Alternatives: Azithromycin, Cotrimoxazole."),
sp(),
]
story += [
h2("6. HERPES GENITALIS"),
h3("Causative Organism:"), p("Herpes Simplex Virus — HSV-2 (most common, genital); HSV-1 (increasingly causing genital herpes). DNA virus, latency in sacral ganglia (S2–S4)."),
h3("Pathology:"), p("Viral replication in epithelial cells → balloon degeneration → multinucleated giant cells → intranuclear inclusions (Cowdry type A) → vesicle formation."),
h3("Clinical Features:"),
b("<b>Primary attack:</b> Multiple painful vesicles → erosions/ulcers on vulva, vagina, cervix, perineum; fever, malaise, inguinal lymphadenopathy; urinary retention possible."),
b("<b>Recurrent:</b> Milder; prodrome of tingling/burning. Triggered by stress, menstruation, immunosuppression."),
b("<b>Neonatal herpes:</b> Life-threatening — disseminated disease, encephalitis, skin/eye/mouth involvement."),
h3("Investigations:"),
b("Tzanck smear: Multinucleated giant cells (not specific)."),
b("Viral culture / PCR: Gold standard."),
b("Direct fluorescent antibody (DFA), serology (type-specific IgG: HSV-1, HSV-2)."),
h3("Management:"),
b("<b>Primary:</b> Acyclovir 200 mg 5×/day × 10 days OR Valacyclovir 1 g BD × 10 days."),
b("<b>Recurrent:</b> Acyclovir 400 mg TDS × 5 days OR suppressive Valacyclovir 500 mg OD."),
b("<b>Neonatal:</b> IV Acyclovir 20 mg/kg/dose 8-hourly × 14–21 days."),
b("Caesarean section if active genital lesions at term — prevents neonatal transmission."),
sp(),
]
story += [
h2("7. HIV / AIDS"),
h3("Causative Organism:"), p("Human Immunodeficiency Virus (HIV-1, HIV-2) — Retrovirus. Targets CD4+ T-helper lymphocytes, macrophages, dendritic cells."),
h3("Pathology:"), p("HIV binds CD4 receptor + co-receptors (CCR5, CXCR4) → reverse transcriptase → integration into host genome as provirus → replication → CD4 cell depletion → immunodeficiency → AIDS (CD4 <200/μL or AIDS-defining illness)."),
h3("Clinical Features (WHO Stages):"),
b("<b>Stage 1 (Asymptomatic / Acute HIV):</b> Seroconversion illness (2–6 wks post-exposure) — fever, pharyngitis, lymphadenopathy, rash, myalgia."),
b("<b>Stage 2:</b> Minor weight loss (<10%), herpes zoster, recurrent URTI, oral ulcers."),
b("<b>Stage 3:</b> Severe weight loss (>10%), chronic diarrhoea >1 month, oral candidiasis, TB, severe bacterial infections."),
b("<b>Stage 4 (AIDS):</b> PCP, cryptococcal meningitis, CMV retinitis, Kaposi's sarcoma, cerebral toxoplasmosis, HIV encephalopathy."),
h3("Investigations:"),
b("ELISA (screening) → Western Blot (confirmatory). Window period: 3–4 weeks (4th gen tests detect p24 antigen earlier)."),
b("CD4 count (immunological status), HIV RNA viral load (treatment monitoring)."),
b("NAAT / p24 antigen assay: Early diagnosis."),
h3("Management:"),
b("<b>ART (Antiretroviral Therapy):</b> All HIV+ patients regardless of CD4. First-line: 2 NRTIs + 1 NNRTI or INSTI (e.g., TDF + 3TC + DTG)."),
b("<b>PrEP:</b> TDF/FTC daily for high-risk HIV-negative individuals."),
b("<b>PEP:</b> Within 72 hours of exposure; 28-day course of ART."),
b("OI prophylaxis: Co-trimoxazole (CD4 <200), Fluconazole, INH (TB prophylaxis if CD4 <350 in endemic areas)."),
sp(),
]
story += [
h2("8. TRICHOMONIASIS"),
h3("Causative Organism:"), p("Trichomonas vaginalis — flagellated protozoan. Only infects the genitourinary tract."),
h3("Clinical Features:"),
b("<b>Females:</b> Frothy, yellow-green, malodorous vaginal discharge; pruritus vulvae; 'strawberry cervix' (punctate haemorrhages)."),
b("<b>Males:</b> Usually asymptomatic; urethritis, prostatitis."),
h3("Investigations:"),
b("Wet mount microscopy: Motile trichomonads (pear-shaped, flagellated)."),
b("Culture (Diamond's medium) — gold standard. NAAT — highest sensitivity."),
b("Vaginal pH: >4.5."),
h3("Management:"), b("Metronidazole 2 g oral single dose OR 400–500 mg BD × 7 days. Treat partner simultaneously. Avoid alcohol (disulfiram-like reaction)."),
sp(),
]
story += [
h2("9. GENITAL WARTS (CONDYLOMATA ACUMINATA)"),
h3("Causative Organism:"), p("Human Papillomavirus (HPV) — DNA virus. Types 6 & 11 cause genital warts (low risk); Types 16, 18, 31, 33 cause cervical/anogenital cancers (high risk)."),
h3("Clinical Features:"), b("Soft, fleshy, cauliflower-like growths on vulva, vagina, cervix, perineum, anus."),
b("Usually asymptomatic; may cause pruritus, discharge, bleeding."),
h3("Investigations:"), b("Clinical diagnosis (aceto-white test with 5% acetic acid). Colposcopy + biopsy if uncertain. PCR for HPV typing."),
h3("Management:"),
b("<b>Medical:</b> Podophyllin 25% (applied by physician); Imiquimod 5% cream (self-applied); Trichloroacetic acid (TCA) 80–90%."),
b("<b>Physical:</b> Cryotherapy, electrocautery, laser ablation, surgical excision."),
b("<b>Prevention:</b> HPV vaccines: Bivalent (16,18), Quadrivalent (6,11,16,18), Nonavalent (9 types). Recommended 9–26 years."),
sp(),
PageBreak(),
]
# ═══════════════════════════════════════════════════════════
# SECTION 2: SHASTRA KARMA
# ═══════════════════════════════════════════════════════════
story += [h1("SECTION 2: SHASTRA KARMA IN STREE ROGA — SURGICAL PROCEDURES IN GYNAECOLOGY"), sp()]
story += [
h2("a. Sterilization of Instruments, Equipment and OT Complex"),
h3("Definition:"),
p("Sterilization is the complete destruction or removal of ALL forms of microbial life, including spores. Disinfection reduces microbial load but may not eliminate spores."),
h3("Methods of Sterilization:"),
make_table(
["Method", "Agent/Technique", "Application", "Temp/Time"],
[
["Autoclaving (Steam)", "Saturated steam under pressure", "Surgical instruments, linen, drapes", "121°C/15 psi/20 min OR 134°C/30 psi/3 min"],
["Dry Heat Oven", "Hot air", "Glassware, oils, powders, sharp instruments", "160°C/1 hr OR 180°C/30 min"],
["Ethylene Oxide (ETO)", "Chemical gas", "Heat-sensitive equipment: endoscopes, plastics, electronics", "Room temp; 4–12 hrs cycle"],
["Glutaraldehyde (2%)", "Chemical liquid", "Endoscopes, instruments with lenses", "20 min (disinfection); 10 hr (sterilization)"],
["Plasma Sterilization", "Hydrogen peroxide plasma", "Heat/moisture-sensitive instruments", "~45°C; 50–75 min"],
["UV Radiation", "UV light (254 nm)", "OT air, surfaces", "Surface decontamination only"],
["Boiling", "Boiling water (100°C)", "Low-level; not for spores", "20 min (not true sterilization)"],
],
col_widths=[3.5*cm, 3.5*cm, 5*cm, 4.5*cm]
),
sp(),
h3("OT (Operation Theatre) Sterility:"),
b("Positive pressure ventilation in OT (prevents entry of outside air)."),
b("HEPA filters; laminar airflow in high-risk areas."),
b("Regular fumigation: Formaldehyde vapour / OT fumigants."),
b("Surgical scrub: Betadine / chlorhexidine; sterile gloves, gowns, drapes."),
b("Labour room: Clean technique; sterile instruments for delivery."),
sp(),
]
story += [
h2("b. Garbhashaya Mukha Vistrutikarana evam Lekhana — Dilatation & Curettage (D&C)"),
h3("Definition:"),
p("D&C is a surgical procedure in which the cervix is dilated and the uterine cavity is evacuated/scraped using a curette."),
h3("Indications:"),
b("Diagnostic: Abnormal uterine bleeding, postmenopausal bleeding, suspected endometrial pathology, endometrial sampling."),
b("Therapeutic: Incomplete/missed abortion, evacuation of retained products of conception (ERPC), hydatidiform mole removal."),
h3("Contraindications:"),
b("Active pelvic infection (relative), cervical carcinoma (diagnostic curettage is acceptable), coagulopathy (correct first)."),
h3("Procedure:"),
b("Patient in lithotomy position under general/spinal/paracervical anaesthesia."),
b("Bimanual examination to assess uterine size/position."),
b("Cervix exposed with Sims speculum; anterior lip held with Allis/vulsellum forceps."),
b("Uterine sound — to measure cavity length and determine uterine axis."),
b("Cervix dilated with Hegar dilators (progressively from smallest: 1→2→3...→8–10 mm)."),
b("Curettage with sharp or suction curette; tissue sent for histopathology."),
h3("Complications:"),
b("Uterine perforation (most serious), cervical laceration, haemorrhage."),
b("Asherman's syndrome (intrauterine adhesions — synechiae) from overzealous curettage."),
b("Infection, cervical incompetence (repeated dilations)."),
sp(),
]
story += [
h2("c. Garbhashaya Mukha Dahana — Cervical Cauterization"),
h3("Definition:"),
p("Application of heat/chemical energy to destroy abnormal or chronically inflamed cervical epithelium."),
h3("Types:"),
b("<b>Electrocoagulation/Electrocautery:</b> Thermal destruction of columnar epithelium; used for cervical erosion, ectropion, chronic cervicitis."),
b("<b>Cryocauterization:</b> Liquid nitrogen (-20 to -30°C) freezes and destroys abnormal cells; used for CIN 1/2, erosion."),
b("<b>Laser Vaporization (CO₂ laser):</b> Precise ablation of transformation zone; for CIN lesions."),
b("<b>LEEP/LLETZ (Loop Electrosurgical Excision Procedure):</b> Excision of transformation zone using a loop electrode; provides histological specimen — preferred for CIN 2/3."),
b("<b>Trichloroacetic acid (TCA):</b> Chemical cauterization for condylomata."),
h3("Indications:"), b("Cervical erosion/ectropion with symptoms, CIN 1–3 (non-invasive lesions), chronic cervicitis unresponsive to medical treatment, genital warts on cervix."),
h3("Complications:"), b("Discharge (watery), cramping, infection, cervical stenosis, secondary haemorrhage."),
sp(),
]
story += [
h2("d. Vandhya Karana — Sterilization: Tubectomy & Vasectomy"),
h3("TUBECTOMY (Female Sterilization)"),
p("Permanent contraception by occluding / severing the fallopian tubes, preventing sperm from reaching the ovum."),
h3("Methods:"),
b("<b>Pomeroy's Method (most common):</b> A loop of tube is ligated and excised. Simple, effective, reversible attempts possible."),
b("<b>Parkland Method:</b> A segment of the isthmic portion is excised after ligating both ends separately."),
b("<b>Fimbriectomy:</b> Removal of fimbriated end — high failure and no reversal."),
b("<b>Irving's Method:</b> Proximal tube end buried in myometrium — lowest failure rate."),
b("<b>Uchida's Method:</b> Tube injected with saline + adrenaline; mesosalpinx opened; tube buried under serosa."),
b("<b>Laparoscopic sterilization:</b> Falope ring (Silastic band), Filshie/Hulka clip, or bipolar coagulation through laparoscope — minimally invasive, preferred."),
b("<b>Minilaparotomy:</b> Small suprapubic incision; postpartum (subumbilical incision) — common in resource-limited settings."),
b("<b>Failure rate:</b> 0.2–0.5% (1–5/1000 women-years). Risk of ectopic pregnancy if failure."),
h3("VASECTOMY (Male Sterilization)"),
p("Division and ligation/excision of a segment of the vas deferens — prevents sperm from entering the ejaculate."),
b("<b>Conventional vasectomy:</b> Two small scrotal incisions; vas identified, ligated, and a segment excised."),
b("<b>No-scalpel vasectomy (NSV):</b> Puncture technique with special forceps — less bleeding, fewer complications, faster recovery. <b>Preferred method.</b>"),
b("<b>Failure rate:</b> ~0.1%; confirm azoospermia by semen analysis at 3 months / after 20 ejaculations."),
b("<b>Complications:</b> Haematoma, infection, sperm granuloma, epididymitis; post-vasectomy pain syndrome (rare)."),
sp(),
]
story += [
h2("e. Udaramarga Garbhashaya Nirharana — Abdominal Hysterectomy"),
h3("Definition:"), p("Surgical removal of the uterus through an abdominal incision (midline or Pfannenstiel). Can be Total (TAH — uterus + cervix) or Subtotal (corpus removed, cervix retained)."),
h3("Indications:"),
b("Fibroid uterus (symptomatic — heavy bleeding, pressure), Endometriosis, Adenomyosis."),
b("Dysfunctional Uterine Bleeding (DUB) unresponsive to medical therapy."),
b("Genital prolapse, Endometrial hyperplasia/carcinoma, Cervical carcinoma (radical hysterectomy — Wertheim's)."),
b("PID with tubo-ovarian abscess unresponsive to antibiotics."),
h3("Procedure (TAH-BSO):"),
b("Patient in supine; Pfannenstiel or midline incision."),
b("Round ligaments divided; bladder flap dissected down; uterine vessels ligated; cardinal and uterosacral ligaments divided."),
b("Vault sutured; bilateral salpingo-oophorectomy (BSO) if indicated."),
b("Wertheim's radical hysterectomy (for cervical Ca): includes parametrium, upper vagina, pelvic lymph node dissection."),
h3("Complications:"),
b("<b>Intraoperative:</b> Haemorrhage, ureteric injury (at level of uterine artery — most common), bladder injury."),
b("<b>Postoperative:</b> DVT/PE, infection, vault haematoma, vault prolapse, urinary fistula."),
b("<b>Long-term:</b> Premature menopause (if oophorectomy), sexual dysfunction."),
sp(),
]
story += [
h2("f. Yonimarga Garbhashaya Nirharana — Vaginal Hysterectomy"),
h3("Definition:"), p("Removal of the uterus through the vagina without an abdominal incision. Combined with anterior/posterior colporrhaphy when performed for prolapse."),
h3("Indications:"),
b("Uterovaginal prolapse (ideal indication)."),
b("Benign conditions (fibroids if uterus <12 weeks), DUB, endometrial hyperplasia."),
b("Manchester (Fothergill) operation: Cervical amputation + colporrhaphy for uterine descent without hysterectomy."),
h3("Advantages over Abdominal Hysterectomy:"),
b("No abdominal incision; less pain; shorter hospital stay; faster recovery; lower infection risk."),
h3("Contraindications:"),
b("Large uterus (>12 weeks), nulliparity (narrow vagina), prior pelvic surgery (adhesions), suspected malignancy, adnexal pathology."),
h3("Complications:"),
b("Bladder/ureteric injury, haemorrhage, infection, vault prolapse, enterocele formation."),
sp(),
]
story += [
h2("g. Arbudanirharana — Myomectomy"),
h3("Definition:"), p("Surgical removal of uterine fibroids (leiomyomas) while preserving the uterus — procedure of choice in women wishing to retain fertility."),
h3("Indications:"),
b("Symptomatic fibroids (heavy bleeding, pressure symptoms, pain) in women desiring fertility."),
b("Infertility due to submucous fibroids distorting the uterine cavity."),
b("Recurrent pregnancy loss associated with fibroids."),
h3("Types:"),
b("<b>Open (abdominal) myomectomy:</b> For large/multiple/deep intramural fibroids."),
b("<b>Laparoscopic myomectomy:</b> For subserosal/pedunculated fibroids; minimally invasive."),
b("<b>Hysteroscopic myomectomy:</b> For submucous fibroids (Types 0, 1, 2 — FIGO classification)."),
h3("Complications:"),
b("Haemorrhage (major risk — may require transfusion), conversion to hysterectomy."),
b("Adhesion formation (risk of infertility/bowel obstruction), recurrence of fibroids (~25–30% by 10 years)."),
b("Uterine rupture in subsequent pregnancy (especially with deep intramural scar)."),
sp(),
]
story += [
h2("h. Granthinirharana — Cystectomy (Ovarian Cystectomy)"),
h3("Definition:"), p("Surgical excision of an ovarian cyst while preserving ovarian tissue. 'Cystectomy' in gynaecology usually refers to ovarian cystectomy (not bladder surgery)."),
h3("Indications:"),
b("Persistent ovarian cysts >5 cm not resolving after 6–8 weeks observation."),
b("Cysts with features of concern (solid components, septations, vascularity on Doppler)."),
b("Dermoid cysts (mature cystic teratoma), endometrioma (chocolate cyst)."),
b("Symptomatic cysts (pain, pressure, torsion)."),
h3("Types:"),
b("<b>Laparoscopic cystectomy:</b> Preferred approach; cyst wall stripped from ovarian cortex."),
b("<b>Open cystectomy:</b> For large/complex cysts."),
b("If malignancy suspected: unilateral salpingo-oophorectomy (USO); do NOT rupture cyst."),
h3("Complications:"), b("Haemorrhage, infection, ovarian cortex damage (reduces ovarian reserve), cyst rupture (chemical peritonitis from dermoid contents — sebum + hair)."),
sp(),
]
story += [
h2("i. Arshanirharana — Polypectomy"),
h3("Definition:"), p("Surgical removal of polyps from the uterine cavity (endometrial polyps), cervix (cervical polyps), or vagina."),
h3("Cervical Polypectomy:"),
b("Usually done OPD under no/local anaesthesia."),
b("Polyp identified at cervical os; grasped with sponge-holding forceps and twisted off at its base; base cauterized."),
b("Histopathology mandatory (rule out malignancy)."),
h3("Endometrial Polypectomy:"),
b("Hysteroscopic polypectomy under direct vision — gold standard."),
b("Resectoscope loop or scissors used to excise polyp at base."),
b("Complete excision reduces recurrence; histopathology of all specimens."),
h3("Indications:"), b("Abnormal uterine bleeding, intermenstrual bleeding, postmenopausal bleeding, infertility, incidental finding on USS/HSG."),
h3("Complications:"), b("Uterine perforation (hysteroscopic), fluid overload (operative hysteroscopy), bleeding, infection."),
sp(),
PageBreak(),
]
# ═══════════════════════════════════════════════════════════
# SECTION 3: DIAGNOSTIC TOOLS
# ═══════════════════════════════════════════════════════════
story += [h1("SECTION 3: DIAGNOSTIC TOOLS AND TECHNIQUES"), sp()]
story += [
h2("a. Pap Smear (Papanicolaou Smear)"),
p("<b>Purpose:</b> Cervical cancer screening — detects premalignant (CIN) and malignant cervical cells."),
b("<b>Specimen:</b> Ectocervical scrape (Ayre's spatula) + endocervical swab (cytobrush) → smear fixed with 95% ethyl alcohol → Papanicolaou stain."),
b("<b>Liquid-Based Cytology (LBC/ThinPrep):</b> Cell suspension in preservative fluid; more sensitive, allows HPV co-testing."),
b("<b>Bethesda System (reporting):</b> ASC-US, LSIL, HSIL, ASC-H, AGC, adenocarcinoma in situ, invasive carcinoma."),
b("<b>Screening protocol (India/WHO):</b> Every 3 years from age 25 (or 3 years after first sexual activity). Combined HPV + cytology every 5 years if both negative."),
b("<b>False negatives:</b> ~20% (sampling error, interpretive error); reduced by LBC."),
sp(),
]
story += [
h2("b. Colposcopy"),
p("<b>Definition:</b> Direct binocular magnified (6–40×) examination of the cervix, vagina, and vulva using a colposcope, following application of 3–5% acetic acid and Lugol's iodine."),
b("<b>Indications:</b> Abnormal Pap smear (HSIL, persistent LSIL, ASC-H, AGC), positive hrHPV, clinically suspicious cervix, follow-up post-treatment of CIN."),
b("<b>Aceto-white changes:</b> Abnormal areas turn white with acetic acid — reflect nuclear density."),
b("<b>Schiller's test (Lugol's iodine):</b> Normal glycogen-rich epithelium stains brown (iodine-positive); abnormal areas remain unstained (iodine-negative = Schiller-positive)."),
b("<b>Colposcopic features of CIN:</b> Acetowhite epithelium, abnormal vascular patterns (punctation, mosaic), coarse surface contour."),
b("<b>Outcome:</b> Directed biopsy from most abnormal area; endocervical curettage (ECC) if transformation zone not fully visualised (unsatisfactory colposcopy)."),
sp(),
]
story += [
h2("c. Cervical Biopsy"),
b("<b>Punch biopsy:</b> Colposcopy-directed; small cores taken from abnormal areas."),
b("<b>LEEP/LLETZ cone biopsy:</b> Loop electrosurgical excision — therapeutic and diagnostic; includes transformation zone."),
b("<b>Cold knife conisation (CKC):</b> Surgical cone excision for endocervical lesions, micro-invasive carcinoma, or unsatisfactory colposcopy."),
b("<b>Histological grading:</b> CIN 1 (mild dysplasia), CIN 2 (moderate), CIN 3 (severe/CIS) → FIGO classification for carcinoma."),
sp(),
]
story += [
h2("d. Endometrial Biopsy"),
b("<b>Indications:</b> Postmenopausal bleeding, AUB unresponsive to treatment, suspected endometrial hyperplasia/carcinoma, infertility workup (secretory phase/luteal phase defect)."),
b("<b>Methods:</b> Pipelle aspirator (OPD, no anaesthesia — sensitivity ~80%); Vabra aspirator; fractional curettage (ECC + uterine curettage separately, to determine level of spread)."),
b("<b>Histology:</b> Confirms normal cycling endometrium, simple/complex hyperplasia (with/without atypia), or carcinoma."),
sp(),
]
story += [
h2("e. Hysterosalpingography (HSG)"),
p("<b>Definition:</b> Radiological investigation using water-soluble/oil-based contrast medium injected through the cervix into the uterine cavity and tubes, imaged under fluoroscopy."),
b("<b>Indications:</b> Infertility (tubal patency assessment), recurrent pregnancy loss (uterine anomalies — septum, bicornuate, fibroids, adhesions), suspected tubal block (PID sequelae)."),
b("<b>Findings:</b> Tubal patency (bilateral peritoneal spill), cornual block, hydrosalpinx, intrauterine filling defects (polyp, fibroid, Asherman's), uterine anomalies."),
b("<b>Complications:</b> Pelvic infection (prophylactic doxycycline recommended), contrast reaction, radiation exposure. <b>Contraindicated</b> in active PID, pregnancy, iodine allergy."),
b("<b>Best timing:</b> Days 7–10 of cycle (post-menstrual, pre-ovulatory — uterine lining thin, no risk of irradiating early pregnancy)."),
sp(),
]
story += [
h2("f. Ultrasonography (USG)"),
b("<b>Transabdominal USG (TAS):</b> Full bladder required; good for large uterus/ovaries, abdominal masses; limited resolution."),
b("<b>Transvaginal USG (TVS):</b> Empty bladder; superior resolution for endometrium, ovaries, early pregnancy, small fibroids. Preferred for gynaecological pathology."),
b("<b>Uses:</b> Endometrial thickness (ET >4 mm in postmenopause → biopsy), fibroid mapping, ovarian cysts, adnexal pathology, IUCD position, folliculometry, Doppler studies."),
b("<b>Sonohysterography (SIS):</b> Saline infused into uterine cavity under USS — outlines intracavitary lesions."),
b("<b>Doppler:</b> Colour/pulsed Doppler for vascularity of ovarian masses; low resistance index (RI <0.4) suggests malignancy."),
sp(),
]
story += [
h2("g. Hysteroscopy"),
p("<b>Definition:</b> Direct endoscopic visualisation of the uterine cavity using a rigid/flexible hysteroscope with distension medium (normal saline, glycine)."),
b("<b>Diagnostic hysteroscopy:</b> Outpatient; 3.5–5 mm hysteroscope; evaluates endometrium, ostia, cavity shape, submucous fibroids, polyps, adhesions."),
b("<b>Operative hysteroscopy:</b> Under GA/regional anaesthesia; resectoscope for TCRE (transcervical resection of endometrium), polypectomy, myomectomy, septum division, adhesiolysis."),
b("<b>Indications:</b> AUB, infertility, recurrent miscarriage, suspected Asherman's, failed/misplaced IUCD."),
b("<b>Complications:</b> Uterine perforation, fluid overload/hypo-osmolar syndrome (especially with glycine), bleeding, infection, air embolism."),
sp(),
]
story += [
h2("h. Laparoscopy"),
p("<b>Definition:</b> Endoscopic visualisation of the pelvic and abdominal organs via a telescope (0°/30°) inserted through the umbilicus under CO₂ pneumoperitoneum."),
b("<b>Diagnostic:</b> Unexplained pelvic pain, infertility work-up (tubal patency with methylene blue dye — chromopertubation), endometriosis staging, suspected ectopic pregnancy, adnexal mass assessment, PID."),
b("<b>Operative:</b> Ovarian cystectomy, myomectomy, salpingectomy (ectopic), adhesiolysis, LUNA (laparoscopic uterine nerve ablation), hysterectomy (TLH/LAVH), sterilisation."),
b("<b>Advantages:</b> Magnification, minimal invasiveness, early recovery, better cosmesis, less adhesion formation."),
b("<b>Complications:</b> Vascular injury (aorta, iliac vessels — trocar insertion), bowel/bladder injury, gas embolism, shoulder tip pain (CO₂ irritating diaphragm), port-site hernia."),
sp(),
]
story += [
h2("i. Magnetic Resonance Imaging (MRI)"),
b("<b>Best imaging for:</b> Uterine anomalies (Müllerian), deep infiltrating endometriosis, fibroid mapping (pre-UAE), endometrial and cervical carcinoma staging, adnexal mass characterisation."),
b("<b>Advantages:</b> No radiation; superior soft-tissue contrast; multiplanar; excellent for parametrial invasion (cervical Ca staging)."),
b("<b>Fibroid:</b> T2 low signal (compared to myometrium); distinguishes fibroid subtypes; 'bridging vessel sign'."),
b("<b>Endometriosis:</b> T1 high signal (haemorrhagic content — 'chocolate' cysts); T2 'shading' in endometriomas."),
b("<b>Limitations:</b> Expensive, time-consuming, contraindicated with certain metallic implants/pacemakers; claustrophobia."),
sp(),
]
story += [
h2("j. Computed Tomography (CT) Scan"),
b("<b>Role in gynaecology:</b> Staging of ovarian cancer (peritoneal metastases, lymph nodes, omental cake, pleural effusion); evaluation of retroperitoneal lymph nodes in cervical/endometrial carcinoma."),
b("<b>CT vs MRI:</b> CT better for nodal staging and distant metastases; MRI better for local staging (parametrial invasion, endometrial cavity)."),
b("<b>PET-CT:</b> Metabolic activity assessment; recurrence detection post-treatment; lymph node involvement in gynaecological cancers."),
b("<b>Limitations:</b> Ionising radiation; contrast nephrotoxicity; poor soft-tissue resolution compared to MRI for primary tumour extent."),
sp(),
PageBreak(),
]
# ═══════════════════════════════════════════════════════════
# SECTION 4: GYNAECOLOGICAL CONDITIONS
# ═══════════════════════════════════════════════════════════
story += [h1("SECTION 4: GYNAECOLOGICAL CONDITIONS"), sp()]
story += [
h2("1. DYSMENORRHOEA"),
h3("Definition:"), p("Painful menstruation — cramping lower abdominal pain before/during menstruation."),
h3("Types:"),
make_table(
["Feature", "Primary Dysmenorrhoea", "Secondary Dysmenorrhoea"],
[
["Pathology", "No pelvic pathology; excess prostaglandin (PGF2α, PGE2) from secretory endometrium → uterine contractions + ischaemia", "Underlying pelvic disease"],
["Age", "Young women, starts 6–12 months after menarche (after ovulatory cycles)", "Older women; onset after pain-free menstruation years"],
["Pain timing", "Onset 24–48 hrs before, peaks at 24 hrs → resolves by day 2–3", "Pain starts days before menstruation; may persist throughout"],
["Causes", "Excess prostaglandins; increased vasopressin", "Endometriosis, adenomyosis, fibroids, PID, IUCD, cervical stenosis, polyps"],
["Pelvic exam", "Normal", "Abnormal findings (tender, nodularity, masses)"],
],
col_widths=[3.5*cm, 7*cm, 6*cm]
),
sp(),
h3("Investigations:"), b("Primary: Clinical diagnosis; USS to exclude secondary causes. Secondary: TVS, HSG, laparoscopy, CA-125."),
h3("Management:"),
b("<b>NSAIDs (first-line for primary):</b> Ibuprofen 400–600 mg TDS; Mefenamic acid 500 mg TDS; start 1–2 days before menstruation. (Inhibit prostaglandin synthesis.)"),
b("<b>OCP:</b> Combined oral contraceptive pill — reduces endometrial proliferation and prostaglandin production; effective for primary and secondary."),
b("<b>Progestins:</b> Norethisterone, Medroxyprogesterone acetate; Levonorgestrel-IUS (Mirena) — especially for adenomyosis."),
b("<b>GnRH analogues:</b> For endometriosis-related dysmenorrhoea (see below)."),
b("<b>Surgical (secondary):</b> Treat underlying cause — laparoscopic excision of endometriosis, myomectomy, LUNA, presacral neurectomy (PSN) for severe primary."),
sp(),
]
story += [
h2("2. PRURITUS VULVAE"),
h3("Definition:"), p("Intense itching of the vulva and surrounding external genitalia."),
h3("Causes:"),
b("<b>Local causes:</b> Vulvovaginal candidiasis (most common), trichomoniasis, bacterial vaginosis, threadworm infestation, contact dermatitis (soaps, detergents, sanitary pads), pubic lice."),
b("<b>Dermatological:</b> Lichen sclerosus (white patches, figure-of-8 distribution around vulva and anus), lichen planus, lichen simplex chronicus, psoriasis."),
b("<b>Systemic:</b> Diabetes mellitus (glycosuria promotes candida), chronic renal failure, cholestatic jaundice, iron-deficiency anaemia, lymphoma."),
b("<b>Neoplastic:</b> Vulvar intraepithelial neoplasia (VIN), vulvar carcinoma — must be excluded in persistent cases."),
b("<b>Psychogenic/Neurological:</b> Post-herpetic neuralgia, vulvodynia."),
h3("Investigations:"),
b("Vaginal swab (HVS): Microscopy, culture (Candida, Trichomonas, BV clue cells)."),
b("Blood sugar (diabetes), FBC (anaemia), LFTs, renal function."),
b("Vulvar biopsy: Mandatory for any persistent/suspicious lesion (thickened, ulcerated, pigmented areas) to exclude malignancy."),
b("Patch testing for contact allergens."),
h3("Management:"),
b("<b>Candidiasis:</b> Topical Clotrimazole 1% cream / Miconazole; Fluconazole 150 mg single oral dose. Treat partner."),
b("<b>Lichen sclerosus:</b> Topical ultra-potent corticosteroid (Clobetasol 0.05%) — first-line; maintenance therapy required. Topical testosterone (historical)."),
b("<b>General:</b> Avoid irritants; loose cotton underwear; emollients (aqueous cream); antihistamines for symptom relief; manage underlying systemic causes."),
sp(),
]
story += [
h2("3. ENDOMETRIOSIS"),
h3("Definition:"), p("Presence of functional endometrial glands and stroma outside the uterine cavity, most commonly on ovaries, uterosacral ligaments, Pouch of Douglas, and pelvic peritoneum."),
h3("Pathogenesis (theories):"),
b("<b>Sampson's retrograde menstruation theory</b> (most accepted): Menstrual debris flows back through fallopian tubes → implants on peritoneal surfaces."),
b("<b>Coelomic metaplasia theory:</b> Peritoneal mesothelium undergoes metaplastic transformation."),
b("<b>Lymphatic/haematogenous dissemination:</b> Explains distant sites (lung, brain)."),
b("<b>Stem cell theory:</b> Bone marrow-derived progenitor cells differentiate into endometrial tissue."),
h3("Clinical Features (3 Ds):"),
b("<b>Dysmenorrhoea</b> (secondary, progressively worsening — 'crescendo' pattern), <b>Dyspareunia</b> (deep), <b>Dyschezia</b> (painful defaecation)."),
b("Chronic pelvic pain, subfertility/infertility."),
b("Cyclical haematuria, haemoptysis (if bladder/lung involvement — rare)."),
b("<b>Examination:</b> Tender, fixed retroverted uterus; nodularity in Pouch of Douglas; adnexal mass (endometrioma)."),
h3("Investigations:"),
b("<b>CA-125:</b> Elevated (>35 U/mL) in moderate-severe disease — not diagnostic; useful for monitoring."),
b("<b>TVS:</b> Endometrioma — 'ground glass' echogenicity; homogeneous low-level echoes; loss of follicles on affected ovary."),
b("<b>MRI:</b> T1 bright (blood), T2 shading; excellent for deep infiltrating endometriosis."),
b("<b>Laparoscopy + biopsy</b> — definitive diagnosis. Classic: powder-burn/gun-shot lesions, blue-black deposits; endometriomas ('chocolate cysts')."),
h3("Management (ASRM staging: I–IV):"),
b("<b>Medical:</b> NSAIDs (pain relief); Combined OCP / Progestins (continuous); Danazol (androgenic side effects); GnRH analogues (Leuprolide, Buserelin) — medical 'pseudomenopause', add-back HRT after 6 months; LNG-IUS (Mirena)."),
b("<b>Surgical:</b> Laparoscopic excision/ablation of implants; cystectomy for endometrioma (preferred over aspiration — lower recurrence); hysterectomy + BSO for completed family with severe disease."),
b("<b>Infertility:</b> Surgical cystectomy + IVF if needed."),
sp(),
]
story += [
h2("4. ADENOMYOSIS"),
h3("Definition:"), p("Presence of endometrial glands and stroma within the myometrium (uterine muscle), associated with smooth muscle hyperplasia — 'internal endometriosis'. Characteristic: junctional zone >12 mm on MRI."),
h3("Pathogenesis:"), p("Invagination of the basal endometrium into the myometrium; trauma from previous surgery (D&C, CS) may be a factor; associated with hyperestrogenism."),
h3("Clinical Features:"),
b("Menorrhagia (heavy periods) — most common."),
b("Secondary dysmenorrhoea (progressively worsening)."),
b("Uniformly enlarged, 'boggy', tender uterus (classically 8–10 weeks size)."),
b("Dyspareunia; subfertility (debated)."),
h3("Investigations:"),
b("<b>TVS:</b> Heterogeneous myometrium; asymmetric thickening; myometrial cysts; poor definition of junctional zone."),
b("<b>MRI (gold standard):</b> Junctional zone width >12 mm; 'JZ/myometrium ratio' >40% — diagnostic."),
b("<b>Histopathology:</b> Endometrial tissue >2.5 mm from basal layer on hysterectomy specimen."),
h3("Management:"),
b("<b>Medical (for fertility preservation):</b> NSAIDs, Progestins, Combined OCP, LNG-IUS (Mirena) — reduces bleeding and pain significantly; GnRH analogues (temporary response)."),
b("<b>Definitive (completed family):</b> Hysterectomy."),
sp(),
]
story += [
h2("5. PELVIC INFLAMMATORY DISEASE (PID)"),
h3("Definition:"), p("Infection and inflammation of the upper female genital tract — includes endometritis, salpingitis, parametritis, oophoritis, tubo-ovarian abscess, and pelvic peritonitis."),
h3("Causative Organisms:"),
b("<b>Primary STI pathogens:</b> Neisseria gonorrhoeae (~25%), Chlamydia trachomatis (~25%)."),
b("<b>Endogenous vaginal flora:</b> Gardnerella vaginalis, Mycoplasma genitalium, E. coli, anaerobes (Bacteroides, Prevotella), Group B Streptococcus."),
b("<b>Risk factors:</b> Age <25, multiple partners, IUCD use (especially first 3 weeks post-insertion), prior STI, intrauterine procedures."),
h3("Clinical Features:"),
b("Lower abdominal/pelvic pain (bilateral); cervical excitation tenderness (CET) — hallmark."),
b("Adnexal tenderness on bimanual examination; mucopurulent cervical discharge."),
b("Fever (>38°C), raised WBC, elevated ESR/CRP (in moderate-severe cases)."),
b("<b>Fitz-Hugh-Curtis syndrome:</b> Perihepatitis — right upper quadrant pain (violin-string adhesions between liver and anterior peritoneum)."),
b("<b>Tubo-ovarian abscess (TOA):</b> Tender adnexal mass; TVUS confirms."),
h3("Minimum Diagnostic Criteria (CDC):"),
b("Uterine tenderness OR adnexal tenderness OR CET — treat empirically."),
h3("Investigations:"),
b("Endocervical swab: NAAT (gonorrhoea + chlamydia); microscopy."),
b("Blood: FBC (leukocytosis), CRP/ESR, blood cultures (febrile)."),
b("TVUS: TOA (complex adnexal mass); free pelvic fluid."),
b("Laparoscopy: Gold standard — visualises tubes; hyperaemia, oedema, purulent exudate."),
h3("Management:"),
b("<b>Outpatient (mild–moderate):</b> Ceftriaxone 500 mg IM stat + Doxycycline 100 mg BD × 14 days + Metronidazole 400 mg BD × 14 days."),
b("<b>Inpatient (severe/TOA):</b> Ceftriaxone 1 g IV OD + Doxycycline 100 mg IV/oral BD + Metronidazole 500 mg IV TDS; IV until 24 hours after clinical improvement, then oral to complete 14 days."),
b("Remove IUCD if no clinical improvement in 72 hours."),
b("TOA: Ultrasound-guided aspiration or surgical drainage if no response to antibiotics."),
h3("Complications (Sequelae):"),
b("Tubal factor infertility (25% after 1 episode, 50% after 3 episodes), Ectopic pregnancy (×6–10 risk), Chronic pelvic pain."),
sp(),
]
story += [
h2("6. PELVIC ORGAN PROLAPSE"),
h3("Definition:"), p("Descent of pelvic organs (uterus, bladder, rectum, small bowel) into or outside the vaginal canal due to weakness of pelvic support structures."),
h3("Classification:"),
b("<b>Cystocele:</b> Anterior vaginal wall prolapse — bladder descends."),
b("<b>Rectocele:</b> Posterior vaginal wall prolapse — rectum bulges."),
b("<b>Enterocele:</b> Herniation of small bowel into the rectovaginal pouch."),
b("<b>Uterovaginal prolapse:</b> Cervix descends; Graded I–IV (Pelvic Organ Prolapse Quantification — POP-Q system): Grade 1 (descent into vagina), Grade 2 (to introitus), Grade 3 (beyond introitus), Grade 4 (Procidentia — complete eversion)."),
h3("Aetiology:"), b("Childbirth trauma, multiparity, menopause (oestrogen deficiency), chronic straining (constipation, cough), obesity, connective tissue disorders."),
h3("Clinical Features:"),
b("'Something coming down' sensation; dragging pelvic heaviness."),
b("Urinary symptoms: Stress urinary incontinence, frequency, incomplete bladder emptying, recurrent UTIs."),
b("Bowel: Constipation, incomplete evacuation, digital evacuation needed (rectocele)."),
b("Sexual dysfunction; backache. Ulceration of exposed cervix/vaginal wall (Procidentia)."),
h3("Investigations:"), b("Clinical POP-Q examination; cough stress test; uroflowmetry/urodynamics; USS (residual urine); MSU (culture)."),
h3("Management:"),
b("<b>Conservative:</b> Pelvic floor exercises (Kegel's), ring pessary, oestrogen cream (postmenopausal — improves tissue)."),
b("<b>Surgical:</b> Anterior colporrhaphy (cystocele), posterior colporrhaphy (rectocele), Manchester operation/vaginal hysterectomy + colporrhaphy (uterovaginal prolapse), sacrocolpopexy (mesh — vault prolapse)."),
sp(),
]
story += [
h2("7. CERVICAL EROSION AND ECTROPION"),
h3("Cervical Ectropion (Erosion):"),
p("Eversion of the endocervical columnar epithelium onto the ectocervix (normally occupied by squamous epithelium). Appears as a raw, red area around the external os. NOT a true erosion — it is normal physiological finding in reproductive age, pregnancy, and OCP users."),
h3("True Cervical Erosion:"),
p("Loss of squamous epithelium from ectocervix exposing underlying stroma — due to trauma, infection, or chemical irritation."),
h3("Clinical Features:"),
b("Often asymptomatic (incidental finding on per-speculum examination)."),
b("Symptoms (when present): Excessive vaginal discharge (clear/mucopurulent), post-coital bleeding, intermenstrual spotting, dyspareunia."),
h3("Investigations:"),
b("Per-speculum examination. Pap smear to exclude CIN/carcinoma. Colposcopy if Pap smear abnormal."),
h3("Management:"),
b("<b>Asymptomatic:</b> No treatment required; reassurance."),
b("<b>Symptomatic:</b> Cryocautery, electrocautery, LEEP — destroys the columnar epithelium; regeneration by squamous metaplasia."),
b("Treat concurrent infections (candida, chlamydia) first."),
sp(),
]
story += [
h2("8. DYSPAREUNIA"),
h3("Definition:"), p("Painful sexual intercourse in women. Can be superficial (introital) or deep (pelvic)."),
h3("Types and Causes:"),
make_table(
["Type", "Causes"],
[
["Superficial (introital)", "Vaginismus, vulvodynia, vulvovaginal atrophy (menopause), insufficient lubrication, Bartholin's cyst/abscess, lichen sclerosus, vaginal infections, skin conditions, episiotomy scar"],
["Deep (pelvic)", "Endometriosis, PID, ovarian cysts, retroverted uterus, uterine fibroids, pelvic adhesions, interstitial cystitis, bladder/rectal pathology"],
],
col_widths=[4*cm, 12.5*cm]
),
sp(),
h3("Investigations:"), b("Pelvic examination, TVS/MRI (structural causes), vulvar biopsy (suspicious skin lesions), laparoscopy (endometriosis, adhesions)."),
h3("Management:"), b("Treat underlying cause; lubricants (atrophy); topical oestrogen (postmenopausal atrophy); physiotherapy (pelvic floor); psychological/psychosexual counselling; EMLA cream for vulvodynia; surgery for structural causes."),
sp(),
]
story += [
h2("9. VAGINISMUS"),
h3("Definition:"), p("Involuntary spasm of the muscles of the outer one-third of the vagina when penetration is attempted, making intercourse painful or impossible."),
h3("Types:"),
b("<b>Primary:</b> Never achieved penetration."),
b("<b>Secondary:</b> Previously painless intercourse, now develops vaginismus (after trauma, dyspareunia, infection, surgery)."),
h3("Causes:"), b("Fear of pain, previous sexual trauma/abuse, anxiety, relationship problems, negative cultural attitudes, previous painful gynaecological examination."),
h3("Management:"),
b("Psychosexual counselling / CBT — addressing fears and anxiety. Partner involvement essential."),
b("Progressive vaginal dilators (smallest to largest, used daily at home)."),
b("Pelvic floor physiotherapy."),
b("Botulinum toxin (Botox) injection into levator ani — for severe refractory cases."),
b("Prognosis: Excellent with appropriate therapy."),
sp(),
]
story += [
h2("10. PRESACRAL NEURALGIA"),
h3("Definition:"), p("Chronic pain arising from the superior hypogastric plexus (presacral nerve) located anterior to the sacrum at L5-S1 level; manifests as intractable midline pelvic/sacral pain."),
h3("Causes:"), b("Endometriosis, PID sequelae, pelvic adhesions, primary dysmenorrhoea (central sensitisation), uterosacral ligament pathology, tumour infiltration (cervical/rectal cancer)."),
h3("Clinical Features:"),
b("Deep, boring, midline sacral/presacral pain — constant or cyclical."),
b("Radiates to perineum, buttocks, thighs. Not relieved by position change."),
b("May be associated with bladder/bowel symptoms."),
h3("Management:"),
b("Medical: NSAIDs, OCPs, GnRH analogues, amitriptyline (neuropathic pain), pregabalin."),
b("<b>LUNA (Laparoscopic Uterine Nerve Ablation):</b> Division of uterosacral ligaments near uterine attachment — disrupts afferent pain pathways."),
b("<b>Presacral neurectomy (PSN):</b> Surgical division of superior hypogastric plexus — more effective than LUNA for midline pain; side effects: constipation, bladder dysfunction."),
sp(),
]
story += [
h2("11. CONSTITUTIONAL NYMPHOMANIA"),
h3("Definition:"), p("Hypersexuality in women — persistently excessive sexual desire not due to organic cause. A psychiatric/psychosexual disorder. (Modern DSM-5 term: Hypersexual Disorder / Compulsive Sexual Behaviour Disorder)."),
h3("Causes:"), b("Primary: Psychological (OCD spectrum, impulse control disorder, bipolar disorder hypomanic phase, personality disorder, childhood sexual abuse, anxiety/depression self-medication through sex); Secondary: Organic — hyperthyroidism, temporal lobe epilepsy, Klüver-Bucy syndrome, Parkinson's disease (dopamine agonist side effect), frontal lobe lesions."),
h3("Clinical Features:"), b("Preoccupation with sexual thoughts interfering with daily function; repeated unsuccessful attempts to control sexual behaviour; distress to patient and partner; may lead to unsafe sexual practices → STI risk."),
h3("Management:"),
b("Psychosexual counselling, CBT, sex-addiction therapy groups."),
b("SSRIs (reduce compulsive behaviour); Naltrexone (opioid antagonist — reduces reward behaviour); anti-androgens (Medroxyprogesterone acetate) for severe cases."),
b("Treat underlying organic/psychiatric cause."),
sp(),
]
story += [
h2("12. EFFLUVIUM SEMINIS (SEMINAL LEAKAGE / VAGINAL FLATULENCE)"),
h3("Definition:"), p("Effluvium seminis literally means 'flowing out of semen' — seminal emission after intercourse; sometimes refers to involuntary passage of air/fluid from the vagina (vaginal flatulence / queefing) or abnormal vaginal discharge."),
h3("Causes of Post-Coital Seminal Discharge:"),
b("Normal physiological drainage of semen from the vaginal canal after intercourse."),
b("Vaginal laxity or prolapse — inability to retain seminal fluid."),
b("Vesico-vaginal fistula, recto-vaginal fistula — abnormal communications."),
h3("Vaginal Flatulence:"),
b("Causes: Pelvic floor weakness (multiparity), prior surgery, pelvic organ prolapse, rectovaginal fistula."),
b("Management: Pelvic floor rehabilitation, prolapse repair, fistula repair."),
h3("In Ayurveda Context:"),
b("Effluvium seminis (Shukra Srava / Shukra Dosha) — one of the Artava / Yoni Vyapat conditions. Associated with Vata aggravation, pelvic floor weakness, and post-coital complaints."),
b("Ayurvedic management: Toning herbs (Ashwagandha, Shatavari), basti karma, yoga, Kegel exercises."),
sp(),
PageBreak(),
]
# SUMMARY TABLE
story += [
h1("QUICK REVISION: STD SUMMARY TABLE"),
sp(),
make_table(
["STD", "Organism", "Hallmark Feature", "Key Investigation", "First-line Treatment"],
[
["Gonorrhoea", "N. gonorrhoeae (GN diplococcus)", "Purulent discharge; intracellular diplococci", "Gram stain + NAAT", "Ceftriaxone 500 mg IM"],
["Syphilis", "T. pallidum (spirochaete)", "Painless chancre → rash on palms/soles", "VDRL (screen) / TPHA (confirm)", "Benzathine Penicillin G 2.4 MU IM"],
["Chlamydia", "C. trachomatis (intracellular)", "Asymptomatic; mucopurulent cervicitis", "NAAT (gold standard)", "Doxycycline 100 mg BD × 7 days"],
["Chancroid", "H. ducreyi", "Painful soft ulcer + tender bubo", "Gram stain 'school of fish'", "Azithromycin 1 g single dose"],
["Donovanosis", "K. granulomatis", "Painless beefy red ulcer; Donovan bodies", "Crush smear (Donovan bodies)", "Doxycycline × ≥3 weeks"],
["Herpes", "HSV-2 (mainly)", "Painful vesicles/ulcers; recurrences", "PCR / Viral culture", "Acyclovir 200 mg 5×/day × 10 days"],
["Trichomoniasis", "T. vaginalis (protozoa)", "Frothy green discharge; strawberry cervix", "Wet mount (motile trichomonads)", "Metronidazole 2 g single dose"],
["Genital Warts", "HPV 6 & 11", "Cauliflower-like warts; aceto-white", "Clinical + colposcopy; PCR typing", "Podophyllin / Imiquimod / LEEP"],
["HIV/AIDS", "HIV-1/2 (Retrovirus)", "Seroconversion illness → CD4 depletion", "ELISA → Western Blot; CD4; VL", "ART: TDF + 3TC + DTG"],
],
col_widths=[2.5*cm, 3.5*cm, 4*cm, 3.5*cm, 3*cm]
),
sp(2),
hr(),
p("<b>Sources:</b> Harrison's Principles of Internal Medicine 22E (2025); Goldman-Cecil Medicine; Robbins & Cotran Pathologic Basis of Disease 11E; Orris Medical Synthesis."),
Paragraph("Prepared by Orris AI Medical Assistant | July 2026 | For Academic/Exam Preparation Use Only", FOOTER_NOTE),
]
doc.build(story)
print("PDF generated:", OUTPUT)
cd /home/daytona/workspace/gynaecology-notes && python gen_pdf.py 2>&1
ls -lh /home/daytona/workspace/gynaecology-notes/Gynaecology_Exam_Notes.pdf
Gynaecology Exam Notes
PDF Document · PDF
Describe obstetric emergencies with causes, clinical features and complications - cord prolapse, uterine inversion, amniotic fluid embolism, obstetric shock and uterine rupture. Discuss causes, clinical features and findings of investigation in obstetric emergencies. Describe Bishop's Score.Explain methods of induction and augmentation of labour. Explain -a. Indications, contraindications, procedure and complications of ventouse delivery.b. Indications, contraindications, procedure and complications of forceps delivery.c. Indications, types and procedure of caesarean section. Calculate and Interpret Bishop’s score.Demonstrate forceps application, vacuum extraction and Caesarean Section.Explain indications and complications for each mode of assistance. Demonstrate abnormal presentations - face, brow, shoulder With good picture with good number of pictures Give these all notes for 20Marks And do PDF
~/obstetrics-notes/gen_obs_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.lib import colors
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, PageBreak, KeepTogether, Image
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.graphics.shapes import (
Drawing, Rect, Circle, Ellipse, Line, String, Polygon,
Path, PolyLine, Group, Arc
)
from reportlab.graphics import renderPDF
from reportlab.graphics.shapes import Drawing
import math, io, os
os.makedirs("/home/daytona/workspace/obstetrics-notes", exist_ok=True)
OUTPUT = "/home/daytona/workspace/obstetrics-notes/Obstetrics_Emergency_Notes.pdf"
doc = SimpleDocTemplate(
OUTPUT, pagesize=A4,
leftMargin=1.8*cm, rightMargin=1.8*cm,
topMargin=2*cm, bottomMargin=2*cm,
title="Obstetrics – 20 Mark Exam Notes",
author="Orris Medical"
)
styles = getSampleStyleSheet()
W = A4[0] - 3.6*cm # usable width
NAVY = colors.HexColor("#0d1b6e")
DBLUE = colors.HexColor("#1565C0")
LBLUE = colors.HexColor("#E3F2FD")
PURPLE = colors.HexColor("#4a148c")
RED = colors.HexColor("#B71C1C")
GREEN = colors.HexColor("#1B5E20")
ORANGE = colors.HexColor("#E65100")
GREY = colors.HexColor("#546E7A")
LGREY = colors.HexColor("#ECEFF1")
TITLE_S = ParagraphStyle("TitleS", fontName="Helvetica-Bold", fontSize=20, textColor=NAVY, alignment=TA_CENTER, spaceAfter=4)
SUB_S = ParagraphStyle("SubS", fontName="Helvetica-Oblique",fontSize=11, textColor=PURPLE, alignment=TA_CENTER, spaceAfter=8)
H1_S = ParagraphStyle("H1S", fontName="Helvetica-Bold", fontSize=13, textColor=colors.white, backColor=NAVY, spaceBefore=12, spaceAfter=4, leftIndent=0, borderPad=5)
H2_S = ParagraphStyle("H2S", fontName="Helvetica-Bold", fontSize=11, textColor=NAVY, spaceBefore=8, spaceAfter=3)
H3_S = ParagraphStyle("H3S", fontName="Helvetica-Bold", fontSize=10, textColor=PURPLE, spaceBefore=5, spaceAfter=2)
BODY_S = ParagraphStyle("BodyS", fontName="Helvetica", fontSize=9.5, leading=14, spaceAfter=3, alignment=TA_JUSTIFY)
BUL_S = ParagraphStyle("BulS", fontName="Helvetica", fontSize=9.5, leading=13, leftIndent=14, firstLineIndent=-10, spaceAfter=2)
WARN_S = ParagraphStyle("WarnS", fontName="Helvetica-Bold", fontSize=9.5, leading=13, leftIndent=6, textColor=RED, spaceAfter=3)
TH_S = ParagraphStyle("ThS", fontName="Helvetica-Bold", fontSize=9, textColor=colors.white, alignment=TA_CENTER)
TD_S = ParagraphStyle("TdS", fontName="Helvetica", fontSize=8.5, leading=11)
FOOT_S = ParagraphStyle("FootS", fontName="Helvetica-Oblique",fontSize=8, textColor=GREY, alignment=TA_CENTER)
CAP_S = ParagraphStyle("CapS", fontName="Helvetica-Oblique",fontSize=8.5, textColor=GREY, alignment=TA_CENTER, spaceAfter=6)
def h1(t): return Paragraph(f" {t}", H1_S)
def h2(t): return Paragraph(t, H2_S)
def h3(t): return Paragraph(t, H3_S)
def p(t): return Paragraph(t, BODY_S)
def b(t): return Paragraph(f"• {t}", BUL_S)
def w(t): return Paragraph(f"⚠ {t}", WARN_S)
def sp(n=1): return Spacer(1, n*0.28*cm)
def hr(): return HRFlowable(width="100%", thickness=0.6, color=NAVY, spaceAfter=4, spaceBefore=2)
def cap(t): return Paragraph(t, CAP_S)
def tbl(headers, rows, cw=None):
data = [[Paragraph(h, TH_S) for h in headers]]
for row in rows:
data.append([Paragraph(str(c), TD_S) for c in row])
if cw is None: cw = [None]*len(headers)
t = Table(data, colWidths=cw, hAlign='LEFT')
t.setStyle(TableStyle([
('BACKGROUND',(0,0),(-1,0), NAVY),
('TEXTCOLOR',(0,0),(-1,0), colors.white),
('ROWBACKGROUNDS',(0,1),(-1,-1),[LBLUE, colors.white]),
('GRID',(0,0),(-1,-1),0.4, colors.HexColor("#90CAF9")),
('VALIGN',(0,0),(-1,-1),'TOP'),
('TOPPADDING',(0,0),(-1,-1),3),
('BOTTOMPADDING',(0,0),(-1,-1),3),
('LEFTPADDING',(0,0),(-1,-1),4),
('RIGHTPADDING',(0,0),(-1,-1),4),
]))
return t
# ══════════════════════════════════════════════════════════
# DIAGRAM HELPERS
# ══════════════════════════════════════════════════════════
def uterus_outline(d, cx, cy, w=60, h=80, col=colors.HexColor("#F8BBD0")):
"""Draw a simple uterus shape"""
d.add(Ellipse(cx-w/2, cy-h*0.55, w, h*0.75, fillColor=col, strokeColor=colors.HexColor("#C2185B"), strokeWidth=1.5))
# cervix
d.add(Rect(cx-10, cy-h*0.55-18, 20, 20, fillColor=colors.HexColor("#EF9A9A"), strokeColor=colors.HexColor("#C2185B"), strokeWidth=1))
# fallopian tubes
d.add(Line(cx-w/2, cy+5, cx-w/2-25, cy+15, strokeColor=colors.HexColor("#C2185B"), strokeWidth=1.5))
d.add(Line(cx+w/2, cy+5, cx+w/2+25, cy+15, strokeColor=colors.HexColor("#C2185B"), strokeWidth=1.5))
def baby_head(d, cx, cy, r=18, col=colors.HexColor("#FFCC80")):
d.add(Circle(cx, cy, r, fillColor=col, strokeColor=colors.HexColor("#E65100"), strokeWidth=1.2))
# ── Diagram 1: Cord Prolapse ──────────────────────────────
def make_cord_prolapse_diag():
dw, dh = 280, 180
d = Drawing(dw, dh)
d.add(Rect(0, 0, dw, dh, fillColor=colors.HexColor("#E3F2FD"), strokeColor=NAVY, strokeWidth=0.5, rx=6))
# Pelvis outline
d.add(Ellipse(140-60, 80-45, 120, 90, fillColor=colors.HexColor("#FFF8E1"), strokeColor=colors.HexColor("#795548"), strokeWidth=1.5))
# baby head
baby_head(d, 140, 105, 25, colors.HexColor("#FFCC80"))
# cervix opening
d.add(Rect(125, 58, 30, 8, fillColor=colors.HexColor("#EF9A9A"), strokeColor=RED, strokeWidth=1))
d.add(String(131, 61, "Cervix", fontSize=6, fillColor=RED))
# cord — looping down past head
d.add(Line(140, 80, 145, 65, strokeColor=colors.HexColor("#4CAF50"), strokeWidth=2))
d.add(Line(145, 65, 148, 55, strokeColor=colors.HexColor("#4CAF50"), strokeWidth=2))
d.add(Line(148, 55, 145, 45, strokeColor=colors.HexColor("#4CAF50"), strokeWidth=2))
d.add(Line(145, 45, 140, 38, strokeColor=colors.HexColor("#4CAF50"), strokeWidth=2))
d.add(Line(140, 38, 135, 30, strokeColor=colors.HexColor("#4CAF50"), strokeWidth=2))
# labels
d.add(String(150, 47, "Prolapsed cord", fontSize=7, fillColor=colors.HexColor("#1B5E20")))
d.add(String(90, 108, "Fetal head", fontSize=7, fillColor=colors.HexColor("#E65100")))
d.add(String(50, 145, "CORD PROLAPSE", fontSize=10, fillColor=NAVY))
d.add(String(45, 132, "(cord ahead of presenting part)", fontSize=7, fillColor=GREY))
return d
# ── Diagram 2: Uterine Inversion ─────────────────────────
def make_uterine_inversion_diag():
dw, dh = 300, 200
d = Drawing(dw, dh)
d.add(Rect(0, 0, dw, dh, fillColor=colors.HexColor("#FCE4EC"), strokeColor=NAVY, strokeWidth=0.5, rx=6))
# Normal uterus (left side)
d.add(String(20, 175, "Normal", fontSize=8, fillColor=GREEN))
uterus_outline(d, 70, 110, 45, 70, colors.HexColor("#F8BBD0"))
d.add(String(48, 48, "Fundus up", fontSize=7, fillColor=GREY))
# Arrow
d.add(String(118, 110, "→", fontSize=16, fillColor=RED))
# Inverted uterus (right side)
d.add(String(155, 175, "Inverted", fontSize=8, fillColor=RED))
d.add(Ellipse(155+22, 100, 50, 65, fillColor=colors.HexColor("#EF9A9A"), strokeColor=RED, strokeWidth=2))
# inverted fundus poking down
d.add(Ellipse(175, 82, 28, 30, fillColor=RED, strokeColor=colors.HexColor("#B71C1C"), strokeWidth=1.5))
d.add(String(163, 100, "Fundus", fontSize=7, fillColor=colors.white))
d.add(String(163, 90, "inverted", fontSize=7, fillColor=colors.white))
d.add(String(152, 68, "into vagina", fontSize=7, fillColor=RED))
d.add(String(60, 12, "UTERINE INVERSION — Fundus turns inside out", fontSize=9, fillColor=NAVY))
return d
# ── Diagram 3: Amniotic Fluid Embolism pathway ───────────
def make_afe_diag():
dw, dh = 380, 160
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=LGREY, strokeColor=NAVY, strokeWidth=0.5, rx=6))
boxes = [
(20, "AF enters\nmaternal\ncirculation", colors.HexColor("#E3F2FD")),
(110, "Pulmonary\nvasospasm\n+ obstruction", colors.HexColor("#FFF3E0")),
(200, "Right heart\nfailure +\nhypoxia", colors.HexColor("#FCE4EC")),
(290, "DIC +\ncoagulopathy\n(Phase 2)", RED),
]
y0 = 65
for x, txt, col in boxes:
tc = colors.white if col == RED else NAVY
d.add(Rect(x, y0, 82, 55, fillColor=col, strokeColor=NAVY, strokeWidth=1, rx=4))
lines = txt.split("\n")
for i, ln in enumerate(lines):
d.add(String(x+41-len(ln)*2.5, y0+40-i*12, ln, fontSize=7.5, fillColor=tc))
if x < 290:
d.add(String(x+86, y0+25, "→", fontSize=14, fillColor=NAVY))
d.add(String(80, 135, "AMNIOTIC FLUID EMBOLISM — Pathophysiology Cascade", fontSize=9, fillColor=NAVY))
d.add(String(30, 148, "Trigger: Labour, delivery, or uterine manipulation", fontSize=8, fillColor=GREY))
d.add(String(20, 12, "AF = Amniotic fluid | DIC = Disseminated intravascular coagulation", fontSize=7.5, fillColor=GREY))
return d
# ── Diagram 4: Obstetric Shock — ABCDE box ───────────────
def make_shock_diag():
dw, dh = 380, 150
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=colors.HexColor("#FFF8E1"), strokeColor=NAVY, strokeWidth=0.5, rx=6))
items = [
("HAEMORRHAGIC", "PPH, APH,\nuterine rupture", colors.HexColor("#FFCDD2")),
("SEPTIC", "Chorioamnionitis\nPuerperal sepsis", colors.HexColor("#F8BBD0")),
("NEUROGENIC", "Inverted uterus\nPain/epidural", colors.HexColor("#E1BEE7")),
("CARDIOGENIC", "AFE, cardiac\ndisease", colors.HexColor("#BBDEFB")),
("ANAPHYLACTIC", "Drug reaction\noxytocin allergy", colors.HexColor("#C8E6C9")),
]
x0, y0, bw, bh = 8, 30, 70, 90
for i, (title, detail, col) in enumerate(items):
x = x0 + i*(bw+5)
d.add(Rect(x, y0, bw, bh, fillColor=col, strokeColor=NAVY, strokeWidth=1, rx=4))
d.add(String(x+4, y0+bh-14, title, fontSize=7, fillColor=NAVY))
lines = detail.split("\n")
for j, ln in enumerate(lines):
d.add(String(x+3, y0+55-j*13, ln, fontSize=7, fillColor=GREY))
d.add(String(80, 135, "TYPES OF OBSTETRIC SHOCK", fontSize=10, fillColor=NAVY))
d.add(String(40, 12, "Common features: hypotension, tachycardia, pallor, cold clammy skin, altered consciousness", fontSize=7.5, fillColor=RED))
return d
# ── Diagram 5: Uterine Rupture sites ─────────────────────
def make_uterine_rupture_diag():
dw, dh = 290, 180
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=colors.HexColor("#FFF3E0"), strokeColor=NAVY, strokeWidth=0.5, rx=6))
uterus_outline(d, 145, 105, 70, 100, colors.HexColor("#FFCDD2"))
# scar line (lower segment)
d.add(Line(108, 68, 182, 68, strokeColor=RED, strokeWidth=2.5))
d.add(String(108, 58, "Lower segment scar (most common)", fontSize=7, fillColor=RED))
# fundal rupture
d.add(Line(130, 145, 160, 145, strokeColor=colors.HexColor("#B71C1C"), strokeWidth=1.5))
d.add(String(100, 135, "Fundal (spontaneous — rare)", fontSize=7, fillColor=PURPLE))
d.add(String(55, 162, "UTERINE RUPTURE — Common sites", fontSize=9, fillColor=NAVY))
d.add(String(40, 12, "LSCS scar is the MOST common site in developed countries", fontSize=7.5, fillColor=GREY))
return d
# ── Diagram 6: Bishop's Score visual ─────────────────────
def make_bishop_diag():
dw, dh = 460, 175
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=LBLUE, strokeColor=NAVY, strokeWidth=0.5, rx=6))
cols_labels = ["Feature", "Score 0", "Score 1", "Score 2", "Score 3"]
rows_data = [
("Dilatation", "Closed", "1-2 cm", "3-4 cm", "≥5 cm"),
("Effacement", "0-30%", "40-50%", "60-70%", "≥80%"),
("Station", "-3", "-2", "-1/0", "+1/+2"),
("Consistency","Firm", "Medium", "Soft", "—"),
("Position", "Post.", "Mid", "Ant.", "—"),
]
col_w = [80, 68, 68, 68, 68]
x0, y0 = 5, 15
# header
hx = x0
for i, cl in enumerate(cols_labels):
fc = NAVY if i == 0 else colors.HexColor("#1565C0")
d.add(Rect(hx, y0+120, col_w[i], 22, fillColor=fc, strokeColor=colors.white, strokeWidth=0.5))
d.add(String(hx+4, y0+127, cl, fontSize=8, fillColor=colors.white))
hx += col_w[i]
row_colors = [colors.HexColor("#E3F2FD"), colors.white, colors.HexColor("#E3F2FD"), colors.white, colors.HexColor("#E3F2FD")]
for ri, (feat, s0, s1, s2, s3) in enumerate(rows_data):
ry = y0 + 120 - (ri+1)*22
rx = x0
for ci, val in enumerate([feat, s0, s1, s2, s3]):
bg = NAVY if ci == 0 else row_colors[ri]
fc_t = colors.white if ci == 0 else NAVY
d.add(Rect(rx, ry, col_w[ci], 21, fillColor=bg, strokeColor=colors.HexColor("#90CAF9"), strokeWidth=0.5))
d.add(String(rx+4, ry+6, val, fontSize=8, fillColor=fc_t))
rx += col_w[ci]
d.add(String(5, 8, "Score ≥8 = Favourable cervix (induction likely successful) | Score ≤5 = Unfavourable (cervical ripening needed first)", fontSize=7.5, fillColor=RED))
d.add(String(5, 158, "BISHOP'S SCORE — Cervical Assessment", fontSize=10, fillColor=NAVY))
return d
# ── Diagram 7: Face presentation ────────────────────────
def make_face_diag():
dw, dh = 200, 160
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=LGREY, strokeColor=NAVY, strokeWidth=0.5, rx=6))
# pelvis
d.add(Ellipse(100-50, 70-35, 100, 70, fillColor=colors.HexColor("#FFF8E1"), strokeColor=colors.HexColor("#795548"), strokeWidth=1.5))
# head — face presentation, extended
baby_head(d, 100, 90, 24, colors.HexColor("#FFCC80"))
# face features
d.add(Circle(92, 95, 3, fillColor=colors.HexColor("#795548"), strokeColor=None))
d.add(Circle(108, 95, 3, fillColor=colors.HexColor("#795548"), strokeColor=None))
d.add(Line(93, 83, 107, 83, strokeColor=colors.HexColor("#795548"), strokeWidth=1.5))
d.add(Line(100, 90, 100, 78, strokeColor=colors.HexColor("#E65100"), strokeWidth=1))
d.add(String(108, 68, "Chin (mentum)\nas presenting part", fontSize=6.5, fillColor=RED))
d.add(String(30, 145, "FACE PRESENTATION", fontSize=9, fillColor=NAVY))
d.add(String(20, 130, "Denominator = Mentum", fontSize=7.5, fillColor=PURPLE))
d.add(String(15, 10, "Extended head — face leads", fontSize=7.5, fillColor=GREY))
return d
# ── Diagram 8: Brow presentation ────────────────────────
def make_brow_diag():
dw, dh = 200, 160
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=colors.HexColor("#FFF3E0"), strokeColor=NAVY, strokeWidth=0.5, rx=6))
d.add(Ellipse(100-50, 70-35, 100, 70, fillColor=colors.HexColor("#FFF8E1"), strokeColor=colors.HexColor("#795548"), strokeWidth=1.5))
baby_head(d, 100, 88, 24, colors.HexColor("#FFCC80"))
# brow
d.add(Line(82, 98, 118, 98, strokeColor=colors.HexColor("#795548"), strokeWidth=2))
d.add(String(90, 66, "Brow leads", fontSize=7, fillColor=RED))
d.add(String(20, 145, "BROW PRESENTATION", fontSize=9, fillColor=NAVY))
d.add(String(18, 130, "Denominator = Frontal bone", fontSize=7.5, fillColor=PURPLE))
d.add(String(5, 10, "Partially extended — brow leads; LARGEST diameter (13.5 cm)", fontSize=7, fillColor=GREY))
return d
# ── Diagram 9: Shoulder presentation ────────────────────
def make_shoulder_diag():
dw, dh = 200, 160
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=colors.HexColor("#E8F5E9"), strokeColor=NAVY, strokeWidth=0.5, rx=6))
d.add(Ellipse(100-50, 70-35, 100, 70, fillColor=colors.HexColor("#FFF8E1"), strokeColor=colors.HexColor("#795548"), strokeWidth=1.5))
# baby lying transverse
d.add(Ellipse(45, 78, 110, 40, fillColor=colors.HexColor("#FFCC80"), strokeColor=colors.HexColor("#E65100"), strokeWidth=1.5))
baby_head(d, 45, 90, 18, colors.HexColor("#FFCC80"))
d.add(String(75, 95, "Shoulder / Arm", fontSize=7, fillColor=RED))
d.add(String(73, 83, "as presenting part", fontSize=6.5, fillColor=RED))
d.add(String(22, 145, "SHOULDER PRESENTATION", fontSize=9, fillColor=NAVY))
d.add(String(20, 130, "Lie = Transverse | Denom. = Acromion", fontSize=7.5, fillColor=PURPLE))
d.add(String(5, 10, "CANNOT deliver vaginally — CS mandatory (unless 2nd twin)", fontSize=7, fillColor=RED))
return d
# ── Diagram 10: Forceps types ───────────────────────────
def make_forceps_diag():
dw, dh = 360, 130
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=LGREY, strokeColor=NAVY, strokeWidth=0.5, rx=6))
types = [
(30, "Wrigley's", "Low/outlet,\nCS forceps"),
(130, "Anderson's\n(Neville-Barnes)", "Most common\nMOD forceps"),
(250, "Kielland's", "Rotational\nforceps"),
]
for x, name, use in types:
d.add(Rect(x, 20, 85, 80, fillColor=LBLUE, strokeColor=DBLUE, strokeWidth=1, rx=4))
# simplified blade shape
d.add(Ellipse(x+15, 35, 55, 28, fillColor=colors.HexColor("#90CAF9"), strokeColor=DBLUE, strokeWidth=1))
d.add(Line(x+42, 49, x+42, 20, strokeColor=NAVY, strokeWidth=2))
lines_n = name.split("\n")
for i, ln in enumerate(lines_n):
d.add(String(x+5, 108-i*10, ln, fontSize=7.5, fillColor=NAVY))
lines_u = use.split("\n")
for i, ln in enumerate(lines_u):
d.add(String(x+3, 28-i*10, ln, fontSize=7, fillColor=GREY))
d.add(String(100, 115, "TYPES OF OBSTETRIC FORCEPS", fontSize=10, fillColor=NAVY))
return d
# ── Diagram 11: Ventouse cup diagram ───────────────────
def make_ventouse_diag():
dw, dh = 280, 130
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=colors.HexColor("#FFF3E0"), strokeColor=NAVY, strokeWidth=0.5, rx=6))
# Baby head
baby_head(d, 90, 65, 38, colors.HexColor("#FFCC80"))
# Cup on head
d.add(Ellipse(62, 82, 56, 24, fillColor=colors.HexColor("#B0BEC5"), strokeColor=GREY, strokeWidth=1.5))
# Tube
d.add(Line(118, 94, 200, 94, strokeColor=GREY, strokeWidth=3))
d.add(Line(200, 94, 220, 80, strokeColor=GREY, strokeWidth=3))
d.add(String(150, 100, "Suction tube", fontSize=7, fillColor=GREY))
d.add(String(60, 50, "Vacuum cup\napplied to\nfetal scalp", fontSize=7, fillColor=NAVY))
d.add(String(215, 65, "Suction\npump", fontSize=7, fillColor=GREY))
d.add(String(60, 115, "VENTOUSE (VACUUM EXTRACTOR) — Cup applied 3 cm from fontanelle", fontSize=8, fillColor=NAVY))
d.add(String(50, 5, "Chignon = Scalp oedema formed inside cup", fontSize=7.5, fillColor=RED))
return d
# ── Diagram 12: CS incision layers ─────────────────────
def make_cs_diag():
dw, dh = 340, 170
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=LGREY, strokeColor=NAVY, strokeWidth=0.5, rx=6))
layers = [
(145, "Skin (Pfannenstiel)", colors.HexColor("#FFCC80")),
(126, "Subcutaneous fat", colors.HexColor("#FFF9C4")),
(108, "Rectus sheath", colors.HexColor("#C8E6C9")),
(90, "Rectus muscle", colors.HexColor("#A5D6A7")),
(72, "Peritoneum", colors.HexColor("#B3E5FC")),
(54, "Uterovesical fold", colors.HexColor("#E1BEE7")),
(36, "Lower uterine segment (incision)", RED),
]
for y, label, col in layers:
d.add(Rect(20, y, 180, 16, fillColor=col, strokeColor=NAVY, strokeWidth=0.5))
tc = colors.white if col == RED else NAVY
d.add(String(24, y+4, label, fontSize=7.5, fillColor=tc))
d.add(String(215, 110, "Pfannenstiel\n= transverse\nsuprapubic incision", fontSize=8, fillColor=NAVY))
d.add(Line(200, 145, 215, 145, strokeColor=NAVY, strokeWidth=0.8))
d.add(Line(200, 36, 215, 36, strokeColor=RED, strokeWidth=1.5))
d.add(String(215, 30, "LSCS incision", fontSize=7.5, fillColor=RED))
d.add(String(50, 157, "CAESAREAN SECTION — Surgical Layers", fontSize=10, fillColor=NAVY))
d.add(String(20, 5, "LSCS = Lower Segment Caesarean Section (most common)", fontSize=7.5, fillColor=GREY))
return d
# ══════════════════════════════════════════════════════════
# BUILD STORY
# ══════════════════════════════════════════════════════════
story = []
# COVER
story += [
sp(3),
Paragraph("OBSTETRICS", TITLE_S),
Paragraph("20-Mark Exam Notes with Diagrams", SUB_S),
Paragraph("Obstetric Emergencies • Bishop's Score • Induction & Augmentation<br/>Instrumental Delivery (Forceps & Ventouse) • Caesarean Section • Abnormal Presentations", SUB_S),
sp(1), hr(), sp(1),
Paragraph("Based on Harrison's, Rosen's Emergency Medicine, Goldman-Cecil Medicine | Orris Medical", FOOT_S),
PageBreak()
]
# ═══════════════════════ SECTION 1: OBSTETRIC EMERGENCIES ═══════════════════
story += [h1("SECTION 1: OBSTETRIC EMERGENCIES"), sp()]
# ─── 1. CORD PROLAPSE ──────────────────────────────────────
story += [
h2("1. CORD PROLAPSE"),
p("Cord prolapse is the descent of the umbilical cord through the cervix alongside (occult) or past (overt) the presenting part after rupture of membranes, while the presenting part remains unfixed. It is an acute obstetric emergency — fetal mortality 10–17% if delivery is delayed."),
sp(0.5),
]
story.append(make_cord_prolapse_diag())
story.append(cap("Fig 1. Cord prolapse — umbilical cord descends ahead of presenting part, risking compression"))
story += [
sp(0.5),
h3("Causes / Predisposing Factors:"),
b("<b>Fetal factors:</b> High presenting part, mal-presentation (transverse lie, oblique lie, breech, face, brow), prematurity (small fetus, unfixed presenting part)."),
b("<b>Placental/cord:</b> Low-lying placenta, polyhydramnios (cord floats), long umbilical cord."),
b("<b>Iatrogenic:</b> Artificial rupture of membranes (ARM) with high presenting part, external cephalic version, fetal blood sampling, insertion of intrauterine pressure catheter."),
b("<b>Multiparity:</b> Lax uterine/abdominal muscles → unstable lie."),
h3("Clinical Features:"),
b("Variable decelerations or severe bradycardia on CTG (cord compression = immediate fetal distress)."),
b("<b>Overt prolapse:</b> Cord visible at vulva or felt in vagina on digital examination."),
b("<b>Occult prolapse:</b> Cord alongside presenting part — not visible; diagnosed by CTG changes during/after membrane rupture."),
h3("Immediate Management — 'PUSH UP':"),
b("<b>P</b> — Position: Knee-chest (Trendelenburg) or left lateral with hips elevated — reduces cord compression."),
b("<b>U</b> — Umbilical cord: Keep warm and moist (wrap in warm saline-soaked swab); NEVER compress cord."),
b("<b>S</b> — Stop oxytocin infusion immediately."),
b("<b>H</b> — Hand: Examiner's fingers manually elevate presenting part off the cord until delivery."),
b("<b>U</b> — Urgent CS (most cases); vaginal delivery if fully dilated and delivery imminent."),
b("<b>P</b> — Paediatrician to attend; tocolysis (terbutaline 250 mcg SC) — to reduce uterine contractions."),
w("Delivery must occur within 30 minutes. Fetal heart monitoring continuous until delivery."),
h3("Complications:"),
b("Fetal: Asphyxia, hypoxic ischaemic encephalopathy (HIE), stillbirth, cerebral palsy, perinatal death."),
b("Maternal: CS-related complications (haemorrhage, infection, VTE)."),
sp(),
]
# ─── 2. UTERINE INVERSION ──────────────────────────────────
story += [
h2("2. UTERINE INVERSION"),
p("Uterine inversion is the turning inside out of the uterine fundus through the cervix — the fundus descends into the uterine cavity, through the cervix, and sometimes outside the vagina. Incidence: 1 in 2,000–20,000 deliveries. LIFE-THREATENING — causes severe haemorrhage and neurogenic shock."),
sp(0.5),
]
story.append(make_uterine_inversion_diag())
story.append(cap("Fig 2. Uterine inversion — fundus turns inside out; degrees from partial to complete (procidentia)"))
story += [
sp(0.5),
h3("Degrees of Inversion:"),
tbl(["Degree", "Description"],
[["1st (Incomplete)","Fundus dimples but remains above the internal os"],
["2nd (Complete)","Fundus passes through internal os into vagina but not beyond introitus"],
["3rd (Prolapsed)","Fundus visible at/beyond introitus — procidentia uteri inversi"],
["4th (Total)","Vagina also inverted (very rare)"]],
cw=[3.5*cm, 13*cm]),
sp(0.5),
h3("Causes:"),
b("<b>Mismanagement of third stage of labour (most common):</b> Fundal pressure (Credé manoeuvre) with atonic uterus, cord traction before placental separation."),
b("Short umbilical cord, abnormally adherent placenta (accreta/fundal placenta)."),
b("Precipitate labour, uterine anomalies, connective tissue disorders."),
h3("Clinical Features:"),
b("<b>Sudden severe postpartum haemorrhage</b> (blood loss 800–1800 mL typical)."),
b("<b>Neurogenic shock</b> — disproportionate hypotension (vagal response from inversion)."),
b("Severe pelvic/lower abdominal pain."),
b("Mass at/protruding from introitus (if 3rd/4th degree)."),
b("Absent uterine fundus on abdominal palpation (cannot feel fundus abdominally)."),
h3("Management:"),
b("<b>CALL FOR HELP — RESUSCITATE:</b> IV access × 2, crystalloids/blood, oxygen, monitoring."),
b("<b>Manual replacement (Johnson's manoeuvre):</b> Grasp inverted fundus with whole hand; push fundus upward through vagina toward umbilicus (DO NOT remove placenta first — increases haemorrhage). Sustained pressure until uterus normal."),
b("<b>O'Sullivan's hydrostatic method:</b> Warm saline (3–5 L) infused into vagina via nozzle with outlet blocked by operator's hand — hydrostatic pressure restores uterus."),
b("<b>Tocolysis before repositioning:</b> Terbutaline, GTN, or general anaesthesia to relax uterus."),
b("<b>Once replaced:</b> Oxytocin infusion immediately (contracts uterus, prevents re-inversion). Uterotonic agents."),
b("<b>Surgical (if manual fails):</b> Huntington's operation (abdominal — cups or clamps pull fundus up); Haultain's operation (posterior cervical incision to allow reduction)."),
w("NEVER attempt to remove placenta before repositioning — massively increases haemorrhage."),
sp(),
]
# ─── 3. AMNIOTIC FLUID EMBOLISM ────────────────────────────
story += [
h2("3. AMNIOTIC FLUID EMBOLISM (AFE)"),
p("Amniotic fluid embolism (AFE) is a catastrophic, unpredictable obstetric emergency in which amniotic fluid, fetal cells, hair, and debris enter the maternal pulmonary circulation, triggering a massive anaphylactoid/immune response. Mortality: 20–60%. Incidence: 1 in 8,000–80,000 deliveries."),
sp(0.5),
]
story.append(make_afe_diag())
story.append(cap("Fig 3. AFE cascade — amniotic fluid enters maternal blood → pulmonary vasospasm → right heart failure → DIC"))
story += [
sp(0.5),
h3("Causes/Risk Factors:"),
b("Tumultuous/rapid labour, uterine hyperstimulation (oxytocin, prostaglandins)."),
b("Amniocentesis, ARM, CS, uterine rupture, placenta praevia/abruption."),
b("Advanced maternal age, multiparity, IUFD."),
h3("Pathophysiology (Two-Phase Model):"),
b("<b>Phase 1:</b> AF enters pulmonary circulation → intense pulmonary vasospasm → acute right heart failure → hypoxia, maternal collapse."),
b("<b>Phase 2 (30–60 min later):</b> Left heart failure (LV dysfunction) + massive Disseminated Intravascular Coagulation (DIC) → uncontrollable haemorrhage."),
h3("Clinical Features (Classical triad):"),
b("<b>Sudden cardiovascular collapse:</b> Hypotension, cardiac arrest."),
b("<b>Acute respiratory failure:</b> Dyspnoea, cyanosis, pulmonary oedema, bronchospasm, respiratory arrest."),
b("<b>DIC with haemorrhage:</b> Uncontrollable PPH, haematuria, bleeding from venepuncture sites."),
b("Other: Seizures (10%), altered consciousness, fetal distress."),
h3("Investigations:"),
b("Clinical diagnosis (exclude other causes). ABG: Hypoxia, metabolic acidosis. CXR: Pulmonary oedema. ECG: Right heart strain (S1Q3T3). FBC: Thrombocytopenia. Coagulation: Prolonged PT/APTT, low fibrinogen, elevated FDP/D-dimer. Bronchoscopy/histology: Fetal squames, mucin (post-mortem diagnosis)."),
h3("Management (Supportive — no specific treatment):"),
b("<b>Airway & Breathing:</b> Immediate intubation, 100% O₂, ventilatory support."),
b("<b>Circulation:</b> CPR if arrest; IV fluids; vasopressors (noradrenaline/adrenaline) for hypotension; inotropes (dobutamine) for cardiac failure."),
b("<b>DIC treatment:</b> FFP, cryoprecipitate (fibrinogen), platelets, packed RBCs. Target fibrinogen >2 g/L. Tranexamic acid."),
b("<b>Delivery:</b> Perimortem CS within 5 minutes of maternal cardiac arrest (improves maternal and fetal outcome)."),
b("<b>ICU:</b> Multidisciplinary team — obstetrics, anaesthetics, haematology."),
w("Mortality 20–60%. Survivors may have permanent neurological deficit."),
sp(),
]
# ─── 4. OBSTETRIC SHOCK ────────────────────────────────────
story += [
h2("4. OBSTETRIC SHOCK"),
p("Shock is a state of circulatory failure resulting in inadequate tissue perfusion and oxygenation. In obstetrics, it is defined by: <b>systolic BP <90 mmHg</b> and <b>pulse >100 bpm</b>, with associated signs of organ hypoperfusion."),
sp(0.5),
]
story.append(make_shock_diag())
story.append(cap("Fig 4. Five types of obstetric shock and their common causes"))
story += [
sp(0.5),
h3("Causes:"),
tbl(["Type of Shock", "Obstetric Causes"],
[["Haemorrhagic (most common)","PPH (uterine atony, retained placenta, genital tract trauma), APH (placenta praevia, abruption), ectopic pregnancy rupture, uterine rupture"],
["Septic", "Chorioamnionitis, puerperal sepsis, pyelonephritis, septic abortion"],
["Neurogenic","Uterine inversion, intense pain, high spinal/epidural block"],
["Cardiogenic","AFE, cardiac disease (peripartum cardiomyopathy), air embolism"],
["Anaphylactic","Penicillin, oxytocin, blood transfusion reaction"]],
cw=[4*cm, 12.5*cm]),
sp(0.5),
h3("Clinical Features:"),
b("<b>Compensated shock (Class I–II, <30% blood loss):</b> Tachycardia, pallor, cool clammy skin, anxiety, reduced pulse pressure, urine output 20–30 mL/hr."),
b("<b>Decompensated shock (Class III–IV, >30–40% loss):</b> Hypotension (SBP <90), tachycardia >120, altered consciousness, oliguria/anuria (<0.5 mL/kg/hr), mottled skin, air hunger."),
b("<b>Septic shock:</b> Fever/hypothermia + warm vasodilated peripheries initially (warm shock) → later cold shocked."),
h3("Shock Index (SI):"),
p("<b>Shock Index = Heart Rate / Systolic BP</b>. Normal SI = 0.5–0.7. SI >1.0 indicates significant haemorrhage/shock (PPH patients with SI >1.0 require blood transfusion)."),
h3("Investigations:"),
b("FBC (Hb, platelets), coagulation screen (PT, APTT, fibrinogen), U&E, LFTs, ABG, lactate (>4 mmol/L = severe sepsis), blood cultures, crossmatch, fibrinogen, D-dimer."),
b("Urine output (catheterise), ECG, CXR, bedside ultrasound (FAST scan)."),
h3("Management — ABCDE Approach:"),
b("<b>A — Airway:</b> Secure and protect; intubate if GCS <8."),
b("<b>B — Breathing:</b> High-flow O₂ 15 L/min non-rebreather mask."),
b("<b>C — Circulation:</b> 2 large-bore IV cannulae; fluid resuscitation (crystalloid 1–2 L rapidly); blood transfusion (O-negative if crossmatch not available); vasopressors if septic/cardiogenic."),
b("<b>D — Disability:</b> AVPU/GCS; blood glucose."),
b("<b>E — Exposure:</b> Full examination; identify and treat cause."),
b("<b>Haemorrhagic:</b> Massive transfusion protocol (RBC:FFP:platelets 1:1:1), TXA (tranexamic acid 1 g IV within 3 hours), uterotonic agents (oxytocin, ergometrine, carboprost), surgery/embolisation if needed."),
b("<b>Septic:</b> IV antibiotics within 1 hour (piperacillin-tazobactam/meropenem); noradrenaline if vasopressor needed; source control."),
w("MEOWS (Modified Early Obstetric Warning Score) — used for early recognition of deteriorating obstetric patients."),
sp(),
]
# ─── 5. UTERINE RUPTURE ────────────────────────────────────
story += [
h2("5. UTERINE RUPTURE"),
p("Uterine rupture is a full-thickness tear of the uterine wall during pregnancy or labour. It is one of the most catastrophic obstetric emergencies — maternal mortality 1–13%, perinatal mortality 50–75% in resource-poor settings."),
sp(0.5),
]
story.append(make_uterine_rupture_diag())
story.append(cap("Fig 5. Uterine rupture sites — lower segment scar (LSCS) most common; spontaneous fundal rupture rare"))
story += [
sp(0.5),
h3("Types:"),
b("<b>Complete rupture:</b> Full-thickness breach of uterine wall + overlying peritoneum — fetus/placenta may extrude into abdominal cavity."),
b("<b>Incomplete (silent/dehiscence):</b> Tear through myometrium but peritoneum intact — may be asymptomatic."),
h3("Causes:"),
b("<b>Scarred uterus (most common in developed countries):</b> Previous LSCS (risk ~0.5–1%), myomectomy, hysterotomy, cornual resection."),
b("<b>Obstructed labour (most common in developing countries):</b> Cephalopelvic disproportion (CPD), malpresentation (shoulder), contracted pelvis."),
b("<b>Injudicious oxytocin use / uterine hyperstimulation.</b>"),
b("Grand multiparity (thin, atrophic myometrium). Uterine anomalies. External trauma."),
h3("Clinical Features:"),
h3("Threatened (Impending) Rupture:"),
b("Bandl's ring: Pathological retraction ring visible as transverse groove on abdomen above pubic symphysis (upper edge of lower segment)."),
b("Uterine hyperstimulation — very frequent, painful contractions with poor relaxation."),
b("Haematuria (pressure on bladder). Fetal distress (late decelerations, bradycardia)."),
b("Maternal distress, tachycardia."),
h3("Actual Rupture:"),
b("<b>Sudden cessation of contractions</b> followed by constant abdominal pain."),
b("<b>Fetal distress → fetal heart absent</b> (intrauterine death post-rupture in 50–75% if delayed)."),
b("Recession of presenting part (fetus moves out of pelvis into abdomen)."),
b("<b>Maternal shock:</b> Hypotension, tachycardia, pallor."),
b("<b>Abdominal signs:</b> Guarding, rigidity (haemoperitoneum); fetal parts easily palpable abdominally."),
b("Vaginal bleeding (may be minimal if fetus extruded into abdomen — blood in peritoneum, not per vagina)."),
h3("Investigations:"),
b("Clinical diagnosis (emergency!). USS: Free fluid in abdomen, absent uterine wall continuity. CTG: Bradycardia/loss of FHR. FBC, crossmatch, coagulation screen, U&E."),
h3("Management:"),
b("<b>RESUSCITATE:</b> IV access × 2, blood transfusion, O₂, catheter, monitoring."),
b("<b>Emergency laparotomy IMMEDIATELY</b> — do not delay for investigations."),
b("<b>Repair (uterine conservation — if feasible):</b> Primary repair + bilateral tubal ligation (if family complete); in young women with small clean tear."),
b("<b>Hysterectomy:</b> If repair not feasible (extensive rupture, bladder involvement, haemorrhage uncontrolled), or if patient agrees — total/subtotal hysterectomy."),
b("Paediatric team for neonatal resuscitation."),
w("Prevention: VBAC (vaginal birth after CS) only in fully equipped centres with immediate CS facilities. Never use high-dose oxytocin in a scarred uterus without close monitoring."),
sp(),
PageBreak(),
]
# ═══════════════════════ SECTION 2: BISHOP'S SCORE ══════════════════════════
story += [h1("SECTION 2: BISHOP'S SCORE"), sp()]
story += [
p("Bishop's score is a pre-labour cervical assessment scoring system developed by <b>Dr. Edward Bishop (1964)</b> to predict the likely success of induction of labour and to determine the need for cervical ripening before induction."),
sp(0.5),
]
story.append(make_bishop_diag())
story.append(cap("Fig 6. Bishop's Score — 5 cervical parameters scored 0–3. Maximum score = 13"))
story += [
sp(0.5),
h3("The Five Parameters (DECCP):"),
tbl(["Parameter", "Score 0", "Score 1", "Score 2", "Score 3", "Notes"],
[["Dilatation of cervix", "Closed", "1–2 cm", "3–4 cm", "≥5 cm", "Most important"],
["Effacement (thinning)", "0–30%", "40–50%", "60–70%", "≥80%", "Cervical length shortening"],
["Consistency", "Firm", "Medium", "Soft", "—", "Max score 2"],
["Cervical position", "Posterior", "Mid", "Anterior", "—", "Max score 2"],
["Presenting part station", "-3", "-2", "-1 to 0", "+1 to +2", "Relative to ischial spines"]],
cw=[3.2*cm, 2*cm, 2*cm, 2*cm, 2*cm, 5.3*cm]),
sp(0.5),
h3("Interpretation:"),
b("<b>Score ≥8:</b> FAVOURABLE cervix — induction likely to succeed; proceed with oxytocin/ARM. Success rate ~90–95%."),
b("<b>Score 6–7:</b> Intermediate — cervical ripening recommended first."),
b("<b>Score ≤5:</b> UNFAVOURABLE cervix — cervical ripening mandatory before induction (prostaglandins, Foley catheter)."),
h3("Modified Bishop's Score:"),
p("Adds <b>cervical length in cm</b> as a parameter instead of effacement percentage; also assigns negative scores for post-dates, nulliparity, premature rupture of membranes."),
sp(),
]
# ═══════════════════════ SECTION 3: INDUCTION & AUGMENTATION ════════════════
story += [h1("SECTION 3: INDUCTION AND AUGMENTATION OF LABOUR"), sp()]
story += [
h2("Definitions:"),
b("<b>Induction of labour (IOL):</b> Artificial initiation of uterine contractions before spontaneous onset of labour, to achieve vaginal delivery."),
b("<b>Augmentation:</b> Enhancement of spontaneous labour that has started but is inadequate (inefficient uterine activity)."),
sp(0.5),
h2("Indications for Induction:"),
tbl(["Maternal Indications", "Fetal Indications"],
[["Post-dates (≥41 weeks)", "IUGR (intrauterine growth restriction)"],
["Pre-eclampsia/Eclampsia", "Oligohydramnios"],
["Gestational/Pre-existing diabetes", "IUFD (intrauterine fetal death)"],
["Obstetric cholestasis", "Rhesus haemolytic disease"],
["Premature rupture of membranes (PROM)", "Non-reassuring CTG at term"],
["Maternal medical disease (renal, cardiac)", "Macrosomia (selected cases)"]],
cw=[8.25*cm, 8.25*cm]),
sp(0.5),
h2("Contraindications to Induction:"),
b("Placenta praevia major / vasa praevia. Previous classical (upper segment) CS or extensive uterine surgery. Transverse/oblique lie. Active herpes infection. Cord presentation."),
sp(0.5),
h2("Methods of Induction:"),
]
story += [
h3("A. CERVICAL RIPENING (When Bishop's score ≤5):"),
b("<b>1. Prostaglandins (most widely used):</b>"),
b("Dinoprostone (PGE₂): Vaginal gel 0.5 mg (Prepidil) or intracervical, repeat after 6 hours. Vaginal tablet 3 mg (Prostin) — repeat after 6 hours if needed."),
b("Misoprostol (PGE₁): 25–50 mcg vaginally/orally every 4–6 hours. Very effective, cheap; NOT licensed for IOL in many countries (but widely used)."),
b("<b>Caution:</b> Tachysystole (>5 contractions in 10 min), uterine hyperstimulation — tocolysis with terbutaline may be needed. CONTRAINDICATED in scarred uterus (high rupture risk)."),
b("<b>2. Balloon / Foley catheter:</b> Transcervical Foley catheter (30–60 mL balloon) inserted and inflated — mechanical dilation of cervix. Safe in scarred uterus."),
b("<b>3. Membrane sweeping (stretch and sweep):</b> Examiner's finger separates chorionic membranes from lower uterine segment — releases prostaglandins endogenously. Done outpatient at 40–41 weeks."),
b("<b>4. Osmotic dilators:</b> Laminaria tents, Dilapan — hygroscopic, absorb fluid, dilate cervix mechanically over hours."),
h3("B. INDUCTION METHODS (Once cervix favourable):"),
b("<b>1. Artificial Rupture of Membranes (ARM / Amniotomy):</b> Amniohook or Drew-Smythe catheter used to rupture forewaters — releases prostaglandins and allows presenting part to engage. Used when cervix ≥2–3 cm dilated. Risk: cord prolapse (if presenting part not engaged)."),
b("<b>2. Syntocinon (Oxytocin) Infusion:</b> IV oxytocin (Syntocinon) — titrated from low dose (1–2 mU/min) upwards every 30 min. Target: 3–4 contractions in 10 minutes, each lasting 40–60 seconds. Maximum dose: 20–40 mU/min. Requires continuous CTG monitoring. Side effects: Uterine hyperstimulation, water intoxication (high doses), fetal distress."),
b("<b>ARM + Oxytocin (Combined):</b> Most effective method of induction once cervix favourable."),
h3("C. AUGMENTATION OF LABOUR (Dystocic/Slow Labour):"),
b("Primary indication: Failure to progress (prolonged active phase — cervical dilatation <1 cm/hr in active phase)."),
b("<b>ARM:</b> If membranes intact — first-line augmentation."),
b("<b>Oxytocin infusion:</b> If contractions inadequate (<3 in 10 min, or <40 sec duration) after ARM."),
b("WHO partograph used to monitor labour — action line 4 hours to the right of alert line."),
w("NEVER augment labour with oxytocin in a patient with a previous uterine scar without very careful monitoring and senior review."),
sp(),
PageBreak(),
]
# ═══════════════════════ SECTION 4: VENTOUSE ════════════════════════════════
story += [h1("SECTION 4a: VENTOUSE DELIVERY (VACUUM EXTRACTION)"), sp()]
story.append(make_ventouse_diag())
story.append(cap("Fig 7. Ventouse vacuum extractor — suction cup applied 3 cm anterior to posterior fontanelle ('flexion point')"))
story += [
sp(0.5),
p("Ventouse (vacuum extractor) uses a suction cup applied to the fetal scalp to create traction and assist delivery during the second stage of labour."),
h2("Indications:"),
b("Prolonged second stage: Nullipara >3 hours (with regional); >2 hours without. Multipara >2 hours with, >1 hour without regional anaesthesia."),
b("Suspected fetal compromise in second stage (non-reassuring CTG)."),
b("Maternal exhaustion; maternal medical conditions contraindicated to prolonged pushing (cardiac disease, intracranial aneurysm, Marfan's, severe hypertension)."),
h2("Contraindications:"),
b("<b>Fetal:</b> <34 weeks gestation (risk of intracranial haemorrhage), face presentation, active fetal bleeding/coagulopathy, suspected fetal skull fracture."),
b("<b>Obstetric:</b> Incompletely dilated cervix, cephalopelvic disproportion, uncertain presenting part."),
h2("Prerequisites (ABCDEFGH):"),
b("A — Anaesthesia (perineal anaesthesia/epidural). B — Bladder emptied. C — Cervix fully dilated. D — Denominator known (occiput). E — Engagement (head engaged). F — Fontanelle (posterior fontanelle accessible — flexing position). G — Gentle traction. H — Head position confirmed."),
h2("Procedure:"),
b("Explain procedure; consent; lithotomy position; catheterise bladder."),
b("<b>Cup selection:</b> Kiwi OmniCup (disposable), Silicone soft cup (OP positions), Rigid metal cup (OP positions — greater traction)."),
b("<b>Cup placement:</b> Applied over 'flexion point' — 3 cm anterior to posterior fontanelle, 6 cm from anterior fontanelle. Check no maternal tissue is caught under cup."),
b("<b>Suction:</b> Build pressure to 0.2 kg/cm² (check cup) → increase to 0.8 kg/cm² (0.6–0.8 = working pressure)."),
b("<b>Traction:</b> Applied with contractions and maternal pushing. Direction: Initially downward (following pelvic curve), then horizontal, then upward as head crowns."),
b("<b>Maximum pulls:</b> 3 pulls, maximum 15–20 minutes total. Abandon if: cup detaches 3 times ('three pull rule'), no progress after 3 pulls, or >20 minutes."),
h2("Complications:"),
tbl(["Fetal Complications", "Maternal Complications"],
[["Chignon (scalp oedema — resolves 24–48 hrs)", "Perineal/vaginal tears"],
["Cephalhaematoma (subperiosteal)", "Cervical tears, uterine rupture (rare)"],
["Subgaleal (subaponeurotic) haemorrhage — DANGEROUS; can cause hypovolaemic shock", "PPH"],
["Intracranial haemorrhage (rare)", "Pelvic floor damage"],
["Retinal haemorrhage", "Failed ventouse → CS → increased maternal morbidity"],
["Facial nerve palsy (rare)", "Psychological distress"]],
cw=[8.25*cm, 8.25*cm]),
sp(),
]
# ═══════════════════════ SECTION 5: FORCEPS ═════════════════════════════════
story += [h1("SECTION 4b: FORCEPS DELIVERY"), sp()]
story.append(make_forceps_diag())
story.append(cap("Fig 8. Types of obstetric forceps — Wrigley's (outlet), Anderson's/Neville-Barnes (MOD), Kielland's (rotational)"))
story += [
sp(0.5),
p("Obstetric forceps consist of two mirror-image blades that articulate at a lock. They grip the fetal head to provide traction and/or rotation to assist delivery."),
h2("Parts of Forceps Blade:"),
b("<b>Cephalic curve:</b> Fits the fetal head. <b>Pelvic curve:</b> Follows the pelvic curve (absent in Kielland's — for rotation)."),
b("Each blade: <b>blade, shank, lock, handle</b>. Lock types: English lock (Anderson's), sliding lock (Kielland's — allows correction of asynclitism)."),
h2("Types of Forceps:"),
tbl(["Forceps", "Type", "Use", "Special Feature"],
[["Wrigley's", "Short, curved", "Outlet forceps; also used at CS", "Lightweight; pelvic curve only"],
["Neville-Barnes / Anderson's", "Classic", "Most common MOD forceps in UK", "Standard blades; English lock"],
["Kielland's", "Rotational", "OT/OP position → rotation + delivery", "Minimal/absent pelvic curve; sliding lock"],
["Haig Ferguson's", "Long curved", "High forceps (historical)", "Rarely used now"],
["Piper's", "For after-coming head of breech", "Breech delivery — head last", "Long shanks, no pelvic curve"]],
cw=[3.5*cm, 2.5*cm, 4.5*cm, 6*cm]),
sp(0.5),
h2("Classification of Forceps by Station:"),
b("<b>Outlet forceps:</b> Scalp visible at introitus; skull at pelvic floor; rotation ≤45°."),
b("<b>Low forceps:</b> Leading bony part at +2 station or more."),
b("<b>Mid-cavity forceps:</b> Head engaged (station 0 to +2); most common type."),
b("<b>High forceps:</b> Head not engaged — ABANDONED (too dangerous; CS indicated)."),
h2("Indications:"),
b("<b>Same as ventouse</b> — prolonged second stage, fetal compromise, maternal exhaustion."),
b("<b>Additional:</b> After-coming head of breech (Piper's forceps), face presentation (Kielland's in mentoanterior position), preterm head protection."),
h2("Contraindications:"),
b("Cervix not fully dilated; head not engaged; face-to-pubes (mentoposterior) position; CPD; position/station not clearly identified; fetal bone disease (osteogenesis imperfecta)."),
h2("Prerequisites (Same 'ABCDEFGH' as ventouse):"),
b("Fully dilated cervix; engaged head; known position; empty bladder; adequate analgesia (spinal/epidural/pudendal); maternal consent; theatre available for immediate CS if needed."),
h2("Procedure — Application (Left blade first):"),
b("<b>Step 1:</b> Left blade (operator's left hand) applied first — inserted along left side of pelvis to lie over baby's left ear. Right blade applied next."),
b("<b>Step 2:</b> Blades locked. Check correct application: sagittal suture midway between blades; both ears equidistant; posterior fontanelle facing upward."),
b("<b>Step 3:</b> Traction — firm, steady, between contractions or with. Pajot's manoeuvre: one hand traction, other presses down on shank to follow pelvic curve."),
b("<b>Step 4:</b> Remove blades as head crowns (after anterior shoulder delivered or just before)."),
h2("Kielland's Forceps Technique:"),
b("<b>Direct application:</b> Both blades applied directly if position accessible."),
b("<b>Wandering method:</b> Anterior blade applied posteriorly and wandered around fetal head to anterior position."),
b("Rotation: Thumbs on shanks, rotate gently. NEVER use excessive force."),
h2("Complications:"),
tbl(["Fetal Complications", "Maternal Complications"],
[["Facial marks/bruising (transient)", "Perineal/vaginal/cervical tears (3rd/4th degree)"],
["Facial nerve palsy", "Bladder/urethral injury"],
["Cephalhaematoma", "Uterine rupture (rare, high forceps)"],
["Depressed skull fracture (rare)", "PPH, pelvic floor damage"],
["Intracranial haemorrhage", "Urinary/faecal incontinence (long-term)"],
["Corneal abrasion (eye trauma)", "Psychological trauma"]],
cw=[8.25*cm, 8.25*cm]),
w("Sequential use of ventouse THEN forceps significantly increases neonatal morbidity — avoid if possible."),
sp(),
PageBreak(),
]
# ═══════════════════════ SECTION 6: CAESAREAN SECTION ═══════════════════════
story += [h1("SECTION 4c: CAESAREAN SECTION (CS)"), sp()]
story.append(make_cs_diag())
story.append(cap("Fig 9. CS surgical layers — Pfannenstiel incision through 7 anatomical layers to access lower uterine segment"))
story += [
sp(0.5),
p("Caesarean section (CS) is the delivery of a fetus through surgical incisions in the abdominal wall (laparotomy) and uterine wall (hysterotomy). Currently accounts for ~21% of global deliveries."),
h2("Types of CS:"),
tbl(["Type", "Uterine Incision", "Indication", "Notes"],
[["LSCS (Lower Segment CS)", "Transverse incision in lower uterine segment", "Most common (>95%)", "Less bleeding, easier repair, lower rupture risk"],
["Classical CS", "Vertical midline upper segment incision", "Transverse lie, anterior placenta praevia, very preterm, cervical carcinoma", "Higher rupture risk in future pregnancy; MUST deliver by CS in all future pregnancies"],
["Emergency CS", "Any type — depends on urgency", "Grade 1 (immediate threat to life) to Grade 4 (elective at patient request)", "Grade 1: Delivery within 30 minutes"],
["Elective (LUSCS)", "Transverse LSCS", "Planned for non-urgent indications", "Ideally ≥39 weeks"]],
cw=[3*cm, 4*cm, 4*cm, 5.5*cm]),
sp(0.5),
h2("RCOG Classification of CS Urgency:"),
b("<b>Grade 1 (Emergency):</b> Immediate threat to maternal or fetal life — within 30 min. (e.g., cord prolapse, scar rupture, AFE, antepartum haemorrhage)."),
b("<b>Grade 2 (Urgent):</b> Maternal/fetal compromise, not immediately life-threatening — within 75 min."),
b("<b>Grade 3 (Scheduled):</b> Needs early delivery but no compromise — at next available list."),
b("<b>Grade 4 (Elective):</b> Planned, at time to suit patient and team — usually 39 weeks."),
h2("Indications:"),
tbl(["Category", "Indications"],
[["Absolute (mandatory CS)", "Placenta praevia major, contracted pelvis (absolute CPD), previous classical CS, transverse lie at term, cord prolapse (most), invasive cervical carcinoma"],
["Relative Maternal", "Severe pre-eclampsia/eclampsia, failed induction, previous LSCS with adverse features, genital herpes active, HIV viral load >1000, maternal request"],
["Relative Fetal", "Severe fetal compromise, macrosomia (>4.5 kg in diabetics), malpresentation (face—mentoposterior, brow, shoulder), twin 1 breech, preterm breech"],
["Failed Instrumental", "Failed ventouse/forceps"]],
cw=[4*cm, 12.5*cm]),
sp(0.5),
h2("Procedure — LSCS Step by Step:"),
b("<b>1. Anaesthesia:</b> Spinal (preferred — bupivacaine 0.5% heavy + fentanyl/diamorphine) OR epidural top-up OR GA (if spinal contraindicated/emergency)."),
b("<b>2. Position:</b> Supine with left lateral tilt (15°) — prevents aortocaval compression; Foley catheter."),
b("<b>3. Skin incision:</b> Pfannenstiel (transverse, 2 cm above pubic symphysis) OR Joel-Cohen (straight, 3 cm above pubic symphysis — faster, less blood loss)."),
b("<b>4. Layers incised:</b> Skin → subcutaneous fat → rectus sheath (transversely) → rectus muscles separated (blunt dissection) → peritoneum opened (vertically)."),
b("<b>5. Uterovesical peritoneum:</b> Incised transversely; bladder retracted inferiorly with Doyen's retractor."),
b("<b>6. Uterine incision:</b> Transverse 'smile' incision in lower uterine segment (1 cm above bladder reflection); extended laterally (sharp or blunt)."),
b("<b>7. Delivery:</b> Baby's head/presenting part delivered manually or with forceps/ventouse. Oxytocin 5 IU slow IV bolus given immediately after delivery."),
b("<b>8. Placenta:</b> Controlled cord traction (CCT) — avoid manual removal (increases PPH risk)."),
b("<b>9. Uterine repair:</b> Double-layer continuous suture (preferred — reduces risk of subsequent rupture)."),
b("<b>10. Closure:</b> Peritoneum may be left unsutured; rectus sheath (continuous absorbable); subcutaneous fat (if >2 cm); skin (subcuticular continuous)."),
h2("Complications:"),
tbl(["Intraoperative", "Early Postoperative", "Long-term"],
[["Haemorrhage (PPH)", "Wound infection", "Placenta praevia/accreta in future"],
["Bladder/urethral injury", "DVT/PE (2–5× higher than VD)", "Scar rupture in future pregnancy"],
["Ureteric injury", "Endometritis", "Adhesions (bowel/bladder)"],
["Anaesthetic complications", "Ileus", "Increased CS rates in future"],
["Fetal lacerations", "Anaemia", "Chronic pelvic pain"]],
cw=[5.5*cm, 5.5*cm, 5.5*cm]),
h2("VBAC (Vaginal Birth After Caesarean):"),
b("<b>Eligibility:</b> One previous LSCS with no other uterine scar; no recurrent indication; adequate pelvis; singleton cephalic; 37–41 weeks."),
b("<b>Success rate:</b> 60–80%. Risk of uterine rupture: ~0.5% (vs 0.02% for planned CS)."),
b("<b>Contraindications:</b> Previous classical CS, >2 previous CS, uterine rupture, previous uterine surgery."),
w("All VBAC should be conducted in units with 24-hour access to CS and blood transfusion services."),
sp(),
PageBreak(),
]
# ═══════════════════════ SECTION 7: ABNORMAL PRESENTATIONS ══════════════════
story += [h1("SECTION 5: ABNORMAL PRESENTATIONS"), sp()]
story += [
p("Normal presentation: Vertex (head) with occiput as denominator. Abnormal presentations include face, brow, and shoulder/transverse lie."),
sp(0.5),
]
# Face, Brow, Shoulder diagrams side by side
diag_table = Table(
[[make_face_diag(), make_brow_diag(), make_shoulder_diag()]],
colWidths=[6.1*cm, 6.1*cm, 6.1*cm]
)
diag_table.setStyle(TableStyle([
('ALIGN',(0,0),(-1,-1),'CENTER'),
('VALIGN',(0,0),(-1,-1),'MIDDLE'),
('TOPPADDING',(0,0),(-1,-1),2),
('BOTTOMPADDING',(0,0),(-1,-1),2),
]))
story.append(diag_table)
story.append(cap("Fig 10–12. Abnormal fetal presentations: Face (left), Brow (centre), Shoulder/Transverse (right)"))
story.append(sp(0.5))
# Full comparison table
story += [
tbl(["Feature", "FACE PRESENTATION", "BROW PRESENTATION", "SHOULDER PRESENTATION"],
[
["Incidence", "1 in 500–600", "1 in 500–1500", "1 in 300–400"],
["Lie", "Longitudinal", "Longitudinal", "Transverse / Oblique"],
["Denominator", "Mentum (chin)", "Frontal bone (sinciput)", "Acromion (shoulder)"],
["Presenting diameter", "Submentobregmatic: 9.5 cm (favourable)", "Mentovertical: 13.5 cm (LARGEST — cannot engage normally)", "Bisacromial: ~11 cm transversely (cannot descend)"],
["Head attitude", "Hyperextended (extreme extension)", "Partial extension (midway between flexion and extension)", "N/A — transverse lie"],
["Causes", "Anencephaly, neck tumour, platypelloid pelvis, multiparity, polyhydramnios", "Same as face (often converts to face or vertex)", "Multiparity, polyhydramnios, uterine anomaly, contracted pelvis, pelvic tumour, placenta praevia"],
["Diagnosis", "Palpation: No hard vertex felt; sinciput/chin palpated. VE: orbital ridges, nose, mouth, chin felt", "VE: Orbital ridges AND anterior fontanelle felt (both), forehead felt", "Inspection/palpation: Wide transverse uterus, no pole at fundus or pelvis. VE: Rib/shoulder/arm felt"],
["Prognosis/Delivery", "Mentoanterior (chin anterior): Vaginal delivery possible (submentobregmatic 9.5 cm). Mentoposterior: CS mandatory — chin cannot rotate", "Usually → CS. May convert to face or vertex with strong contractions. Persistent brow: CS mandatory", "CS mandatory in all cases at term. Neglected transverse lie: Impacted shoulder → threatened uterine rupture"],
["Complications", "Perineal trauma, facial oedema, bruising, neonatal airway issues", "Highest perinatal morbidity among cephalic malpositions", "Neglected transverse: Uterine rupture, maternal death, stillbirth"],
],
cw=[3.2*cm, 4.3*cm, 4.3*cm, 4.7*cm]),
sp(0.5),
]
story += [
h2("FACE PRESENTATION — Detailed:"),
h3("Diagnosis on Vaginal Examination:"),
b("Soft, irregular presenting part. Orbital ridges, nose (triangular saddle), mouth (horseshoe feel), chin (mentum) palpated."),
b("<b>Important:</b> Never confuse with breech — anus vs mouth: anus does not have alveolar ridge; finger not sucked; no triangular orbital ridges."),
h3("Management:"),
b("<b>Mentoanterior (MA) — chin pointing anterior:</b> Allow progress in labour. Head delivers by flexion under pubic symphysis after chin reaches perineum. Vaginal delivery often achieved."),
b("<b>Mentoposterior (MP) — chin pointing posterior:</b> CANNOT deliver vaginally. Long rotation needed. If chin rotates to anterior spontaneously → possible vaginal delivery. If persistent MP → EMERGENCY CS."),
b("<b>Mentolateral:</b> May rotate to MA (favourable) or MP (unfavourable). Monitor carefully."),
sp(),
h2("BROW PRESENTATION — Detailed:"),
h3("Why Brow Cannot Deliver Vaginally:"),
p("The mentovertical diameter (13.5 cm) is the largest diameter of the fetal skull. Average pelvis inlet is ~13 cm. Engagement is impossible unless conversion occurs."),
h3("Management:"),
b("<b>Early/active labour:</b> Observe — often converts spontaneously to vertex (flexion) or face (extension)."),
b("<b>Persistent brow:</b> CS mandatory — no attempt at vaginal delivery with persistent brow."),
b("<b>Internal podalic version:</b> Only if second twin with brow presentation."),
sp(),
h2("SHOULDER / TRANSVERSE LIE — Detailed:"),
h3("Complications (Neglected Transverse Lie):"),
b("<b>Arm prolapse:</b> Arm descends through cervix alongside shoulder."),
b("<b>Impacted/neglected shoulder:</b> After rupture of membranes with labour — shoulder becomes impacted in pelvis; lower segment thinned."),
b("<b>Bandl's ring:</b> Pathological retraction ring → threatened uterine rupture."),
b("<b>Uterine rupture</b> → maternal death."),
b("<b>Stillbirth</b> — if not recognised and treated early."),
h3("Management:"),
b("<b>Before labour (unstable lie at 37–38 weeks):</b> External cephalic version (ECV) attempted. If fails or recurs → admission to hospital."),
b("<b>At term / in labour:</b> CS — safest and only option."),
b("<b>Second twin with transverse lie:</b> Internal podalic version + breech extraction (experienced hands only)."),
b("<b>Neglected transverse lie with dead fetus:</b> Destructive operation (decapitation + evisceration) — only in resource-poor settings where CS not available."),
sp(),
]
# ═══════════════════════ QUICK REVISION TABLES ══════════════════════════════
story += [
h1("QUICK REVISION TABLES"),
sp(),
h2("Obstetric Emergencies — Summary"),
tbl(["Emergency", "Key Clinical Sign", "Immediate Action", "Definitive Tx"],
[["Cord prolapse", "CTG: severe variable decels; cord felt in vagina", "Elevate presenting part; Trendelenburg/knee-chest position; stop oxytocin", "Emergency CS (Grade 1); vaginal if imminent delivery"],
["Uterine inversion", "PPH + neurogenic shock; absent fundus abdominally; mass at introitus", "IV access; fluids; DO NOT remove placenta; tocolysis", "Johnson's/O'Sullivan's manoeuvre; surgical if failed"],
["AFE", "Sudden collapse + DIC + respiratory failure in labour", "CPR/intubation; vasopressors; FFP/platelets", "Perimortem CS if arrested; ICU; supportive"],
["Obstetric shock", "Hypotension + tachycardia; Shock Index >1.0", "ABCDE; IV fluids × 2; O₂; identify cause", "Cause-specific (haemostasis / antibiotics / vasopressors)"],
["Uterine rupture", "Cessation of contractions; fetal distress → absent FH; recession of presenting part; maternal shock", "Resuscitate; emergency laparotomy immediately", "Repair uterus OR hysterectomy"]],
cw=[3*cm, 4.5*cm, 4.5*cm, 4.5*cm]),
sp(),
h2("Instrumental Delivery — Comparison"),
tbl(["Feature", "Ventouse", "Forceps"],
[["Cup/blade type", "Suction cup (soft silicone / metal / disposable Kiwi)", "Metal blades (Wrigley's, Neville-Barnes, Kielland's)"],
["Prerequisites", "Fully dilated; engaged; position known; bladder empty", "Same; also adequate analgesia essential"],
["Rotation", "Can rotate passively as traction applied", "Active rotation (Kielland's) or no rotation (Wrigley's/Anderson's)"],
["Failure rate", "~15–20%", "~5–10%"],
["Fetal risk", "Chignon, cephalhaematoma, subgaleal haemorrhage", "Facial marks, nerve palsy, skull fracture (rare)"],
["Maternal risk", "Less maternal trauma", "Higher perineal/vaginal tears (3rd/4th degree)"],
["Preference in UK", "Preferred first-line in most centres (less maternal trauma)", "For rotation, OP position, preterm, after-coming head of breech"],
["Abandoned if", "3 pop-offs OR no progress after 3 pulls (20 min max)", "No progress after 3 pulls; CPD confirmed"]],
cw=[3.5*cm, 7*cm, 6*cm]),
sp(2),
hr(),
Paragraph("Sources: Harrison's Principles of Internal Medicine 22E | Goldman-Cecil Medicine | Rosen's Emergency Medicine | Robbins Pathology 11E | Orris Medical Synthesis", FOOT_S),
Paragraph("Prepared by Orris AI Medical Assistant | July 2026 | For Academic / Exam Use Only", FOOT_S),
]
doc.build(story)
print("PDF generated:", OUTPUT)
cd /home/daytona/workspace/obstetrics-notes && python gen_obs_pdf.py 2>&1
~/obstetrics-notes/gen_obs_pdf.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/obstetrics-notes/gen_obs_pdf.py'
cd /home/daytona/workspace/obstetrics-notes && python gen_obs_pdf.py 2>&1
ls -lh /home/daytona/workspace/obstetrics-notes/Obstetrics_Emergency_Notes.pdf
Obstetrics Emergency Notes
PDF Document · PDF
| Topic | Diagram | Content |
|---|---|---|
| Cord Prolapse | Fig 1 — Cord past presenting part | Causes, PUSH UP protocol, management, complications |
| Uterine Inversion | Fig 2 — Fundus inverted into vagina | 4 degrees, Johnson's & O'Sullivan's manoeuvres, surgical options |
| Amniotic Fluid Embolism | Fig 3 — Cascade pathway diagram | Two-phase model, DIC, CPR, perimortem CS |
| Obstetric Shock | Fig 4 — 5 types of shock boxes | Shock Index formula, ABCDE approach, massive transfusion |
| Uterine Rupture | Fig 5 — Rupture sites on uterus | Bandl's ring, threatened vs actual, laparotomy/hysterectomy |
If possible reform or re editit in schematic representation
If possible reform or re edit it in schematic representation
~/obstetrics-notes/gen_schematic.py
"""
Obstetrics 20-Mark Notes — Full Schematic PDF
All content in flowcharts, decision trees, mind-map boxes, color-coded schemas
"""
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import cm, mm
from reportlab.lib import colors
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import (
SimpleDocTemplate, Spacer, Table, TableStyle,
HRFlowable, PageBreak, Paragraph
)
from reportlab.graphics.shapes import (
Drawing, Rect, Circle, Ellipse, Line, String,
Polygon, PolyLine, Group
)
import os
os.makedirs("/home/daytona/workspace/obstetrics-notes", exist_ok=True)
OUT = "/home/daytona/workspace/obstetrics-notes/Obstetrics_Schematic.pdf"
PW, PH = A4
LM = RM = 1.6*cm
TM = BM = 1.8*cm
UW = PW - LM - RM # usable width ~17.9 cm
doc = SimpleDocTemplate(OUT, pagesize=A4,
leftMargin=LM, rightMargin=RM,
topMargin=TM, bottomMargin=BM,
title="Obstetrics Schematic Notes – 20 Marks",
author="Orris Medical")
# ── Colour palette ─────────────────────────────────────────
C = dict(
navy = colors.HexColor("#0D1B6E"),
dblue = colors.HexColor("#1565C0"),
lblue = colors.HexColor("#E3F2FD"),
sky = colors.HexColor("#B3E5FC"),
teal = colors.HexColor("#00838F"),
lteal = colors.HexColor("#E0F7FA"),
green = colors.HexColor("#2E7D32"),
lgreen = colors.HexColor("#E8F5E9"),
orange = colors.HexColor("#E65100"),
lorange= colors.HexColor("#FFF3E0"),
red = colors.HexColor("#B71C1C"),
lred = colors.HexColor("#FFCDD2"),
purple = colors.HexColor("#4A148C"),
lpurple= colors.HexColor("#F3E5F5"),
amber = colors.HexColor("#F57F17"),
lamber = colors.HexColor("#FFF8E1"),
grey = colors.HexColor("#546E7A"),
lgrey = colors.HexColor("#ECEFF1"),
white = colors.white,
black = colors.black,
)
# ── Paragraph styles ───────────────────────────────────────
def PS(name, **kw):
base = dict(fontName="Helvetica", fontSize=9, leading=12,
textColor=C["black"], spaceAfter=2, spaceBefore=1)
base.update(kw)
return ParagraphStyle(name, **base)
TITLE = PS("T", fontName="Helvetica-Bold", fontSize=19, textColor=C["navy"],
alignment=TA_CENTER, spaceAfter=4, spaceBefore=6)
SUBT = PS("S", fontSize=10, textColor=C["purple"], alignment=TA_CENTER,
fontName="Helvetica-Oblique", spaceAfter=6)
SEC = PS("SE", fontName="Helvetica-Bold", fontSize=12, textColor=C["white"],
alignment=TA_CENTER, spaceBefore=10, spaceAfter=4)
SECBG = PS("SB", fontName="Helvetica-Bold", fontSize=11, textColor=C["navy"],
spaceBefore=8, spaceAfter=4)
BODY = PS("BO", fontSize=9, leading=13, alignment=TA_JUSTIFY)
BCAP = PS("BC", fontSize=8, textColor=C["grey"], alignment=TA_CENTER,
fontName="Helvetica-Oblique", spaceAfter=4)
FOOT = PS("FO", fontSize=7.5, textColor=C["grey"], alignment=TA_CENTER,
fontName="Helvetica-Oblique")
TH = PS("TH", fontName="Helvetica-Bold", fontSize=8.5, textColor=C["white"],
alignment=TA_CENTER)
TD = PS("TD", fontSize=8.5, leading=11)
def sp(n=1): return Spacer(1, n*0.25*cm)
def hr(): return HRFlowable(width="100%", thickness=0.7,
color=C["navy"], spaceAfter=3, spaceBefore=2)
def p(t): return Paragraph(t, BODY)
def cap(t): return Paragraph(t, BCAP)
# ═══════════════════════════════════════════════════════════
# SCHEMATIC DRAWING HELPERS
# ═══════════════════════════════════════════════════════════
def box(d, x, y, w, h, bg, fg=None, text="", fs=8, bold=False,
rx=5, border=C["navy"], bw=1, tc=None):
"""Rounded rectangle with centred text."""
if fg is None: fg = border
if tc is None: tc = C["white"] if _dark(bg) else C["navy"]
d.add(Rect(x, y, w, h, rx=rx, ry=rx,
fillColor=bg, strokeColor=fg, strokeWidth=bw))
if text:
fn = "Helvetica-Bold" if bold else "Helvetica"
lines = text.split("\n")
lh = fs * 1.25
total = lh * len(lines)
for i, ln in enumerate(lines):
ty = y + h/2 + total/2 - lh*(i+0.5) - 1
d.add(String(x + w/2, ty, ln, fontSize=fs,
fontName=fn, fillColor=tc,
textAnchor="middle"))
def _dark(col):
"""Rough luma check — is colour dark?"""
try:
r,g,b = col.red, col.green, col.blue
return (0.299*r + 0.587*g + 0.114*b) < 0.55
except:
return False
def arrow(d, x1, y1, x2, y2, col=C["navy"], w=1.2, head=6):
"""Arrow from (x1,y1)→(x2,y2)."""
d.add(Line(x1, y1, x2, y2, strokeColor=col, strokeWidth=w))
# arrowhead
import math
angle = math.atan2(y2-y1, x2-x1)
for sign in (+1, -1):
ax = x2 - head*math.cos(angle - sign*0.5)
ay = y2 - head*math.sin(angle - sign*0.5)
d.add(Line(x2, y2, ax, ay, strokeColor=col, strokeWidth=w))
def label(d, x, y, text, fs=7.5, col=C["grey"], anchor="middle"):
d.add(String(x, y, text, fontSize=fs, fillColor=col, textAnchor=anchor))
def diamond(d, cx, cy, hw, hh, bg, text="", fs=7.5, tc=None):
"""Decision diamond."""
if tc is None: tc = C["white"] if _dark(bg) else C["navy"]
pts = [cx, cy+hh, cx+hw, cy, cx, cy-hh, cx-hw, cy]
d.add(Polygon(pts, fillColor=bg, strokeColor=C["navy"], strokeWidth=1.2))
if text:
lines = text.split("\n")
lh = fs*1.3
total = lh*len(lines)
for i,ln in enumerate(lines):
ty = cy + total/2 - lh*(i+0.5) - 1
d.add(String(cx, ty, ln, fontSize=fs,
fontName="Helvetica-Bold", fillColor=tc,
textAnchor="middle"))
def tbl(headers, rows, cw=None, hbg=None):
if hbg is None: hbg = C["navy"]
data = [[Paragraph(h, TH) for h in headers]]
for row in rows:
data.append([Paragraph(str(c), TD) for c in row])
if cw is None: cw = [None]*len(headers)
t = Table(data, colWidths=cw, hAlign='LEFT')
t.setStyle(TableStyle([
('BACKGROUND',(0,0),(-1,0), hbg),
('ROWBACKGROUNDS',(0,1),(-1,-1),[C["lblue"], C["white"]]),
('GRID',(0,0),(-1,-1),0.4, C["sky"]),
('VALIGN',(0,0),(-1,-1),'TOP'),
('TOPPADDING',(0,0),(-1,-1),3),
('BOTTOMPADDING',(0,0),(-1,-1),3),
('LEFTPADDING',(0,0),(-1,-1),4),
('RIGHTPADDING',(0,0),(-1,-1),4),
]))
return t
def sec_banner(text, bg=None):
if bg is None: bg = C["navy"]
t = Table([[Paragraph(text, SEC)]], colWidths=[UW])
t.setStyle(TableStyle([
('BACKGROUND',(0,0),(-1,-1), bg),
('TOPPADDING',(0,0),(-1,-1),6),
('BOTTOMPADDING',(0,0),(-1,-1),6),
('LEFTPADDING',(0,0),(-1,-1),8),
('ROUNDEDCORNERS',[4,4,4,4]),
]))
return t
def subsec(text, bg=None, tc=None):
if bg is None: bg = C["dblue"]
if tc is None: tc = C["white"]
st = PS("SS", fontName="Helvetica-Bold", fontSize=10.5,
textColor=tc, alignment=TA_LEFT,
spaceBefore=6, spaceAfter=3)
t = Table([[Paragraph(f" {text}", st)]], colWidths=[UW])
t.setStyle(TableStyle([
('BACKGROUND',(0,0),(-1,-1), bg),
('TOPPADDING',(0,0),(-1,-1),4),
('BOTTOMPADDING',(0,0),(-1,-1),4),
('LEFTPADDING',(0,0),(-1,-1),4),
('ROUNDEDCORNERS',[3,3,3,3]),
]))
return t
# ══════════════════════════════════════════════════════════════════════════
# SCHEMATIC DIAGRAMS
# ══════════════════════════════════════════════════════════════════════════
# ─── MIND MAP helper ──────────────────────────────────────────────────────
def mind_map(title, branches, dw=500, dh=200,
centre_bg=None, branch_bgs=None):
"""
Radial mind map: centre box + list of (label, [subitems]) branches.
"""
if centre_bg is None: centre_bg = C["navy"]
if branch_bgs is None: branch_bgs = [C["dblue"],C["teal"],C["green"],
C["orange"],C["purple"],C["amber"],C["red"]]
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=C["lgrey"], strokeColor=C["navy"],
strokeWidth=0.4, rx=6))
cx, cy = dw/2, dh/2
cw, ch = 100, 36
box(d, cx-cw/2, cy-ch/2, cw, ch, centre_bg,
text=title, fs=9, bold=True)
n = len(branches)
import math
for i, (label_txt, subs) in enumerate(branches):
angle = math.pi/2 + i * (2*math.pi/n) # top → clockwise
# branch box position
dist = min(dh, dw)*0.34
bx = cx + dist*math.cos(angle)
by = cy + dist*math.sin(angle)
bw, bh = 100, 26
bg = branch_bgs[i % len(branch_bgs)]
# line centre → branch
d.add(Line(cx, cy, bx, by, strokeColor=bg, strokeWidth=1.5))
box(d, bx-bw/2, by-bh/2, bw, bh, bg,
text=label_txt, fs=8, bold=True)
# sub-items radiate further
for j, sub in enumerate(subs):
sangle = angle + (j - (len(subs)-1)/2)*0.45
sdist = dist + 48
sx = cx + sdist*math.cos(sangle)
sy = cy + sdist*math.sin(sangle)
sw, sh = 85, 18
if 0+sw/2 < sx < dw-sw/2 and 0+sh/2 < sy < dh-sh/2:
d.add(Line(bx, by, sx, sy, strokeColor=bg,
strokeWidth=0.8, strokeDashArray=[2,2]))
lc = colors.HexColor("#37474F")
d.add(Rect(sx-sw/2, sy-sh/2, sw, sh, rx=3, ry=3,
fillColor=C["white"], strokeColor=bg,
strokeWidth=0.7))
d.add(String(sx, sy-4, sub, fontSize=6.5,
fillColor=lc, textAnchor="middle"))
return d
# ─── FLOWCHART helper ─────────────────────────────────────────────────────
def flowchart(steps, dw=480, colours=None, title=None):
"""
Vertical flowchart: list of (text, shape) where shape in
'rect','diamond','rounded','oval'.
"""
bh = 32
pad = 14
total = len(steps)
dh = total*(bh+pad) + 30 + (30 if title else 0)
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.4, rx=6))
if colours is None:
colours = [C["navy"],C["dblue"],C["teal"],C["green"],
C["orange"],C["purple"],C["amber"],C["red"]]*4
y0 = dh - (30 if title else 4)
if title:
d.add(String(dw/2, dh-20, title, fontSize=9.5,
fontName="Helvetica-Bold", fillColor=C["navy"],
textAnchor="middle"))
cx = dw/2
bw = dw*0.72
prev_y = None
for i, (text, shape) in enumerate(steps):
y = y0 - bh - i*(bh+pad)
cy_box = y + bh/2
bg = colours[i % len(colours)]
tc = C["white"] if _dark(bg) else C["navy"]
if shape == "diamond":
hw, hh = bw*0.42, bh*0.7
diamond(d, cx, cy_box, hw, hh, bg, text=text, tc=tc, fs=8)
elif shape == "oval":
d.add(Ellipse(cx-bw/2, y, bw, bh,
fillColor=bg, strokeColor=C["navy"], strokeWidth=1))
d.add(String(cx, cy_box-4, text, fontSize=8,
fontName="Helvetica-Bold", fillColor=tc,
textAnchor="middle"))
else:
rx = 15 if shape=="rounded" else 4
box(d, cx-bw/2, y, bw, bh, bg, text=text,
fs=8, bold=True, rx=rx, tc=tc)
if prev_y is not None:
arrow(d, cx, prev_y, cx, y+bh, col=C["grey"], w=1.2, head=5)
prev_y = y
return d
# ─── HORIZONTAL PROCESS FLOW ──────────────────────────────────────────────
def hflow(items, dw=490, dh=70, colours=None, title=None):
"""Left→right process boxes with arrows."""
if colours is None:
colours = [C["navy"],C["dblue"],C["teal"],C["green"],
C["orange"],C["purple"],C["red"],C["amber"]]*3
extra_h = 22 if title else 0
total_dh = dh + extra_h
d = Drawing(dw, total_dh)
d.add(Rect(0,0,dw,total_dh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.4, rx=6))
if title:
d.add(String(dw/2, total_dh-15, title, fontSize=9,
fontName="Helvetica-Bold", fillColor=C["navy"],
textAnchor="middle"))
n = len(items)
bw = (dw - 10 - (n-1)*18) / n
bh = dh - 14
y0 = 8
for i, txt in enumerate(items):
x = 5 + i*(bw+18)
bg = colours[i % len(colours)]
tc = C["white"] if _dark(bg) else C["navy"]
box(d, x, y0, bw, bh, bg, text=txt, fs=8, bold=True, rx=5, tc=tc)
if i < n-1:
mid_y = y0 + bh/2
arrow(d, x+bw, mid_y, x+bw+18, mid_y,
col=C["navy"], w=1.5, head=6)
return d
# ─── TWO-COLUMN SCHEMA ────────────────────────────────────────────────────
def two_col_schema(left_title, left_items, right_title, right_items,
dw=490, lbg=C["dblue"], rbg=C["teal"],
title=None):
"""Two side-by-side bullet boxes."""
extra = 22 if title else 0
dh = max(len(left_items), len(right_items))*18 + 50 + extra
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.4, rx=6))
if title:
d.add(String(dw/2, dh-15, title, fontSize=9.5,
fontName="Helvetica-Bold", fillColor=C["navy"],
textAnchor="middle"))
cw = dw/2 - 8
for xi, (hdr, items, hbg) in enumerate([
(left_title, left_items, lbg),
(right_title, right_items, rbg)]):
x = 4 + xi*(cw+8)
yt = dh - extra - 22
box(d, x, yt, cw, 20, hbg, text=hdr, fs=8.5, bold=True)
for j, item in enumerate(items):
iy = yt - 20 - j*17
tc_col = C["navy"]
d.add(Rect(x, iy, cw, 16, rx=3, ry=3,
fillColor=C["white"] if j%2==0 else C["lblue"],
strokeColor=hbg, strokeWidth=0.5))
txt = f"• {item}"
d.add(String(x+4, iy+4, txt, fontSize=7, fillColor=tc_col))
return d
# ─── GRID SCHEMA ──────────────────────────────────────────────────────────
def grid_schema(items, cols=3, dw=490, item_h=50,
colours=None, title=None):
"""Grid of colored boxes."""
if colours is None:
colours = [C["dblue"],C["teal"],C["green"],C["orange"],
C["purple"],C["amber"],C["red"],C["navy"]]*4
rows = (len(items)+cols-1)//cols
extra = 24 if title else 0
dh = rows*item_h + 12 + extra
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.4, rx=6))
if title:
d.add(String(dw/2, dh-16, title, fontSize=9.5,
fontName="Helvetica-Bold", fillColor=C["navy"],
textAnchor="middle"))
bw = (dw-10)/cols
for i, (hdr, detail) in enumerate(items):
r, c = divmod(i, cols)
x = 5 + c*bw
y = dh - extra - 8 - (r+1)*item_h
bg = colours[i % len(colours)]
tc = C["white"] if _dark(bg) else C["navy"]
box(d, x, y, bw-4, item_h-4, bg, rx=5, tc=tc)
d.add(String(x+(bw-4)/2, y+item_h-16, hdr,
fontSize=8, fontName="Helvetica-Bold",
fillColor=tc, textAnchor="middle"))
lines = detail.split("\n")
for li, ln in enumerate(lines):
d.add(String(x+(bw-4)/2, y+item_h-28-li*10, ln,
fontSize=6.5, fillColor=tc, textAnchor="middle"))
return d
# ─── BISHOP'S SCORE VISUAL GRID ───────────────────────────────────────────
def bishop_schema(dw=490, dh=155):
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.4, rx=6))
d.add(String(dw/2, dh-14, "BISHOP'S SCORE — Cervical Assessment",
fontSize=10, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
cols = ["Feature","Score 0","Score 1","Score 2","Score 3"]
rows = [
("Dilatation","Closed","1–2 cm","3–4 cm","≥5 cm"),
("Effacement","0–30%","40–50%","60–70%","≥80%"),
("Station","-3","-2","-1/0","+1/+2"),
("Consistency","Firm","Medium","Soft","—"),
("Position","Post.","Mid","Ant.","—"),
]
score_bgs = [C["lred"],C["lamber"],C["lgreen"],C["lteal"]]
score_fgs = [C["red"],C["amber"],C["green"],C["teal"]]
cws = [82, 72, 72, 72, 72]
row_h = 20
header_h = 22
y0 = dh - 28
xs = [4]
for w in cws[:-1]: xs.append(xs[-1]+w)
# header
for ci,(col,cw,x) in enumerate(zip(cols,cws,xs)):
bg = C["navy"] if ci==0 else [C["red"],C["amber"],C["green"],C["teal"]][ci-1]
box(d, x, y0-header_h, cw-2, header_h, bg,
text=col, fs=8, bold=True, rx=3)
# data rows
for ri, row in enumerate(rows):
for ci, (val, cw, x) in enumerate(zip(row, cws, xs)):
if ci == 0:
bg = C["navy"]; tc = C["white"]
else:
bg = score_bgs[ci-1] if ri%2==0 else C["white"]
tc = C["navy"]
y = y0 - header_h - (ri+1)*row_h - ri*1
box(d, x, y, cw-2, row_h-1, bg, text=val,
fs=7.5, tc=tc, rx=2)
# interpretation
d.add(Rect(4, 4, 230, 16, rx=4, ry=4,
fillColor=C["red"], strokeColor=None))
d.add(String(8, 8, "Score ≤5 = UNFAVOURABLE → cervical ripening first",
fontSize=7, fillColor=C["white"]))
d.add(Rect(240, 4, 240, 16, rx=4, ry=4,
fillColor=C["green"], strokeColor=None))
d.add(String(244, 8, "Score ≥8 = FAVOURABLE → proceed with induction",
fontSize=7, fillColor=C["white"]))
return d
# ─── DECISION TREE: CORD PROLAPSE MANAGEMENT ──────────────────────────────
def cord_prolapse_tree(dw=490, dh=310):
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.4, rx=6))
# Title
d.add(String(dw/2, dh-14, "CORD PROLAPSE — Management Decision Tree",
fontSize=9.5, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
# START box
box(d, 180, dh-48, 130, 26, C["red"], text="CORD PROLAPSE", fs=9, bold=True)
arrow(d, 245, dh-48, 245, dh-70, col=C["red"], w=1.5)
# PUSH UP box
box(d, 145, dh-96, 200, 26, C["navy"],
text="PUSH UP Protocol\n(Elevate head • Trendelenburg)", fs=8, bold=True)
arrow(d, 245, dh-96, 245, dh-118)
# Check viable?
diamond(d, 245, dh-138, 90, 20, C["amber"],
text="Fetus alive &\nviable?", fs=8)
# YES → fully dilated?
arrow(d, 155, dh-138, 60, dh-138, col=C["green"], w=1.2)
label(d, 108, dh-132, "YES", 7.5, C["green"])
diamond(d, 60, dh-160, 55, 22, C["teal"],
text="Fully\ndilated?", fs=7.5)
# YES → vaginal
arrow(d, 60, dh-182, 60, dh-208, col=C["teal"], w=1.2)
label(d, 62, dh-195, "YES", 7, C["teal"])
box(d, 10, dh-228, 100, 24, C["teal"],
text="Immediate\nVaginal Delivery", fs=7.5, bold=True)
# NO → CS
arrow(d, 15, dh-160, 15, dh-228, col=C["dblue"], w=1.2)
label(d, 1, dh-195, "NO", 7, C["red"])
box(d, 10, dh-252, 100, 22, C["dblue"],
text="Emergency\nCS Grade 1", fs=7.5, bold=True)
# NO fetus → delivery anyway
arrow(d, 335, dh-138, 410, dh-138, col=C["red"], w=1.2)
label(d, 368, dh-132, "NO", 7.5, C["red"])
box(d, 370, dh-150, 110, 24, C["grey"],
text="Consider maternal\nwellbeing only", fs=7.5)
# main YES chain continues
arrow(d, 245, dh-158, 245, dh-185)
box(d, 155, dh-209, 180, 26, C["dblue"],
text="Emergency CS Grade 1\n(within 30 min)", fs=8, bold=True)
arrow(d, 245, dh-209, 245, dh-232)
box(d, 155, dh-256, 180, 26, C["green"],
text="Neonatologist present\nActive resuscitation", fs=7.5)
# Prevent box
box(d, 150, dh-292, 190, 26, C["purple"],
text="PREVENTION:\nARM only when head engaged", fs=7.5)
return d
# ─── UTERINE INVERSION MANAGEMENT ────────────────────────────────────────
def inversion_schema(dw=490, dh=240):
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.4, rx=6))
d.add(String(dw/2, dh-14, "UTERINE INVERSION — Management Flow",
fontSize=9.5, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
steps = [
("CALL FOR HELP + IV ACCESS + O₂ + MONITORING", C["red"], 240, 28),
("STOP OXYTOCIN | Do NOT remove placenta", C["orange"], 260, 24),
("Tocolysis: Terbutaline 250 mcg SC / GTN / GA", C["amber"], 260, 22),
("Manual Replacement: Johnson's Manoeuvre\n(Push fundus up through vagina toward umbilicus)", C["dblue"], 300, 32),
("O'Sullivan's Hydrostatic Method\n(3–5 L warm saline into vagina, block introitus)", C["teal"], 300, 32),
]
bw_pad = (dw - 10)
y = dh - 34
for i, (txt, col, bwi, bhi) in enumerate(steps):
bx = (dw - bwi) / 2
y -= bhi + 4
box(d, bx, y, bwi, bhi, col, text=txt, fs=8, bold=(i==0))
if i < len(steps)-1:
arrow(d, dw/2, y, dw/2, y-4, col=C["grey"], w=1.2, head=5)
# Two surgical branches
y -= 24
d.add(String(dw/2, y+8, "If manual methods FAIL →", fontSize=8,
fillColor=C["red"], textAnchor="middle", fontName="Helvetica-Bold"))
arrow(d, 170, y, 90, y-16, col=C["navy"], w=1.2)
arrow(d, 320, y, 400, y-16, col=C["navy"], w=1.2)
box(d, 20, y-40, 150, 24, C["navy"],
text="Huntington's Op\n(abdominal — pull up)", fs=7.5)
box(d, 320, y-40, 155, 24, C["purple"],
text="Haultain's Op\n(posterior cervical incision)", fs=7.5)
box(d, 170, y-40, 140, 24, C["green"],
text="After replacement:\nOxytocin immediately", fs=7.5)
return d
# ─── AFE CASCADE ──────────────────────────────────────────────────────────
def afe_cascade(dw=490, dh=200):
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.4, rx=6))
d.add(String(dw/2, dh-14, "AMNIOTIC FLUID EMBOLISM — Pathophysiology & Management",
fontSize=9.5, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
# Phase 1 row
ph1 = [("Trigger\n(labour/CS/ARM)", C["orange"]),
("AF enters\npulmonary circ.", C["amber"]),
("Pulmonary\nvasospasm", C["red"]),
("Acute Rt heart\nfailure + Hypoxia", C["red"])]
bw = 90; bh = 36; y1 = dh-60
for i,(txt,col) in enumerate(ph1):
x = 10 + i*(bw+18)
box(d, x, y1, bw, bh, col, text=txt, fs=7.5, bold=(i==0))
if i<len(ph1)-1:
arrow(d, x+bw, y1+bh/2, x+bw+18, y1+bh/2, col=C["navy"], w=1.5)
# Phase 2 row
ph2 = [("LV Failure\n+ pulm. oedema", C["purple"]),
("DIC\nCoagulopathy", C["red"]),
("Massive PPH\n+ Haemorrhage", C["navy"]),
("Seizures /\nCardiac Arrest", C["red"])]
y2 = dh-116
for i,(txt,col) in enumerate(ph2):
x = 10+i*(bw+18)
box(d, x, y2, bw, bh, col, text=txt, fs=7.5)
if i<len(ph2)-1:
arrow(d, x+bw, y2+bh/2, x+bw+18, y2+bh/2, col=C["navy"], w=1.5)
arrow(d, 245, y1, 245, y2+bh, col=C["red"], w=1.5)
label(d, 250, (y1+y2+bh)/2, "Phase 2\n(30 min later)", 7, C["red"])
# Management row
mgmt = [("Intubate\n+ 100% O₂", C["teal"]),
("CPR +\nVasopressors", C["dblue"]),
("FFP + Platelets\n+ Cryo + TXA", C["green"]),
("Perimortem\nCS if arrested", C["navy"])]
y3 = dh-170
d.add(Rect(6, y3-4, dw-12, 56, rx=4, ry=4,
fillColor=colors.HexColor("#E0F2F1"),
strokeColor=C["teal"], strokeWidth=1))
d.add(String(dw/2, y3+46, "MANAGEMENT (Supportive)",
fontSize=7.5, fillColor=C["teal"],
fontName="Helvetica-Bold", textAnchor="middle"))
for i,(txt,col) in enumerate(mgmt):
x = 10+i*(bw+18)
box(d, x, y3+4, bw, 36, col, text=txt, fs=7.5)
if i<len(mgmt)-1:
arrow(d, x+bw, y3+22, x+bw+18, y3+22, col=C["teal"], w=1.2)
return d
# ─── SHOCK SCHEMA ─────────────────────────────────────────────────────────
def shock_schema(dw=490, dh=210):
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.4, rx=6))
d.add(String(dw/2, dh-14, "OBSTETRIC SHOCK — Classification & ABCDE Management",
fontSize=9.5, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
# Shock types
types = [
("HAEMO-\nRRHAGIC","PPH/APH\nRupture", C["red"]),
("SEPTIC","Chorioamnion.\nSepsis", C["orange"]),
("NEURO-\nGENIC","Inversion\nPain/Epidural",C["purple"]),
("CARDIO-\nGENIC","AFE\nPeripartum CM", C["dblue"]),
("ANAPHY-\nLACTIC","Drug Rxn\nTransfusion",C["teal"]),
]
bw=80; bh=52; y_types = dh-82
for i,(t,d2,col) in enumerate(types):
x = 10+i*(bw+8)
box(d, x, y_types, bw, bh, col, text=f"{t}\n{d2}",
fs=7, bold=False)
# Central shock box
box(d, 150, y_types-36, 190, 28, C["navy"],
text="SHOCK\n(SBP<90 + HR>100)", fs=9, bold=True)
for i in range(5):
x = 10+i*(bw+8)+bw//2
arrow(d, x, y_types, 245, y_types-8, col=C["grey"], w=0.8)
# ABCDE management
abcde = [
("A","Airway\nIntubate if GCS<8", C["navy"]),
("B","Breathing\n100% O₂ NRB", C["dblue"]),
("C","Circulation\n2 large bore IV\nFluids + Blood", C["teal"]),
("D","Disability\nGCS/AVPU\nBlood glucose", C["green"]),
("E","Exposure\nFind & treat\nunderlying cause", C["orange"]),
]
bw2=76; bh2=56; y_abcde = dh-185
d.add(String(dw/2, y_abcde+60,
"ABCDE Management",
fontSize=8, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
arrow(d, 245, y_types-36, 245, y_abcde+56, col=C["navy"], w=1.5)
for i,(letter,detail,col) in enumerate(abcde):
x = 8+i*(bw2+6)
box(d, x, y_abcde, bw2, bh2, col,
text=f"{letter}\n{detail}", fs=7, bold=False)
# Shock Index
d.add(Rect(6, 4, 200, 16, rx=3, ry=3,
fillColor=C["amber"], strokeColor=None))
d.add(String(10, 8, "Shock Index = HR / SBP | Normal: 0.5–0.7 | >1.0 = significant haemorrhage",
fontSize=7, fillColor=C["navy"]))
return d
# ─── UTERINE RUPTURE DECISION ──────────────────────────────────────────────
def rupture_schema(dw=490, dh=260):
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.4, rx=6))
d.add(String(dw/2, dh-14,
"UTERINE RUPTURE — Signs, Degrees & Management",
fontSize=9.5, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
# threatened vs actual
box(d, 10, dh-52, 220, 30, C["amber"],
text="THREATENED RUPTURE\nBandl's ring • Tachycardia • CTG changes", fs=7.5, bold=True)
box(d, 260, dh-52, 220, 30, C["red"],
text="ACTUAL RUPTURE\nContractions STOP • FHR absent • Shock", fs=7.5, bold=True)
arrow(d, 120, dh-52, 120, dh-94, col=C["amber"], w=1.2)
arrow(d, 370, dh-52, 370, dh-94, col=C["red"], w=1.5)
# causes
box(d, 10, dh-118, 220, 24, C["lamber"],
text="Causes: LSCS scar • CPD • Oxytocin overuse\nGrand multiparity • Malpresentation",
fs=7, tc=C["navy"])
box(d, 260, dh-118, 220, 24, C["lred"],
text="Signs: Recession of presenting part\nAbdominal guarding • Vaginal bleeding",
fs=7, tc=C["navy"])
# Resuscitate
box(d, 145, dh-148, 200, 22, C["navy"],
text="RESUSCITATE: IV × 2 + Blood + O₂", fs=8, bold=True)
arrow(d, 245, dh-118, 245, dh-126, col=C["navy"], w=1.5)
arrow(d, 120, dh-118, 245, dh-148, col=C["amber"], w=1)
arrow(d, 370, dh-118, 245, dh-148, col=C["red"], w=1)
arrow(d, 245, dh-148, 245, dh-172, col=C["navy"], w=1.5)
box(d, 105, dh-196, 270, 24, C["red"],
text="EMERGENCY LAPAROTOMY — DO NOT DELAY", fs=9, bold=True)
arrow(d, 245, dh-196, 245, dh-218, col=C["navy"], w=1.5)
# repair vs hyst
box(d, 30, dh-240, 170, 24, C["teal"],
text="REPAIR (if feasible)\nPrimary suture + BTL", fs=7.5)
box(d, 285, dh-240, 170, 24, C["purple"],
text="HYSTERECTOMY\n(extensive / uncontrolled bleed)", fs=7.5)
arrow(d, 245, dh-218, 120, dh-216, col=C["teal"], w=1)
arrow(d, 245, dh-218, 370, dh-216, col=C["purple"], w=1)
return d
# ─── INDUCTION DECISION TREE ──────────────────────────────────────────────
def induction_tree(dw=490, dh=300):
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.4, rx=6))
d.add(String(dw/2, dh-14,
"INDUCTION & AUGMENTATION — Decision Algorithm",
fontSize=9.5, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
# IOL indication
box(d, 155, dh-46, 180, 24, C["navy"],
text="Indication for IOL", fs=9, bold=True)
arrow(d, 245, dh-46, 245, dh-68, col=C["navy"], w=1.5)
# Check contraindication
diamond(d, 245, dh-86, 100, 22, C["red"],
text="Contraindication\npresent?", fs=8)
arrow(d, 345, dh-86, 430, dh-86, col=C["red"], w=1.2)
box(d, 380, dh-98, 100, 24, C["red"],
text="CS instead\nPlan accordingly", fs=7.5)
label(d, 385, dh-80, "YES", 7.5, C["red"])
arrow(d, 245, dh-108, 245, dh-130, col=C["green"], w=1.2)
label(d, 248, dh-120, "NO", 7.5, C["green"])
# Bishop's
diamond(d, 245, dh-150, 100, 22, C["amber"],
text="Bishop's\nScore?", fs=8)
# ≤5 branch
arrow(d, 145, dh-150, 60, dh-150, col=C["red"], w=1.2)
label(d, 92, dh-144, "≤5", 7.5, C["red"])
box(d, 5, dh-168, 110, 32, C["orange"],
text="RIPEN CERVIX\nPGE₂/Misoprostol\nFoley balloon", fs=7.5)
arrow(d, 60, dh-168, 60, dh-214, col=C["orange"], w=1.2)
box(d, 5, dh-236, 110, 24, C["amber"],
text="Reassess Bishop's\nafter 6–12 hrs", fs=7.5)
# ≥8 branch
arrow(d, 345, dh-150, 420, dh-150, col=C["green"], w=1.2)
label(d, 373, dh-144, "≥8", 7.5, C["green"])
box(d, 375, dh-168, 110, 24, C["teal"],
text="FAVOURABLE\nProceed to ARM", fs=7.5)
arrow(d, 430, dh-168, 430, dh-212, col=C["teal"], w=1.2)
box(d, 375, dh-236, 110, 26, C["teal"],
text="ARM + Syntocinon\ninfusion", fs=7.5)
# 6–7 branch
arrow(d, 245, dh-172, 245, dh-192, col=C["amber"], w=1.2)
label(d, 248, dh-183, "6–7", 7.5, C["amber"])
box(d, 165, dh-216, 160, 26, C["amber"],
text="Intermediate:\nCervical ripening\nthen ARM + oxytocin", fs=7.5)
# Augmentation row
box(d, 5, dh-272, 230, 30, C["purple"],
text="AUGMENTATION (poor progress in labour):\nARM if intact → Oxytocin infusion\n(Target: ≥3 contractions/10 min of 40–60 sec)", fs=7)
box(d, 255, dh-272, 230, 30, C["dblue"],
text="MONITORING:\nContinuous CTG • Partograph\nAction line = 4 hrs right of alert line", fs=7)
return d
# ─── VENTOUSE DECISION ───────────────────────────────────────────────────
def ventouse_schema(dw=490, dh=220):
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.4, rx=6))
d.add(String(dw/2, dh-14,
"VENTOUSE DELIVERY — Prerequisites, Procedure & Complications",
fontSize=9.5, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
# Prerequisites grid
prereqs = [
("A — Anaesthesia\nPerineal/regional"),
("B — Bladder\nEmptied"),
("C — Cervix\nFully dilated"),
("D — Denominator\nKnown (occiput)"),
("E — Engaged\nHead"),
("F — Fontanelle\nPost. accessible"),
]
bw=74; bh=36; y_pre = dh-72
bgc = [C["navy"],C["dblue"],C["teal"],C["green"],C["orange"],C["purple"]]
for i,txt in enumerate(prereqs):
x = 5+i*(bw+4)
box(d, x, y_pre, bw, bh, bgc[i], text=txt, fs=7)
d.add(String(dw/2, dh-36, "PREREQUISITES (ABCDEF):",
fontSize=8, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
# Procedure steps
proc = [("Cup at 'flexion point'\n3 cm from post. fontanelle", C["dblue"]),
("Build suction to\n0.8 kg/cm²", C["teal"]),
("Traction with\ncontractions + pushing", C["green"]),
("Max 3 pulls / 20 min\n(3 pop-off rule)", C["orange"])]
bw2=95; bh2=36; y_proc = dh-142
d.add(String(dw/2, dh-110, "PROCEDURE:",
fontSize=8, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
for i,(txt,col) in enumerate(proc):
x = 10+i*(bw2+9)
box(d, x, y_proc, bw2, bh2, col, text=txt, fs=7.5)
if i<len(proc)-1:
arrow(d, x+bw2, y_proc+bh2/2, x+bw2+9, y_proc+bh2/2,
col=C["navy"], w=1.2)
# Complications two col
d.add(String(160, y_proc-18, "FETAL:", fontSize=7.5,
fontName="Helvetica-Bold", fillColor=C["red"]))
d.add(String(160, y_proc-30,
"Chignon • Cephalhaematoma • Subgaleal haemorrhage • ICH",
fontSize=6.5, fillColor=C["navy"]))
d.add(String(160, y_proc-44, "MATERNAL:", fontSize=7.5,
fontName="Helvetica-Bold", fillColor=C["purple"]))
d.add(String(160, y_proc-56,
"Perineal tears • PPH • Cervical tears",
fontSize=6.5, fillColor=C["navy"]))
return d
# ─── FORCEPS SCHEMA ──────────────────────────────────────────────────────
def forceps_schema(dw=490, dh=215):
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.4, rx=6))
d.add(String(dw/2, dh-14,
"FORCEPS DELIVERY — Types, Procedure & Complications",
fontSize=9.5, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
# Forceps types
types = [
("Wrigley's","Outlet\nCS forceps","Short • No rotation", C["teal"]),
("Neville-Barnes\n(Anderson's)","Mid-cavity\n(most common)","English lock\nStandard use", C["dblue"]),
("Kielland's","Rotational\n(OT/OP)","Sliding lock\nNo pelvic curve", C["purple"]),
("Piper's","After-coming\nbreech head","Long shanks\nNo pelvic curve", C["orange"]),
]
bw=105; bh=52; y0=dh-90
for i,(name,use,feat,col) in enumerate(types):
x=10+i*(bw+8)
box(d, x, y0, bw, bh, col, text=f"{name}\n{use}\n{feat}", fs=6.8)
d.add(String(dw/2, dh-36, "TYPES OF FORCEPS:",
fontSize=8, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
# Application steps
d.add(String(dw/2, y0-12, "APPLICATION STEPS:",
fontSize=8, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
steps = ["Left blade\nfirst (L hand)",
"Right blade\n(R hand)",
"Lock blades\nCheck position",
"Pajot's\ntraction",
"Remove at\ncrowning"]
bw2=82; bh2=30; y_st=y0-52
for i,txt in enumerate(steps):
x=8+i*(bw2+6)
box(d, x, y_st, bw2, bh2, [C["navy"],C["dblue"],C["teal"],C["green"],C["orange"]][i],
text=txt, fs=7.5)
if i<len(steps)-1:
arrow(d, x+bw2, y_st+bh2/2, x+bw2+6, y_st+bh2/2,
col=C["grey"], w=1.2)
# Complications
y_c = y_st-20
d.add(Rect(5, y_c-18, 230, 22, rx=3, ry=3,
fillColor=C["lred"], strokeColor=C["red"], strokeWidth=0.8))
d.add(String(8, y_c-12, "FETAL: Facial marks • Nerve palsy • Cephalhaematoma • ICH",
fontSize=6.5, fillColor=C["red"]))
d.add(Rect(245, y_c-18, 240, 22, rx=3, ry=3,
fillColor=C["lpurple"], strokeColor=C["purple"], strokeWidth=0.8))
d.add(String(248, y_c-12, "MATERNAL: 3rd/4th degree tears • Bladder injury • PPH",
fontSize=6.5, fillColor=C["purple"]))
return d
# ─── CS SCHEMA ───────────────────────────────────────────────────────────
def cs_schema(dw=490, dh=260):
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.4, rx=6))
d.add(String(dw/2, dh-14,
"CAESAREAN SECTION — Types, Grading & Procedure",
fontSize=9.5, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
# RCOG grading
grades = [
("Grade 1\nEMERGENCY","Immediate threat\nto life\n→ within 30 min", C["red"]),
("Grade 2\nURGENT","Maternal/fetal\ncompromise\n→ within 75 min", C["orange"]),
("Grade 3\nSCHEDULED","Needs early\ndelivery, no\ncompromise", C["amber"]),
("Grade 4\nELECTIVE","Planned\n→ ideally\n≥39 weeks", C["green"]),
]
bw=100; bh=54; y_g=dh-92
d.add(String(dw/2, dh-36, "RCOG URGENCY CLASSIFICATION:",
fontSize=8, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
for i,(g,det,col) in enumerate(grades):
x=18+i*(bw+14)
box(d, x, y_g, bw, bh, col, text=f"{g}\n{det}", fs=7)
# Procedure waterfall
layers = [("Skin (Pfannenstiel incision)", C["lamber"]),
("Subcutaneous fat", C["lorange"]),
("Rectus sheath (transverse)", C["lgreen"]),
("Rectus muscles (blunt separation)", C["lteal"]),
("Peritoneum (vertical)", C["lblue"]),
("Uterovesical fold → Doyen's retractor", C["lpurple"]),
("Lower uterine segment — INCISE", C["lred"])]
d.add(String(dw/2, y_g-12, "SURGICAL LAYERS (Pfannenstiel):",
fontSize=8, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
lbw=220; lbh=16; y_l=y_g-30
for i,(txt,col) in enumerate(layers):
inset = i*6
x = (dw-lbw)/2 + inset/2
w = lbw - inset
box(d, x, y_l-i*lbh, w, lbh-1, col,
text=txt, fs=7.5,
tc=C["red"] if "INCISE" in txt else C["navy"],
bw=1.2 if "INCISE" in txt else 0.5)
# VBAC + key info
y_v = y_l - len(layers)*lbh - 6
box(d, 5, y_v, 225, 28, C["lteal"],
text="VBAC: 1 prev LSCS + singleton + cephalic\nSuccess 60–80% | Rupture risk 0.5%",
fs=7, tc=C["navy"])
box(d, 258, y_v, 225, 28, C["lred"],
text="Classical CS: Upper segment vertical\n→ CS in ALL future pregnancies (scar rupture)",
fs=7, tc=C["navy"])
return d
# ─── ABNORMAL PRESENTATIONS SCHEMA ───────────────────────────────────────
def presentations_schema(dw=490, dh=200):
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.4, rx=6))
d.add(String(dw/2, dh-14,
"ABNORMAL PRESENTATIONS — Comparison Schema",
fontSize=9.5, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
# Headers
headers = ["Feature","FACE","BROW","SHOULDER"]
hbgs = [C["navy"],C["teal"],C["orange"],C["purple"]]
col_ws = [110,120,120,120]
xs = [4, 114, 234, 354]
y_h = dh-44
for ci,(hdr,bg,cw,x) in enumerate(zip(headers,hbgs,col_ws,xs)):
box(d, x, y_h, cw-2, 24, bg, text=hdr, fs=8.5, bold=True)
rows = [
("Denominator", "Mentum (chin)", "Frontal bone", "Acromion"),
("Diameter", "Submentobregmatic\n9.5 cm", "Mentovertical\n13.5 cm (LARGEST)", "Bisacromial\n11 cm transverse"),
("Head attitude","Hyper-extended","Partially extended","Transverse lie"),
("VE finding", "Orbital ridges\nnose + chin", "Orbital ridges\n+ ant. fontanelle", "Shoulder/rib\nor arm"),
("Delivery", "Mentoanterior: VD\nMentoposterior: CS", "CS (mostly)\nMay → vertex/face", "CS MANDATORY"),
]
row_h = 28; row_bgs = [C["lblue"],C["white"]]*4
for ri,row in enumerate(rows):
y = y_h - (ri+1)*(row_h+1)
for ci,(val,cw,x) in enumerate(zip(row,col_ws,xs)):
bg = (hbgs[ci] if ci==0 else row_bgs[ri])
tc = C["white"] if ci==0 else C["navy"]
if "CS MANDATORY" in val or "Mentoposterior: CS" in val:
bg2 = C["lred"]; tc = C["red"]
elif "VD" in val or "vertex" in val:
bg2 = C["lgreen"]; tc = C["green"]
else:
bg2 = bg
box(d, x, y, cw-2, row_h-1, bg2, text=val,
fs=6.5, tc=tc, rx=2)
return d
# ─── BISHOP'S SCORE INTERPRET FLOWCHART ──────────────────────────────────
def bishop_flow(dw=490, dh=130):
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.4, rx=6))
d.add(String(dw/2, dh-14, "BISHOP'S SCORE — Interpretation & Action",
fontSize=9.5, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
# Score range boxes
ranges = [
("Score ≤5\nUNFAVOURABLE", "Cervical ripening\nPGE₂ / Foley\nbefore induction", C["red"]),
("Score 6–7\nINTERMEDIATE", "Cervical ripening\nrecommended;\nreassess in 6 hr", C["amber"]),
("Score ≥8\nFAVOURABLE", "Proceed directly\nto ARM + Syntocinon\ninduction", C["green"]),
]
bw=130; bh=80; y0=30
total_w = len(ranges)*bw + (len(ranges)-1)*20
x_start = (dw-total_w)/2
for i,(score,action,col) in enumerate(ranges):
x = x_start + i*(bw+20)
box(d, x, y0, bw, bh, col, text=f"{score}\n↓\n{action}", fs=7.5)
if i<len(ranges)-1:
arrow(d, x+bw, y0+bh/2, x+bw+20, y0+bh/2,
col=C["grey"], w=1.2, head=5)
return d
# ─── MIND MAPS ────────────────────────────────────────────────────────────
def cord_causes_mm():
return mind_map(
"CORD\nPROLAPSE\nCauses",
[("Malpresentation",["Transverse lie","Breech","Face/Brow"]),
("High presenting\npart",["Unengaged head","Multiparity","CPD"]),
("Polyhydramnios",["Cord floats","Fetal anomaly"]),
("Iatrogenic",["ARM – high head","ECV","Catheter insert."]),
("Cord factors",["Long cord","Low placenta"]),
("Prematurity",["Small fetus","Unfixed part"])],
dw=460, dh=190,
centre_bg=C["red"]
)
def rupture_causes_mm():
return mind_map(
"UTERINE\nRUPTURE\nCauses",
[("Scarred\nuterus",["Prev LSCS","Myomectomy","Hysterotomy"]),
("Obstructed\nlabour",["CPD","Transverse lie","Contracted pelvis"]),
("Oxytocin",["Hyperstimulation","Grand multipara"]),
("Trauma",["External","Instrumental"]),
("Anomalies",["Bicornuate uterus","Weak myometrium"])],
dw=460, dh=185,
centre_bg=C["red"]
)
# ══════════════════════════════════════════════════════════════════════════
# BUILD STORY
# ══════════════════════════════════════════════════════════════════════════
story = []
# COVER ────────────────────────────────────────────────────────────────────
story += [
sp(3),
Paragraph("OBSTETRICS", TITLE),
Paragraph("20-Mark Exam Notes — Full Schematic Edition", SUBT),
Paragraph("Obstetric Emergencies • Bishop's Score • Induction / Augmentation<br/>"
"Ventouse • Forceps • Caesarean Section • Abnormal Presentations", SUBT),
sp(), hr(), sp(),
Paragraph("All content in flowcharts, decision trees, process schemas & colour-coded grids", FOOT),
Paragraph("Harrison's 22E | Goldman-Cecil | Rosen's Emergency Medicine | Orris Medical", FOOT),
PageBreak()
]
# ═══════════════ SECTION 1: OBSTETRIC EMERGENCIES ═════════════════════════
story += [sec_banner("SECTION 1 — OBSTETRIC EMERGENCIES"), sp(0.5)]
# 1a. Cord prolapse
story += [subsec("1. CORD PROLAPSE", C["red"]), sp(0.3)]
story += [cord_causes_mm(), cap("Fig 1. Cord prolapse — mind map of predisposing factors"), sp(0.4)]
story += [cord_prolapse_tree(), cap("Fig 2. Cord prolapse management decision tree"), sp(0.4)]
story += [
tbl(["Presentation","Signs","Investigation","Management"],
[["Overt prolapse","Cord visible/felt at introitus; CTG — severe variable decels/bradycardia","Clinical + immediate CTG","PUSH UP + Emergency CS Grade 1 within 30 min"],
["Occult prolapse","CTG changes only during/after membrane rupture; no cord visible","CTG + VE if suspicious","Elevate presenting part; stop oxytocin; CS"],
["Cord presentation","Cord felt before membranes ruptured; CTG normal","VE + USS","ARM contraindicated; CS planned"]],
cw=[3.5*cm,4.5*cm,3.5*cm,5.5*cm]),
sp()
]
# 1b. Uterine inversion
story += [subsec("2. UTERINE INVERSION", C["red"]), sp(0.3)]
story += [inversion_schema(), cap("Fig 3. Uterine inversion — management flowchart"), sp(0.4)]
story += [
tbl(["Degree","Pathology","Signs","Management"],
[["1st (Incomplete)","Fundus dimples above internal os","Absent fundus abdominally; mild PPH","Oxytocin + gentle manual reduction"],
["2nd (Complete)","Fundus through internal os into vagina","Mass in vagina; PPH + shock","Johnson's manoeuvre; tocolysis first"],
["3rd (Prolapsed)","Fundus at/beyond introitus","Mass visible at vulva; haemorrhagic shock","Johnson's / O'Sullivan's; surgical if failed"],
["4th (Total)","Vagina also inverted (rare)","Extreme shock; total eversion","Surgical: Huntington's / Haultain's"]],
cw=[3*cm,4*cm,4.5*cm,5*cm]),
sp()
]
# 1c. AFE
story += [subsec("3. AMNIOTIC FLUID EMBOLISM (AFE)", C["red"]), sp(0.3)]
story += [afe_cascade(), cap("Fig 4. AFE — two-phase cascade and management schema"), sp(0.4)]
story += [
tbl(["Feature","Details"],
[["Incidence","1 in 8,000–80,000 deliveries; maternal mortality 20–60%"],
["Classical Triad","① Sudden cardiovascular collapse ② Acute respiratory failure ③ DIC/coagulopathy"],
["Phase 1","AF enters pulmonary circulation → vasospasm → acute right heart failure → hypoxia"],
["Phase 2 (30–60 min)","Left heart failure + massive DIC → uncontrollable haemorrhage"],
["Diagnosis","Clinical (exclude others). ABG: hypoxia + acidosis. CXR: pulmonary oedema. Coag: ↓fibrinogen, ↑D-dimer"],
["Key Management","CPR/intubation; vasopressors; FFP + platelets + cryoprecipitate + TXA; perimortem CS within 5 min of arrest"]],
cw=[4*cm,12.5*cm]),
sp()
]
# 1d. Obstetric Shock
story += [subsec("4. OBSTETRIC SHOCK", C["red"]), sp(0.3)]
story += [shock_schema(), cap("Fig 5. Obstetric shock — types, Shock Index formula, ABCDE management"), sp(0.4)]
story += [
tbl(["Class","Blood Loss","HR","SBP","Signs","Action"],
[["I","<750 mL / <15%","<100","Normal","Anxious, mild pallor","IV fluids, monitor"],
["II","750–1500 mL / 15–30%","100–120","Normal–low","Tachycardia, decreased pulse pressure","2 large-bore IV, crossmatch, fluid bolus"],
["III","1500–2000 mL / 30–40%","120–140","<90","Confusion, pallor, oliguria","Transfusion; massive haemorrhage protocol"],
["IV",">2000 mL / >40%",">140","<70","Unconscious, anuria","Immediate surgery; MHP; vasopressors"]],
cw=[1.5*cm,3.5*cm,2*cm,2*cm,4*cm,4.5*cm]),
sp(),
PageBreak()
]
# 1e. Uterine Rupture
story += [subsec("5. UTERINE RUPTURE", C["red"]), sp(0.3)]
story += [rupture_schema(), cap("Fig 6. Uterine rupture — threatened vs actual, decision schema"), sp(0.3)]
story += [rupture_causes_mm(), cap("Fig 7. Uterine rupture — mind map of causes"), sp(0.4)]
story += [
tbl(["Sign","Threatened Rupture","Actual Rupture"],
[["Pain","Severe constant uterine pain; hyperstimulation","Sudden cessation of contractions then constant abdominal pain"],
["Abdomen","Bandl's retraction ring visible above pubis","Guarding + rigidity; fetal parts easily palpable"],
["Fetal heart","Tachycardia/variable decelerations","Absent (fetal death in 50–75%)"],
["Presenting part","Remains in pelvis","Recedes upward into abdomen"],
["Maternal","Tachycardia, haematuria","Hypotension, shock; pallor"],
["Management","STOP oxytocin; prep for CS","Emergency laparotomy + repair/hysterectomy"]],
cw=[3.5*cm,6.5*cm,6.5*cm]),
sp(), PageBreak()
]
# ═══════════════ SECTION 2: BISHOP'S SCORE ════════════════════════════════
story += [sec_banner("SECTION 2 — BISHOP'S SCORE"), sp(0.5)]
story += [bishop_schema(), cap("Fig 8. Bishop's Score — visual grid (5 parameters × 4 scores; max = 13)"), sp(0.4)]
story += [bishop_flow(), cap("Fig 9. Bishop's Score interpretation and action flowchart"), sp(0.4)]
story += [
tbl(["Parameter","Score 0","Score 1","Score 2","Score 3","Clinical Tip"],
[["Dilatation","Closed","1–2 cm","3–4 cm","≥5 cm","Most important single parameter"],
["Effacement","0–30%","40–50%","60–70%","≥80%","Length of cervix shortening"],
["Station","-3","-2","-1 to 0","+1 to +2","Relative to ischial spines"],
["Consistency","Firm","Medium","Soft","—","Max score = 2"],
["Position","Posterior","Mid","Anterior","—","Max score = 2"]],
cw=[3*cm,2*cm,2*cm,2*cm,2*cm,5.5*cm]),
sp(), PageBreak()
]
# ═══════════════ SECTION 3: INDUCTION & AUGMENTATION ═════════════════════
story += [sec_banner("SECTION 3 — INDUCTION & AUGMENTATION OF LABOUR"), sp(0.5)]
story += [induction_tree(), cap("Fig 10. Induction/Augmentation decision algorithm"), sp(0.4)]
story += [
tbl(["Method","Agent","Dose","Indication","Notes"],
[["Membrane sweep","Endogenous PGs released","Digital separation of chorion at 40–41 wk","Outpatient IOL priming","Reduces need for formal IOL"],
["Dinoprostone (PGE₂)","Vaginal gel/pessary","Gel 0.5 mg intracervical; pessary 3 mg vaginal; repeat 6 hrly","Unfavourable cervix (Bishop ≤5)","Avoid in scarred uterus"],
["Misoprostol (PGE₁)","Oral/vaginal tablet","25–50 mcg vaginally q4–6h","Cervical ripening; incomplete abortion","Cheap; not licensed for IOL in many countries"],
["Foley catheter","Mechanical","30–60 mL balloon transcervically","Unfavourable cervix; scarred uterus","Safe in prev CS; no systemic effects"],
["ARM","Amniotomy","Amniohook; cervix ≥2–3 cm","Favourable cervix; augmentation","Risk: cord prolapse if head not engaged"],
["Syntocinon (Oxytocin)","IV infusion","1–2 mU/min; titrate q30 min; max 40 mU/min","IOL (post-ARM) + Augmentation","Requires continuous CTG; water intoxication risk"]],
cw=[3.2*cm,2.5*cm,3*cm,3.2*cm,4.6*cm]),
sp(), PageBreak()
]
# ═══════════════ SECTION 4a: VENTOUSE ════════════════════════════════════
story += [sec_banner("SECTION 4a — VENTOUSE (VACUUM EXTRACTOR) DELIVERY"), sp(0.5)]
story += [ventouse_schema(), cap("Fig 11. Ventouse — prerequisites, procedure & complications schema"), sp(0.4)]
story += [
tbl(["Indication","Contraindication","Cup Placement","Abandon if"],
[["Prolonged 2nd stage","<34 weeks gestation","Flexion point: 3 cm anterior to post. fontanelle","Cup pops off 3 times"],
["Fetal compromise in 2nd stage","Face presentation","Ensure no maternal tissue caught under cup","No progress after 3 pulls"],
["Maternal exhaustion","Active fetal bleeding/coagulopathy","Apply suction gradually to 0.8 kg/cm²","Total time >20 minutes"],
["Cardiac/neurological disease (prevent Valsalva)","Incompletely dilated cervix","Traction with contraction AND maternal push","CPD confirmed"]],
cw=[4*cm,4*cm,5*cm,3.5*cm]),
sp(), PageBreak()
]
# ═══════════════ SECTION 4b: FORCEPS ═════════════════════════════════════
story += [sec_banner("SECTION 4b — FORCEPS DELIVERY"), sp(0.5)]
story += [forceps_schema(), cap("Fig 12. Forceps types, application steps and complications schema"), sp(0.4)]
story += [
tbl(["Classification","Head position","Forceps type","Notes"],
[["Outlet","Scalp at introitus; rotation ≤45°","Wrigley's","Easiest; lowest risk"],
["Low","Station ≥+2","Neville-Barnes / Anderson's","Most common in UK practice"],
["Mid-cavity","Station 0 to +2","Neville-Barnes or Kielland's","Needs senior obstetrician"],
["High","Not engaged","ABANDONED","CS indicated — do NOT apply"]],
cw=[3.5*cm,4*cm,4.5*cm,4.5*cm]),
sp(),
tbl(["Ventouse vs Forceps","Ventouse","Forceps"],
[["Rotation","Passive","Active (Kielland's)"],
["Maternal trauma","Less","More (perineal tears)"],
["Fetal risk","Chignon; subgaleal haematoma","Facial marks; nerve palsy"],
["Failure rate","15–20%","5–10%"],
["Use in preterm","Avoid (<34 wk)","May protect preterm head"],
["After-coming breech head","Not suitable","Piper's forceps used"],
["Sequential use","High neonatal morbidity — AVOID combination if possible","—"]],
cw=[5*cm,5.5*cm,6*cm]),
sp(), PageBreak()
]
# ═══════════════ SECTION 4c: CAESAREAN SECTION ════════════════════════════
story += [sec_banner("SECTION 4c — CAESAREAN SECTION (CS)"), sp(0.5)]
story += [cs_schema(), cap("Fig 13. CS grading (RCOG), surgical layers, and VBAC schema"), sp(0.4)]
story += [
tbl(["Type","Incision","Indication","Future delivery"],
[["LSCS","Transverse lower segment","Most common (>95%)","VBAC possible if eligible"],
["Classical CS","Vertical upper segment","Transverse lie; anterior placenta praevia; very preterm","CS in ALL future pregnancies"],
["Emergency (Grade 1)","Fastest access route","Immediate threat to life","Depends on type of incision"],
["Elective","LSCS preferred","Maternal request; placenta praevia; breech","VBAC possible after 1 LSCS"]],
cw=[3.5*cm,3.5*cm,5.5*cm,4*cm]),
sp(),
tbl(["Complication","Intraoperative","Postoperative","Long-term"],
[["Haemorrhage","PPH (uterine atony, placenta accreta)","Wound haematoma","Scar rupture in future pregnancy"],
["Urological","Bladder laceration; ureteric injury","Urinary fistula (VVF)","Bladder adhesions"],
["Infective","—","Endometritis; wound infection","Chronic pelvic pain; adhesions"],
["Thrombotic","—","DVT/PE (2–5× higher than VD)","—"],
["Neonatal","Fetal lacerations (1%)","TTN (transient tachypnoea)","Higher asthma risk"]],
cw=[3.2*cm,4.3*cm,4.3*cm,4.7*cm]),
sp(), PageBreak()
]
# ═══════════════ SECTION 5: ABNORMAL PRESENTATIONS ════════════════════════
story += [sec_banner("SECTION 5 — ABNORMAL PRESENTATIONS"), sp(0.5)]
story += [presentations_schema(), cap("Fig 14. Abnormal presentations comparison schema — Face / Brow / Shoulder"), sp(0.4)]
# Individual schemas for each
face_flow = hflow(
["Vertex → fully\nextended = FACE",
"VE: orbital ridges\n+ nose + chin",
"Determine\nMENTUM position",
"Mentoanterior\n→ Vaginal delivery",
"Mentoposterior\n→ CS (MANDATORY)"],
dw=490, dh=75,
title="FACE PRESENTATION — Management Flow",
colours=[C["teal"],C["teal"],C["amber"],C["green"],C["red"]])
brow_flow = hflow(
["Partial extension\n= BROW",
"VE: orbital ridges\n+ BOTH fontanelles",
"Mentovertical\n13.5 cm (can't\nengage)",
"Often converts:\nVertex or Face",
"Persistent brow\n→ CS MANDATORY"],
dw=490, dh=75,
title="BROW PRESENTATION — Management Flow",
colours=[C["orange"],C["orange"],C["red"],C["amber"],C["red"]])
shoulder_flow = hflow(
["Transverse lie\n= SHOULDER",
"Inspection: wide\nuterus; no pole\nat fundus/pelvis",
"VE: rib / arm\n/ shoulder felt",
"Pre-labour:\nAttempt ECV",
"At term / labour\n→ CS MANDATORY",
"Neglected: Bandl's\nring → rupture risk"],
dw=490, dh=75,
title="SHOULDER / TRANSVERSE LIE — Management Flow",
colours=[C["purple"],C["purple"],C["purple"],C["amber"],C["red"],C["red"]])
story += [
face_flow, cap("Fig 15. Face presentation management flow"), sp(0.3),
brow_flow, cap("Fig 16. Brow presentation management flow"), sp(0.3),
shoulder_flow, cap("Fig 17. Shoulder/transverse lie management flow"), sp(0.4),
]
story += [
tbl(["Presentation","Incidence","Denominator","Diameter","VD Possible?","Key Management"],
[["Face","1/500","Mentum (chin)","Submentobregmatic 9.5 cm","YES — if mentoanterior","Mentoposterior: CS; spontaneous rotation monitored"],
["Brow","1/1000","Frontal bone","Mentovertical 13.5 cm — LARGEST","NO (persistent)","Observe for conversion; persistent brow → CS"],
["Shoulder / Transverse","1/300","Acromion","Bisacromial (transverse — cannot engage)","NO","ECV if pre-labour; CS at term; neglected → uterine rupture"]],
cw=[2.5*cm,2*cm,2.5*cm,3.5*cm,2.5*cm,4.5*cm]),
sp(2),
hr(),
Paragraph("Sources: Harrison's Principles of Internal Medicine 22E (2025) | Goldman-Cecil Medicine | "
"Rosen's Emergency Medicine | Robbins & Cotran Pathology 11E | Orris Medical", FOOT),
Paragraph("Prepared by Orris AI Medical Assistant | July 2026 | For Academic/Exam Preparation Only", FOOT),
]
doc.build(story)
print("PDF generated:", OUT)
cd /home/daytona/workspace/obstetrics-notes && python gen_schematic.py 2>&1
ls -lh /home/daytona/workspace/obstetrics-notes/Obstetrics_Schematic.pdf
Obstetrics Schematic
PDF Document · PDF
| Fig | Schema Type | Content |
|---|---|---|
| 1 | Radial Mind Map | Cord Prolapse — causes radiating outward |
| 2 | Decision Tree with diamonds | Cord Prolapse — PUSH UP → viable? → dilated? → CS vs VD |
| 3 | Vertical Flowchart | Uterine Inversion — step-by-step management cascade |
| 4 | Horizontal 2-Row Process Flow | AFE — Phase 1 cascade + Phase 2 DIC + Management row |
| 5 | 5-Column Grid + ABCDE Row | Obstetric Shock — types → ABCDE management |
| 6 | Decision Tree | Uterine Rupture — threatened vs actual → laparotomy → repair/hysterectomy |
| 7 | Radial Mind Map | Uterine Rupture — causes |
| 8 | Color-coded Grid | Bishop's Score — 5 parameters × 4 scores (red/amber/green scoring) |
| 9 | 3-Box Decision Flow | Bishop's ≤5 → ripen / 6-7 → intermediate / ≥8 → ARM + oxytocin |
| 10 | Decision Tree | Induction algorithm — contraindication check → Bishop's → ripen or proceed |
| 11 | 6-Box Prerequisites + 4-Step Procedure | Ventouse — ABCDEF grid + process flow |
| 12 | 4-Type Grid + 5-Step Application | Forceps — types grid + left-blade-first steps |
| 13 | 4-Grade + Layer Waterfall + VBAC | CS — RCOG grading + 7 surgical layers in staircase format |
| 14 | 4-Column Comparison Grid | All 3 abnormal presentations side-by-side |
| 15 | Horizontal Process Flow | Face presentation — vertex→extended→mentum→MA vs MP |
| 16 | Horizontal Process Flow | Brow — partial extension → 13.5 cm → converts or CS |
| 17 | Horizontal Process Flow | Shoulder/transverse — ECV → CS → neglected rupture risk |
Thank you
But needed in very big fonts because I can't see when I take Xerox
~/obstetrics-notes/gen_large.py
"""
Obstetrics Schematic PDF — LARGE FONT / XEROX-FRIENDLY VERSION
All text enlarged for clear photocopying
"""
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import cm, mm
from reportlab.lib import colors
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import (
SimpleDocTemplate, Spacer, Table, TableStyle,
HRFlowable, PageBreak, Paragraph
)
from reportlab.graphics.shapes import (
Drawing, Rect, Circle, Ellipse, Line, String,
Polygon, PolyLine, Group
)
import os, math
os.makedirs("/home/daytona/workspace/obstetrics-notes", exist_ok=True)
OUT = "/home/daytona/workspace/obstetrics-notes/Obstetrics_Schematic_LARGE.pdf"
PW, PH = A4
LM = RM = 1.4*cm
TM = BM = 1.6*cm
UW = PW - LM - RM
doc = SimpleDocTemplate(OUT, pagesize=A4,
leftMargin=LM, rightMargin=RM,
topMargin=TM, bottomMargin=BM,
title="Obstetrics Schematic – LARGE PRINT",
author="Orris Medical")
# ── Colours ────────────────────────────────────────────────
C = dict(
navy=colors.HexColor("#0D1B6E"), dblue=colors.HexColor("#1565C0"),
lblue=colors.HexColor("#DDEEFF"), sky=colors.HexColor("#B3E5FC"),
teal=colors.HexColor("#00838F"), lteal=colors.HexColor("#E0F7FA"),
green=colors.HexColor("#2E7D32"), lgreen=colors.HexColor("#E8F5E9"),
orange=colors.HexColor("#E65100"), lorange=colors.HexColor("#FFF3E0"),
red=colors.HexColor("#B71C1C"), lred=colors.HexColor("#FFCDD2"),
purple=colors.HexColor("#4A148C"), lpurple=colors.HexColor("#F3E5F5"),
amber=colors.HexColor("#F57F17"), lamber=colors.HexColor("#FFF8E1"),
grey=colors.HexColor("#546E7A"), lgrey=colors.HexColor("#F5F5F5"),
white=colors.white, black=colors.black,
)
# ── LARGE Paragraph styles (Xerox-friendly) ───────────────
def PS(name, **kw):
base = dict(fontName="Helvetica", fontSize=12, leading=17,
textColor=C["black"], spaceAfter=4, spaceBefore=2)
base.update(kw)
return ParagraphStyle(name, **base)
TITLE = PS("T", fontName="Helvetica-Bold", fontSize=22, textColor=C["navy"],
alignment=TA_CENTER, spaceAfter=6, spaceBefore=8)
SUBT = PS("S", fontSize=12, textColor=C["purple"], alignment=TA_CENTER,
fontName="Helvetica-Oblique", spaceAfter=6)
SEC = PS("SE", fontName="Helvetica-Bold", fontSize=14, textColor=C["white"],
alignment=TA_CENTER, spaceBefore=8, spaceAfter=4)
SECBG = PS("SB", fontName="Helvetica-Bold", fontSize=13, textColor=C["navy"],
spaceBefore=8, spaceAfter=4)
H2 = PS("H2", fontName="Helvetica-Bold", fontSize=13, textColor=C["navy"],
spaceBefore=6, spaceAfter=3)
H3 = PS("H3", fontName="Helvetica-Bold", fontSize=12, textColor=C["purple"],
spaceBefore=4, spaceAfter=2)
BODY = PS("BO", fontSize=11, leading=16, alignment=TA_JUSTIFY)
BUL = PS("BU", fontSize=11, leading=16, leftIndent=16, firstLineIndent=-12)
BCAP = PS("BC", fontSize=9.5, textColor=C["grey"], alignment=TA_CENTER,
fontName="Helvetica-Oblique", spaceAfter=4)
FOOT = PS("FO", fontSize=9, textColor=C["grey"], alignment=TA_CENTER,
fontName="Helvetica-Oblique")
TH = PS("TH", fontName="Helvetica-Bold", fontSize=11, textColor=C["white"],
alignment=TA_CENTER)
TD = PS("TD", fontSize=10.5, leading=14)
WARN = PS("WA", fontName="Helvetica-Bold", fontSize=11, textColor=C["red"],
leading=15)
def sp(n=1): return Spacer(1, n*0.3*cm)
def hr(): return HRFlowable(width="100%", thickness=0.8,
color=C["navy"], spaceAfter=4, spaceBefore=2)
def p(t): return Paragraph(t, BODY)
def b(t): return Paragraph(f"• {t}", BUL)
def w(t): return Paragraph(f"⚠ {t}", WARN)
def cap(t): return Paragraph(t, BCAP)
def h2(t): return Paragraph(t, H2)
def h3(t): return Paragraph(t, H3)
def tbl(headers, rows, cw=None, hbg=None):
if hbg is None: hbg = C["navy"]
data = [[Paragraph(h, TH) for h in headers]]
for row in rows:
data.append([Paragraph(str(c), TD) for c in row])
if cw is None: cw = [None]*len(headers)
t = Table(data, colWidths=cw, hAlign='LEFT')
t.setStyle(TableStyle([
('BACKGROUND',(0,0),(-1,0), hbg),
('ROWBACKGROUNDS',(0,1),(-1,-1),[C["lblue"],C["white"]]),
('GRID',(0,0),(-1,-1),0.5,C["sky"]),
('VALIGN',(0,0),(-1,-1),'TOP'),
('TOPPADDING',(0,0),(-1,-1),5),
('BOTTOMPADDING',(0,0),(-1,-1),5),
('LEFTPADDING',(0,0),(-1,-1),6),
('RIGHTPADDING',(0,0),(-1,-1),6),
]))
return t
def sec_banner(text, bg=None):
if bg is None: bg = C["navy"]
t = Table([[Paragraph(text, SEC)]], colWidths=[UW])
t.setStyle(TableStyle([
('BACKGROUND',(0,0),(-1,-1), bg),
('TOPPADDING',(0,0),(-1,-1),8),
('BOTTOMPADDING',(0,0),(-1,-1),8),
('LEFTPADDING',(0,0),(-1,-1),10),
]))
return t
def subsec(text, bg=None, tc=None):
if bg is None: bg = C["dblue"]
if tc is None: tc = C["white"]
st = PS("SS", fontName="Helvetica-Bold", fontSize=12.5,
textColor=tc, alignment=TA_LEFT,
spaceBefore=4, spaceAfter=2)
t = Table([[Paragraph(f" {text}", st)]], colWidths=[UW])
t.setStyle(TableStyle([
('BACKGROUND',(0,0),(-1,-1), bg),
('TOPPADDING',(0,0),(-1,-1),5),
('BOTTOMPADDING',(0,0),(-1,-1),5),
]))
return t
# ── Drawing helpers (larger fonts in schematics) ───────────
def _dark(col):
try:
return (0.299*col.red + 0.587*col.green + 0.114*col.blue) < 0.55
except: return False
def box(d, x, y, w, h, bg, fg=None, text="", fs=10, bold=False,
rx=5, border=None, bw=1.2, tc=None):
if border is None: border = C["navy"]
if fg is None: fg = border
if tc is None: tc = C["white"] if _dark(bg) else C["navy"]
d.add(Rect(x, y, w, h, rx=rx, ry=rx,
fillColor=bg, strokeColor=fg, strokeWidth=bw))
if text:
fn = "Helvetica-Bold" if bold else "Helvetica"
lines = text.split("\n")
lh = fs * 1.3
total = lh * len(lines)
for i, ln in enumerate(lines):
ty = y + h/2 + total/2 - lh*(i+0.5) - 1
d.add(String(x+w/2, ty, ln, fontSize=fs,
fontName=fn, fillColor=tc, textAnchor="middle"))
def arrow(d, x1, y1, x2, y2, col=None, w=1.5, head=7):
if col is None: col = C["navy"]
d.add(Line(x1,y1,x2,y2, strokeColor=col, strokeWidth=w))
angle = math.atan2(y2-y1, x2-x1)
for sign in (+1,-1):
ax = x2 - head*math.cos(angle - sign*0.5)
ay = y2 - head*math.sin(angle - sign*0.5)
d.add(Line(x2,y2,ax,ay, strokeColor=col, strokeWidth=w))
def lbl(d, x, y, text, fs=9, col=None, anchor="middle"):
if col is None: col = C["grey"]
d.add(String(x, y, text, fontSize=fs, fillColor=col,
textAnchor=anchor, fontName="Helvetica-Bold"))
def diamond(d, cx, cy, hw, hh, bg, text="", fs=9, tc=None):
if tc is None: tc = C["white"] if _dark(bg) else C["navy"]
pts = [cx, cy+hh, cx+hw, cy, cx, cy-hh, cx-hw, cy]
d.add(Polygon(pts, fillColor=bg, strokeColor=C["navy"], strokeWidth=1.5))
if text:
lines = text.split("\n")
lh = fs*1.3
total = lh*len(lines)
for i,ln in enumerate(lines):
ty = cy + total/2 - lh*(i+0.5) - 1
d.add(String(cx, ty, ln, fontSize=fs,
fontName="Helvetica-Bold", fillColor=tc,
textAnchor="middle"))
# ════════════════════════════════════════════════
# LARGE-FONT SCHEMATICS
# ════════════════════════════════════════════════
def hflow(items, dw=490, dh=85, colours=None, title=None, fs=9.5):
if colours is None:
colours=[C["navy"],C["dblue"],C["teal"],C["green"],
C["orange"],C["purple"],C["red"],C["amber"]]*3
extra = 24 if title else 0
tdh = dh + extra
d = Drawing(dw, tdh)
d.add(Rect(0,0,dw,tdh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.5, rx=6))
if title:
d.add(String(dw/2, tdh-17, title, fontSize=11,
fontName="Helvetica-Bold", fillColor=C["navy"],
textAnchor="middle"))
n = len(items)
bw = (dw - 12 - (n-1)*16) / n
bh = dh - 14
for i, txt in enumerate(items):
x = 6 + i*(bw+16)
bg = colours[i % len(colours)]
tc = C["white"] if _dark(bg) else C["navy"]
box(d, x, 8, bw, bh, bg, text=txt, fs=fs, bold=True, rx=5, tc=tc)
if i < n-1:
mid_y = 8 + bh/2
arrow(d, x+bw, mid_y, x+bw+16, mid_y, col=C["navy"], w=1.5, head=6)
return d
def flowchart_v(steps, dw=490, colours=None, title=None, fs=10):
bh = 38; pad = 12
extra = 30 if title else 6
dh = len(steps)*(bh+pad) + extra + 10
if colours is None:
colours=[C["navy"],C["dblue"],C["teal"],C["green"],
C["orange"],C["purple"],C["amber"],C["red"]]*4
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.5, rx=6))
if title:
d.add(String(dw/2, dh-20, title, fontSize=11,
fontName="Helvetica-Bold", fillColor=C["navy"],
textAnchor="middle"))
cx = dw/2; bw = dw*0.74
y0 = dh - extra; prev_y = None
for i,(text, shape) in enumerate(steps):
y = y0 - bh - i*(bh+pad)
cy_box = y + bh/2
bg = colours[i % len(colours)]
tc = C["white"] if _dark(bg) else C["navy"]
if shape == "diamond":
hw, hh = bw*0.40, bh*0.75
diamond(d, cx, cy_box, hw, hh, bg, text=text, tc=tc, fs=fs-1)
elif shape == "oval":
d.add(Ellipse(cx-bw/2, y, bw, bh,
fillColor=bg, strokeColor=C["navy"], strokeWidth=1.2))
d.add(String(cx, cy_box-5, text, fontSize=fs,
fontName="Helvetica-Bold", fillColor=tc,
textAnchor="middle"))
else:
rx = 14 if shape=="rounded" else 5
box(d, cx-bw/2, y, bw, bh, bg, text=text,
fs=fs, bold=True, rx=rx, tc=tc)
if prev_y is not None:
arrow(d, cx, prev_y, cx, y+bh, col=C["grey"], w=1.5, head=6)
prev_y = y
return d
def grid_schema(items, cols=3, dw=490, item_h=60, colours=None, title=None, fs=9.5):
if colours is None:
colours=[C["dblue"],C["teal"],C["green"],C["orange"],
C["purple"],C["amber"],C["red"],C["navy"]]*4
rows = (len(items)+cols-1)//cols
extra = 28 if title else 6
dh = rows*item_h + 12 + extra
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.5, rx=6))
if title:
d.add(String(dw/2, dh-18, title, fontSize=11,
fontName="Helvetica-Bold", fillColor=C["navy"],
textAnchor="middle"))
bw = (dw-10)/cols
for i,(hdr,detail) in enumerate(items):
r,c = divmod(i,cols)
x = 5+c*bw
y = dh-extra-8-(r+1)*item_h
bg = colours[i % len(colours)]
tc = C["white"] if _dark(bg) else C["navy"]
box(d, x, y, bw-4, item_h-4, bg, rx=5, tc=tc)
d.add(String(x+(bw-4)/2, y+item_h-18, hdr,
fontSize=fs+0.5, fontName="Helvetica-Bold",
fillColor=tc, textAnchor="middle"))
for li, ln in enumerate(detail.split("\n")):
d.add(String(x+(bw-4)/2, y+item_h-31-li*12, ln,
fontSize=fs-1, fillColor=tc, textAnchor="middle"))
return d
def bishop_schema_lg(dw=490, dh=175):
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.5, rx=6))
d.add(String(dw/2, dh-16, "BISHOP'S SCORE — Cervical Assessment",
fontSize=12, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
cols_l = ["Feature","Score 0","Score 1","Score 2","Score 3"]
rows = [
("Dilatation","Closed","1–2 cm","3–4 cm","≥5 cm"),
("Effacement","0–30%","40–50%","60–70%","≥80%"),
("Station","-3","-2","-1/0","+1/+2"),
("Consistency","Firm","Medium","Soft","—"),
("Position","Post.","Mid","Ant.","—"),
]
sbgs=[C["lred"],C["lamber"],C["lgreen"],C["lteal"]]
cws=[88,72,72,72,72]; rh=22; hh=26
xs=[4]
for w in cws[:-1]: xs.append(xs[-1]+w)
y0=dh-34
for ci,(col,cw,x) in enumerate(zip(cols_l,cws,xs)):
bg=C["navy"] if ci==0 else [C["red"],C["amber"],C["green"],C["teal"]][ci-1]
box(d,x,y0-hh,cw-2,hh,bg,text=col,fs=10,bold=True,rx=3)
for ri,row in enumerate(rows):
for ci,(val,cw,x) in enumerate(zip(row,cws,xs)):
if ci==0: bg=C["navy"]; tc=C["white"]
else:
bg=sbgs[ci-1] if ri%2==0 else C["white"]
tc=C["navy"]
y=y0-hh-(ri+1)*rh-ri*1
box(d,x,y,cw-2,rh-1,bg,text=val,fs=9,tc=tc,rx=2)
d.add(Rect(4,4,235,18,rx=4,ry=4,fillColor=C["red"],strokeColor=None))
d.add(String(8,8,"Score ≤5 = UNFAVOURABLE → ripen cervix first",
fontSize=8.5,fillColor=C["white"]))
d.add(Rect(244,4,240,18,rx=4,ry=4,fillColor=C["green"],strokeColor=None))
d.add(String(248,8,"Score ≥8 = FAVOURABLE → ARM + Syntocinon",
fontSize=8.5,fillColor=C["white"]))
return d
def cord_tree_lg(dw=490, dh=310):
d = Drawing(dw, dh)
d.add(Rect(0,0,dw,dh, fillColor=C["lgrey"],
strokeColor=C["navy"], strokeWidth=0.5, rx=6))
d.add(String(dw/2, dh-16, "CORD PROLAPSE — Management Decision Tree",
fontSize=11, fontName="Helvetica-Bold",
fillColor=C["navy"], textAnchor="middle"))
# boxes
box(d,165,dh-50,160,30,C["red"],text="CORD PROLAPSE\nDIAGNOSED",fs=10,bold=True)
arrow(d,245,dh-50,245,dh-74)
box(d,110,dh-102,270,30,C["navy"],
text="PUSH UP — Elevate presenting part\nTrendelenburg / Knee-chest position",fs=9.5,bold=True)
arrow(d,245,dh-102,245,dh-124)
diamond(d,245,dh-144,108,24,C["amber"],text="Fetus\nalive & viable?",fs=10)
# YES branch → dilated?
arrow(d,137,dh-144,65,dh-144,col=C["green"],w=1.5)
lbl(d,100,dh-136,"YES",10,C["green"])
diamond(d,65,dh-172,58,24,C["teal"],text="Fully\ndilated?",fs=9)
arrow(d,65,dh-196,65,dh-226,col=C["teal"],w=1.2)
lbl(d,68,dh-212,"YES",9,C["teal"])
box(d,10,dh-254,110,28,C["teal"],text="Vaginal\nDelivery",fs=10,bold=True)
arrow(d,7,dh-172,7,dh-226,col=C["red"],w=1.2)
lbl(d,0,dh-205,"NO",9,C["red"])
box(d,0,dh-260,100,26,C["dblue"],text="Grade 1\nEmerg CS",fs=9,bold=True)
# NO fetus
arrow(d,353,dh-144,420,dh-144,col=C["red"],w=1.5)
lbl(d,378,dh-136,"NO",10,C["red"])
box(d,378,dh-158,105,26,C["grey"],text="Maternal\nwellbeing only",fs=8.5)
# main flow continues
arrow(d,245,dh-168,245,dh-195)
box(d,150,dh-223,190,28,C["dblue"],
text="Emergency CS Grade 1\nDelivery within 30 min",fs=9.5,bold=True)
arrow(d,245,dh-223,245,dh-248)
box(d,150,dh-278,190,28,C["green"],
text="Neonatologist present\nActive fetal resuscitation",fs=9)
# prevention
box(d,140,dh-310,210,28,C["purple"],
text="PREVENT: ARM only when\npresenting part is engaged",fs=9)
return d
def inversion_flow_lg(dw=490, dh=250):
d=Drawing(dw,dh)
d.add(Rect(0,0,dw,dh,fillColor=C["lgrey"],strokeColor=C["navy"],strokeWidth=0.5,rx=6))
d.add(String(dw/2,dh-16,"UTERINE INVERSION — Management Flowchart",
fontSize=11,fontName="Helvetica-Bold",
fillColor=C["navy"],textAnchor="middle"))
steps=[
("CALL FOR HELP + IV × 2 + O₂ + Monitoring",C["red"],280,30),
("STOP Oxytocin | Do NOT remove placenta",C["orange"],280,28),
("TOCOLYSIS: Terbutaline 250 mcg SC / GTN / GA",C["amber"],280,26),
("Johnson's Manoeuvre:\nPush fundus upward through vagina → umbilicus",C["dblue"],300,36),
("O'Sullivan's Method:\n3–5 L warm saline into vagina; block introitus",C["teal"],300,36),
]
y=dh-34
for i,(txt,col,bwi,bhi) in enumerate(steps):
bx=(dw-bwi)/2; y-=bhi+4
box(d,bx,y,bwi,bhi,col,text=txt,fs=9.5,bold=(i==0))
if i<len(steps)-1:
arrow(d,dw/2,y,dw/2,y-4,col=C["grey"],w=1.5,head=6)
# surgical
y-=24
d.add(String(dw/2,y+10,"If manual methods FAIL →",
fontSize=10,fillColor=C["red"],
textAnchor="middle",fontName="Helvetica-Bold"))
arrow(d,175,y,90,y-18,col=C["navy"],w=1.2)
arrow(d,315,y,400,y-18,col=C["navy"],w=1.2)
box(d,20,y-46,150,28,C["navy"],text="Huntington's Op\n(abdominal pull-up)",fs=9)
box(d,320,y-46,150,28,C["purple"],text="Haultain's Op\n(cervical incision)",fs=9)
box(d,175,y-46,140,28,C["green"],text="Post-reduction:\nOxytocin ASAP",fs=9)
return d
def afe_lg(dw=490,dh=210):
d=Drawing(dw,dh)
d.add(Rect(0,0,dw,dh,fillColor=C["lgrey"],strokeColor=C["navy"],strokeWidth=0.5,rx=6))
d.add(String(dw/2,dh-16,"AFE — Cascade & Management",
fontSize=11,fontName="Helvetica-Bold",
fillColor=C["navy"],textAnchor="middle"))
ph1=[("Trigger\n(labour/CS/ARM)",C["orange"]),
("AF enters\npulmonary circ.",C["amber"]),
("Pulmonary\nvasospasm",C["red"]),
("Acute Rt heart\nfailure + Hypoxia",C["red"])]
bw=93;bh=42;y1=dh-68
for i,(txt,col) in enumerate(ph1):
x=10+i*(bw+15)
box(d,x,y1,bw,bh,col,text=txt,fs=9,bold=(i==0))
if i<len(ph1)-1:
arrow(d,x+bw,y1+bh/2,x+bw+15,y1+bh/2,col=C["navy"],w=1.5)
d.add(String(dw/2,y1-10,"↓ Phase 2 (30–60 min later)",
fontSize=9.5,fillColor=C["red"],
fontName="Helvetica-Bold",textAnchor="middle"))
ph2=[("LV Failure\n+ pulm. oedema",C["purple"]),
("DIC + coagulopathy",C["red"]),
("Massive PPH\nhaemorrhage",C["navy"]),
("Seizures /\nCardiac Arrest",C["red"])]
y2=dh-134
for i,(txt,col) in enumerate(ph2):
x=10+i*(bw+15)
box(d,x,y2,bw,bh,col,text=txt,fs=9)
if i<len(ph2)-1:
arrow(d,x+bw,y2+bh/2,x+bw+15,y2+bh/2,col=C["navy"],w=1.5)
mgmt=[("Intubate\n100% O₂",C["teal"]),
("CPR +\nVasopressors",C["dblue"]),
("FFP + Platelets\n+ Cryo + TXA",C["green"]),
("Perimortem CS\n(within 5 min)",C["navy"])]
y3=dh-182
d.add(Rect(6,y3-6,dw-12,50,rx=4,ry=4,
fillColor=C["lteal"],strokeColor=C["teal"],strokeWidth=1))
d.add(String(dw/2,y3+40,"MANAGEMENT:",
fontSize=10,fillColor=C["teal"],
fontName="Helvetica-Bold",textAnchor="middle"))
for i,(txt,col) in enumerate(mgmt):
x=10+i*(bw+15)
box(d,x,y3+2,bw,36,col,text=txt,fs=9)
if i<len(mgmt)-1:
arrow(d,x+bw,y3+20,x+bw+15,y3+20,col=C["teal"],w=1.2)
return d
def shock_lg(dw=490,dh=220):
d=Drawing(dw,dh)
d.add(Rect(0,0,dw,dh,fillColor=C["lgrey"],strokeColor=C["navy"],strokeWidth=0.5,rx=6))
d.add(String(dw/2,dh-16,"OBSTETRIC SHOCK — Types & ABCDE Management",
fontSize=11,fontName="Helvetica-Bold",
fillColor=C["navy"],textAnchor="middle"))
types=[("HAEMORRHAGIC\nPPH/APH/Rupture",C["red"]),
("SEPTIC\nChorioamnionitis",C["orange"]),
("NEUROGENIC\nInversion/Epidural",C["purple"]),
("CARDIOGENIC\nAFE/Peripartum CM",C["dblue"]),
("ANAPHYLACTIC\nDrug/Transfusion",C["teal"])]
bw=82;bh=56;y_t=dh-88
for i,(txt,col) in enumerate(types):
x=10+i*(bw+7)
box(d,x,y_t,bw,bh,col,text=txt,fs=8.5,bold=False)
arrow(d,x+bw/2,y_t,245,y_t-32,col=C["grey"],w=0.8)
box(d,160,y_t-60,170,28,C["navy"],
text="SHOCK\nSBP<90 + HR>100",fs=10,bold=True)
abcde=[("A","Airway\nIntubate if\nGCS<8",C["navy"]),
("B","Breathing\n100% O₂",C["dblue"]),
("C","Circulation\n2 IV + Blood\n+ Fluids",C["teal"]),
("D","Disability\nGCS/AVPU\nGlucose",C["green"]),
("E","Exposure\nFind & treat\ncause",C["orange"])]
bw2=78;bh2=64;y_a=dh-192
arrow(d,245,y_t-60,245,y_a+bh2,col=C["navy"],w=1.5)
for i,(l,det,col) in enumerate(abcde):
x=8+i*(bw2+7)
box(d,x,y_a,bw2,bh2,col,text=f"{l}\n{det}",fs=8.5)
d.add(Rect(6,4,dw-12,20,rx=3,ry=3,fillColor=C["amber"],strokeColor=None))
d.add(String(dw/2,8,"Shock Index = HR ÷ SBP | Normal: 0.5–0.7 | >1.0 = significant haemorrhage",
fontSize=9,fillColor=C["navy"],textAnchor="middle",
fontName="Helvetica-Bold"))
return d
def rupture_lg(dw=490,dh=265):
d=Drawing(dw,dh)
d.add(Rect(0,0,dw,dh,fillColor=C["lgrey"],strokeColor=C["navy"],strokeWidth=0.5,rx=6))
d.add(String(dw/2,dh-16,"UTERINE RUPTURE — Decision Schema",
fontSize=11,fontName="Helvetica-Bold",
fillColor=C["navy"],textAnchor="middle"))
box(d,10,dh-54,220,32,C["amber"],
text="THREATENED\nBandl's ring • Tachycardia • CTG↓",fs=9,bold=True)
box(d,260,dh-54,220,32,C["red"],
text="ACTUAL RUPTURE\nContractions STOP • FHR absent • Shock",fs=9,bold=True)
arrow(d,120,dh-54,120,dh-96,col=C["amber"],w=1.2)
arrow(d,370,dh-54,370,dh-96,col=C["red"],w=1.5)
box(d,10,dh-120,220,26,C["lamber"],
text="Causes: LSCS scar | CPD\nOxytocin overuse | Grand multiparity",
fs=8.5,tc=C["navy"])
box(d,260,dh-120,220,26,C["lred"],
text="Signs: Recession of presenting part\nAbdominal rigidity | Maternal shock",
fs=8.5,tc=C["navy"])
box(d,140,dh-152,210,26,C["navy"],
text="RESUSCITATE: IV×2 + Blood + O₂",fs=10,bold=True)
arrow(d,120,dh-120,245,dh-126,col=C["amber"],w=1)
arrow(d,370,dh-120,245,dh-126,col=C["red"],w=1)
arrow(d,245,dh-152,245,dh-178,col=C["navy"],w=1.5)
box(d,100,dh-206,290,28,C["red"],
text="EMERGENCY LAPAROTOMY — DO NOT DELAY",fs=11,bold=True)
arrow(d,245,dh-206,245,dh-228,col=C["navy"],w=1.5)
box(d,25,dh-256,175,26,C["teal"],
text="REPAIR (if feasible)\nPrimary suture + BTL",fs=9.5)
box(d,290,dh-256,175,26,C["purple"],
text="HYSTERECTOMY\n(extensive rupture)",fs=9.5)
arrow(d,245,dh-228,120,dh-230,col=C["teal"],w=1)
arrow(d,245,dh-228,370,dh-230,col=C["purple"],w=1)
return d
def induction_lg(dw=490,dh=305):
d=Drawing(dw,dh)
d.add(Rect(0,0,dw,dh,fillColor=C["lgrey"],strokeColor=C["navy"],strokeWidth=0.5,rx=6))
d.add(String(dw/2,dh-16,"INDUCTION & AUGMENTATION — Decision Algorithm",
fontSize=11,fontName="Helvetica-Bold",
fillColor=C["navy"],textAnchor="middle"))
box(d,155,dh-50,180,26,C["navy"],text="INDICATION for IOL",fs=10,bold=True)
arrow(d,245,dh-50,245,dh-74)
diamond(d,245,dh-94,110,24,C["red"],text="Contraindication\npresent?",fs=10)
arrow(d,355,dh-94,430,dh-94,col=C["red"],w=1.5)
box(d,385,dh-108,100,26,C["red"],text="CS / alternate\nplan",fs=9)
lbl(d,390,dh-86,"YES",10,C["red"])
arrow(d,245,dh-118,245,dh-140,col=C["green"],w=1.5)
lbl(d,248,dh-130,"NO",10,C["green"])
diamond(d,245,dh-160,110,24,C["amber"],text="Bishop's Score?",fs=10)
# ≤5
arrow(d,135,dh-160,55,dh-160,col=C["red"],w=1.5)
lbl(d,88,dh-152,"≤5",10,C["red"])
box(d,2,dh-180,110,34,C["orange"],
text="RIPEN CERVIX\nPGE₂/Misoprostol\nFoley balloon",fs=8.5)
arrow(d,57,dh-180,57,dh-228,col=C["orange"],w=1.2)
box(d,2,dh-256,110,28,C["amber"],text="Reassess\nBishop's 6–12h",fs=8.5)
# ≥8
arrow(d,355,dh-160,420,dh-160,col=C["green"],w=1.5)
lbl(d,374,dh-152,"≥8",10,C["green"])
box(d,378,dh-180,108,26,C["teal"],text="FAVOURABLE\nProceed → ARM",fs=8.5)
arrow(d,432,dh-180,432,dh-226,col=C["teal"],w=1.2)
box(d,380,dh-254,108,28,C["teal"],text="ARM +\nSyntocinon",fs=9)
# 6-7
arrow(d,245,dh-184,245,dh-205,col=C["amber"],w=1.5)
lbl(d,248,dh-196,"6–7",10,C["amber"])
box(d,165,dh-233,160,30,C["amber"],
text="Intermediate:\nCervical ripening\nthen ARM + oxytocin",fs=8.5)
# aug row
box(d,5,dh-278,235,32,C["purple"],
text="AUGMENTATION (poor progress):\nARM if intact → Oxytocin infusion\nTarget: ≥3 cx/10min × 40–60 sec",fs=8)
box(d,252,dh-278,233,32,C["dblue"],
text="MONITORING:\nContinuous CTG\nWHO Partograph — action line",fs=8)
return d
def bishop_flow_lg(dw=490,dh=140):
d=Drawing(dw,dh)
d.add(Rect(0,0,dw,dh,fillColor=C["lgrey"],strokeColor=C["navy"],strokeWidth=0.5,rx=6))
d.add(String(dw/2,dh-16,"BISHOP'S SCORE — Interpretation & Action",
fontSize=11,fontName="Helvetica-Bold",
fillColor=C["navy"],textAnchor="middle"))
items=[
("Score ≤5\nUNFAVOURABLE","Cervical ripening:\nPGE₂ / Foley\nbefore induction",C["red"]),
("Score 6–7\nINTERMEDIATE","Cervical ripening\nrecommended;\nreassess in 6 hr",C["amber"]),
("Score ≥8\nFAVOURABLE","Proceed directly:\nARM + Syntocinon\ninduction",C["green"]),
]
bw=138;bh=94;y0=24
x_start=(dw-len(items)*bw-(len(items)-1)*18)/2
for i,(score,action,col) in enumerate(items):
x=x_start+i*(bw+18)
box(d,x,y0,bw,bh,col,text=f"{score}\n↓\n{action}",fs=9.5)
if i<len(items)-1:
arrow(d,x+bw,y0+bh/2,x+bw+18,y0+bh/2,col=C["grey"],w=1.5,head=7)
return d
def ventouse_lg(dw=490,dh=230):
d=Drawing(dw,dh)
d.add(Rect(0,0,dw,dh,fillColor=C["lgrey"],strokeColor=C["navy"],strokeWidth=0.5,rx=6))
d.add(String(dw/2,dh-16,"VENTOUSE — Prerequisites, Procedure & Complications",
fontSize=11,fontName="Helvetica-Bold",
fillColor=C["navy"],textAnchor="middle"))
# prereqs
d.add(String(dw/2,dh-36,"PREREQUISITES (ABCDEF):",
fontSize=10,fontName="Helvetica-Bold",
fillColor=C["navy"],textAnchor="middle"))
pre=[("A — Anaesthesia\nPerineal/regional",C["navy"]),
("B — Bladder\nEmptied",C["dblue"]),
("C — Cervix\nFully dilated",C["teal"]),
("D — Denominator\nKnown (occiput)",C["green"]),
("E — Engaged\nHead",C["orange"]),
("F — Fontanelle\nPost. accessible",C["purple"])]
bw_p=74;bh_p=40;y_p=dh-80
for i,(txt,col) in enumerate(pre):
x=5+i*(bw_p+4)
box(d,x,y_p,bw_p,bh_p,col,text=txt,fs=8.5)
# procedure
d.add(String(dw/2,y_p-14,"PROCEDURE:",
fontSize=10,fontName="Helvetica-Bold",
fillColor=C["navy"],textAnchor="middle"))
proc=[("Cup at\nflexion point\n(3 cm from\npost. fontanelle)",C["dblue"]),
("Build suction\nto 0.8 kg/cm²",C["teal"]),
("Traction with\ncontractions +\nmaternal push",C["green"]),
("Max 3 pulls\n/ 20 min total\n(3 pop-off rule)",C["orange"])]
bw_r=100;bh_r=52;y_r=y_p-78
for i,(txt,col) in enumerate(proc):
x=10+i*(bw_r+10)
box(d,x,y_r,bw_r,bh_r,col,text=txt,fs=8.5)
if i<len(proc)-1:
arrow(d,x+bw_r,y_r+bh_r/2,x+bw_r+10,y_r+bh_r/2,col=C["navy"],w=1.5)
# complications
d.add(Rect(5,4,232,26,rx=3,ry=3,fillColor=C["lred"],strokeColor=C["red"],strokeWidth=0.8))
d.add(String(8,12,"FETAL: Chignon • Cephalhaematoma • Subgaleal haemorrhage",
fontSize=8.5,fillColor=C["red"]))
d.add(Rect(248,4,236,26,rx=3,ry=3,fillColor=C["lpurple"],strokeColor=C["purple"],strokeWidth=0.8))
d.add(String(252,12,"MATERNAL: Perineal tears • PPH • Cervical tears",
fontSize=8.5,fillColor=C["purple"]))
return d
def forceps_lg(dw=490,dh=220):
d=Drawing(dw,dh)
d.add(Rect(0,0,dw,dh,fillColor=C["lgrey"],strokeColor=C["navy"],strokeWidth=0.5,rx=6))
d.add(String(dw/2,dh-16,"FORCEPS — Types, Application & Complications",
fontSize=11,fontName="Helvetica-Bold",
fillColor=C["navy"],textAnchor="middle"))
d.add(String(dw/2,dh-34,"TYPES OF FORCEPS:",
fontSize=10,fontName="Helvetica-Bold",
fillColor=C["navy"],textAnchor="middle"))
types=[("Wrigley's","Outlet / CS\nforceps\nShort + curved",C["teal"]),
("Neville-Barnes","Mid-cavity\nMOST COMMON\nEnglish lock",C["dblue"]),
("Kielland's","Rotational\nOT/OP positions\nSliding lock",C["purple"]),
("Piper's","After-coming\nbreech head\nLong shanks",C["orange"])]
bw_t=108;bh_t=58;y_t=dh-100
for i,(name,use,col) in enumerate(types):
x=10+i*(bw_t+9)
box(d,x,y_t,bw_t,bh_t,col,text=f"{name}\n{use}",fs=8.5)
d.add(String(dw/2,y_t-14,"APPLICATION (Left blade FIRST):",
fontSize=10,fontName="Helvetica-Bold",
fillColor=C["navy"],textAnchor="middle"))
steps=["Left blade\nfirst (L hand)",
"Right blade\n(R hand)",
"Lock & check\nposition",
"Pajot's\ntraction",
"Remove at\ncrowning"]
bw_s=82;bh_s=34;y_s=y_t-62
for i,txt in enumerate(steps):
x=8+i*(bw_s+7)
box(d,x,y_s,bw_s,bh_s,
[C["navy"],C["dblue"],C["teal"],C["green"],C["orange"]][i],
text=txt,fs=9)
if i<len(steps)-1:
arrow(d,x+bw_s,y_s+bh_s/2,x+bw_s+7,y_s+bh_s/2,
col=C["grey"],w=1.2)
d.add(Rect(5,4,232,24,rx=3,ry=3,fillColor=C["lred"],strokeColor=C["red"],strokeWidth=0.8))
d.add(String(8,10,"FETAL: Facial marks • Nerve palsy • Cephalhaematoma",
fontSize=8.5,fillColor=C["red"]))
d.add(Rect(248,4,236,24,rx=3,ry=3,fillColor=C["lpurple"],strokeColor=C["purple"],strokeWidth=0.8))
d.add(String(252,10,"MATERNAL: 3rd/4th degree tears • Bladder injury • PPH",
fontSize=8.5,fillColor=C["purple"]))
return d
def cs_lg(dw=490,dh=275):
d=Drawing(dw,dh)
d.add(Rect(0,0,dw,dh,fillColor=C["lgrey"],strokeColor=C["navy"],strokeWidth=0.5,rx=6))
d.add(String(dw/2,dh-16,"CAESAREAN SECTION — Grading, Layers & VBAC",
fontSize=11,fontName="Helvetica-Bold",
fillColor=C["navy"],textAnchor="middle"))
# RCOG grades
d.add(String(dw/2,dh-34,"RCOG URGENCY GRADING:",
fontSize=10,fontName="Helvetica-Bold",
fillColor=C["navy"],textAnchor="middle"))
grades=[("Grade 1\nEMERGENCY\n→ 30 min",C["red"]),
("Grade 2\nURGENT\n→ 75 min",C["orange"]),
("Grade 3\nSCHEDULED\n→ Early",C["amber"]),
("Grade 4\nELECTIVE\n→ ≥39 wk",C["green"])]
bw_g=106;bh_g=58;y_g=dh-102
for i,(txt,col) in enumerate(grades):
x=15+i*(bw_g+12)
box(d,x,y_g,bw_g,bh_g,col,text=txt,fs=9.5,bold=True)
# Layers staircase
d.add(String(dw/2,y_g-14,"SURGICAL LAYERS (Pfannenstiel):",
fontSize=10,fontName="Helvetica-Bold",
fillColor=C["navy"],textAnchor="middle"))
layers=[("Skin (Pfannenstiel incision)",C["lamber"]),
("Subcutaneous fat",C["lorange"]),
("Rectus sheath (transverse)",C["lgreen"]),
("Rectus muscles (blunt separation)",C["lteal"]),
("Peritoneum (vertical)",C["lblue"]),
("Uterovesical fold + Doyen's retractor",C["lpurple"]),
("Lower Uterine Segment — INCISE HERE",C["lred"])]
lbw=230;lbh=17;y_l=y_g-32
for i,(txt,col) in enumerate(layers):
inset=i*5
x=(dw-lbw)/2+inset/2; w=lbw-inset
tc=C["red"] if "INCISE" in txt else C["navy"]
bord=C["red"] if "INCISE" in txt else C["navy"]
box(d,x,y_l-i*lbh,w,lbh-1,col,
text=txt,fs=8.5,tc=tc,bw=1.8 if "INCISE" in txt else 0.6)
# VBAC
y_v=y_l-len(layers)*lbh-8
box(d,5,y_v,238,28,C["lteal"],
text="VBAC: 1 prev LSCS + cephalic\nSuccess 60–80% | Rupture risk 0.5%",
fs=9,tc=C["navy"])
box(d,252,y_v,233,28,C["lred"],
text="Classical CS → CS in ALL future\npregnancies (high rupture risk)",
fs=9,tc=C["navy"])
return d
def presentations_lg(dw=490,dh=215):
d=Drawing(dw,dh)
d.add(Rect(0,0,dw,dh,fillColor=C["lgrey"],strokeColor=C["navy"],strokeWidth=0.5,rx=6))
d.add(String(dw/2,dh-16,"ABNORMAL PRESENTATIONS — Comparison",
fontSize=11,fontName="Helvetica-Bold",
fillColor=C["navy"],textAnchor="middle"))
hdrs=["Feature","FACE","BROW","SHOULDER"]
hbgs=[C["navy"],C["teal"],C["orange"],C["purple"]]
cws=[110,122,122,122]; xs=[4,114,236,358]
yh=dh-44
for ci,(h,bg,cw,x) in enumerate(zip(hdrs,hbgs,cws,xs)):
box(d,x,yh,cw-2,26,bg,text=h,fs=10,bold=True)
rows=[
("Denominator","Mentum (chin)","Frontal bone","Acromion"),
("Diameter","Submentobregmatic\n9.5 cm","Mentovertical\n13.5 cm LARGEST","Bisacromial\n11 cm transverse"),
("VE finding","Orbital ridges\nnose + chin","Orbital ridges\n+ BOTH fontanelles","Shoulder / arm\nor rib felt"),
("Delivery","Mentoanterior →\nVaginal delivery\nMentoposterior → CS","CS (mostly)\nMay → vertex/face","CS MANDATORY\n(all cases at term)"),
("Key warning","Mentoposterior =\nCS immediately","Largest diameter =\nnever delivers","Neglected → uterine\nrupture + death"),
]
rh=32
for ri,row in enumerate(rows):
for ci,(val,cw,x) in enumerate(zip(row,cws,xs)):
if ci==0: bg=C["navy"]; tc=C["white"]
else:
if "CS MANDATORY" in val or "CS immediately" in val or "rupture" in val.lower():
bg=C["lred"]; tc=C["red"]
elif "Vaginal" in val or "vertex" in val:
bg=C["lgreen"]; tc=C["green"]
else:
bg=C["lblue"] if ri%2==0 else C["white"]; tc=C["navy"]
y=yh-(ri+1)*(rh+1)
box(d,x,y,cw-2,rh,bg,text=val,fs=7.5,tc=tc,rx=2)
return d
# ══════════════════════════════════════════════════════════
# BUILD STORY
# ══════════════════════════════════════════════════════════
story=[]
# COVER
story+=[
sp(3),
Paragraph("OBSTETRICS", TITLE),
Paragraph("20-Mark Notes — LARGE PRINT Schematic Edition", SUBT),
Paragraph("Optimised for Xerox / Photocopy printing", SUBT),
sp(),hr(),sp(),
Paragraph("Obstetric Emergencies • Bishop's Score • Induction/Augmentation<br/>"
"Ventouse • Forceps • Caesarean Section • Abnormal Presentations", SUBT),
Paragraph("Harrison's 22E | Goldman-Cecil | Rosen's EM | Orris Medical", FOOT),
PageBreak()
]
# ─── SECTION 1: OBSTETRIC EMERGENCIES ────────────────────
story+=[sec_banner("SECTION 1 — OBSTETRIC EMERGENCIES"),sp(0.5)]
# 1. CORD PROLAPSE
story+=[subsec("1. CORD PROLAPSE",C["red"]),sp(0.3)]
story+=[cord_tree_lg(),cap("Fig 1. Cord prolapse — management decision tree"),sp(0.4)]
story+=[
tbl(["Type","Signs","Immediate Action","Definitive Rx"],
[["Overt prolapse","Cord visible at introitus;\nCTG — bradycardia/variable decels",
"PUSH UP protocol; elevate presenting part;\nTrendelenburg/knee-chest; stop oxytocin",
"Emergency CS Grade 1\n(within 30 min)"],
["Occult prolapse","CTG changes only;\ncord not visible",
"VE to confirm; elevate head;\nstop oxytocin",
"CS if fetal compromise\nnot resolving"]],
cw=[3*cm,4*cm,5*cm,4.5*cm]),
sp(0.4)
]
story+=[
h2("PUSH UP Protocol:"),
b("<b>P</b> — Position: Knee-chest or Trendelenburg — reduces cord compression"),
b("<b>U</b> — Umbilical cord: Keep warm & moist (saline-soaked swab); NEVER compress"),
b("<b>S</b> — Stop oxytocin infusion immediately"),
b("<b>H</b> — Hand: Elevate presenting part off cord until delivery"),
b("<b>U</b> — Urgent CS Grade 1 (within 30 min) in most cases"),
b("<b>P</b> — Paediatrician/neonatologist to attend; tocolysis (terbutaline 250 mcg SC)"),
w("DELIVERY MUST OCCUR WITHIN 30 MINUTES"),
sp(0.5),PageBreak()
]
# 2. UTERINE INVERSION
story+=[subsec("2. UTERINE INVERSION",C["red"]),sp(0.3)]
story+=[inversion_flow_lg(),cap("Fig 2. Uterine inversion — step-by-step management flowchart"),sp(0.4)]
story+=[
tbl(["Degree","Description","Management"],
[["1st (Incomplete)","Fundus dimples above internal os","Oxytocin + gentle manual reduction"],
["2nd (Complete)","Fundus through internal os into vagina","Johnson's manoeuvre; tocolysis first"],
["3rd (Prolapsed)","Fundus visible at/beyond introitus","Johnson's / O'Sullivan's method"],
["4th (Total)","Vagina also inverted","Surgical: Huntington's / Haultain's"]],
cw=[3*cm,6*cm,7.5*cm]),
sp(0.4)
]
story+=[
w("NEVER remove placenta before repositioning — causes massive haemorrhage"),
h2("Key Diagnosis Points:"),
b("Sudden massive PPH + neurogenic shock (disproportionate hypotension)"),
b("CANNOT feel uterine fundus abdominally"),
b("Mass visible at or protruding from introitus (3rd/4th degree)"),
sp(0.5),PageBreak()
]
# 3. AFE
story+=[subsec("3. AMNIOTIC FLUID EMBOLISM (AFE)",C["red"]),sp(0.3)]
story+=[afe_lg(),cap("Fig 3. AFE — two-phase pathophysiology cascade + management"),sp(0.4)]
story+=[
tbl(["Feature","Details"],
[["Incidence","1 in 8,000–80,000; Mortality 20–60%"],
["Classical Triad","① Sudden collapse ② Respiratory failure ③ DIC/coagulopathy"],
["Phase 1","AF enters pulmonary circ → vasospasm → acute Rt heart failure → hypoxia"],
["Phase 2 (30–60 min)","LV failure + DIC → uncontrollable haemorrhage + seizures"],
["Investigations","ABG: hypoxia + acidosis | CXR: pulm oedema | Coag: ↓fibrinogen, ↑D-dimer"],
["Perimortem CS","If maternal cardiac arrest → CS within 5 minutes (improves both outcomes)"]],
cw=[4*cm,12.5*cm]),
sp(0.5),PageBreak()
]
# 4. OBSTETRIC SHOCK
story+=[subsec("4. OBSTETRIC SHOCK",C["red"]),sp(0.3)]
story+=[shock_lg(),cap("Fig 4. Obstetric shock — 5 types + ABCDE management schema"),sp(0.4)]
story+=[
tbl(["Class","Blood Loss","HR","SBP","Action"],
[["I (<15%)","<750 mL","<100","Normal","IV fluids, monitor, crossmatch"],
["II (15–30%)","750–1500 mL","100–120","Normal–low","2 large-bore IV, fluid bolus, transfuse"],
["III (30–40%)","1500–2000 mL","120–140","<90","Blood + FFP; massive haemorrhage protocol"],
["IV (>40%)",">2000 mL",">140","<70","Immediate surgery; vasopressors; MHP"]],
cw=[2.5*cm,3*cm,2*cm,2*cm,7*cm]),
sp(0.5),PageBreak()
]
# 5. UTERINE RUPTURE
story+=[subsec("5. UTERINE RUPTURE",C["red"]),sp(0.3)]
story+=[rupture_lg(),cap("Fig 5. Uterine rupture — threatened vs actual, decision schema"),sp(0.4)]
story+=[
tbl(["Sign","Threatened Rupture","Actual Rupture"],
[["Pain","Severe uterine pain; hyperstimulation","Contractions stop; constant pain"],
["Bandl's ring","Visible above pubic symphysis","May be absent (rupture occurred)"],
["Fetal heart","Tachycardia / variable decels","ABSENT (fetal death 50–75%)"],
["Presenting part","Remains in pelvis","RECEDES into abdomen"],
["Maternal","Tachycardia; haematuria","Hypotension; shock; rigidity"],
["Management","STOP oxytocin; prepare theatre","Emergency laparotomy IMMEDIATELY"]],
cw=[3.5*cm,6.5*cm,6.5*cm]),
w("Prevention: VBAC only in units with 24-hr CS access. Never use high-dose oxytocin in scarred uterus."),
sp(0.5),PageBreak()
]
# ─── SECTION 2: BISHOP'S SCORE ───────────────────────────
story+=[sec_banner("SECTION 2 — BISHOP'S SCORE"),sp(0.5)]
story+=[bishop_schema_lg(),cap("Fig 6. Bishop's Score — 5 parameters × 4 scores (maximum = 13)"),sp(0.4)]
story+=[bishop_flow_lg(),cap("Fig 7. Bishop's Score interpretation and action flowchart"),sp(0.4)]
story+=[
tbl(["Parameter","Score 0","Score 1","Score 2","Score 3","Note"],
[["Dilatation","Closed","1–2 cm","3–4 cm","≥5 cm","MOST important"],
["Effacement","0–30%","40–50%","60–70%","≥80%","Cervix shortening"],
["Station","-3","-2","-1 to 0","+1 to +2","Re: ischial spines"],
["Consistency","Firm","Medium","Soft","—","Max = 2"],
["Position","Posterior","Mid","Anterior","—","Max = 2"]],
cw=[3.2*cm,2*cm,2*cm,2*cm,2*cm,5.3*cm]),
sp(0.5),PageBreak()
]
# ─── SECTION 3: INDUCTION ────────────────────────────────
story+=[sec_banner("SECTION 3 — INDUCTION & AUGMENTATION OF LABOUR"),sp(0.5)]
story+=[induction_lg(),cap("Fig 8. Induction/Augmentation decision algorithm"),sp(0.4)]
story+=[
tbl(["Method","Dose/Technique","Indication","Key Points"],
[["Membrane sweep","Digital separation of chorion at 40–41 wk","Outpatient IOL priming","Reduces need for formal IOL"],
["Dinoprostone PGE₂","Gel 0.5 mg intracervical; repeat q6h","Bishop ≤5; unfavourable","Avoid in scarred uterus"],
["Misoprostol PGE₁","25–50 mcg vaginally q4–6h","Cervical ripening","Cheap; widely used; AVOID in scarred uterus"],
["Foley catheter","30–60 mL balloon transcervically","Unfavourable cervix; SAFE in prev CS","Mechanical; no systemic effects"],
["ARM (Amniotomy)","Amniohook; cervix ≥2–3 cm dilated","Favourable cervix; augmentation","Risk: cord prolapse if head unengaged"],
["Syntocinon (Oxytocin)","1–2 mU/min IV; titrate q30 min; max 40 mU/min","Post-ARM IOL + augmentation","Continuous CTG mandatory; risk of uterine hyperstimulation"]],
cw=[3.2*cm,4*cm,3.5*cm,5.8*cm]),
w("NEVER augment with oxytocin in scarred uterus without close senior monitoring"),
sp(0.5),PageBreak()
]
# ─── SECTION 4a: VENTOUSE ────────────────────────────────
story+=[sec_banner("SECTION 4a — VENTOUSE (VACUUM EXTRACTOR) DELIVERY"),sp(0.5)]
story+=[ventouse_lg(),cap("Fig 9. Ventouse — prerequisites, procedure steps, complications"),sp(0.4)]
story+=[
tbl(["Indication","Contraindication"],
[["Prolonged 2nd stage (nullipara >3 hr with regional; >2 hr without)","<34 weeks gestation (risk of intracranial haemorrhage)"],
["Fetal compromise in 2nd stage (non-reassuring CTG)","Face presentation"],
["Maternal exhaustion","Active fetal bleeding or coagulopathy"],
["Maternal conditions — avoid prolonged Valsalva (cardiac, neuro, aneurysm)","CPD or uncertain presentation/position"]],
cw=[8.25*cm,8.25*cm]),
sp(0.4)
]
story+=[
h2("Complications:"),
h3("Fetal:"),
b("<b>Chignon:</b> Scalp oedema inside cup — resolves in 24–48 hours (benign)"),
b("<b>Cephalhaematoma:</b> Subperiosteal haematoma — resolves in weeks"),
b("<b>Subgaleal haemorrhage:</b> DANGEROUS — crosses skull sutures; can cause hypovolaemic shock"),
b("<b>Intracranial haemorrhage</b> (rare) | Retinal haemorrhage"),
h3("Maternal:"),
b("Perineal/vaginal tears, PPH, cervical tears"),
sp(0.5),PageBreak()
]
# ─── SECTION 4b: FORCEPS ─────────────────────────────────
story+=[sec_banner("SECTION 4b — FORCEPS DELIVERY"),sp(0.5)]
story+=[forceps_lg(),cap("Fig 10. Forceps types, left-blade-first application, complications"),sp(0.4)]
story+=[
tbl(["Classification","Station","Forceps Used","Notes"],
[["Outlet forceps","Scalp at introitus; rotation ≤45°","Wrigley's","Easiest; lowest risk"],
["Low forceps","Station ≥+2","Neville-Barnes","Most common in practice"],
["Mid-cavity forceps","Station 0 to +2","Neville-Barnes / Kielland's","Needs senior obstetrician"],
["High forceps","Not engaged","ABANDONED","CS indicated — NEVER apply"]],
cw=[3.5*cm,4.5*cm,4*cm,4.5*cm]),
sp(0.3)
]
story+=[
tbl(["Feature","Ventouse","Forceps"],
[["Maternal trauma","Less","More (perineal tears 3rd/4th degree)"],
["Fetal risk","Chignon, subgaleal haematoma","Facial marks, nerve palsy, skull fracture"],
["Failure rate","15–20%","5–10%"],
["Rotation","Passive (head rotates spontaneously)","Active rotation (Kielland's)"],
["Preterm head","AVOID <34 weeks","May protect preterm head"],
["Breech after-coming head","Not suitable","Piper's forceps"],
["Sequential use","Avoid using BOTH — increases neonatal morbidity","—"]],
cw=[4*cm,6*cm,6.5*cm]),
sp(0.5),PageBreak()
]
# ─── SECTION 4c: CS ──────────────────────────────────────
story+=[sec_banner("SECTION 4c — CAESAREAN SECTION (CS)"),sp(0.5)]
story+=[cs_lg(),cap("Fig 11. CS RCOG grading, surgical layers, VBAC criteria"),sp(0.4)]
story+=[
tbl(["Type","Uterine Incision","Key Indication","Future Pregnancy"],
[["LSCS","Transverse lower segment","Most common (>95%)","VBAC possible if eligible"],
["Classical CS","Vertical upper segment","Transverse lie; very preterm; anterior PP","CS mandatory in ALL future pregnancies"],
["Emergency (Gr 1)","Fastest route","Immediate threat to life","Depends on incision type"],
["Elective (Gr 4)","LSCS preferred","Maternal request; planned breech","VBAC possible after 1 prev LSCS"]],
cw=[3*cm,3.5*cm,6*cm,4*cm]),
sp(0.3)
]
story+=[
h2("Absolute Indications for CS:"),
b("Placenta praevia major | Classical CS scar | Transverse lie at term"),
b("Cord prolapse (most) | Contracted pelvis (absolute CPD) | Invasive cervical Ca"),
h2("VBAC Eligibility:"),
b("1 previous LSCS | Singleton | Cephalic presentation | 37–41 weeks"),
b("No recurrent indication | Adequate pelvis | Unit with 24-hr CS access"),
w("Risk of uterine rupture in VBAC = ~0.5% (vs 0.02% for planned CS)"),
sp(0.5),PageBreak()
]
# ─── SECTION 5: ABNORMAL PRESENTATIONS ──────────────────
story+=[sec_banner("SECTION 5 — ABNORMAL PRESENTATIONS"),sp(0.5)]
story+=[presentations_lg(),cap("Fig 12. Face / Brow / Shoulder presentation comparison schema"),sp(0.4)]
face_f=hflow(["Vertex fully\nextended\n= FACE","VE: orbital\nridges + nose\n+ chin felt",
"Determine\nMENTUM\nposition","Mentoanterior\n→ Vaginal\ndelivery","Mentoposterior\n→ CS\nMANDATORY"],
dw=490,dh=88,title="FACE PRESENTATION — Management Flow",
colours=[C["teal"],C["teal"],C["amber"],C["green"],C["red"]],fs=9.5)
brow_f=hflow(["Partial\nextension\n= BROW","VE: orbital\nridges + BOTH\nfontanelles",
"Mentovertical\n13.5 cm —\nCANNOT engage","Often converts\n→ vertex\nor face","Persistent\nbrow →\nCS MANDATORY"],
dw=490,dh=88,title="BROW PRESENTATION — Management Flow",
colours=[C["orange"],C["orange"],C["red"],C["amber"],C["red"]],fs=9.5)
shoulder_f=hflow(["Transverse lie\n= SHOULDER","Wide uterus;\nno pole at\nfundus/pelvis",
"VE: rib/arm\nshoulder felt","Pre-labour:\nattempt ECV",
"At term /\nin labour →\nCS MANDATORY","Neglected →\nBandl's ring\n→ RUPTURE"],
dw=490,dh=88,title="SHOULDER/TRANSVERSE LIE — Management Flow",
colours=[C["purple"],C["purple"],C["purple"],C["amber"],C["red"],C["red"]],fs=9.5)
story+=[
face_f,cap("Fig 13. Face presentation — vertex→extended→mentum→MA vs MP decision"),sp(0.3),
brow_f,cap("Fig 14. Brow presentation — partial extension→converts vs persistent brow→CS"),sp(0.3),
shoulder_f,cap("Fig 15. Shoulder/transverse lie — ECV→CS; neglected→rupture"),sp(0.4),
]
story+=[
tbl(["Presentation","Denom.","Diameter","VD Possible?","Key Action"],
[["Face","Mentum (chin)","Submentobregmatic 9.5 cm","YES — if mentoanterior","Mentoposterior → CS immediately"],
["Brow","Frontal bone","Mentovertical 13.5 cm — LARGEST","NO (persistent)","Persistent brow → CS; observe for conversion"],
["Shoulder /\nTransverse","Acromion","Bisacromial (transverse)","NEVER at term","ECV pre-labour; CS at term; neglected → uterine rupture"]],
cw=[3*cm,2.5*cm,4*cm,3*cm,4*cm]),
sp(2),hr(),
Paragraph("Sources: Harrison's Principles of Internal Medicine 22E | Goldman-Cecil Medicine | "
"Rosen's Emergency Medicine | Orris Medical", FOOT),
Paragraph("LARGE PRINT Edition — Optimised for Xerox/Photocopy | July 2026", FOOT),
]
doc.build(story)
print("PDF generated:", OUT)
cd /home/daytona/workspace/obstetrics-notes && python gen_large.py 2>&1
Stopped??? Send fastttttttttttt I have exams tomorrow morning please
Obstetrics Schematic LARGE
PDF Document · PDF
Obstetrics Schematic
PDF Document · PDF
Gynaecology Exam Notes
PDF Document · PDF
Stanya Vigyana - Lactation a. Stanya, Stanya Sampat. b. Physiology of Lactation, Breast feeding techniques. c. Stanya dushti, Stana Shotha, Stana Vidradhi. d. Mastitis, Breast abscess. Diagnose Breast Engorgement, Mastitis, Breast abscess. Explain causes,clinical features,investigations and management of mastitis and breast abscess. Elaborate Stana Roga - Stana Keelaka, Stana Granthi and Stanarbuda with Nidana, Samprapti, Lakshana and Chikitsa. Describe causative factors, etiopathogenesis, clinical features, investigations, complications and management of Mastalgia, Fibroadenoma, Carcinoma breast. Demonstrate Self Breast examination Illustrate Investigations in diseases of Breast - 1. Sono- mammogram 2. Fine Needle Aspiration Cytology (FNAC)3. Biopsy Diagnose and manage Fibroadenoma Breast Diagnose Breast carcinoma needed in very big fonts because I can't see when I take Xerox Pdf
Stanya Vigyana - Lactation a. Stanya, Stanya Sampat. b. Physiology of Lactation, Breast feeding techniques. c. Stanya dushti, Stana Shotha, Stana Vidradhi. d. Mastitis, Breast abscess. Diagnose Breast Engorgement, Mastitis, Breast abscess. Explain causes,clinical features,investigations and management of mastitis and breast abscess. Elaborate Stana Roga - Stana Keelaka, Stana Granthi and Stanarbuda with Nidana, Samprapti, Lakshana and Chikitsa. Describe causative factors, etiopathogenesis, clinical features, investigations, complications and management of Mastalgia, Fibroadenoma, Carcinoma breast. Demonstrate Self Breast examination Illustrate Investigations in diseases of Breast - 1. Sono- mammogram 2. Fine Needle Aspiration Cytology (FNAC)3. Biopsy Diagnose and manage Fibroadenoma Breast Diagnose Breast carcinoma needed in very big fonts because I can't see when I take Xerox Pdf