attachment
attachment
attachment
attachment

Create answers for following questions

Reading File
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Reading File
Reading File
Finding Sources
All 28 questions (21 SAQs + 7 LAQs) have been answered in full. Here's a quick reference summary:

Quick Reference Index

SAQ Topics Covered:

  1. OxyHb Dissociation Curve - sigmoid shape, key points, right/left shift factors, role of 2,3-BPG
  2. Hering-Breuer Reflex - stretch receptors → CN X → inhibits inspiration; protective mechanism
  3. Bohr Effect - CO2/H+ shift OxyHb curve right; O2 unloading in active tissues
  4. Haldane Effect - O2 binding causes CO2 release; accounts for ~50% of CO2 transport in lungs
  5. P50 - PO2 at 50% Hb saturation; normal = 26 mmHg; indicator of O2 affinity
  6. Pulmonary Circulation - low pressure/resistance, West's 3 zones, HPV (opposite to systemic)
  7. High Altitude Acclimatisation - hyperventilation, polycythaemia, 2,3-BPG, EPO, AMS/HACE/HAPE
  8. Peripheral Chemoreceptors - carotid bodies (CN IX), aortic bodies (CN X); respond mainly to low PO2
  9. Alveolar Air Composition - VA, dead space, V/Q, RQ, alveolar gas equation
  10. Hypoxia - 4 types (hypoxic, anaemic, stagnant, histotoxic); hypoxic hypoxia detailed
  11. Surfactant - Type II pneumocytes, DPPC, Laplace's law, RDS/HMD in premature babies
  12. Work of Breathing - 3 components: elastic (65%), tissue resistance (7%), airway resistance (28%)
  13. Muscles of Respiration - diaphragm (primary), external intercostals, SCM, scalenes, abdominals
  14. FRC - ERV + RV = ~2500 mL; O2 buffer, prevents collapse, reduced by anaesthesia/obesity
  15. AMS - rapid ascent, hypoxic vasodilation, cerebral oedema; tx: descent, O2, acetazolamide, dexamethasone
  16. Periodic Breathing & Ondine's Curse - Cheyne-Stokes (heart failure), CCHS (PHOX2B mutation)
  17. Obstructive Lung Disease - FEV1/FVC <0.7, air trapping, COPD types, pink puffer vs blue bloater
  18. Lung Volumes & Capacities - 4 volumes + 4 capacities; RV/FRC/TLC need plethysmography
  19. V/Q Ratio - normal 0.8; dead space (PE) vs shunt (pneumonia); HPV improves matching
  20. Kussmaul Breathing - deep regular rapid breathing; metabolic acidosis (DKA, uraemia); compensatory CO2 blow-off
  21. Asphyxia, Cyanosis, Dyspnoea - definitions, types, mechanisms, clinical features

LAQ Topics Covered:

  1. Neural Regulation - DRG, VRG, pre-Bötzinger complex, pneumotaxic/apneustic centres, reflexes
  2. Chemical Control - central (CO2/H+, BBB, retrotrapezoid nucleus) + peripheral chemoreceptors; interaction
  3. Lung Compliance - ΔV/ΔP, surface tension (2/3) + elastic recoil (1/3), HMD pathophysiology
  4. Respiratory Membrane - 8 layers, Fick's law, factors affecting, DLCO/CO method principle
  5. Pulmonary Ventilation - Boyle's law, pressure changes, negative pressure inspiration, PPB types and effects
  6. Transport of O2 - dissolved (1.5%) + Hb-bound (98.5%), Hüfner's constant, cooperative binding, Fick's principle
  7. CO2 Transport - dissolved (7%), bicarbonate (70%), carbamino (23%), chloride shift, Haldane effect

Create a comprehensive exam study guide PDF covering all respiratory physiology topics

Reading File
Running Command

ls -la /home/daytona/workspace/ 2>/dev/null || echo "workspace not found"

Running Command

mkdir -p /home/daytona/workspace/respiratory-study-guide && python3 -c "import reportlab; print('reportlab ok')" && python3 -c "from reportlab.lib.pagesizes import A4; print('A4 ok')"

Give a flow chart based answers pdf

Running Command

python3 -c "import reportlab; from reportlab.lib.pagesizes import A4; from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, HRFlowable, PageBreak; from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle; from reportlab.lib import colors; from reportlab.lib.units import cm, mm; from reportlab.graphics.shapes import Drawing, Rect, String, Line, Arrow; from reportlab.graphics import renderPDF; print('all imports ok')"

Running Command

python3 -c "from reportlab.graphics.shapes import Drawing, Rect, String, Line, Polygon, Path; print('ok')"

Writing File

~/respiratory-study-guide/build_pdf.py

"""
Respiratory Physiology - Flowchart-Based Study Guide PDF
Covers all 21 SAQ + 7 LAQ topics
"""

from reportlab.lib.pagesizes import A4
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, PageBreak, KeepTogether
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Polygon, Circle
from reportlab.graphics import renderPDF
from reportlab.platypus.flowables import Flowable

# ── Color Palette ──────────────────────────────────────────────────────────────
C_NAVY    = colors.HexColor("#1A3A5C")
C_TEAL    = colors.HexColor("#1B7A78")
C_ORANGE  = colors.HexColor("#E07B39")
C_YELLOW  = colors.HexColor("#F5C842")
C_LIME    = colors.HexColor("#4CAF7D")
C_RED     = colors.HexColor("#C0392B")
C_PURPLE  = colors.HexColor("#6C3483")
C_BLUE    = colors.HexColor("#2E86C1")
C_CREAM   = colors.HexColor("#FDFBF5")
C_LTBLUE  = colors.HexColor("#D6EAF8")
C_LTGREEN = colors.HexColor("#D5F5E3")
C_LTYELL  = colors.HexColor("#FEF9E7")
C_LTORG   = colors.HexColor("#FDEBD0")
C_LTRED   = colors.HexColor("#FDEDEC")
C_LTPUR   = colors.HexColor("#F4ECF7")
C_LTTEAL  = colors.HexColor("#D1F2EB")
C_GREY    = colors.HexColor("#F2F3F4")
C_DKGREY  = colors.HexColor("#566573")
WHITE     = colors.white
BLACK     = colors.HexColor("#1C1C1C")

W, H = A4  # 595 x 842 pts

# ── Helper Flowable: Flowchart Drawing ────────────────────────────────────────
class FlowchartFlowable(Flowable):
    """Custom flowable wrapping a ReportLab Drawing."""
    def __init__(self, drawing):
        super().__init__()
        self.drawing = drawing
        self.width = drawing.width
        self.height = drawing.height

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

    def wrap(self, aW, aH):
        return self.width, self.height


# ── Drawing helpers ────────────────────────────────────────────────────────────
def box(d, x, y, w, h, fill, text, font="Helvetica-Bold", fsize=8,
        text_color=WHITE, radius=6, border=None):
    """Draw a rounded rectangle with centred text."""
    r = Rect(x, y, w, h, rx=radius, ry=radius,
             fillColor=fill, strokeColor=border or C_NAVY, strokeWidth=0.8)
    d.add(r)
    # Split text into lines
    lines = text.split("\n")
    lh = fsize + 2
    total = len(lines) * lh
    start_y = y + h/2 + total/2 - fsize
    for i, line in enumerate(lines):
        s = String(x + w/2, start_y - i*lh, line,
                   fontName=font, fontSize=fsize,
                   fillColor=text_color, textAnchor="middle")
        d.add(s)


def diamond(d, cx, cy, w, h, fill, text, fsize=7.5, text_color=WHITE):
    """Draw a diamond shape with centred text."""
    hw, hh = w/2, h/2
    pts = [cx, cy+hh, cx+hw, cy, cx, cy-hh, cx-hw, cy]
    p = Polygon(pts, fillColor=fill, strokeColor=C_NAVY, strokeWidth=0.8)
    d.add(p)
    lines = text.split("\n")
    lh = fsize + 2
    total = len(lines) * lh
    start_y = cy + total/2 - fsize + 2
    for i, line in enumerate(lines):
        s = String(cx, start_y - i*lh, line,
                   fontName="Helvetica-Bold", fontSize=fsize,
                   fillColor=text_color, textAnchor="middle")
        d.add(s)


def arrow_down(d, x, y, length=22, color=C_NAVY):
    """Draw a downward arrow."""
    d.add(Line(x, y, x, y-length+6, strokeColor=color, strokeWidth=1.2))
    tip = [x, y-length, x-5, y-length+8, x+5, y-length+8]
    d.add(Polygon(tip, fillColor=color, strokeColor=color, strokeWidth=0.5))


def arrow_right(d, x, y, length=30, color=C_NAVY):
    d.add(Line(x, y, x+length-6, y, strokeColor=color, strokeWidth=1.2))
    tip = [x+length, y, x+length-8, y+5, x+length-8, y-5]
    d.add(Polygon(tip, fillColor=color, strokeColor=color, strokeWidth=0.5))


def arrow_left(d, x, y, length=30, color=C_NAVY):
    d.add(Line(x, y, x-length+6, y, strokeColor=color, strokeWidth=1.2))
    tip = [x-length, y, x-length+8, y+5, x-length+8, y-5]
    d.add(Polygon(tip, fillColor=color, strokeColor=color, strokeWidth=0.5))


def label(d, x, y, text, fsize=7, color=C_DKGREY, anchor="middle"):
    d.add(String(x, y, text, fontName="Helvetica", fontSize=fsize,
                 fillColor=color, textAnchor=anchor))


def title_box(d, dw, text, y, bg=C_NAVY):
    """Full-width title bar."""
    r = Rect(0, y, dw, 24, rx=0, ry=0, fillColor=bg, strokeColor=None, strokeWidth=0)
    d.add(r)
    d.add(String(dw/2, y+8, text, fontName="Helvetica-Bold", fontSize=11,
                 fillColor=WHITE, textAnchor="middle"))


# ═══════════════════════════════════════════════════════════════════════════════
#  FLOWCHART BUILDERS
# ═══════════════════════════════════════════════════════════════════════════════

def fc_oxy_hb(dw=520):
    """OxyHb Dissociation Curve – factors flowchart."""
    dh = 420
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "1. Oxy-Haemoglobin Dissociation Curve – Factors & 2,3-BPG", dh-26)

    # Central node
    cx = dw/2
    box(d, cx-80, dh-100, 160, 36, C_TEAL, "S-shaped (Sigmoid) Curve\nP50 = 26 mmHg", fsize=8)

    # Two branches
    # LEFT: Right shift
    box(d, 20, dh-170, 140, 30, C_RED, "RIGHT SHIFT\n(↓ O2 affinity)", fsize=8)
    arrow_left(d, cx-80, dh-82, 70)
    label(d, 90, dh-152, "↑CO2, ↑H+, ↑Temp", fsize=7, color=C_RED, anchor="middle")
    label(d, 90, dh-162, "↑2,3-BPG, Exercise", fsize=7, color=C_RED, anchor="middle")

    # RIGHT: Left shift
    box(d, dw-160, dh-170, 140, 30, C_BLUE, "LEFT SHIFT\n(↑ O2 affinity)", fsize=8)
    arrow_right(d, cx+80, dh-82, 70)
    label(d, dw-90, dh-152, "↓CO2, ↓Temp, Alkalosis", fsize=7, color=C_BLUE, anchor="middle")
    label(d, dw-90, dh-162, "HbF, CO poisoning", fsize=7, color=C_BLUE, anchor="middle")

    # 2,3-BPG section
    arrow_down(d, cx, dh-100, 28)
    box(d, cx-100, dh-160, 200, 30, C_ORANGE,
        "2,3-BPG – produced in RBCs (glycolysis)", fsize=8)
    arrow_down(d, cx, dh-160, 28)
    box(d, cx-110, dh-218, 220, 32, C_LIME,
        "Binds β-chains of deoxy-Hb → T-state\n→ Right shift → More O2 to tissues", fsize=8)
    arrow_down(d, cx, dh-218, 26)
    box(d, cx-120, dh-274, 240, 32, C_YELLOW,
        "2,3-BPG ↑ in: High altitude, Anaemia\nChronic hypoxia, Hyperthyroidism", fsize=8, text_color=BLACK)
    arrow_down(d, cx, dh-274, 26)
    box(d, cx-115, dh-330, 230, 32, C_PURPLE,
        "Stored blood: low 2,3-BPG\n→ ↑ O2 affinity → less O2 delivery", fsize=8)

    # Bohr legend
    box(d, 20, 20, 200, 30, C_LTBLUE,
        "Bohr Effect: CO2/H+ → Right shift\n(O2 unloading in active tissues)",
        fsize=7.5, text_color=C_NAVY, border=C_BLUE)
    box(d, dw-220, 20, 200, 30, C_LTYELL,
        "HbF P50 ~20 mmHg (left) – high affinity\nAdult HbA P50 ~26 mmHg",
        fsize=7.5, text_color=C_NAVY, border=C_ORANGE)
    return d


def fc_hering_breuer(dw=520):
    dh = 310
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "2. Hering-Breuer Reflex", dh-26)
    steps = [
        (C_TEAL,   "Lung OVER-INFLATION\n(Tidal Vol > 1.5 L)"),
        (C_BLUE,   "Slowly Adapting Stretch Receptors\n(bronchi/bronchioles smooth muscle) FIRE"),
        (C_ORANGE, "Signals travel via VAGUS (CN X)\nto Dorsal Respiratory Group (DRG)"),
        (C_RED,    "Inspiratory RAMP inhibited\nInspiration SWITCHED OFF"),
        (C_LIME,   "Expiration begins (passive)\nPrevents over-inflation"),
    ]
    y = dh-66
    for i, (col, txt) in enumerate(steps):
        box(d, dw//2-140, y, 280, 34, col, txt, fsize=8)
        if i < len(steps)-1:
            arrow_down(d, dw//2, y, 20)
            y -= 54
    # Note
    box(d, 10, 10, 500, 24, C_GREY,
        "In humans: activated only when TV > 3x normal (~1.5L) – PROTECTIVE, not normal rhythm control. Vagotomy → slow deep breathing.",
        fsize=7, text_color=C_DKGREY, border=C_DKGREY)
    return d


def fc_bohr_haldane(dw=520):
    dh = 380
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "3 & 4. Bohr Effect & Haldane Effect", dh-26)

    # BOHR – left column
    bx = 20
    box(d, bx, dh-70, 230, 28, C_NAVY, "BOHR EFFECT", fsize=9)
    steps_b = [
        (C_TEAL,   "Active tissues produce\n↑CO2 + ↑H+"),
        (C_BLUE,   "CO2 → H2CO3 → H+ + HCO3-\nH+ binds His residues on Hb"),
        (C_ORANGE, "Hb changes T→R state\n(allosteric change)"),
        (C_RED,    "O2 AFFINITY ↓\n→ Curve shifts RIGHT"),
        (C_LIME,   "More O2 UNLOADED\nto active tissues"),
    ]
    y = dh-104
    for i, (col, txt) in enumerate(steps_b):
        box(d, bx, y, 230, 30, col, txt, fsize=7.5)
        if i < len(steps_b)-1:
            arrow_down(d, bx+115, y, 16)
            y -= 46

    # HALDANE – right column
    hx = dw-250
    box(d, hx, dh-70, 230, 28, C_PURPLE, "HALDANE EFFECT", fsize=9)
    steps_h = [
        (C_PURPLE, "O2 binds Hb in LUNGS\n(oxygenation)"),
        (C_BLUE,   "OxyHb = stronger acid\n→ releases H+"),
        (C_ORANGE, "H+ + HCO3- → H2CO3\n→ CO2 + H2O"),
        (C_RED,    "CO2 expelled from RBC\nand exhaled"),
        (C_TEAL,   "Accounts for ~50% CO2\ntransport from tissues"),
    ]
    y = dh-104
    for i, (col, txt) in enumerate(steps_h):
        box(d, hx, y, 230, 30, col, txt, fsize=7.5)
        if i < len(steps_h)-1:
            arrow_down(d, hx+115, y, 16)
            y -= 46

    # Dividing line
    d.add(Line(dw//2, dh-36, dw//2, 10, strokeColor=C_DKGREY,
               strokeWidth=0.6, strokeDashArray=[3,3]))
    label(d, dw//2, 12, "Synergistic effects for efficient O2/CO2 exchange",
          fsize=7.5, color=C_TEAL, anchor="middle")
    return d


def fc_p50(dw=520):
    dh = 240
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "5. P50 – Definition & Clinical Significance", dh-26)

    box(d, dw//2-130, dh-72, 260, 30, C_NAVY,
        "P50 = PO2 at which Hb is 50% saturated\nNormal = 26 mmHg (pH 7.4, 37°C, PCO2 40 mmHg)", fsize=8)
    arrow_down(d, dw//2, dh-72, 22)

    # Two arms
    box(d, 20, dh-150, 210, 50, C_RED,
        "HIGH P50 (>26 mmHg)\nLow O2 affinity – RIGHT SHIFT\nMore O2 released to tissues\nCauses: acidosis, fever,\nhigh altitude (acclimatised), anaemia", fsize=7.5)
    arrow_left(d, dw//2-130, dh-58, 90)

    box(d, dw-230, dh-150, 210, 50, C_BLUE,
        "LOW P50 (<26 mmHg)\nHigh O2 affinity – LEFT SHIFT\nLess O2 released\nCauses: HbF (P50~20), CO,\nalkalosis, stored blood", fsize=7.5)
    arrow_right(d, dw//2+130, dh-58, 90)

    box(d, dw//2-160, 20, 320, 28, C_LTTEAL,
        "Clinical: Banked blood has low 2,3-BPG → ↓P50 → less O2 delivery to tissues (transfusion concern)",
        fsize=7.5, text_color=C_NAVY, border=C_TEAL)
    return d


def fc_pulm_circ(dw=520):
    dh = 400
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "6. Characteristics of Pulmonary Circulation", dh-26)

    features = [
        (C_BLUE,   "LOW PRESSURE\n25/8 mmHg (mean 15 mmHg)\nvs systemic 120/80 mmHg"),
        (C_TEAL,   "LOW RESISTANCE\nThin walls (~1/3 aorta)\nHuge compliance"),
        (C_ORANGE, "HYPOXIC VASOCONSTRICTION\nLow alveolar O2 → vasoconstrict\n(OPPOSITE to systemic)"),
        (C_RED,    "WEST'S 3 ZONES\nZone 1: PA>Pa>Pv (apex, no flow)\nZone 2: Pa>PA>Pv (mid)\nZone 3: Pa>Pv>PA (base, most flow)"),
        (C_PURPLE, "BLOOD FLOW DISTRIBUTION\nBase > Apex (gravity)\nVentilation also ↑ base but less\n→ V/Q highest at apex"),
        (C_LIME,   "BRONCHIAL vs PULMONARY\nBronchial: oxygenate lung tissue\nPulmonary: gas exchange\nPCWP = 6-12 mmHg"),
    ]

    col_w = (dw-40) // 2 - 5
    positions = [
        (20, dh-90), (dw//2+10, dh-90),
        (20, dh-200), (dw//2+10, dh-200),
        (20, dh-310), (dw//2+10, dh-310),
    ]
    for (col, txt), (fx, fy) in zip(features, positions):
        box(d, fx, fy, col_w, 80, col, txt, fsize=7.5)

    # Bottom note
    box(d, 10, 10, dw-20, 24, C_GREY,
        "HPV (Hypoxic Pulmonary Vasoconstriction): diverts blood from poorly ventilated → well ventilated alveoli → improves V/Q matching",
        fsize=7, text_color=C_DKGREY, border=C_DKGREY)
    return d


def fc_altitude(dw=520):
    dh = 480
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "7. Acclimatisation to High Altitude", dh-26)

    cx = dw//2
    # Trigger
    box(d, cx-100, dh-66, 200, 28, C_NAVY, "ASCENT TO HIGH ALTITUDE\n↓ Atmospheric PO2", fsize=8)
    arrow_down(d, cx, dh-66, 22)
    box(d, cx-90, dh-122, 180, 26, C_RED, "HYPOXIA – ↓ PaO2", fsize=8)
    arrow_down(d, cx, dh-122, 22)

    # Split into 3 phases
    phases = [
        (20,       "IMMEDIATE (minutes-hours)",   C_ORANGE,
         "↑Ventilation (hyperventilation)\nRespiratory alkalosis (↓PCO2)\npH rises → limits further ↑VA"),
        (dw//2-90, "SHORT-TERM (days)",            C_TEAL,
         "Kidneys excrete HCO3-\n→ pH normalises\nVA increases further (400%)\n↑2,3-BPG → right shift"),
        (dw-200,   "LONG-TERM (weeks)",            C_BLUE,
         "EPO → Polycythaemia\n↑RBC, ↑Hb\n↑Capillary density\n↑Myoglobin in muscles"),
    ]
    bw = (dw-40)//3 - 4
    for px, ptitle, pcol, ptext in phases:
        box(d, px, dh-180, bw, 22, pcol, ptitle, fsize=7.5)
        box(d, px, dh-290, bw, 90, pcol, ptext, fsize=7, border=pcol)
        # Connect arrow from trigger to phase title
        d.add(Line(cx, dh-144, px+bw//2, dh-180,
                   strokeColor=C_DKGREY, strokeWidth=0.8))

    # AMS section
    arrow_down(d, cx, dh-300, 22)
    box(d, cx-150, dh-354, 300, 26, C_RED,
        "RAPID ASCENT → ACUTE MOUNTAIN SICKNESS (AMS)", fsize=8)
    arrow_down(d, cx, dh-354, 20)

    # HACE / HAPE
    box(d, 20, dh-430, 225, 56, C_ORANGE,
        "HACE (Cerebral Oedema)\nVasodilation → ↑ICP\nHeadache, ataxia, confusion\nTx: Descent, Dexamethasone, O2", fsize=7.5)
    box(d, dw-245, dh-430, 225, 56, C_PURPLE,
        "HAPE (Pulmonary Oedema)\nUneven HPV → capillary stress\nFrothy sputum, crackles\nTx: Descent, Nifedipine, O2", fsize=7.5)
    arrow_left(d, cx-150, dh-388, 80)
    arrow_right(d, cx+150, dh-388, 75)

    box(d, 10, 10, dw-20, 24, C_LTYELL,
        "Acetazolamide (carbonic anhydrase inhibitor): causes metabolic acidosis → stimulates breathing → prophylaxis/treatment",
        fsize=7, text_color=BLACK, border=C_ORANGE)
    return d


def fc_chemoreceptors(dw=520):
    dh = 380
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "8. Peripheral Chemoreceptors – Characteristics & Functions", dh-26)

    # Two bodies
    box(d, 20, dh-100, 220, 62, C_TEAL,
        "CAROTID BODIES (main)\nBifurcation of common carotid\nNerve: CN IX (Hering's nerve)\nType I (glomus) + Type II cells", fsize=7.5)
    box(d, dw-240, dh-100, 220, 62, C_BLUE,
        "AORTIC BODIES (minor)\nAround aortic arch\nNerve: CN X (vagus)\nLess important than carotid", fsize=7.5)

    arrow_down(d, 130, dh-100, 24)
    arrow_down(d, dw-130, dh-100, 24)

    box(d, dw//2-130, dh-154, 260, 26, C_ORANGE,
        "Impulses → DORSAL RESPIRATORY GROUP (DRG)", fsize=8)

    # Stimuli
    stims = [
        (C_RED,    "↓ PaO2 < 60 mmHg\n(PRIMARY stimulus)"),
        (C_ORANGE, "↑ PaCO2\n(synergistic with O2)"),
        (C_PURPLE, "↓ pH (↑ H+)\nMetabolic acidosis"),
        (C_BLUE,   "↓ Blood pressure\n(baroreceptors nearby)"),
    ]
    sw = (dw-40)//4 - 3
    sx = 20
    arrow_down(d, dw//2, dh-180, 22)
    box(d, dw//2-80, dh-224, 160, 22, C_NAVY, "STIMULI (in order of potency)", fsize=8)
    for col, txt in stims:
        box(d, sx, dh-310, sw, 62, col, txt, fsize=7.5)
        sx += sw + 4

    # Key facts
    box(d, 10, dh-366, dw-20, 38, C_GREY,
        "Key: Blood flow ~2000 mL/100g/min → O2 content NOT sensed (only PO2)\n"
        "Anaemia & CO poisoning: PO2 normal → chemoreceptors NOT activated\n"
        "Critical in acclimatisation (central receptors adapt, peripheral maintain drive)",
        fsize=7, text_color=C_DKGREY, border=C_DKGREY)
    return d


def fc_hypoxia(dw=520):
    dh = 420
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "10. Hypoxia – Classification & Hypoxic Hypoxia", dh-26)

    box(d, dw//2-100, dh-66, 200, 28, C_NAVY, "HYPOXIA\nDeficient O2 at tissue level", fsize=8)
    arrow_down(d, dw//2, dh-66, 20)
    box(d, dw//2-110, dh-110, 220, 24, C_DKGREY, "4 TYPES", fsize=8)

    types = [
        (20,        C_RED,    "HYPOXIC\n(Anoxic)",
         "↓PaO2\nNormal capacity\nHigh altitude,\nlung disease,\nV/Q mismatch"),
        (145,       C_ORANGE, "ANAEMIC",
         "Normal PaO2\n↓O2 capacity\nAnaemia, CO\npoisoning"),
        (270,       C_PURPLE, "STAGNANT\n(Ischaemic)",
         "Normal PaO2\nNormal capacity\n↓Perfusion\nHeart failure,\nshock"),
        (395,       C_BLUE,   "HISTOTOXIC",
         "Normal PaO2\nNormal capacity\nNormal perfusion\nCyanide blocks\ncytochrome oxidase"),
    ]
    tw = 115
    for tx, col, title, body in types:
        box(d, tx, dh-160, tw, 22, col, title, fsize=7.5)
        box(d, tx, dh-260, tw, 80, col, body, fsize=7, border=col)

    # Hypoxic hypoxia expanded
    arrow_down(d, 77, dh-260, 22)
    box(d, 10, dh-320, 500, 28, C_RED,
        "HYPOXIC HYPOXIA – CAUSES IN DETAIL", fsize=8)

    causes = [
        (C_LTRED, "Low Inspired PO2\nHigh altitude\nConfined space"),
        (C_LTORG, "Hypoventilation\nCNS depression\nMuscle paralysis\nAirway obstruction"),
        (C_LTBLUE, "Diffusion Impairment\nFibrosis, ARDS\nPulmonary oedema"),
        (C_LTPUR, "V/Q Mismatch\nPneumonia,\nAtelectasis, PE"),
        (C_LTGREEN, "R→L Shunt\nCyanotic CHD\nLung AV shunts"),
    ]
    cw = (dw-20)//5 - 3
    cx2 = 10
    for col, txt in causes:
        box(d, cx2, dh-390, cw, 52, col, txt, fsize=7, text_color=BLACK, border=C_RED)
        cx2 += cw + 4

    box(d, 10, 10, dw-20, 22, C_LTYELL,
        "Cyanosis in hypoxic hypoxia: visible (deoxyHb ↑). In anaemic hypoxia: may be ABSENT (insufficient total Hb for 5g/dL deoxyHb)",
        fsize=7, text_color=BLACK, border=C_ORANGE)
    return d


def fc_surfactant(dw=520):
    dh = 390
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "11. Surfactant – Functions & RDS", dh-26)

    # Source
    box(d, dw//2-120, dh-70, 240, 28, C_TEAL,
        "TYPE II PNEUMOCYTES\n(Alveolar epithelial cells)", fsize=8)
    arrow_down(d, dw//2, dh-70, 20)
    box(d, dw//2-140, dh-122, 280, 26, C_BLUE,
        "Composition: ~90% lipid (DPPC*) + 10% protein (SP-A,B,C,D)", fsize=8)
    arrow_down(d, dw//2, dh-122, 20)
    box(d, dw//2-70, dh-166, 140, 22, C_NAVY, "PRODUCTION: 24-26 wks\nAdequate: 32-34 wks", fsize=7.5)

    # Functions
    funcs = [
        (C_LIME,   "Reduces surface tension\n~70 → 2-5 mN/m"),
        (C_TEAL,   "Prevents alveolar\ncollapse at expiration"),
        (C_BLUE,   "Stabilises alveoli\n(Laplace: P=2T/r)\nSmaller → less tension"),
        (C_ORANGE, "Keeps alveoli DRY\n↓ fluid transudation"),
        (C_PURPLE, "Immune function\nSP-A, SP-D are opsonins"),
    ]
    fw = (dw-30)//5 - 2
    fx = 15
    box(d, 15, dh-222, dw-30, 20, C_DKGREY, "FUNCTIONS", fsize=8)
    for col, txt in funcs:
        box(d, fx, dh-300, fw, 58, col, txt, fsize=7.5)
        fx += fw + 3

    # RDS
    arrow_down(d, dw//2, dh-300, 18)
    box(d, dw//2-140, dh-342, 280, 22, C_RED,
        "DEFICIENCY → RDS / HYALINE MEMBRANE DISEASE", fsize=8)
    arrow_down(d, dw//2, dh-342, 18)

    box(d, 10, 10, dw//2-15, 62, C_LTRED,
        "PATHOPHYSIOLOGY\nNo surfactant → alveoli collapse\nHypoxia → injures type II cells\nProtein leak → hyaline membranes\nVicious cycle ↓↓surfactant",
        fsize=7.5, text_color=BLACK, border=C_RED)
    box(d, dw//2+5, 10, dw//2-15, 62, C_LTGREEN,
        "TREATMENT\nAntenatal: Betamethasone (mother)\nPostnatal: Exogenous surfactant\nCPAP / Mechanical ventilation\nSupportive O2",
        fsize=7.5, text_color=BLACK, border=C_LIME)
    label(d, 10, 74, "*DPPC = Dipalmitoylphosphatidylcholine", fsize=6.5, color=C_DKGREY, anchor="start")
    return d


def fc_lung_volumes(dw=520):
    dh = 360
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "18. Lung Volumes & Capacities", dh-26)

    vols = [
        ("TV",  "Tidal Volume",                  "500 mL",  "Normal breath",          C_BLUE),
        ("IRV", "Inspiratory Reserve Vol.",       "3000 mL", "Extra inspired above TV", C_TEAL),
        ("ERV", "Expiratory Reserve Vol.",        "1100 mL", "Extra expired below TV",  C_ORANGE),
        ("RV",  "Residual Volume",                "1200 mL", "After max expiration",    C_RED),
    ]
    caps = [
        ("IC",  "Inspiratory Capacity",  "TV+IRV=3500 mL", "Max air from resting",    C_LTBLUE),
        ("FRC", "Functional Residual\nCapacity",  "ERV+RV=2300 mL","Resting lung vol; O2 buffer",C_LTYELL),
        ("VC",  "Vital Capacity",        "IRV+TV+ERV=4600 mL","Max breath in → out",    C_LTGREEN),
        ("TLC", "Total Lung Capacity",   "All 4=5800 mL",  "Max inspiration",         C_LTORG),
    ]
    table_data = [["Abbr", "Name", "Value", "Significance"]]
    ts_vol = [("VOL", v[0], v[1], v[2], v[3], v[4]) for v in vols]
    ts_cap = [("CAP", c[0], c[1], c[2], c[3], c[4]) for c in caps]

    # Draw as visual bars
    bar_y = dh-74
    bar_h = 18
    bar_x = 10
    max_w = dw-20
    max_vol = 5800
    for abbr, name, val, sig, col in vols:
        v = int(val.split()[0].replace(",",""))
        bw = int(v / max_vol * max_w)
        box(d, bar_x, bar_y, bw, bar_h, col, f"{abbr}: {name} = {val}", fsize=7.5)
        bar_y -= bar_h + 4

    bar_y -= 10
    box(d, bar_x, bar_y, max_w, bar_h-2, C_DKGREY, "CAPACITIES (= 2+ volumes)", fsize=8)
    bar_y -= bar_h + 2
    for abbr, name, val, sig, col in caps:
        v_str = val.split("=")[-1].strip().split()[0].replace(",","")
        v = int(v_str)
        bw = int(v / max_vol * max_w)
        box(d, bar_x, bar_y, bw, bar_h, col, f"{abbr}={val} – {sig}",
            fsize=7, text_color=BLACK, border=C_DKGREY)
        bar_y -= bar_h + 4

    box(d, 10, 10, dw-20, 28, C_LTRED,
        "RV, FRC, TLC cannot be measured by spirometry alone.\nRequire: Helium dilution OR Body plethysmography (air trapping)",
        fsize=7.5, text_color=BLACK, border=C_RED)
    return d


def fc_vq_ratio(dw=520):
    dh = 380
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "19. Ventilation-Perfusion (V/Q) Ratio", dh-26)

    box(d, dw//2-100, dh-72, 200, 30, C_NAVY,
        "Normal V/Q = 0.8\nVA=4 L/min ÷ Q=5 L/min", fsize=8)
    arrow_down(d, dw//2, dh-72, 22)

    box(d, 20, dh-140, 225, 42, C_TEAL,
        "APEX of lung\nV/Q = ~3.3 (high)\n↑PO2, ↑PCO2 lower\nIdeal for TB organisms", fsize=7.5)
    box(d, dw-245, dh-140, 225, 42, C_ORANGE,
        "BASE of lung\nV/Q = ~0.63 (low)\n↓PO2, more blood flow\nMost gas exchange here", fsize=7.5)
    arrow_left(d, dw//2-100, dh-90, 80)
    arrow_right(d, dw//2+100, dh-90, 75)

    # Abnormalities
    arrow_down(d, dw//2, dh-120, 22)
    box(d, dw//2-100, dh-164, 200, 22, C_RED, "V/Q ABNORMALITIES", fsize=8)

    abnorms = [
        (C_RED,    "DEAD SPACE\nV/Q → ∞\nVentilated, NOT perfused\nCause: Pulmonary embolism\nWasted ventilation"),
        (C_PURPLE, "SHUNT\nV/Q → 0\nPerfused, NOT ventilated\nCause: Pneumonia, Atelectasis\nVenous admixture → Hypoxia"),
        (C_BLUE,   "HPV (Response)\nHypoxic alveolus →\nvasoconstriction\nDiverts blood to\nventilated regions"),
    ]
    aw = (dw-30)//3 - 2
    ax = 15
    for col, txt in abnorms:
        box(d, ax, dh-300, aw, 110, col, txt, fsize=7.5)
        ax += aw + 4

    box(d, 10, dh-340, dw-20, 26, C_LTBLUE,
        "Mechanism of HPV: ↓alveolar O2 → inhibit K+ channels → depolarise smooth muscle → Ca2+ influx → vasoconstriction",
        fsize=7.5, text_color=BLACK, border=C_BLUE)
    box(d, 10, 10, dw-20, 22, C_LTYELL,
        "Shunt equation: Qs/Qt = (CcO2-CaO2) / (CcO2-CvO2). High flow O2 corrects V/Q mismatch but NOT true shunt.",
        fsize=7, text_color=BLACK, border=C_ORANGE)
    return d


def fc_neural_regulation(dw=520):
    dh = 500
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "LAQ 1. Neural Regulation of Respiration", dh-26)

    # Cortex
    box(d, dw//2-80, dh-66, 160, 24, C_DKGREY, "CEREBRAL CORTEX\n(Voluntary control)", fsize=8)
    arrow_down(d, dw//2, dh-66, 18)

    # Pons
    box(d, 20, dh-122, 220, 36, C_BLUE,
        "PNEUMOTAXIC CENTRE (Upper Pons)\nInhibits inspiration → ↓TV, ↑RR\nControls rate & depth", fsize=7.5)
    box(d, dw-240, dh-122, 220, 36, C_ORANGE,
        "APNEUSTIC CENTRE (Lower Pons)\nExcites DRG → sustains inspiration\nNormally overridden by pneumotaxic", fsize=7.5)

    # Medulla
    arrow_down(d, dw//2, dh-106, 18)
    box(d, dw//2-130, dh-162, 260, 22, C_NAVY, "MEDULLARY RESPIRATORY CENTRES", fsize=8)
    arrow_down(d, dw//2, dh-162, 18)

    box(d, 20, dh-226, 225, 46, C_TEAL,
        "DRG – Dorsal Respiratory Group\n(Nucleus Tractus Solitarius)\nInspiratory neurons\nRamp pattern firing\nReceives vagal afferents", fsize=7.5)
    box(d, dw-245, dh-226, 225, 46, C_RED,
        "VRG – Ventral Respiratory Group\n(Nucleus Ambiguus)\nInspiratory + Expiratory\nPre-Bötzinger complex =\nRHYTHM GENERATOR", fsize=7.5)

    arrow_down(d, dw//2, dh-240, 18)
    box(d, dw//2-100, dh-280, 200, 22, C_LIME, "MOTOR OUTPUT", fsize=8)
    arrow_down(d, dw//2, dh-280, 18)
    box(d, dw//2-110, dh-326, 220, 30, C_TEAL,
        "Phrenic nerve (C3,4,5)\n→ Diaphragm (60-75% TV)", fsize=8)
    box(d, 20, dh-326, 140, 30, C_BLUE,
        "Intercostal nerves\n→ Intercostals", fsize=8)
    box(d, dw-160, dh-326, 140, 30, C_ORANGE,
        "Accessory nerves\n→ SCM, Scalenes", fsize=8)

    # Reflexes
    arrow_down(d, dw//2, dh-356, 18)
    box(d, dw//2-110, dh-396, 220, 22, C_PURPLE, "REFLEX INPUTS TO CENTRES", fsize=8)
    refs = [
        (C_LTPUR, "Hering-Breuer\nStretch receptors\n→ CN X → DRG\nInhibit inspiration"),
        (C_LTBLUE, "J-Receptors\nAlveolar walls\nCap. congestion\n→ rapid shallow"),
        (C_LTGREEN, "Irritant Receptors\n(RAR) Dust, smoke\n→ Cough, bronchoconstriction"),
        (C_LTORG, "Proprioceptors\nJoints, muscles\n→ Exercise\nhyperventilation"),
    ]
    rw = (dw-30)//4 - 2
    rx = 15
    for col, txt in refs:
        box(d, rx, dh-462, rw, 52, col, txt, fsize=7, text_color=BLACK, border=C_PURPLE)
        rx += rw + 3

    box(d, 10, 10, dw-20, 22, C_LTYELL,
        "Inspiratory RAMP: DRG fires with gradually ↑ frequency over 2 sec → smooth diaphragm contraction (not abrupt)",
        fsize=7, text_color=BLACK, border=C_ORANGE)
    return d


def fc_chemical_control(dw=520):
    dh = 450
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "LAQ 2. Chemical Control of Respiration", dh-26)

    box(d, dw//2-120, dh-66, 240, 26, C_NAVY,
        "GOAL: Maintain PaO2, PaCO2, pH\nTWO sensor systems", fsize=8)

    # Central
    bx = 15
    box(d, bx, dh-110, 235, 22, C_BLUE, "CENTRAL CHEMORECEPTORS", fsize=8)
    steps_c = [
        (C_BLUE,   "Location: Retrotrapezoid nucleus\nVentrolateral medulla (0.2mm deep)"),
        (C_TEAL,   "Bathed in CSF & brain ECF\nNOT in blood directly"),
        (C_ORANGE, "Primary stimulus: H+ in CSF\n(not directly CO2)"),
        (C_RED,    "CO2 freely crosses BBB\n→ CO2 + H2O → H+ (in CSF)\n→ stimulates neurons"),
        (C_PURPLE, "Blood H+ does NOT cross BBB well\n→ less potent acute stimulant"),
        (C_LIME,   "Adaptation in 1-2 days:\nKidneys excrete HCO3-\n→ pH normalises → drive ↓"),
    ]
    y = dh-142
    for col, txt in steps_c:
        box(d, bx, y, 235, 32, col, txt, fsize=7)
        if y > 60:
            arrow_down(d, bx+117, y, 12)
        y -= 44

    # Peripheral
    px = dw-250
    box(d, px, dh-110, 235, 22, C_RED, "PERIPHERAL CHEMORECEPTORS", fsize=8)
    steps_p = [
        (C_RED,    "Location: Carotid bodies (main)\nAortic bodies (minor)"),
        (C_ORANGE, "Respond to ↓PaO2 < 60 mmHg\n(primary stimulus)"),
        (C_TEAL,   "Also: ↑PCO2, ↓pH\n(synergistic with O2)"),
        (C_BLUE,   "COPD adaptation: central receptors\ndesensitise → O2 = main drive"),
        (C_PURPLE, "HIGH-FLOW O2 in COPD:\nSuppresses hypoxic drive\n→ ↑PCO2 (danger!)"),
        (C_LIME,   "Bilateral carotid removal:\n→ blunted hypoxic ventilatory response"),
    ]
    y = dh-142
    for col, txt in steps_p:
        box(d, px, y, 235, 32, col, txt, fsize=7)
        if y > 60:
            arrow_down(d, px+117, y, 12)
        y -= 44

    d.add(Line(dw//2, dh-36, dw//2, 40,
               strokeColor=C_DKGREY, strokeWidth=0.6, strokeDashArray=[4,3]))
    box(d, 10, 10, dw-20, 24, C_LTTEAL,
        "CO2 response: VA ↑ 2L/min per 1 mmHg ↑PCO2. O2 response: Little change until PaO2 <60 mmHg, then steep. Effects SYNERGISTIC.",
        fsize=7, text_color=BLACK, border=C_TEAL)
    return d


def fc_compliance(dw=520):
    dh = 420
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "LAQ 3. Lung Compliance – Factors & HMD", dh-26)

    box(d, dw//2-130, dh-68, 260, 28, C_NAVY,
        "LUNG COMPLIANCE = ΔVolume / ΔPressure\nNormal = 200 mL/cmH2O", fsize=8)
    arrow_down(d, dw//2, dh-68, 20)

    box(d, 20, dh-132, 225, 38, C_TEAL,
        "Surface tension of alveolar fluid\n= 2/3 of lung compliance\nSurfactant essential to reduce it", fsize=7.5)
    box(d, dw-245, dh-132, 225, 38, C_BLUE,
        "Elastic recoil of lung tissue\n(collagen + elastin) = 1/3\nDestroyed in emphysema → ↑compliance", fsize=7.5)

    arrow_down(d, dw//2, dh-130, 20)
    box(d, dw//2-80, dh-174, 160, 22, C_ORANGE, "FACTORS AFFECTING", fsize=8)

    dec = [
        "Pulmonary fibrosis\n(↑collagen, stiff)",
        "Pulmonary oedema\n(fluid in interstitium)",
        "ARDS\n(diffuse lung injury)",
        "Surfactant deficiency\n(HMD/RDS)",
        "Atelectasis\n(collapsed alveoli)",
        "Obesity / Pregnancy\n(↑abdominal pressure)",
    ]
    inc = [
        "Emphysema\n(elastic tissue destroyed)",
        "Advancing age\n(loss of elastin)",
    ]

    dw2 = (dw//2-25)//3 - 3
    x2 = 10
    box(d, 10, dh-204, dw//2-20, 18, C_RED, "DECREASED COMPLIANCE (Restrictive)", fsize=7.5)
    for txt in dec:
        box(d, x2, dh-278, dw2, 56, C_LTRED, txt, fsize=7, text_color=BLACK, border=C_RED)
        x2 += dw2 + 3

    iw = (dw//2-25)//2 - 3
    ix = dw//2+10
    box(d, dw//2+10, dh-204, dw//2-20, 18, C_LIME, "INCREASED COMPLIANCE (Obstructive)", fsize=7.5)
    for txt in inc:
        box(d, ix, dh-278, iw, 56, C_LTGREEN, txt, fsize=7.5, text_color=BLACK, border=C_LIME)
        ix += iw + 4

    # HMD
    arrow_down(d, dw//2, dh-278, 20)
    box(d, dw//2-140, dh-322, 280, 22, C_RED, "HYALINE MEMBRANE DISEASE (HMD/RDS)", fsize=8)

    box(d, 10, dh-396, dw//2-15, 58, C_LTRED,
        "PATHOLOGY\nPreterm (<32 wks) – immature type II cells\nNo surfactant → alveolar collapse\nEosinophilic hyaline membranes\nVicious cycle: hypoxia → less surfactant",
        fsize=7.5, text_color=BLACK, border=C_RED)
    box(d, dw//2+5, dh-396, dw//2-15, 58, C_LTGREEN,
        "TREATMENT\nAntenatal: Betamethasone to mother\n(24-34 wks, most effective)\nPostnatal: Exogenous surfactant\n(intratracheal); CPAP/ventilation",
        fsize=7.5, text_color=BLACK, border=C_LIME)

    box(d, 10, 10, dw-20, 24, C_LTYELL,
        "Laplace Law: P=2T/r. Smaller alveolus → higher P → collapses into larger one WITHOUT surfactant. Surfactant ↓T as r↓, equalising pressure.",
        fsize=7, text_color=BLACK, border=C_ORANGE)
    return d


def fc_resp_membrane(dw=520):
    dh = 440
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "LAQ 4. Respiratory Membrane – Gaseous Exchange & CO Method", dh-26)

    # Layers
    layers = [
        (C_LTYELL,  "1. Surfactant layer (phospholipid + hypophase)"),
        (C_LTBLUE,  "2. Type I Pneumocyte (alveolar epithelium) – 0.1-0.2 μm thick"),
        (C_LTGREEN, "3. Epithelial basement membrane"),
        (C_LTORG,   "4. Interstitial space (collagen, fibroblasts)"),
        (C_LTPUR,   "5. Capillary basement membrane"),
        (C_LTRED,   "6. Capillary endothelium"),
        (C_LTTEAL,  "7. Plasma layer"),
        (C_LTBLUE,  "8. RBC membrane + Hb (final destination)"),
    ]
    lw = (dw-30)//2 - 5
    box(d, 15, dh-56, lw, 20, C_NAVY, "8 LAYERS (Alveolus → Capillary)", fsize=8)
    ly = dh-82
    for col, txt in layers:
        box(d, 15, ly, lw, 20, col, txt, fsize=7, text_color=BLACK, border=C_DKGREY)
        ly -= 22
    label(d, 15+lw//2, ly+4, "Total thickness: ~0.5 μm | Surface area: ~70 m²", fsize=7.5, color=C_TEAL, anchor="middle")

    # Fick's Law
    px = dw//2+10
    box(d, px, dh-56, dw//2-20, 20, C_PURPLE, "FICK'S LAW OF DIFFUSION", fsize=8)
    box(d, px, dh-100, dw//2-20, 36, C_LTPUR,
        "Rate ∝ (Area × ΔP × Solubility)\n÷ (Thickness × √Mol.Weight)",
        fsize=8, text_color=BLACK, border=C_PURPLE)

    facts = [
        (C_BLUE,   "O2: ΔP=60mmHg, Perfusion-limited"),
        (C_RED,    "CO2: 20x more soluble, ΔP=6mmHg\nDiffuses 20x faster"),
        (C_ORANGE, "Surface area ↓: Emphysema (wall destruction)\nPneumonectomy, Atelectasis"),
        (C_TEAL,   "Thickness ↑: Fibrosis, Pulmonary oedema\nARDS, Pneumonia"),
    ]
    fy = dh-146
    for col, txt in facts:
        box(d, px, fy, dw//2-20, 32, col, txt, fsize=7.5)
        fy -= 36

    # CO Method
    arrow_down(d, dw//2, dh-290, 18)
    box(d, dw//2-100, dh-332, 200, 20, C_NAVY, "CO METHOD (DLCO)", fsize=8)
    arrow_down(d, dw//2, dh-332, 18)
    steps_co = [
        (C_BLUE,   "Inhale 0.3% CO for 10 sec"),
        (C_TEAL,   "CO binds Hb 200x > O2\n→ back-pressure ≈ 0"),
        (C_ORANGE, "CO is DIFFUSION-LIMITED\n(not perfusion-limited)"),
        (C_LIME,   "DLCO = VCO ÷ (PACO - PcCO)\nNormal ~25 mL/min/mmHg"),
    ]
    cy = dh-372
    cx2 = dw//4-60
    for col, txt in steps_co:
        box(d, cx2, cy, 240, 28, col, txt, fsize=7.5)
        if cy > 60:
            arrow_down(d, cx2+120, cy, 12)
        cy -= 40

    box(d, 10, 10, dw-20, 22, C_LTYELL,
        "DLCO ↓ in: Emphysema, Fibrosis, ARDS, Anaemia, PE  |  DLCO ↑ in: Polycythaemia, Pulmonary haemorrhage",
        fsize=7, text_color=BLACK, border=C_ORANGE)
    return d


def fc_o2_transport(dw=520):
    dh = 400
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "LAQ 6. Transport of Oxygen", dh-26)

    box(d, dw//2-110, dh-70, 220, 26, C_NAVY,
        "O2 in blood: TWO FORMS\n~1000 mL/min delivered at rest", fsize=8)

    # Two arms
    box(d, 20, dh-130, 215, 28, C_BLUE,
        "DISSOLVED in plasma\n~1.5% of total", fsize=8)
    box(d, dw-235, dh-130, 215, 28, C_TEAL,
        "BOUND to HAEMOGLOBIN\n~98.5% of total", fsize=8)
    arrow_left(d, dw//2-110, dh-78, 80)
    arrow_right(d, dw//2+110, dh-78, 75)

    arrow_down(d, 127, dh-130, 18)
    box(d, 20, dh-178, 215, 34, C_LTBLUE,
        "Henry's law: 0.3 mL/100mL at PaO2=100\nInsignificant normally\nImportant in hyperbaric O2",
        fsize=7.5, text_color=BLACK, border=C_BLUE)

    arrow_down(d, dw-127, dh-130, 18)
    box(d, dw-235, dh-178, 215, 34, C_LTTEAL,
        "Hüfner's constant: 1.34 mL O2/g Hb\n15g Hb/dL × 1.34 = 20.1 mL/100mL\nArterial content ~19.7 mL/100mL",
        fsize=7.5, text_color=BLACK, border=C_TEAL)

    # Fick
    arrow_down(d, dw//2, dh-158, 18)
    box(d, dw//2-120, dh-198, 240, 22, C_ORANGE, "FICK'S PRINCIPLE", fsize=8)
    box(d, dw//2-140, dh-246, 280, 34, C_LTORG,
        "VO2 = CO × (CaO2 - CvO2)\n= 5 L/min × (20-14.8) mL/100mL = 250 mL/min",
        fsize=8, text_color=BLACK, border=C_ORANGE)

    # Cooperative binding
    arrow_down(d, dw//2, dh-246, 18)
    box(d, dw//2-120, dh-286, 240, 22, C_PURPLE, "Hb COOPERATIVE BINDING", fsize=8)
    box(d, dw//2-130, dh-336, 260, 34, C_LTPUR,
        "2α + 2β chains; each has haem (Fe2+)\nBinding 1st O2 → R-state → ↑affinity for next\n→ Sigmoidal OxyHb curve",
        fsize=7.5, text_color=BLACK, border=C_PURPLE)

    arrow_down(d, dw//2, dh-336, 18)
    box(d, dw//2-130, dh-376, 260, 26, C_LIME,
        "Myoglobin (muscle): P50~3mmHg (↑affinity)\nO2 store; facilitates intracellular diffusion",
        fsize=7.5)

    box(d, 10, 10, dw-20, 22, C_LTYELL,
        "O2 unloading facilitated by: ↓pH, ↑CO2, ↑Temp, ↑2,3-BPG (Bohr effect + right shift)",
        fsize=7, text_color=BLACK, border=C_TEAL)
    return d


def fc_co2_transport(dw=520):
    dh = 420
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "LAQ 7. Transport of CO2", dh-26)

    box(d, dw//2-120, dh-68, 240, 26, C_NAVY,
        "CO2 transported in THREE FORMS\nVenous PCO2=45, Arterial=40 mmHg", fsize=8)

    forms = [
        (20,        C_BLUE,   "DISSOLVED\n7-8%",
         "Physical solution\n0.6 mL/100mL A-V diff\nMost soluble gas"),
        (dw//2-80,  C_TEAL,   "BICARBONATE\n70% (main)",
         "CO2+H2O→H2CO3→H++HCO3-\nCarbonic anhydrase (RBC)\nChloride shift (HCO3- out)\nH+ buffered by deoxyHb"),
        (dw-220,    C_ORANGE, "CARBAMINO\n23%",
         "CO2+Hb-NH2→Hb-NHCOOH\n(Carbaminohaemoglobin)\nDeoxy-Hb binds more CO2\n(Haldane effect)"),
    ]
    fw = (dw-30)//3 - 3
    for fx, col, title, body in forms:
        box(d, fx, dh-116, fw, 26, col, title, fsize=8)
        box(d, fx, dh-220, fw, 84, col, body, fsize=7.5)
        d.add(Line(fx+fw//2, dh-90, fx+fw//2, dh-116,
                   strokeColor=C_DKGREY, strokeWidth=1))
        tip = [fx+fw//2, dh-90, fx+fw//2-4, dh-98, fx+fw//2+4, dh-98]
        d.add(Polygon(tip, fillColor=C_DKGREY, strokeColor=C_DKGREY))

    # Chloride shift detail
    arrow_down(d, dw//2, dh-220, 20)
    box(d, dw//2-140, dh-264, 280, 28, C_TEAL,
        "CHLORIDE (HAMBURGER) SHIFT\nHCO3- exits RBC via Band 3 (AE1) protein\nCl- enters RBC to maintain electrical neutrality", fsize=7.5)

    # Haldane
    arrow_down(d, dw//2, dh-264, 20)
    box(d, dw//2-140, dh-308, 280, 28, C_PURPLE,
        "HALDANE EFFECT IN LUNGS\nO2 + Hb → OxyHb (stronger acid) → releases H+\nH+ + HCO3- → H2CO3 → CO2 exhaled\nAccounts for ~50% CO2 expelled", fsize=7.5)

    arrow_down(d, dw//2, dh-308, 20)
    box(d, dw//2-140, dh-352, 280, 26, C_LIME,
        "CO2 DISSOCIATION CURVE\nMore linear (not sigmoidal) than O2\nVenous: 52 mL/100mL | Arterial: 48 mL/100mL", fsize=7.5)

    box(d, 10, dh-396, dw-20, 30, C_GREY,
        "Metabolic acidosis → lungs blow off CO2 (Kussmaul breathing)\n"
        "Respiratory acidosis → kidneys retain HCO3- (renal compensation)\n"
        "Acetazolamide → blocks CA → metabolic acidosis → ↑ventilation (altitude sickness Rx)",
        fsize=7, text_color=C_DKGREY, border=C_DKGREY)
    return d


def fc_work_breathing(dw=520):
    dh = 360
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "12. Work of Breathing – Applied Importance", dh-26)

    box(d, dw//2-130, dh-68, 260, 26, C_NAVY,
        "Work of Breathing = P × ΔV\nagainst 3 forces", fsize=8)
    arrow_down(d, dw//2, dh-68, 20)

    comps = [
        (15,        C_TEAL,   "ELASTIC WORK\n~65%",
         "Against elastic recoil\nof lungs + chest wall\n↑ in: Fibrosis, RDS\n(stiff lungs)"),
        (dw//2-80,  C_ORANGE, "TISSUE RESISTANCE\n~7%",
         "Viscous resistance\nof lung/chest tissues\n↑ in: Fibrosis"),
        (dw-200,    C_RED,    "AIRWAY RESISTANCE\n~28%",
         "Against airflow in\nairways (Poiseuille)\n↑ in: Asthma, COPD\nr4 dependence"),
    ]
    bw = (dw-30)//3 - 3
    for bx, col, title, body in comps:
        box(d, bx, dh-120, bw, 26, col, title, fsize=8)
        box(d, bx, dh-222, bw, 82, col, body, fsize=7.5)
        d.add(Line(bx+bw//2, dh-94, bx+bw//2, dh-120, strokeColor=C_DKGREY, strokeWidth=0.8))

    # Applied
    box(d, 10, dh-258, dw-20, 20, C_PURPLE, "APPLIED IMPORTANCE", fsize=8)
    applied = [
        (C_LTPUR, "Rest: ~0.5 kg·m/min\n=3% total VO2"),
        (C_LTBLUE, "Exercise: 25x resting\n→ limiting factor"),
        (C_LTORG, "Mechanical ventilation\nreduces patient\nwork of breathing"),
        (C_LTGREEN, "COPD: pursed-lip breathing\nreduces expiratory resistance\n→ less air trapping"),
    ]
    aw = (dw-30)//4 - 3
    ax = 15
    for col, txt in applied:
        box(d, ax, dh-316, aw, 42, col, txt, fsize=7, text_color=BLACK, border=C_PURPLE)
        ax += aw + 4

    box(d, 10, 10, dw-20, 22, C_LTYELL,
        "Unsustainable when >600 mL O2/min or >40% max ventilatory capacity → respiratory failure. Basis for intubation.",
        fsize=7, text_color=BLACK, border=C_ORANGE)
    return d


def fc_frc(dw=520):
    dh = 320
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "14. Functional Residual Capacity (FRC)", dh-26)

    box(d, dw//2-130, dh-68, 260, 28, C_NAVY,
        "FRC = ERV + RV = ~2500 mL\nResting lung volume (passive expiration)", fsize=8)
    arrow_down(d, dw//2, dh-68, 18)
    box(d, dw//2-130, dh-112, 260, 24, C_TEAL,
        "= Balance point: inward recoil (lung)\n= outward recoil (chest wall)", fsize=8)

    sigs = [
        (C_BLUE,   "O2 RESERVOIR\nBuffer against swings\nin alveolar PO2"),
        (C_LIME,   "PREVENTS COLLAPSE\nAlveoli kept open\nbetween breaths"),
        (C_ORANGE, "DILUTION EFFECT\n500mL mixes with 2500mL\n→ only 1/5 replaced/breath"),
        (C_PURPLE, "V/Q MATCHING\nMaintains uniform\nventilation distribution"),
    ]
    sw = (dw-30)//4 - 3
    sx = 15
    arrow_down(d, dw//2, dh-136, 18)
    box(d, 15, dh-166, dw-30, 18, C_DKGREY, "PHYSIOLOGICAL SIGNIFICANCE", fsize=8)
    for col, txt in sigs:
        box(d, sx, dh-232, sw, 50, col, txt, fsize=7.5)
        sx += sw + 4

    red_facts = [
        "Supine: ↓500 mL",
        "Obesity",
        "Anaesthesia (major cause of perioperative atelectasis)",
        "Pregnancy",
        "Restrictive disease",
    ]
    box(d, 10, dh-268, dw//2-15, 22, C_RED, "FACTORS REDUCING FRC", fsize=7.5)
    box(d, 10, dh-302, dw//2-15, 26, C_LTRED,
        " | ".join(red_facts), fsize=7, text_color=BLACK, border=C_RED)

    box(d, dw//2+5, dh-268, dw//2-15, 22, C_ORANGE, "CLINICAL IMPORTANCE", fsize=7.5)
    box(d, dw//2+5, dh-302, dw//2-15, 26, C_LTORG,
        "Low FRC in preterms → RDS risk\nPEEP in ventilated patients ↑ FRC → prevents derecruitment",
        fsize=7, text_color=BLACK, border=C_ORANGE)
    return d


def fc_misc(dw=520):
    """AMS, Periodic breathing, Kussmaul, Asphyxia/Cyanosis/Dyspnoea."""
    dh = 560
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "15-16-20-21. AMS | Periodic Breathing | Kussmaul | Asphyxia/Cyanosis/Dyspnoea", dh-26)

    # AMS
    box(d, 10, dh-58, 245, 20, C_RED, "15. ACUTE MOUNTAIN SICKNESS", fsize=8)
    box(d, 10, dh-158, 245, 90, C_LTRED,
        "Rapid ascent >2500m\nHypoxia→ NO-mediated cerebral vasodilation\n→ vasogenic oedema → ↑ICP\nSymptoms: Headache + nausea/fatigue/dizziness\nTx: Descent, O2, Acetazolamide\nHACE: Ataxia, confusion → Dexamethasone\nHAPE: Frothy sputum → Nifedipine",
        fsize=7.5, text_color=BLACK, border=C_RED)

    # Periodic Breathing
    box(d, dw//2+5, dh-58, 245, 20, C_ORANGE, "16. PERIODIC BREATHING & ONDINE'S CURSE", fsize=7)
    box(d, dw//2+5, dh-158, 245, 90, C_LTORG,
        "Cheyne-Stokes: waxing/waning + apnoeas\nCause: ↑circulation time (HF) → delay\nAlso: high altitude, CNS lesions, sleep\nBiot's breathing: random apnoeas (brainstem)\nOndine's Curse (CCHS): PHOX2B mutation\nAutomatic breathing fails during SLEEP\nTx: Nocturnal CPAP / diaphragm pacing",
        fsize=7.5, text_color=BLACK, border=C_ORANGE)

    # Kussmaul
    box(d, 10, dh-182, 245, 20, C_PURPLE, "20. KUSSMAUL BREATHING", fsize=8)
    box(d, 10, dh-290, 245, 96, C_LTPUR,
        "Deep, regular, rapid breathing\nNO apnoeas (unlike Cheyne-Stokes)\nMechanism: Metabolic acidosis\n→ ↓pH → central + peripheral chemoreceptors\n→ ↑ventilation → blow off CO2\nCauses: DKA (classic), Uraemia,\nLactic acidosis, Salicylate poisoning\nRequires pH <7.2 to be clinically visible",
        fsize=7.5, text_color=BLACK, border=C_PURPLE)

    # Obstructive
    box(d, dw//2+5, dh-182, 245, 20, C_BLUE, "17. OBSTRUCTIVE LUNG DISEASE", fsize=8)
    box(d, dw//2+5, dh-290, 245, 96, C_LTBLUE,
        "FEV1/FVC < 0.70 (diagnostic)\nFEV1 ↓, FVC normal/↓, RV↑, TLC↑\nAsthma: reversible, TH2, bronchospasm\nCOPD: emphysema + chronic bronchitis\nPink puffer: emphysema, barrel chest\nBlue bloater: bronchitis, cyanosis, oedema\nBronchiectasis, Cystic fibrosis",
        fsize=7.5, text_color=BLACK, border=C_BLUE)

    # Cyanosis/Asphyxia/Dyspnoea
    box(d, 10, dh-314, 500, 20, C_NAVY, "21. ASPHYXIA | CYANOSIS | DYSPNOEA", fsize=8)

    box(d, 10, dh-414, 155, 88, C_LTRED,
        "ASPHYXIA\nHypoxia + Hypercapnia\nCauses: airway obstruction\ndrowning, strangulation\nStages: tachypnoea\n→ apnoea → gasping\n→ cardiac arrest",
        fsize=7.5, text_color=BLACK, border=C_RED)
    box(d, 175, dh-414, 170, 88, C_LTBLUE,
        "CYANOSIS\n>5g/dL deoxyHb in capillaries\nCentral: tongue, lips (↓SaO2)\nPeripheral: fingertips (↓flow)\nDiff. cyanosis: lower limbs (PDA+PHT)\nAbsent in severe anaemia!",
        fsize=7.5, text_color=BLACK, border=C_BLUE)
    box(d, 355, dh-414, 155, 88, C_LTGREEN,
        "DYSPNOEA\nSubjective breathlessness\nJ-receptor activation (congestion)\nChemoreceptor stimulation\nMismatch: neural drive vs mechanics\nOrthopnoea=LHF, PND=LHF\nPlatypnoea=hepatopulmonary",
        fsize=7.5, text_color=BLACK, border=C_LIME)

    # Muscles + Alveolar air + Ventilation in brief
    box(d, 10, dh-448, 500, 20, C_TEAL, "13. MUSCLES OF RESPIRATION", fsize=8)
    box(d, 10, dh-514, 500, 54, C_LTTEAL,
        "INSPIRATION: Diaphragm (C3-C5, 60-75% TV) + External intercostals + Scalenes + SCM (accessory)\n"
        "QUIET EXPIRATION: PASSIVE – elastic recoil only\n"
        "FORCED EXPIRATION: Abdominals (most important) + Internal intercostals + Innermost intercostals\n"
        "Applied: C4 injury → complete ventilator dependence. SCM use at rest = sign of respiratory distress.",
        fsize=7.5, text_color=BLACK, border=C_TEAL)

    box(d, 10, 10, dw-20, 18, C_GREY,
        "Alveolar Gas Equation: PAO2 = PIO2 – (PACO2/RQ) | RQ=0.8 | Normal PAO2=100mmHg, PACO2=40mmHg | PH2O=47mmHg",
        fsize=7, text_color=C_DKGREY, border=C_DKGREY)
    return d


def fc_pulm_ventilation(dw=520):
    dh = 440
    d = Drawing(dw, dh)
    d.add(Rect(0, 0, dw, dh, fillColor=C_CREAM, strokeColor=None))
    title_box(d, dw, "LAQ 5. Pulmonary Ventilation – Mechanism & Positive Pressure Breathing", dh-26)

    # Mechanism
    box(d, dw//2-120, dh-68, 240, 24, C_NAVY,
        "BASIS: Boyle's Law (P×V = constant)\nVolume ↑ → Pressure ↓ → Air flows in", fsize=8)

    box(d, 10, dh-104, 245, 20, C_TEAL, "INSPIRATION (Active)", fsize=8)
    insp_steps = [
        "Diaphragm contracts (descends 1-2 cm)",
        "External intercostals → ribs ↑ & out",
        "Thoracic volume ↑",
        "Intrapleural pressure: -5 → -8 cmH2O",
        "Transpulmonary pressure ↑ → alveoli expand",
        "Alveolar P: 0 → -1 cmH2O",
        "Air flows in (atm > alveolar)",
    ]
    sy = dh-128
    for step in insp_steps:
        box(d, 10, sy, 245, 18, C_LTBLUE, step, fsize=7, text_color=BLACK, border=C_TEAL)
        sy -= 20

    box(d, dw//2+5, dh-104, 245, 20, C_ORANGE, "QUIET EXPIRATION (Passive)", fsize=8)
    exp_steps = [
        "Respiratory muscles RELAX",
        "Elastic recoil of lungs",
        "Thoracic volume ↓",
        "Alveolar P: 0 → +1 cmH2O",
        "Air flows out",
        "(Forced expiration: abdominal muscles contract)",
    ]
    ey = dh-128
    for step in exp_steps:
        box(d, dw//2+5, ey, 245, 18, C_LTORG, step, fsize=7, text_color=BLACK, border=C_ORANGE)
        ey -= 20

    # Pressures
    arrow_down(d, dw//2, dh-290, 18)
    box(d, dw//2-130, dh-330, 260, 22, C_PURPLE, "POSITIVE PRESSURE BREATHING (PPB)", fsize=8)
    arrow_down(d, dw//2, dh-330, 16)

    ppb_types = [
        (C_BLUE,   "IPPB\nPositive P during insp\nPassive expiration"),
        (C_TEAL,   "CPAP\nConstant positive P\nboth phases"),
        (C_ORANGE, "PEEP\nPositive at end-expiration\n(ventilated patients)"),
        (C_PURPLE, "BiPAP\nDifferent IPAP & EPAP\n(two-level pressure)"),
    ]
    pw = (dw-30)//4 - 3
    px = 15
    for col, txt in ppb_types:
        box(d, px, dh-400, pw, 52, col, txt, fsize=7.5)
        px += pw + 4

    box(d, 10, dh-432, dw//2-15, 22, C_LTRED,
        "Adverse: ↑intrathoracic P → ↓venous return → ↓CO\nRisk: Barotrauma, ↓renal perfusion",
        fsize=7, text_color=BLACK, border=C_RED)
    box(d, dw//2+5, dh-432, dw//2-15, 22, C_LTGREEN,
        "Benefits: ↑FRC, recruits alveoli, ↑oxygenation\nCardiogenic pulmonary oedema: ↓LV afterload",
        fsize=7, text_color=BLACK, border=C_LIME)

    box(d, 10, 10, dw-20, 22, C_LTYELL,
        "Pressures: Intrapleural -5 (expir) → -8 cmH2O (inspir) | Alveolar ±1 cmH2O | Transpulmonary 5 cmH2O (resting)",
        fsize=7, text_color=BLACK, border=C_ORANGE)
    return d


# ═══════════════════════════════════════════════════════════════════════════════
#  COVER PAGE + DOC BUILD
# ═══════════════════════════════════════════════════════════════════════════════

def build_pdf(output_path):
    doc = SimpleDocTemplate(
        output_path,
        pagesize=A4,
        rightMargin=1.5*cm,
        leftMargin=1.5*cm,
        topMargin=1.8*cm,
        bottomMargin=1.5*cm,
    )
    styles = getSampleStyleSheet()

    TITLE = ParagraphStyle("TITLE", parent=styles["Title"],
                           fontName="Helvetica-Bold", fontSize=22,
                           textColor=C_NAVY, spaceAfter=6, alignment=1)
    SUB   = ParagraphStyle("SUB", parent=styles["Normal"],
                           fontName="Helvetica", fontSize=11,
                           textColor=C_DKGREY, spaceAfter=4, alignment=1)
    SEC   = ParagraphStyle("SEC", parent=styles["Normal"],
                           fontName="Helvetica-Bold", fontSize=12,
                           textColor=C_TEAL, spaceBefore=10, spaceAfter=4)

    story = []

    # ── COVER ──────────────────────────────────────────────────────────────────
    story.append(Spacer(1, 2*cm))
    story.append(Paragraph("RESPIRATORY PHYSIOLOGY", TITLE))
    story.append(Paragraph("Flowchart-Based Study Guide", SUB))
    story.append(Paragraph("SAQ & LAQ – Complete Exam Reference", SUB))
    story.append(HRFlowable(width="100%", thickness=2, color=C_TEAL, spaceAfter=10))
    story.append(Spacer(1, 0.5*cm))

    toc = [
        ["SAQ", "Topic"],
        ["1",  "Oxygen-Haemoglobin Dissociation Curve & 2,3-BPG"],
        ["2",  "Hering-Breuer Reflex"],
        ["3&4","Bohr Effect & Haldane Effect"],
        ["5",  "P50"],
        ["6",  "Characteristics of Pulmonary Circulation"],
        ["7",  "Acclimatisation to High Altitude & AMS"],
        ["8",  "Peripheral Chemoreceptors"],
        ["9",  "Factors Affecting Alveolar Air Composition (in FC#misc)"],
        ["10", "Hypoxia – Classification & Hypoxic Hypoxia"],
        ["11", "Surfactant & RDS"],
        ["12", "Work of Breathing"],
        ["13", "Muscles of Respiration (in FC#misc)"],
        ["14", "Functional Residual Capacity"],
        ["15", "Acute Mountain Sickness (in FC#misc)"],
        ["16", "Periodic Breathing & Ondine's Curse (in FC#misc)"],
        ["17", "Obstructive Lung Diseases (in FC#misc)"],
        ["18", "Lung Volumes & Capacities"],
        ["19", "Ventilation-Perfusion Ratio"],
        ["20", "Kussmaul Breathing (in FC#misc)"],
        ["21", "Asphyxia, Cyanosis & Dyspnoea (in FC#misc)"],
        ["LAQ","Topic"],
        ["1",  "Neural Regulation of Respiration"],
        ["2",  "Chemical Control of Respiration"],
        ["3",  "Lung Compliance & Hyaline Membrane Disease"],
        ["4",  "Respiratory Membrane & CO Method (DLCO)"],
        ["5",  "Pulmonary Ventilation & Positive Pressure Breathing"],
        ["6",  "Transport of Oxygen"],
        ["7",  "Transport of CO2"],
    ]
    ts = TableStyle([
        ("BACKGROUND", (0,0), (-1,0), C_NAVY),
        ("TEXTCOLOR",  (0,0), (-1,0), WHITE),
        ("BACKGROUND", (0,21),(1,21), C_TEAL),
        ("TEXTCOLOR",  (0,21),(1,21), WHITE),
        ("FONTNAME",   (0,0), (-1,0), "Helvetica-Bold"),
        ("FONTNAME",   (0,21),(1,21), "Helvetica-Bold"),
        ("FONTSIZE",   (0,0), (-1,-1), 8),
        ("ROWBACKGROUNDS", (0,1), (-1,20), [C_CREAM, C_GREY]),
        ("ROWBACKGROUNDS", (0,22),(-1,-1), [C_LTBLUE, C_LTTEAL]),
        ("GRID", (0,0), (-1,-1), 0.4, C_DKGREY),
        ("ALIGN", (0,0), (0,-1), "CENTER"),
        ("VALIGN", (0,0), (-1,-1), "MIDDLE"),
        ("TOPPADDING",    (0,0),(-1,-1), 3),
        ("BOTTOMPADDING", (0,0),(-1,-1), 3),
    ])
    t = Table(toc, colWidths=[1.5*cm, 14*cm])
    t.setStyle(ts)
    story.append(t)
    story.append(PageBreak())

    # ── FLOWCHARTS ─────────────────────────────────────────────────────────────
    DW = 520  # drawing width (pts) – fits within A4 margins

    charts = [
        ("SAQ 1 – Oxy-Haemoglobin Dissociation Curve",   fc_oxy_hb),
        ("SAQ 2 – Hering-Breuer Reflex",                  fc_hering_breuer),
        ("SAQ 3 & 4 – Bohr Effect & Haldane Effect",      fc_bohr_haldane),
        ("SAQ 5 – P50",                                    fc_p50),
        ("SAQ 6 – Pulmonary Circulation",                  fc_pulm_circ),
        ("SAQ 7 – High Altitude Acclimatisation",          fc_altitude),
        ("SAQ 8 – Peripheral Chemoreceptors",              fc_chemoreceptors),
        ("SAQ 10 – Hypoxia Classification",                fc_hypoxia),
        ("SAQ 11 – Surfactant & RDS",                      fc_surfactant),
        ("SAQ 12 – Work of Breathing",                     fc_work_breathing),
        ("SAQ 14 – Functional Residual Capacity",          fc_frc),
        ("SAQ 18 – Lung Volumes & Capacities",             fc_lung_volumes),
        ("SAQ 19 – V/Q Ratio",                             fc_vq_ratio),
        ("SAQ 15,16,17,20,21 – AMS / Periodic / Kussmaul / Asphyxia",  fc_misc),
        ("LAQ 1 – Neural Regulation of Respiration",       fc_neural_regulation),
        ("LAQ 2 – Chemical Control of Respiration",        fc_chemical_control),
        ("LAQ 3 – Lung Compliance & HMD",                  fc_compliance),
        ("LAQ 4 – Respiratory Membrane & DLCO",            fc_resp_membrane),
        ("LAQ 5 – Pulmonary Ventilation & PPB",            fc_pulm_ventilation),
        ("LAQ 6 – Transport of Oxygen",                    fc_o2_transport),
        ("LAQ 7 – Transport of CO2",                       fc_co2_transport),
    ]

    for heading, builder in charts:
        drawing = builder(DW)
        story.append(KeepTogether([
            FlowchartFlowable(drawing),
            Spacer(1, 6),
        ]))
        story.append(PageBreak())

    # ── QUICK-REFERENCE TABLES ─────────────────────────────────────────────────
    story.append(Paragraph("Quick-Reference Summary Tables", SEC))
    story.append(HRFlowable(width="100%", thickness=1, color=C_TEAL, spaceAfter=6))

    # Normal Values
    nv = [
        ["Parameter", "Normal Value"],
        ["TV", "500 mL"],
        ["IRV", "3000 mL"],
        ["ERV", "1100 mL"],
        ["RV", "1200 mL"],
        ["FRC", "2500 mL"],
        ["VC", "4600 mL"],
        ["TLC", "5800 mL"],
        ["FEV1/FVC", ">0.70"],
        ["PaO2 arterial", "100 mmHg"],
        ["PaCO2 arterial", "40 mmHg"],
        ["Hb saturation (arterial)", "97.5%"],
        ["P50", "26 mmHg"],
        ["Pulmonary artery pressure", "25/8 mmHg (mean 15)"],
        ["PCWP", "6-12 mmHg"],
        ["Normal V/Q", "0.8 (4/5)"],
        ["DLCO", "~25 mL/min/mmHg"],
        ["O2 content (arterial)", "~20 mL/100 mL"],
        ["O2 consumption (rest)", "~250 mL/min"],
        ["O2 delivery", "~1000 mL/min"],
        ["Hüfner's constant", "1.34 mL O2/g Hb"],
        ["Dead space (anatomical)", "~150 mL"],
        ["Surfactant start", "24-26 weeks gestation"],
        ["Surfactant adequate", "32-34 weeks"],
    ]
    nvt = Table(nv, colWidths=[8*cm, 8*cm])
    nvt.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,0), C_NAVY),
        ("TEXTCOLOR",  (0,0), (-1,0), WHITE),
        ("FONTNAME",   (0,0), (-1,0), "Helvetica-Bold"),
        ("FONTSIZE",   (0,0), (-1,-1), 8),
        ("ROWBACKGROUNDS", (0,1), (-1,-1), [C_CREAM, C_LTBLUE]),
        ("GRID", (0,0), (-1,-1), 0.4, C_DKGREY),
        ("ALIGN", (0,0), (-1,-1), "CENTER"),
        ("TOPPADDING",    (0,0),(-1,-1), 3),
        ("BOTTOMPADDING", (0,0),(-1,-1), 3),
    ]))
    story.append(nvt)
    story.append(Spacer(1, 0.5*cm))

    doc.build(story)
    print(f"PDF saved to: {output_path}")


if __name__ == "__main__":
    build_pdf("/home/daytona/workspace/respiratory-study-guide/Respiratory_Physiology_Flowchart_Guide.pdf")
Running Command

cd /home/daytona/workspace/respiratory-study-guide && python3 build_pdf.py 2>&1

Running Command

ls -lh /home/daytona/workspace/respiratory-study-guide/Respiratory_Physiology_Flowchart_Guide.pdf

Your flowchart-based PDF is ready!

Respiratory Physiology Flowchart Guide

PDF Document · PDF


What's inside (23 pages):

SectionContents
Cover + TOCColour-coded table of contents for all 28 questions
21 Flowchart PagesOne dedicated flowchart per topic (or grouped where logical)
Quick-Reference TableAll normal values at a glance

Flowcharts included:

  • SAQ 1 - OxyHb curve: sigmoid shape, right/left shift factors, 2,3-BPG role
  • SAQ 2 - Hering-Breuer: step-by-step reflex pathway
  • SAQ 3&4 - Bohr effect (left column) vs Haldane effect (right column), side-by-side
  • SAQ 5 - P50: high vs low affinity comparison
  • SAQ 6 - Pulmonary circulation: 6 feature boxes + HPV mechanism
  • SAQ 7 - High altitude: 3-phase acclimatisation + HACE/HAPE branches
  • SAQ 8 - Peripheral chemoreceptors: carotid vs aortic, stimuli ranked
  • SAQ 10 - Hypoxia: all 4 types + hypoxic hypoxia causes expanded
  • SAQ 11 - Surfactant: source → functions → RDS pathophysiology + treatment
  • SAQ 12 - Work of breathing: 3 components + applied importance
  • SAQ 14 - FRC: significance + factors reducing it
  • SAQ 18 - Lung volumes: visual bar chart + capacities
  • SAQ 19 - V/Q ratio: apex vs base, dead space vs shunt, HPV mechanism
  • SAQ 15,16,17,20,21 - AMS, Periodic breathing, Obstructive disease, Kussmaul, Asphyxia/Cyanosis/Dyspnoea (grouped)
  • LAQ 1 - Neural regulation: full brainstem pathway + reflex inputs
  • LAQ 2 - Chemical control: central vs peripheral, side-by-side
  • LAQ 3 - Lung compliance + HMD: Laplace law, factors, treatment
  • LAQ 4 - Respiratory membrane: 8 layers + Fick's law + CO method
  • LAQ 5 - Pulmonary ventilation: pressure changes + PPB types
  • LAQ 6 - O2 transport: dissolved vs Hb-bound + Fick's principle
  • LAQ 7 - CO2 transport: 3 forms + chloride shift + Haldane in lungs
This is a shared conversation. Sign in to Orris to start your own chat.