Write a 30 marks answer for Postgraduate Anaesthesia exam on the topic of coagulation cascade and thromboelastography

Reading File
Finding Sources
Finding Sources
Searching PubMed

thromboelastography coagulation monitoring anaesthesia

Finding Sources
Reading File
Reading File
Reading Article

PMID: 42145275

Reading File
Finding Sources
Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Loading Image
Loading Image
Finding Sources
Reading File
I now have comprehensive content from multiple authoritative sources. Let me write the full postgraduate-level exam answer.

Coagulation Cascade and Thromboelastography

Postgraduate Anaesthesia Examination Answer (30 Marks)


1. Introduction (2 marks)

Haemostasis is a tightly regulated physiological process that arrests bleeding while maintaining vascular patency. It integrates three overlapping phases: primary haemostasis (platelet plug formation), secondary haemostasis (the coagulation cascade generating fibrin), and fibrinolysis (clot dissolution). Understanding the cascade and its point-of-care assessment with thromboelastography (TEG) and rotational thromboelastometry (ROTEM) is fundamental to perioperative and critical care anaesthetic practice.

2. The Coagulation Cascade (12 marks)

2.1 Classical (Waterfall) Model

The classical model, developed in the 1960s, divides coagulation into the extrinsic pathway, the intrinsic pathway, and a common pathway that converge at Factor Xa activation.
The coagulation cascade is a series of amplifying enzymatic reactions leading to deposition of an insoluble fibrin clot. Each reaction step involves an enzyme (activated coagulation factor), a substrate (inactive proenzyme), and a cofactor (reaction accelerator), assembled on negatively charged phospholipid surfaces provided by activated platelets. Calcium is required, binding to gamma-carboxylated glutamic acid residues on factors II, VII, IX, and X - these residues are synthesised using Vitamin K as cofactor and are antagonised by coumarin anticoagulants. (Robbins, Cotran & Kumar: Pathologic Basis of Disease)
Coagulation cascade - laboratory vs in vivo
Fig. 1 - Coagulation cascade: laboratory (intrinsic/extrinsic pathways) vs. in vivo (tissue factor-driven). Red = inactive factors, Blue = active factors, Green = cofactors. (Robbins Pathologic Basis of Disease)
Extrinsic pathway (assessed by PT/INR):
  • Tissue factor (TF), a subendothelial transmembrane glycoprotein constitutively expressed on fibroblasts and vascular smooth muscle cells, is exposed by vascular injury
  • TF binds plasma FVII, activating it to FVIIa (the TF:FVIIa extrinsic tenase complex)
  • TF:FVIIa activates FX → FXa and also FIX → FIXa
  • The PT assay assesses factors VII, X, V, II (prothrombin), and fibrinogen
Intrinsic pathway (assessed by aPTT):
  • Initiated in vitro by negatively charged surfaces activating FXII → FXIIa (Hageman factor)
  • FXIIa activates FXI → FXIa, which activates FIX → FIXa
  • FIXa + FVIIIa (intrinsic tenase complex on platelet surface) → activates FX
  • The aPTT assesses factors XII, XI, IX, VIII, X, V, II, and fibrinogen
Common pathway:
  • FXa + FVa (prothrombinase complex, assembled on negatively charged platelet membrane in the presence of calcium) converts prothrombin (FII) → thrombin (FIIa)
  • Thrombin cleaves fibrinogen → fibrin monomers → polymerised insoluble fibrin
  • Thrombin activates FXIII → FXIIIa, a transglutaminase that covalently cross-links fibrin strands, stabilising the clot
  • Thrombin also activates FV, FVIII, FXI (positive feedback amplification loops), and platelet activation via protease-activated receptor-1 (PAR-1)
Limitation of the classical model: Clinical observations challenge its relevance in vivo. Deficiency of FXII does not cause bleeding despite prolonging the aPTT. FVII and FVIII/FIX (haemophilias A and B) deficiencies cause severe bleeding even though each affects only one pathway. This paradox is resolved by the cell-based model. (Sabiston Textbook of Surgery; Harrison's Principles of Internal Medicine 22E)

2.2 Cell-Based Model of Coagulation (Current Paradigm)

The cell-based model, now the accepted physiological framework, emphasises overlapping interactions between coagulation proteins and specific cell membranes. It proceeds in three phases:
Phase 1 - Initiation (on TF-bearing cells - fibroblasts/VSMC): Vascular injury exposes subendothelial TF to plasma FVII, creating the TF:FVIIa complex. This activates small amounts of FX → FXa and FIX → FIXa. FXa + FVa on TF-bearing cells form the prothrombinase complex, generating trace thrombin - the trigger for amplification. Tissue factor pathway inhibitor (TFPI) rapidly inhibits the TF:FVIIa:FXa complex, limiting this phase. (Sabiston Textbook of Surgery)
Phase 2 - Amplification (on platelet surface): Trace thrombin generated in initiation travels to the injury site and activates platelets (via PAR-1/PAR-4), FV → FVa, and FVIII → FVIIIa, and releases vWF. Platelets adhere via GPIb to vWF and via GPIa/IIa or GPVI to subendothelial collagen. Platelet structural change produces net negatively charged outer membranes - the platform for coagulation assembly. This phase dramatically amplifies the pro-coagulant signal.
Phase 3 - Propagation (on activated platelet surface): The assembled intrinsic tenase complex (FIXa + FVIIIa) and prothrombinase complex (FXa + FVa) on the platelet surface generate a thrombin burst - large quantities of thrombin that:
  • Cleave fibrinogen → fibrin monomers
  • Activate FXIII → cross-linked fibrin
  • Activate TAFI (thrombin activatable fibrinolysis inhibitor)
  • Sustain further platelet and factor activation (Schwartz's Principles of Surgery 11e; Rockwood & Green's Fractures in Adults 10e)

2.3 Anticoagulant Mechanisms (4 marks)

Four major endogenous anticoagulant systems prevent unbounded clot propagation:
InhibitorMechanism
Antithrombin III (ATIII)Serine protease inhibitor inactivating thrombin, FXa, FIXa, FXIa, FXIIa. Heparin binds ATIII, inducing a conformational change that accelerates its activity ~1000-fold. Physiologically potentiated by heparan sulphate on endothelial surfaces
Tissue Factor Pathway Inhibitor (TFPI)Directly inhibits the TF:FVIIa:FXa complex, limiting initiation phase. Produced by endothelium
Protein C / Protein S systemThrombin bound to thrombomodulin (expressed on intact endothelium) activates Protein C. Activated Protein C (APC) + Protein S (cofactor) inactivate FVa and FVIIIa, shutting down the propagation phase
Prostacyclin (PGI2) and Nitric OxideReleased by intact endothelium; inhibit platelet aggregation and cause vasodilatation
(Harrison's Principles of Internal Medicine 22E; Goldman-Cecil Medicine)

2.4 Fibrinolysis

Once haemostasis is achieved, fibrinolysis restores vascular patency. Tissue-type plasminogen activator (t-PA), synthesised by endothelium and most active when bound to fibrin, converts plasminogen → plasmin. Plasmin degrades fibrin into fibrin degradation products (FDPs), notably D-dimers - a clinically useful marker of thrombus formation and lysis (DVT/PE screening, DIC). Alpha-2-antiplasmin rapidly inactivates free circulating plasmin. Plasminogen activator inhibitor-1 (PAI-1) inhibits t-PA and uPA. In DIC, PAI-1 is elevated, suppressing normal fibrinolysis and worsening microvascular thrombosis. (Robbins Pathologic Basis of Disease; Sabiston Textbook of Surgery)

3. Thromboelastography (TEG) and Rotational Thromboelastometry (ROTEM) (12 marks)

3.1 Principle and Technology

TEG (Haemonetics) and ROTEM (Werfen) are point-of-care viscoelastic haemostatic assays (VHAs) that measure the mechanical properties of whole blood as it clots. Unlike standard laboratory tests (PT, aPTT, platelet count), which assess individual components of coagulation in plasma under static conditions, VHAs assess the entire haemostatic process - including coagulation factor activity, platelet function, fibrinogen contribution, clot strength, and fibrinolysis - simultaneously and in real time.
Mechanism: In TEG, a small sample of whole blood is placed in a heated cuvette (37°C). A pin is suspended in the blood on a torsion wire. The cuvette oscillates; as a clot forms and strengthens, the increasing mechanical resistance is transmitted to the pin, which is detected as an electrical signal and plotted graphically as the characteristic thromboelastogram. In ROTEM, the cuvette is stationary and the pin rotates - functionally equivalent results, though numerical values differ and are not interchangeable. (Morgan & Mikhail's Clinical Anesthesiology 7e; Scott-Brown's Otorhinolaryngology, Head & Neck Surgery)

3.2 TEG Trace Parameters and Clinical Interpretation

TEG trace showing all parameters
Fig. 2 - Standard TEG trace. The enzymatic phase (R time) is followed by fibrinogen-mediated clot formation (K time, alpha angle), platelet-dependent clot strength (MA), and fibrinolysis (LY30, EPL). (Morgan & Mikhail's Clinical Anesthesiology 7e)
ParameterDefinitionNormal RangeClinical Significance
R time (Reaction time)Time from sample placement to first clot detection (2mm amplitude)5-10 minProlonged: coagulation factor deficiency, anticoagulants (heparin, warfarin, DOACs). Shortened: hypercoagulable state
K time (Kinetics)Time from R-time to 20mm amplitude; clot formation rate1-3 minProlonged: fibrinogen deficiency, thrombocytopaenia. Reflects fibrinogen and early platelet activity
Alpha angle (α)Angle of tangent to the curve at 2mm; rate of fibrin accumulation53-72°Reduced: fibrinogen deficiency, hypofibrinogenaemia. Increased: hypercoagulability. Guides cryoprecipitate use
Maximum Amplitude (MA)Greatest vertical width; reflects clot strength50-70 mmReduced: platelet dysfunction or thrombocytopaenia (platelets contribute ~80% of clot strength, fibrinogen ~20%). Guides platelet transfusion
LY30 (Lysis at 30 min)% reduction in amplitude 30 minutes after MA<7.5%Elevated (>7.5-8%): hyperfibrinolysis. Guides tranexamic acid / aminocaproic acid use
EPL (Estimated Percent Lysis)Predicted lysis before 30 min<15%Similar clinical use to LY30
CI (Coagulation Index)Composite algorithmic score-3 to +3<-3: hypocoagulable; >+3: hypercoagulable
(Morgan & Mikhail's Clinical Anesthesiology 7e; Rockwood & Green's Fractures in Adults 10e; Scott-Brown's Otorhinolaryngology Vol.1)
ROTEM Equivalents:
ROTEM ParameterTEG Equivalent
CT (Clotting Time)R time
CFT (Clot Formation Time)K time
Alpha angle (α)Alpha angle
MCF (Maximum Clot Firmness)MA
LI30 / MLLY30
ROTEM uses specific activator reagents: EXTEM (extrinsic pathway via tissue factor), INTEM (intrinsic pathway via ellagic acid), FIBTEM (extrinsic + platelet inhibitor cytochalasin D, isolating fibrinogen contribution), APTEM (extrinsic + aprotinin, detecting fibrinolysis).

3.3 TEG/ROTEM-Guided Transfusion Algorithms

The greatest clinical utility of VHAs is in goal-directed transfusion therapy, particularly in:
  1. Major trauma and haemorrhage - identifying trauma-induced coagulopathy (TIC), which is characterised by early hyperfibrinolysis, dilution, hypothermia, and acidosis (the "lethal triad")
  2. Cardiac surgery - distinguishing surgical from coagulopathic bleeding
  3. Liver transplantation - monitoring complex coagulopathy including hyperfibrinolysis
  4. Obstetric haemorrhage - real-time guidance for clotting factor replacement
  5. Neurosurgery - detecting hypercoagulability and guiding anticoagulation
Algorithmic use: prolonged R time → FFP or coagulation factor concentrates; reduced alpha/K time → cryoprecipitate or fibrinogen concentrate; reduced MA → platelet transfusion; elevated LY30 → tranexamic acid (TXA) or epsilon-aminocaproic acid. (Rockwood & Green's Fractures 10e; Morgan & Mikhail's Clinical Anesthesiology 7e)

3.4 Advantages over Standard Coagulation Tests

FeaturePT / aPTT / CBCTEG / ROTEM
SamplePlasma onlyWhole blood (includes platelets and RBCs)
ConditionStaticDynamic
Time45-90 min20-30 min (functional result)
Fibrinolysis detectedNo (directly)Yes
Platelet functionNoYes (via MA / MCF)
HypercoagulabilityNoYes
POC availabilityLimitedYes
Standard tests (PT, aPTT) do not detect hyperfibrinolysis, platelet dysfunction, qualitative fibrinogen defects, or hypercoagulability, and are performed on platelet-poor plasma under non-physiological conditions. TEG/ROTEM provide a global, dynamic, real-time haemostatic profile.

3.5 Limitations of TEG/ROTEM

  • Temperature sensitivity: samples must be maintained at 37°C
  • Inter-operator variability; time-sensitive sample processing required
  • Do not assess endothelial function or vascular component of haemostasis
  • Weak sensitivity for antiplatelet drugs (aspirin, ADP receptor inhibitors) - specific platelet mapping reagents needed
  • ROTEM and TEG values are not interchangeable and have different reference ranges
  • Evidence base predominantly from cardiac surgery; evidence in trauma and obstetrics is growing but certainty remains variable
  • Cost and availability in lower-resource settings

4. Current Evidence (4 marks)

A 2026 Cochrane systematic review (Kvisselgaard et al., 35 RCTs, n=3096, mostly cardiac surgery) found TEG/ROTEM-guided transfusion may reduce all-cause mortality (RR 0.76, 95% CI 0.63-0.92), reduce bleeding volume, reduce FFP and platelet transfusion use, and reduce surgical re-exploration, but noted the evidence is of very low certainty. No benefit in packed red blood cell use was demonstrated. This is consistent with earlier systematic reviews cited in Morgan & Mikhail and Goldman-Cecil Medicine (Anaesthesia 2017;72:519-531). The evidence is strongest for cardiac surgery, with emerging data in trauma, liver transplantation, and obstetrics.

5. Anaesthetic Relevance - Practical Summary (marks incorporated above)

The anaesthetist must:
  • Understand the cell-based model rather than the classical cascade alone, to interpret the clinical significance of factor deficiencies and guide replacement
  • Recognise the limitations of PT/aPTT: normal values do not exclude coagulopathy, and they do not detect fibrinolysis or platelet dysfunction
  • Use TEG/ROTEM as decision support tools within a goal-directed algorithm, not as isolated tests
  • Apply tranexamic acid early in high-risk haemorrhage (CRASH-2 / WOMAN trial evidence), as TEG-confirmed hyperfibrinolysis (LY30 >7.5%) indicates further benefit
  • Account for the confounders of anaesthesia on haemostasis: hypothermia impairs enzymatic reactions and platelet function; acidosis disrupts the coagulation factor environment; haemodilution reduces factor and platelet concentrations - all components of the lethal triad in major haemorrhage

Summary Table

AspectKey Points
Classical cascadeExtrinsic (TF-FVII) + Intrinsic (contact, FXII) → common pathway (FXa, prothrombin → thrombin → fibrin)
Cell-based modelInitiation (TF cells) → Amplification (platelets) → Propagation (platelet surface)
ThrombinCentral mediator: fibrinogen cleavage, FXIII activation, platelet activation (PAR-1), feedback activation of FV/FVIII/FXI
AnticoagulantsATIII, TFPI, Protein C/S, PGI2/NO
Fibrinolysist-PA → plasmin → fibrin degradation; D-dimers as markers
TEG/ROTEMGlobal viscoelastic assay: R/CT (factors) → K/CFT + alpha (fibrinogen) → MA/MCF (platelets) → LY30/LI30 (fibrinolysis)
Clinical useGoal-directed transfusion in cardiac surgery, trauma, liver Tx, obstetrics
EvidenceCochrane 2026 (35 RCTs): possible mortality reduction, reduced blood product use; very low certainty evidence

Word count: ~1,800 | Sources: Robbins Pathologic Basis of Disease; Harrison's Principles of Internal Medicine 22E; Sabiston Textbook of Surgery; Morgan & Mikhail's Clinical Anesthesiology 7e; Schwartz's Principles of Surgery 11e; Rockwood & Green's Fractures in Adults 10e; Scott-Brown's Otorhinolaryngology Vol.1; Goldman-Cecil Medicine; Kvisselgaard et al. Cochrane Database Syst Rev 2026 [PMID: 42145275]

Convert the above answer in a pdf

Reading File
Running Command

ls /home/daytona/workspace/ 2>/dev/null || mkdir -p /home/daytona/workspace

Running Command

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

Writing File

~/coagulation-teg/build_pdf.py

#!/usr/bin/env python3
"""
Build a well-formatted PDF of the Coagulation Cascade & TEG exam answer.
Uses ReportLab Platypus for rich layout.
"""

import io
import os
import requests
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, Image, KeepTogether, PageBreak
)
from reportlab.platypus.tableofcontents import TableOfContents
from reportlab.lib.colors import HexColor

# ── Output path ────────────────────────────────────────────────────────────────
OUTPUT = "/home/daytona/workspace/coagulation-teg/Coagulation_Cascade_and_TEG_Exam_Answer.pdf"

# ── Colour palette ─────────────────────────────────────────────────────────────
NAVY      = HexColor("#1a2e4a")
TEAL      = HexColor("#0d6e7e")
LIGHT_BG  = HexColor("#f0f6f8")
RULE_COL  = HexColor("#0d6e7e")
TABLE_HDR = HexColor("#1a2e4a")
TABLE_ALT = HexColor("#e8f4f6")
WHITE     = colors.white
BLACK     = colors.black
GREY      = HexColor("#555555")
ORANGE    = HexColor("#c0392b")

# ── Page geometry ──────────────────────────────────────────────────────────────
PAGE_W, PAGE_H = A4
LEFT_M = RIGHT_M = 2.0 * cm
TOP_M  = 2.2 * cm
BOT_M  = 2.2 * cm

# ── Styles ─────────────────────────────────────────────────────────────────────
base = getSampleStyleSheet()

def make_style(name, parent="Normal", **kw):
    return ParagraphStyle(name, parent=base[parent], **kw)

TITLE_STYLE = make_style("MainTitle",
    fontSize=22, textColor=NAVY, spaceAfter=4,
    alignment=TA_CENTER, fontName="Helvetica-Bold", leading=28)

SUBTITLE_STYLE = make_style("SubTitle",
    fontSize=13, textColor=TEAL, spaceAfter=2,
    alignment=TA_CENTER, fontName="Helvetica", leading=18)

META_STYLE = make_style("Meta",
    fontSize=9, textColor=GREY, spaceAfter=14,
    alignment=TA_CENTER, fontName="Helvetica-Oblique")

H1_STYLE = make_style("H1",
    fontSize=14, textColor=WHITE, spaceAfter=6, spaceBefore=14,
    fontName="Helvetica-Bold", leading=20)

H2_STYLE = make_style("H2",
    fontSize=12, textColor=NAVY, spaceAfter=4, spaceBefore=10,
    fontName="Helvetica-Bold", leading=16)

H3_STYLE = make_style("H3",
    fontSize=10.5, textColor=TEAL, spaceAfter=3, spaceBefore=7,
    fontName="Helvetica-Bold", leading=14, leftIndent=0)

BODY_STYLE = make_style("Body",
    fontSize=10, textColor=BLACK, spaceAfter=5, spaceBefore=2,
    fontName="Helvetica", leading=15, alignment=TA_JUSTIFY)

BULLET_STYLE = make_style("Bullet",
    fontSize=10, textColor=BLACK, spaceAfter=3,
    fontName="Helvetica", leading=14, leftIndent=14, bulletIndent=4)

CAPTION_STYLE = make_style("Caption",
    fontSize=8.5, textColor=GREY, spaceAfter=8,
    fontName="Helvetica-Oblique", leading=11, alignment=TA_CENTER)

REF_STYLE = make_style("Ref",
    fontSize=8.5, textColor=GREY, spaceAfter=3,
    fontName="Helvetica-Oblique", leading=12)

TABLE_HDR_STYLE = make_style("TblHdr",
    fontSize=9, textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER)

TABLE_CELL_STYLE = make_style("TblCell",
    fontSize=9, textColor=BLACK, fontName="Helvetica", leading=12, alignment=TA_LEFT)

# ── Helper to download image ───────────────────────────────────────────────────
def fetch_img(url, width_cm=14):
    try:
        r = requests.get(url, timeout=15)
        r.raise_for_status()
        buf = io.BytesIO(r.content)
        img = Image(buf)
        aspect = img.imageHeight / float(img.imageWidth)
        w = width_cm * cm
        img.drawWidth = w
        img.drawHeight = w * aspect
        return img
    except Exception as e:
        print(f"  [warn] Could not fetch image: {url} — {e}")
        return None

# ── Section header with coloured band ─────────────────────────────────────────
def section_header(story, number, title):
    tbl = Table([[Paragraph(f"{number}. {title}", H1_STYLE)]],
                colWidths=[PAGE_W - LEFT_M - RIGHT_M])
    tbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), NAVY),
        ("TOPPADDING", (0,0), (-1,-1), 6),
        ("BOTTOMPADDING", (0,0), (-1,-1), 6),
        ("LEFTPADDING", (0,0), (-1,-1), 10),
        ("RIGHTPADDING", (0,0), (-1,-1), 10),
        ("ROUNDEDCORNERS", [4]),
    ]))
    story.append(Spacer(1, 8))
    story.append(tbl)
    story.append(Spacer(1, 6))

# ── Styled table builder ───────────────────────────────────────────────────────
def build_table(headers, rows, col_widths=None):
    avail = PAGE_W - LEFT_M - RIGHT_M
    if col_widths is None:
        n = len(headers)
        col_widths = [avail / n] * n

    def cell(txt, is_hdr=False):
        s = TABLE_HDR_STYLE if is_hdr else TABLE_CELL_STYLE
        return Paragraph(str(txt), s)

    data = [[cell(h, True) for h in headers]]
    for i, row in enumerate(rows):
        data.append([cell(c) for c in row])

    ts = TableStyle([
        ("BACKGROUND",    (0,0), (-1,0), TABLE_HDR),
        ("TEXTCOLOR",     (0,0), (-1,0), WHITE),
        ("ROWBACKGROUNDS",(0,1), (-1,-1), [WHITE, TABLE_ALT]),
        ("GRID",          (0,0), (-1,-1), 0.5, HexColor("#cccccc")),
        ("TOPPADDING",    (0,0), (-1,-1), 5),
        ("BOTTOMPADDING", (0,0), (-1,-1), 5),
        ("LEFTPADDING",   (0,0), (-1,-1), 7),
        ("RIGHTPADDING",  (0,0), (-1,-1), 7),
        ("VALIGN",        (0,0), (-1,-1), "MIDDLE"),
    ])
    t = Table(data, colWidths=col_widths, repeatRows=1)
    t.setStyle(ts)
    return t

# ── Page callbacks ─────────────────────────────────────────────────────────────
def header_footer(canvas, doc):
    canvas.saveState()
    w, h = A4
    # Header bar
    canvas.setFillColor(NAVY)
    canvas.rect(LEFT_M, h - TOP_M + 0.3*cm, w - LEFT_M - RIGHT_M, 0.35*cm, fill=1, stroke=0)
    canvas.setFont("Helvetica-Bold", 8)
    canvas.setFillColor(WHITE)
    canvas.drawString(LEFT_M + 4, h - TOP_M + 0.42*cm,
                      "Postgraduate Anaesthesia Examination")
    canvas.setFont("Helvetica", 8)
    canvas.drawRightString(w - RIGHT_M - 4, h - TOP_M + 0.42*cm,
                           "Coagulation Cascade & Thromboelastography")
    # Footer
    canvas.setFillColor(GREY)
    canvas.setFont("Helvetica", 8)
    canvas.drawString(LEFT_M, BOT_M - 0.5*cm, "Orris Medical AI  |  July 2026")
    canvas.drawRightString(w - RIGHT_M, BOT_M - 0.5*cm, f"Page {doc.page}")
    canvas.setStrokeColor(RULE_COL)
    canvas.setLineWidth(0.5)
    canvas.line(LEFT_M, BOT_M - 0.3*cm, w - RIGHT_M, BOT_M - 0.3*cm)
    canvas.restoreState()

# ══════════════════════════════════════════════════════════════════════════════
#  BUILD DOCUMENT
# ══════════════════════════════════════════════════════════════════════════════
def build():
    doc = SimpleDocTemplate(
        OUTPUT, pagesize=A4,
        leftMargin=LEFT_M, rightMargin=RIGHT_M,
        topMargin=TOP_M, bottomMargin=BOT_M,
        title="Coagulation Cascade and Thromboelastography",
        author="Orris Medical AI",
        subject="Postgraduate Anaesthesia Examination Answer"
    )

    story = []

    # ── Cover block ────────────────────────────────────────────────────────────
    story.append(Spacer(1, 1.2*cm))
    story.append(Paragraph("Coagulation Cascade and", TITLE_STYLE))
    story.append(Paragraph("Thromboelastography", TITLE_STYLE))
    story.append(Spacer(1, 0.3*cm))
    story.append(HRFlowable(width="100%", thickness=2, color=TEAL, spaceAfter=8))
    story.append(Paragraph("Postgraduate Anaesthesia Examination  |  30 Marks", SUBTITLE_STYLE))
    story.append(Spacer(1, 0.2*cm))
    story.append(Paragraph(
        "Sources: Robbins Pathologic Basis of Disease · Harrison's Principles of Internal Medicine 22E · "
        "Sabiston Textbook of Surgery · Morgan &amp; Mikhail's Clinical Anesthesiology 7e · "
        "Schwartz's Principles of Surgery 11e · Rockwood &amp; Green's Fractures 10e · "
        "Goldman-Cecil Medicine · Cochrane Database Syst Rev 2026 [PMID: 42145275]",
        META_STYLE))
    story.append(HRFlowable(width="100%", thickness=1, color=TEAL, spaceAfter=12))

    # ══ SECTION 1 ══════════════════════════════════════════════════════════════
    section_header(story, 1, "Introduction  (2 marks)")
    story.append(Paragraph(
        "Haemostasis is a tightly regulated physiological process that arrests bleeding while maintaining "
        "vascular patency. It integrates three overlapping phases: <b>primary haemostasis</b> (platelet plug "
        "formation), <b>secondary haemostasis</b> (the coagulation cascade generating fibrin), and "
        "<b>fibrinolysis</b> (clot dissolution). Understanding the cascade and its point-of-care assessment "
        "with thromboelastography (TEG) and rotational thromboelastometry (ROTEM) is fundamental to "
        "perioperative and critical care anaesthetic practice.", BODY_STYLE))

    # ══ SECTION 2 ══════════════════════════════════════════════════════════════
    section_header(story, 2, "The Coagulation Cascade  (12 marks)")

    # 2.1
    story.append(Paragraph("2.1  Classical (Waterfall) Model", H2_STYLE))
    story.append(Paragraph(
        "The classical model, developed in the 1960s, divides coagulation into the <b>extrinsic pathway</b>, "
        "the <b>intrinsic pathway</b>, and a <b>common pathway</b>. The cascade is a series of amplifying "
        "enzymatic reactions leading to deposition of an insoluble fibrin clot. Each step involves an "
        "<b>enzyme</b> (activated coagulation factor), a <b>substrate</b> (inactive proenzyme), and a "
        "<b>cofactor</b> (reaction accelerator), assembled on negatively charged phospholipid surfaces "
        "provided by activated platelets. Calcium is required, binding to gamma-carboxylated glutamic acid "
        "residues on factors II, VII, IX, and X — synthesised using <b>Vitamin K as cofactor</b> and "
        "antagonised by coumarin anticoagulants.", BODY_STYLE))

    # Insert cascade diagram
    img1 = fetch_img(
        "https://cdn.orris.care/cdss_images/39a84f124f8f24fe1ca25f86d1b73b95cac5832ac3fcbb3ef69e33afc7bb51d0.png",
        width_cm=15)
    if img1:
        story.append(Spacer(1, 4))
        story.append(img1)
        story.append(Paragraph(
            "Fig. 1 — Coagulation cascade: laboratory (intrinsic/extrinsic pathways) vs. in vivo "
            "(tissue factor-driven). Red = inactive factors, Blue = active factors, Green = cofactors. "
            "(Robbins Pathologic Basis of Disease)", CAPTION_STYLE))

    story.append(Paragraph("Extrinsic pathway (assessed by PT/INR):", H3_STYLE))
    for b in [
        "Tissue factor (TF), a subendothelial transmembrane glycoprotein constitutively expressed on fibroblasts and vascular smooth muscle cells, is exposed by vascular injury.",
        "TF binds plasma FVII, activating it to FVIIa — the <b>TF:FVIIa extrinsic tenase complex</b>.",
        "TF:FVIIa activates FX → FXa and FIX → FIXa.",
        "The PT assay assesses factors VII, X, V, II (prothrombin), and fibrinogen."
    ]:
        story.append(Paragraph(f"• {b}", BULLET_STYLE))

    story.append(Paragraph("Intrinsic pathway (assessed by aPTT):", H3_STYLE))
    for b in [
        "Initiated in vitro by negatively charged surfaces activating FXII → FXIIa (Hageman factor).",
        "FXIIa activates FXI → FXIa → FIX → FIXa.",
        "FIXa + FVIIIa (intrinsic tenase complex on platelet surface) activates FX.",
        "The aPTT assesses factors XII, XI, IX, VIII, X, V, II, and fibrinogen."
    ]:
        story.append(Paragraph(f"• {b}", BULLET_STYLE))

    story.append(Paragraph("Common pathway:", H3_STYLE))
    for b in [
        "FXa + FVa (prothrombinase complex, on platelet membrane + Ca²⁺) converts prothrombin (FII) → thrombin (FIIa).",
        "Thrombin cleaves fibrinogen → fibrin monomers → polymerised insoluble fibrin.",
        "Thrombin activates FXIII → FXIIIa, a transglutaminase that covalently cross-links fibrin (clot stabilisation).",
        "Thrombin activates FV, FVIII, FXI (positive feedback amplification loops) and platelets via PAR-1.",
    ]:
        story.append(Paragraph(f"• {b}", BULLET_STYLE))

    story.append(Paragraph(
        "<b>Limitation of the classical model:</b> FXII deficiency prolongs aPTT but does not cause bleeding; "
        "FVIII/FIX (haemophilias A/B) deficiencies cause severe bleeding despite each affecting only one pathway. "
        "This paradox is resolved by the cell-based model. <i>(Sabiston Textbook of Surgery; Harrison's 22E)</i>",
        BODY_STYLE))

    # 2.2
    story.append(Paragraph("2.2  Cell-Based Model of Coagulation (Current Paradigm)", H2_STYLE))
    story.append(Paragraph(
        "The cell-based model, now the accepted physiological framework, emphasises overlapping interactions "
        "between coagulation proteins and specific cell membranes. It proceeds in three phases:",
        BODY_STYLE))

    phases = [
        ("Phase 1 — Initiation\n(TF-bearing cells)",
         "Vascular injury exposes subendothelial TF to plasma FVII, creating TF:FVIIa. This activates small amounts "
         "of FX→FXa and FIX→FIXa. FXa + FVa (prothrombinase complex) generates trace thrombin — the trigger for "
         "amplification. TFPI rapidly inhibits TF:FVIIa:FXa, limiting this phase."),
        ("Phase 2 — Amplification\n(Platelet surface)",
         "Trace thrombin activates platelets (PAR-1/PAR-4), FV→FVa, FVIII→FVIIIa, and releases vWF. Platelets "
         "adhere via GPIb to vWF and via GPIa/IIa or GPVI to collagen. Platelet outer membrane becomes net "
         "negatively charged — the assembly platform for coagulation."),
        ("Phase 3 — Propagation\n(Activated platelet surface)",
         "Intrinsic tenase (FIXa + FVIIIa) and prothrombinase (FXa + FVa) on platelets generate the thrombin burst "
         "→ cleave fibrinogen → fibrin; activate FXIII → cross-linked fibrin; activate TAFI (thrombin activatable "
         "fibrinolysis inhibitor); sustain platelet and factor activation."),
    ]
    tbl_data = [[
        Paragraph(p[0].replace("\n","<br/>"), ParagraphStyle("ph_h", fontName="Helvetica-Bold",
            fontSize=9, textColor=WHITE, leading=12)),
        Paragraph(p[1], TABLE_CELL_STYLE)
    ] for p in phases]
    phase_table = Table(tbl_data, colWidths=[4.2*cm, 12.8*cm])
    phase_table.setStyle(TableStyle([
        ("BACKGROUND",   (0,0), (0,-1), TEAL),
        ("BACKGROUND",   (1,0), (1,-1), WHITE),
        ("ROWBACKGROUNDS",(1,0),(1,-1),[WHITE, TABLE_ALT, WHITE]),
        ("GRID",         (0,0), (-1,-1), 0.5, HexColor("#cccccc")),
        ("VALIGN",       (0,0), (-1,-1), "TOP"),
        ("TOPPADDING",   (0,0), (-1,-1), 7),
        ("BOTTOMPADDING",(0,0), (-1,-1), 7),
        ("LEFTPADDING",  (0,0), (-1,-1), 8),
        ("RIGHTPADDING", (0,0), (-1,-1), 8),
    ]))
    story.append(phase_table)
    story.append(Spacer(1, 6))
    story.append(Paragraph(
        "<i>(Schwartz's Principles of Surgery 11e; Rockwood &amp; Green's Fractures in Adults 10e; "
        "Sabiston Textbook of Surgery)</i>", REF_STYLE))

    # 2.3 Anticoagulant mechanisms
    story.append(Paragraph("2.3  Endogenous Anticoagulant Mechanisms", H2_STYLE))
    story.append(Paragraph(
        "Four major endogenous anticoagulant systems prevent unbounded clot propagation:", BODY_STYLE))

    ac_headers = ["Inhibitor", "Mechanism"]
    ac_rows = [
        ["Antithrombin III (ATIII)",
         "Serine protease inhibitor inactivating thrombin, FXa, FIXa, FXIa, FXIIa. Heparin binds ATIII, "
         "inducing a conformational change that accelerates activity ~1000-fold. Physiologically potentiated "
         "by heparan sulphate on endothelial surfaces."],
        ["Tissue Factor Pathway\nInhibitor (TFPI)",
         "Directly inhibits the TF:FVIIa:FXa complex, limiting the initiation phase. Produced by endothelium."],
        ["Protein C / Protein S",
         "Thrombin bound to thrombomodulin (on intact endothelium) activates Protein C. Activated Protein C "
         "(APC) + Protein S (cofactor) inactivate FVa and FVIIIa, shutting down propagation."],
        ["Prostacyclin (PGI₂)\n& Nitric Oxide (NO)",
         "Released by intact endothelium; inhibit platelet aggregation and cause vasodilatation."],
    ]
    story.append(build_table(ac_headers, ac_rows, col_widths=[5*cm, 12*cm]))
    story.append(Spacer(1, 4))
    story.append(Paragraph(
        "<i>(Harrison's Principles of Internal Medicine 22E; Goldman-Cecil Medicine)</i>", REF_STYLE))

    # 2.4 Fibrinolysis
    story.append(Paragraph("2.4  Fibrinolysis", H2_STYLE))
    for b in [
        "t-PA (tissue plasminogen activator), synthesised by endothelium and most active when bound to fibrin, converts plasminogen → <b>plasmin</b>.",
        "Plasmin degrades fibrin into fibrin degradation products (FDPs), notably <b>D-dimers</b> — a clinically useful marker of thrombus formation and lysis (DVT/PE screening, DIC diagnosis).",
        "<b>Alpha-2-antiplasmin</b> rapidly inactivates free circulating plasmin.",
        "<b>PAI-1</b> (plasminogen activator inhibitor-1) inhibits t-PA and uPA. In DIC, elevated PAI-1 suppresses normal fibrinolysis, worsening microvascular thrombosis.",
        "FXII-dependent pathway also activates plasminogen (possibly explaining the paradox of FXII deficiency and thrombosis).",
    ]:
        story.append(Paragraph(f"• {b}", BULLET_STYLE))
    story.append(Paragraph(
        "<i>(Robbins Pathologic Basis of Disease; Sabiston Textbook of Surgery)</i>", REF_STYLE))

    # ══ SECTION 3 ══════════════════════════════════════════════════════════════
    section_header(story, 3, "Thromboelastography (TEG) and ROTEM  (12 marks)")

    # 3.1 Principle
    story.append(Paragraph("3.1  Principle and Technology", H2_STYLE))
    story.append(Paragraph(
        "TEG (Haemonetics) and ROTEM (Werfen) are <b>point-of-care viscoelastic haemostatic assays (VHAs)</b> "
        "that measure the mechanical properties of whole blood as it clots. Unlike standard laboratory tests "
        "(PT, aPTT, platelet count), which assess individual components in plasma under static conditions, "
        "VHAs assess the <b>entire haemostatic process</b> — coagulation factor activity, platelet function, "
        "fibrinogen contribution, clot strength, and fibrinolysis — simultaneously and in real time.",
        BODY_STYLE))
    story.append(Paragraph(
        "In TEG, whole blood is placed in a heated cuvette (37 °C). A pin is suspended in the blood on a "
        "torsion wire; the cuvette oscillates. As a clot forms and strengthens, increasing mechanical "
        "resistance is transmitted to the pin and plotted as the characteristic thromboelastogram. In ROTEM, "
        "the cuvette is stationary and the pin rotates — functionally equivalent but numerically distinct "
        "and <b>not interchangeable</b>.",
        BODY_STYLE))
    story.append(Paragraph(
        "<i>(Morgan &amp; Mikhail's Clinical Anesthesiology 7e; Scott-Brown's Otorhinolaryngology Vol.1)</i>",
        REF_STYLE))

    # 3.2 Parameters
    story.append(Paragraph("3.2  TEG Trace Parameters and Clinical Interpretation", H2_STYLE))

    # Insert TEG diagram
    img2 = fetch_img(
        "https://cdn.orris.care/cdss_images/0b1425cf1a93207225bb92d1d44f5ea59473ea214e1210004b631d11c938aa87.png",
        width_cm=13)
    if img2:
        story.append(img2)
        story.append(Paragraph(
            "Fig. 2 — Standard TEG trace. Enzymatic phase (R time) → fibrinogen-mediated clot formation "
            "(K time, alpha angle) → platelet-dependent clot strength (MA) → fibrinolysis (LY30, EPL). "
            "(Morgan &amp; Mikhail's Clinical Anesthesiology 7e)", CAPTION_STYLE))

    teg_headers = ["Parameter", "Definition", "Normal Range", "Clinical Significance"]
    teg_rows = [
        ["R time\n(Reaction time)",
         "Time from sample placement to first clot detection (2 mm amplitude)",
         "5–10 min",
         "Prolonged: factor deficiency, anticoagulants (heparin, warfarin, DOACs). Shortened: hypercoagulable state."],
        ["K time\n(Kinetics)",
         "Time from R-time to 20 mm amplitude; rate of clot formation",
         "1–3 min",
         "Prolonged: fibrinogen deficiency, thrombocytopaenia. Guides FFP/cryoprecipitate."],
        ["Alpha angle (α)",
         "Angle of tangent to the curve at 2 mm amplitude; rate of fibrin accumulation",
         "53–72°",
         "Reduced: fibrinogen deficiency. Increased: hypercoagulability. Guides cryoprecipitate/fibrinogen concentrate."],
        ["Maximum\nAmplitude (MA)",
         "Greatest vertical width of trace; reflects clot strength",
         "50–70 mm",
         "Platelets contribute ~80%, fibrinogen ~20% of clot strength. Reduced: platelet dysfunction/thrombocytopaenia → platelet transfusion."],
        ["LY30\n(Lysis at 30 min)",
         "% reduction in amplitude 30 min after MA",
         "<7.5%",
         "Elevated (>7.5–8%): hyperfibrinolysis → tranexamic acid or aminocaproic acid."],
        ["EPL\n(Estimated %\nLysis)",
         "Predicted lysis before 30 min",
         "<15%",
         "Similar clinical significance to LY30; earlier signal."],
        ["CI\n(Coagulation\nIndex)",
         "Composite algorithmic score",
         "−3 to +3",
         "<−3: hypocoagulable; >+3: hypercoagulable."],
    ]
    avail = PAGE_W - LEFT_M - RIGHT_M
    story.append(build_table(teg_headers, teg_rows,
        col_widths=[2.8*cm, 4.2*cm, 2.4*cm, avail - 2.8*cm - 4.2*cm - 2.4*cm]))
    story.append(Spacer(1, 4))

    # ROTEM equivalents
    story.append(Paragraph("ROTEM Equivalent Parameters:", H3_STYLE))
    rotem_headers = ["TEG Parameter", "ROTEM Equivalent", "ROTEM Activator Used"]
    rotem_rows = [
        ["R time",  "CT (Clotting Time)",           "EXTEM / INTEM"],
        ["K time",  "CFT (Clot Formation Time)",     "EXTEM / INTEM"],
        ["Alpha angle", "Alpha angle (α)",           "EXTEM / FIBTEM"],
        ["MA",      "MCF (Maximum Clot Firmness)",   "EXTEM / INTEM / FIBTEM"],
        ["LY30",    "LI30 / ML (Maximum Lysis)",     "EXTEM"],
    ]
    story.append(build_table(rotem_headers, rotem_rows))
    story.append(Spacer(1, 4))
    story.append(Paragraph(
        "ROTEM uses specific reagents: <b>EXTEM</b> (tissue factor — extrinsic pathway), "
        "<b>INTEM</b> (ellagic acid — intrinsic pathway), <b>FIBTEM</b> (extrinsic + cytochalasin D platelet "
        "inhibitor — isolates fibrinogen contribution), <b>APTEM</b> (extrinsic + aprotinin — detects "
        "fibrinolysis by comparison).", BODY_STYLE))

    # 3.3 Clinical Use
    story.append(Paragraph("3.3  TEG/ROTEM-Guided Transfusion Algorithms", H2_STYLE))
    story.append(Paragraph(
        "The greatest clinical utility of VHAs is in <b>goal-directed transfusion therapy</b>. "
        "VHAs free the anaesthetist from reliance solely on the empiric 1:1:1 "
        "(FFP:platelets:pRBC) massive transfusion protocol, enabling targeted product use. "
        "Key clinical contexts include:", BODY_STYLE))

    for b in [
        "<b>Major trauma and haemorrhage</b> — identifying trauma-induced coagulopathy (TIC), characterised by early hyperfibrinolysis, dilution, hypothermia, and acidosis (the 'lethal triad').",
        "<b>Cardiac surgery</b> — distinguishing surgical bleeding from coagulopathic bleeding; strongest evidence base.",
        "<b>Liver transplantation</b> — monitoring complex coagulopathy including hyperfibrinolysis.",
        "<b>Obstetric haemorrhage</b> — real-time guidance for clotting factor replacement.",
        "<b>Neurosurgery</b> — detecting hypercoagulability and guiding anticoagulation.",
    ]:
        story.append(Paragraph(f"• {b}", BULLET_STYLE))

    story.append(Paragraph("<b>Algorithm summary:</b>", H3_STYLE))
    algo_headers = ["VHA Finding", "Likely Defect", "Recommended Intervention"]
    algo_rows = [
        ["Prolonged R time / CT", "Coagulation factor deficiency", "FFP or factor concentrates"],
        ["Prolonged K time / CFT", "Fibrinogen deficiency", "Cryoprecipitate or fibrinogen concentrate"],
        ["Reduced alpha angle", "Fibrinogen deficiency", "Cryoprecipitate or fibrinogen concentrate"],
        ["Reduced MA / MCF", "Platelet dysfunction / thrombocytopaenia", "Platelet transfusion"],
        ["Elevated LY30 / LI30", "Hyperfibrinolysis", "Tranexamic acid or aminocaproic acid"],
        ["Elevated CI (>+3)", "Hypercoagulable state", "Anticoagulation (clinical context dependent)"],
    ]
    avail = PAGE_W - LEFT_M - RIGHT_M
    story.append(build_table(algo_headers, algo_rows,
        col_widths=[4.5*cm, 5.5*cm, avail - 4.5*cm - 5.5*cm]))

    # 3.4 Advantages
    story.append(Paragraph("3.4  Advantages over Standard Coagulation Tests", H2_STYLE))
    adv_headers = ["Feature", "PT / aPTT / CBC", "TEG / ROTEM"]
    adv_rows = [
        ["Sample",              "Plasma only",      "Whole blood (includes platelets and RBCs)"],
        ["Condition",           "Static",           "Dynamic"],
        ["Turnaround time",     "45–90 min",        "20–30 min (functional result)"],
        ["Fibrinolysis",        "Not detected",     "Yes (LY30 / LI30)"],
        ["Platelet function",   "No",               "Yes (via MA / MCF)"],
        ["Hypercoagulability",  "No",               "Yes (CI, shortened R time)"],
        ["Point-of-care use",   "Limited",          "Yes"],
    ]
    story.append(build_table(adv_headers, adv_rows,
        col_widths=[4.5*cm, 4.5*cm, PAGE_W - LEFT_M - RIGHT_M - 9*cm]))

    # 3.5 Limitations
    story.append(Paragraph("3.5  Limitations of TEG/ROTEM", H2_STYLE))
    for b in [
        "Temperature sensitivity: samples must be maintained at 37 °C; hypothermia artefacts affect results.",
        "Inter-operator variability; time-sensitive sample processing required.",
        "Do not assess <b>endothelial function</b> or the vascular component of haemostasis.",
        "Weak sensitivity for antiplatelet drugs (aspirin, P2Y12 inhibitors) — specific platelet mapping reagents required.",
        "ROTEM and TEG values are <b>not interchangeable</b> and use different reference ranges.",
        "Evidence base predominantly from cardiac surgery; emerging but variable certainty in trauma and obstetrics.",
        "Cost and availability in lower-resource settings.",
    ]:
        story.append(Paragraph(f"• {b}", BULLET_STYLE))

    # ══ SECTION 4 ══════════════════════════════════════════════════════════════
    section_header(story, 4, "Current Evidence  (4 marks)")
    story.append(Paragraph(
        "A <b>2026 Cochrane systematic review</b> (Kvisselgaard et al., 35 RCTs, n=3,096, predominantly "
        "cardiac surgery patients) found TEG/ROTEM-guided transfusion compared with standard care:",
        BODY_STYLE))
    for b in [
        "<b>May reduce all-cause mortality</b> (RR 0.76, 95% CI 0.63–0.92; 19 trials, 1865 participants; I²=0%; very low certainty evidence).",
        "<b>May reduce bleeding volume</b> (SMD −0.31, 95% CI −0.51 to −0.11; 19 trials; I²=72%; very low certainty evidence).",
        "<b>May reduce FFP and platelet transfusion use</b> and surgical re-exploration.",
        "<b>No significant reduction in packed red blood cell use</b> (RR 0.94, 95% CI 0.87–1.01; I²=91%).",
        "Overall: <b>very low certainty evidence</b> across all outcomes due to heterogeneity, risk of bias, and indirectness.",
    ]:
        story.append(Paragraph(f"• {b}", BULLET_STYLE))
    story.append(Paragraph(
        "This is consistent with earlier systematic reviews published in Anaesthesia (2017;72:519–531), "
        "cited in Morgan &amp; Mikhail and Goldman-Cecil Medicine. Evidence is <b>strongest for elective "
        "cardiac surgery</b>; emerging data exist for trauma, liver transplantation, and obstetrics.",
        BODY_STYLE))
    story.append(Paragraph(
        "<i>Kvisselgaard AD et al. Cochrane Database Syst Rev. 2026 May 18. doi:10.1002/14651858.CD007871.pub4 "
        "[PMID: 42145275]</i>", REF_STYLE))

    # ══ SECTION 5 ══════════════════════════════════════════════════════════════
    section_header(story, 5, "Anaesthetic Relevance — Practical Summary")
    story.append(Paragraph("The anaesthetist must:", BODY_STYLE))
    for b in [
        "Understand the <b>cell-based model</b> rather than the classical cascade alone, to correctly interpret clinical factor deficiencies and guide targeted replacement.",
        "Recognise the <b>limitations of PT/aPTT</b>: normal values do not exclude coagulopathy, and they do not detect fibrinolysis or platelet dysfunction.",
        "Use TEG/ROTEM as <b>decision support tools within a goal-directed algorithm</b>, not as isolated tests.",
        "Apply <b>tranexamic acid early</b> in high-risk haemorrhage (CRASH-2/WOMAN trial evidence), with VHA-confirmed hyperfibrinolysis (LY30 >7.5%) as additional guidance.",
        "Account for the <b>lethal triad</b> (hypothermia, acidosis, coagulopathy) in major haemorrhage: hypothermia impairs enzymatic reactions and platelet function; acidosis disrupts the coagulation factor environment; haemodilution reduces factor and platelet concentrations.",
    ]:
        story.append(Paragraph(f"• {b}", BULLET_STYLE))

    # ══ SUMMARY TABLE ══════════════════════════════════════════════════════════
    story.append(Spacer(1, 10))
    story.append(HRFlowable(width="100%", thickness=1.5, color=TEAL))
    story.append(Spacer(1, 6))
    story.append(Paragraph("Summary Table", H2_STYLE))
    sum_headers = ["Aspect", "Key Points"]
    sum_rows = [
        ["Classical cascade",
         "Extrinsic (TF-FVII) + Intrinsic (contact, FXII) → common pathway (FXa, prothrombin → thrombin → fibrin)"],
        ["Cell-based model",
         "Initiation (TF cells) → Amplification (platelets) → Propagation (platelet surface)"],
        ["Thrombin",
         "Central mediator: fibrinogen cleavage, FXIII activation, platelet activation (PAR-1), feedback activation of FV/FVIII/FXI"],
        ["Endogenous anticoagulants",
         "ATIII (+ heparin), TFPI (inhibits TF:FVIIa:FXa), Protein C/S (inhibits FVa/FVIIIa), PGI₂/NO"],
        ["Fibrinolysis",
         "t-PA → plasmin → fibrin degradation; D-dimers as markers; controlled by alpha-2-antiplasmin and PAI-1"],
        ["TEG/ROTEM principle",
         "Global viscoelastic assay of whole blood: R/CT (factors) → K/CFT + alpha angle (fibrinogen) → MA/MCF (platelets) → LY30/LI30 (fibrinolysis)"],
        ["Clinical use",
         "Goal-directed transfusion in cardiac surgery, trauma, liver Tx, obstetrics; algorithm-guided product choice"],
        ["Current evidence",
         "Cochrane 2026 (35 RCTs): possible mortality reduction RR 0.76, reduced FFP/platelet use; very low certainty evidence overall"],
    ]
    story.append(build_table(sum_headers, sum_rows, col_widths=[4.5*cm, PAGE_W - LEFT_M - RIGHT_M - 4.5*cm]))

    # ══ REFERENCES ══════════════════════════════════════════════════════════════
    story.append(Spacer(1, 12))
    story.append(HRFlowable(width="100%", thickness=1, color=GREY))
    story.append(Spacer(1, 6))
    story.append(Paragraph("Key References", H2_STYLE))
    refs = [
        "Kumar V, Abbas AK, Aster JC. <i>Robbins and Cotran Pathologic Basis of Disease</i>, 10th ed. Elsevier, 2020.",
        "Fauci AS et al. <i>Harrison's Principles of Internal Medicine</i>, 22nd ed. McGraw-Hill, 2025.",
        "Townsend CM et al. <i>Sabiston Textbook of Surgery</i>, 21st ed. Elsevier, 2022.",
        "Morgan GE, Mikhail MS. <i>Clinical Anesthesiology</i>, 7th ed. McGraw-Hill, 2022.",
        "Brunicardi FC et al. <i>Schwartz's Principles of Surgery</i>, 11th ed. McGraw-Hill, 2019.",
        "Bucholz RW et al. <i>Rockwood and Green's Fractures in Adults</i>, 10th ed. Wolters Kluwer, 2025.",
        "Goldman L, Cooney KA. <i>Goldman-Cecil Medicine</i>, 27th ed. Elsevier, 2024.",
        "Kvisselgaard AD, Wolthers SA, Wikkelso AJ, et al. Thromboelastography (TEG) or thromboelastometry (ROTEM) to monitor haemostatic treatment versus usual care in adults or children with bleeding. <i>Cochrane Database Syst Rev.</i> 2026 May 18. doi:10.1002/14651858.CD007871.pub4. PMID: 42145275.",
    ]
    for i, r in enumerate(refs, 1):
        story.append(Paragraph(f"{i}. {r}", REF_STYLE))

    # ── Build PDF ──────────────────────────────────────────────────────────────
    doc.build(story, onFirstPage=header_footer, onLaterPages=header_footer)
    print(f"PDF saved to: {OUTPUT}")


if __name__ == "__main__":
    build()
Running Command

cd /home/daytona/workspace/coagulation-teg && python3 build_pdf.py 2>&1

Running Command

ls -lh /home/daytona/workspace/coagulation-teg/Coagulation_Cascade_and_TEG_Exam_Answer.pdf

Your PDF is ready (827 KB). Download it here:

Coagulation Cascade and TEG Exam Answer

PDF Document · PDF

What's included in the PDF:
  • Navy header and footer on every page with page numbers
  • Colour-coded section banners for each of the 5 sections
  • Both textbook diagrams embedded (coagulation cascade figure + annotated TEG trace)
  • All formatted tables: TEG/ROTEM parameters, ROTEM equivalents, anticoagulant mechanisms, goal-directed algorithm, advantages vs. standard tests, and summary table
  • Cell-based model displayed as a highlighted three-phase table
  • Full reference list with Cochrane 2026 citation (PMID: 42145275)
  • Optimised for A4 printing

Create a quick reference laminated TEG/ROTEM interpretation card for theatre use

Running Command

ls /home/daytona/workspace/coagulation-teg/

Writing File

~/coagulation-teg/build_card.py

#!/usr/bin/env python3
"""
TEG / ROTEM Quick-Reference Laminated Card for Theatre
Two-sided A5 card (landscape) — both sides on one A4 sheet (print, fold, laminate)
Side A: TEG parameters + ROTEM equivalents + trace diagram
Side B: Goal-directed algorithm + lethal triad + drug effects
"""

import io, requests
from reportlab.lib.pagesizes import A4, landscape
from reportlab.lib.units import cm, mm
from reportlab.lib.colors import HexColor, white, black
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT
from reportlab.platypus import (
    SimpleDocTemplate, Table, TableStyle, Paragraph,
    Spacer, HRFlowable, Image, KeepTogether
)

OUTPUT = "/home/daytona/workspace/coagulation-teg/TEG_ROTEM_Theatre_Card.pdf"

# ── Palette ────────────────────────────────────────────────────────────────────
NAVY    = HexColor("#1a2e4a")
TEAL    = HexColor("#0d6e7e")
TEAL_LT = HexColor("#e0f2f5")
GREEN   = HexColor("#1a6b3c")
GREEN_LT= HexColor("#d4edda")
RED     = HexColor("#8b1a1a")
RED_LT  = HexColor("#fde8e8")
AMBER   = HexColor("#7a4f00")
AMBER_LT= HexColor("#fff3cd")
PURPLE  = HexColor("#4a1a6b")
PURPLE_LT=HexColor("#ede0f7")
GREY    = HexColor("#444444")
LGREY   = HexColor("#f5f5f5")
WHITE   = white
MID     = HexColor("#cccccc")

# ── Card geometry (A4 landscape = two A5 landscape panels) ─────────────────────
PAGE_W, PAGE_H = landscape(A4)   # 841 x 595 pt
CARD_W = PAGE_W / 2 - 10        # each panel
MARGIN = 0.4 * cm

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

CARD_TITLE = S("CT", fontName="Helvetica-Bold", fontSize=11,
               textColor=WHITE, alignment=TA_CENTER, leading=14)
SECTION    = S("SC", fontName="Helvetica-Bold", fontSize=8.5,
               textColor=WHITE, alignment=TA_CENTER, leading=11)
HDR        = S("HD", fontName="Helvetica-Bold", fontSize=7.5,
               textColor=WHITE, alignment=TA_CENTER, leading=10)
CELL       = S("CL", fontName="Helvetica", fontSize=7.5,
               textColor=black, alignment=TA_LEFT, leading=10)
CELL_C     = S("CC", fontName="Helvetica", fontSize=7.5,
               textColor=black, alignment=TA_CENTER, leading=10)
CELL_B     = S("CB", fontName="Helvetica-Bold", fontSize=7.5,
               textColor=black, alignment=TA_LEFT, leading=10)
CELL_BC    = S("CBC", fontName="Helvetica-Bold", fontSize=7.5,
               textColor=black, alignment=TA_CENTER, leading=10)
SMALL      = S("SM", fontName="Helvetica", fontSize=6.5,
               textColor=GREY, alignment=TA_CENTER, leading=8)
SMALL_B    = S("SMB", fontName="Helvetica-Bold", fontSize=6.5,
               textColor=GREY, alignment=TA_LEFT, leading=8)
FOOT       = S("FT", fontName="Helvetica-Oblique", fontSize=6,
               textColor=GREY, alignment=TA_CENTER, leading=8)

def p(txt, style): return Paragraph(txt, style)
def sp(h=2):       return Spacer(1, h)

def fetch_img(url, w_cm, max_h_cm=None):
    try:
        r = requests.get(url, timeout=12)
        r.raise_for_status()
        buf = io.BytesIO(r.content)
        img = Image(buf)
        aspect = img.imageHeight / float(img.imageWidth)
        w = w_cm * cm
        h = w * aspect
        if max_h_cm and h > max_h_cm * cm:
            h = max_h_cm * cm
            w = h / aspect
        img.drawWidth = w
        img.drawHeight = h
        return img
    except Exception as e:
        print(f"  [warn] img fetch failed: {e}")
        return None

# ── Generic section banner ──────────────────────────────────────────────────────
def banner(txt, color=NAVY, w=None):
    cw = w or CARD_W
    t = Table([[p(txt, SECTION)]], colWidths=[cw])
    t.setStyle(TableStyle([
        ("BACKGROUND",   (0,0),(-1,-1), color),
        ("TOPPADDING",   (0,0),(-1,-1), 3),
        ("BOTTOMPADDING",(0,0),(-1,-1), 3),
        ("LEFTPADDING",  (0,0),(-1,-1), 4),
        ("RIGHTPADDING", (0,0),(-1,-1), 4),
    ]))
    return t

# ══════════════════════════════════════════════════════════════════════════════
#  SIDE A — Parameters + Trace + ROTEM equivalents
# ══════════════════════════════════════════════════════════════════════════════
def build_side_a():
    elems = []
    CW = CARD_W

    # ── Title bar ──────────────────────────────────────────────────────────────
    title_tbl = Table([[p("TEG / ROTEM  QUICK REFERENCE", CARD_TITLE)]], colWidths=[CW])
    title_tbl.setStyle(TableStyle([
        ("BACKGROUND",   (0,0),(-1,-1), NAVY),
        ("TOPPADDING",   (0,0),(-1,-1), 5),
        ("BOTTOMPADDING",(0,0),(-1,-1), 5),
        ("LEFTPADDING",  (0,0),(-1,-1), 6),
        ("RIGHTPADDING", (0,0),(-1,-1), 6),
    ]))
    elems.append(title_tbl)
    elems.append(sp(2))

    # ── TEG trace image ────────────────────────────────────────────────────────
    img = fetch_img(
        "https://cdn.orris.care/cdss_images/0b1425cf1a93207225bb92d1d44f5ea59473ea214e1210004b631d11c938aa87.png",
        w_cm=9.5, max_h_cm=3.8)
    if img:
        img_tbl = Table([[img]], colWidths=[CW])
        img_tbl.setStyle(TableStyle([("ALIGN",(0,0),(-1,-1),"CENTER"),
                                      ("VALIGN",(0,0),(-1,-1),"MIDDLE")]))
        elems.append(img_tbl)
        elems.append(p("TEG trace — R time · K time · α angle · MA · LY30", SMALL))
    elems.append(sp(3))

    # ── TEG Parameters table ───────────────────────────────────────────────────
    elems.append(banner("TEG PARAMETERS", TEAL))
    elems.append(sp(1))

    hdr = [p("Parameter", HDR), p("Definition", HDR),
           p("Normal", HDR), p("↑ / ↓ Meaning", HDR)]
    rows = [hdr,
        [p("R time", CELL_B), p("Time to first clot (2 mm amplitude)", CELL),
         p("5–10 min", CELL_C), p("↑ Factor deficiency / anticoagulants\n↓ Hypercoagulable", CELL)],
        [p("K time", CELL_B), p("Time to 20 mm amplitude", CELL),
         p("1–3 min", CELL_C), p("↑ Low fibrinogen / platelets", CELL)],
        [p("α angle", CELL_B), p("Rate of fibrin accumulation", CELL),
         p("53–72°", CELL_C), p("↓ Fibrinogen deficiency\n↑ Hypercoagulable", CELL)],
        [p("MA", CELL_B), p("Max clot strength\n(~80% platelets, ~20% fibrinogen)", CELL),
         p("50–70 mm", CELL_C), p("↓ Platelet dysfunction / low count", CELL)],
        [p("LY30", CELL_B), p("% amplitude loss at 30 min", CELL),
         p("<7.5%", CELL_C), p("↑ >7.5%: Hyperfibrinolysis", CELL)],
        [p("EPL", CELL_B), p("Estimated % lysis (earlier signal)", CELL),
         p("<15%", CELL_C), p("↑ Fibrinolysis (acts before LY30)", CELL)],
        [p("CI", CELL_B), p("Composite coagulation index", CELL),
         p("−3 to +3", CELL_C), p("<−3 hypocoag · >+3 hypercoag", CELL)],
    ]
    c1,c2,c3,c4 = 1.5*cm, 4.0*cm, 1.6*cm, CW-1.5*cm-4.0*cm-1.6*cm
    teg_t = Table(rows, colWidths=[c1, c2, c3, c4], repeatRows=1)
    teg_t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,0), TEAL),
        ("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, TEAL_LT]),
        ("GRID",          (0,0),(-1,-1), 0.4, MID),
        ("TOPPADDING",    (0,0),(-1,-1), 3),
        ("BOTTOMPADDING", (0,0),(-1,-1), 3),
        ("LEFTPADDING",   (0,0),(-1,-1), 4),
        ("RIGHTPADDING",  (0,0),(-1,-1), 4),
        ("VALIGN",        (0,0),(-1,-1), "MIDDLE"),
    ]))
    elems.append(teg_t)
    elems.append(sp(3))

    # ── ROTEM equivalents ──────────────────────────────────────────────────────
    elems.append(banner("ROTEM EQUIVALENTS  &  REAGENTS", NAVY))
    elems.append(sp(1))
    r_hdr = [p("TEG", HDR), p("ROTEM", HDR), p("Reagent", HDR), p("Pathway Tested", HDR)]
    r_rows = [r_hdr,
        [p("R time", CELL_B), p("CT", CELL_BC), p("EXTEM / INTEM", CELL), p("Extrinsic / Intrinsic factors", CELL)],
        [p("K time", CELL_B), p("CFT", CELL_BC), p("EXTEM / INTEM", CELL), p("Fibrinogen + platelets (kinetics)", CELL)],
        [p("α angle", CELL_B), p("α angle", CELL_BC), p("EXTEM / FIBTEM", CELL), p("Fibrinogen contribution", CELL)],
        [p("MA", CELL_B), p("MCF", CELL_BC), p("EXTEM / INTEM / FIBTEM", CELL), p("Clot strength (plts + fibrinogen)", CELL)],
        [p("LY30", CELL_B), p("LI30 / ML", CELL_BC), p("EXTEM ± APTEM", CELL), p("Fibrinolysis (APTEM confirms)", CELL)],
    ]
    ca, cb, cc, cd = 1.5*cm, 1.5*cm, 3.2*cm, CW - 1.5*cm - 1.5*cm - 3.2*cm
    rotem_t = Table(r_rows, colWidths=[ca, cb, cc, cd], repeatRows=1)
    rotem_t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,0), NAVY),
        ("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, LGREY]),
        ("GRID",          (0,0),(-1,-1), 0.4, MID),
        ("TOPPADDING",    (0,0),(-1,-1), 3),
        ("BOTTOMPADDING", (0,0),(-1,-1), 3),
        ("LEFTPADDING",   (0,0),(-1,-1), 4),
        ("RIGHTPADDING",  (0,0),(-1,-1), 4),
        ("VALIGN",        (0,0),(-1,-1), "MIDDLE"),
    ]))
    elems.append(rotem_t)
    elems.append(sp(3))

    # ── ROTEM reagent key ──────────────────────────────────────────────────────
    reagent_data = [
        [p("EXTEM", S("x", fontName="Helvetica-Bold", fontSize=7, textColor=RED, alignment=TA_CENTER)),
         p("Tissue factor → extrinsic pathway", SMALL),
         p("INTEM", S("x", fontName="Helvetica-Bold", fontSize=7, textColor=TEAL, alignment=TA_CENTER)),
         p("Ellagic acid → intrinsic pathway", SMALL)],
        [p("FIBTEM", S("x", fontName="Helvetica-Bold", fontSize=7, textColor=GREEN, alignment=TA_CENTER)),
         p("EXTEM + cytochalasin D (platelet inhibitor) → fibrinogen only", SMALL),
         p("APTEM", S("x", fontName="Helvetica-Bold", fontSize=7, textColor=AMBER, alignment=TA_CENTER)),
         p("EXTEM + aprotinin → confirm fibrinolysis", SMALL)],
    ]
    rkey = Table(reagent_data, colWidths=[1.3*cm, (CW/2-1.3*cm), 1.3*cm, (CW/2-1.3*cm)])
    rkey.setStyle(TableStyle([
        ("BACKGROUND", (0,0),(-1,-1), LGREY),
        ("GRID",       (0,0),(-1,-1), 0.3, MID),
        ("TOPPADDING", (0,0),(-1,-1), 2),
        ("BOTTOMPADDING",(0,0),(-1,-1), 2),
        ("LEFTPADDING",(0,0),(-1,-1), 4),
        ("RIGHTPADDING",(0,0),(-1,-1), 4),
        ("VALIGN",     (0,0),(-1,-1), "MIDDLE"),
    ]))
    elems.append(rkey)
    elems.append(sp(4))
    elems.append(p("Orris Medical AI  |  July 2026  |  Side A — Parameters", FOOT))

    return elems


# ══════════════════════════════════════════════════════════════════════════════
#  SIDE B — Algorithm + Lethal Triad + Drug Effects + Causes
# ══════════════════════════════════════════════════════════════════════════════
def build_side_b():
    elems = []
    CW = CARD_W

    # Title bar
    title_tbl = Table([[p("TEG / ROTEM  GOAL-DIRECTED ALGORITHM", CARD_TITLE)]], colWidths=[CW])
    title_tbl.setStyle(TableStyle([
        ("BACKGROUND",   (0,0),(-1,-1), NAVY),
        ("TOPPADDING",   (0,0),(-1,-1), 5),
        ("BOTTOMPADDING",(0,0),(-1,-1), 5),
    ]))
    elems.append(title_tbl)
    elems.append(sp(2))

    # ── Algorithm table ────────────────────────────────────────────────────────
    elems.append(banner("INTERPRETATION → INTERVENTION", TEAL))
    elems.append(sp(1))

    algo_hdr = [p("VHA Finding", HDR), p("Likely Defect", HDR),
                p("TEG\nParameter", HDR), p("ROTEM\nParameter", HDR), p("Give →", HDR)]

    def row_col(bg):
        return bg

    algo_rows = [algo_hdr,
        [p("Prolonged R time / CT", CELL_B),
         p("Coagulation factor\ndeficiency / anticoagulant", CELL),
         p("R time ↑", CELL_BC), p("CT ↑", CELL_BC),
         p("FFP or Factor\nConcentrates\n(PCC / FibC)", CELL_B)],
        [p("Prolonged K time / CFT\n+ Reduced α angle", CELL_B),
         p("Fibrinogen deficiency", CELL),
         p("K time ↑\nα angle ↓", CELL_BC), p("CFT ↑\nα ↓ or\nFIBTEM MCF ↓", CELL_BC),
         p("Cryoprecipitate\nor Fibrinogen\nConcentrate", CELL_B)],
        [p("Reduced MA / MCF\n(normal α angle)", CELL_B),
         p("Platelet dysfunction\nor thrombocytopaenia", CELL),
         p("MA ↓", CELL_BC), p("EXTEM MCF ↓\nFIBTEM MCF normal", CELL_BC),
         p("Platelet\nTransfusion", CELL_B)],
        [p("Elevated LY30 / LI30\nor ML", CELL_B),
         p("Hyperfibrinolysis", CELL),
         p("LY30 >7.5%\nEPL >15%", CELL_BC), p("LI30 <85%\nML >15%\nAPTEM MCF ↑", CELL_BC),
         p("Tranexamic Acid\nor EACA\n(if no CI)", CELL_B)],
        [p("MA / MCF ↓\n+ α angle ↓\n+ K time ↑", CELL_B),
         p("Combined fibrinogen\n+ platelet deficit\n(e.g. massive haemorrhage)", CELL),
         p("Multiple\nabnormal", CELL_BC), p("EXTEM + FIBTEM\nboth low", CELL_BC),
         p("Cryoprecipitate\nTHEN Platelets\n(fibrinogen first)", CELL_B)],
        [p("Short R time\nElevated CI (>+3)", CELL_B),
         p("Hypercoagulable\nstate", CELL),
         p("R time ↓\nCI >+3", CELL_BC), p("CT ↓", CELL_BC),
         p("Anticoagulation\n(clinical context\ndependent)", CELL_B)],
    ]
    # Column widths
    ca1 = 3.2*cm; ca2 = 3.0*cm; ca3 = 1.6*cm; ca4 = 2.5*cm
    ca5 = CW - ca1 - ca2 - ca3 - ca4
    algo_bg = [WHITE, GREEN_LT, AMBER_LT, RED_LT, PURPLE_LT, LGREY]
    algo_t = Table(algo_rows, colWidths=[ca1, ca2, ca3, ca4, ca5], repeatRows=1)
    algo_t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,0),  TEAL),
        ("BACKGROUND",    (0,1),(-1,1),  GREEN_LT),
        ("BACKGROUND",    (0,2),(-1,2),  AMBER_LT),
        ("BACKGROUND",    (0,3),(-1,3),  RED_LT),
        ("BACKGROUND",    (0,4),(-1,4),  PURPLE_LT),
        ("BACKGROUND",    (0,5),(-1,5),  TEAL_LT),
        ("BACKGROUND",    (0,6),(-1,6),  LGREY),
        ("GRID",          (0,0),(-1,-1), 0.4, MID),
        ("TOPPADDING",    (0,0),(-1,-1), 3),
        ("BOTTOMPADDING", (0,0),(-1,-1), 3),
        ("LEFTPADDING",   (0,0),(-1,-1), 4),
        ("RIGHTPADDING",  (0,0),(-1,-1), 4),
        ("VALIGN",        (0,0),(-1,-1), "MIDDLE"),
        ("LINEBELOW",     (0,0),(-1,0),  1.0, TEAL),
    ]))
    elems.append(algo_t)
    elems.append(sp(3))

    # ── Drug effects row ───────────────────────────────────────────────────────
    elems.append(banner("DRUG EFFECTS ON TEG/ROTEM", NAVY))
    elems.append(sp(1))
    drug_hdr = [p("Drug / Condition", HDR), p("Effect on Trace", HDR), p("Affected Parameter", HDR)]
    drug_rows = [drug_hdr,
        [p("Heparin (UFH)", CELL_B),     p("Prolongs enzymatic phase", CELL),  p("↑ R time / CT  (INTEM sensitive)", CELL)],
        [p("Warfarin / VKA", CELL_B),    p("Prolonged initiation", CELL),       p("↑ R time / CT  (EXTEM sensitive)", CELL)],
        [p("DOACs (direct Xa/IIa)", CELL_B), p("Prolongs R time variably", CELL), p("↑ R time / CT  (drug-specific assays needed)", CELL)],
        [p("Aspirin / NSAIDs", CELL_B),  p("Reduced platelet contribution", CELL), p("↓ MA / MCF  (use platelet mapping)", CELL)],
        [p("P2Y12 inhibitors", CELL_B),  p("Reduced platelet aggregation", CELL),  p("↓ MA / MCF  (ADP-specific mapping)", CELL)],
        [p("Tranexamic acid", CELL_B),   p("Inhibits fibrinolysis", CELL),      p("↓ LY30 / LI30 (normalises if elevated)", CELL)],
        [p("Hypothermia", CELL_B),       p("Slows all enzymatic reactions", CELL), p("↑ R, K times · ↓ MA  (Note: TEG runs at 37°C — underestimates!)", CELL)],
        [p("DIC (acute)", CELL_B),       p("Consumption coagulopathy + fibrinolysis", CELL), p("↑ R + K · ↓ α, MA + ↑↑ LY30", CELL)],
    ]
    da1 = 2.8*cm; da2 = 3.2*cm; da3 = CW - da1 - da2
    drug_t = Table(drug_rows, colWidths=[da1, da2, da3], repeatRows=1)
    drug_t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,0),  NAVY),
        ("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, LGREY]),
        ("GRID",          (0,0),(-1,-1), 0.4, MID),
        ("TOPPADDING",    (0,0),(-1,-1), 3),
        ("BOTTOMPADDING", (0,0),(-1,-1), 3),
        ("LEFTPADDING",   (0,0),(-1,-1), 4),
        ("RIGHTPADDING",  (0,0),(-1,-1), 4),
        ("VALIGN",        (0,0),(-1,-1), "MIDDLE"),
    ]))
    elems.append(drug_t)
    elems.append(sp(3))

    # ── Lethal triad + periop contexts ────────────────────────────────────────
    triad_data = [
        [p("THE LETHAL TRIAD", S("LT", fontName="Helvetica-Bold", fontSize=7.5,
                                  textColor=WHITE, alignment=TA_CENTER)),
         p("PERIOP HIGH-RISK CONTEXTS", S("LT2", fontName="Helvetica-Bold", fontSize=7.5,
                                           textColor=WHITE, alignment=TA_CENTER))],
        [p("🌡 Hypothermia  <35°C\n→ Impairs enzymatic clotting + platelet fx\n\n"
           "⚗ Acidosis  pH <7.2\n→ Disrupts factor + platelet environment\n\n"
           "🩸 Haemodilution\n→ Dilutes factors + platelets\n\n"
           "All three are synergistic → TEG/ROTEM-guided\ncorrection superior to empiric 1:1:1",
           S("tri", fontName="Helvetica", fontSize=7.5, textColor=black, leading=11, alignment=TA_LEFT)),
         p("• <b>Cardiac surgery</b> (strongest evidence)\n"
           "• Major trauma / haemorrhage\n"
           "• Liver transplantation (hyperfibrinolysis)\n"
           "• Obstetric major haemorrhage (PPH)\n"
           "• Neurosurgery (detect hypercoag)\n"
           "• Massive transfusion protocol guidance\n\n"
           "<i>NOTE: TEG ≠ ROTEM — not interchangeable.\nValues differ; use institution-specific ranges.</i>",
           S("ctx", fontName="Helvetica", fontSize=7.5, textColor=black, leading=11, alignment=TA_LEFT))],
    ]
    triad_t = Table(triad_data, colWidths=[CW/2, CW/2])
    triad_t.setStyle(TableStyle([
        ("BACKGROUND",   (0,0),(0,0), RED),
        ("BACKGROUND",   (1,0),(1,0), GREEN),
        ("BACKGROUND",   (0,1),(0,1), RED_LT),
        ("BACKGROUND",   (1,1),(1,1), GREEN_LT),
        ("GRID",         (0,0),(-1,-1), 0.4, MID),
        ("TOPPADDING",   (0,0),(-1,-1), 4),
        ("BOTTOMPADDING",(0,0),(-1,-1), 4),
        ("LEFTPADDING",  (0,0),(-1,-1), 5),
        ("RIGHTPADDING", (0,0),(-1,-1), 5),
        ("VALIGN",       (0,0),(-1,-1), "TOP"),
    ]))
    elems.append(triad_t)
    elems.append(sp(4))
    elems.append(p(
        "Cochrane 2026 (35 RCTs, n=3096): TEG/ROTEM may ↓ mortality (RR 0.76) and ↓ FFP/platelet use — very low certainty evidence  |  "
        "Morgan & Mikhail Clin Anaesthesiology 7e  |  Orris Medical AI  |  July 2026  |  Side B — Algorithm",
        FOOT))
    return elems


# ══════════════════════════════════════════════════════════════════════════════
#  ASSEMBLE: two panels side by side on one A4 landscape sheet
# ══════════════════════════════════════════════════════════════════════════════
def build():
    doc = SimpleDocTemplate(
        OUTPUT,
        pagesize=landscape(A4),
        leftMargin=MARGIN, rightMargin=MARGIN,
        topMargin=MARGIN, bottomMargin=MARGIN,
        title="TEG/ROTEM Quick Reference Theatre Card",
        author="Orris Medical AI"
    )

    side_a = build_side_a()
    side_b = build_side_b()

    # Wrap each side into a single-cell table column, then place both side by side
    def side_table(elems, width):
        rows = [[e] for e in elems]
        t = Table(rows, colWidths=[width])
        t.setStyle(TableStyle([
            ("TOPPADDING",    (0,0),(-1,-1), 0),
            ("BOTTOMPADDING", (0,0),(-1,-1), 0),
            ("LEFTPADDING",   (0,0),(-1,-1), 0),
            ("RIGHTPADDING",  (0,0),(-1,-1), 0),
            ("VALIGN",        (0,0),(-1,-1), "TOP"),
        ]))
        return t

    CW = CARD_W
    DIVIDER = 8   # points of gutter between the two panels

    outer = Table(
        [[side_table(side_a, CW), Spacer(DIVIDER, 1), side_table(side_b, CW)]],
        colWidths=[CW, DIVIDER, CW]
    )
    outer.setStyle(TableStyle([
        ("VALIGN",        (0,0),(-1,-1), "TOP"),
        ("TOPPADDING",    (0,0),(-1,-1), 0),
        ("BOTTOMPADDING", (0,0),(-1,-1), 0),
        ("LEFTPADDING",   (0,0),(-1,-1), 0),
        ("RIGHTPADDING",  (0,0),(-1,-1), 0),
        # Dashed centre cut line
        ("LINEAFTER",     (0,0),(0,-1), 0.5, HexColor("#aaaaaa"), None, None, None, (3,3)),
    ]))

    doc.build([outer])
    print(f"Card saved: {OUTPUT}")


if __name__ == "__main__":
    build()
Running Command

cd /home/daytona/workspace/coagulation-teg && python3 build_card.py 2>&1

Editing File

~/coagulation-teg/build_card.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/coagulation-teg/build_card.py'
Running Command

cd /home/daytona/workspace/coagulation-teg && python3 build_card.py 2>&1

Writing File

~/coagulation-teg/build_card.py

#!/usr/bin/env python3
"""
TEG / ROTEM Quick-Reference Laminated Card — Theatre Use
Two A5-landscape panels printed on one A4-landscape page.
Built with ReportLab canvas + Platypus Frame for precise layout.
"""

import io, requests
from reportlab.lib.pagesizes import A4, landscape
from reportlab.lib.units import cm, mm
from reportlab.lib.colors import HexColor, white, black
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT
from reportlab.platypus import (
    Table, TableStyle, Paragraph, Spacer, HRFlowable, Image, Frame
)
from reportlab.pdfgen import canvas as pdfcanvas

OUTPUT = "/home/daytona/workspace/coagulation-teg/TEG_ROTEM_Theatre_Card.pdf"

# ── Page ──────────────────────────────────────────────────────────────────────
PW, PH = landscape(A4)  # 841.89 x 595.28 pt
GUTTER = 6              # pt between panels
PAD    = 6              # pt inner padding
PANEL_W = (PW - GUTTER) / 2
PANEL_H = PH

# ── Palette ───────────────────────────────────────────────────────────────────
NAVY      = HexColor("#1a2e4a")
TEAL      = HexColor("#0d6e7e")
TEAL_LT   = HexColor("#dff0f3")
GREEN     = HexColor("#1a6b3c")
GREEN_LT  = HexColor("#d4edda")
RED       = HexColor("#8b1a1a")
RED_LT    = HexColor("#fde8e8")
AMBER     = HexColor("#7a4f00")
AMBER_LT  = HexColor("#fff3cd")
PURPLE    = HexColor("#4a1a6b")
PURPLE_LT = HexColor("#ede0f7")
GREY      = HexColor("#555555")
LGREY     = HexColor("#f5f5f5")
MID       = HexColor("#cccccc")
WHITE     = white

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

TITLE = S("TI", fontName="Helvetica-Bold", fontSize=10,  textColor=WHITE, alignment=TA_CENTER, leading=13)
SECT  = S("SE", fontName="Helvetica-Bold", fontSize=8,   textColor=WHITE, alignment=TA_CENTER, leading=11)
HDR   = S("HD", fontName="Helvetica-Bold", fontSize=7,   textColor=WHITE, alignment=TA_CENTER, leading=9)
CELL  = S("CL", fontName="Helvetica",      fontSize=7,   textColor=black, alignment=TA_LEFT,   leading=9)
CELLC = S("CC", fontName="Helvetica",      fontSize=7,   textColor=black, alignment=TA_CENTER, leading=9)
CELLB = S("CB", fontName="Helvetica-Bold", fontSize=7,   textColor=black, alignment=TA_LEFT,   leading=9)
CELLBC= S("CBC",fontName="Helvetica-Bold", fontSize=7,   textColor=black, alignment=TA_CENTER, leading=9)
SMALL = S("SM", fontName="Helvetica",      fontSize=6,   textColor=GREY,  alignment=TA_CENTER, leading=8)
SMALLB= S("SB", fontName="Helvetica-Bold", fontSize=6,   textColor=GREY,  alignment=TA_LEFT,   leading=8)
FOOT  = S("FT", fontName="Helvetica-Oblique", fontSize=5.5, textColor=GREY, alignment=TA_CENTER, leading=7)

p  = lambda txt, sty: Paragraph(txt, sty)
sp = lambda h=2: Spacer(1, h)

# ── Image fetch ───────────────────────────────────────────────────────────────
def fetch_img(url, w_pt, max_h_pt=None):
    try:
        r = requests.get(url, timeout=12)
        r.raise_for_status()
        buf = io.BytesIO(r.content)
        img = Image(buf)
        aspect = img.imageHeight / float(img.imageWidth)
        h = w_pt * aspect
        if max_h_pt and h > max_h_pt:
            h = max_h_pt
            w_pt = h / aspect
        img.drawWidth  = w_pt
        img.drawHeight = h
        return img
    except Exception as e:
        print(f"  [warn] {e}")
        return None

# ── Table helpers ─────────────────────────────────────────────────────────────
def banner_row(txt, color, width):
    t = Table([[p(txt, SECT)]], colWidths=[width])
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,-1), color),
        ("TOPPADDING",    (0,0),(-1,-1), 3),
        ("BOTTOMPADDING", (0,0),(-1,-1), 3),
        ("LEFTPADDING",   (0,0),(-1,-1), 4),
        ("RIGHTPADDING",  (0,0),(-1,-1), 4),
    ]))
    return t

def mk_table(rows, cw, row_bgs=None, hdr_color=NAVY):
    t = Table(rows, colWidths=cw, repeatRows=1)
    style = [
        ("BACKGROUND",    (0,0),(-1,0),  hdr_color),
        ("GRID",          (0,0),(-1,-1), 0.4, MID),
        ("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), "MIDDLE"),
    ]
    if row_bgs:
        for i, bg in enumerate(row_bgs, start=1):
            if bg:
                style.append(("BACKGROUND", (0,i),(-1,i), bg))
    else:
        style.append(("ROWBACKGROUNDS", (0,1),(-1,-1), [WHITE, LGREY]))
    t.setStyle(TableStyle(style))
    return t

# ══════════════════════════════════════════════════════════════════════════════
# SIDE A flowables
# ══════════════════════════════════════════════════════════════════════════════
def side_a_flowables(W):
    elems = []
    IW = W - 2*PAD   # inner width

    # Title
    title = Table([[p("TEG / ROTEM  QUICK REFERENCE  —  THEATRE CARD", TITLE)]], colWidths=[W])
    title.setStyle(TableStyle([
        ("BACKGROUND",   (0,0),(-1,-1), NAVY),
        ("TOPPADDING",   (0,0),(-1,-1), 5),
        ("BOTTOMPADDING",(0,0),(-1,-1), 5),
    ]))
    elems.append(title); elems.append(sp(3))

    # TEG trace image
    img = fetch_img(
        "https://cdn.orris.care/cdss_images/0b1425cf1a93207225bb92d1d44f5ea59473ea214e1210004b631d11c938aa87.png",
        w_pt=IW * 0.78, max_h_pt=80)
    if img:
        img_wrap = Table([[img]], colWidths=[IW])
        img_wrap.setStyle(TableStyle([
            ("ALIGN",(0,0),(-1,-1),"CENTER"), ("VALIGN",(0,0),(-1,-1),"MIDDLE"),
            ("TOPPADDING",(0,0),(-1,-1),0), ("BOTTOMPADDING",(0,0),(-1,-1),0),
        ]))
        elems.append(img_wrap)
        elems.append(p("R time · K time · α angle · MA · LY30 · EPL", SMALL))
        elems.append(sp(3))

    # TEG Parameters
    elems.append(banner_row("TEG  PARAMETERS", TEAL, IW)); elems.append(sp(1))
    c1,c2,c3,c4 = 1.4*cm, 3.8*cm, 1.4*cm, IW - 1.4*cm - 3.8*cm - 1.4*cm
    teg_hdr = [p("Param",HDR), p("Definition",HDR), p("Normal",HDR), p("↑/↓ Meaning & Action",HDR)]
    teg_rows = [teg_hdr,
        [p("R time",CELLB), p("First clot formation (2 mm)",CELL), p("5–10 min",CELLC),
         p("↑ Factor deficiency / anticoag → FFP/PCC\n↓ Hypercoagulable",CELL)],
        [p("K time",CELLB), p("Clot kinetics to 20 mm",CELL), p("1–3 min",CELLC),
         p("↑ Low fibrinogen / platelets → Cryo",CELL)],
        [p("α angle",CELLB), p("Rate of fibrin crosslinking",CELL), p("53–72°",CELLC),
         p("↓ Fibrinogen deficiency → Cryo/FibC\n↑ Hypercoagulable",CELL)],
        [p("MA",CELLB), p("Max clot strength\n(~80% plt, ~20% fibrinogen)",CELL), p("50–70 mm",CELLC),
         p("↓ Plt dysfunction / low count → Platelets",CELL)],
        [p("LY30",CELLB), p("% amplitude loss at 30 min",CELL), p("<7.5%",CELLC),
         p("↑>7.5%: Hyperfibrinolysis → TXA / EACA",CELL)],
        [p("EPL",CELLB), p("Estimated % lysis (earlier)",CELL), p("<15%",CELLC),
         p("↑ Earlier fibrinolysis signal",CELL)],
        [p("CI",CELLB), p("Composite index",CELL), p("−3 to+3",CELLC),
         p("<−3 hypocoag  |  >+3 hypercoag",CELL)],
    ]
    elems.append(mk_table(teg_rows, [c1,c2,c3,c4], hdr_color=TEAL)); elems.append(sp(4))

    # ROTEM equivalents
    elems.append(banner_row("ROTEM  EQUIVALENTS  &  REAGENTS", NAVY, IW)); elems.append(sp(1))
    ra,rb,rc,rd = 1.2*cm, 1.2*cm, 3.0*cm, IW - 1.2*cm - 1.2*cm - 3.0*cm
    rotem_hdr = [p("TEG",HDR), p("ROTEM",HDR), p("Reagent(s)",HDR), p("Tests",HDR)]
    rotem_rows = [rotem_hdr,
        [p("R time",CELLB), p("CT",CELLBC),    p("EXTEM / INTEM",CELL), p("Extrinsic / Intrinsic factors",CELL)],
        [p("K time",CELLB), p("CFT",CELLBC),   p("EXTEM / INTEM",CELL), p("Fibrinogen + platelet kinetics",CELL)],
        [p("α",CELLB),      p("α angle",CELLBC),p("EXTEM / FIBTEM",CELL), p("Fibrinogen contribution",CELL)],
        [p("MA",CELLB),     p("MCF",CELLBC),   p("EXTEM/INTEM/FIBTEM",CELL), p("Clot strength (plt + fibrinogen)",CELL)],
        [p("LY30",CELLB),   p("LI30/ML",CELLBC),p("EXTEM ± APTEM",CELL), p("Fibrinolysis (APTEM confirms)",CELL)],
    ]
    elems.append(mk_table(rotem_rows, [ra,rb,rc,rd])); elems.append(sp(2))

    # Reagent key
    rkw = IW/4
    rk = Table([
        [p("EXTEM",S("e",fontName="Helvetica-Bold",fontSize=7,textColor=RED,alignment=TA_CENTER)),
         p("Tissue factor → extrinsic",SMALL),
         p("INTEM",S("i",fontName="Helvetica-Bold",fontSize=7,textColor=TEAL,alignment=TA_CENTER)),
         p("Ellagic acid → intrinsic",SMALL)],
        [p("FIBTEM",S("f",fontName="Helvetica-Bold",fontSize=7,textColor=GREEN,alignment=TA_CENTER)),
         p("EXTEM + cytoD → fibrinogen only",SMALL),
         p("APTEM",S("a",fontName="Helvetica-Bold",fontSize=7,textColor=AMBER,alignment=TA_CENTER)),
         p("EXTEM + aprotinin → confirms lysis",SMALL)],
    ], colWidths=[rkw*0.55, rkw*1.45, rkw*0.55, rkw*1.45])
    rk.setStyle(TableStyle([
        ("BACKGROUND",(0,0),(-1,-1),LGREY),("GRID",(0,0),(-1,-1),0.3,MID),
        ("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),"MIDDLE"),
    ]))
    elems.append(rk); elems.append(sp(4))
    elems.append(p("Orris Medical AI  |  July 2026  |  Side A — Parameters  |  Print on A4 landscape · cut · laminate", FOOT))
    return elems


# ══════════════════════════════════════════════════════════════════════════════
# SIDE B flowables
# ══════════════════════════════════════════════════════════════════════════════
def side_b_flowables(W):
    elems = []
    IW = W - 2*PAD

    title = Table([[p("TEG / ROTEM  GOAL-DIRECTED ALGORITHM  —  THEATRE CARD", TITLE)]], colWidths=[W])
    title.setStyle(TableStyle([
        ("BACKGROUND",   (0,0),(-1,-1), NAVY),
        ("TOPPADDING",   (0,0),(-1,-1), 5),
        ("BOTTOMPADDING",(0,0),(-1,-1), 5),
    ]))
    elems.append(title); elems.append(sp(3))

    # Algorithm
    elems.append(banner_row("INTERPRETATION  →  INTERVENTION", TEAL, IW)); elems.append(sp(1))
    aa,ab,ac,ad,ae = 3.0*cm, 2.8*cm, 1.5*cm, 2.4*cm, IW - 3.0*cm - 2.8*cm - 1.5*cm - 2.4*cm
    alg_hdr = [p("VHA Finding",HDR), p("Likely Defect",HDR), p("TEG",HDR), p("ROTEM",HDR), p("Give →",HDR)]
    alg_rows = [alg_hdr,
        [p("Prolonged R time/CT",CELLB), p("Factor deficiency\nor anticoagulant",CELL),
         p("R ↑",CELLBC), p("CT ↑",CELLBC), p("FFP or\nPCC/FibC",CELLB)],
        [p("Prolonged K/CFT\n+ Reduced α",CELLB), p("Fibrinogen\ndeficiency",CELL),
         p("K ↑\nα ↓",CELLBC), p("CFT ↑\nFIBTEM MCF ↓",CELLBC), p("Cryo or\nFibrinogen Conc.",CELLB)],
        [p("Reduced MA/MCF\n(normal α)",CELLB), p("Platelet dysfunction\nor ↓ count",CELL),
         p("MA ↓",CELLBC), p("EXTEM MCF ↓\nFIBTEM normal",CELLBC), p("Platelet\nTransfusion",CELLB)],
        [p("↑ LY30 / LI30\nor ML",CELLB), p("Hyperfibrinolysis",CELL),
         p("LY30\n>7.5%",CELLBC), p("LI30 <85%\nAPTEM MCF ↑",CELLBC), p("TXA 1g IV\nor EACA",CELLB)],
        [p("MA ↓ + α ↓\n+ K ↑ (combined)",CELLB), p("Mixed fibrinogen\n+ platelet deficit",CELL),
         p("Multiple\nabnormal",CELLBC), p("EXTEM+FIBTEM\nboth low",CELLBC), p("Cryo FIRST\nthen Platelets",CELLB)],
        [p("Short R / CI >+3",CELLB), p("Hypercoagulable",CELL),
         p("R ↓\nCI >+3",CELLBC), p("CT ↓",CELLBC), p("Anticoag\n(context-dep.)",CELLB)],
    ]
    row_bgs = [None, GREEN_LT, AMBER_LT, RED_LT, PURPLE_LT, HexColor("#e8f0fe"), LGREY]
    elems.append(mk_table(alg_rows, [aa,ab,ac,ad,ae], row_bgs=row_bgs, hdr_color=TEAL))
    elems.append(sp(4))

    # Drug effects
    elems.append(banner_row("DRUG  &  CONDITION  EFFECTS  ON  VHA", NAVY, IW)); elems.append(sp(1))
    da,db,dc = 2.5*cm, 3.0*cm, IW - 2.5*cm - 3.0*cm
    drug_hdr = [p("Drug / Condition",HDR), p("Effect",HDR), p("Key Parameter(s) Affected",HDR)]
    drug_rows = [drug_hdr,
        [p("Heparin (UFH)",CELLB),       p("Prolongs enzymatic phase",CELL), p("↑ R time/CT  — INTEM most sensitive",CELL)],
        [p("Warfarin/VKA",CELLB),        p("Impairs initiation",CELL),       p("↑ R time/CT  — EXTEM sensitive",CELL)],
        [p("DOACs",CELLB),               p("Variable R time prolongation",CELL), p("Drug-specific assays often needed",CELL)],
        [p("Aspirin/NSAIDs",CELLB),      p("Platelet dysfunction",CELL),     p("↓ MA/MCF  — use platelet mapping",CELL)],
        [p("P2Y12 inhibitors",CELLB),    p("↓ platelet aggregation",CELL),   p("↓ MA/MCF  — ADP mapping assay",CELL)],
        [p("TXA / EACA",CELLB),         p("Anti-fibrinolytic",CELL),         p("↓ LY30/LI30 — normalises if elevated",CELL)],
        [p("Hypothermia <35°C",CELLB),   p("Slows all enzymatic steps",CELL),p("↑ R, K · ↓ MA  ⚠ TEG runs at 37°C — underestimates effect!",CELL)],
        [p("Acute DIC",CELLB),           p("Consumption + fibrinolysis",CELL),p("↑↑ R + K · ↓↓ α, MA · ↑↑ LY30",CELL)],
    ]
    elems.append(mk_table(drug_rows, [da,db,dc])); elems.append(sp(3))

    # Lethal triad + contexts
    half = IW / 2
    triad_data = [
        [p("LETHAL TRIAD IN HAEMORRHAGE",
           S("lt",fontName="Helvetica-Bold",fontSize=7,textColor=WHITE,alignment=TA_CENTER)),
         p("CLINICAL CONTEXTS  (strongest → emerging)",
           S("lc",fontName="Helvetica-Bold",fontSize=7,textColor=WHITE,alignment=TA_CENTER))],
        [p("🌡 <b>Hypothermia</b> <35°C\n— impairs enzymatic clotting &amp; platelet function\n\n"
           "⚗ <b>Acidosis</b> pH &lt;7.2\n— disrupts factor and platelet environment\n\n"
           "🩸 <b>Haemodilution</b>\n— dilutes factors and platelets\n\n"
           "<i>Synergistic — TEG/ROTEM-guided correction superior\nto empiric 1:1:1 FFP:Plt:pRBC</i>",
           S("tri",fontName="Helvetica",fontSize=7,textColor=black,leading=10,alignment=TA_LEFT)),
         p("<b>1.</b> Cardiac surgery (strongest RCT evidence)\n"
           "<b>2.</b> Major trauma / TIC\n"
           "<b>3.</b> Liver transplantation (hyperfibrinolysis)\n"
           "<b>4.</b> Obstetric PPH\n"
           "<b>5.</b> Neurosurgery (hypercoag detection)\n"
           "<b>6.</b> Massive transfusion protocol guidance\n\n"
           "<i>⚠ TEG ≠ ROTEM — not interchangeable.\nUse institution-specific reference ranges.</i>",
           S("ctx",fontName="Helvetica",fontSize=7,textColor=black,leading=10,alignment=TA_LEFT))],
    ]
    triad_t = Table(triad_data, colWidths=[half, half])
    triad_t.setStyle(TableStyle([
        ("BACKGROUND",(0,0),(0,0), RED),   ("BACKGROUND",(1,0),(1,0), GREEN),
        ("BACKGROUND",(0,1),(0,1), RED_LT),("BACKGROUND",(1,1),(1,1), GREEN_LT),
        ("GRID",(0,0),(-1,-1),0.4,MID),
        ("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"),
    ]))
    elems.append(triad_t); elems.append(sp(3))
    elems.append(p(
        "Evidence: Cochrane 2026 (35 RCTs, n=3096): TEG/ROTEM may ↓ mortality RR 0.76 (95%CI 0.63–0.92) and ↓ FFP/plt use — very low certainty  |  "
        "Orris Medical AI  |  July 2026  |  Side B — Algorithm  |  PMID 42145275",
        FOOT))
    return elems


# ══════════════════════════════════════════════════════════════════════════════
# RENDER using Frames placed on canvas
# ══════════════════════════════════════════════════════════════════════════════
def build():
    c = pdfcanvas.Canvas(OUTPUT, pagesize=landscape(A4))
    c.setTitle("TEG/ROTEM Quick Reference Theatre Card")
    c.setAuthor("Orris Medical AI")

    # Thin separator line
    c.setStrokeColor(MID)
    c.setLineWidth(0.5)
    c.line(PW/2, 4, PW/2, PH - 4)

    # Frame A — left panel
    fA = Frame(0, 0, PANEL_W, PANEL_H,
               leftPadding=PAD, rightPadding=PAD,
               topPadding=PAD, bottomPadding=PAD,
               showBoundary=0)
    fA.addFromList(side_a_flowables(PANEL_W), c)

    # Frame B — right panel
    fB = Frame(PANEL_W + GUTTER, 0, PANEL_W, PANEL_H,
               leftPadding=PAD, rightPadding=PAD,
               topPadding=PAD, bottomPadding=PAD,
               showBoundary=0)
    fB.addFromList(side_b_flowables(PANEL_W), c)

    c.save()
    print(f"Card saved: {OUTPUT}")


if __name__ == "__main__":
    build()
Running Command

cat > /home/daytona/workspace/coagulation-teg/build_card.py << 'PYEOF' #!/usr/bin/env python3 """ TEG / ROTEM Quick-Reference Laminated Card — Theatre Use Two A5-landscape panels on one A4-landscape page via canvas Frames. """ import io, requests from reportlab.lib.pagesizes import A4, landscape from reportlab.lib.units import cm from reportlab.lib.colors import HexColor, white, black from reportlab.lib.styles import ParagraphStyle from reportlab.lib.enums import TA_CENTER, TA_LEFT from reportlab.platypus import Table, TableStyle, Paragraph, Spacer, Image, Frame from reportlab.pdfgen import canvas as pdfcanvas OUTPUT = "/home/daytona/workspace/coagulation-teg/TEG_ROTEM_Theatre_Card.pdf" PW, PH = landscape(A4) GUTTER = 6 PAD = 5 PANEL_W = (PW - GUTTER) / 2 PANEL_H = PH NAVY=HexColor("#1a2e4a"); TEAL=HexColor("#0d6e7e"); TEAL_LT=HexColor("#dff0f3") GREEN=HexColor("#1a6b3c"); GREEN_LT=HexColor("#d4edda") RED=HexColor("#8b1a1a"); RED_LT=HexColor("#fde8e8") AMBER=HexColor("#7a4f00"); AMBER_LT=HexColor("#fff3cd") PURPLE_LT=HexColor("#ede0f7"); GREY=HexColor("#555555") LGREY=HexColor("#f5f5f5"); MID=HexColor("#cccccc"); WHITE=white def S(name,**kw): return ParagraphStyle(name,**kw) TITLE=S("TI",fontName="Helvetica-Bold",fontSize=10,textColor=WHITE,alignment=TA_CENTER,leading=13) SECT =S("SE",fontName="Helvetica-Bold",fontSize=8, textColor=WHITE,alignment=TA_CENTER,leading=11) HDR =S("HD",fontName="Helvetica-Bold",fontSize=7, textColor=WHITE,alignment=TA_CENTER,leading=9) CELL =S("CL",fontName="Helvetica", fontSize=7, textColor=black,alignment=TA_LEFT, leading=9) CELLC=S("CC",fontName="Helvetica", fontSize=7, textColor=black,alignment=TA_CENTER,leading=9) CELLB=S("CB",fontName="Helvetica-Bold",fontSize=7, textColor=black,alignment=TA_LEFT, leading=9) CELLBC=S("CBC",fontName="Helvetica-Bold",fontSize=7,textColor=black,alignment=TA_CENTER,leading=9) SMALL=S("SM",fontName="Helvetica", fontSize=6, textColor=GREY, alignment=TA_CENTER,leading=8) FOOT =S("FT",fontName="Helvetica-Oblique",fontSize=5.5,textColor=GREY,alignment=TA_CENTER,leading=7) p = lambda t,s: Paragraph(t,s) sp = lambda h=2: Spacer(1,h) def fetch_img(url, w_pt, max_h_pt=None): try: r=requests.get(url,timeout=12); r.raise_for_status() buf=io.BytesIO(r.content); img=Image(buf) aspect=img.imageHeight/float(img.imageWidth) h=w_pt*aspect if max_h_pt and h>max_h_pt: h=max_h_pt; w_pt=h/aspect img.drawWidth=w_pt; img.drawHeight=h; return img except Exception as e: print(f" [warn] {e}"); return None def banner(txt, color, W): t=Table([[p(txt,SECT)]],colWidths=[W]) t.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),color), ("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3), ("LEFTPADDING",(0,0),(-1,-1),4),("RIGHTPADDING",(0,0),(-1,-1),4)])) return t def mktbl(rows,cw,row_bgs=None,hc=NAVY): t=Table(rows,colWidths=cw,repeatRows=1) sty=[("BACKGROUND",(0,0),(-1,0),hc),("GRID",(0,0),(-1,-1),0.4,MID), ("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),"MIDDLE")] if row_bgs: for i,bg in enumerate(row_bgs,1): if bg: sty.append(("BACKGROUND",(0,i),(-1,i),bg)) else: sty.append(("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE,LGREY])) t.setStyle(TableStyle(sty)); return t def side_a(W): E=[]; IW=W-2*PAD ttl=Table([[p("TEG / ROTEM QUICK REFERENCE — THEATRE CARD",TITLE)]],colWidths=[W]) ttl.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),NAVY), ("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5)])) E.append(ttl); E.append(sp(3)) img=fetch_img("https://cdn.orris.care/cdss_images/0b1425cf1a93207225bb92d1d44f5ea59473ea214e1210004b631d11c938aa87.png", w_pt=IW*0.76,max_h_pt=78) if img: iw=Table([[img]],colWidths=[IW]) iw.setStyle(TableStyle([("ALIGN",(0,0),(-1,-1),"CENTER"),("VALIGN",(0,0),(-1,-1),"MIDDLE"), ("TOPPADDING",(0,0),(-1,-1),0),("BOTTOMPADDING",(0,0),(-1,-1),0)])) E.append(iw); E.append(p("R time · K time · α angle · MA · LY30 · EPL",SMALL)); E.append(sp(3)) E.append(banner("TEG PARAMETERS",TEAL,IW)); E.append(sp(1)) c1,c2,c3,c4=1.4*cm,3.8*cm,1.4*cm,IW-1.4*cm-3.8*cm-1.4*cm rows=[ [p("Param",HDR),p("Definition",HDR),p("Normal",HDR),p("↑/↓ Meaning & Action",HDR)], [p("R time",CELLB),p("First clot (2 mm amplitude)",CELL),p("5–10 min",CELLC),p("↑ Factor deficiency/anticoag → FFP/PCC\n↓ Hypercoagulable",CELL)], [p("K time",CELLB),p("Time to 20 mm amplitude",CELL),p("1–3 min",CELLC),p("↑ Low fibrinogen/platelets → Cryo",CELL)], [p("α angle",CELLB),p("Rate of fibrin crosslinking",CELL),p("53–72°",CELLC),p("↓ Fibrinogen deficiency → Cryo/FibC\n↑ Hypercoagulable",CELL)], [p("MA",CELLB),p("Max clot strength\n(~80% plt, ~20% fibrinogen)",CELL),p("50–70 mm",CELLC),p("↓ Platelet dysfunction/low count → Platelets",CELL)], [p("LY30",CELLB),p("% amplitude loss at 30 min",CELL),p("<7.5%",CELLC),p("↑>7.5%: Hyperfibrinolysis → TXA/EACA",CELL)], [p("EPL",CELLB),p("Estimated % lysis (earlier signal)",CELL),p("<15%",CELLC),p("↑ Earlier fibrinolysis detection",CELL)], [p("CI",CELLB),p("Composite index",CELL),p("−3 to+3",CELLC),p("<−3 hypocoag | >+3 hypercoag",CELL)], ] E.append(mktbl(rows,[c1,c2,c3,c4],hc=TEAL)); E.append(sp(4)) E.append(banner("ROTEM EQUIVALENTS & REAGENTS",NAVY,IW)); E.append(sp(1)) ra,rb,rc,rd=1.2*cm,1.2*cm,3.0*cm,IW-1.2*cm-1.2*cm-3.0*cm r2=[ [p("TEG",HDR),p("ROTEM",HDR),p("Reagent(s)",HDR),p("Tests",HDR)], [p("R time",CELLB),p("CT",CELLBC),p("EXTEM / INTEM",CELL),p("Extrinsic / Intrinsic factors",CELL)], [p("K time",CELLB),p("CFT",CELLBC),p("EXTEM / INTEM",CELL),p("Fibrinogen + platelet kinetics",CELL)], [p("α",CELLB),p("α angle",CELLBC),p("EXTEM / FIBTEM",CELL),p("Fibrinogen contribution",CELL)], [p("MA",CELLB),p("MCF",CELLBC),p("EXTEM/INTEM/FIBTEM",CELL),p("Clot strength (plt + fibrinogen)",CELL)], [p("LY30",CELLB),p("LI30/ML",CELLBC),p("EXTEM ± APTEM",CELL),p("Fibrinolysis (APTEM confirms)",CELL)], ] E.append(mktbl(r2,[ra,rb,rc,rd])); E.append(sp(2)) qw=IW/4 rk=Table([ [p("EXTEM",S("ex",fontName="Helvetica-Bold",fontSize=7,textColor=RED,alignment=TA_CENTER)), p("Tissue factor → extrinsic",SMALL), p("INTEM",S("in",fontName="Helvetica-Bold",fontSize=7,textColor=TEAL,alignment=TA_CENTER)), p("Ellagic acid → intrinsic",SMALL)], [p("FIBTEM",S("fi",fontName="Helvetica-Bold",fontSize=7,textColor=GREEN,alignment=TA_CENTER)), p("EXTEM + cytoD → fibrinogen only",SMALL), p("APTEM",S("ap",fontName="Helvetica-Bold",fontSize=7,textColor=AMBER,alignment=TA_CENTER)), p("EXTEM + aprotinin → confirm lysis",SMALL)], ],colWidths=[qw*0.55,qw*1.45,qw*0.55,qw*1.45]) rk.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),LGREY),("GRID",(0,0),(-1,-1),0.3,MID), ("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),"MIDDLE")])) E.append(rk); E.append(sp(4)) E.append(p("Orris Medical AI | July 2026 | Side A — Parameters | Print A4 landscape · cut · laminate",FOOT)) return E def side_b(W): E=[]; IW=W-2*PAD ttl=Table([[p("TEG / ROTEM GOAL-DIRECTED ALGORITHM — THEATRE CARD",TITLE)]],colWidths=[W]) ttl.setStyle(TableStyle([("BACKGROUND",(0,0),(-1,-1),NAVY), ("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5)])) E.append(ttl); E.append(sp(3)) E.append(banner("INTERPRETATION → INTERVENTION",TEAL,IW)); E.append(sp(1)) aa,ab,ac,ad,ae=3.0*cm,2.8*cm,1.4*cm,2.4*cm,IW-3.0*cm-2.8*cm-1.4*cm-2.4*cm alg=[ [p("VHA Finding",HDR),p("Likely Defect",HDR),p("TEG",HDR),p("ROTEM",HDR),p("Give →",HDR)], [p("Prolonged R time/CT",CELLB),p("Factor deficiency\nor anticoagulant",CELL),p("R ↑",CELLBC),p("CT ↑",CELLBC),p("FFP or\nPCC/FibC",CELLB)], [p("Prolonged K/CFT\n+ Reduced α",CELLB),p("Fibrinogen\ndeficiency",CELL),p("K ↑\nα ↓",CELLBC),p("CFT ↑\nFIBTEM MCF ↓",CELLBC),p("Cryo or\nFibrinogen Conc.",CELLB)], [p("Reduced MA/MCF\n(normal α)",CELLB),p("Platelet dysfunction\nor ↓ count",CELL),p("MA ↓",CELLBC),p("EXTEM MCF ↓\nFIBTEM normal",CELLBC),p("Platelet\nTransfusion",CELLB)], [p("↑ LY30/LI30 or ML",CELLB),p("Hyperfibrinolysis",CELL),p("LY30\n>7.5%",CELLBC),p("LI30 <85%\nAPTEM MCF ↑",CELLBC),p("TXA 1g IV\nor EACA",CELLB)], [p("MA ↓ + α ↓ + K ↑",CELLB),p("Mixed fibrinogen\n+ platelet deficit",CELL),p("Multiple\nabnormal",CELLBC),p("EXTEM+FIBTEM\nboth low",CELLBC),p("Cryo FIRST\nthen Platelets",CELLB)], [p("Short R / CI >+3",CELLB),p("Hypercoagulable",CELL),p("R ↓\nCI >+3",CELLBC),p("CT ↓",CELLBC),p("Anticoag\n(context-dep.)",CELLB)], ] bgs=[None,GREEN_LT,AMBER_LT,RED_LT,PURPLE_LT,HexColor("#e8f0fe"),LGREY] E.append(mktbl(alg,[aa,ab,ac,ad,ae],row_bgs=bgs,hc=TEAL)); E.append(sp(4)) E.append(banner("DRUG & CONDITION EFFECTS ON VHA",NAVY,IW)); E.append(sp(1)) da,db,dc=2.5*cm,3.0*cm,IW-2.5*cm-3.0*cm drugs=[ [p("Drug / Condition",HDR),p("Effect",HDR),p("Key Parameter(s) Affected",HDR)], [p("Heparin (UFH)",CELLB),p("Prolongs enzymatic phase",CELL),p("↑ R time/CT — INTEM most sensitive",CELL)], [p("Warfarin/VKA",CELLB),p("Impairs initiation",CELL),p("↑ R time/CT — EXTEM sensitive",CELL)], [p("DOACs",CELLB),p("Variable R time prolongation",CELL),p("Drug-specific assays often needed",CELL)], [p("Aspirin/NSAIDs",CELLB),p("Platelet dysfunction",CELL),p("↓ MA/MCF — use platelet mapping",CELL)], [p("P2Y12 inhibitors",CELLB),p("↓ platelet aggregation",CELL),p("↓ MA/MCF — ADP mapping assay",CELL)], [p("TXA / EACA",CELLB),p("Anti-fibrinolytic",CELL),p("↓ LY30/LI30 — normalises if elevated",CELL)], [p("Hypothermia <35°C",CELLB),p("Slows enzymatic reactions",CELL),p("↑ R, K · ↓ MA ⚠ TEG at 37°C underestimates!",CELL)], [p("Acute DIC",CELLB),p("Consumption + fibrinolysis",CELL),p("↑↑ R+K · ↓↓ α, MA · ↑↑ LY30",CELL)], ] E.append(mktbl(drugs,[da,db,dc])); E.append(sp(3)) half=IW/2 triad=Table([ [p("LETHAL TRIAD IN HAEMORRHAGE",S("lt",fontName="Helvetica-Bold",fontSize=7,textColor=WHITE,alignment=TA_CENTER)), p("CLINICAL CONTEXTS (strongest→emerging)",S("lc",fontName="Helvetica-Bold",fontSize=7,textColor=WHITE,alignment=TA_CENTER))], [p("<b>Hypothermia</b> &lt;35°C — impairs enzymatic clotting + platelet fx\n\n" "<b>Acidosis</b> pH &lt;7.2 — disrupts factor + platelet environment\n\n" "<b>Haemodilution</b> — dilutes factors and platelets\n\n" "<i>All three synergistic. VHA-guided correction\nsuperior to empiric 1:1:1 FFP:Plt:pRBC.</i>", S("tri",fontName="Helvetica",fontSize=7,textColor=black,leading=10,alignment=TA_LEFT)), p("<b>1.</b> Cardiac surgery (strongest RCT evidence)\n" "<b>2.</b> Major trauma / TIC\n" "<b>3.</b> Liver transplantation (hyperfibrinolysis)\n" "<b>4.</b> Obstetric PPH\n" "<b>5.</b> Neurosurgery (hypercoag detection)\n" "<b>6.</b> Massive transfusion protocol guidance\n\n" "<i>⚠ TEG ≠ ROTEM — not interchangeable.\nUse institution-specific reference ranges.</i>", S("ctx",fontName="Helvetica",fontSize=7,textColor=black,leading=10,alignment=TA_LEFT))], ],colWidths=[half,half]) triad.setStyle(TableStyle([ ("BACKGROUND",(0,0),(0,0),RED),("BACKGROUND",(1,0),(1,0),GREEN), ("BACKGROUND",(0,1),(0,1),RED_LT),("BACKGROUND",(1,1),(1,1),GREEN_LT), ("GRID",(0,0),(-1,-1),0.4,MID), ("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4), ("LEFTPADDING",(0,0),(-1,-1),5),("RIGHTPADDING",(0,0),(-1,-1),5), ("VALIGN",(0,0),(-1,-1),"TOP")])) E.append(triad); E.append(sp(3)) E.append(p("Evidence: Cochrane 2026 (35 RCTs, n=3096): TEG/ROTEM may ↓ mortality RR 0.76 (95%CI 0.63–0.92) & ↓ FFP/plt use — very low certainty | Orris Medical AI | July 2026 | Side B — Algorithm | PMID 42145275",FOOT)) return E def build(): c=pdfcanvas.Canvas(OUTPUT,pagesize=landscape(A4)) c.setTitle("TEG/ROTEM Quick Reference Theatre Card") c.setAuthor("Orris Medical AI") c.setStrokeColor(MID); c.setLineWidth(0.5) c.line(PW/2,4,PW/2,PH-4) fA=Frame(0,0,PANEL_W,PANEL_H,leftPadding=PAD,rightPadding=PAD,topPadding=PAD,bottomPadding=PAD,showBoundary=0) fA.addFromList(side_a(PANEL_W),c) fB=Frame(PANEL_W+GUTTER,0,PANEL_W,PANEL_H,leftPadding=PAD,rightPadding=PAD,topPadding=PAD,bottomPadding=PAD,showBoundary=0) fB.addFromList(side_b(PANEL_W),c) c.save() print(f"Card saved: {OUTPUT}") if __name__=="__main__": build() PYEOF echo "written"

Running Command

cd /home/daytona/workspace/coagulation-teg && python3 build_card.py 2>&1

Running Command

ls -lh /home/daytona/workspace/coagulation-teg/TEG_ROTEM_Theatre_Card.pdf

Your theatre card is ready (233 KB). Download here:

TEG ROTEM Theatre Card

PDF Document · PDF


How to use it:
  1. Print on A4 paper, landscape orientation, at 100% scale
  2. Cut along the centre line (marked with a thin grey rule)
  3. Laminate each half - you get two A5-landscape cards

What's on each side:
Side A - Parameters
  • Annotated TEG trace diagram (R · K · α · MA · LY30 labelled)
  • Full TEG parameters table with normal ranges and immediate actions
  • TEG ↔ ROTEM equivalents table
  • Colour-coded ROTEM reagent key (EXTEM · INTEM · FIBTEM · APTEM)
Side B - Algorithm
  • Goal-directed intervention table: VHA finding → likely defect → TEG parameter → ROTEM parameter → what to give (colour-coded rows: green=FFP, amber=cryo, red=TXA, purple=mixed deficit)
  • Drug and condition effects on VHA (heparin, warfarin, DOACs, aspirin, P2Y12 inhibitors, TXA, hypothermia, DIC)
  • Lethal triad summary with clinical context priority list
  • Evidence footnote from Cochrane 2026 (PMID: 42145275)

Generate a 30 marks answer for Postgraduate Anaesthesia exam on the topic of Ultrasound in Anaesthesia with diagrams

Reading File
Finding Sources
Finding Sources
Searching PubMed

ultrasound guided regional anesthesia outcomes

Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Finding Sources
Reading File
Loading Image
Loading Image
Loading Image
Loading Image
Loading Image
I now have extensive content and real textbook images from Miller's Anesthesia. Let me now write the comprehensive exam answer.

Ultrasound in Anaesthesia

Postgraduate Anaesthesia Examination Answer (30 Marks)


1. Introduction (2 marks)

Ultrasound has transformed anaesthetic practice over the past three decades, shifting it from landmark-based, empirical technique to real-time, image-guided precision. Its applications span the entire perioperative period: preoperative assessment, vascular access, regional anaesthesia, airway management, haemodynamic monitoring, and critical care. The result is improved procedural success rates, reduced complications, and better patient outcomes. Proficiency in point-of-care ultrasound (POCUS) is now considered a core competency for anaesthetists.

2. Physics of Ultrasound (4 marks)

2.1 Basic Principles

Ultrasound uses sound waves with frequencies above 20 kHz - clinical imaging uses 2-15 MHz. The fundamental relationship governing resolution and penetration is:
Wave speed (c) = Frequency (f) × Wavelength (λ)
In soft tissue, sound travels at approximately 1540 m/s. The transducer acts both as emitter and receiver (pulse-echo principle).
Key trade-off:
  • High frequency (10-15 MHz): Superior spatial resolution, poor tissue penetration (shallow structures - nerve blocks, vascular access)
  • Low frequency (2-5 MHz): Poor resolution, deep penetration (cardiac, abdominal, deep vessels)

2.2 Piezoelectric Effect

The piezoelectric crystal within the transducer converts electrical energy into sound waves (transmit) and back into electrical signals (receive). This crystal deforms when voltage is applied, generating pressure waves, and generates voltage when deformed by returning echoes.

2.3 Image Generation

Returning echoes are processed according to their:
  • Amplitude (brightness - creating the B-mode greyscale image)
  • Time of arrival (used to calculate depth: depth = c × time/2)
Echogenicity terminology:
TermAppearanceExample
HyperechoicBright whiteBone cortex, needle, fascia
HypoechoicDark greyMuscle, nerve, solid organ
AnechoicBlackFluid (blood, urine, effusion)
IsoechoicSame as surrounding tissueThrombus (fresh)

2.4 Imaging Modes

ModeDescriptionClinical Use in Anaesthesia
B-mode (2D)Brightness-based greyscale cross-sectionStandard imaging for all procedures
M-modeSingle-line motion over timeLung sliding ("seashore sign"), IVC diameter
Colour DopplerDirection and velocity of flow (colour-coded)Distinguish vein from artery
Pulsed wave DopplerFlow velocity at a specific depthCardiac output, stenosis grading
Power DopplerSensitive low-flow detectionConfirm vessel patency

2.5 Artefacts

Understanding artefacts is essential to avoid misinterpretation:
ArtefactCauseSignificance
Acoustic shadowingBone/air blocks beamConfirms calcification or gas
Posterior acoustic enhancementFluid transmits beamConfirms fluid-filled structure
Reverberation / A-linesRepeated reflections between two surfacesNormal lung; horizontal bright parallel lines
B-lines (comet tail)Fluid in interlobular septaPulmonary oedema, ARDS
Mirror artefactStrong reflector duplicates imageDiaphragm-liver interface
AnisotropyAngle-dependent reflectance of tendons/nervesNerve appears less echogenic off-axis

3. Needle Guidance Techniques (2 marks)

Two principal approaches exist for needle insertion under ultrasound guidance:
In-plane (longitudinal approach):
  • Needle inserted parallel to the transducer's long axis
  • Entire needle shaft and tip visualised as a hyperechoic line
  • Preferred for nerve blocks (full needle course visible, safer)
Out-of-plane (transverse approach):
  • Needle inserted perpendicular to the probe
  • Only needle tip (or shaft cross-section) seen as a bright dot
  • Risk of mistaking shaft for tip - "tip tracking" techniques required
  • Preferred for central venous cannulation (short access distance)
Needle echogenicity is enhanced by: echogenic coatings, stylets, increased needle gauge, and oblique cutting of the bevel.

4. Vascular Access (5 marks)

4.1 Central Venous Cannulation

Ultrasound-guided central venous catheterisation (CVC) is now the standard of care, with level 1B evidence from the European Society of Anaesthesiology. The Agency for Healthcare Research and Quality (AHRQ) lists ultrasound as one of 11 practices clinicians should adopt for central venous access. (Miller's Anesthesia 10e)
Internal jugular vein (IJV):
  • Probe placed transversely at the level of the thyroid cartilage
  • IJV: compressible, oval, lateral to the common carotid artery
  • Carotid artery: non-compressible, round, pulsatile, with colour Doppler confirming arterial flow
  • The out-of-plane approach is most commonly used; the in-plane approach visualises the entire needle course
Key advantages:
  • Reduces arterial puncture risk from ~6.3% (landmark) to <1%
  • Reduces haematoma, pneumothorax, and overall complication rate
  • Particularly beneficial in: obesity, coagulopathy, abnormal anatomy, previously attempted sites
  • Subclavian approach - linear probe in infraclavicular fossa; ultrasound guidance reduces pneumothorax risk but is technically more demanding
  • Femoral approach - useful in coagulopathic patients; ultrasound identifies femoral vein medial to femoral artery

4.2 Arterial Cannulation

Systematic review of 11 RCTs comparing radial artery cannulation with and without ultrasound: significantly improved first-attempt success and reduced total attempts in the ultrasound-guided group. (Miller's Anesthesia 10e)
Additional benefit: absence of Doppler flow in the superficial palmar branch on radial occlusion indicates inadequate ulnar collateral circulation - a contraindication to radial cannulation.

4.3 Peripheral Venous Access

Ultrasound-guided peripheral IV access is invaluable in patients with difficult peripheral access (obesity, scar tissue, prior cannulation, intravenous drug use). Long-axis in-plane technique preferred; 18G-20G cannulae inserted into the basilic or cephalic vein of the upper arm.

5. Ultrasound-Guided Regional Anaesthesia (6 marks)

5.1 Historical Context and Evidence

La Grange et al. reported the first use of ultrasound for neural blockade in 1978. Since then, ultrasound-guided nerve blocks have become standard practice, shown to be quicker, more precise, with lower complication rates and higher patient satisfaction. They have transformed enhanced recovery after surgery (ERAS) pathways, reduced length of hospital stay, and improved outcomes. (Miller's Anesthesia 10e)
A 2009 systematic review and meta-analysis comparing ultrasound guidance with electrical neurostimulation for peripheral nerve blocks demonstrated reduced block performance time, improved block quality, and reduced complications with ultrasound (Br J Anaesth. 2009;102:408-417, cited in Miller's Anesthesia 10e).

5.2 Advantages over Nerve Stimulator Technique

FeatureNerve StimulatorUltrasound Guided
Real-time visualisationNoYes
Needle-nerve relationshipIndirect (electrical)Direct visual
Local anaesthetic spreadNot seenVisualised in real time
Intravascular injection detectionNoYes (Doppler)
Intraneural injection warningNoYes (nerve swelling)
Deep block accuracyVariableImproved
Effectiveness in patients with neuropathyReducedMaintained

5.3 Nerve Sonoanatomy

Nerve appearance on ultrasound: Nerves appear as honeycomb structures in cross-section - multiple round hypoechoic fascicles surrounded by hyperechoic perineurium and epineurium. In longitudinal section they appear as parallel echogenic lines ("tram tracks"). Anisotropy must be considered - nerves appear less echogenic when the beam is not perpendicular to them.

5.4 Common Blocks in Anaesthetic Practice

Upper limb:
  • Interscalene brachial plexus block - roots C5/C6/C7 visualised between anterior and middle scalene muscles at C6 level. Used for shoulder surgery. Risk: phrenic nerve paralysis (ipsilateral hemidiaphragm palsy in 100% - avoid bilateral or in severe respiratory compromise).
  • Supraclavicular block - trunks/divisions of brachial plexus at the first rib, around the subclavian artery. "Cluster of grapes" appearance. Dense forearm and hand block.
  • Infraclavicular block - cords around the axillary artery in the infraclavicular fossa. Lateral, posterior, medial cords identified at 9, 6, and 3 o'clock positions respectively.
  • Axillary block - terminal branches (radial, ulnar, median, musculocutaneous) identified around the axillary artery. Multiple injections required.
Lower limb:
  • Femoral nerve block - nerve lies lateral to femoral artery, deep to fascia iliaca. Used for hip fracture analgesia, anterior knee surgery.
  • Adductor canal block (ACB) - saphenous nerve in the adductor canal, mid-thigh. Motor-sparing alternative to femoral nerve block for knee arthroplasty analgesia - preserves quadriceps strength.
  • Popliteal sciatic nerve block - sciatic nerve bifurcation above the popliteal crease. Used for foot/ankle surgery.
Truncal blocks:
  • Transversus abdominis plane (TAP) block - local anaesthetic deposited between internal oblique and transversus abdominis muscles. Provides somatic (not visceral) analgesia for abdominal wall; T7-L1 coverage depending on approach.
  • Erector spinae plane (ESP) block - injection into the plane deep to erector spinae, over transverse process. Covers both somatic and visceral pain via paravertebral spread. Used for thoracic, abdominal, and rib fracture analgesia.
  • Serratus anterior plane (SAP) block - between serratus anterior and either the latissimus dorsi (superficial) or the ribs (deep). T2-T9 coverage - used for thoracic surgery, rib fractures, mastectomy.
  • Rectus sheath block - between rectus abdominis and posterior rectus sheath. Bilateral blocks provide midline abdominal wall analgesia.

5.5 Local Anaesthetic Systemic Toxicity (LAST) Prevention

Real-time visualisation of local anaesthetic spread, combined with aspiration before injection, allows detection of intravascular needle placement. Colour Doppler confirms vascular proximity. Reduced volumes of local anaesthetic are required with ultrasound guidance (precise placement reduces the need for high volumes), thereby lowering LAST risk.

6. Point-of-Care Cardiac Ultrasound (POCUS) (5 marks)

6.1 Focused Cardiac Ultrasound (FoCUS)

FoCUS is a targeted, binary (yes/no) cardiac assessment performed by the anaesthetist at the bedside - distinct from formal echocardiography performed by cardiologists. It answers specific clinical questions and guides immediate management.
Core FoCUS views:
ViewProbe PositionStructures Assessed
Parasternal long axis (PLAX)Left parasternal, 3rd/4th ICSLV size, wall motion, MV, AV, pericardial effusion
Parasternal short axis (PSAX)Left parasternal, rotated 90°LV end-diastolic area, RV:LV ratio, wall motion
Apical 4-chamberCardiac apexBiventricular size and function, valves, effusion
Subcostal 4-chamberSubxiphoidRV/LV, pericardial effusion (tamponade), IVC
IVC long axisSubcostalVolume status: IVC collapsibility >50% = hypovolaemia
Four-chamber subcostal echocardiographic view showing right ventricle (S) and left ventricle (K)
Fig. 1 - Subcostal echocardiographic view: S = stomach/right ventricle side, K = left ventricle. Used to assess biventricular function and pericardial effusion. (Miller's Anesthesia 10e)

6.2 Clinical Applications of FoCUS in Anaesthesia

Preoperative:
  • Rapid assessment of ventricular function before emergency/urgent surgery
  • Detection of pericardial effusion or tamponade
  • Preoperative cardiac risk stratification (hip fracture patients - delay for echocardiography associated with increased mortality)
  • ROSE protocol (Rapid Obstetric Screening Echocardiography) for haemodynamically unstable obstetric patients
Intraoperative:
  • Feasible in >90% of surgical cases (Miller's Anesthesia 10e)
  • Impacts management in 22-66% of intraoperative uses
  • Differentiation of shock subtypes (hypovolaemic, cardiogenic, distributive, obstructive)
  • Detection of acute right heart strain (pulmonary embolism - D-shaped interventricular septum)
  • Monitoring response to fluid resuscitation
Perioperative haemodynamic assessment:
  • IVC diameter and collapsibility: IVC <1.5 cm with >50% inspiratory collapse = hypovolaemia; IVC >2.5 cm with <25% collapse = volume overload / raised CVP
  • LV end-diastolic area (LVEDA): Reduced (<10 cm²) = hypovolaemia ("kissing ventricles" in severe hypovolaemia); elevated = volume overload or poor function
  • Visually estimated LVEF: Reduced (<30%) = severe cardiogenic dysfunction

6.3 Transoesophageal Echocardiography (TOE)

TOE provides superior image quality compared to transthoracic echo due to proximity of the transducer to the heart. Performed under GA or deep sedation. It is the gold standard for:
  • Intraoperative cardiac surgical monitoring
  • Assessment of aortic disease, valve pathology
  • Detection of intracardiac thrombus/air
  • Monitoring after cardiopulmonary bypass (assessment of de-airing)

7. Lung Ultrasound (3 marks)

7.1 Principles

Normal aerated lung reflects ultrasound at the pleural interface, generating characteristic artefacts.
Lung ultrasound showing A-lines (normal), Z-lines, lung point (pneumothorax), and pathological B-lines (pulmonary oedema)
Fig. 2 - Lung ultrasound findings. (A) A-lines: horizontal repetitive artefacts - normal aeration. (B) Z-lines: short B-lines, often normal. (C) Lung point: highly specific for pneumothorax - transition between sliding and non-sliding. (D) Pathological B-lines: comet-tail artefacts indicating interstitial fluid (pulmonary oedema). (Miller's Anesthesia 10e)
Key findings:
FindingAppearanceSignificance
A-linesHorizontal regularly spaced bright linesNormal lung - aeration present
Lung slidingShimmering motion at pleural linePleural surfaces in apposition (normal)
B-lines ("rockets")Vertical comet-tail artefacts reaching screen edgeInterstitial fluid: pulmonary oedema, ARDS
Lung pointTransition between sliding and non-slidingHighly specific for pneumothorax
Absent lung slidingNo pleural movementPneumothorax, apnoea, mainstem intubation
"Seashore sign" (M-mode)Granular pattern below pleural lineNormal lung sliding present
"Barcode sign" (M-mode)Parallel lines throughoutPneumothorax (absent lung sliding)
M-mode lung ultrasound: seashore sign (normal lung sliding, A) versus barcode sign (pneumothorax, B)
Fig. 3 - M-mode lung ultrasound. (A) Normal "seashore sign" - granular pattern below pleural line indicates lung sliding. (B) Absence of seashore pattern in pneumothorax. (Miller's Anesthesia 10e)

7.2 Pneumothorax Detection

Lung ultrasound predicts absence of pneumothorax with 93.8% sensitivity and 99.9% negative predictive value, superior to chest X-ray. (Miller's Anesthesia 10e). The lung point is pathognomonic for pneumothorax - the precise transition point between free air and lung contact.

7.3 eFAST (Extended Focused Assessment with Sonography for Trauma)

eFAST extends the traditional FAST exam (abdominal free fluid) to include thoracic assessment.
eFAST probe positions: A = subcostal (pericardium), B = left upper quadrant, C = pelvic, D = right upper quadrant, E = thoracic/lung
Fig. 4 - eFAST exam probe positions. A = subcostal (pericardial effusion), B = left upper quadrant, C = pelvic (free fluid), D = right upper quadrant (Morrison's pouch), E = thoracic (pneumothorax/haemothorax). (Miller's Anesthesia 10e)
eFAST components:
  • Pericardial view (subcostal): pericardial effusion, tamponade
  • Right upper quadrant (Morrison's pouch): hepatorenal free fluid
  • Left upper quadrant (splenorenal): free fluid
  • Pelvic view (bladder): pelvic free fluid
  • Bilateral thoracic views: haemothorax (anechoic fluid above diaphragm), pneumothorax (absent lung sliding)

8. Airway Assessment (2 marks)

8.1 Gastric Ultrasound

A full stomach is defined as identification of solid food or presence of more than 1.5 mL/kg of clear liquid calculated by measuring the gastric antral cross-sectional area (CSA). The formula used is:
Gastric volume (mL) = 27.0 + 14.6 × right-lateral CSA − 1.28 × age
Solid content appears as heterogeneous, echogenic material with posterior acoustic shadowing ("frosted glass" appearance). Clear fluid appears anechoic. This assessment is particularly valuable in emergency surgery where aspiration risk is uncertain (trauma patients, delayed gastric emptying, uncertain fasting status).

8.2 Tracheal/Laryngeal Ultrasound

  • Identifies tracheal midline for confirmation of endotracheal tube position (bilateral lung sliding confirms bilateral ventilation)
  • Detects supraglottic structures for awake intubation planning
  • Measures subglottic diameter to guide endotracheal tube selection (particularly in paediatric anaesthesia)
  • Identifies cricothyroid membrane for emergency front-of-neck access (FONA) - the CTM is located between the thyroid and cricoid cartilages as a hypoechoic gap between two hyperechoic cartilaginous structures

9. Limitations, Training and Governance (2 marks)

9.1 Limitations

  • Operator dependency: Image quality and interpretation are directly proportional to skill
  • Acoustic windows: Obesity, subcutaneous emphysema, and dressings impair imaging
  • Learning curve: Requires dedicated structured training; misinterpretation can cause harm (e.g., mistaking a thrombus for patent vessel, intraneural injection not prevented)
  • Equipment: High-quality machines are expensive; portable devices have limitations
  • POCUS does not replace formal echocardiography - a negative focused assessment does not exclude all cardiac pathology
  • Anaesthetic interference: General anaesthesia, positive pressure ventilation, and the sterile surgical field complicate intraoperative use
  • No standardisation: TEE values and POCUS reference ranges vary between institutions

9.2 Training and Competency

The Association of Anaesthetists of Great Britain and Ireland (AAGBI) and British Society of Echocardiography (BSE) have published guidelines for credentialing. Levels of competency range from:
  • Level 1: Basic POCUS (cardiac, lung, vascular access) - expected of all anaesthetists
  • Level 2: Advanced perioperative echocardiography
  • Level 3: Expert / diagnostic TOE for complex cardiac surgery
Barriers to adoption include lack of training (most commonly cited), lack of equipment, and absence of formal credentialling pathways. (Miller's Anesthesia 10e)

10. Summary Table (marks incorporated above)

ApplicationProbeFrequencyKey Benefit
Central venous access (IJV)Linear10-15 MHz↓ arterial puncture, ↓ pneumothorax
Arterial cannulationLinear10-15 MHz↑ first-attempt success
Nerve blocks (superficial)Linear10-15 MHzDirect visualisation, ↓ LAST
Nerve blocks (deep - e.g., femoral)Curved/Linear5-10 MHzDepth penetration
Cardiac (FoCUS/TOE)Phased array2-5 MHzHaemodynamic assessment
LungCurved/Linear2-10 MHzPneumothorax, effusion, oedema
Gastric assessmentCurved2-5 MHzAspiration risk
Airway/CTMLinear10-15 MHzFONA planning

References

  • Miller RD et al. Miller's Anesthesia, 10th ed. Elsevier, 2023 - Chapter 33 (Monitoring), Chapter 42 (Regional Anaesthesia)
  • Barash PG et al. Clinical Anesthesia, 9th ed. Wolters Kluwer, 2022
  • European Society of Anaesthesiology Guidelines for Central Venous Access (1B evidence for IJV ultrasound guidance)
  • Agency for Healthcare Research and Quality. Making Health Care Safer - 11 practices including ultrasound for CVC
  • Koscielniak-Nielsen ZJ. Ultrasound-guided peripheral nerve blocks: what are the benefits? Acta Anaesthesiol Scand. 2008
  • Pietroski Dos Santos N et al. Systemic review with meta-analysis: long-acting vs mixed local anaesthetics for US-guided peripheral nerve blocks. Reg Anesth Pain Med. 2026 [PMID: 39779278]
  • La Grange P, Foster PA, Pretorius LK. Application of the Doppler ultrasound blood-flow detector. Br J Anaesth. 1978

Write a 30 marks answer for Postgraduate Anaesthesia exam on the topic of Capnography and Capnometry

Your credits are exhausted. You can purchase a top-up or subscribe to a plan to continue using Orris. If you're already subscribed, your daily credits will reset tomorrow.
This is a shared conversation. Sign in to Orris to start your own chat.