Write a 30 marks answer for Postgraduate Anaesthesia exam on the topic of Capnography and Capnometry
| Feature | Mainstream (Non-diverting) | Sidestream (Diverting) |
|---|---|---|
| Sensor location | In-line in the breathing circuit | Remote - at the monitor console |
| Sample method | Gas analysed in the airway | Gas aspirated via thin tubing (30-500 mL/min) |
| Response time | Fast - minimal lag | Delayed - aspiration lag time |
| Weight on airway | Adds dead space and weight | None added to circuit |
| Water interference | Less prone | Prone to water condensation and blockage |
| Neonatal use | Less suitable (added dead space) | Preferred; but high flow rates can entrain fresh gas and underestimate ETCO2 |
| Common use | Less common clinically | Most common in operating rooms |
| Capnogram Pattern | Clinical Cause |
|---|---|
| Absent waveform | Oesophageal intubation, circuit disconnect, cardiac arrest |
| Elevated baseline (phase 0 non-zero) | CO2 rebreathing - exhausted absorber, faulty valves |
| Steep phase III upslope (shark-fin pattern) | Obstructive airway disease (asthma, COPD) |
| Sudden fall to zero | Circuit disconnect, ETT obstruction, pulmonary embolism, cardiac arrest |
| Gradual rise in ETCO2 | Hypoventilation, rising metabolic rate |
| Rapid marked rise | Malignant hyperthermia, CO2 pneumoperitoneum |
| Dip in phase III plateau | Spontaneous respiratory effort during IPPV |
| Cleft in waveform | Curare cleft - partial neuromuscular blockade, spontaneous effort |
| Gradual fall of ETCO2 | Hyperventilation, decreasing cardiac output, hypothermia |
| Return of waveform after arrest | ROSC during CPR |
Convert the above answer into pdf
ls /home/daytona/workspace/ 2>/dev/null || mkdir -p /home/daytona/workspace
~/capnography_pdf/generate_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.lib import colors
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, PageBreak, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import ListFlowable, ListItem
OUTPUT = "/home/daytona/workspace/capnography_pdf/Capnography_and_Capnometry_PG_Anaesthesia.pdf"
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
rightMargin=2*cm,
leftMargin=2*cm,
topMargin=2.2*cm,
bottomMargin=2.2*cm,
title="Capnography and Capnometry – PG Anaesthesia Exam Answer",
author="Orris Medical AI",
)
styles = getSampleStyleSheet()
# Custom styles
title_style = ParagraphStyle(
'CustomTitle',
parent=styles['Title'],
fontSize=20,
textColor=colors.HexColor('#1a2a4a'),
spaceAfter=6,
leading=26,
alignment=TA_CENTER,
)
subtitle_style = ParagraphStyle(
'Subtitle',
parent=styles['Normal'],
fontSize=11,
textColor=colors.HexColor('#4a6fa5'),
spaceAfter=2,
alignment=TA_CENTER,
italic=True,
)
marks_style = ParagraphStyle(
'Marks',
parent=styles['Normal'],
fontSize=10,
textColor=colors.white,
backColor=colors.HexColor('#1a2a4a'),
spaceBefore=4,
spaceAfter=10,
alignment=TA_CENTER,
borderPadding=(5, 8, 5, 8),
)
h1_style = ParagraphStyle(
'H1',
parent=styles['Heading1'],
fontSize=13,
textColor=colors.white,
backColor=colors.HexColor('#1a2a4a'),
spaceBefore=14,
spaceAfter=6,
leading=18,
borderPadding=(6, 8, 6, 8),
)
h2_style = ParagraphStyle(
'H2',
parent=styles['Heading2'],
fontSize=11,
textColor=colors.HexColor('#1a2a4a'),
spaceBefore=10,
spaceAfter=4,
leading=15,
borderPadding=(0, 0, 2, 0),
)
body_style = ParagraphStyle(
'Body',
parent=styles['Normal'],
fontSize=10,
textColor=colors.HexColor('#222222'),
spaceAfter=5,
leading=15,
alignment=TA_JUSTIFY,
)
bullet_style = ParagraphStyle(
'Bullet',
parent=styles['Normal'],
fontSize=10,
textColor=colors.HexColor('#222222'),
spaceAfter=3,
leading=14,
leftIndent=14,
bulletIndent=0,
alignment=TA_LEFT,
)
formula_style = ParagraphStyle(
'Formula',
parent=styles['Normal'],
fontSize=10,
textColor=colors.HexColor('#1a2a4a'),
backColor=colors.HexColor('#eef2f8'),
spaceAfter=6,
spaceBefore=4,
leading=15,
alignment=TA_CENTER,
borderPadding=(6, 10, 6, 10),
)
ref_style = ParagraphStyle(
'Ref',
parent=styles['Normal'],
fontSize=9,
textColor=colors.HexColor('#555555'),
spaceAfter=3,
leading=13,
leftIndent=12,
italic=True,
)
footer_style = ParagraphStyle(
'Footer',
parent=styles['Normal'],
fontSize=8,
textColor=colors.HexColor('#888888'),
alignment=TA_CENTER,
spaceAfter=0,
)
def h1(text):
return Paragraph(text, h1_style)
def h2(text):
return Paragraph(text, h2_style)
def body(text):
return Paragraph(text, body_style)
def bullet(text):
return Paragraph(f"• {text}", bullet_style)
def formula(text):
return Paragraph(text, formula_style)
def sp(h=6):
return Spacer(1, h)
def hr():
return HRFlowable(width="100%", thickness=0.5, color=colors.HexColor('#c0c8d8'), spaceAfter=4, spaceBefore=4)
story = []
# ── TITLE BLOCK ────────────────────────────────────────────────────────────────
story.append(sp(10))
story.append(Paragraph("Capnography and Capnometry", title_style))
story.append(Paragraph("Postgraduate Anaesthesia Examination Model Answer", subtitle_style))
story.append(Paragraph("Total Marks: 30", marks_style))
story.append(hr())
story.append(sp(4))
# ── SECTION 1 ──────────────────────────────────────────────────────────────────
story.append(h1("1. Definitions and Terminology [3 marks]"))
story.append(sp(4))
story.append(body(
"Considerable confusion arises from the interchangeable use of terms in clinical practice. "
"The following distinctions are essential:"
))
items = [
("<b>Capnometry</b> – measurement and numeric quantification of inhaled or exhaled CO₂ concentrations "
"at the airway opening. A <b>capnometer</b> displays only a numeric CO₂ value."),
("<b>Capnography</b> – measurement of CO₂ <i>and</i> its graphic display as a function of time or "
"expired volume. A <b>capnograph</b> records and displays the waveform; the waveform itself is the <b>capnogram</b>."),
("<b>End-tidal CO₂ (ETCO₂ / PETCO₂)</b> – the peak partial pressure of CO₂ at the end of exhalation, "
"approximating alveolar CO₂ and, under normal conditions, closely estimating arterial PaCO₂."),
]
for i in items:
story.append(bullet(i))
story.append(sp(2))
story.append(Paragraph("<i>Miller's Anesthesia, 10e</i>", ref_style))
# ── SECTION 2 ──────────────────────────────────────────────────────────────────
story.append(h1("2. Physiological Basis [4 marks]"))
story.append(sp(4))
story.append(body(
"CO₂ is a byproduct of aerobic cellular metabolism and is transported via the circulation to the lungs. "
"Exhaled CO₂ reflects the integration of three fundamental physiological processes:"
))
for i in [
"<b>Cellular metabolism</b> – CO₂ production (VCO₂)",
"<b>Cardiovascular transport</b> – delivery of CO₂ to the pulmonary circulation (cardiac output)",
"<b>Pulmonary ventilation</b> – elimination of CO₂ by the lungs",
]:
story.append(bullet(i))
story.append(sp(4))
story.append(body(
"Under steady-state conditions in a healthy patient, ETCO₂ is <b>2–5 mmHg lower than PaCO₂</b>. "
"This gradient reflects <b>alveolar dead space</b> – alveoli that are ventilated but not perfused. "
"When pulmonary perfusion is reduced (e.g., pulmonary embolism, air embolism, reduced cardiac output), "
"alveolar dead space increases, CO₂ is diluted in exhaled gas, and this gradient widens."
))
story.append(sp(4))
story.append(body(
"ETCO₂ combined with PaCO₂ allows estimation of the physiological dead space fraction using the "
"<b>modified Bohr equation</b>:"
))
story.append(formula("Vd / Vt = (PaCO₂ − P̄ECO₂) / PaCO₂"))
story.append(body(
"where P̄ECO₂ is the mixed expired CO₂ partial pressure. Normal Vd/Vt is 0.2–0.3 at rest but rises "
"substantially in lung disease."
))
story.append(Paragraph("<i>Miller's Anesthesia, 10e; Morgan & Mikhail's Clinical Anesthesiology, 7e</i>", ref_style))
# ── SECTION 3 ──────────────────────────────────────────────────────────────────
story.append(h1("3. Technology: Principles of Measurement [4 marks]"))
story.append(sp(4))
story.append(h2("Non-dispersive Infrared Absorption Spectrophotometry (NDIR)"))
story.append(body(
"The most widely used clinical method is <b>NDIR absorption</b>. CO₂ is an asymmetric polyatomic molecule "
"that strongly absorbs infrared light at <b>4.3 µm (4.26 µm)</b>. This principle is governed by the "
"<b>Beer-Lambert Law</b>: absorption is directly proportional to the CO₂ concentration in the sample. "
"As CO₂ concentration rises, infrared transmission falls proportionally. Since CO₂'s absorption spectrum "
"partially overlaps with water vapour and nitrous oxide, infrared filters and compensation algorithms minimise interference."
))
story.append(sp(3))
story.append(body(
"Other methods (now largely of historical interest): mass spectrometry, Raman spectrometry, gas chromatography, "
"piezoelectric crystal oscillation."
))
story.append(sp(6))
story.append(h2("Mainstream vs. Sidestream Capnometers"))
table_data = [
[
Paragraph("<b>Feature</b>", body_style),
Paragraph("<b>Mainstream (Non-diverting)</b>", body_style),
Paragraph("<b>Sidestream (Diverting)</b>", body_style),
],
["Sensor location", "In-line in the breathing circuit", "Remote – at the monitor console"],
["Aspiration", "None – gas analysed in the airway", "Gas aspirated via thin tubing (30–500 mL/min)"],
["Response time", "Fast – minimal lag", "Delayed – aspiration lag time"],
["Weight on circuit", "Adds dead space + weight to airway", "No added weight to circuit"],
["Water interference", "Less prone", "Prone to water condensation + blockage"],
["Neonatal use", "Less suitable (added dead space)", "Preferred; but high flows may underestimate ETCO₂"],
["Common use", "Less common", "Most common in operating rooms"],
]
col_widths = [3.8*cm, 6.5*cm, 6.5*cm]
t = Table(table_data, colWidths=col_widths, repeatRows=1)
t.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#1a2a4a')),
('TEXTCOLOR', (0, 0), (-1, 0), colors.white),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('FONTSIZE', (0, 0), (-1, -1), 9),
('ROWBACKGROUNDS', (0, 1), (-1, -1), [colors.HexColor('#f4f6fb'), colors.white]),
('GRID', (0, 0), (-1, -1), 0.4, colors.HexColor('#c0c8d8')),
('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
('TOPPADDING', (0, 0), (-1, -1), 5),
('BOTTOMPADDING', (0, 0), (-1, -1), 5),
('LEFTPADDING', (0, 0), (-1, -1), 6),
('RIGHTPADDING', (0, 0), (-1, -1), 6),
]))
story.append(t)
story.append(sp(4))
story.append(body(
"Sidestream units aspirate gas through ~6 feet of tubing. This represents a small circuit leak and must be "
"scavenged or returned. In neonates, high aspiration rates entrain fresh gas, diluting ETCO₂ and causing underestimation."
))
story.append(Paragraph("<i>Miller's Anesthesia, 10e; Barash's Clinical Anesthesia, 9e</i>", ref_style))
# ── SECTION 4 ──────────────────────────────────────────────────────────────────
story.append(h1("4. The Capnogram: Waveform Analysis [5 marks]"))
story.append(sp(4))
story.append(h2("Time Capnogram – Phases"))
story.append(body(
"The time capnogram plots CO₂ partial pressure (y-axis) against time (x-axis) and shows a characteristic "
"repeating waveform divided into distinct phases:"
))
phases = [
("<b>Phase 0 (Inspiration):</b> CO₂ falls rapidly to near zero as fresh inspired gas washes the sampling site. "
"A non-zero baseline indicates CO₂ rebreathing."),
("<b>Phase I (Dead Space Expiration):</b> Initial flat portion at near-zero CO₂. Represents exhalation of "
"gas from anatomical dead space (conducting airways, equipment dead space) – no CO₂."),
("<b>Phase II (Transitional / Ascending):</b> Sharp steep rise in CO₂ representing the transition from dead "
"space to alveolar gas. The angle between phases II and III is the <b>alpha (α) angle</b> – widened in "
"obstructive disease."),
("<b>Phase III (Alveolar Plateau):</b> Plateau representing exhalation of alveolar gas. Near-flat in healthy "
"lungs. Slight upslope is normal due to sequential V/Q-dependent alveolar emptying. Steeper upslope (increased "
"S-slope) is seen in asthma and COPD. The peak value at end-expiration is the <b>ETCO₂</b> value."),
("<b>Phase IV (some patients):</b> A brief upstroke at the very end of phase III before inspiration. Caused "
"by closure of low-CO₂ lung units, allowing higher-CO₂ regions to contribute more to the exhaled sample."),
]
for p in phases:
story.append(bullet(p))
story.append(sp(5))
story.append(body(
"The <b>beta (β) angle</b> is formed between the end of phase III and the descending limb back to baseline. "
"An obtuse beta angle with failure to return to zero indicates rebreathing (exhausted CO₂ absorber, faulty valves)."
))
story.append(sp(6))
story.append(h2("Volume Capnogram"))
story.append(body(
"The volume capnogram plots CO₂ partial pressure against exhaled <i>volume</i> (not time). Advantages over "
"the time capnogram include:"
))
for v in [
"Estimation of relative contributions of anatomic vs. alveolar dead space",
"Greater sensitivity to subtle dead space changes caused by alterations in PEEP or pulmonary blood flow",
"Estimation of total CO₂ elimination (VCO₂) per breath from the area under the curve",
"Assessment of cardiac output and fluid responsiveness",
]:
story.append(bullet(v))
story.append(Paragraph("<i>Miller's Anesthesia, 10e</i>", ref_style))
# ── SECTION 5 ──────────────────────────────────────────────────────────────────
story.append(h1("5. Normal Values and ETCO₂–PaCO₂ Gradient [2 marks]"))
story.append(sp(4))
for v in [
"Normal ETCO₂: <b>35–45 mmHg</b> (4.6–6.0 kPa) in a healthy spontaneously breathing or ventilated patient",
"Normal PaCO₂–ETCO₂ gradient: <b>2–5 mmHg</b>",
"In patients with significant V/Q mismatch, pulmonary hypertension, or low cardiac output, this gradient "
"widens substantially. ETCO₂ becomes an unreliable surrogate for PaCO₂ – arterial blood gas analysis is required for accuracy.",
]:
story.append(bullet(v))
# ── SECTION 6 ──────────────────────────────────────────────────────────────────
story.append(h1("6. Causes of Abnormal ETCO₂ [4 marks]"))
story.append(sp(4))
story.append(h2("Causes of Elevated ETCO₂ (Hypercapnia)"))
story.append(body("<b>Increased CO₂ production / delivery to lungs:</b>"))
for c in [
"Fever, sepsis",
"Seizures",
"Malignant hyperthermia – marked, rapid rise; key early warning",
"Thyrotoxicosis",
"Increased cardiac output (e.g., during effective CPR)",
"Laparoscopic surgery – CO₂ absorption from pneumoperitoneum",
"Bicarbonate administration – CO₂ generated from buffering",
]:
story.append(bullet(c))
story.append(sp(3))
story.append(body("<b>Decreased alveolar ventilation:</b>"))
for c in [
"Hypoventilation (opioid-induced respiratory depression, inadequate ventilator settings)",
"Partial neuromuscular blockade",
"High spinal or epidural anaesthesia",
"Airway obstruction",
]:
story.append(bullet(c))
story.append(sp(3))
story.append(body("<b>Equipment malfunction:</b>"))
for c in [
"Rebreathing – exhausted CO₂ absorber, faulty expiratory valve, insufficient fresh gas flow",
"Leak in the ventilator circuit",
]:
story.append(bullet(c))
story.append(sp(6))
story.append(h2("Causes of Decreased or Absent ETCO₂ (Hypocapnia / No Waveform)"))
story.append(body("<b>Decreased CO₂ production / delivery:</b>"))
for c in [
"Hypothermia",
"Pulmonary embolism – sudden fall; sensitive indicator",
"Venous air embolism – sudden fall; increases dead space and reduces cardiac output",
"Cardiac arrest",
"Haemorrhage, hypotension, severe reduction in cardiac output",
]:
story.append(bullet(c))
story.append(sp(3))
story.append(body("<b>Increased alveolar ventilation:</b>"))
story.append(bullet("Hyperventilation (deliberate or inadvertent)"))
story.append(sp(3))
story.append(body("<b>Equipment malfunction / patient safety events:</b>"))
for c in [
"Circuit disconnection – sudden loss of waveform",
"<b>Oesophageal intubation</b> – absent or rapidly disappearing waveform after intubation (most critical application)",
"Kinked or obstructed endotracheal tube",
"Sampling line blockage or water in the line",
"Leak around ETT cuff",
]:
story.append(bullet(c))
story.append(Paragraph("<i>Miller's Anesthesia, 10e (Table 37.2); Morgan & Mikhail's Clinical Anesthesiology, 7e</i>", ref_style))
# ── SECTION 7 ──────────────────────────────────────────────────────────────────
story.append(h1("7. Clinical Applications [5 marks]"))
story.append(sp(4))
apps = [
("(a) Confirmation of Endotracheal Tube Placement",
"The most critical application. Capnography reliably detects <b>oesophageal intubation</b>. Small amounts "
"of CO₂ from swallowed gas wash out within a few breaths; a persistent waveform confirms tracheal placement. "
"Capnography does <b>not</b> reliably detect mainstem bronchial intubation, as CO₂ continues to be exhaled from the contralateral lung."),
("(b) Monitoring Adequacy of Ventilation",
"Capnography is the <b>standard of care</b> for monitoring ventilation under general anaesthesia, mandated "
"by major anaesthetic societies (ASA, AAGBI). It is superior to pulse oximetry for detecting early "
"hypoventilation, especially with supplemental oxygen (SpO₂ may remain normal for several minutes despite "
"apnoea). Respiratory depression is <b>17.6 times</b> more likely to be detected with capnography than with standard monitoring alone."),
("(c) Procedural Sedation and MAC",
"Capnography detects airway and respiratory compromise earlier and more frequently than pulse oximetry during "
"procedural sedation. Studies show all episodes of apnoea >20 seconds during MAC were detected by capnography "
"but not by the anaesthetist. Capnography is now mandated for moderate and deep sedation in many guidelines."),
("(d) Detection of Malignant Hyperthermia",
"A marked, rapid rise in ETCO₂ due to greatly increased CO₂ production from hypermetabolism is one of the "
"<b>earliest and most sensitive</b> indicators of malignant hyperthermia, typically preceding temperature "
"elevation. Early detection permits prompt treatment."),
("(e) Detection of Venous Air/CO₂ Embolism",
"A <b>sudden sharp decrease</b> in ETCO₂ during laparoscopy, neurosurgery, or major vascular procedures "
"suggests venous air embolism. Both increased dead space and reduced cardiac output lower CO₂ delivery to "
"the lungs and reduce ETCO₂."),
("(f) Cardiopulmonary Resuscitation (CPR)",
"ETCO₂ monitors the adequacy of chest compressions. ETCO₂ <b><10 mmHg</b> after 20 minutes of CPR is "
"associated with very poor prognosis and can guide decisions about terminating resuscitation. A <b>sudden "
"rise</b> in ETCO₂ during CPR indicates return of spontaneous circulation (ROSC) before it is detectable "
"by pulse oximetry."),
("(g) Assessment of Dead Space and Pulmonary Blood Flow",
"ETCO₂ trends assess V/Q mismatch, pulmonary embolism, and changes in cardiac output. Rising dead space "
"fraction (Vd/Vt) can be estimated non-invasively."),
("(h) LMA Placement Confirmation",
"Persistent ETCO₂ waveforms confirm satisfactory positioning of a laryngeal mask airway and adequate gas exchange."),
]
for title, text in apps:
story.append(h2(title))
story.append(body(text))
story.append(sp(2))
story.append(Paragraph("<i>Morgan & Mikhail's Clinical Anesthesiology, 7e; Barash's Clinical Anesthesia, 9e; Miller's Anesthesia, 10e</i>", ref_style))
# ── SECTION 8 ──────────────────────────────────────────────────────────────────
story.append(h1("8. Limitations and Sources of Error [2 marks]"))
story.append(sp(4))
for lim in [
"<b>Sidestream systems:</b> Aspiration lag causes delayed readings; water condensation blocks the sampling line; in small tidal volumes, fresh gas entrainment underestimates ETCO₂",
"<b>V/Q mismatch:</b> ETCO₂ underestimates PaCO₂ when the gradient is widened – arterial blood gases are required for accuracy",
"<b>Rapid breathing:</b> Insufficient time for alveolar plateau to develop, leading to ETCO₂ underestimation",
"<b>Calibration errors:</b> Incorrect calibration leads to spurious readings",
"<b>Xenon anaesthesia:</b> Infrared spectrophotometry cannot detect xenon – not informative for xenon-based anaesthesia",
"<b>TIVA:</b> ETCO₂ provides no information about anaesthetic depth when total intravenous anaesthesia is used",
"<b>Neonates:</b> Small tidal volumes make accurate ETCO₂ measurement technically challenging",
]:
story.append(bullet(lim))
story.append(Paragraph("<i>Barash's Clinical Anesthesia, 9e; Miller's Anesthesia, 10e</i>", ref_style))
# ── SECTION 9 ──────────────────────────────────────────────────────────────────
story.append(h1("9. Monitoring Standards and Requirements [1 mark]"))
story.append(sp(4))
story.append(body(
"Capnography is a <b>mandatory monitor</b> during general anaesthesia under most international standards:"
))
for s in [
"Association of Anaesthetists of Great Britain and Ireland (AAGBI) guidelines",
"American Society of Anesthesiologists (ASA) standards – required during all general anaesthetics and for "
"monitoring ventilation during moderate and deep sedation",
"Its absence in cases of adverse respiratory events has been associated with significant medicolegal liability",
]:
story.append(bullet(s))
# ── SUMMARY TABLE ──────────────────────────────────────────────────────────────
story.append(sp(8))
story.append(h1("Summary: Capnogram Waveform Pattern Recognition"))
story.append(sp(4))
summary_data = [
[
Paragraph("<b>Capnogram Pattern</b>", body_style),
Paragraph("<b>Clinical Cause</b>", body_style),
],
["Absent waveform", "Oesophageal intubation, circuit disconnect, cardiac arrest"],
["Elevated baseline (phase 0 non-zero)", "CO₂ rebreathing – exhausted absorber, faulty valves"],
["Steep phase III upslope (shark-fin pattern)", "Obstructive airway disease (asthma, COPD)"],
["Sudden fall to zero", "Circuit disconnect, ETT obstruction, pulmonary embolism, cardiac arrest"],
["Gradual rise in ETCO₂", "Hypoventilation, rising metabolic rate, malignant hyperthermia"],
["Rapid marked rise in ETCO₂", "Malignant hyperthermia, CO₂ pneumoperitoneum"],
["Dip / notch in phase III plateau", "Spontaneous respiratory effort during IPPV (curare cleft)"],
["Gradual fall of ETCO₂", "Hyperventilation, decreasing cardiac output, hypothermia"],
["Return of waveform during CPR", "Return of spontaneous circulation (ROSC)"],
["Non-zero inspiratory baseline", "CO₂ rebreathing (faulty valve, exhausted absorber)"],
]
col_widths2 = [8.5*cm, 8.5*cm]
t2 = Table(summary_data, colWidths=col_widths2, repeatRows=1)
t2.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#1a2a4a')),
('TEXTCOLOR', (0, 0), (-1, 0), colors.white),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('FONTSIZE', (0, 0), (-1, -1), 9),
('ROWBACKGROUNDS', (0, 1), (-1, -1), [colors.HexColor('#f4f6fb'), colors.white]),
('GRID', (0, 0), (-1, -1), 0.4, colors.HexColor('#c0c8d8')),
('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
('TOPPADDING', (0, 0), (-1, -1), 5),
('BOTTOMPADDING', (0, 0), (-1, -1), 5),
('LEFTPADDING', (0, 0), (-1, -1), 6),
('RIGHTPADDING', (0, 0), (-1, -1), 6),
]))
story.append(t2)
# ── REFERENCES ─────────────────────────────────────────────────────────────────
story.append(sp(10))
story.append(hr())
story.append(h2("References"))
refs = [
"Miller RD et al. <i>Miller's Anesthesia</i>, 10th ed. Elsevier, 2023 (Chapter 37: Respiratory Monitoring).",
"Barash PG et al. <i>Barash, Cullen, and Stoelting's Clinical Anesthesia</i>, 9th ed. Wolters Kluwer, 2023 "
"(Chapters 26 and 30).",
"Morgan GE, Mikhail MS. <i>Morgan and Mikhail's Clinical Anesthesiology</i>, 7th ed. McGraw-Hill, 2022 "
"(Chapter 6: Intraoperative Monitoring).",
]
for r in refs:
story.append(Paragraph(f"• {r}", ref_style))
story.append(sp(8))
story.append(Paragraph(
"Generated by Orris Medical AI | Postgraduate Anaesthesia Examination Series | July 2026",
footer_style
))
doc.build(story)
print("PDF generated successfully:", OUTPUT)
cd /home/daytona/workspace/capnography_pdf && python generate_pdf.py
Capnography and Capnometry PG Anaesthesia
PDF Document · PDF
Create practice questions on capnography waveform interpretation with answer keys