Awake craniotomy in details

Reading File
Finding Sources
Finding Sources
Searching PubMed

"awake craniotomy" technique outcomes

Awake craniotomy in details anaesthesia implications with more elaborate way

Reading File
Reading File
Reading File
Searching PubMed

"awake craniotomy" anesthesia technique

Reading File
Finding Sources
Reading File
Finding Sources
Loading Image
Reading File
Reading File
Finding Sources
I now have comprehensive material from both Miller's and Barash to write a thorough, well-organized answer. Let me compose the full response.

Awake Craniotomy - Anesthesia Implications in Detail


1. Definition and Rationale

Awake craniotomy is a neurosurgical procedure performed under monitored anesthesia care (MAC) in which the patient remains conscious - either throughout or during a critical phase - allowing real-time neurological testing. It is indicated when a lesion (tumor, epileptic focus, vascular malformation) lies adjacent to or within eloquent cortex controlling:
  • Motor function (primary motor cortex, corticospinal tract)
  • Speech/language (Broca's area, Wernicke's area - usually left hemisphere)
  • Sensory function (primary somatosensory cortex)
  • Memory (mesial temporal structures)
The key advantage is that intraoperative cortical and subcortical mapping in a cooperative patient allows more aggressive tumor resection with simultaneous preservation of neurological function - something surrogate testing under general anesthesia cannot replicate for language. Recent meta-analysis (PMID: 41398134, 2025) confirms awake mapping improves extent of resection and neurological outcomes in low-grade gliomas.

2. Patient Selection and Preoperative Assessment

Patient cooperation is the single most important determinant of success. The anesthesiologist's preoperative role is as critical as the intraoperative one.
Ideal candidate:
  • Psychologically motivated and non-claustrophobic
  • Able to understand and follow instructions
  • No severe anxiety disorder or cognitive impairment
  • No uncontrolled movement disorder (tremor, dyskinesia)
  • No morbid obesity or known difficult airway
  • No language barriers that complicate testing
Preoperative workup includes:
  • Thorough neuropsychological baseline assessment (speech, motor, sensory)
  • Detailed explanation of each phase of the procedure: duration, what the patient will feel, what they will be asked to do, and what their limitations on movement will be
  • Discussion of potential uncomfortable phases: pin fixation, craniotomy, dural manipulation (especially subtemporal dura - painful)
  • If intraoperative electrocorticography (ECoG) is planned, anticonvulsants are often reduced by half or discontinued to avoid suppressing seizure activity needed for localization
  • Benzodiazepine premedication is contraindicated if EEG localization of seizure foci is intended, as they suppress the abnormal EEG activity being sought
  • Anxiolytics may still be used in non-EEG cases with caution
"A motivated patient is critical to the success of the procedure. Preoperative assessment should include a detailed explanation of the anesthetic so as to ensure cooperation and allay anxiety." - Barash Clinical Anesthesia 9e

3. Anesthetic Techniques

There are three recognized approaches, each with specific implications:

A. Monitored Anesthesia Care (MAC) Throughout

The patient is lightly sedated for the entire procedure. Sedation must be titrated carefully - deep enough for patient comfort during skull fixation and craniotomy, light enough for neurological testing throughout.

B. Asleep-Awake-Asleep (AAA) Technique (most commonly used)

  • Phase 1 (Asleep): General anesthesia or deep sedation for positioning, head fixation, scalp infiltration, craniotomy, and dural opening. A supraglottic airway device (LMA/SLMA) is typically used. Some groups use an endotracheal tube with a custom design.
  • Phase 2 (Awake): The airway device is removed once the brain surface is exposed. The patient is woken and cooperative testing (language, motor, sensory) is conducted.
  • Phase 3 (Asleep): Airway device is reinserted and anesthesia re-induced for tumor resection and closure.
"Awake craniotomy can be performed with the patient sedated for the duration of the procedure, or with an 'asleep-awake-asleep' technique employing a supraglottic airway device." - Barash 9e

C. Conscious Sedation Throughout

Light sedation during all phases; the patient is never fully anesthetized. This requires near-perfect local anesthesia.

4. The Local Anesthetic Technique - The Foundation

"The essential element of an anesthetic for an awake craniotomy is the local anesthetic technique. Sedation cannot compensate for inadequate anesthesia of the scalp." - Miller's Anesthesia 10e

Scalp Nerve Block

Six nerves innervate the scalp and relevant structures and must be blocked:
Cutaneous nerves of the scalp for awake craniotomy block
Fig. 53.19 - The cutaneous nerves of the scalp (Miller's Anesthesia 10e)
NerveTerritory
SupratrochlearMedial forehead
SupraorbitalLateral forehead, anterior scalp
ZygomaticotemporalTemple
AuriculotemporalTemporal region, pre-auricular
Lesser occipitalPosterior scalp, lateral
Greater occipitalPosterior scalp, medial
The block may be performed unilaterally or bilaterally. Additionally, pin sites must be infiltrated with local anesthetic - this is one of the most painful stimuli during the procedure.
Agents used:
  • Short procedures: 1% mepivacaine
  • Prolonged procedures: 0.75% ropivacaine
  • Epinephrine-containing solutions are preferred for vasoconstriction and prolongation of block
Key hazard: Local anesthetic toxicity (LAST). The volumes used for scalp blocks plus surgical infiltration of the dura and incision lines are substantial. The anesthesiologist must actively track cumulative doses as the surgeon continues to infiltrate throughout the procedure.
"The volume of local anesthetic used to infiltrate pin sites and perform the scalp nerve blocks can be substantial. It is appropriate for the anesthesiologist to keep track of, and provide advice about, the doses of local anesthetics used." - Miller's Anesthesia 10e

5. Sedation Agents - Detailed Pharmacology

Propofol

  • Most widely used; provides titratable, predictable sedation
  • Rapid awakening facilitates quick transition to the awake phase
  • Must be discontinued at least 15 minutes before EEG recording - leaves a residual high-frequency, high-amplitude beta activity footprint on the EEG that obscures abnormal seizure activity
  • When seizures occur during cortical stimulation, small boluses of propofol (0.5-1.0 mg/kg IV, or 20 mg bolus) are used to terminate them - but should be withheld briefly to allow spontaneous termination since propofol interferes with subsequent EEG localization

Remifentanil

  • Ultra-short-acting opioid; complements propofol for painful phases
  • Infusion rate: 0.02-0.05 mcg/kg/min
  • Synergistic respiratory depression with propofol - the most significant danger in a patient with a fixed, inaccessible airway (head in pin fixation)

Dexmedetomidine

  • Highly selective alpha-2 adrenergic agonist
  • Provides sedation + anxiolysis + analgesia with minimal respiratory depression - its key advantage
  • Increasingly the preferred agent, especially as a sole or primary drug
  • Effective infusion range during testing: 0.1-0.5 mcg/kg/h
  • Does not suppress spontaneous seizure activity at lower doses - suitable when ECoG is planned
  • Allows satisfactory conditions for brain stimulation speech mapping and ECoG
  • Limitation: may cause delays in achieving adequate patient responsiveness (slower onset/offset than propofol)
  • Meta-analysis (PMID: 39079421, 2024) confirms dexmedetomidine provides equivalent sedation and mapping conditions with significantly lower rates of respiratory depression compared to propofol-remifentanil
"Dexmedetomidine is the agent of choice for sedation of patients undergoing awake craniotomies." - Morgan & Mikhail Clinical Anesthesiology 7e

Agent Combinations

  • Propofol + remifentanil: effective but higher respiratory depression risk
  • Propofol + dexmedetomidine: useful combination balancing depth with respiratory safety
  • Dexmedetomidine + remifentanil: increasingly used
  • Benzodiazepines: generally avoided - highest potential to interfere with EEG recording and seizure focus localization; also long duration

Monitoring Sedation Depth

  • Standard ASA monitors
  • Capnography is essential - provides breath-by-breath confirmation of airway patency and respiratory drive if deep sedation is used at any phase
  • BIS monitoring may help titrate sedation
  • An arterial catheter is routinely placed for beat-to-beat hemodynamic monitoring and blood gas sampling

6. Airway Management

The airway is the most unforgiving aspect of awake craniotomy anesthesia, given that:
  • The patient's head is turned and fixed in a rigid pin head-holder
  • The surgical drape obscures most of the patient's body
  • Emergency intubation in this position is extremely difficult
Key principles:
  • Positioning optimization is critical before sedation begins: maximize neck flexion and atlanto-occipital extension so the anesthesiologist retains the widest latitude to sedate while maintaining spontaneous ventilation
  • The surgical drape must be positioned to allow direct, constant visual access to the patient's face - for airway monitoring AND to present naming/speech test images
  • Hypoventilation and hypercapnia are detrimental - CO2 retention causes cerebral vasodilation and brain swelling, worsening surgical exposure
  • Apnea requiring emergency intubation in a patient in a rigid head holder is a potentially catastrophic complication
LMA use: Various groups have reported use of the LMA during the asleep phases with spontaneous or controlled ventilation, removed once the brain surface is exposed. Importantly, LMA techniques are most commonly used when the head is not in pin fixation. When pin fixation is used, the LMA must be removed and replaced carefully, and plans for emergency airway management need to be thought through before the case starts.

7. Cortical and Subcortical Mapping - Anesthesia Interface

How mapping works:

The neurosurgeon uses a bipolar or monopolar probe stimulator to electrically stimulate cortical and subcortical areas while a neuropsychologist conducts real-time tests:
  • Object naming / picture naming - for language cortex identification
  • Counting or reading - speech arrest indicates language involvement
  • Limb movement testing - for motor strip mapping
  • Sensory responses - for sensory cortex mapping

ECoG (Electrocorticography) for seizure surgery:

  • After dural opening, cortical surface EEG is recorded to locate the seizure focus
  • If no spontaneous seizure activity is seen, provocative agents may be given:
    • Methohexital ~0.3 mg/kg - generally safe and effective
    • Etomidate 0.05-0.1 mg/kg - alternative
    • Alfentanil 30-50 mcg/kg bolus - used under general anesthesia
    • Remifentanil 2.5 mcg/kg bolus - reported effective
    • Hyperventilation - also activates seizure foci

Anesthesia implications during mapping:

  • No propofol during EEG recording (residual beta footprint)
  • Dexmedetomidine can continue at low rates during testing
  • Ensure patient is fully responsive, communicating, and understands instructions
  • Constant communication between anesthesiologist, surgeon, and neuropsychologist

8. Intraoperative Complications and Management

ComplicationCauseManagement
Intraoperative seizureCortical stimulation, tumor, or spontaneousCold saline irrigation of cortex by surgeon (first line); propofol 0.5-1.0 mg/kg IV (hold briefly to allow spontaneous termination); have phenytoin/levetiracetam ready
Respiratory depression / apneaOversedation, opioid effect, propofol-remifentanil synergyReduce/stop infusions; airway repositioning; jaw thrust; emergency LMA/intubation (very difficult in pin fixation - plan ahead)
Airway obstructionSedation-induced, positionalAirway repositioning maneuvers; consider nasal airway prior to draping
Patient non-cooperation / disinhibitionAnxiety, confusion, paradoxical reactionReassurance; small propofol bolus; abort awake phase if needed
OversedationExcessive drug titrationHold all infusions; stimulation to arouse; airway rescue
Intractable brain swellingHypercapnia, venous obstruction, tumor edemaHyperventilate; mannitol/hypertonic saline; dexamethasone; abort awake phase
Pain / discomfortInadequate local anesthesia, dural tractionSurgeon supplemental LA infiltration; small opioid bolus; adjust position
Nausea and vomitingOpioids, brain manipulationAnti-emetics (ondansetron, dexamethasone preop); limit opioids
LAST (Local anesthetic systemic toxicity)Excessive LA volumeTrack cumulative doses; have Intralipid 20% immediately available; ACLS
"Seizures should be treated with cold saline applied to the brain surface by the surgeon and a small bolus of propofol (20 mg) intravenously." - Barash 9e

9. Patient Positioning Considerations

  • All padding and positioning must be completed before any sedation is given - the patient cannot reposition themselves once the head is fixed and sedation has started
  • Common positions: lateral decubitus or supine with head turned
  • Pressure areas, eye protection, arm padding
  • Urinary catheter placement (procedures are typically 3-6 hours)
  • Temperature management (warm blankets, forced air warming to prevent hypothermia and shivering during the awake phase)
  • The anesthesiologist must be able to see the patient's face at all times from their position at the head of the bed

10. Monitoring

MonitorPurpose
Arterial lineBeat-to-beat BP, blood gas sampling
SpO2Continuous oxygenation
Capnography (ETCO2)Essential - airway patency and ventilation confirmation
EEG / ECoGSeizure localization (by neurophysiology team)
Standard ECG, NIBPRoutine
TemperaturePrevent hypothermia
Neuropsychological testingReal-time cortical mapping
BIS (optional)Sedation depth titration

11. Postoperative Considerations

  • Patients may be observed in PACU or ICU (similar to any craniotomy)
  • Most patients tolerate sedation for surgical closure after the awake phase
  • Analgesia: multimodal approach - scalp block provides good postoperative pain relief, supplemented with paracetamol/NSAIDs, opioids as needed
  • Monitor for new neurological deficit (compare to intraoperative baseline)
  • Seizure precautions continue postoperatively
  • For patients who tolerated the procedure poorly or are poor awake candidates, surrogate testing under general anesthesia is an alternative for motor/sensory mapping - but language testing cannot be performed under GA

12. Special Considerations

Epilepsy Surgery vs. Tumor Surgery

  • Epilepsy cases require discontinuation of anticonvulsants and avoidance of propofol before EEG recording
  • Tumor cases primarily need language and motor mapping; ECoG is less central

Pregnant Patients

  • Case reports exist; dexmedetomidine and mannitol have been used (PMID: referenced in Miller's - Handlogten et al., 2015)

Pediatric Patients

  • Awake craniotomy in children is rare but feasible from age ~10-12 years; requires highly experienced teams and careful psychological preparation
  • Meta-analysis (PMID: 37839565, 2024) shows comparable outcomes to adults in selected pediatric patients

Failed Awake Craniotomy

  • If the patient becomes uncooperative or experiences an emergency, conversion to general anesthesia in the middle of the procedure with a head in a pin holder is technically very challenging and must be planned for

Summary: The Anesthesiologist's Core Priorities

  1. Patient selection and preparation - Ensure a motivated, well-informed, cooperative patient
  2. Perfect local anesthesia - Scalp nerve blocks are the cornerstone; sedation cannot substitute
  3. Meticulous sedation titration - Match depth to the phase of the procedure
  4. Airway vigilance - Capnography, constant visual access, pre-planned emergency rescue
  5. Avoid LA toxicity - Track cumulative doses
  6. Drug selection for ECoG - No benzodiazepines; stop propofol 15 min before EEG; dexmedetomidine preferred
  7. Seizure preparedness - Cold saline first, propofol rescue second
  8. Communication - Constant verbal contact with the patient throughout

Sources:
  • Miller's Anesthesia, 2-Volume Set, 10e, Chapter 53 (Neurosurgical Anesthesia) - Awake Craniotomy and Seizure Surgery
  • Barash, Cullen, and Stoelting's Clinical Anesthesia, 9e, Chapter on Neuroanesthesia - Awake Craniotomy
  • Morgan & Mikhail's Clinical Anesthesiology, 7e
  • Akavipat et al. (2024) - Dexmedetomidine for awake craniotomy: Systematic review and meta-analysis [PMID: 39079421]
  • Sadhasivam et al. (2025) - Awake mapping and extent of resection in low-grade gliomas [PMID: 41398134]
  • Honeyman et al. (2025) - Awake vs asleep craniotomy for eloquent glioblastoma [PMID: 40887547]

Create a quick reference PDF for awake craniotomy anesthesia team checklist

Reading File
Running Command

ls -la /home/daytona/workspace/ 2>/dev/null && mkdir -p /home/daytona/workspace/awake-craniotomy

Writing File

~/awake-craniotomy/generate_checklist.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm, cm
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
from reportlab.platypus import FrameBreak
from reportlab.lib.colors import HexColor

OUTPUT = "/home/daytona/workspace/awake-craniotomy/Awake_Craniotomy_Checklist.pdf"

# ── Colour palette ──────────────────────────────────────────────────────────
NAVY      = HexColor("#1B2A4A")
TEAL      = HexColor("#0D7377")
TEAL_LITE = HexColor("#E0F4F4")
RED       = HexColor("#C0392B")
RED_LITE  = HexColor("#FDECEA")
AMBER     = HexColor("#D4700A")
AMBER_LT  = HexColor("#FFF3E0")
GREEN     = HexColor("#1A6B3C")
GREEN_LT  = HexColor("#E8F5E9")
GREY_LT   = HexColor("#F4F6F9")
GREY_MID  = HexColor("#BDC3C7")
WHITE     = colors.white

doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    leftMargin=14*mm,
    rightMargin=14*mm,
    topMargin=14*mm,
    bottomMargin=14*mm,
    title="Awake Craniotomy Anesthesia Team Checklist",
    author="Orris Medical Reference",
)

W, H = A4
CW = W - 28*mm   # content width

styles = getSampleStyleSheet()

def style(name, **kw):
    s = ParagraphStyle(name, **kw)
    return s

# ── Custom paragraph styles ─────────────────────────────────────────────────
S_TITLE = style("title",
    fontName="Helvetica-Bold", fontSize=16, textColor=WHITE,
    leading=20, alignment=TA_CENTER, spaceAfter=0)

S_SUBTITLE = style("subtitle",
    fontName="Helvetica", fontSize=9, textColor=HexColor("#D0E8F2"),
    leading=12, alignment=TA_CENTER, spaceAfter=0)

S_SEC = style("sec",
    fontName="Helvetica-Bold", fontSize=9.5, textColor=WHITE,
    leading=13, spaceAfter=0, spaceBefore=0)

S_ITEM = style("item",
    fontName="Helvetica", fontSize=8.2, textColor=HexColor("#1A1A2E"),
    leading=11.5, leftIndent=4, spaceAfter=0)

S_ITEM_BOLD = style("item_bold",
    fontName="Helvetica-Bold", fontSize=8.2, textColor=HexColor("#1A1A2E"),
    leading=11.5, leftIndent=4, spaceAfter=0)

S_WARN = style("warn",
    fontName="Helvetica-Bold", fontSize=8, textColor=RED,
    leading=11, leftIndent=4, spaceAfter=0)

S_NOTE = style("note",
    fontName="Helvetica-Oblique", fontSize=7.5, textColor=HexColor("#555566"),
    leading=10, leftIndent=4, spaceAfter=0)

S_DRUG = style("drug",
    fontName="Helvetica", fontSize=8, textColor=HexColor("#1A1A2E"),
    leading=11, leftIndent=2, spaceAfter=0)

S_DRUG_H = style("drug_h",
    fontName="Helvetica-Bold", fontSize=8, textColor=WHITE,
    leading=11, leftIndent=2, spaceAfter=0)

S_FOOTER = style("footer",
    fontName="Helvetica-Oblique", fontSize=6.5, textColor=HexColor("#888899"),
    leading=9, alignment=TA_CENTER)

# ── Helper builders ──────────────────────────────────────────────────────────
def section_header(text, bg=TEAL):
    """Coloured section header bar."""
    data = [[Paragraph(f"▌  {text}", S_SEC)]]
    t = Table(data, colWidths=[CW])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), bg),
        ("TOPPADDING",    (0,0), (-1,-1), 4),
        ("BOTTOMPADDING", (0,0), (-1,-1), 4),
        ("LEFTPADDING",   (0,0), (-1,-1), 7),
        ("RIGHTPADDING",  (0,0), (-1,-1), 7),
        ("LINEBELOW", (0,0), (-1,-1), 0.5, WHITE),
    ]))
    return t

def checkbox_row(items, ncols=2, bg=None):
    """
    items: list of (text, style, warn_flag)
    Returns a Table with checkbox column.
    """
    if bg is None:
        bg = WHITE
    rows = []
    # split into ncols columns
    col_items = [items[i::ncols] for i in range(ncols)]
    max_rows = max(len(c) for c in col_items)
    for r in range(max_rows):
        row = []
        for c in range(ncols):
            if r < len(col_items[c]):
                txt, sty, warn = col_items[c][r]
                cb = "☐"
                row.append(Paragraph(cb, S_ITEM))
                row.append(Paragraph(txt, sty))
            else:
                row.append("")
                row.append("")
        rows.append(row)
    # column widths: checkbox narrow, text fills rest
    cb_w = 8*mm
    txt_w = (CW - ncols * cb_w) / ncols
    col_ws = []
    for _ in range(ncols):
        col_ws += [cb_w, txt_w]

    t = Table(rows, colWidths=col_ws, repeatRows=0)
    ts = [
        ("BACKGROUND", (0,0), (-1,-1), bg),
        ("TOPPADDING",    (0,0), (-1,-1), 2),
        ("BOTTOMPADDING", (0,0), (-1,-1), 2),
        ("LEFTPADDING",   (0,0), (-1,-1), 3),
        ("RIGHTPADDING",  (0,0), (-1,-1), 3),
        ("VALIGN", (0,0), (-1,-1), "TOP"),
        ("LINEBELOW", (0,-1), (-1,-1), 0.3, GREY_MID),
    ]
    t.setStyle(TableStyle(ts))
    return t

def info_table(rows_data, col_widths, header_bg=NAVY, row_bg=GREY_LT, alt_bg=WHITE):
    """Generic info table with coloured header."""
    header = rows_data[0]
    body   = rows_data[1:]
    hrow = [Paragraph(str(h), S_DRUG_H) for h in header]
    brows = []
    for i, row in enumerate(body):
        bg_c = row_bg if i % 2 == 0 else alt_bg
        brows.append([Paragraph(str(c), S_DRUG) for c in row])
    all_rows = [hrow] + brows
    t = Table(all_rows, colWidths=col_widths)
    ts_list = [
        ("BACKGROUND", (0,0), (-1,0), header_bg),
        ("TOPPADDING",    (0,0), (-1,-1), 3),
        ("BOTTOMPADDING", (0,0), (-1,-1), 3),
        ("LEFTPADDING",   (0,0), (-1,-1), 5),
        ("RIGHTPADDING",  (0,0), (-1,-1), 5),
        ("VALIGN", (0,0), (-1,-1), "TOP"),
        ("GRID", (0,0), (-1,-1), 0.4, GREY_MID),
        ("ROWBACKGROUNDS", (0,1), (-1,-1), [row_bg, alt_bg]),
    ]
    t.setStyle(TableStyle(ts_list))
    return t

# ── Build story ──────────────────────────────────────────────────────────────
story = []

# ── TITLE BANNER ────────────────────────────────────────────────────────────
title_data = [[
    Paragraph("AWAKE CRANIOTOMY", S_TITLE),
    Paragraph("ANESTHESIA TEAM QUICK-REFERENCE CHECKLIST", S_SUBTITLE),
]]
title_tbl = Table([[
    Paragraph("AWAKE CRANIOTOMY<br/><font size=10>ANESTHESIA TEAM QUICK-REFERENCE CHECKLIST</font>", S_TITLE)
]], colWidths=[CW])
title_tbl.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), NAVY),
    ("TOPPADDING",    (0,0), (-1,-1), 10),
    ("BOTTOMPADDING", (0,0), (-1,-1), 10),
    ("LEFTPADDING",   (0,0), (-1,-1), 12),
    ("RIGHTPADDING",  (0,0), (-1,-1), 12),
    ("LINEBELOW", (0,0), (-1,-1), 2, TEAL),
]))
story.append(title_tbl)
story.append(Spacer(1, 4*mm))

# ── PHASE INDICATOR ROW ──────────────────────────────────────────────────────
phases = [
    ("PHASE 1", "ASLEEP / INDUCTION", NAVY),
    ("PHASE 2", "AWAKE / MAPPING", TEAL),
    ("PHASE 3", "RE-SLEEP / RESECTION & CLOSURE", HexColor("#34495E")),
]
phase_cells = []
for ph, label, bg in phases:
    cell = Paragraph(f"<b>{ph}</b><br/><font size=7>{label}</font>",
                     style("ph", fontName="Helvetica-Bold", fontSize=9,
                           textColor=WHITE, leading=12, alignment=TA_CENTER))
    phase_cells.append(cell)

phase_tbl = Table([phase_cells], colWidths=[CW/3]*3)
phase_tbl.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (0,0), NAVY),
    ("BACKGROUND", (1,0), (1,0), TEAL),
    ("BACKGROUND", (2,0), (2,0), HexColor("#34495E")),
    ("TOPPADDING",    (0,0), (-1,-1), 6),
    ("BOTTOMPADDING", (0,0), (-1,-1), 6),
    ("LEFTPADDING",   (0,0), (-1,-1), 4),
    ("RIGHTPADDING",  (0,0), (-1,-1), 4),
    ("LINEBETWEEN", (0,0), (-1,-1), 1, WHITE),
]))
story.append(phase_tbl)
story.append(Spacer(1, 4*mm))

# ── TWO-COLUMN LAYOUT USING NESTED TABLES ────────────────────────────────────
# Left column content and right column content assembled as nested tables.

def col_block(header_text, header_bg, items_list, bg=GREY_LT):
    """items_list: list of (text, bold, warn)"""
    parts = [section_header(header_text, bg=header_bg)]
    rows = []
    for txt, bold, warn in items_list:
        if warn:
            s = S_WARN
        elif bold:
            s = S_ITEM_BOLD
        else:
            s = S_ITEM
        rows.append(("☐  " + txt if not warn else "⚠  " + txt, s))
    
    tbl_rows = []
    for txt, s in rows:
        tbl_rows.append([Paragraph(txt, s)])
    
    if tbl_rows:
        inner = Table(tbl_rows, colWidths=[CW/2 - 4*mm])
        inner.setStyle(TableStyle([
            ("BACKGROUND", (0,0), (-1,-1), bg),
            ("TOPPADDING",    (0,0), (-1,-1), 2.5),
            ("BOTTOMPADDING", (0,0), (-1,-1), 2.5),
            ("LEFTPADDING",   (0,0), (-1,-1), 6),
            ("RIGHTPADDING",  (0,0), (-1,-1), 4),
            ("VALIGN", (0,0), (-1,-1), "TOP"),
            ("LINEBELOW", (0,-1), (-1,-1), 0.3, GREY_MID),
        ]))
        parts.append(inner)
    return parts


# ─────────────── PREOPERATIVE SECTION ───────────────────────────────────────
story.append(section_header("PRE-OPERATIVE ASSESSMENT  (≥24 h Before Surgery)", bg=NAVY))
story.append(Spacer(1, 1*mm))

preop_items = [
    ("Patient motivation & psychological assessment", True, False),
    ("Explain ALL phases: duration, discomfort, required tasks", False, False),
    ("Baseline neuropsychological testing documented", False, False),
    ("Difficult airway assessment (Mallampati, mouth opening, neck)", True, False),
    ("Obtain history of seizure aura type and character", False, False),
    ("Anticonvulsants: reduce or hold if ECoG planned (per neuro)", True, False),
    ("NO benzodiazepine premedication if EEG localization planned", False, True),
    ("Identify interpreters if language barrier exists", False, False),
    ("Coagulation screen, FBC, U&E, group & save", False, False),
    ("Contraindications excluded: morbid obesity, claustrophobia, uncooperative, severe GORD, movement disorder", False, True),
    ("Intralipid 20% availability confirmed (LAST prophylaxis)", True, False),
    ("Consent: awake procedure, possible conversion to GA", True, False),
]

preop_rows = [[Paragraph("☐  " + txt if not warn else "⚠  " + txt,
                          S_ITEM_BOLD if bold and not warn else (S_WARN if warn else S_ITEM))]
              for txt, bold, warn in preop_items]
preop_tbl = Table(preop_rows, colWidths=[CW/2 - 3*mm, CW/2 - 3*mm] if False else [CW])
preop_tbl = Table(
    [[Paragraph("☐  " + txt if not w else "⚠  " + txt,
                S_ITEM_BOLD if b and not w else (S_WARN if w else S_ITEM))
      for txt, b, w in preop_items[i::2]]
     for i in range((len(preop_items)+1)//2)],
    colWidths=[CW/2 - 2*mm, CW/2 - 2*mm]
)
preop_tbl.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), GREY_LT),
    ("TOPPADDING",    (0,0), (-1,-1), 2.5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 2.5),
    ("LEFTPADDING",   (0,0), (-1,-1), 5),
    ("RIGHTPADDING",  (0,0), (-1,-1), 5),
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("LINEBELOW", (0,-1), (-1,-1), 0.4, GREY_MID),
]))
story.append(preop_tbl)
story.append(Spacer(1, 3*mm))

# ─────────────── EQUIPMENT & DRUGS ──────────────────────────────────────────
story.append(section_header("EQUIPMENT & DRUG PREPARATION  (Day of Surgery)", bg=HexColor("#2C3E50")))
story.append(Spacer(1, 1*mm))

equip_left = [
    "Arterial line kit + transducer",
    "LMA (sizes 3, 4, 5) + lubrication",
    "Video laryngoscope + bougie (emergency)",
    "Nasopharyngeal airway",
    "Sidestream ETCO₂ (nasal cannula capnography)",
    "SpO₂, ECG, NIBP, temperature",
    "BIS monitor (optional)",
    "Warming blanket (forced air)",
    "Long IV extension sets (≥1.5 m)",
    "Urinary catheter kit",
]

equip_right = [
    "Propofol infusion (10 mg/mL syringe)",
    "Remifentanil infusion (20–50 mcg/mL)",
    "Dexmedetomidine infusion (4 mcg/mL)",
    "LA kit: ropivacaine 0.75% + bupivacaine 0.5% + epi",
    "Lidocaine 2% (topical / airway)",
    "Cold normal saline (500 mL, for seizure irrigation)",
    "Propofol 20 mg bolus drawn up + labeled",
    "Intralipid 20% 500 mL available in room",
    "Ondansetron 4 mg IV drawn up",
    "Dexamethasone 8 mg IV drawn up",
]

eq_rows = [[Paragraph("☐  " + l, S_ITEM), Paragraph("☐  " + r, S_ITEM)]
           for l, r in zip(equip_left, equip_right)]
eq_tbl = Table(eq_rows, colWidths=[CW/2 - 2*mm, CW/2 - 2*mm])
eq_tbl.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), WHITE),
    ("ROWBACKGROUNDS", (0,0), (-1,-1), [GREY_LT, WHITE]),
    ("TOPPADDING",    (0,0), (-1,-1), 2.5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 2.5),
    ("LEFTPADDING",   (0,0), (-1,-1), 5),
    ("RIGHTPADDING",  (0,0), (-1,-1), 5),
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("LINEBELOW", (0,-1), (-1,-1), 0.4, GREY_MID),
    ("LINEBETWEEN", (0,0), (1,-1), 0.3, GREY_MID),
]))
story.append(eq_tbl)
story.append(Spacer(1, 3*mm))

# ─────────────── SCALP NERVE BLOCK ──────────────────────────────────────────
story.append(section_header("SCALP NERVE BLOCK  —  The Cornerstone of Awake Craniotomy", bg=TEAL))
story.append(Spacer(1, 1*mm))

nerve_data = [
    ["Nerve", "Landmark / Injection Point", "Territory"],
    ["Supratrochlear", "Medial orbital rim at corrugator", "Medial forehead"],
    ["Supraorbital", "Supraorbital notch / foramen", "Lateral forehead, anterior scalp"],
    ["Zygomaticotemporal", "Lateral orbital rim, temporal fossa", "Temple"],
    ["Auriculotemporal", "1–1.5 cm anterior to tragus, above zygomatic arch", "Temporal scalp, pre-auricular"],
    ["Lesser occipital", "Posterior border of SCM, ⅓ from mastoid", "Posterior scalp, lateral"],
    ["Greater occipital", "Medial to occipital artery, 3 cm lateral to midline", "Posterior scalp, medial"],
]
nerve_tbl = info_table(nerve_data,
    col_widths=[38*mm, 68*mm, 52*mm],
    header_bg=TEAL, row_bg=TEAL_LITE, alt_bg=WHITE)
story.append(nerve_tbl)

warn_la = Table([[Paragraph(
    "⚠  TRACK CUMULATIVE LA DOSE — Scalp block + pin site infiltration + dural infiltration = HIGH TOTAL VOLUME  |  "
    "Ropivacaine 0.75% max ~3 mg/kg  |  Have Intralipid 20% in room",
    style("warnbar", fontName="Helvetica-Bold", fontSize=7.8, textColor=WHITE, leading=11, alignment=TA_LEFT)
)]],
colWidths=[CW])
warn_la.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), RED),
    ("TOPPADDING",    (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING",   (0,0), (-1,-1), 8),
    ("RIGHTPADDING",  (0,0), (-1,-1), 8),
]))
story.append(Spacer(1, 1.5*mm))
story.append(warn_la)
story.append(Spacer(1, 3*mm))

# ─────────────── SEDATION DRUG REFERENCE ────────────────────────────────────
story.append(section_header("SEDATION AGENT QUICK-REFERENCE", bg=HexColor("#6C3483")))
story.append(Spacer(1, 1*mm))

drug_data = [
    ["Agent", "Induction / Loading", "Maintenance Infusion", "Key Advantage", "Key Caution"],
    ["Propofol", "0.5–1 mg/kg titrated", "25–75 mcg/kg/min", "Titratable, rapid offset", "Resp. depression; stop 15 min before EEG"],
    ["Remifentanil", "—", "0.02–0.05 mcg/kg/min", "Ultra-short acting opioid", "Synergistic resp. depression with propofol"],
    ["Dexmedetomidine", "0.5–1 mcg/kg over 10 min (optional)", "0.2–0.5 mcg/kg/h", "Analgesia + sedation, minimal resp. depression", "Slow onset/offset; possible bradycardia"],
    ["Propofol + Remi", "Propofol titrated", "As above", "Deep sedation possible", "HIGH resp. depression risk in pin fixation"],
    ["Dex + Remi", "Dex load ± remi", "As above", "Best respiratory safety", "Ensure remi rate low"],
]
drug_tbl = info_table(drug_data,
    col_widths=[28*mm, 34*mm, 38*mm, 46*mm, 36*mm],
    header_bg=HexColor("#6C3483"), row_bg=HexColor("#F5EEF8"), alt_bg=WHITE)
story.append(drug_tbl)
story.append(Spacer(1, 3*mm))

# ─────────────── PHASE 1 — ASLEEP ────────────────────────────────────────────
story.append(section_header("PHASE 1 — ASLEEP  (Induction → Dural Opening)", bg=NAVY))
story.append(Spacer(1, 1*mm))

p1_left = [
    ("Complete ALL positioning + padding BEFORE sedation", True, False),
    ("Arterial line sited and zeroed", True, False),
    ("Verify clear visual access to patient's face", True, False),
    ("Verify: emergency airway plan discussed with team", False, True),
    ("Insert nasopharyngeal airway if needed", False, False),
    ("Sidestream ETCO₂ nasal cannula in place", True, False),
    ("Bladder catheter in situ", False, False),
    ("Warming blanket applied", False, False),
]
p1_right = [
    ("LMA inserted (asleep phase) — size checked", True, False),
    ("LMA position confirmed: ETCO₂ trace, chest rise", True, False),
    ("Sedation infusion running (propofol ± dex ± remi)", False, False),
    ("Pin site LA infiltration completed (track dose)", True, False),
    ("Scalp nerve block completed (track dose)", True, False),
    ("Incision line infiltrated by surgeon (track dose)", False, False),
    ("Brain relaxation: mannitol / hypertonic saline if ordered", False, False),
    ("Steroids (dexamethasone) given if ordered", False, False),
]

p1_rows = [[
    Paragraph("☐  " + l if not lw else "⚠  " + l, S_ITEM_BOLD if lb and not lw else (S_WARN if lw else S_ITEM)),
    Paragraph("☐  " + r if not rw else "⚠  " + r, S_ITEM_BOLD if rb and not rw else (S_WARN if rw else S_ITEM))
] for (l, lb, lw), (r, rb, rw) in zip(p1_left, p1_right)]

p1_tbl = Table(p1_rows, colWidths=[CW/2 - 2*mm, CW/2 - 2*mm])
p1_tbl.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), GREY_LT),
    ("ROWBACKGROUNDS", (0,0), (-1,-1), [GREY_LT, WHITE]),
    ("TOPPADDING",    (0,0), (-1,-1), 2.5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 2.5),
    ("LEFTPADDING",   (0,0), (-1,-1), 5),
    ("RIGHTPADDING",  (0,0), (-1,-1), 5),
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("LINEBELOW", (0,-1), (-1,-1), 0.4, GREY_MID),
    ("LINEBETWEEN", (0,0), (1,-1), 0.3, GREY_MID),
]))
story.append(p1_tbl)
story.append(Spacer(1, 3*mm))

# ─────────────── PHASE 2 — AWAKE ─────────────────────────────────────────────
story.append(section_header("PHASE 2 — AWAKE  (Brain Surface Exposed → Mapping Complete)", bg=TEAL))
story.append(Spacer(1, 1*mm))

p2_left = [
    ("Discontinue propofol ≥15 min BEFORE EEG recording", False, True),
    ("Dexmedetomidine: reduce to 0.1–0.3 mcg/kg/h for testing", True, False),
    ("LMA removed — confirm spontaneous ventilation", True, False),
    ("Patient oriented and responsive before mapping begins", True, False),
    ("Nasal O₂ (4 L/min) + ETCO₂ monitoring continuous", True, False),
    ("Surgical drape: confirm face is fully visible to team", True, False),
    ("Verbal communication established with patient", True, False),
    ("Baseline neurological test performed (naming, counting)", False, False),
]
p2_right = [
    ("Neuropsychologist / speech therapist present and ready", False, False),
    ("Cold saline 500 mL drawn up and labeled at surgical field", False, True),
    ("Propofol 20 mg bolus labeled and immediately accessible", False, True),
    ("Anticonvulsants immediately accessible (phenytoin/LEV)", False, False),
    ("Monitor ETCO₂: target 35–40 mmHg (avoid hypercapnia)", True, False),
    ("Reassure patient continuously; explain each stimulus", False, False),
    ("If oversedated: stop all infusions, stimulate, jaw thrust", False, True),
    ("Note: brain parenchyma manipulation is PAINLESS", False, False),
]

p2_rows = [[
    Paragraph("☐  " + l if not lw else "⚠  " + l, S_ITEM_BOLD if lb and not lw else (S_WARN if lw else S_ITEM)),
    Paragraph("☐  " + r if not rw else "⚠  " + r, S_ITEM_BOLD if rb and not rw else (S_WARN if rw else S_ITEM))
] for (l, lb, lw), (r, rb, rw) in zip(p2_left, p2_right)]

p2_tbl = Table(p2_rows, colWidths=[CW/2 - 2*mm, CW/2 - 2*mm])
p2_tbl.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), TEAL_LITE),
    ("ROWBACKGROUNDS", (0,0), (-1,-1), [TEAL_LITE, WHITE]),
    ("TOPPADDING",    (0,0), (-1,-1), 2.5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 2.5),
    ("LEFTPADDING",   (0,0), (-1,-1), 5),
    ("RIGHTPADDING",  (0,0), (-1,-1), 5),
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("LINEBELOW", (0,-1), (-1,-1), 0.4, GREY_MID),
    ("LINEBETWEEN", (0,0), (1,-1), 0.3, GREY_MID),
]))
story.append(p2_tbl)
story.append(Spacer(1, 3*mm))

# ─────────────── PHASE 3 — RE-SLEEP ──────────────────────────────────────────
story.append(section_header("PHASE 3 — RE-SLEEP  (Resection & Closure)", bg=HexColor("#34495E")))
story.append(Spacer(1, 1*mm))

p3_items = [
    ("Mapping complete — confirmed with surgeon and neuropsychologist", True, False),
    ("Re-induce sedation / general anesthesia", True, False),
    ("Re-insert LMA — confirm position with ETCO₂", True, False),
    ("Propofol infusion re-started (± remifentanil)", False, False),
    ("Most patients tolerate sedation (not full GA) for closure", False, False),
    ("Anti-emetic given if not already (ondansetron 4 mg)", False, False),
    ("Post-op pain plan: scalp block provides good analgesia", False, False),
    ("Mannitol / hypertonic saline given if brain swelling", False, False),
]

p3_rows = [[Paragraph("☐  " + txt if not w else "⚠  " + txt,
                       S_ITEM_BOLD if b and not w else (S_WARN if w else S_ITEM))]
           for txt, b, w in p3_items]
p3_rows2 = [[
    Paragraph("☐  " + p3_items[i][0] if not p3_items[i][2] else "⚠  " + p3_items[i][0],
              S_ITEM_BOLD if p3_items[i][1] and not p3_items[i][2] else (S_WARN if p3_items[i][2] else S_ITEM)),
    Paragraph("☐  " + p3_items[i+1][0] if i+1 < len(p3_items) and not p3_items[i+1][2] else
              ("⚠  " + p3_items[i+1][0] if i+1 < len(p3_items) else ""),
              S_ITEM_BOLD if i+1 < len(p3_items) and p3_items[i+1][1] and not p3_items[i+1][2]
              else (S_WARN if i+1 < len(p3_items) and p3_items[i+1][2] else S_ITEM))
] for i in range(0, len(p3_items), 2)]

p3_tbl = Table(p3_rows2, colWidths=[CW/2 - 2*mm, CW/2 - 2*mm])
p3_tbl.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), GREY_LT),
    ("ROWBACKGROUNDS", (0,0), (-1,-1), [GREY_LT, WHITE]),
    ("TOPPADDING",    (0,0), (-1,-1), 2.5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 2.5),
    ("LEFTPADDING",   (0,0), (-1,-1), 5),
    ("RIGHTPADDING",  (0,0), (-1,-1), 5),
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("LINEBELOW", (0,-1), (-1,-1), 0.4, GREY_MID),
    ("LINEBETWEEN", (0,0), (1,-1), 0.3, GREY_MID),
]))
story.append(p3_tbl)
story.append(Spacer(1, 3*mm))

# ─────────────── COMPLICATIONS RESPONSE ──────────────────────────────────────
story.append(section_header("INTRAOPERATIVE COMPLICATION RESPONSE", bg=RED))
story.append(Spacer(1, 1*mm))

comp_data = [
    ["Complication", "First-Line Response", "Second-Line / Escalation"],
    ["Intraoperative SEIZURE",
     "1. Signal surgeon: cold saline irrigation to cortex\n2. Stop cortical stimulation\n3. Observe 30 s for spontaneous termination",
     "Propofol 0.5–1 mg/kg IV bolus (20 mg increments)\nLevetiracetam / phenytoin if refractory\nSecure airway if LOC"],
    ["Respiratory DEPRESSION / Apnea",
     "Stop propofol + remifentanil immediately\nJaw thrust + head-tilt\nNasal airway / O₂ increase",
     "LMA insertion (difficult in pin fixation — pre-plan)\nEmergency intubation: video laryngoscope\nCall for additional help"],
    ["Patient NON-COOPERATION",
     "Verbal reassurance\nIdentify cause (pain → more LA; anxiety → small propofol 10–20 mg)",
     "Abort awake phase\nConvert to GA (pre-planned route)\nDocument for future cases"],
    ["BRAIN SWELLING",
     "Ensure no hypercapnia (ETCO₂ <40 mmHg)\nHead position optimized, venous drainage unobstructed",
     "Mannitol 0.5–1 g/kg or 3% saline 100–150 mL\nDexamethasone\nSurgeon may need to abort resection"],
    ["LA SYSTEMIC TOXICITY (LAST)",
     "Stop LA immediately\nCalls for help\nO₂ 100%, ABCDE",
     "Intralipid 20% 1.5 mL/kg bolus → 0.25 mL/kg/min\nAvoid propofol (lipid carrier insufficient)\nCPR if cardiac arrest"],
    ["Nausea / Vomiting",
     "Ondansetron 4 mg IV\nMetoclopramide 10 mg IV\nLimit opioids",
     "Dexamethasone 4–8 mg IV\nAspiration precautions\nPosition head-up if possible"],
]

comp_tbl = info_table(comp_data,
    col_widths=[36*mm, 72*mm, 70*mm],
    header_bg=RED, row_bg=RED_LITE, alt_bg=WHITE)
story.append(comp_tbl)
story.append(Spacer(1, 3*mm))

# ─────────────── POST-OP HANDOVER ────────────────────────────────────────────
story.append(section_header("POST-OPERATIVE HANDOVER POINTS", bg=GREEN))
story.append(Spacer(1, 1*mm))

postop_items = [
    ("Neurological baseline documented intraoperatively (speech, motor, sensory)", True, False),
    ("Document total LA volumes used (scalp block + pin sites + dural)", True, False),
    ("Anticonvulsants restarted per neurology instructions", True, False),
    ("Adequate analgesia prescribed (paracetamol, NSAIDs ± opioids)", False, False),
    ("New neurological deficit — immediate CT head if suspected", False, True),
    ("ICU/HDU vs PACU: decision per case complexity", False, False),
    ("Monitoring: GCS, BP (avoid hypertension), SpO₂, temperature", False, False),
    ("Inform ward of seizure risk and emergency response", False, False),
]

po_rows2 = [[
    Paragraph("☐  " + postop_items[i][0] if not postop_items[i][2] else "⚠  " + postop_items[i][0],
              S_ITEM_BOLD if postop_items[i][1] and not postop_items[i][2] else (S_WARN if postop_items[i][2] else S_ITEM)),
    Paragraph("☐  " + postop_items[i+1][0] if i+1 < len(postop_items) and not postop_items[i+1][2] else
              ("⚠  " + postop_items[i+1][0] if i+1 < len(postop_items) else ""),
              S_ITEM_BOLD if i+1 < len(postop_items) and postop_items[i+1][1] and not postop_items[i+1][2]
              else (S_WARN if i+1 < len(postop_items) and postop_items[i+1][2] else S_ITEM))
] for i in range(0, len(postop_items), 2)]

po_tbl = Table(po_rows2, colWidths=[CW/2 - 2*mm, CW/2 - 2*mm])
po_tbl.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), GREEN_LT),
    ("ROWBACKGROUNDS", (0,0), (-1,-1), [GREEN_LT, WHITE]),
    ("TOPPADDING",    (0,0), (-1,-1), 2.5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 2.5),
    ("LEFTPADDING",   (0,0), (-1,-1), 5),
    ("RIGHTPADDING",  (0,0), (-1,-1), 5),
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("LINEBELOW", (0,-1), (-1,-1), 0.4, GREY_MID),
    ("LINEBETWEEN", (0,0), (1,-1), 0.3, GREY_MID),
]))
story.append(po_tbl)
story.append(Spacer(1, 3*mm))

# ─────────────── KEY REMINDERS BOX ───────────────────────────────────────────
reminders = [
    "Sedation CANNOT replace an inadequate scalp block — fix the block, not the drug dose.",
    "ETCO₂ >45 mmHg = cerebral vasodilation → brain swelling → poor surgical field. Act immediately.",
    "In pin fixation, EMERGENCY AIRWAY ACCESS IS EXTREMELY LIMITED — plan before you sedate.",
    "Propofol must be STOPPED ≥15 min before EEG recording — residual beta activity obscures seizure foci.",
    "Language mapping can ONLY be performed in an awake patient — GA surrogate testing is not equivalent.",
]
rem_rows = [[Paragraph(f"★  {r}",
    style("rem", fontName="Helvetica-Bold", fontSize=7.8,
          textColor=NAVY, leading=11, leftIndent=2))]
    for r in reminders]

rem_tbl = Table(rem_rows, colWidths=[CW])
rem_tbl.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), AMBER_LT),
    ("TOPPADDING",    (0,0), (-1,-1), 3),
    ("BOTTOMPADDING", (0,0), (-1,-1), 3),
    ("LEFTPADDING",   (0,0), (-1,-1), 8),
    ("RIGHTPADDING",  (0,0), (-1,-1), 8),
    ("VALIGN", (0,0), (-1,-1), "TOP"),
    ("LINEBELOW", (0,0), (-1,-2), 0.3, AMBER),
    ("BOX", (0,0), (-1,-1), 1, AMBER),
]))

reminder_header = Table([[Paragraph("★  KEY REMINDERS FOR AWAKE CRANIOTOMY",
    style("remh", fontName="Helvetica-Bold", fontSize=9,
          textColor=WHITE, leading=13))]],
    colWidths=[CW])
reminder_header.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), AMBER),
    ("TOPPADDING", (0,0), (-1,-1), 4),
    ("BOTTOMPADDING", (0,0), (-1,-1), 4),
    ("LEFTPADDING", (0,0), (-1,-1), 8),
]))

story.append(reminder_header)
story.append(rem_tbl)
story.append(Spacer(1, 3*mm))

# ─────────────── FOOTER ───────────────────────────────────────────────────────
story.append(HRFlowable(width=CW, thickness=0.5, color=GREY_MID))
story.append(Spacer(1, 1*mm))
story.append(Paragraph(
    "Orris Medical Reference  |  Awake Craniotomy Anesthesia Team Checklist  |  "
    "Based on Miller's Anesthesia 10e, Barash Clinical Anesthesia 9e, Morgan & Mikhail 7e  |  June 2026  |  "
    "For educational and clinical reference use only — verify against local protocols and current guidelines.",
    S_FOOTER
))

# ── Build ────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF written to: {OUTPUT}")
Running Command

cd /home/daytona/workspace/awake-craniotomy && python generate_checklist.py 2>&1

Running Command

ls -lh /home/daytona/workspace/awake-craniotomy/Awake_Craniotomy_Checklist.pdf

The PDF is ready. Here's your download link:

Awake Craniotomy Checklist

PDF Document · PDF


Here's what's included in the checklist:
Structure (A4, color-coded by section):
SectionColor
Pre-operative AssessmentDark navy
Equipment & Drug PreparationCharcoal
Scalp Nerve Block (6 nerves table)Teal
Sedation Agent Quick-ReferencePurple
Phase 1 — Asleep (Induction → Dural opening)Navy
Phase 2 — Awake (Brain mapping)Teal
Phase 3 — Re-sleep (Resection & Closure)Dark slate
Complication Response TableRed
Post-op Handover PointsGreen
Key Reminders BoxAmber
Design features:
  • ☐ Checkboxes for every actionable item
  • ⚠ Red warning markers on high-risk items (e.g., NO benzos before EEG, propofol stop 15 min before recording, LAST risk, emergency airway limitation)
  • Dual-column layout throughout to maximize content density
  • Scalp nerve block table with landmarks and territories
  • Sedation drug table with loading doses, infusion rates, and key cautions
  • Complication response table with first-line and escalation steps
  • Footer citing Miller's 10e, Barash 9e, Morgan & Mikhail 7e

Explain pattern of stimulation TOF NEUROMUSCULAR STIMULATION Tof count ratio Fade on Tetanic stimulation In easy understanding way

Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Loading Image
Loading Image
Reading File
Loading Image
I now have all the diagrams and textbook content needed. Here is a thorough, easy-to-understand explanation:

Train-of-Four (TOF) Neuromuscular Stimulation - Simple Explanation


The Big Picture - Why Do We Monitor This?

When you give a neuromuscular blocking drug (like rocuronium or vecuronium), the muscle becomes paralyzed. The question is: how paralyzed is the patient right now?
You cannot just look at the patient and tell. So we use a peripheral nerve stimulator - a small device placed over a nerve (usually the ulnar nerve at the wrist) that sends controlled electrical pulses and produces muscle twitches that we observe.
Think of it like pressing a doorbell repeatedly. The height of the "ring" (muscle twitch) tells you how much signal is getting through.

1. Train-of-Four (TOF) Stimulation

What is it?

The nerve stimulator delivers 4 electrical pulses in rapid succession, each 0.5 seconds apart (= 2 Hz). This produces 4 twitches (T1, T2, T3, T4) in the muscle being monitored (usually the thumb - adductor pollicis).
TOF stimulation pattern showing 4 equal twitches when unblocked, T4/T1 ratio = 1.0
TOF pattern - unblocked state: all 4 twitches equal, ratio = 1.0 (Barash Clinical Anesthesia 9e)
TOF and depolarizing vs non-depolarizing block patterns
Non-depolarizing block: progressive fade (T4 < T1). Depolarizing block: all twitches diminish equally, no fade (Miller's Anesthesia 10e)

Normal state (no drug):

All 4 twitches are equal height. T4 = T1. Like 4 identical doorbells.

Why do the twitches change with muscle relaxants?

It all comes down to acetylcholine (ACh) - the chemical signal at the neuromuscular junction.
Each electrical pulse causes the nerve to release ACh. With each successive pulse, the nerve slightly depletes its ready supply of ACh. In a normal person, there is so much ACh in reserve that you never notice - all 4 twitches look the same.
But when a nondepolarizing blocker (rocuronium, vecuronium, cisatracurium) is present:
  • It blocks the postsynaptic receptors (competes with ACh)
  • It also blocks presynaptic receptors that are supposed to mobilize more ACh stores for the next impulse
  • Result: each successive pulse releases a bit less ACh AND there are fewer free receptors - so each twitch gets progressively weaker
This progressive weakening is called FADE.

2. TOF Count

What is it?

Simply count how many twitches you can feel or see out of the 4.

How to read it:

TOF CountWhat it meansApproximate % receptors blocked
4 of 4Moderate block / recovering~70-75% blocked
3 of 4Deep surgical block~80% blocked
2 of 4Deep block~85% blocked
1 of 4Very deep block~90% blocked
0 of 4Profound block (use PTC instead)>90% blocked
Easy memory trick: As the block deepens, twitches disappear in reverse order - T4 goes first, then T3, then T2, then T1. During recovery, they come back in the same reverse order - T1 first, then T2, T3, T4 last.
"As the effects of a nondepolarizing neuromuscular blocking drug deepen, the number of muscle responses will decline, T4 will be lost first, then T3, then T2 and finally T1. Regression of drug effect will follow the same pattern in reverse." - Barash 9e

3. TOF Ratio (T4/T1)

What is it?

When all 4 twitches are present, you can calculate a ratio:
TOF Ratio = Height of T4 ÷ Height of T1
  • Normal (no drug): T4 = T1 → ratio = 1.0
  • Partial block: T4 < T1 → ratio somewhere between 0 and 1.0
  • The lower the ratio, the more residual block remains

The critical number: TOF ratio ≥ 0.9

This is the threshold considered safe for extubation and full recovery. Below 0.9 = residual paralysis, which increases risk of:
  • Airway obstruction
  • Aspiration
  • Hypoxia after extubation

The clinical problem with TOF ratio:

You need a machine (acceleromyography, electromyography) to measure the actual ratio. With just your fingers (subjective assessment), you can only detect fade when the ratio is below about 0.4. Between 0.4 and 0.9 - which is the danger zone for residual paralysis - you cannot feel or see the difference by hand. This is why objective quantitative monitoring is recommended.
"At a TOF ratio between 0.4 and 0.9, fade cannot be detected either visually or tactically. Therefore, objective monitoring devices are needed to reliably exclude residual paralysis." - Miller's Anesthesia 10e

4. Fade - What Exactly Is It?

Fade = the progressive weakening of successive muscle twitches during repeated stimulation.

Simple analogy:

Imagine you have a bucket of water (ACh stores) and a leaky tap.
  • You press the button 4 times.
  • Each press releases some water (ACh).
  • The first press produces a big splash (big twitch).
  • By the 4th press, less water came out (less ACh mobilized) → smaller twitch.
  • If the drain (blocked receptors) is already partly clogged by the drug, even less water gets through → the difference between 1st and 4th twitch gets bigger = more fade.

The mechanism of fade (two components):

1. Postsynaptic: The nondepolarizing drug blocks ACh receptors at the muscle. As ACh delivery decreases with successive pulses, fewer free receptors remain, weakening each subsequent twitch.
2. Presynaptic: Nondepolarizing drugs also block neuronal-subtype (α3β2) presynaptic receptors that normally act as a feedback mechanism - telling the nerve terminal "release more ACh stores." Block this, and ACh mobilization is impaired, making the depletion worse with each pulse. This is the main driver of fade.
"A characteristic of nondepolarizing drugs observed with partial nerve block is fade due to blocking of the presynaptic α3β2 acetylcholine receptors." - Barash 9e

5. Tetanic Stimulation and Fade

What is tetanic stimulation?

Instead of 4 pulses, the nerve stimulator delivers rapid continuous pulses at 50 Hz (50 per second) for 5 seconds. This is like pressing the doorbell 50 times per second non-stop.
Normal response: one strong, sustained muscle contraction throughout (a tetanus = the muscle locks up firmly).
Tetanic stimulation - control vs non-dep block vs dep block
Control: sustained tetanic response. Moderate non-dep. block: fade during tetanus + post-tetanic facilitation. Moderate dep. block: sustained tetanic response, no post-tetanic facilitation (Miller's Anesthesia 10e)

What happens with nondepolarizing block?

During tetanic stimulation, the ACh stores are rapidly depleted at very high rate. Combined with presynaptic receptor blockade, the muscle loses strength partway through - the contraction starts strong but visibly weakens before the 5 seconds are up. This is tetanic fade.
Tetanic fade is more sensitive than TOF fade for detecting residual block - you can feel it at higher TOF ratios than you could detect TOF fade.

Post-tetanic facilitation (post-tetanic count):

After tetanic stimulation, there is a period where the nerve terminal has been "revved up" - it releases more ACh than usual for the next few minutes. If you then do single twitches, they are temporarily bigger - this is post-tetanic facilitation.
This is the basis of the Post-Tetanic Count (PTC) - used when the block is so deep that there are 0/4 twitches on TOF. By applying tetanus then counting how many single twitches appear, you can estimate how deep the block is in the truly profound range.

Depolarizing block (succinylcholine) - key difference:

FeatureNondepolarizing BlockDepolarizing Block (Suxamethonium)
TOF twitchesT4 disappears first, then T3, T2, T1All 4 twitches weaken equally
TOF fadeYES (T4 < T1)NO (T4 = T1)
Tetanic stimulationFADE (weakens over 5 sec)SUSTAINED (no fade)
Post-tetanic facilitationYESNO
Phase II block (sux overdose)N/AFADE appears (like non-dep)
"During a partial nondepolarizing block, the TOF ratio decreases (fades)... During a partial depolarizing block, no fade occurs in the TOF response and the TOF ratio remains 1.0. Fade in the TOF response after injection of succinylcholine signifies the development of a phase II block." - Miller's Anesthesia 10e

Summary Table - Everything at a Glance

ConceptSimple MeaningKey Number
TOF4 pulses at 2 Hz; watch 4 twitchesRepeat every ≥10-15 sec
TOF CountHow many of the 4 twitches are presentCount 1-4 (0 = profound block)
TOF RatioT4 ÷ T1 heightSafe to extubate: ≥0.9
FadeT4 weaker than T1 (nondep. block)Detectable by hand only if ratio <0.4
No fadeAll twitches equal heightSux (depolarizing) - no fade
Tetanic stimulation50 Hz for 5 secFade = nondep block. Sustained = dep block
Post-tetanic facilitationTwitches bigger after tetanusOnly with nondep block
Residual paralysisTOF ratio 0.4-0.9 - feels fine but is dangerousCan't detect by hand - need a machine

Sources: Miller's Anesthesia 10e (Ch. 39 - Neuromuscular Monitoring), Barash Clinical Anesthesia 9e (Ch. 21 - Neuromuscular Blocking Drugs), Morgan & Mikhail Clinical Anesthesiology 7e

Pit them in pdf

Running Command

mkdir -p /home/daytona/workspace/tof-nmb && ls /home/daytona/workspace/tof-nmb/

Running Command

cd /home/daytona/workspace/tof-nmb && python3 -c " import urllib.request, os imgs = { 'tof_unblocked.png': 'https://cdn.orris.care/cdss_images/255397a14095e5d234e461b283b583729221de37a08283a6a5c9991fa08b0ee5.png', 'tof_nondep_dep.png': 'https://cdn.orris.care/cdss_images/c93916980d950d2b9e2a6c1a4415ae1676fa281327bb2236601268f33e80ea65.png', 'tetanic.png': 'https://cdn.orris.care/cdss_images/a7ede52ed2bf40ca3dc908cf5ebba2607e35ba1c21463e1e27992f45b74a2a1c.png', } for fname, url in imgs.items(): urllib.request.urlretrieve(url, fname) print(f'Downloaded {fname}: {os.path.getsize(fname)} bytes') "

Writing File

~/tof-nmb/generate_tof_pdf.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.lib.colors import HexColor
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, Image, KeepTogether
)
import os

BASE   = "/home/daytona/workspace/tof-nmb/"
OUTPUT = BASE + "TOF_Neuromuscular_Monitoring.pdf"

W, H   = A4
LM = RM = 14*mm
TM = BM = 14*mm
CW = W - LM - RM

# ── Palette ─────────────────────────────────────────────────────────────────
NAVY     = HexColor("#1B2A4A")
TEAL     = HexColor("#0D7377")
TEAL_LT  = HexColor("#E0F4F4")
PURPLE   = HexColor("#5B2C8D")
PURP_LT  = HexColor("#F3EEF9")
RED      = HexColor("#C0392B")
RED_LT   = HexColor("#FDECEA")
AMBER    = HexColor("#D4700A")
AMBER_LT = HexColor("#FFF3E0")
GREEN    = HexColor("#1A6B3C")
GREEN_LT = HexColor("#E8F5E9")
GREY_LT  = HexColor("#F4F6F9")
GREY_MID = HexColor("#BDC3C7")
SLATE    = HexColor("#2C3E50")
WHITE    = colors.white

doc = SimpleDocTemplate(
    OUTPUT, pagesize=A4,
    leftMargin=LM, rightMargin=RM, topMargin=TM, bottomMargin=BM,
    title="Train-of-Four (TOF) Neuromuscular Monitoring",
    author="Orris Medical Reference",
)

# ── Style factory ────────────────────────────────────────────────────────────
def S(name, **kw):
    return ParagraphStyle(name, **kw)

S_TITLE   = S("title", fontName="Helvetica-Bold", fontSize=18,
               textColor=WHITE, leading=24, alignment=TA_CENTER)
S_SUBT    = S("subt",  fontName="Helvetica",      fontSize=9,
               textColor=HexColor("#C8DCF0"), leading=13, alignment=TA_CENTER)
S_H1      = S("h1",    fontName="Helvetica-Bold", fontSize=11,
               textColor=WHITE, leading=15, spaceAfter=0)
S_H2      = S("h2",    fontName="Helvetica-Bold", fontSize=9.5,
               textColor=WHITE, leading=13, spaceAfter=0)
S_BODY    = S("body",  fontName="Helvetica",      fontSize=8.5,
               textColor=HexColor("#1A1A2E"), leading=12.5, spaceAfter=0, alignment=TA_JUSTIFY)
S_BOLD    = S("bold",  fontName="Helvetica-Bold", fontSize=8.5,
               textColor=HexColor("#1A1A2E"), leading=12.5, spaceAfter=0)
S_BULLET  = S("bul",   fontName="Helvetica",      fontSize=8.3,
               textColor=HexColor("#1A1A2E"), leading=12, leftIndent=8, spaceAfter=0)
S_WARN    = S("warn",  fontName="Helvetica-Bold", fontSize=8.3,
               textColor=RED, leading=12, spaceAfter=0)
S_NOTE    = S("note",  fontName="Helvetica-Oblique", fontSize=7.5,
               textColor=HexColor("#555566"), leading=10, alignment=TA_CENTER)
S_TH      = S("th",    fontName="Helvetica-Bold", fontSize=8,
               textColor=WHITE, leading=11)
S_TD      = S("td",    fontName="Helvetica",      fontSize=8,
               textColor=HexColor("#1A1A2E"), leading=11)
S_TD_B    = S("tdb",   fontName="Helvetica-Bold", fontSize=8,
               textColor=HexColor("#1A1A2E"), leading=11)
S_FOOTER  = S("foot",  fontName="Helvetica-Oblique", fontSize=6.5,
               textColor=HexColor("#888899"), leading=9, alignment=TA_CENTER)
S_CAP     = S("cap",   fontName="Helvetica-Oblique", fontSize=7.5,
               textColor=HexColor("#444455"), leading=10, alignment=TA_CENTER)
S_KEY     = S("key",   fontName="Helvetica-Bold", fontSize=8,
               textColor=NAVY, leading=11.5, leftIndent=4)

# ── Helpers ──────────────────────────────────────────────────────────────────
def banner(text, sub=None, bg=NAVY, accent=TEAL):
    rows = [[Paragraph(text, S_TITLE)]]
    if sub:
        rows.append([Paragraph(sub, S_SUBT)])
    t = Table(rows, colWidths=[CW])
    ts = [
        ("BACKGROUND", (0,0), (-1,-1), bg),
        ("TOPPADDING",    (0,0), (-1,-1), 10),
        ("BOTTOMPADDING", (0,0), (-1,-1), 10),
        ("LEFTPADDING",   (0,0), (-1,-1), 10),
        ("RIGHTPADDING",  (0,0), (-1,-1), 10),
        ("LINEBELOW", (0,-1), (-1,-1), 3, accent),
    ]
    t.setStyle(TableStyle(ts))
    return t

def sec_hdr(text, bg=TEAL):
    t = Table([[Paragraph(f"▌  {text}", S_H1)]], colWidths=[CW])
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0), (-1,-1), bg),
        ("TOPPADDING",    (0,0), (-1,-1), 5),
        ("BOTTOMPADDING", (0,0), (-1,-1), 5),
        ("LEFTPADDING",   (0,0), (-1,-1), 8),
        ("RIGHTPADDING",  (0,0), (-1,-1), 8),
    ]))
    return t

def sub_hdr(text, bg=SLATE):
    t = Table([[Paragraph(f"  {text}", S_H2)]], colWidths=[CW])
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0), (-1,-1), bg),
        ("TOPPADDING",    (0,0), (-1,-1), 3),
        ("BOTTOMPADDING", (0,0), (-1,-1), 3),
        ("LEFTPADDING",   (0,0), (-1,-1), 8),
        ("RIGHTPADDING",  (0,0), (-1,-1), 8),
    ]))
    return t

def body_box(paras, bg=GREY_LT):
    rows = [[p] for p in paras]
    t = Table(rows, colWidths=[CW])
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0), (-1,-1), bg),
        ("TOPPADDING",    (0,0), (-1,-1), 3),
        ("BOTTOMPADDING", (0,0), (-1,-1), 3),
        ("LEFTPADDING",   (0,0), (-1,-1), 8),
        ("RIGHTPADDING",  (0,0), (-1,-1), 8),
        ("VALIGN",        (0,0), (-1,-1), "TOP"),
    ]))
    return t

def two_col(left_items, right_items, bg_l=GREY_LT, bg_r=WHITE):
    max_r = max(len(left_items), len(right_items))
    rows  = []
    for i in range(max_r):
        lp = left_items[i]  if i < len(left_items)  else Paragraph("", S_BODY)
        rp = right_items[i] if i < len(right_items) else Paragraph("", S_BODY)
        rows.append([lp, rp])
    cw = CW / 2 - 2*mm
    t  = Table(rows, colWidths=[cw, cw])
    t.setStyle(TableStyle([
        ("ROWBACKGROUNDS", (0,0), (-1,-1), [GREY_LT, WHITE]),
        ("TOPPADDING",    (0,0), (-1,-1), 3),
        ("BOTTOMPADDING", (0,0), (-1,-1), 3),
        ("LEFTPADDING",   (0,0), (-1,-1), 6),
        ("RIGHTPADDING",  (0,0), (-1,-1), 6),
        ("VALIGN",        (0,0), (-1,-1), "TOP"),
        ("LINEBETWEEN",   (0,0), (1,-1),  0.4, GREY_MID),
        ("LINEBELOW",     (0,-1), (-1,-1), 0.4, GREY_MID),
    ]))
    return t

def info_table(data, col_widths, hdr_bg=NAVY, row_bg=GREY_LT):
    header = [Paragraph(str(h), S_TH) for h in data[0]]
    body   = [[Paragraph(str(c), S_TD) for c in row] for row in data[1:]]
    all_r  = [header] + body
    t      = Table(all_r, colWidths=col_widths)
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0), (-1,0),  hdr_bg),
        ("ROWBACKGROUNDS",(0,1), (-1,-1), [row_bg, WHITE]),
        ("TOPPADDING",    (0,0), (-1,-1), 3),
        ("BOTTOMPADDING", (0,0), (-1,-1), 3),
        ("LEFTPADDING",   (0,0), (-1,-1), 5),
        ("RIGHTPADDING",  (0,0), (-1,-1), 5),
        ("VALIGN",        (0,0), (-1,-1), "TOP"),
        ("GRID",          (0,0), (-1,-1), 0.4, GREY_MID),
    ]))
    return t

def callout(text, bg=AMBER_LT, border=AMBER, style=None):
    s = style or S_KEY
    t = Table([[Paragraph(text, s)]], colWidths=[CW])
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0), (-1,-1), bg),
        ("TOPPADDING",    (0,0), (-1,-1), 5),
        ("BOTTOMPADDING", (0,0), (-1,-1), 5),
        ("LEFTPADDING",   (0,0), (-1,-1), 10),
        ("RIGHTPADDING",  (0,0), (-1,-1), 10),
        ("BOX",           (0,0), (-1,-1), 1.2, border),
    ]))
    return t

def img_block(path, caption, width_mm=130):
    img = Image(path, width=width_mm*mm, height=None)
    cap = Paragraph(caption, S_CAP)
    t = Table([[img], [cap]], colWidths=[CW])
    t.setStyle(TableStyle([
        ("ALIGN",         (0,0), (-1,-1), "CENTER"),
        ("TOPPADDING",    (0,0), (-1,-1), 4),
        ("BOTTOMPADDING", (0,0), (-1,-1), 2),
        ("BACKGROUND",    (0,0), (-1,-1), WHITE),
        ("BOX",           (0,0), (-1,-1), 0.5, GREY_MID),
    ]))
    return t

def bullet(txt, indent=0):
    prefix = "    " * indent
    return Paragraph(f"{prefix}•  {txt}", S_BULLET)

def warn(txt):
    return Paragraph(f"⚠  {txt}", S_WARN)

# ────────────────────────────────────────────────────────────────────────────
story = []

# ── TITLE BANNER ─────────────────────────────────────────────────────────────
story.append(banner(
    "TRAIN-OF-FOUR (TOF) NEUROMUSCULAR MONITORING",
    sub="A Complete Easy-to-Understand Reference for Anaesthetists & Perioperative Teams",
    bg=NAVY, accent=TEAL
))
story.append(Spacer(1, 5*mm))

# ── WHY SECTION ──────────────────────────────────────────────────────────────
story.append(sec_hdr("WHY DO WE MONITOR NEUROMUSCULAR BLOCKADE?", bg=NAVY))
story.append(body_box([
    Paragraph(
        "When a neuromuscular blocking drug (NMBD) is given, the muscle becomes paralysed. "
        "The challenge is knowing <b>exactly how paralysed</b> the patient is at any given moment — "
        "you cannot judge this visually. A peripheral nerve stimulator sends controlled electrical pulses "
        "to a nerve (usually the <b>ulnar nerve</b> at the wrist), and we observe the resulting muscle "
        "twitch (usually the <b>adductor pollicis / thumb</b>) to estimate the depth of block.",
        S_BODY),
    Spacer(1, 2*mm),
    Paragraph(
        "Think of it like pressing a doorbell repeatedly — the height of the 'ring' (twitch) tells you "
        "how much signal is getting through the neuromuscular junction.",
        S_BODY),
    Spacer(1, 2*mm),
    warn("As many as 30–40% of patients reversed with neostigmine have residual paralysis at extubation. "
         "Objective TOF monitoring dramatically reduces this risk."),
], bg=GREY_LT))
story.append(Spacer(1, 4*mm))

# ── SECTION 1: TOF STIMULATION ────────────────────────────────────────────────
story.append(sec_hdr("1.  TRAIN-OF-FOUR (TOF) STIMULATION — THE BASICS", bg=TEAL))
story.append(Spacer(1, 1*mm))

story.append(sub_hdr("What is it?", bg=SLATE))
story.append(body_box([
    Paragraph(
        "The nerve stimulator delivers <b>4 electrical pulses in rapid succession</b>, "
        "each separated by 0.5 seconds (= 2 Hz frequency). This produces <b>4 twitches</b> "
        "(T1, T2, T3, T4) in the monitored muscle.",
        S_BODY),
    Spacer(1,2*mm),
    Paragraph("The train should <b>not</b> be repeated more frequently than every <b>10–15 seconds</b> "
              "— repeating too soon causes physiological fade independent of any drug effect.", S_BODY),
], bg=TEAL_LT))
story.append(Spacer(1, 2*mm))

story.append(img_block(
    BASE + "tof_unblocked.png",
    "Fig. 1 — TOF in an unblocked patient: all 4 twitches are equal height → T₄/T₁ ratio = 1.0  "
    "(Barash Clinical Anesthesia 9e)",
    width_mm=110
))
story.append(Spacer(1, 3*mm))

story.append(sub_hdr("Normal state (no NMBD)", bg=GREEN))
story.append(body_box([
    Paragraph("All 4 twitches are <b>equal height</b>. T1 = T2 = T3 = T4. TOF ratio = 1.0", S_BODY),
    Paragraph("The nerve's ready acetylcholine (ACh) stores are plentiful — so even though each "
              "pulse depletes a small amount, there is always enough left for a full-strength twitch.", S_BODY),
], bg=GREEN_LT))
story.append(Spacer(1, 2*mm))

story.append(sub_hdr("What happens with a nondepolarising NMBD (rocuronium, vecuronium, cisatracurium)?", bg=SLATE))
story.append(body_box([
    Paragraph("The drug <b>competes with ACh</b> at postsynaptic nicotinic receptors AND blocks "
              "<b>presynaptic α3β2 receptors</b> that normally signal the nerve terminal to "
              "mobilise more ACh stores for the next impulse.", S_BODY),
    Spacer(1,1*mm),
    Paragraph("Result: each successive pulse releases progressively <b>less ACh</b>, and there are "
              "fewer free receptors → <b>each twitch gets progressively weaker.</b> "
              "This progressive weakening is called <b>FADE</b>.", S_BODY),
    Spacer(1,1*mm),
    Paragraph(
        "<b>Analogy:</b> Imagine a bucket of water (ACh stores) and a partially clogged drain "
        "(blocked receptors). Each time you press the button, less water gets through. "
        "The first press = big splash (T1). By the 4th press = much smaller splash (T4). "
        "The difference between them = <b>fade</b>.",
        S_BODY),
], bg=GREY_LT))
story.append(Spacer(1, 3*mm))

story.append(img_block(
    BASE + "tof_nondep_dep.png",
    "Fig. 2 — TOF responses: Nondepolarising block shows progressive fade (T4 < T1). "
    "Depolarising block (suxamethonium) shows all 4 twitches diminish equally — NO fade.  "
    "(Miller's Anesthesia 10e)",
    width_mm=125
))
story.append(Spacer(1, 4*mm))

# ── SECTION 2: TOF COUNT ─────────────────────────────────────────────────────
story.append(sec_hdr("2.  TOF COUNT", bg=PURPLE))
story.append(Spacer(1, 1*mm))

story.append(sub_hdr("Definition", bg=SLATE))
story.append(body_box([
    Paragraph("Simply <b>count how many twitches you can feel or see</b> out of the 4. "
              "This is the TOF count.", S_BODY),
    Spacer(1,1*mm),
    Paragraph(
        "<b>Key rule:</b> As the block deepens, twitches disappear in <b>reverse order — "
        "T4 goes first, then T3, then T2, then T1.</b> "
        "During recovery they return in the <b>same reverse order: T1 first, T2, T3, then T4 last.</b>",
        S_BOLD),
], bg=PURP_LT))
story.append(Spacer(1, 2*mm))

story.append(info_table([
    ["TOF Count",  "Depth of Block",               "Approx. % Receptors Occupied", "Clinical State"],
    ["4 / 4",      "Minimal / Recovering",          "~70–75%",                      "Surgical relaxation may still be present; DO NOT extubate without ratio ≥0.9"],
    ["3 / 4",      "Moderate-Deep surgical block",  "~80%",                         "Adequate for most surgery"],
    ["2 / 4",      "Deep surgical block",           "~85%",                         "Good relaxation"],
    ["1 / 4",      "Very deep block",               "~90%",                         "Use PTC to assess further"],
    ["0 / 4",      "Profound block",                ">90–95%",                      "Switch to Post-Tetanic Count (PTC)"],
], col_widths=[20*mm, 42*mm, 44*mm, 60*mm],
hdr_bg=PURPLE, row_bg=PURP_LT))
story.append(Spacer(1, 2*mm))

story.append(callout(
    "★  Memory trick for deepening block:  T4 → T3 → T2 → T1 disappear  "
    "|  Recovery: T1 → T2 → T3 → T4 return  |  'Last in, first out'",
    bg=PURP_LT, border=PURPLE, style=S_KEY
))
story.append(Spacer(1, 4*mm))

# ── SECTION 3: TOF RATIO ─────────────────────────────────────────────────────
story.append(sec_hdr("3.  TOF RATIO (T4/T1)", bg=HexColor("#0E6655")))
story.append(Spacer(1, 1*mm))

story.append(sub_hdr("Definition", bg=SLATE))
story.append(body_box([
    Paragraph("When <b>all 4 twitches are present</b>, the TOF ratio is:", S_BODY),
    Spacer(1,1*mm),
    Paragraph(
        "<font size=12><b>TOF Ratio  =  Height of T4  ÷  Height of T1</b></font>",
        S("big", fontName="Helvetica-Bold", fontSize=11,
          textColor=TEAL, alignment=TA_CENTER, leading=16)),
    Spacer(1,1*mm),
    Paragraph("Range: 0 (no T4) → 1.0 (T4 = T1, fully recovered)", S_BODY),
    Paragraph("The <b>lower</b> the ratio, the <b>more residual block</b> remains.", S_BODY),
], bg=TEAL_LT))
story.append(Spacer(1, 2*mm))

story.append(sub_hdr("The critical threshold: TOF ratio ≥ 0.9", bg=GREEN))
story.append(body_box([
    Paragraph(
        "A TOF ratio of <b>≥ 0.9</b> is the internationally accepted threshold for safe extubation "
        "and full neuromuscular recovery. Below 0.9 = <b>residual paralysis.</b>",
        S_BOLD),
    Spacer(1,1*mm),
    Paragraph("Residual paralysis (TOF ratio 0.4–0.9) significantly increases the risk of:", S_BODY),
    bullet("Upper airway obstruction"),
    bullet("Aspiration (impaired pharyngeal and laryngeal reflexes)"),
    bullet("Hypoxaemia after extubation"),
    bullet("Unpleasant symptoms: diplopia, difficulty swallowing, generalised weakness"),
], bg=GREEN_LT))
story.append(Spacer(1, 2*mm))

story.append(sub_hdr("The clinical trap — why you CANNOT rely on your fingers alone", bg=RED))
story.append(body_box([
    warn("Subjective (tactile/visual) assessment can only detect fade when TOF ratio is < 0.4."),
    Spacer(1,1*mm),
    Paragraph(
        "Between TOF ratio <b>0.4 and 0.9</b> — the exact danger zone for residual paralysis — "
        "<b>you cannot feel or see any difference by hand.</b> The patient feels 'recovered' "
        "to your touch, but their airway reflexes and respiratory reserve are still impaired.",
        S_BODY),
    Spacer(1,1*mm),
    Paragraph(
        "<b>Solution:</b> Use an <b>objective quantitative monitoring device</b> (acceleromyography, "
        "kinemyography, or electromyography) to measure the actual numeric ratio.",
        S_BOLD),
], bg=RED_LT))
story.append(Spacer(1, 2*mm))

tof_ratio_table = info_table([
    ["TOF Ratio",  "What You Can Feel/See",          "Clinical Meaning"],
    ["1.0",        "4 equal twitches",                "Fully recovered — safe to extubate"],
    ["0.9–1.0",    "Feels equal (cannot detect fade)",  "⚠ Target threshold — need device to confirm"],
    ["0.7–0.9",    "Cannot feel fade by hand",         "⚠ Residual paralysis — DO NOT extubate"],
    ["0.4–0.7",    "Usually cannot feel fade",         "⚠ Significant residual block"],
    ["<0.4",       "Fade detectable by hand",          "Moderate–deep block"],
    ["0",          "Only 1–3 twitches present",        "TOF count used instead of ratio"],
], col_widths=[25*mm, 65*mm, 76*mm],
hdr_bg=HexColor("#0E6655"), row_bg=TEAL_LT)
story.append(tof_ratio_table)
story.append(Spacer(1, 4*mm))

# ── SECTION 4: FADE ──────────────────────────────────────────────────────────
story.append(sec_hdr("4.  FADE — MECHANISM AND MEANING", bg=AMBER))
story.append(Spacer(1, 1*mm))

story.append(sub_hdr("What exactly is fade?", bg=SLATE))
story.append(body_box([
    Paragraph(
        "<b>Fade</b> = the progressive weakening of successive muscle twitches during repeated "
        "stimulation. It is the <b>hallmark of nondepolarising (competitive) block</b> and is "
        "<b>absent in normal depolarising (phase I) block.</b>",
        S_BODY),
], bg=AMBER_LT))
story.append(Spacer(1, 1*mm))

story.append(sub_hdr("Two mechanisms that cause fade", bg=SLATE))
left_items = [
    Paragraph("<b>1. Postsynaptic (receptor depletion effect)</b>", S_BOLD),
    Spacer(1,1*mm),
    bullet("The drug occupies postsynaptic nicotinic ACh receptors at the muscle end-plate."),
    bullet("Each successive nerve impulse releases slightly less ACh (stores deplete)."),
    bullet("With fewer free receptors AND less ACh → each successive twitch is weaker."),
    bullet("This creates the characteristic staircase descent: T1 > T2 > T3 > T4."),
]
right_items = [
    Paragraph("<b>2. Presynaptic (mobilisation failure)</b>", S_BOLD),
    Spacer(1,1*mm),
    bullet("Nondepolarising NMBDs also block presynaptic neuronal-subtype α3β2 receptors."),
    bullet("These receptors normally act as a feedback sensor: 'We're running low on ACh — mobilise more!'"),
    bullet("Block them → the nerve can't replenish its ACh store fast enough → accelerated depletion."),
    bullet("This is considered the MAIN driver of fade, especially during TOF and tetanic stimulation."),
]
story.append(two_col(left_items, right_items))
story.append(Spacer(1, 3*mm))

story.append(callout(
    "★  Key concept: FADE is a presynaptic phenomenon at its core — caused by blockade of "
    "presynaptic ACh mobilisation receptors, worsened by postsynaptic receptor competition. "
    "No fade = no presynaptic involvement = depolarising (suxamethonium) block.",
    bg=AMBER_LT, border=AMBER
))
story.append(Spacer(1, 4*mm))

# ── SECTION 5: TETANIC STIMULATION ───────────────────────────────────────────
story.append(sec_hdr("5.  TETANIC STIMULATION AND TETANIC FADE", bg=RED))
story.append(Spacer(1, 1*mm))

story.append(sub_hdr("What is tetanic stimulation?", bg=SLATE))
story.append(body_box([
    Paragraph(
        "Instead of 4 spaced pulses, the stimulator fires at <b>50 Hz (50 pulses per second) "
        "continuously for 5 seconds</b>. This is an intense, high-frequency stimulus that rapidly "
        "demands large amounts of ACh release.",
        S_BODY),
    Spacer(1,1*mm),
    Paragraph(
        "<b>Normal response (no drug):</b> One strong, <b>sustained</b> muscle contraction throughout "
        "the 5 seconds — called a tetanic contraction. Feels like one hard squeeze.",
        S_BODY),
    Spacer(1,1*mm),
    Paragraph(
        "<b>With nondepolarising block:</b> The contraction <b>starts strong but fades</b> — the "
        "muscle weakens visibly partway through. This is <b>tetanic fade</b>. "
        "This is because ACh stores are depleted much faster at 50 Hz than at the 2 Hz of TOF, "
        "and presynaptic mobilisation failure becomes even more apparent.",
        S_BODY),
    Spacer(1,1*mm),
    Paragraph(
        "<b>With depolarising block (suxamethonium — phase I):</b> The tetanic response is <b>fully "
        "sustained</b> — no fade. The drug works by persistent depolarisation (not competitive "
        "blockade), so presynaptic mobilisation is not impaired.",
        S_BODY),
], bg=RED_LT))
story.append(Spacer(1, 2*mm))

story.append(img_block(
    BASE + "tetanic.png",
    "Fig. 3 — Tetanic stimulation (50 Hz / 5 s): Control = sustained contraction. "
    "Moderate nondep. block = fade + post-tetanic facilitation. "
    "Moderate dep. block = sustained, no post-tetanic facilitation.  (Miller's Anesthesia 10e)",
    width_mm=130
))
story.append(Spacer(1, 2*mm))

story.append(sub_hdr("Post-Tetanic Facilitation and Post-Tetanic Count (PTC)", bg=SLATE))
story.append(body_box([
    Paragraph(
        "After tetanic stimulation, the nerve terminal has been intensely 'revved up' and "
        "temporarily releases <b>more ACh than usual</b> for the next few minutes. "
        "If you then apply single twitches, they are temporarily <b>bigger than before</b> — "
        "this is called <b>post-tetanic facilitation</b>.",
        S_BODY),
    Spacer(1,1*mm),
    Paragraph("<b>Post-Tetanic Count (PTC)</b> — used when block is <b>so deep that TOF = 0</b>:", S_BOLD),
    Spacer(1,1*mm),
    bullet("Apply 50 Hz tetanus for 5 seconds"),
    bullet("Wait 3 seconds"),
    bullet("Apply single twitches at 1 Hz and count how many appear"),
    bullet("Fewer PTC twitches = deeper block. PTC ≥ 10 predicts return of TOF count 1 within minutes."),
    Spacer(1,1*mm),
    warn("Post-tetanic facilitation occurs ONLY with nondepolarising block. "
         "It does NOT occur with suxamethonium phase I block — another way to distinguish the two."),
], bg=GREY_LT))
story.append(Spacer(1, 4*mm))

# ── SECTION 6: DEPOLARISING vs NON-DEPOLARISING COMPARISON ───────────────────
story.append(sec_hdr("6.  NONDEPOLARISING vs DEPOLARISING BLOCK — SIDE-BY-SIDE", bg=NAVY))
story.append(Spacer(1, 1*mm))

story.append(info_table([
    ["Feature",                  "Nondepolarising Block\n(rocuronium, vecuronium, cisatracurium)",
                                  "Depolarising Block — Phase I\n(suxamethonium)"],
    ["Mechanism",                "Competitive ACh receptor antagonism\n+ presynaptic α3β2 blockade",
                                  "Persistent receptor depolarisation\n(agonist-type binding)"],
    ["TOF twitches",             "T4 disappears first → T3 → T2 → T1",
                                  "All 4 twitches diminish equally"],
    ["TOF fade (T4/T1)",         "YES — T4 < T1  (ratio < 1.0)",
                                  "NO — T4 = T1  (ratio stays 1.0)"],
    ["Tetanic stimulation",      "FADE — contraction weakens over 5 sec",
                                  "SUSTAINED — no fade"],
    ["Post-tetanic facilitation","YES — twitches larger after tetanus",
                                  "NO — no change after tetanus"],
    ["Phase II block (sux)",     "N/A",
                                  "After large/repeated doses: FADE appears\n(behaves like nondep. block)"],
    ["Reversal",                 "Neostigmine (if TOF≥2), sugammadex (rocuronium/vecuronium)",
                                  "Wait for pseudocholinesterase metabolism"],
], col_widths=[40*mm, 76*mm, 50*mm],
hdr_bg=NAVY, row_bg=GREY_LT))
story.append(Spacer(1, 4*mm))

# ── SECTION 7: DEPTH OF BLOCK OVERVIEW ───────────────────────────────────────
story.append(sec_hdr("7.  DEPTH OF BLOCK — COMPLETE OVERVIEW", bg=HexColor("#6C3483")))
story.append(Spacer(1, 1*mm))

story.append(info_table([
    ["Depth",         "TOF Count", "TOF Ratio",  "PTC",         "Clinical Meaning / Action"],
    ["Intense",       "0",         "N/A",         "0",           "Maximum block — use for intubation, complex laparoscopy"],
    ["Deep",          "0",         "N/A",         "1–5",         "Cannot reverse — wait or use sugammadex"],
    ["Deep-moderate", "0",         "N/A",         "6–10",        "Approaching return of TOF; plan reversal timing"],
    ["Moderate",      "1–3",       "Not useable", "N/A",         "Surgical relaxation; can reverse with sugammadex; neostigmine needs TOF≥2"],
    ["Shallow",       "4",         "0.1–0.4",     "N/A",         "Fade visible by hand; neostigmine reversal possible"],
    ["Minimal",       "4",         "0.4–0.9",     "N/A",         "⚠ RESIDUAL PARALYSIS — looks OK by hand, NOT safe"],
    ["Full recovery", "4",         "≥ 0.9",       "N/A",         "Safe to extubate — MUST use device to confirm"],
], col_widths=[28*mm, 22*mm, 22*mm, 20*mm, 74*mm],
hdr_bg=HexColor("#6C3483"), row_bg=PURP_LT))
story.append(Spacer(1, 4*mm))

# ── SECTION 8: LIMITATIONS ───────────────────────────────────────────────────
story.append(sec_hdr("8.  LIMITATIONS OF SUBJECTIVE TOF MONITORING", bg=SLATE))
story.append(Spacer(1, 1*mm))

lim_left = [
    Paragraph("<b>What you CANNOT detect by hand:</b>", S_BOLD),
    Spacer(1,1*mm),
    warn("Fade between TOF ratio 0.4 and 0.9 — the exact zone of dangerous residual paralysis."),
    Spacer(1,1*mm),
    bullet("Subjective fade detection accurate only at ratio < 0.4"),
    bullet("Even 100 Hz tetanus only detects fade up to ratio ~0.4–0.5"),
    bullet("Double-burst stimulation (DBS) is marginally better but still unreliable above 0.6"),
    bullet("Postoperative residual paralysis rate: 30–40% with neostigmine reversal"),
]
lim_right = [
    Paragraph("<b>What OBJECTIVE devices provide:</b>", S_BOLD),
    Spacer(1,1*mm),
    bullet("Acceleromyography (AMG): measures thumb acceleration — most common portable device"),
    bullet("Electromyography (EMG): measures electrical signal — gold standard"),
    bullet("Kinemyography (KMG): measures bending of finger — found in TOF-Watch devices"),
    Spacer(1,1*mm),
    Paragraph(
        "Guidelines from Canada, France, Spain, Australia now <b>advocate quantitative monitoring</b> "
        "before extubation of every patient receiving NMBDs.",
        S_BODY),
]
story.append(two_col(lim_left, lim_right))
story.append(Spacer(1, 4*mm))

# ── QUICK REFERENCE SUMMARY ───────────────────────────────────────────────────
story.append(sec_hdr("QUICK REFERENCE SUMMARY — EVERYTHING AT A GLANCE", bg=TEAL))
story.append(Spacer(1, 1*mm))

story.append(info_table([
    ["Concept",               "Simple Meaning",                                  "Key Number / Fact"],
    ["TOF Stimulation",       "4 pulses at 2 Hz → 4 twitches (T1–T4)",          "Repeat every ≥10–15 sec"],
    ["TOF Count",             "How many of the 4 twitches are present",          "0 = profound; 4 = at least moderate recovery"],
    ["TOF Ratio (T4/T1)",     "T4 height ÷ T1 height",                           "≥ 0.9 = safe to extubate"],
    ["Fade",                  "T4 weaker than T1 (nondep. block sign)",           "Detectable by hand only if ratio < 0.4"],
    ["No Fade",               "All twitches equal height",                        "Suxamethonium phase I — no presynaptic blockade"],
    ["Tetanic Stimulation",   "50 Hz for 5 sec — demands heavy ACh release",     "Fade = nondep block; Sustained = dep block"],
    ["Post-tetanic Facilitation", "Twitches bigger immediately after tetanus",   "Only with nondepolarising block; not with sux"],
    ["PTC (Post-Tetanic Count)", "Count twitches after tetanus when TOF = 0",   "PTC ≥ 10 → TOF count 1 will return soon"],
    ["Residual Paralysis",    "TOF ratio 0.4–0.9 — feels recovered, IS NOT",    "Cannot detect by hand — need objective device"],
], col_widths=[42*mm, 80*mm, 44*mm],
hdr_bg=TEAL, row_bg=TEAL_LT))
story.append(Spacer(1, 3*mm))

# ── KEY REMINDERS ─────────────────────────────────────────────────────────────
reminders = [
    "TOF ratio ≥ 0.9 is the ONLY reliable threshold for safe extubation — you need an objective device to confirm it.",
    "Fade is the fingerprint of nondepolarising block. No fade = depolarising (suxamethonium) or fully recovered.",
    "Subjective (hand) monitoring misses residual paralysis in the 0.4–0.9 ratio range — the most dangerous zone.",
    "T4 is lost first as block deepens; T4 returns last during recovery. Use this to track the curve of block.",
    "Tetanic stimulation is more sensitive than TOF for detecting small amounts of residual block — but it can alter subsequent monitoring for several minutes, so use it sparingly.",
]

rem_header = Table([[Paragraph("★  CRITICAL REMINDERS", S("remh", fontName="Helvetica-Bold", fontSize=9, textColor=WHITE, leading=13))]],
    colWidths=[CW])
rem_header.setStyle(TableStyle([
    ("BACKGROUND",(0,0),(-1,-1), AMBER),
    ("TOPPADDING",(0,0),(-1,-1), 4),
    ("BOTTOMPADDING",(0,0),(-1,-1), 4),
    ("LEFTPADDING",(0,0),(-1,-1), 8),
]))
story.append(rem_header)

rem_rows = [[Paragraph(f"★  {r}", S_KEY)] for r in reminders]
rem_tbl = Table(rem_rows, colWidths=[CW])
rem_tbl.setStyle(TableStyle([
    ("BACKGROUND",(0,0),(-1,-1), AMBER_LT),
    ("TOPPADDING",(0,0),(-1,-1), 3),
    ("BOTTOMPADDING",(0,0),(-1,-1), 3),
    ("LEFTPADDING",(0,0),(-1,-1), 8),
    ("RIGHTPADDING",(0,0),(-1,-1), 8),
    ("LINEBELOW",(0,0),(-1,-2), 0.3, AMBER),
    ("BOX",(0,0),(-1,-1), 1, AMBER),
]))
story.append(rem_tbl)
story.append(Spacer(1, 3*mm))

# ── FOOTER ────────────────────────────────────────────────────────────────────
story.append(HRFlowable(width=CW, thickness=0.5, color=GREY_MID))
story.append(Spacer(1, 1*mm))
story.append(Paragraph(
    "Orris Medical Reference  |  Train-of-Four (TOF) Neuromuscular Monitoring  |  "
    "Sources: Miller's Anesthesia 10e (Ch. 39), Barash Clinical Anesthesia 9e (Ch. 21), "
    "Morgan & Mikhail Clinical Anesthesiology 7e  |  June 2026  |  "
    "For educational and clinical reference use only — verify against local protocols.",
    S_FOOTER
))

# ── BUILD ─────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF written: {OUTPUT}")
print(f"File size: {os.path.getsize(OUTPUT):,} bytes")
Running Command

cd /home/daytona/workspace/tof-nmb && python3 generate_tof_pdf.py 2>&1

Editing File

~/tof-nmb/generate_tof_pdf.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/tof-nmb/generate_tof_pdf.py'
Editing File

~/tof-nmb/generate_tof_pdf.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/tof-nmb/generate_tof_pdf.py'
Editing File

~/tof-nmb/generate_tof_pdf.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/tof-nmb/generate_tof_pdf.py'
Editing File

~/tof-nmb/generate_tof_pdf.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/tof-nmb/generate_tof_pdf.py'
Editing File

~/tof-nmb/generate_tof_pdf.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/tof-nmb/generate_tof_pdf.py'
Editing File

~/tof-nmb/generate_tof_pdf.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/tof-nmb/generate_tof_pdf.py'
Running Command

cd /home/daytona/workspace/tof-nmb && python3 generate_tof_pdf.py 2>&1

Your PDF is ready - 476 KB, fully formatted:

TOF Neuromuscular Monitoring

PDF Document · PDF


What's inside the PDF:
SectionContent
Why we monitorClinical rationale, residual paralysis incidence (30-40%)
Section 1 - TOF StimulationHow it works, the bucket-of-ACh analogy, includes the TOF pattern diagram (Fig. 1 & 2)
Section 2 - TOF CountFull table: count 0-4 vs receptor occupancy vs clinical state; memory trick
Section 3 - TOF RatioFormula, critical 0.9 threshold, the danger zone (0.4-0.9), why your fingers lie
Section 4 - FadeBoth mechanisms explained (postsynaptic + presynaptic α3β2); analogy
Section 5 - Tetanic Stimulation50 Hz/5 sec, fade vs sustained, post-tetanic facilitation, PTC; includes Fig. 3
Section 6 - Nondep vs Dep comparisonFull side-by-side table: fade, tetanus, PTC, reversal
Section 7 - Depth of BlockIntense → deep → moderate → shallow → full recovery with all monitoring parameters
Section 8 - LimitationsWhy subjective monitoring fails; objective device types
Quick Reference SummaryAll concepts in one concise table
Critical Reminders5 gold-box key points
This is a shared conversation. Sign in to Orris to start your own chat.