Correction of Respiratory Acidosis Step by step with BiPaP ,Titration,maintaince and further guidance with values of ABGs n settings for BiPaP according

Reading File
Finding Sources
Finding Sources
Searching PubMed

"respiratory acidosis" AND "noninvasive ventilation" AND "BiPAP"

Finding Sources
Finding Sources
Searching PubMed

"noninvasive ventilation" AND "hypercapnic respiratory failure" AND guidelines

Reading File
Reading File
Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Finding Sources
Reading File
Reading File
Finding Sources
Finding Sources
Reading File
Searching the Web

BiPAP settings titration respiratory acidosis IPAP EPAP starting values ABG targets 2024

I now have comprehensive data from multiple authoritative sources. Let me compile the complete guide.

Correction of Respiratory Acidosis with BiPAP: Step-by-Step Guide

1. Understanding Respiratory Acidosis — ABG Criteria

ParameterNormalAcute Resp. AcidosisChronic Resp. Acidosis
pH7.35–7.45< 7.35< 7.35 (partially compensated)
PaCO₂35–45 mmHg> 45 mmHg (↑)> 45 mmHg (↑)
HCO₃⁻22–26 mEq/L↑ 1 mEq/L per 10 mmHg ↑PaCO₂↑ 4 mEq/L per 10 mmHg ↑PaCO₂
PaO₂80–100 mmHgOften ↓ (hypoxemia coexists)Often ↓
Compensation rule:
  • Acute (< 24 hrs): HCO₃⁻ rises by 1 mEq/L per 10 mmHg rise in PaCO₂
  • Chronic (> 24 hrs): HCO₃⁻ rises by 4 mEq/L per 10 mmHg rise in PaCO₂ (renal adaptation); max HCO₃⁻ rarely exceeds 38 mEq/L
— Brenner and Rector's The Kidney

2. Indications for BiPAP in Respiratory Acidosis

BiPAP (bilevel positive airway pressure, S/T mode) is strongly recommended when:
CriterionValue
pH7.25–7.35 (the sweet spot — acidotic but not yet critically so)
PaCO₂> 45 mmHg with clinical distress
Respiratory rate> 25 breaths/min
SpO₂< 90% on supplemental O₂
Classic indications: COPD exacerbation, OHS (obesity-hypoventilation syndrome), NMD (neuromuscular disease), cardiogenic pulmonary edema with hypercapnia.
Contraindications (proceed to intubation):
  • pH < 7.25 and rapidly deteriorating
  • GCS ≤ 8 / inability to protect airway
  • Hemodynamic instability / respiratory arrest
  • Copious secretions / facial trauma
  • Tachypnea > 35 with GCS < 11 (predictors of NIV failure)
— Rosen's Emergency Medicine; Murray & Nadel's Textbook of Respiratory Medicine

3. Interface Selection

  1. Full-face (oronasal) mask — first choice; better seal, lower leak rate, better patient-ventilator synchrony
  2. Nasal mask — second choice; higher leak rate, patient comfort varies
  3. Helmet interface — option in some centers for prolonged use
Ensure a proper seal before starting — leaks are the #1 cause of asynchrony during NIV. Inspiratory leaks cause prolonged inspiration; expiratory leaks cause auto-triggering.
— Murray & Nadel's Textbook of Respiratory Medicine

4. Initial BiPAP Settings — Hypercapnic (Type II) Respiratory Failure

ParameterStarting ValueNotes
ModeS/T (Spontaneous-Timed)Preferred for hypercapnia
IPAP10–15 cmH₂OStart at 10–12; titrate up
EPAP4–6 cmH₂OLower EPAP in pure hypercapnia (COPD)
Pressure Support (PS = IPAP−EPAP)≥ 6–8 cmH₂O initially, target > 10Drives tidal volume and CO₂ clearance
Backup RR12–16 breaths/minPrevent apnea; set close to patient's own RR
FiO₂0.50–1.0Start at 1.0, wean to SpO₂ 88–92%
Rise timeShort (1–2)Shorter = faster pressurization → better comfort in obstructive disease
I:E ratio1:2 to 1:3 (COPD) / 1:1 (NMD)Longer expiratory time → prevents dynamic hyperinflation in COPD
Ti (inspiratory time)ShortReduces risk of auto-PEEP in COPD
For pure hypoxemia (Type I): IPAP 12–14 / EPAP 8 cmH₂O, FiO₂ 1.0
— BTS NIV Algorithm; Rosen's Emergency Medicine; Fishman's Pulmonary Diseases

5. Titration Protocol (Step-by-Step)

Phase 1 — First 30–60 Minutes

Start → Observe → Adjust every 5–10 minutes:
Step 1: Apply mask, start IPAP 10 / EPAP 4–5 cmH₂O, FiO₂ 1.0
Step 2: Observe for 5–10 min — patient comfort, synchrony, RR, SpO₂
Step 3: Increase IPAP by 2 cmH₂O increments if:
         ✓ WOB still increased
         ✓ RR still > 25
         ✓ Tidal volume inadequate (target 6–8 mL/kg IBW)
Step 4: Increase EPAP by 1–2 cmH₂O if:
         ✓ SpO₂ still < 88–92% despite adequate IPAP
         ✓ Auto-PEEP suspected (note: also re-raise IPAP to maintain PS)
Step 5: Check ABG at 60–90 minutes

Titration Targets (ABG Goals at 1 hour)

ABG ParameterTarget
pH> 7.35
PaCO₂Gradual reduction (do NOT drop > 10 mmHg/hr — risk of post-hypercapnic alkalosis + seizures)
PaO₂55–80 mmHg (or SpO₂ 88–92% in COPD — avoid hyperoxia)
HCO₃⁻Will remain elevated until kidneys excrete the buffer load (days)

IPAP Limits

LimitReason
Max IPAP ≤ 20–25 cmH₂OAbove this → gastric insufflation, mask leak, discomfort
BTS guideline: up to 30 cmH₂O with expert reviewFor refractory hypercapnia
High-intensity BiPAP: PS > 15 cmH₂ORecommended for stable hypercapnic COPD (home NIV)
— Rosen's Emergency Medicine; BTS NIV Algorithm; Fishman's Pulmonary Diseases

6. ABG Check Schedule

TimeAction
BaselineABG before starting BiPAP
1 hourFirst follow-up ABG — most critical check
4 hoursSecond ABG if any setting changes made
Every 4–6 hoursOngoing if clinically stable
After each setting changeRepeat ABG 1 hour after any adjustment
If pH < 7.25 at 1 hour, or clinical deterioration → escalate to intubation.

7. Signs of Success vs. Failure

Success (continue BiPAP)

  • pH improving toward > 7.35
  • PaCO₂ decreasing (not precipitously)
  • RR decreasing (< 25/min)
  • SpO₂ 88–92%
  • Decreased accessory muscle use
  • Patient comfort and synchrony improving

Failure (escalate to intubation)

  • pH < 7.25 despite 1–2 hours of optimized BiPAP
  • GCS falling (worsening encephalopathy)
  • RR > 35 with deteriorating mechanics
  • Hemodynamic instability
  • Inability to tolerate mask
  • PaCO₂ not improving or rising
  • Excessive secretions / aspiration risk
NNT for NPPV in COPD exacerbation = 12 to prevent one intubation; reduces intubation need by 65%.
— Rosen's Emergency Medicine

8. Maintenance Phase (Hours 2–24+)

Once stabilized on BiPAP:
  1. Continuous monitoring: SpO₂, RR, HR, ETCO₂ if available, mental status
  2. Wean FiO₂ to target SpO₂ 88–92% (COPD) or 92–96% (other causes)
  3. ABG every 4–6 hours while on BiPAP
  4. Treat underlying cause simultaneously:
    • COPD: bronchodilators, systemic steroids, antibiotics (if infective exacerbation)
    • CHF: diuresis, afterload reduction
    • OHS/OSA: weight management, positional therapy
  5. Minimum 4 hours of continuous BiPAP recommended for acute exacerbation — do not interrupt for meals until stable

9. Weaning from BiPAP

Once ABG targets are met and underlying cause is improving:
Step 1: Reduce IPAP by 2 cmH₂O every 2–4 hours
Step 2: Reduce FiO₂ toward 0.21–0.35 as tolerated
Step 3: Trial breaks (1–2 hours off BiPAP with supplemental O₂ via nasal cannula)
Step 4: Check ABG 30–60 min after removal of BiPAP
Step 5: Wean EPAP last — reduce to 4 cmH₂O before discontinuing
Wean criteria (safe to remove):
  • pH > 7.35 consistently
  • PaCO₂ at or near patient's chronic baseline
  • SpO₂ > 90% on ≤ 4 L/min nasal cannula
  • RR < 24/min
  • Patient awake, cooperative, able to manage secretions
— Pulmonology 2023 (PMID 36137890): How do I wean a patient with acute hypercapnic respiratory failure from NIV?

10. Home NIV (Long-Term / Post-Discharge)

For patients with persistent hypercapnia (PaCO₂ ≥ 52 mmHg) after hospital discharge following an acute exacerbation:
  • High-intensity BiPAP (PS = IPAP−EPAP ≥ 15 cmH₂O, often IPAP 20–30 cmH₂O) improves outcomes
  • Use S/T mode with backup rate and short inspiratory time for COPD
  • Consider AVAPS (Average Volume-Assured Pressure Support) mode to maintain consistent tidal volumes despite disease progression
  • NNT = 6 to avoid one readmission when home NIV added to LTOT in post-exacerbation persistent hypercapnia
  • Aim for ≥ 4–5 hours/night usage minimum; longer is better
— Fishman's Pulmonary Diseases and Disorders; Chest 2024 (PMID 38417700)

Quick Reference Card

BIPAP FOR RESPIRATORY ACIDOSIS — QUICK GUIDE

INDICATION: pH 7.25–7.35, PaCO₂ > 45, ↑WOB, RR > 25

START:        IPAP 10–12 / EPAP 4–5 / FiO₂ 1.0
              Mode: S/T, RR backup 12–16/min
              I:E 1:2–1:3 (COPD), Short Ti, Short rise time

TITRATE:      ↑ IPAP by 2 cmH₂O q5–10 min for ↑WOB / ↑RR / ↑PaCO₂
              ↑ EPAP by 1–2 cmH₂O for refractory hypoxemia
              Max IPAP: 20–25 cmH₂O (up to 30 with expert review)
              Target PS (IPAP-EPAP) > 10–15 cmH₂O

ABG GOAL:     pH > 7.35, PaCO₂ ↓ gradually (<10 mmHg/hr)
              PaO₂ 55–80 (SpO₂ 88–92% in COPD)

CHECK ABG:    1 hr, 4 hrs, then q4–6 hrs / after each change

FAILURE:      pH < 7.25 at 1 hr, ↓GCS, ↑RR → INTUBATE

Sources: Brenner & Rector's The Kidney | Murray & Nadel's Respiratory Medicine | Rosen's Emergency Medicine | Fishman's Pulmonary Diseases | BTS NIV Algorithm | PMID 36137890 | PMID 38417700

Create a PDF protocol for acute respiratory acidosis management in your institution

Reading File
Running Command

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

Running Command

mkdir -p /home/daytona/workspace/resp-acidosis-protocol && python3 -c "from reportlab.lib.pagesizes import A4; print('reportlab ok')" && python3 -c "from reportlab.platypus import SimpleDocTemplate; print('platypus ok')"

Writing File

~/resp-acidosis-protocol/build_protocol.py

#!/usr/bin/env python3
"""
Generate: Acute Respiratory Acidosis & BiPAP Management Protocol PDF
"""

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT, TA_JUSTIFY
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether, PageBreak
)
from reportlab.platypus.flowables import BalancedColumns
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Polygon
from reportlab.graphics import renderPDF
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Arrow
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
import os

# ─── Output path ────────────────────────────────────────────────────────────
OUT = "/home/daytona/workspace/resp-acidosis-protocol/Acute_Respiratory_Acidosis_Protocol.pdf"

# ─── Colour palette ──────────────────────────────────────────────────────────
NAVY      = colors.HexColor("#1A3557")
TEAL      = colors.HexColor("#1B6CA8")
LIGHT_BLUE= colors.HexColor("#D6E8F7")
LIGHT_TEAL= colors.HexColor("#E8F4FD")
RED       = colors.HexColor("#C0392B")
LIGHT_RED = colors.HexColor("#FADBD8")
GREEN     = colors.HexColor("#1E8449")
LIGHT_GRN = colors.HexColor("#D5F5E3")
AMBER     = colors.HexColor("#D68910")
LIGHT_AMB = colors.HexColor("#FEF9E7")
GREY      = colors.HexColor("#566573")
LIGHT_GRY = colors.HexColor("#F2F3F4")
WHITE     = colors.white
BLACK     = colors.black
ORANGE    = colors.HexColor("#E67E22")
LIGHT_ORG = colors.HexColor("#FDEBD0")

# ─── Page geometry ───────────────────────────────────────────────────────────
PAGE_W, PAGE_H = A4          # 595.3 x 841.9 pt
MARGIN_L = 1.8*cm
MARGIN_R = 1.8*cm
MARGIN_T = 2.2*cm
MARGIN_B = 2.0*cm
CONTENT_W = PAGE_W - MARGIN_L - MARGIN_R

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

def S(name, **kw):
    return ParagraphStyle(name, **kw)

STYLE = {
    "title": S("ptitle", fontSize=22, fontName="Helvetica-Bold",
               textColor=WHITE, alignment=TA_CENTER, leading=26,
               spaceAfter=2),
    "subtitle": S("psubt", fontSize=11, fontName="Helvetica",
                  textColor=LIGHT_BLUE, alignment=TA_CENTER, leading=14),
    "meta": S("pmeta", fontSize=8.5, fontName="Helvetica",
              textColor=LIGHT_GRY, alignment=TA_CENTER, leading=11),
    "section": S("psect", fontSize=12, fontName="Helvetica-Bold",
                 textColor=WHITE, alignment=TA_LEFT, leading=15,
                 leftIndent=4),
    "h2": S("ph2", fontSize=10.5, fontName="Helvetica-Bold",
            textColor=NAVY, leading=13, spaceAfter=3, spaceBefore=6),
    "body": S("pbody", fontSize=9, fontName="Helvetica",
              textColor=BLACK, leading=12, spaceAfter=2),
    "body_sm": S("pbsm", fontSize=8, fontName="Helvetica",
                 textColor=BLACK, leading=11),
    "bold": S("pbold", fontSize=9, fontName="Helvetica-Bold",
              textColor=NAVY, leading=12),
    "bullet": S("pbull", fontSize=9, fontName="Helvetica",
                textColor=BLACK, leading=12, leftIndent=12,
                bulletIndent=4, spaceAfter=1),
    "bullet_red": S("pbull_r", fontSize=9, fontName="Helvetica",
                    textColor=RED, leading=12, leftIndent=12,
                    bulletIndent=4, spaceAfter=1),
    "bullet_grn": S("pbull_g", fontSize=9, fontName="Helvetica",
                    textColor=GREEN, leading=12, leftIndent=12,
                    bulletIndent=4, spaceAfter=1),
    "caption": S("pcap", fontSize=7.5, fontName="Helvetica-Oblique",
                 textColor=GREY, alignment=TA_CENTER, leading=10),
    "footer": S("pfooter", fontSize=7, fontName="Helvetica",
                textColor=GREY, alignment=TA_CENTER, leading=9),
    "th": S("pth", fontSize=8.5, fontName="Helvetica-Bold",
            textColor=WHITE, alignment=TA_CENTER, leading=11),
    "td": S("ptd", fontSize=8.5, fontName="Helvetica",
            textColor=BLACK, alignment=TA_LEFT, leading=11),
    "td_c": S("ptdc", fontSize=8.5, fontName="Helvetica",
              textColor=BLACK, alignment=TA_CENTER, leading=11),
    "td_bold": S("ptdb", fontSize=8.5, fontName="Helvetica-Bold",
                 textColor=NAVY, alignment=TA_LEFT, leading=11),
    "warning": S("pwarn", fontSize=9, fontName="Helvetica-Bold",
                 textColor=RED, alignment=TA_CENTER, leading=12),
    "note": S("pnote", fontSize=8, fontName="Helvetica-Oblique",
              textColor=GREY, leading=10, spaceAfter=2),
    "box_title": S("pboxt", fontSize=10, fontName="Helvetica-Bold",
                   textColor=NAVY, leading=13, spaceAfter=2),
    "ref": S("pref", fontSize=7.5, fontName="Helvetica",
             textColor=GREY, leading=10),
}

# ─── Helpers ─────────────────────────────────────────────────────────────────
def section_header(text, color=NAVY):
    """Coloured section bar."""
    data = [[Paragraph(text, STYLE["section"])]]
    t = Table(data, colWidths=[CONTENT_W])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), color),
        ("TOPPADDING",    (0,0),(-1,-1), 5),
        ("BOTTOMPADDING", (0,0),(-1,-1), 5),
        ("LEFTPADDING",   (0,0),(-1,-1), 8),
        ("RIGHTPADDING",  (0,0),(-1,-1), 8),
        ("ROUNDEDCORNERS", [4]),
    ]))
    return t

def simple_table(headers, rows, col_widths, hdr_color=NAVY,
                 alt_color=LIGHT_TEAL, row_color=WHITE):
    hdr_cells = [Paragraph(h, STYLE["th"]) for h in headers]
    data = [hdr_cells]
    for i, row in enumerate(rows):
        cells = []
        for j, cell in enumerate(row):
            if isinstance(cell, str):
                st = STYLE["td_bold"] if j == 0 else STYLE["td_c"] if j > 0 else STYLE["td"]
                cells.append(Paragraph(cell, st))
            else:
                cells.append(cell)
        data.append(cells)
    t = Table(data, colWidths=col_widths, repeatRows=1)
    style_cmds = [
        ("BACKGROUND",    (0,0),(-1,0),   hdr_color),
        ("TEXTCOLOR",     (0,0),(-1,0),   WHITE),
        ("FONTNAME",      (0,0),(-1,0),   "Helvetica-Bold"),
        ("FONTSIZE",      (0,0),(-1,0),   8.5),
        ("ALIGN",         (0,0),(-1,0),   "CENTER"),
        ("TOPPADDING",    (0,0),(-1,-1),  4),
        ("BOTTOMPADDING", (0,0),(-1,-1),  4),
        ("LEFTPADDING",   (0,0),(-1,-1),  5),
        ("RIGHTPADDING",  (0,0),(-1,-1),  5),
        ("GRID",          (0,0),(-1,-1),  0.4, colors.HexColor("#BDC3C7")),
        ("VALIGN",        (0,0),(-1,-1),  "MIDDLE"),
    ]
    for i in range(1, len(data)):
        bg = alt_color if i % 2 == 0 else row_color
        style_cmds.append(("BACKGROUND", (0,i),(-1,i), bg))
    t.setStyle(TableStyle(style_cmds))
    return t

def coloured_box(content_flowables, bg=LIGHT_TEAL, border=TEAL, radius=4):
    """Wrap flowables in a coloured box using a single-cell table."""
    inner = []
    for f in content_flowables:
        inner.append(f)
    data = [[inner]]
    t = Table([[inner]], colWidths=[CONTENT_W - 4])
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,-1), bg),
        ("BOX",           (0,0),(-1,-1), 0.8, border),
        ("TOPPADDING",    (0,0),(-1,-1), 8),
        ("BOTTOMPADDING", (0,0),(-1,-1), 8),
        ("LEFTPADDING",   (0,0),(-1,-1), 10),
        ("RIGHTPADDING",  (0,0),(-1,-1), 10),
        ("VALIGN",        (0,0),(-1,-1), "TOP"),
    ]))
    return t

def HR(color=TEAL, thickness=1):
    return HRFlowable(width="100%", thickness=thickness,
                      color=color, spaceAfter=4, spaceBefore=4)

def SP(h=4):
    return Spacer(1, h)

def B(text, style="bullet"):
    return Paragraph(f"• {text}", STYLE[style])

def two_col(left_items, right_items, col_w=None):
    """Two-column layout."""
    if col_w is None:
        col_w = [CONTENT_W/2 - 4, CONTENT_W/2 - 4]
    data = [[left_items, right_items]]
    t = Table(data, colWidths=col_w)
    t.setStyle(TableStyle([
        ("VALIGN",       (0,0),(-1,-1), "TOP"),
        ("LEFTPADDING",  (0,0),(-1,-1), 2),
        ("RIGHTPADDING", (0,0),(-1,-1), 2),
        ("TOPPADDING",   (0,0),(-1,-1), 0),
        ("BOTTOMPADDING",(0,0),(-1,-1), 0),
    ]))
    return t

# ─── Header / Footer ─────────────────────────────────────────────────────────
def on_page(canvas, doc):
    canvas.saveState()
    w, h = A4
    # Header bar
    canvas.setFillColor(NAVY)
    canvas.rect(0, h - 1.2*cm, w, 1.2*cm, fill=1, stroke=0)
    canvas.setFillColor(WHITE)
    canvas.setFont("Helvetica-Bold", 8)
    canvas.drawString(MARGIN_L, h - 0.85*cm,
                      "ACUTE RESPIRATORY ACIDOSIS — BiPAP MANAGEMENT PROTOCOL")
    canvas.setFont("Helvetica", 7.5)
    canvas.drawRightString(w - MARGIN_R, h - 0.85*cm,
                           f"Page {doc.page}")
    # Footer
    canvas.setFillColor(NAVY)
    canvas.rect(0, 0, w, 0.9*cm, fill=1, stroke=0)
    canvas.setFillColor(WHITE)
    canvas.setFont("Helvetica", 7)
    canvas.drawCentredString(w/2, 0.32*cm,
        "Internal Clinical Protocol  |  Respiratory/Critical Care  |  "
        "Review Date: May 2027  |  Version 1.0")
    canvas.restoreState()

def on_first_page(canvas, doc):
    # No running header on cover
    canvas.saveState()
    w, h = A4
    canvas.setFillColor(NAVY)
    canvas.rect(0, 0, w, 0.9*cm, fill=1, stroke=0)
    canvas.setFillColor(WHITE)
    canvas.setFont("Helvetica", 7)
    canvas.drawCentredString(w/2, 0.32*cm,
        "Internal Clinical Protocol  |  Respiratory/Critical Care  |  "
        "Review Date: May 2027  |  Version 1.0")
    canvas.restoreState()

# ─── Build document ──────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
    OUT, pagesize=A4,
    leftMargin=MARGIN_L, rightMargin=MARGIN_R,
    topMargin=MARGIN_T + 0.6*cm, bottomMargin=MARGIN_B + 0.4*cm,
    title="Acute Respiratory Acidosis & BiPAP Protocol",
    author="Respiratory/Critical Care Department",
    subject="Clinical Management Protocol"
)

story = []

# ══════════════════════════════════════════════════════════════════════════════
# COVER
# ══════════════════════════════════════════════════════════════════════════════
cover_title = Table(
    [[Paragraph("ACUTE RESPIRATORY ACIDOSIS", STYLE["title"])],
     [Paragraph("BiPAP Management Protocol", STYLE["subtitle"])],
     [SP(4)],
     [Paragraph(
         "Respiratory Medicine  ·  Critical Care  ·  Emergency Department",
         STYLE["meta"])]],
    colWidths=[CONTENT_W]
)
cover_title.setStyle(TableStyle([
    ("BACKGROUND",    (0,0),(-1,-1), NAVY),
    ("TOPPADDING",    (0,0),(-1,-1), 12),
    ("BOTTOMPADDING", (0,0),(-1,-1), 12),
    ("LEFTPADDING",   (0,0),(-1,-1), 16),
    ("RIGHTPADDING",  (0,0),(-1,-1), 16),
    ("ROUNDEDCORNERS",[6]),
]))
story += [cover_title, SP(8)]

# Version info box
meta_rows = [
    ["Document No.", "RCC-PROT-001",   "Version", "1.0"],
    ["Effective Date", "May 2026",      "Review Date", "May 2027"],
    ["Approved By", "Clinical Director", "Department", "Resp / Critical Care"],
]
meta_t = Table(
    [[Paragraph(c, STYLE["body_sm"]) for c in row] for row in meta_rows],
    colWidths=[3.2*cm, 4.8*cm, 3.2*cm, 4.8*cm]
)
meta_t.setStyle(TableStyle([
    ("BACKGROUND",    (0,0),(0,-1), LIGHT_BLUE),
    ("BACKGROUND",    (2,0),(2,-1), LIGHT_BLUE),
    ("FONTNAME",      (0,0),(0,-1), "Helvetica-Bold"),
    ("FONTNAME",      (2,0),(2,-1), "Helvetica-Bold"),
    ("GRID",          (0,0),(-1,-1), 0.4, colors.HexColor("#BDC3C7")),
    ("TOPPADDING",    (0,0),(-1,-1), 4),
    ("BOTTOMPADDING", (0,0),(-1,-1), 4),
    ("LEFTPADDING",   (0,0),(-1,-1), 5),
    ("RIGHTPADDING",  (0,0),(-1,-1), 5),
]))
story += [meta_t, SP(10)]

# ── Purpose box ─────────────────────────────────────────────────────────────
purpose_items = [
    Paragraph("PURPOSE & SCOPE", STYLE["box_title"]),
    SP(3),
    Paragraph(
        "This protocol provides a standardised, evidence-based framework for the "
        "recognition, initial management, BiPAP titration, monitoring, weaning, and "
        "escalation of care for adult patients presenting with <b>acute or acute-on-chronic "
        "respiratory acidosis</b>. It applies to Emergency Department, Medical Ward, High "
        "Dependency Unit, and ICU settings.",
        STYLE["body"]),
    SP(4),
    Paragraph("<b>Target Users:</b> Physicians, Residents, Nurses, Respiratory Therapists",
              STYLE["body"]),
    Paragraph("<b>Population:</b> Adult patients (≥ 18 years) with pH &lt; 7.35 and PaCO₂ &gt; 45 mmHg",
              STYLE["body"]),
]
story += [coloured_box(purpose_items, bg=LIGHT_TEAL, border=TEAL), SP(10)]

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 1 — DIAGNOSTIC CRITERIA
# ══════════════════════════════════════════════════════════════════════════════
story += [section_header("1. DIAGNOSTIC CRITERIA — RESPIRATORY ACIDOSIS"), SP(6)]

story += [Paragraph("1.1  ABG Interpretation", STYLE["h2"])]

abg_headers = ["Parameter", "Normal Range", "Respiratory Acidosis", "Clinical Significance"]
abg_rows = [
    ["pH",      "7.35 – 7.45",  "< 7.35",             "Primary acidaemia"],
    ["PaCO₂",   "35 – 45 mmHg", "> 45 mmHg (↑)",      "Primary defect — hypoventilation"],
    ["HCO₃⁻",  "22 – 26 mEq/L","↑ (compensation)",    "Acute: +1 / Chronic: +4 per 10 mmHg ↑CO₂"],
    ["PaO₂",    "80–100 mmHg",  "Often ↓",             "Hypoxaemia frequently coexists"],
    ["SpO₂",    "95–100%",      "Often < 90%",         "Target 88–92% in COPD during O₂ therapy"],
    ["HCO₃⁻ max","—",           "Rarely > 38 mEq/L",   "Upper limit of renal compensation"],
]
story += [simple_table(abg_headers, abg_rows,
                       [3.2*cm, 3.5*cm, 4.2*cm, 5.1*cm]), SP(6)]

story += [Paragraph("1.2  Compensation Formulae", STYLE["h2"])]
comp_data = [
    [Paragraph("Type", STYLE["th"]),
     Paragraph("Duration", STYLE["th"]),
     Paragraph("Expected HCO₃⁻ Rise", STYLE["th"]),
     Paragraph("Expected pH", STYLE["th"])],
    [Paragraph("Acute", STYLE["td_bold"]),
     Paragraph("< 24 hours", STYLE["td_c"]),
     Paragraph("+1 mEq/L per 10 mmHg ↑ PaCO₂", STYLE["td"]),
     Paragraph("Falls ~0.08 per 10 mmHg ↑ PaCO₂", STYLE["td"])],
    [Paragraph("Chronic", STYLE["td_bold"]),
     Paragraph("> 24 hours", STYLE["td_c"]),
     Paragraph("+4 mEq/L per 10 mmHg ↑ PaCO₂", STYLE["td"]),
     Paragraph("Falls ~0.03 per 10 mmHg ↑ PaCO₂", STYLE["td"])],
]
comp_t = Table(comp_data, colWidths=[3.5*cm, 3.0*cm, 5.5*cm, 4.0*cm])
comp_t.setStyle(TableStyle([
    ("BACKGROUND",    (0,0),(-1,0),  NAVY),
    ("BACKGROUND",    (0,2),(-1,2),  LIGHT_TEAL),
    ("GRID",          (0,0),(-1,-1), 0.4, colors.HexColor("#BDC3C7")),
    ("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"),
]))
story += [comp_t, SP(6)]

story += [Paragraph("1.3  Common Causes", STYLE["h2"])]
causes_left = [
    Paragraph("<b>Airway / Pulmonary</b>", STYLE["bold"]),
    B("COPD acute exacerbation"),
    B("Severe asthma (status asthmaticus)"),
    B("Pneumonia with respiratory fatigue"),
    B("Pulmonary oedema"),
    B("Pneumothorax / haemothorax"),
    SP(4),
    Paragraph("<b>Neuromuscular</b>", STYLE["bold"]),
    B("Myasthenia gravis crisis"),
    B("Guillain-Barré syndrome"),
    B("Spinal cord injury (C3–C5)"),
    B("Amyotrophic lateral sclerosis"),
]
causes_right = [
    Paragraph("<b>CNS / Ventilatory Drive</b>", STYLE["bold"]),
    B("Opioid / sedative overdose"),
    B("Brainstem stroke"),
    B("Head trauma"),
    B("Obesity-hypoventilation syndrome (OHS)"),
    SP(4),
    Paragraph("<b>Mechanical / Iatrogenic</b>", STYLE["bold"]),
    B("Ventilator malfunction / misadjustment"),
    B("Bronchospasm post-intubation"),
    B("Permissive hypercapnia (ARDS management)"),
    B("Post-operative splinting"),
]
story += [two_col(causes_left, causes_right), SP(8)]

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 2 — INITIAL ASSESSMENT
# ══════════════════════════════════════════════════════════════════════════════
story += [section_header("2. INITIAL CLINICAL ASSESSMENT"), SP(6)]

assess_items = [
    Paragraph("2.1  Rapid 5-Point Assessment (perform simultaneously with ABG)", STYLE["h2"]),
]
assess_tbl_data = [
    [Paragraph("Step", STYLE["th"]), Paragraph("Assessment", STYLE["th"]),
     Paragraph("Key Findings", STYLE["th"]), Paragraph("Action", STYLE["th"])],
    [Paragraph("1", STYLE["td_c"]), Paragraph("Airway patency", STYLE["td_bold"]),
     Paragraph("Obstruction, secretions, stridor", STYLE["td"]),
     Paragraph("Suction, jaw thrust, OPA/NPA if needed", STYLE["td"])],
    [Paragraph("2", STYLE["td_c"]), Paragraph("Breathing pattern", STYLE["td_bold"]),
     Paragraph("RR, depth, accessory muscles, paradox", STYLE["td"]),
     Paragraph("SpO₂, ETCO₂ if available", STYLE["td"])],
    [Paragraph("3", STYLE["td_c"]), Paragraph("Consciousness (GCS)", STYLE["td_bold"]),
     Paragraph("GCS < 8 = intubation threshold", STYLE["td"]),
     Paragraph("GCS ≤ 8 → call anaesthesia/ICU stat", STYLE["td"])],
    [Paragraph("4", STYLE["td_c"]), Paragraph("Haemodynamics", STYLE["td_bold"]),
     Paragraph("BP, HR, perfusion, CO₂ on VBG", STYLE["td"]),
     Paragraph("Shock → stabilise before NIV", STYLE["td"])],
    [Paragraph("5", STYLE["td_c"]), Paragraph("ABG + labs", STYLE["td_bold"]),
     Paragraph("pH, PaCO₂, PaO₂, HCO₃⁻, lactate, K⁺", STYLE["td"]),
     Paragraph("Guides NIV vs. intubation decision", STYLE["td"])],
]
assess_t = Table(assess_tbl_data, colWidths=[1.4*cm, 3.8*cm, 5.0*cm, 5.8*cm])
assess_t.setStyle(TableStyle([
    ("BACKGROUND",    (0,0),(-1,0), NAVY),
    ("BACKGROUND",    (0,2),(-1,2), LIGHT_TEAL),
    ("BACKGROUND",    (0,4),(-1,4), LIGHT_TEAL),
    ("GRID",          (0,0),(-1,-1), 0.4, colors.HexColor("#BDC3C7")),
    ("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"),
    ("ALIGN",         (0,0),(0,-1), "CENTER"),
]))
story += [assess_t, SP(8)]

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 3 — DECISION PATHWAY
# ══════════════════════════════════════════════════════════════════════════════
story += [section_header("3. DECISION PATHWAY — BiPAP vs. INTUBATION"), SP(6)]

# NIV indications
niv_ind = [
    Paragraph("✔  INDICATIONS FOR BiPAP (NIV)", STYLE["h2"]),
    B("pH 7.25 – 7.35 with PaCO₂ > 45 mmHg", "bullet"),
    B("Respiratory rate > 25 breaths/min", "bullet"),
    B("Moderate–severe dyspnoea with increased WOB", "bullet"),
    B("SpO₂ < 90% despite supplemental oxygen", "bullet"),
    B("COPD exacerbation with acute hypercapnia", "bullet"),
    B("Cardiogenic pulmonary oedema + hypercapnia", "bullet"),
    B("OHS / neuromuscular disease exacerbation", "bullet"),
    B("Patient awake, cooperative, haemodynamically stable", "bullet"),
]
niv_ci = [
    Paragraph("✘  CONTRAINDICATIONS (→ Intubate)", STYLE["h2"]),
    B("pH < 7.25 and rapidly deteriorating", "bullet_red"),
    B("GCS ≤ 8 / inability to protect airway", "bullet_red"),
    B("Respiratory arrest or gasping", "bullet_red"),
    B("Haemodynamic instability / refractory shock", "bullet_red"),
    B("Copious secretions / high aspiration risk", "bullet_red"),
    B("Uncooperative / agitated patient", "bullet_red"),
    B("Facial trauma or deformity preventing mask seal", "bullet_red"),
    B("Recent upper GI surgery (relative)", "bullet_red"),
]
story += [two_col(
    coloured_box(niv_ind, bg=LIGHT_GRN, border=GREEN),
    coloured_box(niv_ci,  bg=LIGHT_RED, border=RED)
), SP(6)]

# NIV failure predictors
fail_items = [
    Paragraph("⚠  PREDICTORS OF NIV FAILURE (escalate to ICU early if present)", STYLE["warning"]),
    SP(3),
    two_col(
        [B("GCS < 11 at initiation", "bullet"),
         B("Sustained pH < 7.25 after 60 min of NIV", "bullet"),
         B("RR > 35 breaths/min not responding to NIV", "bullet")],
        [B("Worsening encephalopathy on NIV", "bullet"),
         B("Inability to reduce PaCO₂ after 2 hours", "bullet"),
         B("NNT for intubation = 1 if all 3 criteria present", "bullet")]
    )
]
story += [coloured_box(fail_items, bg=LIGHT_RED, border=RED), SP(10)]

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 4 — BiPAP SETUP
# ══════════════════════════════════════════════════════════════════════════════
story += [section_header("4. BiPAP SETUP & INITIAL SETTINGS"), SP(6)]

story += [Paragraph("4.1  Interface Selection", STYLE["h2"])]
iface_data = [
    [Paragraph("Interface", STYLE["th"]), Paragraph("First Choice", STYLE["th"]),
     Paragraph("Indication", STYLE["th"]), Paragraph("Notes", STYLE["th"])],
    [Paragraph("Full-face (oronasal) mask", STYLE["td_bold"]),
     Paragraph("✔ YES", STYLE["td_c"]),
     Paragraph("All acute hypercapnic RF", STYLE["td"]),
     Paragraph("Lower leak rate; recommended as first choice", STYLE["td"])],
    [Paragraph("Nasal mask", STYLE["td_bold"]),
     Paragraph("Second line", STYLE["td_c"]),
     Paragraph("If oronasal not tolerated", STYLE["td"]),
     Paragraph("Higher leak; patient must keep mouth closed", STYLE["td"])],
    [Paragraph("Helmet interface", STYLE["td_bold"]),
     Paragraph("Third line", STYLE["td_c"]),
     Paragraph("Prolonged NIV, skin breakdown", STYLE["td"]),
     Paragraph("Specialised; check dead space ventilation", STYLE["td"])],
]
iface_t = Table(iface_data, colWidths=[4.5*cm, 2.4*cm, 4.5*cm, 4.6*cm])
iface_t.setStyle(TableStyle([
    ("BACKGROUND",    (0,0),(-1,0), NAVY),
    ("BACKGROUND",    (0,1),(-1,1), LIGHT_GRN),
    ("BACKGROUND",    (0,3),(-1,3), LIGHT_TEAL),
    ("GRID",          (0,0),(-1,-1), 0.4, colors.HexColor("#BDC3C7")),
    ("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"),
]))
story += [iface_t, SP(6)]

story += [Paragraph("4.2  Mode Selection", STYLE["h2"])]
mode_items = [
    B("<b>S/T (Spontaneous-Timed)</b> — PREFERRED for all acute hypercapnic RF. Delivers pressure support when patient triggers; backup rate provides ventilation if apnoea occurs.", "bullet"),
    B("S (Spontaneous) — for patients with reliable respiratory drive and mild disease only.", "bullet"),
    B("T (Timed) — for neuromuscular disease with unreliable drive.", "bullet"),
    B("<b>Pressure Control / AVAPS</b> — consider for home NIV or OHS if standard S/T insufficient.", "bullet"),
    SP(2),
    Paragraph("⚠ Avoid Pressure Control (PC) mode in COPD — patient-generated tachypnoea "
              "delivers all breaths at set Ti, worsening dynamic hyperinflation.", STYLE["note"]),
]
story += mode_items + [SP(6)]

story += [Paragraph("4.3  Initial Settings by Clinical Phenotype", STYLE["h2"])]
settings_headers = ["Setting", "COPD Exacerbation", "Cardiogenic Oedema", "OHS / NMD",
                    "Rationale"]
settings_rows = [
    ["Mode",       "S/T",          "S/T or CPAP",    "S/T",          "Backup RR protects apnoeic patients"],
    ["IPAP (cmH₂O)", "10–12 start\n→ target 20–25", "10–14",       "12–16",       "Drives tidal volume & CO₂ clearance"],
    ["EPAP (cmH₂O)", "4–5",        "6–8",            "4–6",          "Higher EPAP for hypoxaemia/oedema"],
    ["PS = IPAP−EPAP", "≥ 6–8\n→ target ≥ 15", "≥ 6",        "≥ 8–10",       "Determines tidal volume and work offloading"],
    ["Backup RR", "12–16/min",     "12–16/min",      "14–18/min",    "Set near patient's own RR"],
    ["FiO₂",      "0.50–1.0\n(wean to SpO₂ 88–92%)", "1.0\n(wean to 94–98%)", "0.50–1.0",  "Avoid hyperoxia in COPD/OHS"],
    ["I:E ratio", "1:2 to 1:3",   "1:1 to 1:2",     "1:1 to 1:2",   "Longer expiration prevents auto-PEEP (COPD)"],
    ["Rise time", "Short (1–2)",   "Medium (2–3)",   "Short-Med",    "Faster rise improves comfort in obstruction"],
    ["Ti",        "Short",         "Standard",       "Standard",     "Short Ti → longer expiration in COPD"],
]
col_w = [3.0*cm, 3.2*cm, 3.2*cm, 2.8*cm, 3.8*cm]
story += [simple_table(settings_headers, settings_rows, col_w, hdr_color=TEAL), SP(6)]

# Limits box
limits_items = [
    Paragraph("⚠  PRESSURE LIMITS — DO NOT EXCEED WITHOUT SENIOR REVIEW", STYLE["warning"]),
    SP(4),
    two_col(
        [B("<b>Max IPAP: 20–25 cmH₂O</b> (routine)", "bullet"),
         B("Up to 30 cmH₂O with consultant review (BTS)", "bullet"),
         B("Risk above 25: gastric insufflation, mask leak", "bullet")],
        [B("<b>Max EPAP: 8 cmH₂O</b> without expert review", "bullet"),
         B("If EPAP increased → also raise IPAP to maintain PS", "bullet"),
         B("High-intensity BiPAP: PS > 15 cmH₂O (home COPD NIV)", "bullet")]
    )
]
story += [coloured_box(limits_items, bg=LIGHT_AMB, border=AMBER), SP(8)]

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 5 — TITRATION PROTOCOL
# ══════════════════════════════════════════════════════════════════════════════
story += [section_header("5. TITRATION PROTOCOL"), SP(6)]

story += [Paragraph("5.1  Step-by-Step Titration Algorithm", STYLE["h2"])]

# Flowchart as table
flow_data = [
    [Paragraph("STEP 1 — INITIATE", STYLE["th"])],
    [Paragraph(
        "Apply interface  ·  Mode: S/T  ·  IPAP: 10–12 cmH₂O  ·  EPAP: 4–5 cmH₂O  ·  "
        "FiO₂: 1.0  ·  Backup RR: 12–16/min\nExplain to patient; encourage compliance",
        STYLE["td"])],
]
flow_t = Table(flow_data, colWidths=[CONTENT_W])
flow_t.setStyle(TableStyle([
    ("BACKGROUND",    (0,0),(0,0), TEAL),
    ("BACKGROUND",    (0,1),(0,1), LIGHT_TEAL),
    ("GRID",          (0,0),(-1,-1), 0.6, TEAL),
    ("TOPPADDING",    (0,0),(-1,-1), 5),
    ("BOTTOMPADDING", (0,0),(-1,-1), 5),
    ("LEFTPADDING",   (0,0),(-1,-1), 8),
    ("RIGHTPADDING",  (0,0),(-1,-1), 8),
]))
story += [flow_t, SP(3)]

flow2_data = [
    [Paragraph("STEP 2 — OBSERVE (first 5–15 minutes)", STYLE["th"])],
    [Paragraph(
        "Assess: patient comfort  ·  chest rise  ·  patient-ventilator synchrony  ·  "
        "SpO₂  ·  RR  ·  HR\nAdjust mask fit to minimise leak  ·  "
        "Offer sedating antihistamine if distressed (NOT opioids/benzodiazepines)",
        STYLE["td"])],
]
flow2_t = Table(flow2_data, colWidths=[CONTENT_W])
flow2_t.setStyle(TableStyle([
    ("BACKGROUND",    (0,0),(0,0), TEAL),
    ("BACKGROUND",    (0,1),(0,1), LIGHT_TEAL),
    ("GRID",          (0,0),(-1,-1), 0.6, TEAL),
    ("TOPPADDING",    (0,0),(-1,-1), 5),
    ("BOTTOMPADDING", (0,0),(-1,-1), 5),
    ("LEFTPADDING",   (0,0),(-1,-1), 8),
    ("RIGHTPADDING",  (0,0),(-1,-1), 8),
]))
story += [flow2_t, SP(3)]

flow3_data = [
    [Paragraph("STEP 3 — TITRATE (every 5–10 minutes based on response)", STYLE["th"])],
    [Paragraph(
        "↑ IPAP by 2 cmH₂O if:  WOB still high  |  RR > 25  |  Tidal volume < 6–8 mL/kg IBW  |  PaCO₂ not improving\n"
        "↑ EPAP by 1–2 cmH₂O if:  SpO₂ < 88% despite adequate IPAP  |  Suspected auto-PEEP  |  "
        "(If EPAP ↑, also ↑ IPAP to maintain PS)\n"
        "↓ FiO₂ to target SpO₂ 88–92% (COPD) or 92–96% (other)  ·  "
        "Titrate by 2–3 cmH₂O per increment  ·  Max IPAP 20–25 cmH₂O",
        STYLE["td"])],
]
flow3_t = Table(flow3_data, colWidths=[CONTENT_W])
flow3_t.setStyle(TableStyle([
    ("BACKGROUND",    (0,0),(0,0), TEAL),
    ("BACKGROUND",    (0,1),(0,1), LIGHT_TEAL),
    ("GRID",          (0,0),(-1,-1), 0.6, TEAL),
    ("TOPPADDING",    (0,0),(-1,-1), 5),
    ("BOTTOMPADDING", (0,0),(-1,-1), 5),
    ("LEFTPADDING",   (0,0),(-1,-1), 8),
    ("RIGHTPADDING",  (0,0),(-1,-1), 8),
]))
story += [flow3_t, SP(3)]

flow4_data = [
    [Paragraph("STEP 4 — RECHECK ABG at 60–90 minutes", STYLE["th"])],
    [Paragraph(
        "pH > 7.35 and improving  →  Continue, maintain settings, repeat ABG at 4 hrs\n"
        "pH 7.25–7.35 and improving  →  Optimise settings, repeat ABG 1 hr\n"
        "pH < 7.25 OR not improving at 60 min  →  Senior review; consider intubation",
        STYLE["td"])],
]
flow4_t = Table(flow4_data, colWidths=[CONTENT_W])
flow4_t.setStyle(TableStyle([
    ("BACKGROUND",    (0,0),(0,0), NAVY),
    ("BACKGROUND",    (0,1),(0,1), LIGHT_BLUE),
    ("GRID",          (0,0),(-1,-1), 0.6, NAVY),
    ("TOPPADDING",    (0,0),(-1,-1), 5),
    ("BOTTOMPADDING", (0,0),(-1,-1), 5),
    ("LEFTPADDING",   (0,0),(-1,-1), 8),
    ("RIGHTPADDING",  (0,0),(-1,-1), 8),
]))
story += [flow4_t, SP(6)]

story += [Paragraph("5.2  ABG Targets During BiPAP", STYLE["h2"])]
target_headers = ["Parameter", "Target During NIV", "COPD-Specific", "Notes"]
target_rows = [
    ["pH",       "> 7.35",          "> 7.35",           "Primary endpoint of NIV success"],
    ["PaCO₂",    "Gradual ↓",       "Toward chronic baseline", "Do NOT drop > 10 mmHg/hr — risk of seizures"],
    ["PaO₂",     "55–80 mmHg",      "55–75 mmHg",       "Avoid excessive oxygenation in COPD"],
    ["SpO₂",     "92–96%",          "88–92%",           "Hyperoxia abolishes hypoxic drive"],
    ["HCO₃⁻",   "Will remain ↑",   "Days to normalise","Renal excretion of buffer takes days"],
    ["RR",        "< 25/min",        "< 25/min",         "Falling RR = sign of success"],
    ["Tidal Vol","6–8 mL/kg IBW",   "6–8 mL/kg IBW",    "Adjust IPAP to achieve target Vt"],
]
story += [simple_table(target_headers, target_rows,
                       [3.0*cm, 3.5*cm, 3.5*cm, 6.0*cm], hdr_color=TEAL), SP(8)]

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 6 — MONITORING
# ══════════════════════════════════════════════════════════════════════════════
story += [section_header("6. MONITORING SCHEDULE"), SP(6)]

mon_headers = ["Time Point", "Continuous", "Intermittent", "ABG / Labs"]
mon_rows = [
    ["0 min (Baseline)", "SpO₂, HR, RR, BP", "GCS, WOB assessment", "ABG, VBG, FBC, U&E, lactate, CXR"],
    ["5–15 min",         "SpO₂, HR, RR",     "Mask fit, synchrony, comfort", "—"],
    ["30–60 min",        "SpO₂, HR, RR",     "WOB, GCS",                "ABG (most critical check)"],
    ["4 hours",          "SpO₂, HR, RR, BP", "Full clinical review",    "ABG; adjust if setting change"],
    ["Every 4–6 hrs",    "SpO₂, HR, RR",     "GCS, tolerance",          "ABG if clinically indicated"],
    ["After any change", "SpO₂, HR, RR",     "Comfort, synchrony",      "ABG 1 hr after change"],
    ["12 hrs",           "Cardiac monitoring","Full assessment",         "ABG, U&E, glucose"],
]
story += [simple_table(mon_headers, mon_rows,
                       [3.2*cm, 4.0*cm, 4.2*cm, 4.6*cm], hdr_color=TEAL), SP(6)]

asyn_items = [
    Paragraph("6.1  Managing Patient-Ventilator Asynchrony", STYLE["h2"]),
    B("Inspiratory leaks → prolonged inspiration (most common). Fix: adjust mask harness, re-seat mask, try different size.", "bullet"),
    B("Expiratory leaks → auto-triggering. Fix: use NIV-dedicated ventilator with leak compensation algorithm.", "bullet"),
    B("Asynchrony > 10% of breaths = significant. Adjust trigger sensitivity and cycling criteria.", "bullet"),
    B("Persistent asynchrony despite optimisation → consider changing interface type.", "bullet"),
]
story += asyn_items + [SP(8)]

# ══════════════════════════════════════════════════════════════════════════════
# PAGE BREAK
# ══════════════════════════════════════════════════════════════════════════════
story += [PageBreak()]

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 7 — RESPONSE & FAILURE CRITERIA
# ══════════════════════════════════════════════════════════════════════════════
story += [section_header("7. RESPONSE CRITERIA & FAILURE PROTOCOL"), SP(6)]

success_items = [
    Paragraph("✔  SIGNS OF NIV SUCCESS — CONTINUE BiPAP", STYLE["h2"]),
    B("pH trending up toward > 7.35", "bullet_grn"),
    B("PaCO₂ falling gradually (not precipitously)", "bullet_grn"),
    B("SpO₂ at target on stable or reduced FiO₂", "bullet_grn"),
    B("RR decreasing (< 25 breaths/min)", "bullet_grn"),
    B("Accessory muscle use decreasing", "bullet_grn"),
    B("Patient subjectively more comfortable", "bullet_grn"),
    B("Good patient-ventilator synchrony", "bullet_grn"),
    B("GCS stable or improving", "bullet_grn"),
]
failure_items = [
    Paragraph("✘  SIGNS OF NIV FAILURE — ESCALATE / INTUBATE", STYLE["h2"]),
    B("pH < 7.25 at 60 min despite optimised BiPAP", "bullet_red"),
    B("PaCO₂ not improving or worsening", "bullet_red"),
    B("GCS falling or < 8", "bullet_red"),
    B("RR > 35/min persisting after 60 min", "bullet_red"),
    B("Haemodynamic deterioration (SBP < 90 mmHg)", "bullet_red"),
    B("Inability to maintain SpO₂ target on BiPAP", "bullet_red"),
    B("Excessive secretions / aspiration event", "bullet_red"),
    B("Patient unable to tolerate mask", "bullet_red"),
]
story += [two_col(
    coloured_box(success_items, bg=LIGHT_GRN, border=GREEN),
    coloured_box(failure_items, bg=LIGHT_RED, border=RED)
), SP(4)]

fail_protocol = [
    Paragraph("7.1  NIV Failure Action Protocol", STYLE["h2"]),
    B("<b>Immediate:</b> Call senior physician (SpR/Consultant) + Anaesthesia if pH < 7.25 at 60 min", "bullet"),
    B("<b>Prepare:</b> RSI drugs, intubation equipment, bougie, video laryngoscope", "bullet"),
    B("<b>Pre-oxygenate:</b> BiPAP can be used for pre-oxygenation prior to intubation (superior to bag-mask)", "bullet"),
    B("<b>Post-intubation targets:</b> Vt 6–8 mL/kg IBW, PEEP 5 cmH₂O, RR 12–16, FiO₂ 1.0 initially", "bullet"),
    SP(2),
    Paragraph(
        "Evidence: NPPV reduces intubation in COPD by 65%; NNT = 12. "
        "NIV failure with delayed intubation is associated with higher mortality than early intubation.",
        STYLE["note"]),
]
story += fail_protocol + [SP(8)]

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 8 — WEANING
# ══════════════════════════════════════════════════════════════════════════════
story += [section_header("8. WEANING FROM BiPAP"), SP(6)]

story += [Paragraph("8.1  Criteria for Initiating Wean (all should be present)", STYLE["h2"])]
wean_criteria = [
    B("pH > 7.35 on two consecutive ABGs", "bullet_grn"),
    B("PaCO₂ at or near patient's chronic baseline", "bullet_grn"),
    B("SpO₂ > 90% on ≤ 4 L/min supplemental O₂", "bullet_grn"),
    B("RR < 24 breaths/min consistently", "bullet_grn"),
    B("Underlying cause treated / improving", "bullet_grn"),
    B("Patient awake, cooperative, managing secretions", "bullet_grn"),
    B("Minimum 4 hours continuous BiPAP completed", "bullet_grn"),
]
story += wean_criteria + [SP(5)]

story += [Paragraph("8.2  Step-by-Step Weaning Protocol", STYLE["h2"])]
wean_tbl = [
    [Paragraph("Wean Step", STYLE["th"]), Paragraph("Action", STYLE["th"]),
     Paragraph("Interval", STYLE["th"]), Paragraph("Monitor / Check", STYLE["th"])],
    [Paragraph("Step 1", STYLE["td_bold"]),
     Paragraph("↓ FiO₂ toward 0.28–0.35 while maintaining SpO₂ target", STYLE["td"]),
     Paragraph("q30–60 min", STYLE["td_c"]),
     Paragraph("SpO₂, RR", STYLE["td"])],
    [Paragraph("Step 2", STYLE["td_bold"]),
     Paragraph("↓ IPAP by 2 cmH₂O every 2–4 hours", STYLE["td"]),
     Paragraph("q2–4 hrs", STYLE["td_c"]),
     Paragraph("RR, WOB, SpO₂", STYLE["td"])],
    [Paragraph("Step 3", STYLE["td_bold"]),
     Paragraph("Trial 1–2 hour break from BiPAP with nasal cannula O₂", STYLE["td"]),
     Paragraph("Once IPAP ≤ 14", STYLE["td_c"]),
     Paragraph("SpO₂, RR, WOB, GCS", STYLE["td"])],
    [Paragraph("Step 4", STYLE["td_bold"]),
     Paragraph("ABG 30–60 min after BiPAP removal; check for deterioration", STYLE["td"]),
     Paragraph("After each break", STYLE["td_c"]),
     Paragraph("ABG, clinical assessment", STYLE["td"])],
    [Paragraph("Step 5", STYLE["td_bold"]),
     Paragraph("↓ EPAP last — reduce to 4 cmH₂O before discontinuing BiPAP", STYLE["td"]),
     Paragraph("Final step", STYLE["td_c"]),
     Paragraph("Mask tolerance, SpO₂", STYLE["td"])],
    [Paragraph("Step 6", STYLE["td_bold"]),
     Paragraph("Discharge to ward on supplemental O₂ via Venturi/nasal cannula", STYLE["td"]),
     Paragraph("After 2+ successful breaks", STYLE["td_c"]),
     Paragraph("Reassess at 24 hrs", STYLE["td"])],
]
wean_t = Table(wean_tbl, colWidths=[2.0*cm, 6.5*cm, 2.8*cm, 4.7*cm])
wean_t.setStyle(TableStyle([
    ("BACKGROUND",    (0,0),(-1,0), NAVY),
    ("BACKGROUND",    (0,2),(-1,2), LIGHT_TEAL),
    ("BACKGROUND",    (0,4),(-1,4), LIGHT_TEAL),
    ("BACKGROUND",    (0,6),(-1,6), LIGHT_TEAL),
    ("GRID",          (0,0),(-1,-1), 0.4, colors.HexColor("#BDC3C7")),
    ("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"),
    ("ALIGN",         (2,1),(2,-1), "CENTER"),
]))
story += [wean_t, SP(8)]

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 9 — MAINTENANCE & CONCURRENT TREATMENTS
# ══════════════════════════════════════════════════════════════════════════════
story += [section_header("9. MAINTENANCE & CONCURRENT TREATMENTS"), SP(6)]

maint_left = [
    Paragraph("<b>Concurrent Medical Therapy</b>", STYLE["bold"]),
    SP(2),
    Paragraph("<i>COPD Exacerbation:</i>", STYLE["body"]),
    B("Nebulised SABA (salbutamol 2.5–5 mg) q20 min × 3, then q4–6 hrs", "bullet"),
    B("Nebulised ipratropium 0.5 mg q6–8 hrs", "bullet"),
    B("Prednisolone 40 mg PO/IV × 5 days", "bullet"),
    B("Antibiotics if purulent sputum / CRP > 20 / consolidation on CXR", "bullet"),
    SP(4),
    Paragraph("<i>Cardiogenic Pulmonary Oedema:</i>", STYLE["body"]),
    B("IV furosemide 40–80 mg stat (titrate)", "bullet"),
    B("IV GTN infusion (if SBP > 100 mmHg)", "bullet"),
    B("Treat precipitant (ACS, AF, hypertensive crisis)", "bullet"),
]
maint_right = [
    Paragraph("<b>Supportive Care on BiPAP</b>", STYLE["bold"]),
    SP(2),
    B("Nurse at 30–45° head-of-bed elevation", "bullet"),
    B("Continuous SpO₂ and cardiac monitoring × 12 hrs minimum", "bullet"),
    B("Oral care and skin protection at mask contact points", "bullet"),
    B("NG tube if > 24 hrs NIV or risk of aspiration", "bullet"),
    B("DVT prophylaxis once stabilised", "bullet"),
    B("Avoid benzodiazepines / opioids during NIV", "bullet"),
    B("Nutritional support — do NOT pause NIV for meals until stable", "bullet"),
    SP(4),
    Paragraph("<b>Minimum Continuous Duration:</b> 4 hrs for acute exacerbation", STYLE["bold"]),
]
story += [two_col(maint_left, maint_right), SP(8)]

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 10 — HOME / LONG-TERM NIV
# ══════════════════════════════════════════════════════════════════════════════
story += [section_header("10. HOME NIV — POST-DISCHARGE GUIDANCE"), SP(6)]

home_items = [
    Paragraph(
        "For patients with <b>persistent hypercapnia</b> (PaCO₂ ≥ 52 mmHg) 2–4 weeks after "
        "discharge following an acute COPD exacerbation requiring NIV:",
        STYLE["body"]),
    SP(4),
]
home_tbl = [
    [Paragraph("Parameter", STYLE["th"]), Paragraph("Recommendation", STYLE["th"]),
     Paragraph("Evidence", STYLE["th"])],
    [Paragraph("Indication threshold", STYLE["td_bold"]),
     Paragraph("PaCO₂ ≥ 52 mmHg, 2–4 weeks post-discharge", STYLE["td"]),
     Paragraph("NNT = 6 to prevent one readmission (Fishman's)", STYLE["td"])],
    [Paragraph("Mode", STYLE["td_bold"]),
     Paragraph("BiPAP S/T (or AVAPS for variable disease)", STYLE["td"]),
     Paragraph("AVAPS assures consistent Vt despite progression", STYLE["td"])],
    [Paragraph("Pressure support target", STYLE["td_bold"]),
     Paragraph("IPAP−EPAP ≥ 15 cmH₂O (high-intensity)", STYLE["td"]),
     Paragraph("High-PS reduces dynamic hyperinflation, improves V/Q", STYLE["td"])],
    [Paragraph("IPAP target (home)", STYLE["td_bold"]),
     Paragraph("20–30 cmH₂O (titrate to eucapnia)", STYLE["td"]),
     Paragraph("Target PaCO₂ reduction ≥ 20% or to normal", STYLE["td"])],
    [Paragraph("Backup RR", STYLE["td_bold"]),
     Paragraph("12–16/min (started at 12; titrate)", STYLE["td"]),
     Paragraph("I:E 1:3, short rise time", STYLE["td"])],
    [Paragraph("Min daily usage", STYLE["td_bold"]),
     Paragraph("≥ 4–5 hours/night", STYLE["td"]),
     Paragraph("More hours = better CO₂ control", STYLE["td"])],
    [Paragraph("Combine with LTOT", STYLE["td_bold"]),
     Paragraph("Yes — add to long-term O₂ therapy", STYLE["td"]),
     Paragraph("Home NIPPV + LTOT improves admission-free survival", STYLE["td"])],
    [Paragraph("Follow-up ABG", STYLE["td_bold"]),
     Paragraph("4–6 weeks, then 3–6 monthly", STYLE["td"]),
     Paragraph("Titrate settings as disease evolves", STYLE["td"])],
]
home_t = Table(home_tbl, colWidths=[3.8*cm, 5.5*cm, 6.7*cm])
home_t.setStyle(TableStyle([
    ("BACKGROUND",    (0,0),(-1,0), NAVY),
    ("BACKGROUND",    (0,2),(-1,2), LIGHT_TEAL),
    ("BACKGROUND",    (0,4),(-1,4), LIGHT_TEAL),
    ("BACKGROUND",    (0,6),(-1,6), LIGHT_TEAL),
    ("BACKGROUND",    (0,8),(-1,8), LIGHT_TEAL),
    ("GRID",          (0,0),(-1,-1), 0.4, colors.HexColor("#BDC3C7")),
    ("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"),
]))
story += home_items + [home_t, SP(8)]

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 11 — QUICK REFERENCE CARD
# ══════════════════════════════════════════════════════════════════════════════
story += [section_header("11. QUICK REFERENCE CARD", color=RED), SP(6)]

qr_content = """
<b>INDICATION:</b>  pH 7.25–7.35  |  PaCO₂ > 45 mmHg  |  RR > 25  |  ↑WOB  |  Cooperative patient

<b>INITIATE:</b>    IPAP 10–12 / EPAP 4–5 cmH₂O  |  Mode: S/T  |  Backup RR 12–16  |  FiO₂ 1.0
              Full-face mask  |  30–45° head-up position

<b>TITRATE:</b>     ↑ IPAP by 2 cmH₂O q5–10 min if: WOB high / RR > 25 / Vt low / PaCO₂ not falling
              ↑ EPAP by 1–2 cmH₂O if: SpO₂ < 88% (then also ↑ IPAP to maintain PS)
              Target PS (IPAP−EPAP) > 10–15 cmH₂O  |  Max IPAP 20–25 cmH₂O

<b>TARGETS:</b>     pH > 7.35  |  PaCO₂ ↓ gradually (< 10 mmHg/hr)
              SpO₂ 88–92% (COPD) / 92–96% (other)  |  RR < 25  |  Vt 6–8 mL/kg IBW

<b>ABG CHECK:</b>   Baseline → 60 min → 4 hrs → q4–6 hrs  |  After every change: ABG at 1 hr

<b>FAILURE →</b>    pH < 7.25 at 60 min  |  GCS ↓  |  RR > 35  |  No CO₂ improvement
<b>INTUBATE:</b>    Call senior + anaesthesia STAT  |  Prepare RSI kit
"""
qr_para = Paragraph(qr_content, ParagraphStyle(
    "qr", fontSize=8.5, fontName="Courier",
    textColor=BLACK, leading=14, leftIndent=6
))
story += [coloured_box([qr_para], bg=LIGHT_AMB, border=ORANGE), SP(8)]

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 12 — DOCUMENTATION & GOVERNANCE
# ══════════════════════════════════════════════════════════════════════════════
story += [section_header("12. DOCUMENTATION & GOVERNANCE"), SP(6)]

doc_items = [
    Paragraph("12.1  Mandatory Documentation", STYLE["h2"]),
    B("Time and indication for BiPAP initiation", "bullet"),
    B("Interface type and initial settings (IPAP/EPAP/RR/FiO₂/mode)", "bullet"),
    B("All ABG results with time and settings at time of ABG", "bullet"),
    B("All setting changes with reason and clinician name", "bullet"),
    B("Response assessment at 60 min", "bullet"),
    B("NIV care bundle completion checklist", "bullet"),
    B("Weaning plan and discharge NIV prescription if applicable", "bullet"),
    SP(4),
    Paragraph("12.2  References & Evidence Base", STYLE["h2"]),
    Paragraph(
        "1. Murray & Nadel's Textbook of Respiratory Medicine, 7th ed. — CPAP and BiPAP section\n"
        "2. Fishman's Pulmonary Diseases and Disorders — NIV in COPD (p.2533)\n"
        "3. Brenner & Rector's The Kidney — Respiratory Acid-Base Disorders (p.707)\n"
        "4. Rosen's Emergency Medicine — Noninvasive Ventilation (p.48–49)\n"
        "5. BTS/ICS Guidelines for NIV in Acute Hypercapnic Respiratory Failure\n"
        "6. Özsancak Uğurlu A, Ergan B. Pulmonology 2023 Mar–Apr. [PMID: 36137890]\n"
        "7. Farmer MJS et al. Chest 2024 Jun. [PMID: 38417700]\n"
        "8. AASM Best Practice Guide — NPPV Titration, J Clin Sleep Med 2010;6(5)",
        STYLE["ref"]),
]
story += doc_items + [SP(8)]

# ── Final note ───────────────────────────────────────────────────────────────
final_note = [
    Paragraph(
        "This protocol is intended as a clinical decision-support tool. It does not replace "
        "clinical judgment. Individual patient circumstances may require deviation from these "
        "guidelines. All deviations should be documented with rationale. Senior review is "
        "mandatory when pH < 7.25 or clinical deterioration occurs despite NIV.",
        STYLE["caption"]),
]
story += [HR(color=NAVY), SP(3)] + final_note

# ─── Build ────────────────────────────────────────────────────────────────────
doc.build(story,
          onFirstPage=on_first_page,
          onLaterPages=on_page)

print(f"PDF generated: {OUT}")
print(f"File size: {os.path.getsize(OUT):,} bytes")
Running Command

cd /home/daytona/workspace/resp-acidosis-protocol && python3 build_protocol.py 2>&1

Editing File

~/resp-acidosis-protocol/build_protocol.py

Error: String not found in file: 'from reportlab.graphics.shapes import Drawing, Rect, String, Line, Arrow
from reportlab.graphics import renderPDF
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Arrow'
Running Command

head -25 /home/daytona/workspace/resp-acidosis-protocol/build_protocol.py | cat -n

Running Command

sed -i '16s/.*/from reportlab.graphics.shapes import Drawing, Rect, String, Line, Polygon/' /home/daytona/workspace/resp-acidosis-protocol/build_protocol.py && sed -i '17s/.*/from reportlab.graphics import renderPDF/' /home/daytona/workspace/resp-acidosis-protocol/build_protocol.py && sed -i '18d' /home/daytona/workspace/resp-acidosis-protocol/build_protocol.py && head -22 /home/daytona/workspace/resp-acidosis-protocol/build_protocol.py

Running Command

python3 -c " content = open('/home/daytona/workspace/resp-acidosis-protocol/build_protocol.py').read() content = content.replace( 'from reportlab.graphics.shapes import Drawing, Rect, String, Line, Polygon\nfrom reportlab.graphics import renderPDF\nfrom reportlab.graphics.shapes import Drawing, Rect, String, Line, Arrow', 'from reportlab.graphics.shapes import Drawing, Rect, String, Line, Polygon\nfrom reportlab.graphics import renderPDF' ) open('/home/daytona/workspace/resp-acidosis-protocol/build_protocol.py','w').write(content) print('done') "

Running Command

cd /home/daytona/workspace/resp-acidosis-protocol && python3 build_protocol.py 2>&1

The PDF has been generated successfully. Here's your download link:

Acute Respiratory Acidosis Protocol

PDF Document · PDF


What's Inside the Protocol (12 Sections, ~30 KB, A4 Format)

SectionContent
CoverDocument number, version, effective/review dates, department
1. Diagnostic CriteriaABG table with normal vs. acidosis values, compensation formulae (acute vs. chronic), common causes in two columns
2. Initial Assessment5-point rapid assessment table (airway → haemodynamics → ABG)
3. Decision PathwayGreen box (BiPAP indications) vs. Red box (contraindications/intubate), NIV failure predictors
4. BiPAP SetupInterface selection table, mode selection guidance, phenotype-specific settings (COPD / Cardiogenic / OHS-NMD)
5. Titration ProtocolStep-by-step 4-phase flow (Initiate → Observe → Titrate → Recheck ABG), ABG targets table
6. MonitoringSchedule from baseline to 12 hrs; asynchrony management
7. Response & FailureSuccess criteria (green) vs. failure criteria (red), NIV failure action protocol
8. WeaningWean criteria checklist, 6-step weaning table with intervals
9. MaintenanceConcurrent treatments (COPD / APO), supportive care checklist
10. Home NIVPost-discharge persistent hypercapnia guidance, AVAPS, LTOT, home settings targets
11. Quick Reference CardMonospace card with all key numbers at a glance
12. Documentation & ReferencesMandatory charting points, 8 evidence-based references (textbooks + PubMed PMIDs)
The PDF has a running header on every page identifying the protocol title and page number, and a navy footer with version and review date.
This is a shared conversation. Sign in to Orris to start your own chat.