Give in detail of pseudoaneurism radiology for Ppt presentation
pseudoaneurysm radiology imaging features ultrasound CT angiography diagnosis treatment 2024
https://pmc.ncbi.nlm.nih.gov/articles/PMC10716566
mkdir -p /tmp/workspace/pseudoaneurysm-ppt && ls /tmp/workspace/
~/pseudoaneurysm-ppt/build_ppt.py
import subprocess, json, base64
from io import BytesIO
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.oxml.ns import qn
from lxml import etree
# ── Colour palette (radiology/dark academic theme) ──────────────────────────
DARK_BG = RGBColor(0x0D, 0x1B, 0x2A) # deep navy
MID_BG = RGBColor(0x1A, 0x2E, 0x44) # mid navy
ACCENT = RGBColor(0x00, 0xB4, 0xD8) # cyan
ACCENT2 = RGBColor(0x90, 0xE0, 0xEF) # light cyan
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
YELLOW = RGBColor(0xFF, 0xD1, 0x66)
ORANGE = RGBColor(0xFF, 0x85, 0x3A)
LIGHT_GRAY= RGBColor(0xCC, 0xD6, 0xE0)
W = Inches(13.333)
H = Inches(7.5)
prs = Presentation()
prs.slide_width = W
prs.slide_height = H
blank = prs.slide_layouts[6]
# ── helpers ──────────────────────────────────────────────────────────────────
def bg(slide, color):
"""Fill slide background with solid colour."""
background = slide.background
fill = background.fill
fill.solid()
fill.fore_color.rgb = color
def rect(slide, x, y, w, h, color, alpha=None):
shape = slide.shapes.add_shape(1, x, y, w, h)
shape.fill.solid()
shape.fill.fore_color.rgb = color
shape.line.fill.background()
return shape
def tb(slide, text, x, y, w, h,
size=18, bold=False, color=WHITE, align=PP_ALIGN.LEFT,
italic=False, wrap=True):
box = slide.shapes.add_textbox(x, y, w, h)
tf = box.text_frame
tf.word_wrap = wrap
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
p = tf.paragraphs[0]
p.alignment = align
r = p.add_run()
r.text = text
r.font.name = "Calibri"
r.font.size = Pt(size)
r.font.bold = bold
r.font.italic = italic
r.font.color.rgb = color
return box
def multi_para(slide, lines, x, y, w, h,
size=16, bold=False, color=WHITE, bullet=True, spacing=1.15):
"""Add multiple bullet lines to one textbox."""
box = slide.shapes.add_textbox(x, y, w, h)
tf = box.text_frame
tf.word_wrap = True
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = 0
for i, line in enumerate(lines):
p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
p.alignment = PP_ALIGN.LEFT
p.space_after = Pt(4)
r = p.add_run()
r.text = ("• " if bullet else "") + line
r.font.name = "Calibri"
r.font.size = Pt(size)
r.font.bold = bold
r.font.color.rgb = color
return box
def heading_bar(slide, title, subtitle=None):
"""Coloured top bar with title."""
rect(slide, 0, 0, W, Inches(1.1), MID_BG)
rect(slide, 0, Inches(1.1), W, Inches(0.07), ACCENT)
tb(slide, title, Inches(0.4), Inches(0.08), Inches(12), Inches(0.85),
size=32, bold=True, color=ACCENT)
if subtitle:
tb(slide, subtitle, Inches(0.4), Inches(0.72), Inches(12), Inches(0.4),
size=16, color=ACCENT2)
def add_image_from_url(slide, url, x, y, w, h):
result = json.loads(subprocess.check_output(
["python", "/tmp/skills/shared/scripts/fetch_images.py", url]
))
if result and result[0].get("base64"):
raw = base64.b64decode(result[0]["base64"].split(",")[-1])
slide.shapes.add_picture(BytesIO(raw), x, y, w, h)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 1 — Title
# ═══════════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
bg(s, DARK_BG)
rect(s, 0, 0, W, Inches(0.07), ACCENT)
rect(s, 0, Inches(7.43), W, Inches(0.07), ACCENT)
rect(s, 0, Inches(1.5), Inches(0.12), Inches(4.5), ACCENT)
tb(s, "PSEUDOANEURYSM", Inches(0.5), Inches(1.1), Inches(12), Inches(1.4),
size=54, bold=True, color=ACCENT, align=PP_ALIGN.LEFT)
tb(s, "Radiology — Imaging, Diagnosis & Interventional Management",
Inches(0.5), Inches(2.55), Inches(12), Inches(0.7),
size=24, color=ACCENT2, align=PP_ALIGN.LEFT)
tb(s, "Comprehensive Radiological Review",
Inches(0.5), Inches(3.35), Inches(9), Inches(0.5),
size=18, color=LIGHT_GRAY, italic=True, align=PP_ALIGN.LEFT)
# right accent panel
rect(s, Inches(10.5), Inches(1.5), Inches(2.7), Inches(5.5), MID_BG)
for label, val in [("Modalities Covered", "US · CT · MRI · DSA"),
("Locations", "Peripheral · Visceral · Aortic"),
("Treatment", "Compression · Thrombin · Embolization · Stent")]:
idx = [("Modalities Covered", "US · CT · MRI · DSA"),
("Locations", "Peripheral · Visceral · Aortic"),
("Treatment", "Compression · Thrombin · Embolization · Stent")].index((label,val))
tb(s, label, Inches(10.65), Inches(1.75 + idx*1.55), Inches(2.5), Inches(0.4),
size=11, color=YELLOW, bold=True)
tb(s, val, Inches(10.65), Inches(2.15 + idx*1.55), Inches(2.5), Inches(0.7),
size=13, color=WHITE, wrap=True)
tb(s, "Sources: Grainger & Allison's Diagnostic Radiology · Textbook of Clinical Echocardiography · StatPearls · PMC 2023",
Inches(0.5), Inches(6.9), Inches(10), Inches(0.5),
size=10, color=LIGHT_GRAY, italic=True)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 2 — Definition & Anatomy
# ═══════════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
bg(s, DARK_BG)
heading_bar(s, "Definition & Pathophysiology")
# Left column — definition
rect(s, Inches(0.3), Inches(1.35), Inches(6.1), Inches(5.8), MID_BG)
tb(s, "What is a Pseudoaneurysm?", Inches(0.5), Inches(1.45), Inches(5.7), Inches(0.5),
size=20, bold=True, color=YELLOW)
multi_para(s, [
"A pulsatile haematoma that communicates with the arterial lumen through a defect in the arterial wall",
"LACKS all three layers of the true arterial wall (intima, media, adventitia)",
"Contained by surrounding soft tissue, connective tissue, or haematoma",
"Distinct from a TRUE aneurysm — which involves full-thickness dilation of all three walls",
], Inches(0.5), Inches(2.0), Inches(5.7), Inches(2.5), size=15, color=WHITE)
tb(s, "Key Structural Difference", Inches(0.5), Inches(4.55), Inches(5.7), Inches(0.4),
size=16, bold=True, color=ACCENT)
multi_para(s, [
"True Aneurysm: full-wall dilation — intima + media + adventitia all present",
"Pseudoaneurysm: wall breach — contained only by perivascular tissue / clot",
"Higher risk of rupture due to absent elastic wall support",
], Inches(0.5), Inches(5.0), Inches(5.7), Inches(1.8), size=14, color=LIGHT_GRAY)
# Right column — causes
rect(s, Inches(6.7), Inches(1.35), Inches(6.3), Inches(5.8), MID_BG)
tb(s, "Aetiology / Risk Factors", Inches(6.9), Inches(1.45), Inches(5.9), Inches(0.5),
size=20, bold=True, color=YELLOW)
categories = [
("Iatrogenic (Most Common)", ["Arterial catheterisation (femoral, radial, brachial)", "Post-surgical anastomosis", "Percutaneous biopsy / nephrostomy", "Post-pancreatectomy haemorrhage"]),
("Traumatic", ["Penetrating trauma (stab, gunshot)", "Blunt abdominal trauma", "Renal trauma — more common in penetrating"]),
("Infectious / Mycotic", ["Bacterial endocarditis", "Septic emboli", "Post-pancreatic pseudocyst erosion"]),
("Spontaneous / Inflammatory", ["Pancreatitis eroding visceral arteries", "Tumour invasion", "Connective tissue disorders"]),
]
y_pos = 2.1
for cat, items in categories:
tb(s, cat, Inches(6.9), Inches(y_pos), Inches(5.9), Inches(0.4),
size=14, bold=True, color=ACCENT2)
y_pos += 0.42
for item in items:
tb(s, " • " + item, Inches(6.9), Inches(y_pos), Inches(5.9), Inches(0.35),
size=12, color=WHITE)
y_pos += 0.33
y_pos += 0.1
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 3 — Clinical Features
# ═══════════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
bg(s, DARK_BG)
heading_bar(s, "Clinical Presentation")
boxes = [
("Superficial / Peripheral PSA", ACCENT, [
"Painful, pulsatile mass",
"Usually within 24 h of arterial access",
"Bruit / thrill over the site",
"Expanding haematoma",
"Overlying skin erythema or bruising",
]),
("Visceral / Deep PSA", ORANGE, [
"Abdominal or back pain",
"GI bleeding (haemobilia, melaena)",
"Obstructive jaundice (hepatic PSA)",
"Haematuria (renal PSA)",
"Haemodynamic instability if ruptured",
]),
("Aortic PSA", YELLOW, [
"Chest / back pain",
"Pulsatile abdominal mass",
"Lower limb ischaemia",
"Dysphagia / stridor if mediastinal",
"Catastrophic bleeding on rupture",
]),
("Complications", RGBColor(0xFF,0x4D,0x4D), [
"Rupture — most feared, potentially fatal",
"Compression of adjacent structures",
"Distal embolism / thrombosis",
"Fistula formation (AV or visceral)",
"Infection / sepsis",
]),
]
for i, (title, col, items) in enumerate(boxes):
col_x = Inches(0.3 + i * 3.25)
rect(s, col_x, Inches(1.3), Inches(3.1), Inches(5.9), MID_BG)
rect(s, col_x, Inches(1.3), Inches(3.1), Inches(0.5), col)
tb(s, title, col_x + Inches(0.1), Inches(1.33), Inches(2.9), Inches(0.45),
size=13, bold=True, color=DARK_BG if col != RGBColor(0xFF,0x4D,0x4D) else WHITE, align=PP_ALIGN.CENTER)
multi_para(s, items, col_x + Inches(0.12), Inches(1.9), Inches(2.85), Inches(5.0),
size=13, color=WHITE)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 4 — Ultrasound (B-mode + Doppler)
# ═══════════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
bg(s, DARK_BG)
heading_bar(s, "Ultrasound Imaging — B-mode & Colour Doppler")
rect(s, Inches(0.3), Inches(1.35), Inches(7.8), Inches(5.8), MID_BG)
tb(s, "B-mode Ultrasound", Inches(0.5), Inches(1.45), Inches(7.5), Inches(0.45),
size=20, bold=True, color=ACCENT)
multi_para(s, [
"Anechoic or hypoechoic rounded / oval collection adjacent to the artery",
"May appear as an intra-renal or perivascular 'cyst'",
"Swirling internal echoes visible (blood in motion = B-flow artefact)",
"Partial thrombosis appears as hyperechoic material within the sac",
"Narrow communicating neck connects sac to parent artery",
], Inches(0.5), Inches(1.95), Inches(7.5), Inches(2.2), size=14, color=WHITE)
tb(s, "Colour Doppler — Pathognomonic Signs", Inches(0.5), Inches(4.2), Inches(7.5), Inches(0.45),
size=20, bold=True, color=ACCENT)
signs = [
("Yin-Yang Sign", "Turbulent swirling flow in the sac — alternating red/blue colour on CDI; bidirectional vortex"),
("To-and-Fro Sign", "Spectral Doppler at the neck: 'to' = forward flow (systole, into sac); 'fro' = reverse flow (diastole, out of sac)"),
("Arterialised Waveform", "High-resistance pulsatile signal at the neck distinguishes PSA from AVM/cyst"),
]
y = 4.72
for name, desc in signs:
rect(s, Inches(0.5), Inches(y), Inches(2.1), Inches(0.75), ACCENT)
tb(s, name, Inches(0.55), Inches(y+0.1), Inches(1.95), Inches(0.55),
size=13, bold=True, color=DARK_BG, align=PP_ALIGN.CENTER)
tb(s, desc, Inches(2.7), Inches(y+0.05), Inches(5.2), Inches(0.65),
size=12, color=WHITE, wrap=True)
y += 0.88
# Right — echo image (aortic PSA TEE)
tb(s, "TEE: Aortic Pseudoaneurysm", Inches(8.25), Inches(1.38), Inches(4.8), Inches(0.45),
size=16, bold=True, color=ACCENT2, align=PP_ALIGN.CENTER)
add_image_from_url(s,
"https://cdn.orris.care/cdss_images/bc9f2422dd421e8b303194b4cc8fe863448904f286733829dc2439e32da8b6dc.png",
Inches(8.2), Inches(1.85), Inches(4.9), Inches(3.8))
tb(s, "TEE long-axis: disruption of posterior aortic sinus of Valsalva forming a PSA (long arrow) between Ao and LA. From: Textbook of Clinical Echocardiography.",
Inches(8.2), Inches(5.7), Inches(4.9), Inches(1.2),
size=10, color=LIGHT_GRAY, italic=True, wrap=True)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 5 — CT Angiography
# ═══════════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
bg(s, DARK_BG)
heading_bar(s, "CT Angiography — The Imaging Modality of Choice")
# Left panel — text
rect(s, Inches(0.3), Inches(1.35), Inches(6.2), Inches(5.8), MID_BG)
tb(s, "Why CTA?", Inches(0.5), Inches(1.5), Inches(5.9), Inches(0.4),
size=18, bold=True, color=YELLOW)
multi_para(s, [
"Sensitivity ~90–95% and specificity ~98.7–100% for arterial injury",
"Precisely defines PSA size, shape, neck, and feeding artery",
"Characterises surrounding structures and non-vascular injuries",
"Guides endovascular treatment planning",
], Inches(0.5), Inches(1.95), Inches(5.9), Inches(1.6), size=14, color=WHITE)
tb(s, "CT Phases & Findings", Inches(0.5), Inches(3.6), Inches(5.9), Inches(0.45),
size=18, bold=True, color=ACCENT)
phases = [
("Non-contrast", "Low-attenuation rounded mass adjacent to artery; intermediate/high-density adjacent haematoma if ruptured; high attenuation within sac = thrombosis"),
("Arterial phase", "Contrast-filled sac = classic finding; pseudoaneurysm is rounded or oval and HIGH density (isodense to aorta); active extravasation = 'blush'"),
("Portal venous / delayed", "Sac becomes ISODENSE to surrounding tissue — differentiates from true active bleeding; partial thrombosis = residual low-attenuation zone"),
("Max. Intensity Projection", "MIP reconstructions best depict neck, feeding artery, and 3-D relationship to vital structures"),
]
y = 4.1
for phase, desc in phases:
rect(s, Inches(0.5), Inches(y), Inches(1.6), Inches(0.7), ACCENT)
tb(s, phase, Inches(0.55), Inches(y+0.05), Inches(1.5), Inches(0.6),
size=11, bold=True, color=DARK_BG, align=PP_ALIGN.CENTER)
tb(s, desc, Inches(2.2), Inches(y+0.03), Inches(4.1), Inches(0.66),
size=11, color=WHITE, wrap=True)
y += 0.79
# Right — CT image (renal PSA)
tb(s, "CT: Traumatic Renal Pseudoaneurysm", Inches(6.75), Inches(1.38), Inches(6.3), Inches(0.45),
size=16, bold=True, color=ACCENT2, align=PP_ALIGN.CENTER)
add_image_from_url(s,
"https://cdn.orris.care/cdss_images/4bd3fc14c7fddfe5b1ac9e6a54c8440ce1dd714c6eb7e8503254b9a2f4c139ab.png",
Inches(6.7), Inches(1.85), Inches(6.35), Inches(3.6))
tb(s,
"(A) Non-contrast: large perinephric haematoma (★). "
"(B) Arterial phase: high-density pseudoaneurysm (arrow) — isodense to aorta. "
"(C) Delayed phase: sac remains isodense. "
"Source: Grainger & Allison's Diagnostic Radiology.",
Inches(6.7), Inches(5.52), Inches(6.35), Inches(1.2),
size=10, color=LIGHT_GRAY, italic=True, wrap=True)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 6 — MRI & Conventional Angiography
# ═══════════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
bg(s, DARK_BG)
heading_bar(s, "MR Angiography & Conventional (Digital Subtraction) Angiography")
# MRA column
rect(s, Inches(0.3), Inches(1.35), Inches(6.1), Inches(5.8), MID_BG)
tb(s, "MR Angiography (MRA)", Inches(0.5), Inches(1.45), Inches(5.9), Inches(0.45),
size=22, bold=True, color=ACCENT)
mra_points = [
"3D gadolinium-enhanced MRA clearly demonstrates the PSA sac",
"T1-weighted imaging: intraluminal thrombus appears hyperintense",
"T2-weighted imaging: patent sac shows flow signal; thrombosed areas hypointense",
"No ionising radiation — ideal for young patients, allergy to iodine, renal impairment",
"LIMITATIONS: time-consuming; not suitable for acute/traumatic emergencies",
"Claustrophobia limits use; metallic artefacts reduce quality",
"Motion artefact is a concern in deep visceral PSA",
]
multi_para(s, mra_points, Inches(0.5), Inches(2.0), Inches(5.7), Inches(3.8), size=14, color=WHITE)
tb(s, "Indications for MRA over CTA", Inches(0.5), Inches(5.85), Inches(5.7), Inches(0.4),
size=15, bold=True, color=YELLOW)
multi_para(s, [
"Contrast allergy / chronic kidney disease",
"Pregnancy (avoid radiation; gadolinium with caution in 2nd/3rd trimester)",
"Follow-up of known PSA without need for immediate intervention",
], Inches(0.5), Inches(6.27), Inches(5.7), Inches(1.0), size=13, color=LIGHT_GRAY)
# DSA column
rect(s, Inches(6.7), Inches(1.35), Inches(6.3), Inches(5.8), MID_BG)
tb(s, "Conventional Angiography (DSA)", Inches(6.9), Inches(1.45), Inches(6.1), Inches(0.45),
size=22, bold=True, color=ORANGE)
dsa_points = [
"GOLD STANDARD — highest sensitivity and spatial resolution",
"Detects PSA not visible on US, CT, or MRA",
"Fully characterises: neck size/length, sac morphology, feeding artery, collaterals",
"Essential for planning of embolisation, stent placement, or surgical ligation",
"Allows simultaneous diagnosis AND endovascular treatment in one sitting",
]
multi_para(s, dsa_points, Inches(6.9), Inches(1.95), Inches(6.0), Inches(2.6), size=14, color=WHITE)
tb(s, "DSA Findings in PSA", Inches(6.9), Inches(4.6), Inches(6.0), Inches(0.45),
size=16, bold=True, color=ACCENT)
multi_para(s, [
"Opacification of sac communicating with donor artery via a narrow neck",
"Delayed washout of contrast from the sac",
"Associated AV fistula: early venous filling",
"Active extravasation: contrast 'blush' outside sac = rupture",
], Inches(6.9), Inches(5.1), Inches(6.0), Inches(1.8), size=13, color=WHITE)
tb(s, "Limitations: Invasive; contrast and radiation use; risk of access-site complication; not first-line unless treatment planned.",
Inches(6.9), Inches(6.8), Inches(6.1), Inches(0.55),
size=11, color=LIGHT_GRAY, italic=True, wrap=True)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 7 — Anatomical Locations
# ═══════════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
bg(s, DARK_BG)
heading_bar(s, "Anatomical Locations — Peripheral, Visceral & Aortic")
locs = [
("PERIPHERAL", ACCENT, [
"Femoral (most common overall)",
" — Post-catheterisation / cardiac cath",
" — Duplex US: gold standard for diagnosis",
" — Sensitivity 100% (StatPearls 2024)",
"Radial / brachial artery",
" — Increasing incidence with transradial PCI",
"Popliteal artery",
" — Knee trauma or orthopaedic surgery",
"Carotid artery",
" — Neck trauma / endarterectomy complication",
"Peroneal / tibial arteries",
" — Peripheral vascular surgery",
]),
("VISCERAL", ORANGE, [
"Splenic artery (most common visceral PSA)",
" — Pancreatitis, splenomegaly, trauma",
"Hepatic artery",
" — Liver biopsy, biliary procedures, trauma",
" — Haemobilia triad: pain, jaundice, GI bleed",
"Renal artery",
" — Penetrating > blunt trauma",
" — Post-biopsy, nephrostomy",
"Gastroduodenal / pancreaticoduodenal arteries",
" — Pancreatitis (enzyme erosion)",
"Superior mesenteric artery branches",
" — Inflammatory bowel, surgery, trauma",
]),
("AORTIC / CARDIAC", YELLOW, [
"Post-surgical aortic PSA",
" — Proximal/distal graft anastomoses",
" — Coronary reimplantation sites",
"Aortic valve / root surgery",
" — Root-enlarging procedures",
" — Endocarditis with tissue destruction",
"Echocardiographic appearance:",
" — Echolucent area adjacent to graft",
" — Color flow: filling of extra-cardiac space",
" — TEE > TTE for image quality",
"Post-traumatic aortic PSA",
" — Isthmus: deceleration injury (MVC)",
]),
]
for i, (title, col, items) in enumerate(locs):
x = Inches(0.3 + i * 4.33)
rect(s, x, Inches(1.3), Inches(4.1), Inches(5.95), MID_BG)
rect(s, x, Inches(1.3), Inches(4.1), Inches(0.5), col)
tb(s, title, x + Inches(0.1), Inches(1.33), Inches(3.9), Inches(0.45),
size=16, bold=True, color=DARK_BG, align=PP_ALIGN.CENTER)
y = 1.88
for item in items:
indent = item.startswith(" —")
tb(s, item.strip(), x + Inches(0.15 + (0.2 if indent else 0.0)),
Inches(y), Inches(3.7), Inches(0.37),
size=11 if indent else 12,
color=LIGHT_GRAY if indent else WHITE,
bold=not indent)
y += 0.37
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 8 — Differential Diagnosis
# ═══════════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
bg(s, DARK_BG)
heading_bar(s, "Differential Diagnosis — Imaging Pitfalls & Key Differentiators")
# Table header
headers = ["Entity", "US Appearance", "CT Appearance", "Key Differentiator"]
col_widths = [Inches(2.4), Inches(3.0), Inches(3.2), Inches(4.3)]
col_x = [Inches(0.25), Inches(2.7), Inches(5.75), Inches(9.0)]
y_row = 1.35
for i, (hdr, cx, cw) in enumerate(zip(headers, col_x, col_widths)):
rect(s, cx, Inches(y_row), cw, Inches(0.55), ACCENT)
tb(s, hdr, cx + Inches(0.05), Inches(y_row + 0.05), cw - Inches(0.1), Inches(0.45),
size=14, bold=True, color=DARK_BG, align=PP_ALIGN.CENTER)
rows = [
("True Aneurysm", "Fusiform/saccular dilation; all 3 layers visible", "Fusiform/saccular enhancement; normal wall layers", "No history of trauma/procedure; full-wall dilation on imaging"),
("Haematoma", "Non-compressible heterogeneous mass; no flow on CDI", "Non-enhancing collection; variable density", "Absent vascular communication on Doppler / post-contrast CT"),
("AV Fistula", "Turbulent arterialised venous flow; no sac", "Early venous enhancement from arterial phase", "No discrete sac; persistent forward (not to-and-fro) flow"),
("Abscess / Cyst", "Hypoechoic/anechoic; internal debris; no flow", "Rim-enhancing collection; non-vascular", "No Doppler signal; no connection to artery; clinical infection"),
("Lymph Node / Tumour", "Hypoechoic; vascularity may be present", "Enhancing mass; no arterial communication", "No neck; characteristic lymph node morphology; biopsy"),
("Arterial Dissection", "Double-lumen; intimal flap on B-mode", "Two lumens; intimal flap; no sac", "True + false lumen; no sac; different flow dynamics"),
]
row_colors = [DARK_BG, MID_BG, DARK_BG, MID_BG, DARK_BG, MID_BG]
y_row = 1.9
row_h = 0.82
for row_i, (row, bg_col) in enumerate(zip(rows, row_colors)):
for ci, (cell, cx, cw) in enumerate(zip(row, col_x, col_widths)):
rect(s, cx, Inches(y_row), cw, Inches(row_h), bg_col)
tb(s, cell, cx + Inches(0.07), Inches(y_row + 0.05), cw - Inches(0.1), Inches(row_h - 0.1),
size=11, color=WHITE if ci > 0 else ACCENT2, bold=(ci==0), wrap=True)
y_row += row_h
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 9 — Treatment Options
# ═══════════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
bg(s, DARK_BG)
heading_bar(s, "Treatment — From Conservative to Endovascular & Surgical")
options = [
("Observation / Conservative", ACCENT, [
"Small PSA (<2 cm), especially post-biopsy",
"High spontaneous thrombosis rate in small PSAs",
"Serial US surveillance every 4–6 weeks",
"Anticoagulated patients: higher failure rate",
]),
("US-Guided Compression", RGBColor(0x00, 0x96, 0x88), [
"External compression of PSA neck with US probe",
"Target: thrombosis of sac while preserving artery patency",
"Success 63–88%; painful for patient",
"Failure in deep/large PSA or anticoagulated patients",
]),
("Thrombin Injection (UGTI)", ORANGE, [
"US-guided injection of thrombin into sac (NOT the neck)",
"Converts fibrinogen → fibrin → thrombosis of sac",
"Success rate near 97% in non-infected PSA",
"Risk: distal thromboembolism if thrombin enters artery",
"Contraindicated: infected PSA, wide neck (>1 cm)",
]),
("Endovascular — Embolisation", YELLOW, [
"IR coil / glue / plug embolisation of feeding artery",
"Visceral PSA (splenic, hepatic, renal, GDA): ~100% success",
"Approaches: selective parent artery, neck packing, sac fill",
"CT angiography guides catheter selection",
]),
("Endovascular — Covered Stent", RGBColor(0xE0, 0x60, 0x20), [
"Stent-graft deployed across PSA neck",
"Excludes sac while maintaining parent artery flow",
"Ideal for large-vessel PSA (femoral, iliac, aortic)",
"Requires adequate proximal/distal landing zones",
]),
("Surgery", RGBColor(0xFF, 0x4D, 0x4D), [
"Open repair: excision + direct suture / patch",
"Bypass grafting if vessel sacrifice needed",
"Indicated: failed endovascular, infected anastomotic PSA",
"Post-cardiac surgery: urgent repair to prevent mediastinal rupture",
]),
]
ncols = 3
nrows = 2
box_w = Inches(4.1)
box_h = Inches(2.55)
gutter_x = Inches(0.32)
gutter_y = Inches(0.25)
start_x = Inches(0.25)
start_y = Inches(1.35)
for idx, (title, col, items) in enumerate(options):
row = idx // ncols
ci = idx % ncols
bx = start_x + ci * (box_w + gutter_x)
by = start_y + row * (box_h + gutter_y)
rect(s, bx, by, box_w, box_h, MID_BG)
rect(s, bx, by, box_w, Inches(0.45), col)
tb(s, title, bx + Inches(0.08), by + Inches(0.03),
box_w - Inches(0.1), Inches(0.4),
size=13, bold=True, color=DARK_BG, align=PP_ALIGN.CENTER)
multi_para(s, items, bx + Inches(0.1), by + Inches(0.5),
box_w - Inches(0.15), box_h - Inches(0.6),
size=12, color=WHITE)
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 10 — Imaging Protocol Summary & Pearls
# ═══════════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
bg(s, DARK_BG)
heading_bar(s, "Imaging Protocol Summary & Radiological Pearls")
# Protocol table
rect(s, Inches(0.3), Inches(1.35), Inches(8.0), Inches(5.9), MID_BG)
tb(s, "Recommended Imaging Protocol by Location", Inches(0.5), Inches(1.45), Inches(7.7), Inches(0.45),
size=18, bold=True, color=ACCENT)
protocol_rows = [
("Femoral / Peripheral", "Duplex US (first-line)", "CTA if complex / pre-op", "Not routine"),
("Visceral (hepatic/splenic/renal)", "US + CDI (initial screen)", "CTA with arterial + portal phases", "DSA if endovascular Rx planned"),
("Post-pancreatectomy haemorrhage", "CTA immediately", "CTA → DSA/embolisation", "MRA not appropriate (urgent)"),
("Aortic / post-cardiac surgery", "TTE / TEE", "CTA chest with ECG-gating", "DSA for repair planning"),
("Traumatic renal", "FAST US (initial)", "Multiphase MDCT incl. delayed", "DSA if active bleeding"),
]
hdr_cols = ["Location", "First-Line", "Second-Line", "Adjunct"]
hdr_widths = [Inches(2.2), Inches(1.8), Inches(2.0), Inches(2.0)]
hdr_x_vals = [Inches(0.35), Inches(2.6), Inches(4.45), Inches(6.5)]
y_tbl = 2.0
for hx, hw, hd in zip(hdr_x_vals, hdr_widths, hdr_cols):
rect(s, hx, Inches(y_tbl), hw, Inches(0.45), ACCENT)
tb(s, hd, hx+Inches(0.05), Inches(y_tbl+0.05), hw-Inches(0.05), Inches(0.35),
size=12, bold=True, color=DARK_BG, align=PP_ALIGN.CENTER)
y_tbl += 0.46
for ri, row in enumerate(protocol_rows):
row_bg = DARK_BG if ri % 2 == 0 else RGBColor(0x15, 0x28, 0x3E)
for cell, hx, hw in zip(row, hdr_x_vals, hdr_widths):
rect(s, hx, Inches(y_tbl), hw, Inches(0.88), row_bg)
tb(s, cell, hx+Inches(0.07), Inches(y_tbl+0.04), hw-Inches(0.1), Inches(0.8),
size=11, color=WHITE if hdr_x_vals.index(hx)>0 else ACCENT2,
bold=(hdr_x_vals.index(hx)==0), wrap=True)
y_tbl += 0.88
# Pearls column
rect(s, Inches(8.55), Inches(1.35), Inches(4.5), Inches(5.9), MID_BG)
tb(s, "⚡ Key Radiological Pearls", Inches(8.7), Inches(1.45), Inches(4.2), Inches(0.45),
size=18, bold=True, color=YELLOW)
pearls = [
("To-and-Fro = Pathognomonic", "Spectral Doppler at the neck is diagnostic; absent in cysts/haematomas"),
("Wash-in/Wash-out on CT", "Arterial high density → portal venous isodensity distinguishes PSA from active bleed"),
("Neck Width Matters", "Narrow neck (<5 mm): thrombin injection safe; Wide neck: prefer stent-graft"),
("Multiphase MDCT", "Non-contrast + arterial + portal venous phases mandatory for complete characterisation"),
("CTA = treatment roadmap", "Defines anatomy for embolisation route; predicts need for collateral preservation"),
("Missed PSA risk", "Delayed presentation (days to weeks post-trauma/procedure) — always consider when haematuria or pulsatile mass develops late"),
]
y_p = 2.0
for title, desc in pearls:
rect(s, Inches(8.7), Inches(y_p), Inches(0.12), Inches(0.6), ACCENT)
tb(s, title, Inches(8.9), Inches(y_p), Inches(3.9), Inches(0.35),
size=13, bold=True, color=ACCENT2)
tb(s, desc, Inches(8.9), Inches(y_p+0.35), Inches(3.9), Inches(0.5),
size=11, color=WHITE, wrap=True)
y_p += 0.9
# ═══════════════════════════════════════════════════════════════════════════════
# SLIDE 11 — Summary & References
# ═══════════════════════════════════════════════════════════════════════════════
s = prs.slides.add_slide(blank)
bg(s, DARK_BG)
heading_bar(s, "Summary")
rect(s, 0, Inches(7.43), W, Inches(0.07), ACCENT)
summary_points = [
"Pseudoaneurysm = pulsatile haematoma communicating with an artery, contained by perivascular tissue (NOT true arterial wall)",
"Most common aetiology: iatrogenic (post-catheterisation femoral artery)",
"US with CDI: first-line for superficial PSA — pathognomonic yin-yang sign + to-and-fro Doppler waveform at the neck",
"CTA: modality of choice for deep/visceral/aortic PSA — arterial-phase high density → delayed-phase isodensity",
"DSA: gold standard; simultaneously enables endovascular treatment (embolisation, stent-graft)",
"MRA: radiation-free alternative for contrast allergy / renal impairment; not suitable in acute settings",
"Treatment ladder: observation → compression → thrombin injection (UGTI) → embolisation → stent-graft → surgery",
"Rupture is the most feared complication — early diagnosis and treatment are essential",
]
rect(s, Inches(0.3), Inches(1.35), Inches(12.7), Inches(5.1), MID_BG)
multi_para(s, summary_points, Inches(0.55), Inches(1.5), Inches(12.2), Inches(4.8),
size=15, color=WHITE)
# References
rect(s, Inches(0.3), Inches(6.55), Inches(12.7), Inches(0.85), RGBColor(0x10, 0x22, 0x32))
refs = ("References: Grainger & Allison's Diagnostic Radiology (9780323760751) · "
"Textbook of Clinical Echocardiography (9780323882088) · "
"StatPearls: Pseudoaneurysm (NCBI) · "
"PMC10716566: Pseudoaneurysms — ultrasound patterns (2023) · "
"PMC6798774: Interventional treatment options in pseudoaneurysms (2019) · "
"Radiología 67:202–213 (2025): Imaging of pseudoaneurysms")
tb(s, refs, Inches(0.5), Inches(6.62), Inches(12.3), Inches(0.72),
size=9, color=LIGHT_GRAY, italic=True, wrap=True)
# ═══════════════════════════════════════════════════════════════════════════════
# SAVE
# ═══════════════════════════════════════════════════════════════════════════════
out = "/tmp/workspace/pseudoaneurysm-ppt/Pseudoaneurysm_Radiology.pptx"
buf = BytesIO()
prs.save(buf)
with open(out, "wb") as f:
f.write(buf.getvalue())
print(f"Saved: {out}")
print(f"Slides: {len(prs.slides)}")
cd /tmp/workspace/pseudoaneurysm-ppt && python build_ppt.py 2>&1
~/pseudoaneurysm-ppt/build_ppt.py
Successfully replaced 1 instance(s) of the string in '/tmp/workspace/pseudoaneurysm-ppt/build_ppt.py'
cd /tmp/workspace/pseudoaneurysm-ppt && python build_ppt.py 2>&1
Pseudoaneurysm Radiology
Presentation · PPTX
| # | Slide Title | Key Content |
|---|---|---|
| 1 | Title Slide | Cover with modalities, locations, and treatment tags |
| 2 | Definition & Pathophysiology | PSA vs. true aneurysm; all aetiologies (iatrogenic, trauma, infectious, inflammatory) |
| 3 | Clinical Presentation | Four columns: peripheral, visceral, aortic PSA, and complications |
| 4 | Ultrasound — B-mode & Colour Doppler | Yin-yang sign, to-and-fro waveform, arterialised waveform; TEE echocardiography image of aortic PSA |
| 5 | CT Angiography | CT phases (non-contrast, arterial, portal venous, delayed, MIP); wash-in/wash-out sign; real CT image — traumatic renal PSA (Grainger & Allison) |
| 6 | MRA & DSA | MRA indications/limitations; DSA as gold standard; simultaneous diagnosis + therapy |
| 7 | Anatomical Locations | Three columns: peripheral (femoral, radial, carotid), visceral (splenic, hepatic, renal, GDA), aortic/cardiac |
| 8 | Differential Diagnosis | Table: true aneurysm, haematoma, AV fistula, abscess, tumour, dissection — US vs. CT vs. key differentiator |
| 9 | Treatment Options | Six boxes: observation, compression, US-guided thrombin injection, embolisation, covered stent, surgery — with indications and success rates |
| 10 | Protocol Summary & Pearls | Protocol table by anatomical location; 6 high-yield radiological pearls (to-and-fro, wash-in/wash-out, neck width, multiphase CT) |
| 11 | Summary & References | 8-point summary; full references (Grainger & Allison, Clinical Echocardiography, StatPearls, PMC papers) |