Physiological changes during pregnancy & make a detailed summary downloadable photo or pdf for better visual memory

Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Running Command

mkdir -p /home/daytona/workspace/pregnancy-physiology && ls /home/daytona/workspace/pregnancy-physiology/

Writing File

~/pregnancy-physiology/make_pdf.py

#!/usr/bin/env python3
"""
Physiological Changes During Pregnancy - Visual Summary PDF
Based on Morgan & Mikhail's Clinical Anesthesiology, 7e
"""

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame
from reportlab.lib.colors import HexColor
import reportlab.lib.colors as rcolors

# ── Color Palette ──────────────────────────────────────────────────────────
DARK_BG      = HexColor('#0D1B2A')   # deep navy
HEADER_BG    = HexColor('#1B4F72')   # dark teal-blue
ACCENT_PINK  = HexColor('#E91E8C')   # hot pink accent
ACCENT_CYAN  = HexColor('#00BCD4')   # cyan accent
ACCENT_GOLD  = HexColor('#FFD600')   # golden yellow
ACCENT_GREEN = HexColor('#4CAF50')   # green
ACCENT_ORG   = HexColor('#FF6F00')   # orange
LIGHT_TEXT   = HexColor('#ECEFF1')   # near white
CARD_BG_1    = HexColor('#112233')   # card dark navy
CARD_BG_2    = HexColor('#0A2540')
ROW_ALT      = HexColor('#1A3555')
TABLE_HDR    = HexColor('#1565C0')
WHITE        = colors.white
BLACK        = colors.black

# ── Styles ─────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()

title_style = ParagraphStyle(
    'TitleStyle',
    fontName='Helvetica-Bold',
    fontSize=26,
    textColor=WHITE,
    alignment=TA_CENTER,
    spaceAfter=4,
    leading=30,
)
subtitle_style = ParagraphStyle(
    'SubtitleStyle',
    fontName='Helvetica',
    fontSize=12,
    textColor=ACCENT_CYAN,
    alignment=TA_CENTER,
    spaceAfter=2,
)
source_style = ParagraphStyle(
    'SourceStyle',
    fontName='Helvetica-Oblique',
    fontSize=9,
    textColor=HexColor('#90A4AE'),
    alignment=TA_CENTER,
    spaceAfter=6,
)
section_title_style = ParagraphStyle(
    'SectionTitle',
    fontName='Helvetica-Bold',
    fontSize=13,
    textColor=WHITE,
    alignment=TA_CENTER,
    spaceAfter=2,
    leading=16,
)
body_style = ParagraphStyle(
    'BodyStyle',
    fontName='Helvetica',
    fontSize=9,
    textColor=LIGHT_TEXT,
    alignment=TA_JUSTIFY,
    spaceAfter=4,
    leading=13,
)
bullet_style = ParagraphStyle(
    'BulletStyle',
    fontName='Helvetica',
    fontSize=8.5,
    textColor=LIGHT_TEXT,
    alignment=TA_LEFT,
    leftIndent=10,
    bulletIndent=2,
    spaceAfter=2,
    leading=12,
)
small_bold = ParagraphStyle(
    'SmallBold',
    fontName='Helvetica-Bold',
    fontSize=8,
    textColor=ACCENT_GOLD,
    alignment=TA_CENTER,
)
footnote_style = ParagraphStyle(
    'Footnote',
    fontName='Helvetica-Oblique',
    fontSize=7.5,
    textColor=HexColor('#78909C'),
    alignment=TA_CENTER,
)
card_header_style = ParagraphStyle(
    'CardHeader',
    fontName='Helvetica-Bold',
    fontSize=10,
    textColor=WHITE,
    alignment=TA_CENTER,
    leading=13,
)
card_body_style = ParagraphStyle(
    'CardBody',
    fontName='Helvetica',
    fontSize=8,
    textColor=LIGHT_TEXT,
    alignment=TA_LEFT,
    leading=11,
)
arrow_style = ParagraphStyle(
    'ArrowStyle',
    fontName='Helvetica-Bold',
    fontSize=9,
    textColor=ACCENT_GOLD,
    alignment=TA_CENTER,
)

# ── Helper to make a colored section banner ────────────────────────────────
def section_banner(title, icon, bg_color):
    data = [[Paragraph(f'{icon}  {title}', section_title_style)]]
    t = Table(data, colWidths=[17*cm])
    t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), bg_color),
        ('ROUNDEDCORNERS', [8]),
        ('TOPPADDING', (0,0), (-1,-1), 8),
        ('BOTTOMPADDING', (0,0), (-1,-1), 8),
        ('LEFTPADDING', (0,0), (-1,-1), 12),
    ]))
    return t

def make_change_table(rows, accent):
    """rows: list of (Parameter, Change, Clinical Note)"""
    header = [
        Paragraph('Parameter', ParagraphStyle('th', fontName='Helvetica-Bold', fontSize=9, textColor=WHITE, alignment=TA_CENTER)),
        Paragraph('Change', ParagraphStyle('th', fontName='Helvetica-Bold', fontSize=9, textColor=WHITE, alignment=TA_CENTER)),
        Paragraph('Clinical Significance', ParagraphStyle('th', fontName='Helvetica-Bold', fontSize=9, textColor=WHITE, alignment=TA_CENTER)),
    ]
    table_data = [header]
    for i, (param, change, note) in enumerate(rows):
        bg = ROW_ALT if i % 2 == 0 else CARD_BG_1
        # Determine change color
        if '+' in str(change):
            chg_color = HexColor('#69F0AE')  # green for increase
        elif '-' in str(change):
            chg_color = HexColor('#FF5252')  # red for decrease
        else:
            chg_color = ACCENT_GOLD
        row = [
            Paragraph(param, ParagraphStyle('td', fontName='Helvetica', fontSize=8.5, textColor=LIGHT_TEXT, alignment=TA_LEFT)),
            Paragraph(f'<b>{change}</b>', ParagraphStyle('chg', fontName='Helvetica-Bold', fontSize=9, textColor=chg_color, alignment=TA_CENTER)),
            Paragraph(note, ParagraphStyle('note', fontName='Helvetica', fontSize=8, textColor=HexColor('#B0BEC5'), alignment=TA_LEFT)),
        ]
        table_data.append(row)
    t = Table(table_data, colWidths=[5.5*cm, 2.5*cm, 9*cm])
    style = [
        ('BACKGROUND', (0,0), (-1,0), accent),
        ('GRID', (0,0), (-1,-1), 0.3, HexColor('#2C3E50')),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
        ('RIGHTPADDING', (0,0), (-1,-1), 6),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [ROW_ALT, CARD_BG_1]),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
    ]
    t.setStyle(TableStyle(style))
    return t

# ── Document setup ─────────────────────────────────────────────────────────
OUTPUT = '/home/daytona/workspace/pregnancy-physiology/Physiological_Changes_During_Pregnancy.pdf'

doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    rightMargin=1.8*cm,
    leftMargin=1.8*cm,
    topMargin=1.5*cm,
    bottomMargin=1.5*cm,
)

story = []

# ══════════════════════════════════════════════════════════════════════════════
# HEADER BLOCK
# ══════════════════════════════════════════════════════════════════════════════
header_data = [[
    Paragraph('PHYSIOLOGICAL CHANGES<br/>DURING PREGNANCY', title_style),
]]
header_table = Table(header_data, colWidths=[17*cm])
header_table.setStyle(TableStyle([
    ('BACKGROUND', (0,0), (-1,-1), DARK_BG),
    ('TOPPADDING', (0,0), (-1,-1), 18),
    ('BOTTOMPADDING', (0,0), (-1,-1), 8),
    ('ROUNDEDCORNERS', [10]),
]))
story.append(header_table)

story.append(Paragraph('A Visual Medical Summary for Students & Clinicians', subtitle_style))
story.append(Paragraph('Source: Morgan & Mikhail\'s Clinical Anesthesiology, 7e | p. 1572–1586', source_style))
story.append(Spacer(1, 5*mm))

# ══════════════════════════════════════════════════════════════════════════════
# QUICK REFERENCE NUMBERS TABLE
# ══════════════════════════════════════════════════════════════════════════════
story.append(section_banner('QUICK REFERENCE: KEY NUMBERS AT A GLANCE', '📊', TABLE_HDR))
story.append(Spacer(1, 2*mm))

qr_data = [
    [Paragraph('System', small_bold), Paragraph('Parameter', small_bold),
     Paragraph('Change', small_bold), Paragraph('System', small_bold),
     Paragraph('Parameter', small_bold), Paragraph('Change', small_bold)],
    # col 1                                        col 2
    ['Neuro', 'MAC', Paragraph('<b><font color="#FF5252">-40%</font></b>', arrow_style),
     'CVS', 'Blood Volume', Paragraph('<b><font color="#69F0AE">+35%</font></b>', arrow_style)],
    ['Resp', 'O₂ Consumption', Paragraph('<b><font color="#69F0AE">+20-50%</font></b>', arrow_style),
     'CVS', 'Plasma Volume', Paragraph('<b><font color="#69F0AE">+55%</font></b>', arrow_style)],
    ['Resp', 'FRC', Paragraph('<b><font color="#FF5252">-20%</font></b>', arrow_style),
     'CVS', 'Cardiac Output', Paragraph('<b><font color="#69F0AE">+40%</font></b>', arrow_style)],
    ['Resp', 'Minute Ventilation', Paragraph('<b><font color="#69F0AE">+50%</font></b>', arrow_style),
     'CVS', 'Heart Rate', Paragraph('<b><font color="#69F0AE">+20%</font></b>', arrow_style)],
    ['Resp', 'Tidal Volume', Paragraph('<b><font color="#69F0AE">+40%</font></b>', arrow_style),
     'CVS', 'Stroke Volume', Paragraph('<b><font color="#69F0AE">+30%</font></b>', arrow_style)],
    ['Resp', 'PaCO₂', Paragraph('<b><font color="#FF5252">-15%</font></b>', arrow_style),
     'CVS', 'DBP', Paragraph('<b><font color="#FF5252">-15%</font></b>', arrow_style)],
    ['Resp', 'Airway Resistance', Paragraph('<b><font color="#FF5252">-35%</font></b>', arrow_style),
     'Haem', 'Hemoglobin', Paragraph('<b><font color="#FF5252">-20%</font></b>', arrow_style)],
    ['Renal', 'GFR', Paragraph('<b><font color="#69F0AE">+50%</font></b>', arrow_style),
     'Haem', 'Clotting Factors', Paragraph('<b><font color="#69F0AE">+30-250%</font></b>', arrow_style)],
]

cell_style = ParagraphStyle('cs', fontName='Helvetica', fontSize=8.5, textColor=LIGHT_TEXT, alignment=TA_LEFT)
qr_table = Table(qr_data, colWidths=[2.2*cm, 4*cm, 2.3*cm, 2.2*cm, 4*cm, 2.3*cm])
qr_style = TableStyle([
    ('BACKGROUND', (0,0), (-1,0), HexColor('#1565C0')),
    ('TEXTCOLOR', (0,0), (-1,0), WHITE),
    ('FONTNAME', (0,0), (-1,0), 'Helvetica-Bold'),
    ('FONTSIZE', (0,0), (-1,0), 8),
    ('ROWBACKGROUNDS', (0,1), (-1,-1), [CARD_BG_1, ROW_ALT]),
    ('GRID', (0,0), (-1,-1), 0.3, HexColor('#2C3E50')),
    ('TOPPADDING', (0,0), (-1,-1), 4),
    ('BOTTOMPADDING', (0,0), (-1,-1), 4),
    ('LEFTPADDING', (0,0), (-1,-1), 5),
    ('RIGHTPADDING', (0,0), (-1,-1), 5),
    ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
    ('FONTNAME', (0,1), (0,-1), 'Helvetica-Bold'),
    ('FONTNAME', (3,1), (3,-1), 'Helvetica-Bold'),
    ('TEXTCOLOR', (0,1), (0,-1), ACCENT_CYAN),
    ('TEXTCOLOR', (3,1), (3,-1), ACCENT_CYAN),
    ('ALIGN', (2,0), (2,-1), 'CENTER'),
    ('ALIGN', (5,0), (5,-1), 'CENTER'),
])
qr_table.setStyle(qr_style)
story.append(qr_table)
story.append(Spacer(1, 5*mm))

# ══════════════════════════════════════════════════════════════════════════════
# 1. NEUROLOGICAL
# ══════════════════════════════════════════════════════════════════════════════
story.append(KeepTogether([
    section_banner('1. NEUROLOGICAL / CNS CHANGES', '🧠', HexColor('#4A148C')),
    Spacer(1, 2*mm),
    make_change_table([
        ('MAC (Min. Alveolar Conc.)', '-40%', 'Reduced anesthetic requirement at term; MAC returns to normal by day 3 post-delivery'),
        ('Sensitivity to local anesthetics', 'Increased', 'Neural blockade at lower concentrations due to progesterone & engorgement of epidural veins'),
        ('Epidural space volume', 'Decreased', 'Engorged epidural veins -> smaller epidural/intrathecal volume -> wider block spread'),
    ], HexColor('#6A1B9A')),
    Spacer(1, 2*mm),
    Paragraph(
        '<b>Mechanism:</b> Progesterone (up to 20x normal at term) increases sedation. '
        'β-endorphin surge during labor contributes. Enhanced sensitivity to local anesthetics '
        'is partly neuronal (progesterone effect) and partly mechanical (engorged epidural veins '
        'reduce volume of epidural/subarachnoid space).',
        body_style
    ),
    Spacer(1, 3*mm),
]))

# ══════════════════════════════════════════════════════════════════════════════
# 2. RESPIRATORY
# ══════════════════════════════════════════════════════════════════════════════
story.append(KeepTogether([
    section_banner('2. RESPIRATORY CHANGES', '🫁', HexColor('#01579B')),
    Spacer(1, 2*mm),
    make_change_table([
        ('Oxygen Consumption', '+20 to 50%', 'Meets increased metabolic demands of fetus, uterus, and maternal tissue'),
        ('Minute Ventilation', '+50%', 'Mainly via ↑ tidal volume (progesterone-driven); PaCO₂ drops to ~32 mmHg'),
        ('Tidal Volume', '+40%', 'Primary driver of hyperventilation; progesterone stimulates respiratory centers'),
        ('Respiratory Rate', '+15%', 'Minor contributor to increased minute ventilation'),
        ('Functional Residual Capacity (FRC)', '-20%', 'Elevated diaphragm from gravid uterus; makes mother prone to rapid desaturation'),
        ('Airway Resistance', '-35%', 'Progesterone-mediated bronchodilation'),
        ('PaO₂', '+10%', 'Rises to ~106 mmHg near sea level; hyperventilation effect'),
        ('PaCO₂', '-15%', 'Drops to ~32 mmHg; compensatory metabolic acidosis (HCO₃⁻ drops to ~20 mEq/L)'),
        ('HCO₃⁻', '-15%', 'Renal compensation for respiratory alkalosis; normal pH ~7.44'),
        ('P50 (Hb-O₂ curve)', '+27→30 mmHg', 'Right shift facilitates O₂ offloading to fetus'),
    ], HexColor('#0277BD')),
    Spacer(1, 2*mm),
    Paragraph(
        '<b>Key clinical points:</b> The ↓ FRC combined with ↑ O₂ consumption means that apnea '
        '(e.g., during intubation) leads to much faster O₂ desaturation than in non-pregnant patients - '
        'pre-oxygenation is critical. Airway edema (progesterone/estrogen) can make intubation difficult; '
        'a smaller ETT (6.0-7.0 mm) is often recommended. The physiological respiratory alkalosis '
        '(PaCO₂ ~32 mmHg) is the normal state; a "normal" PaCO₂ of 40 mmHg in pregnancy suggests '
        'impending respiratory failure.',
        body_style
    ),
    Spacer(1, 3*mm),
]))

# ══════════════════════════════════════════════════════════════════════════════
# 3. CARDIOVASCULAR
# ══════════════════════════════════════════════════════════════════════════════
story.append(KeepTogether([
    section_banner('3. CARDIOVASCULAR CHANGES', '❤️', HexColor('#B71C1C')),
    Spacer(1, 2*mm),
    make_change_table([
        ('Blood Volume', '+35%', 'Starts rising in 1st trimester; peaks at 28-32 weeks; helps offset blood loss at delivery'),
        ('Plasma Volume', '+55%', 'Exceeds RBC expansion -> physiological "dilutional" anemia of pregnancy'),
        ('Cardiac Output', '+40%', 'Rises by 8-10 weeks; peaks near end of 2nd trimester; further increases during labor'),
        ('Stroke Volume', '+30%', 'Due to increased preload and decreased afterload'),
        ('Heart Rate', '+20%', 'Rises by ~15-20 bpm; tachycardia >100 bpm is normal in late pregnancy'),
        ('Systolic BP', '-5%', 'Slight decrease; drops most in 2nd trimester, rises back to baseline at term'),
        ('Diastolic BP', '-15%', 'More pronounced drop; nadirs around 24-28 weeks'),
        ('Peripheral Vascular Resistance', '-15%', 'Progesterone + placental arteriovenous shunt + vasodilation mediators'),
        ('Pulmonary Vascular Resistance', '-30%', 'Reduces RV afterload; important in pulmonary hypertension management'),
    ], HexColor('#C62828')),
    Spacer(1, 2*mm),
    Paragraph(
        '<b>Aortocaval compression:</b> After 18-20 weeks, the gravid uterus can compress the '
        'inferior vena cava and abdominal aorta when supine, reducing venous return by up to 40% '
        '("supine hypotension syndrome"). Left uterine displacement (LUD) is standard of care during '
        'labor and all obstetric procedures. Cardiac output further increases during labor '
        '(+10-25% in first stage, up to +45% in second stage) due to autotransfusion from uterine '
        'contractions, pain, and anxiety.',
        body_style
    ),
    Spacer(1, 3*mm),
]))

# ══════════════════════════════════════════════════════════════════════════════
# 4. HEMATOLOGICAL
# ══════════════════════════════════════════════════════════════════════════════
story.append(KeepTogether([
    section_banner('4. HEMATOLOGICAL CHANGES', '🩸', HexColor('#E65100')),
    Spacer(1, 2*mm),
    make_change_table([
        ('Hemoglobin', '-20%', 'Physiological dilutional anemia; Hgb <11 g/dL in 1st trimester or <10.5 g/dL in 2nd trimester is pathological'),
        ('Hematocrit', 'Decreases', 'Falls from ~40% to ~34%; nadirs at ~30-34 weeks'),
        ('Platelets', '-10%', 'Mild thrombocytopenia is normal; <70,000 warrants investigation'),
        ('WBC', 'Increased', 'Leukocytosis up to 12,000/μL; during labor may reach 20,000-30,000/μL'),
        ('Fibrinogen', 'Doubles', 'Rises from ~300 to 600 mg/dL; ESR increases markedly'),
        ('Clotting Factors (II,VII,VIII,X,XII)', '+30 to 250%', 'Pregnancy is a hypercoagulable state; risk of DVT/PE increases 4-5x'),
        ('Protein C & S', 'Decreased', 'Further tilts balance toward thrombosis; fibrinolytic activity decreased'),
        ('Serum albumin', 'Decreased', 'From ~4.0 to ~3.0 g/dL; affects protein-bound drug pharmacokinetics'),
    ], HexColor('#E64A19')),
    Spacer(1, 2*mm),
    Paragraph(
        '<b>Coagulation implications:</b> The hypercoagulable state protects against hemorrhage at delivery '
        'but increases thromboembolism risk 4-5 fold. Virchow\'s triad is complete in pregnancy: '
        'hypercoagulability (clotting factor excess), venous stasis (uterine compression), and '
        'endothelial injury (delivery). VTE prophylaxis should be considered in high-risk patients.',
        body_style
    ),
    Spacer(1, 3*mm),
]))

# ══════════════════════════════════════════════════════════════════════════════
# 5. RENAL
# ══════════════════════════════════════════════════════════════════════════════
story.append(KeepTogether([
    section_banner('5. RENAL & METABOLIC CHANGES', '🫘', HexColor('#1B5E20')),
    Spacer(1, 2*mm),
    make_change_table([
        ('Glomerular Filtration Rate (GFR)', '+50%', 'Starts rising in 1st trimester; renal plasma flow increases 70%; kidneys enlarge ~1 cm'),
        ('Serum Creatinine', 'Decreased', 'Normal creatinine 0.5-0.8 mg/dL in pregnancy; "normal" 1.0 mg/dL suggests renal impairment'),
        ('Serum BUN', 'Decreased', 'Lower due to increased GFR; normal ~8-9 mg/dL'),
        ('Serum Uric Acid', 'Decreased early', 'Rises in 3rd trimester; elevated uric acid is a marker of preeclampsia'),
        ('Glucosuria', 'May be present', 'Tubular reabsorption of glucose does not increase proportionally with GFR'),
        ('Urinary protein', 'Up to 300 mg/day', 'Normal upper limit doubles; >300 mg/24h suggests preeclampsia'),
        ('Sodium retention', 'Increased', 'Despite elevated GFR; estrogen/aldosterone effect; contributes to edema'),
    ], HexColor('#2E7D32')),
    Spacer(1, 2*mm),
    Paragraph(
        '<b>Drug dosing:</b> Increased renal clearance affects many drugs (penicillins, aminoglycosides, '
        'digoxin) - doses may need to be higher or more frequent. Serum creatinine and BUN are normally '
        'lower; values in the "normal" non-pregnant range may indicate significant renal dysfunction.',
        body_style
    ),
    Spacer(1, 3*mm),
]))

# ══════════════════════════════════════════════════════════════════════════════
# 6. GASTROINTESTINAL
# ══════════════════════════════════════════════════════════════════════════════
story.append(KeepTogether([
    section_banner('6. GASTROINTESTINAL CHANGES', '🤰', HexColor('#4E342E')),
    Spacer(1, 2*mm),
    make_change_table([
        ('Gastric emptying', 'Delayed', 'Progesterone reduces GI motility; risk of aspiration during anesthesia (Mendelson syndrome)'),
        ('Lower esophageal sphincter tone', 'Decreased', 'Progesterone effect; combined with increased intragastric pressure -> GERD in >80%'),
        ('Intragastric pressure', 'Increased', 'Gravid uterus elevates stomach; increases aspiration risk'),
        ('Nausea & vomiting', 'Common', 'Affects 70-80%; hyperemesis gravidarum in <2%; peaks at 8-10 weeks'),
        ('Liver enzymes (ALK-P)', 'Increased', 'Placenta produces alkaline phosphatase; ALT/AST should remain normal'),
        ('Serum albumin', 'Decreased', 'Dilutional; from 4.0 -> 3.0 g/dL; affects drug binding'),
        ('Gallbladder emptying', 'Delayed', 'Bile becomes more lithogenic; cholesterol gallstones 2x more common in pregnancy'),
        ('Constipation', 'Common', 'Reduced colonic motility; water absorption; iron supplementation worsens this'),
    ], HexColor('#5D4037')),
    Spacer(1, 2*mm),
    Paragraph(
        '<b>Aspiration risk:</b> All pregnant patients beyond 12-16 weeks are considered to have a '
        '"full stomach" for anesthesia purposes, regardless of fasting time. Rapid sequence '
        'induction (RSI) with cricoid pressure is the standard for general anesthesia. '
        'Antacid prophylaxis (sodium citrate, H2-blockers, PPI) is recommended.',
        body_style
    ),
    Spacer(1, 3*mm),
]))

# ══════════════════════════════════════════════════════════════════════════════
# 7. ENDOCRINE / HORMONAL
# ══════════════════════════════════════════════════════════════════════════════
story.append(KeepTogether([
    section_banner('7. ENDOCRINE & HORMONAL CHANGES', '⚗️', HexColor('#006064')),
    Spacer(1, 2*mm),
    make_change_table([
        ('Progesterone', 'Up to 20x normal', 'Sedation, bronchodilation, reduced GI motility, decreased LES tone, vasodilation'),
        ('Estrogen', 'Greatly increased', 'Airway mucosal edema, clotting factor synthesis, increased binding proteins'),
        ('hCG (human chorionic gonadotropin)', 'Peaks at 8-10 wks', 'Maintains corpus luteum; basis of pregnancy tests; elevated in molar pregnancy'),
        ('hPL (human placental lactogen)', 'Increases throughout', 'Insulin antagonist; promotes lipolysis; causes gestational insulin resistance'),
        ('Insulin resistance', 'Increases', 'Peaks in 3rd trimester; gestational diabetes in ~7-10% of pregnancies'),
        ('Thyroid hormones (total T3/T4)', 'Increased', 'TBG doubles; free T3/T4 remain normal; TSH may transiently decrease in 1st trimester'),
        ('Cortisol', 'Increased', '3x normal at term; partly explains glucose intolerance and striae gravidarum'),
        ('Aldosterone', 'Increased 10x', 'Compensates for progesterone-induced Na loss; contributes to fluid retention'),
    ], HexColor('#00838F')),
    Spacer(1, 3*mm),
]))

# ══════════════════════════════════════════════════════════════════════════════
# 8. MUSCULOSKELETAL / OTHER
# ══════════════════════════════════════════════════════════════════════════════
story.append(KeepTogether([
    section_banner('8. MUSCULOSKELETAL & OTHER CHANGES', '🦴', HexColor('#37474F')),
    Spacer(1, 2*mm),
    make_change_table([
        ('Lumbar lordosis', 'Increases', 'Compensates for anterior shift in center of gravity; causes back pain in ~50%'),
        ('Relaxin hormone', 'Increased', 'Relaxes pelvic ligaments (pubic symphysis, sacroiliac joints) for delivery'),
        ('Uterus weight', '60g -> 1000g', 'Increases 20-fold; blood flow rises from 50 ml/min to 500-700 ml/min at term'),
        ('Skin changes', 'Striae, linea nigra', 'Hyperpigmentation (MSH from placenta), spider angiomata, palmar erythema'),
        ('Eye changes', 'Corneal thickening', 'Avoid new contact lens prescriptions; IOP decreases; visual changes common'),
        ('Body weight', '+11-16 kg average', 'Fetus ~3.3 kg; placenta ~0.6 kg; amniotic fluid ~0.8 kg; rest is maternal tissue'),
        ('Total body water', '+6-8 L', 'Distributed: plasma, interstitial, amniotic fluid; dependent edema in 80% is normal'),
    ], HexColor('#455A64')),
    Spacer(1, 3*mm),
]))

# ══════════════════════════════════════════════════════════════════════════════
# CLINICAL PEARLS BOX
# ══════════════════════════════════════════════════════════════════════════════
pearls_data = [[
    Paragraph(
        '<b><font color="#FFD600">🏆 HIGH-YIELD CLINICAL PEARLS</font></b><br/><br/>'
        '<font color="#69F0AE"><b>1.</b></font> <font color="#ECEFF1">Rapid desaturation during apnea</font> '
        '- ↓FRC + ↑O₂ consumption = short safe apnea time. Pre-oxygenate 3-5 min before induction.<br/>'
        '<font color="#69F0AE"><b>2.</b></font> <font color="#ECEFF1">Supine hypotension</font> '
        '- IVC compression after 18-20 wks. Always use LEFT LATERAL TILT 15°.<br/>'
        '<font color="#69F0AE"><b>3.</b></font> <font color="#ECEFF1">Full stomach risk</font> '
        '- Use RSI for all GA in pregnancy >12-16 wks regardless of fasting status.<br/>'
        '<font color="#69F0AE"><b>4.</b></font> <font color="#ECEFF1">Dilutional anemia</font> '
        '- Hgb 10-11 g/dL is normal in pregnancy (not pathological if other causes excluded).<br/>'
        '<font color="#69F0AE"><b>5.</b></font> <font color="#ECEFF1">PaCO₂ "normal" = danger</font> '
        '- Normal non-pregnant PaCO₂ (40 mmHg) in pregnancy = respiratory FAILURE (normal = 32 mmHg).<br/>'
        '<font color="#69F0AE"><b>6.</b></font> <font color="#ECEFF1">Creatinine "normal" = impaired</font> '
        '- Normal creatinine in pregnancy = 0.5-0.8 mg/dL. Value of 1.0 mg/dL warrants investigation.<br/>'
        '<font color="#69F0AE"><b>7.</b></font> <font color="#ECEFF1">Hypercoagulability</font> '
        '- VTE risk 4-5x higher. Immobility + surgery = thromboprophylaxis is essential.<br/>'
        '<font color="#69F0AE"><b>8.</b></font> <font color="#ECEFF1">Reduced MAC</font> '
        '- Need 40% less volatile anesthetic; also more sensitive to IV sedatives and opioids.',
        ParagraphStyle('pearls', fontName='Helvetica', fontSize=8.5, textColor=LIGHT_TEXT,
                       leading=14, alignment=TA_LEFT)
    )
]]
pearls_table = Table(pearls_data, colWidths=[17*cm])
pearls_table.setStyle(TableStyle([
    ('BACKGROUND', (0,0), (-1,-1), HexColor('#0A1628')),
    ('BOX', (0,0), (-1,-1), 1.5, ACCENT_GOLD),
    ('TOPPADDING', (0,0), (-1,-1), 12),
    ('BOTTOMPADDING', (0,0), (-1,-1), 12),
    ('LEFTPADDING', (0,0), (-1,-1), 14),
    ('RIGHTPADDING', (0,0), (-1,-1), 14),
    ('ROUNDEDCORNERS', [8]),
]))
story.append(pearls_table)
story.append(Spacer(1, 5*mm))

# ══════════════════════════════════════════════════════════════════════════════
# TRIMESTER TIMELINE
# ══════════════════════════════════════════════════════════════════════════════
story.append(section_banner('TIMELINE: WHEN CHANGES OCCUR', '📅', HexColor('#1A237E')))
story.append(Spacer(1, 2*mm))

timeline_data = [
    [
        Paragraph('<b>1st Trimester (0-12 wks)</b>', ParagraphStyle('t1h', fontName='Helvetica-Bold', fontSize=9, textColor=ACCENT_GOLD, alignment=TA_CENTER)),
        Paragraph('<b>2nd Trimester (13-26 wks)</b>', ParagraphStyle('t2h', fontName='Helvetica-Bold', fontSize=9, textColor=ACCENT_GREEN, alignment=TA_CENTER)),
        Paragraph('<b>3rd Trimester (27-40 wks)</b>', ParagraphStyle('t3h', fontName='Helvetica-Bold', fontSize=9, textColor=ACCENT_PINK, alignment=TA_CENTER)),
    ],
    [
        Paragraph(
            '• ↑hCG peaks 8-10 wks\n• Nausea/vomiting peak\n• ↑Progesterone & estrogen\n'
            '• Plasma volume starts ↑\n• ↑Heart rate begins\n• GFR starts increasing\n'
            '• Progesterone -> ↑ventilation',
            ParagraphStyle('t1b', fontName='Helvetica', fontSize=8, textColor=LIGHT_TEXT, leading=12)
        ),
        Paragraph(
            '• BP nadir at 24-28 wks\n• Plasma volume peaks (+55%)\n• CO peaks (late 2nd trimester)\n'
            '• FRC decreases (diaphragm rises)\n• IVC compression risk begins\n'
            '• Gestational DM screening (24-28 wks)\n• Fetal movements felt',
            ParagraphStyle('t2b', fontName='Helvetica', fontSize=8, textColor=LIGHT_TEXT, leading=12)
        ),
        Paragraph(
            '• MAC -40% at term\n• Uterus 1000g; blood flow 700ml/min\n• Insulin resistance peaks\n'
            '• Clotting factors max elevation\n• BP returns near baseline\n'
            '• Lumbar lordosis maximal\n• RBC mass peaks',
            ParagraphStyle('t3b', fontName='Helvetica', fontSize=8, textColor=LIGHT_TEXT, leading=12)
        ),
    ]
]
timeline_table = Table(timeline_data, colWidths=[5.6*cm, 5.6*cm, 5.6*cm])
timeline_table.setStyle(TableStyle([
    ('BACKGROUND', (0,0), (0,0), HexColor('#3E2700')),
    ('BACKGROUND', (1,0), (1,0), HexColor('#004D00')),
    ('BACKGROUND', (2,0), (2,0), HexColor('#4A0020')),
    ('BACKGROUND', (0,1), (0,1), CARD_BG_1),
    ('BACKGROUND', (1,1), (1,1), CARD_BG_2),
    ('BACKGROUND', (2,1), (2,1), CARD_BG_1),
    ('GRID', (0,0), (-1,-1), 0.5, HexColor('#2C3E50')),
    ('TOPPADDING', (0,0), (-1,-1), 8),
    ('BOTTOMPADDING', (0,0), (-1,-1), 8),
    ('LEFTPADDING', (0,0), (-1,-1), 8),
    ('VALIGN', (0,0), (-1,-1), 'TOP'),
]))
story.append(timeline_table)
story.append(Spacer(1, 5*mm))

# ══════════════════════════════════════════════════════════════════════════════
# FOOTER
# ══════════════════════════════════════════════════════════════════════════════
story.append(HRFlowable(width='100%', thickness=0.5, color=HexColor('#37474F')))
story.append(Spacer(1, 2*mm))
story.append(Paragraph(
    'Source: Morgan & Mikhail\'s Clinical Anesthesiology, 7e, Chapter 40 (pp. 1572-1587) | '
    'Compiled for educational purposes | Orris Medical Summary',
    footnote_style
))

# ══════════════════════════════════════════════════════════════════════════════
# BUILD
# ══════════════════════════════════════════════════════════════════════════════

def add_background(canvas, doc):
    canvas.saveState()
    canvas.setFillColor(DARK_BG)
    canvas.rect(0, 0, A4[0], A4[1], fill=1, stroke=0)
    canvas.restoreState()

doc.build(story, onFirstPage=add_background, onLaterPages=add_background)
print(f"PDF created: {OUTPUT}")
Running Command

cd /home/daytona/workspace/pregnancy-physiology && python make_pdf.py 2>&1

The PDF was created successfully. Here is your complete visual summary:

Physiological Changes During Pregnancy

Source: Morgan & Mikhail's Clinical Anesthesiology, 7e (Chapter 40)

Download Your Visual Summary PDF:

Physiological Changes During Pregnancy

PDF Document · PDF


The PDF is dark-themed with color-coded sections for easy visual memory. Here is a text overview of what it contains:

Quick Reference Numbers

SystemParameterChange
NeuroMAC-40%
RespO₂ Consumption+20-50%
RespFRC-20%
RespMinute Ventilation+50%
CVSPlasma Volume+55%
CVSCardiac Output+40%
CVSHeart Rate+20%
RenalGFR+50%
HaemClotting Factors+30-250%

1. Neurological

  • MAC falls 40% at term - far less anesthetic needed
  • Enhanced sensitivity to local anesthetics (epidural veins engorged, volume of epidural space reduced)
  • Progesterone (up to 20x normal) is responsible; returns to normal by day 3 postpartum

2. Respiratory

  • Minute ventilation +50% (progesterone stimulates respiratory centers)
  • FRC -20% (diaphragm pushed up) + O₂ consumption +50% = rapid desaturation during apnea
  • PaCO₂ drops to ~32 mmHg (compensated by HCO₃⁻ dropping to ~20 mEq/L) - pH ~7.44
  • A "normal" PaCO₂ of 40 mmHg in pregnancy signals impending respiratory failure

3. Cardiovascular

  • Cardiac output rises by 8-10 weeks, peaks late 2nd trimester (+40%)
  • BP nadir at 24-28 weeks; rises back to near baseline at term
  • Aortocaval compression after 18-20 weeks in supine position reduces venous return up to 40% - always use left uterine displacement
  • During labor, CO rises another 10-45% via uterine autotransfusion

4. Hematological

  • Plasma volume +55% >> RBC expansion = physiological dilutional anemia (Hgb ~10-11 g/dL is normal)
  • Hypercoagulable state: clotting factors up +30-250%, protein C/S decrease = VTE risk 4-5x higher
  • Virchow's triad is complete in pregnancy

5. Renal

  • GFR +50% from 1st trimester; kidneys enlarge ~1 cm
  • "Normal" creatinine of 1.0 mg/dL in pregnancy = impaired kidneys (normal = 0.5-0.8 mg/dL)
  • Glucosuria can be physiological (tubular reabsorption doesn't scale with GFR)

6. Gastrointestinal

  • Delayed gastric emptying + reduced LES tone + elevated intragastric pressure = aspiration risk
  • All patients >12-16 weeks are "full stomach" for anesthesia purposes - RSI is mandatory
  • Gallstones 2x more common (progesterone slows gallbladder emptying)

7. Endocrine/Hormonal

  • Progesterone (up to 20x): bronchodilation, reduced GI motility, vasodilation, sedation
  • hPL acts as insulin antagonist - gestational DM in ~7-10%
  • Cortisol 3x normal; aldosterone 10x normal (fluid retention)

8. Musculoskeletal

  • Uterine blood flow 50 ml/min → 700 ml/min at term
  • Relaxin loosens pelvic ligaments
  • Total body water increases 6-8 L; weight gain 11-16 kg average

Top 8 High-Yield Clinical Pearls

  1. Pre-oxygenate before any GA induction - safe apnea time is very short
  2. Left lateral tilt 15° - always, to prevent IVC compression
  3. RSI mandatory for all GA in pregnancy >12-16 weeks
  4. Hgb 10-11 is normal - do not over-transfuse
  5. PaCO₂ 40 = failure in pregnancy (normal is 32 mmHg)
  6. Creatinine 1.0 = investigate in pregnancy (normal is 0.5-0.8)
  7. VTE prophylaxis in all high-risk obstetric patients
  8. -40% MAC - reduce volatile anesthetic dose accordingly

Can you make this pdf with more diagrams and flowchart for better visual memory

Writing File

~/pregnancy-physiology/make_pdf_v2.py

#!/usr/bin/env python3
"""
Physiological Changes During Pregnancy - ENHANCED Visual PDF v2
With bar charts, flowcharts, body diagrams, and system maps
"""

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether, PageBreak
)
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.lib.colors import HexColor
from reportlab.graphics.shapes import (
    Drawing, Rect, String, Line, Circle, Polygon, Ellipse,
    Arrow, Group, Path
)
from reportlab.graphics import renderPDF
from reportlab.graphics.charts.barcharts import VerticalBarChart, HorizontalBarChart
from reportlab.graphics.charts.piecharts import Pie
from reportlab.platypus import Flowable
import math

# ── Palette ────────────────────────────────────────────────────────────────
DARK_BG      = HexColor('#0A0F1E')
NAVY         = HexColor('#0D1B2A')
CARD_DARK    = HexColor('#0F1F35')
CARD_MID     = HexColor('#112233')
ROW_ALT      = HexColor('#1A3555')
HEADER_BG    = HexColor('#1B4F72')
TABLE_HDR    = HexColor('#1565C0')
PINK         = HexColor('#E91E8C')
CYAN         = HexColor('#00BCD4')
GOLD         = HexColor('#FFD600')
GREEN        = HexColor('#4CAF50')
ORANGE       = HexColor('#FF6F00')
RED          = HexColor('#EF5350')
PURPLE       = HexColor('#7B1FA2')
TEAL         = HexColor('#00897B')
BLUE         = HexColor('#1E88E5')
LIME         = HexColor('#C6FF00')
WHITE        = colors.white
LIGHT_TEXT   = HexColor('#ECEFF1')
DIM_TEXT     = HexColor('#90A4AE')

W, H = A4   # 595.27 x 841.89 pts

# ── Reusable styles ────────────────────────────────────────────────────────
def S(name, **kw):
    return ParagraphStyle(name, **kw)

title_s   = S('T', fontName='Helvetica-Bold', fontSize=28, textColor=WHITE,
               alignment=TA_CENTER, leading=34, spaceAfter=4)
sub_s     = S('S', fontName='Helvetica', fontSize=11, textColor=CYAN,
               alignment=TA_CENTER, spaceAfter=2)
src_s     = S('SR', fontName='Helvetica-Oblique', fontSize=8.5, textColor=DIM_TEXT,
               alignment=TA_CENTER, spaceAfter=6)
sec_s     = S('SEC', fontName='Helvetica-Bold', fontSize=13, textColor=WHITE,
               alignment=TA_CENTER, leading=16)
body_s    = S('B', fontName='Helvetica', fontSize=8.5, textColor=LIGHT_TEXT,
               alignment=TA_JUSTIFY, leading=13, spaceAfter=3)
bullet_s  = S('BU', fontName='Helvetica', fontSize=8.5, textColor=LIGHT_TEXT,
               alignment=TA_LEFT, leading=12, leftIndent=10, spaceAfter=2)
small_b   = S('SB', fontName='Helvetica-Bold', fontSize=8, textColor=GOLD,
               alignment=TA_CENTER)
note_s    = S('N', fontName='Helvetica-Oblique', fontSize=7.5, textColor=DIM_TEXT,
               alignment=TA_CENTER)
lbl_s     = S('L', fontName='Helvetica-Bold', fontSize=8, textColor=WHITE,
               alignment=TA_CENTER, leading=10)
lbl_sm    = S('LS', fontName='Helvetica', fontSize=7, textColor=LIGHT_TEXT,
               alignment=TA_CENTER, leading=9)

CONTENT_W = 17 * cm

# ═══════════════════════════════════════════════════════════════════════════
# DRAWING HELPERS
# ═══════════════════════════════════════════════════════════════════════════

class DrawingFlowable(Flowable):
    def __init__(self, drawing):
        Flowable.__init__(self)
        self.drawing = drawing
        self.width = drawing.width
        self.height = drawing.height

    def draw(self):
        renderPDF.draw(self.drawing, self.canv, 0, 0)


def hex2rgb(h):
    h = h.hexval()[1:]
    return tuple(int(h[i:i+2], 16)/255 for i in (0,2,4))


def rounded_rect(d, x, y, w, h, r, fill_color, stroke_color=None, stroke_width=0.5):
    p = Path()
    p.moveTo(x+r, y)
    p.lineTo(x+w-r, y)
    p.curveTo(x+w-r, y, x+w, y, x+w, y+r)
    p.lineTo(x+w, y+h-r)
    p.curveTo(x+w, y+h-r, x+w, y+h, x+w-r, y+h)
    p.lineTo(x+r, y+h)
    p.curveTo(x+r, y+h, x, y+h, x, y+h-r)
    p.lineTo(x, y+r)
    p.curveTo(x, y+r, x, y, x+r, y)
    p.closePath()
    p.fillColor = fill_color
    p.strokeColor = stroke_color
    p.strokeWidth = stroke_width
    d.add(p)


def arrow_line(d, x1, y1, x2, y2, color=GOLD, width=1.5):
    """Draw a line with an arrowhead at (x2,y2)."""
    d.add(Line(x1, y1, x2, y2, strokeColor=color, strokeWidth=width))
    # arrowhead
    angle = math.atan2(y2-y1, x2-x1)
    size = 6
    ax1 = x2 - size*math.cos(angle-0.4)
    ay1 = y2 - size*math.sin(angle-0.4)
    ax2 = x2 - size*math.cos(angle+0.4)
    ay2 = y2 - size*math.sin(angle+0.4)
    d.add(Polygon([x2, y2, ax1, ay1, ax2, ay2],
                  fillColor=color, strokeColor=color, strokeWidth=0.3))


def text_box(d, x, y, w, h, text, bg, fg=WHITE, font='Helvetica-Bold', size=9, r=5):
    rounded_rect(d, x, y, w, h, r, bg, HexColor('#2C3E50'), 0.5)
    d.add(String(x+w/2, y+h/2-size*0.38, text,
                 textAnchor='middle', fontSize=size,
                 fontName=font, fillColor=fg))


# ═══════════════════════════════════════════════════════════════════════════
# CHART 1: Horizontal bar chart of % changes
# ═══════════════════════════════════════════════════════════════════════════
def make_bar_chart():
    DW, DH = CONTENT_W, 7.2*cm
    d = Drawing(DW, DH)

    # Background
    rounded_rect(d, 0, 0, DW, DH, 8, CARD_DARK, HexColor('#1A3555'), 0.8)

    # Title
    d.add(String(DW/2, DH-14, 'KEY PARAMETER CHANGES IN PREGNANCY  (% change from baseline)',
                 textAnchor='middle', fontSize=9, fontName='Helvetica-Bold', fillColor=GOLD))

    params = [
        ('Plasma Volume',       +55, CYAN),
        ('Min. Ventilation',    +50, BLUE),
        ('GFR',                 +50, GREEN),
        ('Cardiac Output',      +40, PINK),
        ('Tidal Volume',        +40, PINK),
        ('O₂ Consumption',      +35, ORANGE),
        ('Blood Volume',        +35, ORANGE),
        ('Heart Rate',          +20, HexColor('#FF9800')),
        ('Clotting Factors',    +30, RED),
        ('Stroke Volume',       +30, LIME),
        ('FRC',                 -20, HexColor('#FF5252')),
        ('Hemoglobin',          -20, HexColor('#FF5252')),
        ('MAC',                 -40, PURPLE),
        ('PaCO₂',               -15, HexColor('#FF7043')),
        ('Pulm Resistance',     -30, HexColor('#CE93D8')),
    ]

    bar_area_x = 130
    bar_area_w = DW - bar_area_x - 60
    zero_x = bar_area_x + bar_area_w * 0.45
    row_h = 14
    start_y = DH - 32

    max_val = 60

    for i, (name, val, clr) in enumerate(params):
        y = start_y - i * row_h
        if y < 8:
            break

        # label
        d.add(String(bar_area_x - 4, y-3, name,
                     textAnchor='end', fontSize=7, fontName='Helvetica',
                     fillColor=LIGHT_TEXT))

        # bar
        bar_len = abs(val) / max_val * bar_area_w * 0.45
        if val > 0:
            bx = zero_x
        else:
            bx = zero_x - bar_len

        r2 = Rect(bx, y-2, bar_len if val > 0 else bar_len,
                  row_h - 4, fillColor=clr, strokeColor=None)
        r2.rx = 2
        d.add(r2)

        # value text
        tx = zero_x + bar_len + 3 if val > 0 else zero_x - bar_len - 3
        anchor = 'start' if val > 0 else 'end'
        sign = '+' if val > 0 else ''
        d.add(String(tx, y-3, f'{sign}{val}%',
                     textAnchor=anchor, fontSize=7, fontName='Helvetica-Bold',
                     fillColor=clr))

    # zero line
    d.add(Line(zero_x, 12, zero_x, DH-22,
               strokeColor=HexColor('#546E7A'), strokeWidth=1, strokeDashArray=[3,2]))
    d.add(String(zero_x, 6, '0%', textAnchor='middle', fontSize=7,
                 fontName='Helvetica', fillColor=DIM_TEXT))

    # Legend
    d.add(String(bar_area_x+bar_area_w*0.1, 6, '← DECREASE',
                 textAnchor='middle', fontSize=7, fontName='Helvetica-Bold',
                 fillColor=HexColor('#FF5252')))
    d.add(String(bar_area_x+bar_area_w*0.8, 6, 'INCREASE →',
                 textAnchor='middle', fontSize=7, fontName='Helvetica-Bold',
                 fillColor=HexColor('#69F0AE')))

    return DrawingFlowable(d)


# ═══════════════════════════════════════════════════════════════════════════
# CHART 2: Body system diagram
# ═══════════════════════════════════════════════════════════════════════════
def make_body_diagram():
    DW, DH = CONTENT_W, 9.5*cm
    d = Drawing(DW, DH)

    rounded_rect(d, 0, 0, DW, DH, 8, CARD_DARK, HexColor('#1A3555'), 0.8)
    d.add(String(DW/2, DH-14, 'BODY SYSTEMS AFFECTED IN PREGNANCY',
                 textAnchor='middle', fontSize=10, fontName='Helvetica-Bold', fillColor=GOLD))

    # Draw simplified body silhouette
    cx = DW/2
    # Head
    d.add(Ellipse(cx, DH-50, 22, 22, fillColor=HexColor('#1C3A5E'), strokeColor=CYAN, strokeWidth=1.2))
    d.add(String(cx, DH-54, 'CNS', textAnchor='middle', fontSize=7, fontName='Helvetica-Bold', fillColor=CYAN))

    # Neck
    d.add(Rect(cx-8, DH-80, 16, 14, fillColor=HexColor('#1C3A5E'), strokeColor=None))

    # Torso
    rounded_rect(d, cx-40, DH-185, 80, 100, 10, HexColor('#0F2840'), CYAN, 1.2)

    # Heart (left chest)
    d.add(Ellipse(cx-15, DH-125, 16, 16,
                  fillColor=HexColor('#7B0000'), strokeColor=RED, strokeWidth=1.5))
    d.add(String(cx-15, DH-129, '❤', textAnchor='middle', fontSize=10, fillColor=RED))

    # Lungs (both sides)
    d.add(Ellipse(cx-28, DH-130, 14, 22,
                  fillColor=HexColor('#01435A'), strokeColor=BLUE, strokeWidth=1.2))
    d.add(Ellipse(cx+10, DH-130, 14, 22,
                  fillColor=HexColor('#01435A'), strokeColor=BLUE, strokeWidth=1.2))

    # Uterus (lower torso)
    d.add(Ellipse(cx, DH-170, 28, 24,
                  fillColor=HexColor('#880E4F'), strokeColor=PINK, strokeWidth=1.5))
    d.add(String(cx, DH-174, 'Uterus', textAnchor='middle', fontSize=7,
                 fontName='Helvetica-Bold', fillColor=PINK))

    # Kidneys
    d.add(Ellipse(cx-38, DH-148, 10, 16,
                  fillColor=HexColor('#1B5E20'), strokeColor=GREEN, strokeWidth=1.2))
    d.add(Ellipse(cx+38, DH-148, 10, 16,
                  fillColor=HexColor('#1B5E20'), strokeColor=GREEN, strokeWidth=1.2))

    # Arms
    rounded_rect(d, cx-72, DH-185, 28, 80, 8, HexColor('#0D2035'), CYAN, 0.8)
    rounded_rect(d, cx+44, DH-185, 28, 80, 8, HexColor('#0D2035'), CYAN, 0.8)

    # Legs
    rounded_rect(d, cx-35, DH-270, 28, 80, 8, HexColor('#0D2035'), CYAN, 0.8)
    rounded_rect(d, cx+7, DH-270, 28, 80, 8, HexColor('#0D2035'), CYAN, 0.8)

    # ── CALLOUT BOXES ──────────────────────────────────────────────────────
    # Left side callouts
    box_w, box_h = 105, 38
    lx = 4

    # CNS box
    rounded_rect(d, lx, DH-70, box_w, box_h, 5, HexColor('#1A0A3E'), PURPLE, 0.8)
    d.add(String(lx+box_w/2, DH-56, '🧠 CNS / NEURO',
                 textAnchor='middle', fontSize=8, fontName='Helvetica-Bold', fillColor=PURPLE))
    d.add(String(lx+box_w/2, DH-68, 'MAC ↓40%  |  Local anesthetic sensitivity ↑',
                 textAnchor='middle', fontSize=6.5, fontName='Helvetica', fillColor=LIGHT_TEXT))
    arrow_line(d, lx+box_w, DH-50, cx-22, DH-46, PURPLE)

    # Cardiovascular
    rounded_rect(d, lx, DH-125, box_w, 46, 5, HexColor('#1A0808'), RED, 0.8)
    d.add(String(lx+box_w/2, DH-108, '❤️ CARDIOVASCULAR',
                 textAnchor='middle', fontSize=8, fontName='Helvetica-Bold', fillColor=RED))
    for ii, txt in enumerate(['CO ↑40%  HR ↑20%  SV ↑30%',
                               'Blood vol ↑35%  Plasma ↑55%',
                               'SVR ↓15%  DBP ↓15%']):
        d.add(String(lx+box_w/2, DH-118-ii*9, txt,
                     textAnchor='middle', fontSize=6, fontName='Helvetica', fillColor=LIGHT_TEXT))
    arrow_line(d, lx+box_w, DH-102, cx-32, DH-118, RED)

    # Respiratory
    rounded_rect(d, lx, DH-180, box_w, 46, 5, HexColor('#001A2E'), BLUE, 0.8)
    d.add(String(lx+box_w/2, DH-163, '🫁 RESPIRATORY',
                 textAnchor='middle', fontSize=8, fontName='Helvetica-Bold', fillColor=BLUE))
    for ii, txt in enumerate(['MV ↑50%  TV ↑40%  FRC ↓20%',
                               'PaCO₂ ↓15%  PaO₂ ↑10%',
                               'Airway resistance ↓35%']):
        d.add(String(lx+box_w/2, DH-172-ii*9, txt,
                     textAnchor='middle', fontSize=6, fontName='Helvetica', fillColor=LIGHT_TEXT))
    arrow_line(d, lx+box_w, DH-158, cx-42, DH-128, BLUE)

    # Right side callouts
    rx = cx + 48

    # Renal
    rounded_rect(d, rx, DH-125, box_w, 38, 5, HexColor('#0A2E0A'), GREEN, 0.8)
    d.add(String(rx+box_w/2, DH-109, '🫘 RENAL',
                 textAnchor='middle', fontSize=8, fontName='Helvetica-Bold', fillColor=GREEN))
    for ii, txt in enumerate(['GFR ↑50%  RPF ↑70%',
                               'Creat ↓  BUN ↓  Uric acid ↓',
                               'Normal Cr = 0.5-0.8 mg/dL']):
        d.add(String(rx+box_w/2, DH-118-ii*9, txt,
                     textAnchor='middle', fontSize=6, fontName='Helvetica', fillColor=LIGHT_TEXT))
    arrow_line(d, rx, DH-106, cx+48, DH-135, GREEN)

    # Uterus/Hormonal
    rounded_rect(d, rx, DH-185, box_w, 52, 5, HexColor('#2E0A2E'), PINK, 0.8)
    d.add(String(rx+box_w/2, DH-166, '🤰 UTERUS / HORMONAL',
                 textAnchor='middle', fontSize=8, fontName='Helvetica-Bold', fillColor=PINK))
    for ii, txt in enumerate(['Progesterone ↑20x',
                               'Blood flow 50→700 ml/min',
                               'hCG peaks 8-10 wks',
                               'Relaxin: ligament laxity']):
        d.add(String(rx+box_w/2, DH-175-ii*9, txt,
                     textAnchor='middle', fontSize=6, fontName='Helvetica', fillColor=LIGHT_TEXT))
    arrow_line(d, rx, DH-162, cx+28, DH-162, PINK)

    # Hematology (bottom left)
    rounded_rect(d, lx, DH-235, box_w, 46, 5, HexColor('#1A0F00'), ORANGE, 0.8)
    d.add(String(lx+box_w/2, DH-218, '🩸 HEMATOLOGY',
                 textAnchor='middle', fontSize=8, fontName='Helvetica-Bold', fillColor=ORANGE))
    for ii, txt in enumerate(['Hgb ↓20%  Plt ↓10%  WBC ↑',
                               'Fibrinogen doubles',
                               'Clotting factors ↑30-250%']):
        d.add(String(lx+box_w/2, DH-228-ii*9, txt,
                     textAnchor='middle', fontSize=6, fontName='Helvetica', fillColor=LIGHT_TEXT))
    arrow_line(d, lx+box_w, DH-212, cx-30, DH-230, ORANGE)

    # GI (bottom right)
    rounded_rect(d, rx, DH-250, box_w, 55, 5, HexColor('#1A0A00'), HexColor('#FF8F00'), 0.8)
    d.add(String(rx+box_w/2, DH-230, '🍽️ GASTROINTESTINAL',
                 textAnchor='middle', fontSize=8, fontName='Helvetica-Bold', fillColor=HexColor('#FF8F00')))
    for ii, txt in enumerate(['Gastric emptying delayed',
                               'LES tone ↓ → GERD ↑',
                               'Aspiration risk ↑↑',
                               'Gallstones 2x more common']):
        d.add(String(rx+box_w/2, DH-240-ii*9, txt,
                     textAnchor='middle', fontSize=6, fontName='Helvetica', fillColor=LIGHT_TEXT))
    arrow_line(d, rx, DH-222, cx+20, DH-200, HexColor('#FF8F00'))

    return DrawingFlowable(d)


# ═══════════════════════════════════════════════════════════════════════════
# FLOWCHART: Aspiration risk chain
# ═══════════════════════════════════════════════════════════════════════════
def make_aspiration_flowchart():
    DW, DH = CONTENT_W, 4.8*cm
    d = Drawing(DW, DH)
    rounded_rect(d, 0, 0, DW, DH, 8, CARD_DARK, HexColor('#1A3555'), 0.8)
    d.add(String(DW/2, DH-13, '⚠️  ASPIRATION RISK FLOWCHART IN PREGNANCY',
                 textAnchor='middle', fontSize=9, fontName='Helvetica-Bold', fillColor=RED))

    boxes = [
        ('Progesterone ↑', HexColor('#4A148C'), 22),
        ('LES tone ↓\nGastric motility ↓', HexColor('#1A237E'), 22),
        ('Delayed emptying\n+ Gravid uterus', HexColor('#1B5E20'), 22),
        ('↑ Intragastric\npressure', HexColor('#BF360C'), 22),
        ('FULL STOMACH\nRISK ↑↑', RED, 22),
        ('RSI + Cricoid\npressure MANDATORY', HexColor('#006064'), 22),
    ]

    bw = 73
    bh = 38
    gap = 10
    total = len(boxes)*bw + (len(boxes)-1)*gap
    start_x = (DW - total) / 2
    y_center = DH/2 - 10

    for i, (label, bg, _) in enumerate(boxes):
        bx = start_x + i*(bw+gap)
        rounded_rect(d, bx, y_center-bh/2, bw, bh, 6, bg, HexColor('#37474F'), 0.8)
        lines = label.split('\n')
        for j, ln in enumerate(lines):
            d.add(String(bx+bw/2, y_center + (len(lines)-1)*5 - j*10,
                         ln, textAnchor='middle', fontSize=7,
                         fontName='Helvetica-Bold', fillColor=WHITE))
        if i < len(boxes)-1:
            arrow_line(d, bx+bw, y_center, bx+bw+gap, y_center, GOLD, 1.5)

    # Bottom note
    d.add(String(DW/2, 6, 'All pregnant patients >12-16 weeks treated as "full stomach" regardless of fasting time',
                 textAnchor='middle', fontSize=7, fontName='Helvetica-Oblique', fillColor=DIM_TEXT))

    return DrawingFlowable(d)


# ═══════════════════════════════════════════════════════════════════════════
# FLOWCHART: Cardiovascular cascade
# ═══════════════════════════════════════════════════════════════════════════
def make_cvs_flowchart():
    DW, DH = CONTENT_W, 6.5*cm
    d = Drawing(DW, DH)
    rounded_rect(d, 0, 0, DW, DH, 8, CARD_DARK, HexColor('#1A3555'), 0.8)
    d.add(String(DW/2, DH-13, '❤️  CARDIOVASCULAR CHANGES - CAUSE & EFFECT',
                 textAnchor='middle', fontSize=9, fontName='Helvetica-Bold', fillColor=RED))

    # Column 1: Causes
    causes = [
        ('Estrogen\n+ Relaxin', HexColor('#4A0E82'), 50),
        ('Progesterone', HexColor('#1A237E'), 50),
        ('Placental\nA-V shunt', HexColor('#004D40'), 50),
    ]
    # Column 2: Mechanisms
    mechs = [
        ('SVR ↓ 15%', HexColor('#1B5E20'), 50),
        ('Plasma vol\n↑ 55%', HexColor('#0D47A1'), 50),
        ('O₂ demand ↑', HexColor('#E65100'), 50),
    ]
    # Column 3: Effect
    effects = [
        ('HR ↑ 20%', HexColor('#B71C1C'), 50),
        ('SV ↑ 30%', HexColor('#880E4F'), 50),
    ]
    # Column 4: Outcome
    outcomes = [
        ('CARDIAC OUTPUT\n↑ 40%', RED, 80),
    ]

    col_x = [10, 140, 290, 400]
    bw_c = [110, 110, 90, 130]
    bh = 30
    gap_v = 8

    def draw_col(items, col_idx, start_y):
        n = len(items)
        total_h = n*bh + (n-1)*gap_v
        y0 = start_y + (DH-50 - total_h) / 2
        cx_arr = col_x[col_idx] + bw_c[col_idx]/2
        for i, (lbl, bg, _) in enumerate(items):
            by = y0 + i*(bh+gap_v)
            rounded_rect(d, col_x[col_idx], by, bw_c[col_idx], bh, 5, bg, HexColor('#37474F'), 0.6)
            lines = lbl.split('\n')
            for j, ln in enumerate(lines):
                d.add(String(cx_arr, by+bh/2+(len(lines)-1)*4-j*9,
                             ln, textAnchor='middle', fontSize=7.5,
                             fontName='Helvetica-Bold', fillColor=WHITE))
        return y0, bh, n, gap_v

    y0_c, _, n_c, gv_c = draw_col(causes, 0, 12)
    y0_m, _, n_m, gv_m = draw_col(mechs, 1, 12)
    y0_e, _, n_e, gv_e = draw_col(effects, 2, 12)
    y0_o, _, n_o, gv_o = draw_col(outcomes, 3, 12)

    # Arrows: causes -> mechs
    for i in range(3):
        sy = y0_c + i*(bh+gv_c) + bh/2
        ey = y0_m + i*(bh+gv_m) + bh/2
        arrow_line(d, col_x[0]+bw_c[0], sy, col_x[1], ey, CYAN, 1.2)

    # mechs -> effects (fan in)
    effect_ys = [y0_e + i*(bh+gv_e) + bh/2 for i in range(n_e)]
    mech_ys   = [y0_m + i*(bh+gv_m) + bh/2 for i in range(n_m)]
    pairs = [(0,0),(1,1),(2,0),(2,1)]
    for mi, ei in pairs:
        arrow_line(d, col_x[1]+bw_c[1], mech_ys[mi], col_x[2], effect_ys[ei], GREEN, 1)

    # effects -> outcome
    out_y = y0_o + bh/2
    for i in range(n_e):
        sy = y0_e + i*(bh+gv_e) + bh/2
        arrow_line(d, col_x[2]+bw_c[2], sy, col_x[3], out_y, GOLD, 1.5)

    # Labels
    for i, lbl in enumerate(['TRIGGERS', 'MECHANISMS', 'EFFECTS', 'RESULT']):
        d.add(String(col_x[i]+bw_c[i]/2, DH-24, lbl,
                     textAnchor='middle', fontSize=7, fontName='Helvetica-Bold', fillColor=DIM_TEXT))

    return DrawingFlowable(d)


# ═══════════════════════════════════════════════════════════════════════════
# FLOWCHART: Respiratory cascade
# ═══════════════════════════════════════════════════════════════════════════
def make_resp_flowchart():
    DW, DH = CONTENT_W, 5.2*cm
    d = Drawing(DW, DH)
    rounded_rect(d, 0, 0, DW, DH, 8, CARD_DARK, HexColor('#1A3555'), 0.8)
    d.add(String(DW/2, DH-13, '🫁  RESPIRATORY CHANGES - MECHANISM FLOW',
                 textAnchor='middle', fontSize=9, fontName='Helvetica-Bold', fillColor=BLUE))

    # Row 1: progesterone chain
    r1 = [
        ('Progesterone\n↑ 20x', PURPLE, True),
        ('Stimulates\nmedullary\nresp. center', HexColor('#1A237E'), True),
        ('Tidal Volume\n↑ 40%', BLUE, True),
        ('Minute Vent.\n↑ 50%', BLUE, True),
        ('PaCO₂\n↓ 15%\n(→32 mmHg)', HexColor('#1B5E20'), True),
    ]

    bw, bh = 82, 42
    gap = 9
    total = len(r1)*bw + (len(r1)-1)*gap
    start_x = (DW - total) / 2
    y1 = DH - 70

    for i, (lbl, bg, _) in enumerate(r1):
        bx = start_x + i*(bw+gap)
        rounded_rect(d, bx, y1, bw, bh, 5, bg, HexColor('#37474F'), 0.8)
        lines = lbl.split('\n')
        for j, ln in enumerate(lines):
            d.add(String(bx+bw/2, y1+bh/2+(len(lines)-1)*5-j*9,
                         ln, textAnchor='middle', fontSize=7.5,
                         fontName='Helvetica-Bold', fillColor=WHITE))
        if i < len(r1)-1:
            arrow_line(d, bx+bw, y1+bh/2, bx+bw+gap, y1+bh/2, GOLD, 1.5)

    # Bottom row: FRC danger chain
    r2 = [
        ('Uterus ↑\ndiaphragm', HexColor('#37474F'), False),
        ('FRC\n↓ 20%', RED, False),
        ('+  O₂ demand\n↑ 35%', ORANGE, False),
        ('→ Rapid\ndesaturation\non apnea', RED, False),
        ('Pre-O₂\n3-5 min\nMANDATORY', HexColor('#004D40'), False),
    ]

    y2 = 8
    for i, (lbl, bg, _) in enumerate(r2):
        bx = start_x + i*(bw+gap)
        rounded_rect(d, bx, y2, bw, bh-4, 5, bg, HexColor('#37474F'), 0.8)
        lines = lbl.split('\n')
        for j, ln in enumerate(lines):
            d.add(String(bx+bw/2, y2+(bh-4)/2+(len(lines)-1)*5-j*9,
                         ln, textAnchor='middle', fontSize=7.5,
                         fontName='Helvetica-Bold', fillColor=WHITE))
        if i < len(r2)-1:
            arrow_line(d, bx+bw, y2+(bh-4)/2, bx+bw+gap, y2+(bh-4)/2, HexColor('#FF5252'), 1.5)

    return DrawingFlowable(d)


# ═══════════════════════════════════════════════════════════════════════════
# COAGULATION cascade diagram
# ═══════════════════════════════════════════════════════════════════════════
def make_coag_diagram():
    DW, DH = CONTENT_W, 4.5*cm
    d = Drawing(DW, DH)
    rounded_rect(d, 0, 0, DW, DH, 8, CARD_DARK, HexColor('#1A3555'), 0.8)
    d.add(String(DW/2, DH-13, '🩸  VIRCHOW\'S TRIAD IN PREGNANCY (VTE Risk ↑4-5x)',
                 textAnchor='middle', fontSize=9, fontName='Helvetica-Bold', fillColor=ORANGE))

    # Triangle arrangement
    cx = DW/2
    tri_y_top = DH - 52
    tri_y_bot = 14

    # 3 nodes
    nodes = [
        (cx, tri_y_top + 18, 'HYPERCOAGULABILITY', 'Clotting factors ↑30-250%\nFibrinogen doubles\nProtein C/S ↓', HexColor('#7B0000')),
        (cx - 140, tri_y_bot + 18, 'VENOUS STASIS', 'IVC compression\nReduced mobility\nPelvic veins dilated', HexColor('#01579B')),
        (cx + 140, tri_y_bot + 18, 'ENDOTHELIAL INJURY', 'Delivery trauma\nCervical dilation\nSurgical delivery', HexColor('#1B5E20')),
    ]

    node_w, node_h = 155, 42
    node_positions = []
    for (nx, ny, title, sub, bg) in nodes:
        bx = nx - node_w/2
        by = ny - node_h/2
        node_positions.append((nx, ny))
        rounded_rect(d, bx, by, node_w, node_h, 6, bg, HexColor('#37474F'), 1)
        d.add(String(nx, ny+8, title, textAnchor='middle', fontSize=7.5,
                     fontName='Helvetica-Bold', fillColor=WHITE))
        for i, ln in enumerate(sub.split('\n')):
            d.add(String(nx, ny-2-i*9, ln, textAnchor='middle', fontSize=6.5,
                         fontName='Helvetica', fillColor=LIGHT_TEXT))

    # Lines connecting them
    for i in range(3):
        for j in range(i+1, 3):
            x1, y1 = node_positions[i]
            x2, y2 = node_positions[j]
            d.add(Line(x1, y1, x2, y2, strokeColor=GOLD, strokeWidth=1.5, strokeDashArray=[4,3]))

    # Center label
    d.add(String(cx, (tri_y_top+tri_y_bot)/2+10, 'VTE',
                 textAnchor='middle', fontSize=12, fontName='Helvetica-Bold', fillColor=RED))
    d.add(String(cx, (tri_y_top+tri_y_bot)/2-4, 'RISK',
                 textAnchor='middle', fontSize=10, fontName='Helvetica-Bold', fillColor=RED))

    return DrawingFlowable(d)


# ═══════════════════════════════════════════════════════════════════════════
# TIMELINE diagram
# ═══════════════════════════════════════════════════════════════════════════
def make_timeline():
    DW, DH = CONTENT_W, 5.8*cm
    d = Drawing(DW, DH)
    rounded_rect(d, 0, 0, DW, DH, 8, CARD_DARK, HexColor('#1A3555'), 0.8)
    d.add(String(DW/2, DH-13, '📅  TIMELINE OF KEY PHYSIOLOGICAL CHANGES',
                 textAnchor='middle', fontSize=9, fontName='Helvetica-Bold', fillColor=GOLD))

    # Timeline line
    line_y = DH/2 - 5
    tl_x1, tl_x2 = 35, DW-15
    d.add(Line(tl_x1, line_y, tl_x2, line_y, strokeColor=CYAN, strokeWidth=2))

    # Arrow at end
    d.add(Polygon([tl_x2+10, line_y, tl_x2, line_y+5, tl_x2, line_y-5],
                  fillColor=CYAN, strokeColor=CYAN))

    # Week markers
    weeks = [0, 8, 12, 16, 24, 28, 32, 40]
    w_labels = ['0', '8', '12', '16', '24', '28', '32', '40 wks']
    total_wks = 40
    for wk, lbl in zip(weeks, w_labels):
        px = tl_x1 + (wk/total_wks)*(tl_x2-tl_x1)
        d.add(Line(px, line_y-5, px, line_y+5, strokeColor=CYAN, strokeWidth=1))
        d.add(String(px, line_y-14, lbl, textAnchor='middle', fontSize=6.5,
                     fontName='Helvetica', fillColor=DIM_TEXT))

    # Events - above line
    events_above = [
        (8, 'hCG peaks', PINK, 1),
        (10, 'Nausea peak', HexColor('#FF8F00'), 1),
        (12, 'Plasma vol ↑\nbegins', CYAN, 2),
        (16, 'IVC risk\nstarts', RED, 1),
        (24, 'BP nadir\nDGDM screen', GREEN, 2),
        (32, 'Plasma vol\npeak +55%', BLUE, 1),
        (40, 'MAC ↓40%\nmax term', PURPLE, 2),
    ]
    # Events - below line
    events_below = [
        (6, 'GFR ↑\nbegins', GREEN, 1),
        (8, 'CO ↑ starts', RED, 2),
        (20, 'Fetal\nmovements', HexColor('#FF8F00'), 1),
        (28, 'CO peaks', RED, 2),
        (36, 'Clotting\nfactors max', ORANGE, 2),
        (40, 'Uterus 1kg\n700ml/min', PINK, 1),
    ]

    tick_h = 18
    for (wk, lbl, clr, rows) in events_above:
        px = tl_x1 + (wk/total_wks)*(tl_x2-tl_x1)
        stem_h = tick_h + (rows-1)*10
        d.add(Line(px, line_y+5, px, line_y+stem_h+4, strokeColor=clr, strokeWidth=0.8))
        for i, ln in enumerate(lbl.split('\n')):
            d.add(String(px, line_y+stem_h+4+i*8, ln,
                         textAnchor='middle', fontSize=6, fontName='Helvetica-Bold', fillColor=clr))

    for (wk, lbl, clr, rows) in events_below:
        px = tl_x1 + (wk/total_wks)*(tl_x2-tl_x1)
        stem_h = tick_h + (rows-1)*10
        d.add(Line(px, line_y-5, px, line_y-stem_h-4, strokeColor=clr, strokeWidth=0.8))
        for i, ln in enumerate(lbl.split('\n')):
            d.add(String(px, line_y-stem_h-12-i*8, ln,
                         textAnchor='middle', fontSize=6, fontName='Helvetica-Bold', fillColor=clr))

    # Trimester shading bands
    t1_end = tl_x1 + (12/40)*(tl_x2-tl_x1)
    t2_end = tl_x1 + (28/40)*(tl_x2-tl_x1)
    for (bx, bw2, lbl, clr) in [
        (tl_x1, t1_end-tl_x1, 'T1', HexColor('#3E2700')),
        (t1_end, t2_end-t1_end, 'T2', HexColor('#004D00')),
        (t2_end, tl_x2-t2_end, 'T3', HexColor('#4A0020')),
    ]:
        r = Rect(bx, line_y-3, bw2, 6, fillColor=clr, strokeColor=None)
        d.add(r)

    return DrawingFlowable(d)


# ═══════════════════════════════════════════════════════════════════════════
# SUPINE HYPOTENSION DIAGRAM
# ═══════════════════════════════════════════════════════════════════════════
def make_supine_diagram():
    DW, DH = CONTENT_W, 4.2*cm
    d = Drawing(DW, DH)
    rounded_rect(d, 0, 0, DW, DH, 8, CARD_DARK, HexColor('#1A3555'), 0.8)
    d.add(String(DW/2, DH-13, '⚠️  AORTOCAVAL COMPRESSION SYNDROME (Supine Hypotension)',
                 textAnchor='middle', fontSize=9, fontName='Helvetica-Bold', fillColor=RED))

    steps = [
        ('Supine\nposition', HexColor('#37474F')),
        ('Uterus\ncompresses\nIVC + Aorta', RED),
        ('Venous return\n↓ up to 40%', HexColor('#7B0000')),
        ('Cardiac output\n↓ sharply', HexColor('#880E4F')),
        ('Maternal\nhypotension\n+ Fetal distress', RED),
        ('FIX: Left\nuterine tilt 15°', HexColor('#006064')),
    ]

    bw, bh = 75, 44
    gap = 8
    total = len(steps)*bw + (len(steps)-1)*gap
    start_x = (DW - total) / 2
    y = DH/2 - bh/2 - 8

    for i, (lbl, bg) in enumerate(steps):
        bx = start_x + i*(bw+gap)
        rounded_rect(d, bx, y, bw, bh, 5, bg, HexColor('#37474F'), 0.8)
        lines = lbl.split('\n')
        for j, ln in enumerate(lines):
            d.add(String(bx+bw/2, y+bh/2+(len(lines)-1)*4.5-j*9,
                         ln, textAnchor='middle', fontSize=7,
                         fontName='Helvetica-Bold', fillColor=WHITE))
        if i < len(steps)-1:
            col = HexColor('#FF5252') if i < len(steps)-2 else GOLD
            arrow_line(d, bx+bw, y+bh/2, bx+bw+gap, y+bh/2, col, 1.5)

    d.add(String(DW/2, 6, 'Onset after 18-20 weeks gestation  |  Always use left lateral tilt for all procedures',
                 textAnchor='middle', fontSize=7, fontName='Helvetica-Oblique', fillColor=DIM_TEXT))

    return DrawingFlowable(d)


# ═══════════════════════════════════════════════════════════════════════════
# BLOOD VOLUME VISUAL (proportional circles)
# ═══════════════════════════════════════════════════════════════════════════
def make_volume_diagram():
    DW, DH = CONTENT_W, 3.8*cm
    d = Drawing(DW, DH)
    rounded_rect(d, 0, 0, DW, DH, 8, CARD_DARK, HexColor('#1A3555'), 0.8)
    d.add(String(DW/2, DH-13, '📊  BLOOD VOLUME EXPANSION IN PREGNANCY',
                 textAnchor='middle', fontSize=9, fontName='Helvetica-Bold', fillColor=CYAN))

    items = [
        ('Total Blood\nVolume', 35, CYAN, 55),
        ('Plasma\nVolume', 55, BLUE, 65),
        ('RBC\nMass', 25, RED, 45),
        ('Cardiac\nOutput', 40, PINK, 55),
        ('GFR', 50, GREEN, 60),
    ]

    section_w = DW / len(items)
    cy = DH/2 - 8

    for i, (lbl, pct, clr, base_r) in enumerate(items):
        cx2 = section_w*i + section_w/2
        r_non = 18
        r_preg = r_non * math.sqrt(1 + pct/100)

        # Non-pregnant (dim)
        d.add(Circle(cx2-12, cy, r_non, fillColor=HexColor('#1A3555'),
                     strokeColor=clr, strokeWidth=0.8))
        d.add(String(cx2-12, cy-4, 'Pre', textAnchor='middle',
                     fontSize=6, fontName='Helvetica', fillColor=DIM_TEXT))

        # Pregnant (bright)
        d.add(Circle(cx2+16, cy, r_preg, fillColor=clr.__class__(
            min(255, int(clr.red*255*0.4)), min(255, int(clr.green*255*0.4)),
            min(255, int(clr.blue*255*0.4))),
            strokeColor=clr, strokeWidth=1.5))
        d.add(String(cx2+16, cy-4, 'Preg', textAnchor='middle',
                     fontSize=6, fontName='Helvetica-Bold', fillColor=WHITE))

        # Arrow between
        arrow_line(d, cx2-12+r_non+2, cy, cx2+16-r_preg-2, cy, GOLD, 1)

        # Label and %
        sign = '+' if pct > 0 else ''
        d.add(String(cx2+2, DH-24, lbl.replace('\n', ' '),
                     textAnchor='middle', fontSize=6.5, fontName='Helvetica-Bold', fillColor=LIGHT_TEXT))
        d.add(String(cx2+2, 5, f'{sign}{pct}%',
                     textAnchor='middle', fontSize=8, fontName='Helvetica-Bold', fillColor=clr))

    return DrawingFlowable(d)


# ═══════════════════════════════════════════════════════════════════════════
# SECTION BANNER helper
# ═══════════════════════════════════════════════════════════════════════════
def banner(title, icon, bg):
    data = [[Paragraph(f'{icon}  {title}', sec_s)]]
    t = Table(data, colWidths=[CONTENT_W])
    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), 14),
    ]))
    return t


def make_table(rows, accent):
    header = [
        Paragraph('Parameter', S('h', fontName='Helvetica-Bold', fontSize=9, textColor=WHITE, alignment=TA_CENTER)),
        Paragraph('Change', S('h', fontName='Helvetica-Bold', fontSize=9, textColor=WHITE, alignment=TA_CENTER)),
        Paragraph('Clinical Significance', S('h', fontName='Helvetica-Bold', fontSize=9, textColor=WHITE, alignment=TA_CENTER)),
    ]
    data = [header]
    for param, change, note in rows:
        clr = HexColor('#69F0AE') if '+' in str(change) else HexColor('#FF5252') if '-' in str(change) else GOLD
        data.append([
            Paragraph(param, S('p', fontName='Helvetica', fontSize=8.5, textColor=LIGHT_TEXT, alignment=TA_LEFT)),
            Paragraph(f'<b>{change}</b>', S('c', fontName='Helvetica-Bold', fontSize=9, textColor=clr, alignment=TA_CENTER)),
            Paragraph(note, S('n', fontName='Helvetica', fontSize=8, textColor=HexColor('#B0BEC5'), alignment=TA_LEFT)),
        ])
    t = Table(data, colWidths=[5.5*cm, 2.5*cm, 9*cm])
    t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,0), accent),
        ('GRID', (0,0), (-1,-1), 0.3, HexColor('#2C3E50')),
        ('TOPPADDING', (0,0), (-1,-1), 5),
        ('BOTTOMPADDING', (0,0), (-1,-1), 5),
        ('LEFTPADDING', (0,0), (-1,-1), 6),
        ('ROWBACKGROUNDS', (0,1), (-1,-1), [ROW_ALT, CARD_MID]),
        ('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
    ]))
    return t


# ═══════════════════════════════════════════════════════════════════════════
# CLINICAL PEARLS
# ═══════════════════════════════════════════════════════════════════════════
def make_pearls():
    pearls = [
        ('🔴', 'Rapid desaturation', 'FRC ↓ + O₂ consumption ↑ = very short safe apnea time. Pre-oxygenate 3-5 min.', RED),
        ('🟡', 'Supine hypotension', 'IVC compression after 18-20 wks. Always use LEFT LATERAL TILT 15°.', GOLD),
        ('🟠', 'Full stomach risk', 'RSI mandatory for all GA >12-16 weeks regardless of fasting.', ORANGE),
        ('🩸', 'Dilutional anemia', 'Hgb 10-11 g/dL is NORMAL in pregnancy (plasma ↑ more than RBC).', HexColor('#EF9A9A')),
        ('💨', 'PaCO₂ "normal" = danger', 'Normal PaCO₂ in pregnancy = 32 mmHg. A reading of 40 mmHg = respiratory failure.', BLUE),
        ('🫘', 'Creatinine "normal" = impaired', 'Normal Cr in pregnancy = 0.5-0.8 mg/dL. Cr of 1.0 warrants investigation.', GREEN),
        ('🩺', 'Hypercoagulability', 'VTE risk 4-5x higher. Immobility + surgery = thromboprophylaxis essential.', ORANGE),
        ('💉', 'Reduced MAC', 'Need 40% less volatile anesthetic. Also more sensitive to IV sedatives and opioids.', PURPLE),
    ]

    rows = []
    for i in range(0, len(pearls), 2):
        row = []
        for j in range(2):
            if i+j < len(pearls):
                ico, title, body, clr = pearls[i+j]
                cell_content = Paragraph(
                    f'<b><font color="#{clr.hexval()[1:]}">{ico} {title}</font></b><br/>'
                    f'<font color="#B0BEC5">{body}</font>',
                    S('pc', fontName='Helvetica', fontSize=8, textColor=LIGHT_TEXT,
                      leading=12, alignment=TA_LEFT)
                )
                row.append(cell_content)
            else:
                row.append('')
        rows.append(row)

    t = Table(rows, colWidths=[CONTENT_W/2 - 2*mm, CONTENT_W/2 - 2*mm])
    t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), CARD_MID),
        ('GRID', (0,0), (-1,-1), 0.3, HexColor('#2C3E50')),
        ('TOPPADDING', (0,0), (-1,-1), 8),
        ('BOTTOMPADDING', (0,0), (-1,-1), 8),
        ('LEFTPADDING', (0,0), (-1,-1), 10),
        ('VALIGN', (0,0), (-1,-1), 'TOP'),
        ('ROWBACKGROUNDS', (0,0), (-1,-1), [CARD_MID, ROW_ALT]),
    ]))
    return t


# ═══════════════════════════════════════════════════════════════════════════
# HORMONAL EFFECTS diagram
# ═══════════════════════════════════════════════════════════════════════════
def make_hormones_diagram():
    DW, DH = CONTENT_W, 5*cm
    d = Drawing(DW, DH)
    rounded_rect(d, 0, 0, DW, DH, 8, CARD_DARK, HexColor('#1A3555'), 0.8)
    d.add(String(DW/2, DH-13, '⚗️  HORMONAL CHANGES & THEIR EFFECTS',
                 textAnchor='middle', fontSize=9, fontName='Helvetica-Bold', fillColor=CYAN))

    hormones = [
        ('PROGESTERONE\n↑ up to 20x', HexColor('#4A148C'), 55, DH-48,
         ['MAC ↓', 'Bronchodilation', 'LES tone ↓', 'GI motility ↓', 'Vasodilation', 'Ventilation ↑']),
        ('ESTROGEN\n↑ markedly', HexColor('#880E4F'), 55, DH-48,
         ['Airway edema', 'Clotting factors ↑', 'TBG ↑', 'Binding proteins ↑', 'Na retention', 'Mucosal hyperemia']),
        ('hPL\n↑ throughout', HexColor('#E65100'), 55, DH-48,
         ['Insulin resistance', 'Lipolysis ↑', 'Glucose ↑', 'GDM risk ↑', 'Fetal nutrition', 'Anti-insulin']),
        ('CORTISOL\n↑ 3x', HexColor('#1B5E20'), 55, DH-48,
         ['Glucose tolerance ↓', 'Striae gravidarum', 'Immune modulation', 'Bone turnover ↑']),
        ('ALDOSTERONE\n↑ 10x', HexColor('#0D47A1'), 55, DH-48,
         ['Na retention', 'Fluid retention', 'Edema', 'K excretion ↑']),
    ]

    n = len(hormones)
    section_w = DW / n
    hormone_y = DH - 55
    h_bw = 85
    h_bh = 30

    for i, (name, bg, _, _, effects) in enumerate(hormones):
        cx2 = section_w*i + section_w/2
        # Hormone box
        bx = cx2 - h_bw/2
        rounded_rect(d, bx, hormone_y, h_bw, h_bh, 5, bg, HexColor('#37474F'), 0.8)
        for j, ln in enumerate(name.split('\n')):
            d.add(String(cx2, hormone_y+h_bh/2+5-j*11, ln,
                         textAnchor='middle', fontSize=7, fontName='Helvetica-Bold', fillColor=WHITE))

        # Effect boxes below
        eff_bh = 11
        eff_gap = 3
        for k, eff in enumerate(effects):
            ey = hormone_y - (k+1)*(eff_bh+eff_gap)
            if ey < 5:
                break
            eff_bg = HexColor(f'#{max(0, int(bg.red*255)-30):02x}'
                              f'{max(0, int(bg.green*255)-30):02x}'
                              f'{max(0, int(bg.blue*255)-30):02x}')
            d.add(Rect(cx2-40, ey, 80, eff_bh, fillColor=eff_bg,
                       strokeColor=bg, strokeWidth=0.5))
            d.add(String(cx2, ey+3.5, eff, textAnchor='middle', fontSize=6,
                         fontName='Helvetica', fillColor=LIGHT_TEXT))
            # connector line
            if k == 0:
                d.add(Line(cx2, hormone_y, cx2, ey+eff_bh,
                           strokeColor=bg, strokeWidth=0.6, strokeDashArray=[2,2]))

    return DrawingFlowable(d)


# ═══════════════════════════════════════════════════════════════════════════
# BUILD PDF
# ═══════════════════════════════════════════════════════════════════════════
OUTPUT = '/home/daytona/workspace/pregnancy-physiology/Physiological_Changes_Pregnancy_v2.pdf'

doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    rightMargin=1.8*cm, leftMargin=1.8*cm,
    topMargin=1.5*cm, bottomMargin=1.5*cm,
)

story = []

def add_bg(canvas, doc):
    canvas.saveState()
    canvas.setFillColor(DARK_BG)
    canvas.rect(0, 0, A4[0], A4[1], fill=1, stroke=0)
    canvas.restoreState()

# ── PAGE 1: Cover + Bar Chart + Body Diagram ──────────────────────────────
hdr_data = [[Paragraph('PHYSIOLOGICAL CHANGES<br/>DURING PREGNANCY', title_s)]]
hdr_t = Table(hdr_data, colWidths=[CONTENT_W])
hdr_t.setStyle(TableStyle([
    ('BACKGROUND', (0,0), (-1,-1), NAVY),
    ('TOPPADDING', (0,0), (-1,-1), 18),
    ('BOTTOMPADDING', (0,0), (-1,-1), 8),
]))
story.append(hdr_t)
story.append(Paragraph('A Visual Medical Summary — Systems, Flowcharts & Diagrams', sub_s))
story.append(Paragraph('Source: Morgan & Mikhail\'s Clinical Anesthesiology, 7e (pp. 1572–1587)', src_s))
story.append(Spacer(1, 3*mm))

# Bar chart
story.append(banner('MAGNITUDE OF CHANGES — AT A GLANCE', '📊', TABLE_HDR))
story.append(Spacer(1, 2*mm))
story.append(make_bar_chart())
story.append(Spacer(1, 4*mm))

# Body diagram
story.append(banner('BODY SYSTEMS MAP', '🏃', HexColor('#1A237E')))
story.append(Spacer(1, 2*mm))
story.append(make_body_diagram())
story.append(PageBreak())

# ── PAGE 2: CVS Flowchart + Volume diagram + Supine ──────────────────────
story.append(banner('CARDIOVASCULAR CHANGES — FLOWCHART', '❤️', HexColor('#B71C1C')))
story.append(Spacer(1, 2*mm))
story.append(make_cvs_flowchart())
story.append(Spacer(1, 4*mm))

story.append(banner('BLOOD VOLUME EXPANSION', '🔵', HexColor('#0D47A1')))
story.append(Spacer(1, 2*mm))
story.append(make_volume_diagram())
story.append(Spacer(1, 4*mm))

story.append(banner('SUPINE HYPOTENSION / AORTOCAVAL COMPRESSION', '⚠️', HexColor('#7B1515')))
story.append(Spacer(1, 2*mm))
story.append(make_supine_diagram())
story.append(Spacer(1, 4*mm))

# CVS detail table
story.append(make_table([
    ('Blood Volume', '+35%', 'Starts 1st trimester; peaks 28-32 weeks; buffers delivery blood loss'),
    ('Plasma Volume', '+55%', 'Exceeds RBC expansion → physiological dilutional anemia'),
    ('Cardiac Output', '+40%', 'Rises by 8-10 weeks; further ↑ during labor contractions (+10-45%)'),
    ('Stroke Volume', '+30%', 'Increased preload + decreased afterload'),
    ('Heart Rate', '+20%', 'Tachycardia >100 bpm is normal in late pregnancy'),
    ('Systolic BP', '-5%', 'Slight decrease; returns to near baseline at term'),
    ('Diastolic BP', '-15%', 'Nadir at 24-28 weeks; used to diagnose PIH/preeclampsia'),
    ('SVR', '-15%', 'Progesterone + placental AV shunt + prostacyclin'),
    ('Pulmonary resistance', '-30%', 'Reduces RV afterload; important in pulmonary hypertension'),
], HexColor('#C62828')))
story.append(PageBreak())

# ── PAGE 3: Respiratory ────────────────────────────────────────────────────
story.append(banner('RESPIRATORY CHANGES — MECHANISM FLOW', '🫁', HexColor('#01579B')))
story.append(Spacer(1, 2*mm))
story.append(make_resp_flowchart())
story.append(Spacer(1, 4*mm))

story.append(banner('ASPIRATION RISK FLOWCHART', '⚠️', HexColor('#7B1515')))
story.append(Spacer(1, 2*mm))
story.append(make_aspiration_flowchart())
story.append(Spacer(1, 4*mm))

story.append(make_table([
    ('O₂ Consumption', '+20–50%', 'Increased metabolic demands of fetus, uterus, placenta, breasts'),
    ('Minute Ventilation', '+50%', 'Progesterone stimulates medullary respiratory center'),
    ('Tidal Volume', '+40%', 'Primary driver; RR also rises +15%'),
    ('FRC', '-20%', 'Elevated diaphragm; ↓ ERV and RV; predisposes to atelectasis & rapid desaturation'),
    ('Airway Resistance', '-35%', 'Progesterone-mediated bronchodilation'),
    ('PaO₂', '+10%', 'Rises to ~106 mmHg at sea level; hyperventilation effect'),
    ('PaCO₂', '-15%', 'Drops to ~32 mmHg; HCO₃⁻ drops to ~20 mEq/L; pH ~7.44'),
    ('P50', '+27→30 mmHg', 'Right-shifted O₂-Hb curve; facilitates O₂ offloading to fetus'),
], HexColor('#0277BD')))
story.append(PageBreak())

# ── PAGE 4: Hematology + Coagulation ──────────────────────────────────────
story.append(banner('VTE RISK — VIRCHOW\'S TRIAD IN PREGNANCY', '🩸', HexColor('#7B1515')))
story.append(Spacer(1, 2*mm))
story.append(make_coag_diagram())
story.append(Spacer(1, 4*mm))

story.append(banner('HEMATOLOGICAL CHANGES', '🩸', HexColor('#E65100')))
story.append(Spacer(1, 2*mm))
story.append(make_table([
    ('Hemoglobin', '-20%', 'Hgb <11 g/dL (1st tri) or <10.5 g/dL (2nd tri) is pathological'),
    ('Hematocrit', 'Decreases', 'Falls from ~40% to ~34%; nadir at 30-34 weeks'),
    ('Platelets', '-10%', 'Mild thrombocytopenia is normal; <70,000 warrants investigation'),
    ('WBC', 'Increases', 'Up to 12,000/μL; in labor may reach 20,000-30,000/μL'),
    ('Fibrinogen', 'Doubles', 'Rises from 300 → 600 mg/dL; ESR increases markedly'),
    ('Clotting factors II, VII, VIII, X', '+30–250%', 'Pregnancy is strongly hypercoagulable'),
    ('Protein C & S', 'Decreased', 'Further tilts balance toward thrombosis'),
    ('Serum albumin', 'Decreased', '4.0 → 3.0 g/dL; affects protein-bound drug pharmacokinetics'),
], HexColor('#E64A19')))
story.append(PageBreak())

# ── PAGE 5: Hormones + Renal + GI ─────────────────────────────────────────
story.append(banner('HORMONAL CHANGES & THEIR EFFECTS', '⚗️', HexColor('#006064')))
story.append(Spacer(1, 2*mm))
story.append(make_hormones_diagram())
story.append(Spacer(1, 4*mm))

story.append(banner('RENAL CHANGES', '🫘', HexColor('#1B5E20')))
story.append(Spacer(1, 2*mm))
story.append(make_table([
    ('GFR', '+50%', 'Starts 1st trimester; renal plasma flow ↑70%; kidneys enlarge ~1 cm'),
    ('Serum Creatinine', 'Decreased', 'Normal = 0.5–0.8 mg/dL; "normal" 1.0 mg/dL suggests impairment'),
    ('Serum BUN', 'Decreased', 'Normal ~8-9 mg/dL; lower due to ↑GFR'),
    ('Glycosuria', 'May occur', 'Tubular reabsorption does not scale with GFR; not pathological alone'),
    ('Urine protein', 'Up to 300 mg/day', '>300 mg/24h = pathological; marker for preeclampsia'),
], HexColor('#2E7D32')))
story.append(Spacer(1, 4*mm))

story.append(banner('GASTROINTESTINAL CHANGES', '🤰', HexColor('#4E342E')))
story.append(Spacer(1, 2*mm))
story.append(make_table([
    ('Gastric emptying', 'Delayed', 'Progesterone ↓ GI motility; aspiration risk (Mendelson syndrome)'),
    ('LES tone', 'Decreased', 'Combined with ↑ intragastric pressure → GERD in >80%'),
    ('Nausea & vomiting', 'Common', 'Affects 70-80%; hyperemesis gravidarum in <2%; peak 8-10 wks'),
    ('Alkaline phosphatase', 'Increased', 'Placenta produces ALP; ALT/AST should remain normal'),
    ('Gallbladder', 'Delayed emptying', 'Cholesterol gallstones 2x more common in pregnancy'),
], HexColor('#5D4037')))
story.append(PageBreak())

# ── PAGE 6: Timeline + Clinical Pearls ────────────────────────────────────
story.append(banner('TIMELINE OF KEY PHYSIOLOGICAL CHANGES', '📅', HexColor('#1A237E')))
story.append(Spacer(1, 2*mm))
story.append(make_timeline())
story.append(Spacer(1, 5*mm))

story.append(banner('⭐ HIGH-YIELD CLINICAL PEARLS', '🏆', HexColor('#1A3020')))
story.append(Spacer(1, 2*mm))
story.append(make_pearls())
story.append(Spacer(1, 5*mm))

# Footer
story.append(HRFlowable(width='100%', thickness=0.5, color=HexColor('#37474F')))
story.append(Spacer(1, 2*mm))
story.append(Paragraph(
    'Source: Morgan & Mikhail\'s Clinical Anesthesiology, 7e, Chapter 40 (pp. 1572–1587) | '
    'Compiled for educational purposes | Orris Medical Summary  —  6-page visual reference',
    note_s
))

doc.build(story, onFirstPage=add_bg, onLaterPages=add_bg)
print(f'✅ PDF created: {OUTPUT}')
Running Command

cd /home/daytona/workspace/pregnancy-physiology && python make_pdf_v2.py 2>&1

Editing File

~/pregnancy-physiology/make_pdf_v2.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/pregnancy-physiology/make_pdf_v2.py'
Running Command

cd /home/daytona/workspace/pregnancy-physiology && python make_pdf_v2.py 2>&1

Editing File

~/pregnancy-physiology/make_pdf_v2.py

Error: String not found in file: '    for i, (ico, title, body, clr) in enumerate(pearls[i+j:i+j+1]):
                cell_content = Paragraph(
                    f'<b><font color="#{clr.hexval()[1:]}">{ico} {title}</font></b><br/>'
                    f'<font color="#B0BEC5">{body}</font>',
                    S('pc', fontName='Helvetica', fontSize=8, textColor=LIGHT_TEXT,
                      leading=12, alignment=TA_LEFT)
                )
                row.append(cell_content)'
Searching Content

"hexval" in ~/pregnancy-physiology

Reading File
Reading File
Running Command

python3 -c "from reportlab.lib.colors import HexColor; c=HexColor('#EF5350'); print(repr(c.hexval())); print('%02X%02X%02X' % (int(c.red*255), int(c.green*255), int(c.blue*255)))"

Editing File

~/pregnancy-physiology/make_pdf_v2.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/pregnancy-physiology/make_pdf_v2.py'
Editing File

~/pregnancy-physiology/make_pdf_v2.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/pregnancy-physiology/make_pdf_v2.py'
Editing File

~/pregnancy-physiology/make_pdf_v2.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/pregnancy-physiology/make_pdf_v2.py'
Running Command

cd /home/daytona/workspace/pregnancy-physiology && python make_pdf_v2.py 2>&1

Running Command

ls -lh /home/daytona/workspace/pregnancy-physiology/Physiological_Changes_Pregnancy_v2.pdf

Your enhanced 6-page visual PDF is ready:

Physiological Changes Pregnancy v2

PDF Document · PDF


Here's what's inside all 6 pages:
Page 1 - Overview
  • Horizontal bar chart showing all key % changes (green = increase, red = decrease) for every parameter at a glance
  • Full body system map with annotated callout boxes pointing to CNS, heart, lungs, kidneys, uterus, GI - with arrows connecting each organ to its changes
Page 2 - Cardiovascular
  • Cause-and-effect flowchart: Triggers → Mechanisms → Effects → Cardiac Output
  • Proportional circle diagram showing blood volume/plasma/RBC/CO/GFR expansion (bigger circle = bigger change)
  • Supine hypotension step-by-step flowchart (6 boxes with arrows): supine → IVC compression → ↓venous return → ↓CO → hypotension → FIX: left tilt
Page 3 - Respiratory
  • Mechanism flow (progesterone → medullary stimulation → TV ↑ → MV ↑ → PaCO₂ ↓)
  • Danger chain (uterus pushes diaphragm → FRC ↓ + O₂ demand ↑ → rapid desaturation → pre-O₂ mandatory)
  • Aspiration risk flowchart: Progesterone → LES tone ↓ → delayed emptying → ↑intragastric pressure → full stomach → RSI mandatory
Page 4 - Hematology
  • Virchow's triad triangle diagram with VTE at center (hypercoagulability + venous stasis + endothelial injury nodes)
  • Hematological changes table with color-coded values
Page 5 - Endocrine, Renal, GI
  • Hormonal effect tree: 5 hormones (progesterone, estrogen, hPL, cortisol, aldosterone) each branching into their downstream effects
  • Renal and GI tables
Page 6 - Timeline + Pearls
  • Full pregnancy timeline (0-40 weeks) with labeled events above and below the line, trimester color bands
  • 8 high-yield clinical pearls in a 2-column color-coded grid
This is a shared conversation. Sign in to Orris to start your own chat.