Criteria and cannulation of new fistula and needles direction, is it towards fistula or towards heart or few hemodialysis done only through taking vein poin in fistula please guide us through reference
arteriovenous fistula cannulation hemodialysis needle direction criteria
PMID: 37609532
AV fistula new cannulation criteria maturation needle direction antegrade retrograde guidelines KDOQI
https://www.midwestkidneynetwork.org/sites/default/files/rev…
Important update (KDOQI 2019): The NIH Hemodialysis Fistula Maturation Study reassessed the Rule of 6s. Using criteria of flow ≥600 mL/min, diameter ≥6 mm, and depth ≤2 mm, successful maturation was achieved in only ~50% of cases. Greater depths produced particularly poor outcomes. KDOQI 2019 states that cannulation criteria need to be revisited and studied further - so local vascular surgeon/nephrologist judgement remains essential.
| Access Type | Minimum Wait Before Cannulation |
|---|---|
| New AVF (autogenous) | 8-12 weeks (physician order required) |
| Standard AV graft | 2-4 weeks after insertion |
| "Early cannulation" AV graft | Can be needled within 24 hours per manufacturer instructions |
| Needle | Direction | Orientation | Rationale |
|---|---|---|---|
| Arterial needle (blood leaving patient) | Retrograde (toward anastomosis) | Tip points toward the arterial anastomosis, against blood flow | Draws blood from the high-pressure arterial inflow zone; reduces recirculation |
| Venous needle (blood returning to patient) | Antegrade (toward heart) | Tip points away from anastomosis, with blood flow, toward the heart | Returns blood in the direction of venous outflow; minimizes turbulence |
| Blood Flow Rate | Minimum Needle Gauge |
|---|---|
| <300 mL/min | 17 gauge |
| 300-350 mL/min | 16 gauge |
| 350-450 mL/min | 15 gauge |
| >450 mL/min | 14 gauge |
Create a reference PDF with fistula cannulation protocols and needle gauge charts
ls -la /home/daytona/workspace/ 2>/dev/null || mkdir -p /home/daytona/workspace
mkdir -p /home/daytona/workspace/fistula-cannulation && python3 -c "from reportl…
~/fistula-cannulation/generate_pdf.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import mm, cm
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether, PageBreak
)
from reportlab.platypus.flowables import HRFlowable
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Circle, Polygon
from reportlab.graphics import renderPDF
from reportlab.graphics.charts.lineplots import LinePlot
from reportlab.graphics.widgets.markers import makeMarker
import os
OUTPUT = "/home/daytona/workspace/fistula-cannulation/AV_Fistula_Cannulation_Protocol.pdf"
# ── Colour palette ───────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1A3A5C")
TEAL = colors.HexColor("#0D7377")
TEAL_LIGHT = colors.HexColor("#E8F7F7")
AMBER = colors.HexColor("#E07B00")
AMBER_LITE = colors.HexColor("#FFF4E0")
RED = colors.HexColor("#C0392B")
RED_LITE = colors.HexColor("#FDECEA")
GREEN = colors.HexColor("#1B7A4A")
GREEN_LITE = colors.HexColor("#E8F5EE")
GREY = colors.HexColor("#5A5A5A")
LGREY = colors.HexColor("#F4F6F8")
WHITE = colors.white
BLACK = colors.black
W, H = A4
MARGIN = 1.8 * cm
# ── Style helpers ─────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()
def S(name, **kw):
base = styles.get(name) if name in styles else styles["Normal"]
return ParagraphStyle(name + "_custom", parent=base, **kw)
cover_title = S("Title", fontSize=26, textColor=WHITE, leading=32, alignment=TA_CENTER, fontName="Helvetica-Bold")
cover_sub = S("Normal", fontSize=13, textColor=colors.HexColor("#CCE8EC"), leading=18, alignment=TA_CENTER)
cover_note = S("Normal", fontSize=9, textColor=colors.HexColor("#A0C4CC"), alignment=TA_CENTER)
h1 = S("Heading1", fontSize=14, textColor=WHITE, leading=18, fontName="Helvetica-Bold", spaceAfter=2)
h2 = S("Heading2", fontSize=12, textColor=NAVY, leading=16, fontName="Helvetica-Bold", spaceBefore=10, spaceAfter=4)
h3 = S("Heading3", fontSize=10, textColor=TEAL, leading=14, fontName="Helvetica-Bold", spaceBefore=6, spaceAfter=2)
body = S("Normal", fontSize=9, textColor=GREY, leading=13, spaceAfter=4, alignment=TA_JUSTIFY)
body_b = S("Normal", fontSize=9, textColor=BLACK, leading=13, spaceAfter=3, fontName="Helvetica-Bold")
small = S("Normal", fontSize=8, textColor=GREY, leading=11)
ref = S("Normal", fontSize=7.5,textColor=GREY, leading=10, spaceAfter=2)
bullet= S("Normal", fontSize=9, textColor=GREY, leading=13, leftIndent=14, spaceAfter=3,
bulletIndent=4, bulletFontName="Helvetica", bulletFontSize=10)
# ── Reusable builders ─────────────────────────────────────────────────────────
def section_header(text, bg=NAVY):
tbl = Table([[Paragraph(text, h1)]], colWidths=[W - 2*MARGIN])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("ROUNDEDCORNERS", (0,0), (-1,-1), [4,4,4,4]),
]))
return tbl
def info_box(text, bg=TEAL_LIGHT, border=TEAL):
tbl = Table([[Paragraph(text, body)]], colWidths=[W - 2*MARGIN])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("TOPPADDING", (0,0), (-1,-1), 8),
("BOTTOMPADDING", (0,0), (-1,-1), 8),
("LEFTPADDING", (0,0), (-1,-1), 12),
("RIGHTPADDING", (0,0), (-1,-1), 8),
("BOX", (0,0), (-1,-1), 1.5, border),
]))
return tbl
def warn_box(text):
return info_box(text, bg=AMBER_LITE, border=AMBER)
def danger_box(text):
return info_box(text, bg=RED_LITE, border=RED)
def bullet_para(text):
return Paragraph(f"• {text}", bullet)
def sp(h=4):
return Spacer(1, h * mm)
# ── Cover page ────────────────────────────────────────────────────────────────
def cover_page():
# Full-bleed header block built as a tall table
header_data = [[
Paragraph("AV FISTULA CANNULATION", cover_title),
],[
Paragraph("REFERENCE PROTOCOL", cover_title),
],[
Spacer(1, 6*mm),
],[
Paragraph("Criteria for New Fistula Use • Needle Direction Guidelines<br/>"
"Gauge-to-Flow Charts • Week-by-Week Progression • Cannulation Techniques", cover_sub),
],[
Spacer(1, 4*mm),
],[
Paragraph("Based on KDOQI 2019 Vascular Access Guidelines | UK VASBI 2018 | Karkhah et al. 2023 Systematic Review", cover_note),
]]
tbl = Table(header_data, colWidths=[W - 2*MARGIN])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("TOPPADDING", (0,0), (-1,-1), 10),
("BOTTOMPADDING", (0,0), (-1,-1), 10),
("LEFTPADDING", (0,0), (-1,-1), 16),
("RIGHTPADDING", (0,0), (-1,-1), 16),
]))
return [sp(4), tbl, sp(6)]
# ── Needle direction diagram (Drawing) ────────────────────────────────────────
def needle_direction_diagram():
d = Drawing(W - 2*MARGIN, 95)
dw = W - 2*MARGIN
# Background
d.add(Rect(0, 0, dw, 95, fillColor=LGREY, strokeColor=None))
# Title
d.add(String(dw/2, 80, "NEEDLE DIRECTION IN STANDARD (REGULAR FLOW) AVF",
textAnchor='middle', fontName='Helvetica-Bold', fontSize=9, fillColor=NAVY))
# Vein tube
vein_y = 44
vein_x1 = 50
vein_x2 = dw - 50
d.add(Rect(vein_x1, vein_y - 8, vein_x2 - vein_x1, 16,
fillColor=colors.HexColor("#ADE8F4"), strokeColor=TEAL, strokeWidth=1.5))
# Anastomosis circle (left)
d.add(Circle(vein_x1, vein_y, 10, fillColor=colors.HexColor("#F9A825"),
strokeColor=AMBER, strokeWidth=2))
d.add(String(vein_x1, vein_y - 3, "A", textAnchor='middle',
fontName='Helvetica-Bold', fontSize=8, fillColor=NAVY))
# Blood flow arrow in vein (left to right)
mid = (vein_x1 + vein_x2) / 2
flow_y = vein_y
for x in [mid - 40, mid, mid + 40]:
d.add(Line(x, flow_y, x + 18, flow_y,
strokeColor=TEAL, strokeWidth=1.5))
# arrowhead
d.add(Polygon([x+18, flow_y, x+12, flow_y+4, x+12, flow_y-4],
fillColor=TEAL, strokeColor=None))
d.add(String(mid, flow_y + 13, "Blood flow direction -> -> ->",
textAnchor='middle', fontName='Helvetica', fontSize=7.5, fillColor=TEAL))
# Arterial needle (retrograde, pointing LEFT toward anastomosis)
art_x = vein_x1 + 75
d.add(Line(art_x, vein_y + 30, art_x - 8, vein_y + 8,
strokeColor=RED, strokeWidth=2.5))
# needle tip arrow pointing left
d.add(Polygon([art_x - 8, vein_y + 8, art_x - 2, vein_y + 16, art_x + 4, vein_y + 12],
fillColor=RED, strokeColor=None))
d.add(String(art_x, vein_y + 36, "ARTERIAL NEEDLE",
textAnchor='middle', fontName='Helvetica-Bold', fontSize=8, fillColor=RED))
d.add(String(art_x, vein_y + 27, "RETROGRADE",
textAnchor='middle', fontName='Helvetica', fontSize=7, fillColor=RED))
d.add(String(art_x, vein_y + 20, "(toward anastomosis)",
textAnchor='middle', fontName='Helvetica', fontSize=6.5, fillColor=GREY))
# Venous needle (antegrade, pointing RIGHT toward heart)
ven_x = vein_x2 - 75
d.add(Line(ven_x, vein_y + 30, ven_x + 8, vein_y + 8,
strokeColor=GREEN, strokeWidth=2.5))
# needle tip arrow pointing right
d.add(Polygon([ven_x + 8, vein_y + 8, ven_x + 2, vein_y + 16, ven_x - 4, vein_y + 12],
fillColor=GREEN, strokeColor=None))
d.add(String(ven_x, vein_y + 36, "VENOUS NEEDLE",
textAnchor='middle', fontName='Helvetica-Bold', fontSize=8, fillColor=GREEN))
d.add(String(ven_x, vein_y + 27, "ANTEGRADE",
textAnchor='middle', fontName='Helvetica', fontSize=7, fillColor=GREEN))
d.add(String(ven_x, vein_y + 20, "(toward heart)",
textAnchor='middle', fontName='Helvetica', fontSize=6.5, fillColor=GREY))
# Heart symbol (right)
d.add(String(dw - 42, vein_y - 3, "HEART",
textAnchor='middle', fontName='Helvetica-Bold', fontSize=7, fillColor=NAVY))
d.add(String(dw - 42, vein_y + 6, ">>>", textAnchor='middle',
fontName='Helvetica', fontSize=9, fillColor=NAVY))
# Minimum distance label
dist_x = vein_x1 + 10
d.add(Line(vein_x1 + 10, vein_y - 14, art_x, vein_y - 14,
strokeColor=AMBER, strokeWidth=1, strokeDashArray=[3, 2]))
d.add(String((vein_x1 + 10 + art_x) / 2, vein_y - 22, "min 1.5-2 inches from anastomosis",
textAnchor='middle', fontName='Helvetica-Oblique', fontSize=6.5, fillColor=AMBER))
return d
# ── Main content builder ──────────────────────────────────────────────────────
def build_story():
story = []
# ── COVER ─────────────────────────────────────────────────────────────────
story += cover_page()
story.append(sp(8))
# ── SECTION 1: MATURATION CRITERIA ────────────────────────────────────────
story.append(section_header("1. CRITERIA FOR CANNULATING A NEW AV FISTULA"))
story.append(sp(3))
story.append(Paragraph("Before attempting the first cannulation, ALL of the following maturation criteria should be met "
"(minimum 8-12 weeks post-creation, with physician order):", body))
story.append(sp(2))
# Rule of 6s table
rule6_data = [
[Paragraph("<b>Parameter</b>", body_b), Paragraph("<b>Threshold</b>", body_b),
Paragraph("<b>Notes</b>", body_b)],
["Vein Diameter", "≥ 6 mm", "Measured by ultrasound or clinical palpation"],
["Blood Flow Rate", "≥ 600 mL/min", "NIH Fistula Maturation Study target"],
["Depth Below Skin","≤ 6 mm (ideally ≤2 mm)","Greater depth = poorer cannulation outcomes"],
["Maturation Time", "8 – 12 weeks", "Never rush without surgeon/nephrologist order"],
["Vessel Length", "≥ 6 cm usable segment","For two-needle placement with spacing"],
]
rule6_tbl = Table(rule6_data, colWidths=[4.5*cm, 4.5*cm, 9.2*cm])
rule6_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9),
("ROWBACKGROUNDS",(0,1), (-1,-1), [WHITE, LGREY]),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#D0D8E0")),
("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"),
]))
story.append(rule6_tbl)
story.append(sp(2))
story.append(warn_box(
"<b>KDOQI 2019 Update:</b> The NIH Fistula Maturation Study found that using criteria of flow ≥600 mL/min, "
"diameter ≥6 mm, and depth ≤2 mm, successful maturation occurred in only ~50% of cases. "
"Cannulation readiness requires physician judgment beyond the Rule of 6s alone."
))
story.append(sp(3))
# Functional maturity definition
story.append(Paragraph("KDOQI 2019 – Functional Maturity Definition:", h3))
story.append(info_box(
"A fistula is <b>functionally mature</b> when it can provide prescribed dialysis consistently "
"with <b>2 needles for >2/3 of dialysis sessions within 4 consecutive weeks</b>."
))
story.append(sp(3))
# Pre-cannulation checklist
story.append(Paragraph("Pre-Cannulation Assessment Checklist (Every New Cannulation):", h3))
checks = [
"Obtain written physician/surgeon order before first cannulation attempt",
"Only experienced, trained dialysis nurses should cannulate new fistulas",
"LOOK: Inspect for hematoma, infiltration, infection, skin changes",
"FEEL: Continuous thrill along the entire fistula length (strong = good flow)",
"LISTEN: Low-pitched machinery bruit (high-pitched = stenosis)",
"ARM ELEVATION TEST: Fistula partially collapses on elevation (rules out outflow stenosis)",
"Measure usable vein length; mark cannulation zones",
"Confirm no new swelling or tenderness since last session",
"Document access assessment findings before each treatment",
]
for c in checks:
story.append(bullet_para(c))
story.append(sp(2))
story.append(danger_box(
"<b>CONTRAINDICATIONS to cannulation:</b> Active infection/cellulitis over access, "
"unresolved hematoma, pulsatile (not thrill) access suggesting stenosis, "
"skin breakdown, or patient/surgeon refusal."
))
story.append(sp(4))
# ── SECTION 2: NEEDLE DIRECTION ───────────────────────────────────────────
story.append(section_header("2. NEEDLE DIRECTION: ANTEGRADE vs. RETROGRADE"))
story.append(sp(3))
story.append(Paragraph(
"Correct needle orientation reduces access recirculation, optimizes dialysis adequacy (Kt/V), "
"and protects the fistula from early damage.", body))
story.append(sp(3))
# Direction diagram
story.append(needle_direction_diagram())
story.append(sp(4))
# Needle direction table
nd_data = [
[Paragraph("<b>Needle</b>", body_b),
Paragraph("<b>Direction</b>", body_b),
Paragraph("<b>Tip Orientation</b>", body_b),
Paragraph("<b>Rationale</b>", body_b)],
[Paragraph("<b>ARTERIAL</b>\n(blood leaving patient)", body_b),
Paragraph("<font color='#C0392B'><b>RETROGRADE</b></font>", body_b),
"Points TOWARD anastomosis\n(against blood flow)",
"Draws from high-pressure inflow zone;\nreduces access recirculation (AR)"],
[Paragraph("<b>VENOUS</b>\n(blood returning to patient)", body_b),
Paragraph("<font color='#1B7A4A'><b>ANTEGRADE</b></font>", body_b),
"Points AWAY from anastomosis\n(with blood flow, toward heart)",
"Returns blood in direction of venous\noutflow; minimizes turbulence"],
]
nd_tbl = Table(nd_data, colWidths=[3.8*cm, 3.2*cm, 5.5*cm, 5.7*cm])
nd_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9),
("ROWBACKGROUNDS",(0,1), (-1,-1), [colors.HexColor("#FFF0F0"), colors.HexColor("#F0FFF4")]),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#D0D8E0")),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(nd_tbl)
story.append(sp(3))
story.append(info_box(
"<b>UK VASBI 2018 Recommendation B:</b> \"Ideally both needles should be inserted in an antegrade direction "
"(needle pointing away from the anastomosis / with the flow of blood). If required, the arterial needle "
"can be inserted in a retrograde direction (needle facing towards the anastomosis / against the flow of blood). "
"This decision requires clinical judgement.\""
))
story.append(sp(2))
# Reverse flow note
story.append(Paragraph("Reverse Flow AVF (e.g., Proximal Radial Artery AVF):", h3))
story.append(bullet_para("Blood flow direction dictates needle placement (opposite to standard AVF)"))
story.append(bullet_para("Venous needle in forearm: RETROGRADE toward the hand (direction of venous flow)"))
story.append(bullet_para("Venous needle in upper arm: ANTEGRADE toward the shoulder/heart"))
story.append(sp(2))
# Evidence note
story.append(warn_box(
"<b>Evidence note (Karkhah et al. 2023 – Systematic Review & Meta-Analysis):</b> "
"Analysis of 3 RCTs and 4 non-RCTs found <b>uncertainty</b> about the effect of needle direction "
"on Kt/V and access recirculation. Non-RCT data suggested retrograde arterial needle decreases Kt/V; "
"antegrade arterial reduces AR. RCT data was inconclusive. "
"Institutional protocol and clinical judgment remain the standard."
))
story.append(sp(3))
# ── SECTION 3: NEEDLE GAUGE AND BFR CHART ─────────────────────────────────
story.append(section_header("3. NEEDLE GAUGE – BLOOD FLOW RATE CHART"))
story.append(sp(3))
story.append(Paragraph(
"Match needle gauge to the prescribed blood flow rate (BFR). Larger needles reduce "
"pre-pump arterial pressure and improve delivered blood flow.", body))
story.append(sp(3))
gauge_data = [
[Paragraph("<b>Blood Flow Rate (BFR)</b>", body_b),
Paragraph("<b>Minimum Needle Gauge</b>", body_b),
Paragraph("<b>Notes</b>", body_b)],
["< 300 mL/min", "17 Gauge", "First week / very new fragile fistulas; initial cannulation"],
["300 – 350 mL/min","16 Gauge", "Week 2 progression; standard mid-range access"],
["350 – 450 mL/min","15 Gauge", "Week 3+ after successful progression"],
["> 450 mL/min", "14 Gauge", "Established fistula; high-efficiency dialysis needs"],
]
gauge_tbl = Table(gauge_data, colWidths=[5.5*cm, 4.5*cm, 8.2*cm])
# Row colors with gauge highlighting
gauge_colors = [NAVY, colors.HexColor("#EDF7EF"), colors.HexColor("#D5EFDA"),
colors.HexColor("#B8E2BF"), colors.HexColor("#90CF9A")]
gauge_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9),
("BACKGROUND", (0,1), (-1,1), colors.HexColor("#EDF7EF")),
("BACKGROUND", (0,2), (-1,2), colors.HexColor("#D5EFDA")),
("BACKGROUND", (0,3), (-1,3), colors.HexColor("#B8E2BF")),
("BACKGROUND", (0,4), (-1,4), colors.HexColor("#90CF9A")),
("FONTNAME", (1,1), (1,-1), "Helvetica-Bold"),
("FONTSIZE", (1,1), (1,-1), 11),
("TEXTCOLOR", (1,1), (1,-1), GREEN),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#C0D8C0")),
("TOPPADDING", (0,0), (-1,-1), 7),
("BOTTOMPADDING", (0,0), (-1,-1), 7),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING", (0,0), (-1,-1), 7),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("ALIGN", (1,0), (1,-1), "CENTER"),
]))
story.append(gauge_tbl)
story.append(sp(2))
story.append(info_box(
"<b>Note:</b> These are <i>minimum</i> recommended gauges. Larger needles (when feasible) "
"further reduce pre-pump arterial pressure and optimize delivered blood flow. "
"Needle gauge must be matched to the actual achieved BFR, not just the prescribed rate."
))
story.append(sp(4))
# ── SECTION 4: WEEK-BY-WEEK PROGRESSION ───────────────────────────────────
story.append(section_header("4. WEEK-BY-WEEK CANNULATION PROGRESSION PROTOCOL"))
story.append(sp(3))
story.append(Paragraph(
"Progress new fistula cannulation gradually. Do NOT advance faster than these guidelines "
"without a physician order. Staff must document each session outcome.", body))
story.append(sp(2))
week_data = [
[Paragraph("<b>Week</b>", body_b), Paragraph("<b>Gauge</b>", body_b),
Paragraph("<b>Blood Flow Rate</b>", body_b), Paragraph("<b>Key Actions</b>", body_b)],
["Week 1", "17G",
"200 – 250 mL/min",
"• Reduced heparin (50% of ordered dose)\n• If no other access: two 17G needles\n"
"• If CVC present: 17G arterial + CVC venous\n• Angle 25° insertion, chevron taping\n"
"• Patient must NOT move access arm\n• Stay ≥1.5–2 inches from anastomosis"],
["Week 2", "16G",
"300 mL/min",
"• Only if Week 1 was fully successful\n• Rotate cannulation sites\n"
"• Continue careful monitoring for infiltration"],
["Week 3+", "15G → 14G",
"350 – 450+ mL/min",
"• Progress toward prescribed BFR and gauge\n• Match gauge to BFR per chart (Section 3)\n"
"• Continue site rotation (rope-ladder technique)\n• Regular heparin dosing"],
]
week_tbl = Table(week_data, colWidths=[2.0*cm, 1.8*cm, 3.5*cm, 10.9*cm])
week_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), TEAL),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("BACKGROUND", (0,1), (-1,1), colors.HexColor("#FFF8E1")),
("BACKGROUND", (0,2), (-1,2), colors.HexColor("#E8F5E9")),
("BACKGROUND", (0,3), (-1,3), colors.HexColor("#E3F2FD")),
("FONTNAME", (0,1), (0,-1), "Helvetica-Bold"),
("TEXTCOLOR", (0,1), (0,-1), NAVY),
("FONTNAME", (1,1), (1,-1), "Helvetica-Bold"),
("FONTSIZE", (1,1), (1,-1), 11),
("TEXTCOLOR", (1,1), (1,-1), TEAL),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#D0D8E0")),
("TOPPADDING", (0,0), (-1,-1), 7),
("BOTTOMPADDING", (0,0), (-1,-1), 7),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
("ALIGN", (0,1), (1,-1), "CENTER"),
]))
story.append(week_tbl)
story.append(sp(3))
story.append(danger_box(
"<b>CATHETER REMOVAL RULE:</b> The central venous catheter (CVC) must NOT be removed until "
"the patient has had <b>6 CONSECUTIVE SUCCESSFUL</b> arterial/venous needle cannulations "
"at the prescribed BFR and needle gauge."
))
story.append(sp(3))
# Infiltration protocol
story.append(Paragraph("Infiltration Management Protocol:", h3))
infilt_data = [
[Paragraph("<b>Occurrence</b>", body_b), Paragraph("<b>Action</b>", body_b)],
["1st Infiltration", "Rest fistula for 1 week, restart with smaller gauge needles. Notify nephrologist."],
["2nd Infiltration", "Rest fistula for 2 weeks, restart with smaller gauge needles. Notify nephrologist."],
["3rd Infiltration", "Notify BOTH surgeon and nephrologist. Do not attempt further cannulation."],
]
infilt_tbl = Table(infilt_data, colWidths=[4*cm, 14.2*cm])
infilt_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), RED),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 9),
("BACKGROUND", (0,1), (-1,1), colors.HexColor("#FFF3CD")),
("BACKGROUND", (0,2), (-1,2), colors.HexColor("#FDDCCA")),
("BACKGROUND", (0,3), (-1,3), RED_LITE),
("FONTNAME", (0,1), (0,-1), "Helvetica-Bold"),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#E0C0C0")),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 8),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
]))
story.append(infilt_tbl)
story.append(sp(4))
# ── SECTION 5: CANNULATION TECHNIQUES ─────────────────────────────────────
story.append(section_header("5. CANNULATION TECHNIQUES (LONG-TERM AVF)"))
story.append(sp(3))
tech_data = [
[Paragraph("<b>Technique</b>", body_b),
Paragraph("<b>Description</b>", body_b),
Paragraph("<b>Advantages</b>", body_b),
Paragraph("<b>Disadvantages / Cautions</b>", body_b)],
[Paragraph("<b>ROPE LADDER</b>\n(RECOMMENDED)", body_b),
"Cannulation sites rotate along entire length of fistula",
"Distributes trauma; allows vessel wall recovery; prevents aneurysm formation; most widely recommended",
"Requires longer usable vein segment; needs staff training in site rotation"],
[Paragraph("<b>BUTTONHOLE</b>\n(Constant-site)", body_b),
"Same needle tract used every session; collagen track forms; blunt needle inserted",
"Reduced pain; less hematoma for suitable patients; good for self-cannulation",
"HIGH INFECTION RISK (esp. S. aureus); strict asepsis essential; guidelines now more cautious; not suitable for everyone"],
[Paragraph("<b>AREA PUNCTURE</b>\n(NOT recommended)", body_b),
"Repeated cannulation in same small zone without a formal buttonhole track",
"None",
"HIGH RISK: pseudoaneurysm, stenosis, aneurysm, skin breakdown. Refer to vascular team if identified."],
]
tech_tbl = Table(tech_data, colWidths=[3.5*cm, 4.5*cm, 4.5*cm, 5.7*cm])
tech_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8.5),
("ROWBACKGROUNDS",(0,1), (-1,-1), [GREEN_LITE, AMBER_LITE, RED_LITE]),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#D0D8E0")),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 7),
("RIGHTPADDING", (0,0), (-1,-1), 6),
("VALIGN", (0,0), (-1,-1), "TOP"),
("BACKGROUND", (0,1), (0,1), colors.HexColor("#C6EFD0")),
("BACKGROUND", (0,2), (0,2), colors.HexColor("#FFEFD0")),
("BACKGROUND", (0,3), (0,3), colors.HexColor("#FDDCDC")),
]))
story.append(tech_tbl)
story.append(sp(3))
# ── SECTION 6: SINGLE-NEEDLE / SINGLE-POINT DIALYSIS ──────────────────────
story.append(section_header("6. SINGLE-NEEDLE DIALYSIS (LIMITED ACCESS SESSIONS)"))
story.append(sp(3))
story.append(Paragraph(
"When a new fistula is too fragile, short, or narrow for two-needle placement, single-needle "
"dialysis may be used as a bridge during early maturation.", body))
story.append(sp(2))
sn_points = [
"Blood is alternately withdrawn and returned through a single needle using a double-pump system or Y-connector",
"Accepted as a TEMPORARY bridge only - not suitable for ongoing long-term use",
"Kt/V delivery is REDUCED due to increased access recirculation (less efficient than 2-needle)",
"Must be physician-ordered and documented",
"Central venous catheter should remain in place as backup during this period",
"Progress to 2-needle cannulation as soon as fistula matures sufficiently",
"Monitor Kt/V each session; increase treatment time to compensate for reduced efficiency if needed",
]
for p in sn_points:
story.append(bullet_para(p))
story.append(sp(3))
# ── SECTION 7: GENERAL NEEDLING PRINCIPLES ─────────────────────────────────
story.append(section_header("7. GENERAL NEEDLING TECHNIQUE PRINCIPLES"))
story.append(sp(3))
principles = [
("<b>Bevel UP:</b>", "Always insert needle with bevel facing upward"),
("<b>Insertion Angle:</b>", "Minimum angle needed to reach vessel depth; aim for needle tip to sit in CENTER of vessel (typically 25-35°)"),
("<b>Minimum Distance:</b>", "Always stay ≥1.5 to 2 inches (3.8-5 cm) from the arteriovenous anastomosis"),
("<b>Needle Spacing:</b>", "Arterial and venous needles should be ≥5 cm apart to minimize access recirculation"),
("<b>No Rotation:</b>", "Do NOT rotate the needle once inserted - causes vessel wall damage ('coring')"),
("<b>Securing:</b>", "Secure with chevron or 'H' taping technique; secure tubing separately"),
("<b>Tourniquet:</b>", "Apply tourniquet for AVF cannulation; do NOT apply for AV graft"),
("<b>Flush:</b>", "Flush needle after insertion to confirm patency and adequate flow before connecting"),
("<b>Removal:</b>", "Remove needle at the same angle as insertion; do NOT apply pressure before needle is fully out"),
("<b>Pressure:</b>", "Apply pressure for minimum 10 minutes after removal; do not 'peek' during this time"),
("<b>Asepsis:</b>", "Strict aseptic technique for all cannulations; cleanse site per local policy"),
]
for bold_part, detail in principles:
story.append(bullet_para(f"{bold_part} {detail}"))
story.append(sp(3))
# ── SECTION 8: REFERENCES ─────────────────────────────────────────────────
story.append(HRFlowable(width="100%", thickness=1, color=colors.HexColor("#D0D8E0")))
story.append(sp(2))
story.append(Paragraph("REFERENCES & GUIDELINES", h2))
refs = [
"1. KDOQI 2019 Clinical Practice Guideline for Vascular Access. Am J Kidney Dis. 2019;75(4 Suppl 2):S1–S164.",
"2. UK VASBI 2018 Clinical Practice Recommendations for Needling of Arteriovenous Fistulae and Grafts for Haemodialysis. "
"Vascular Access Society of Britain and Ireland, 2018. Available: vasbi.org.uk",
"3. Karkhah S, Pourshaikhian M, Ghorbani Vajargah P, et al. Needle Direction and Distance of Arteriovenous Fistula "
"Cannulation in Hemodialysis Adequacy: A Systematic Review and Meta-Analysis. Arch Acad Emerg Med. 2023. PMID: 37609532.",
"4. Midwest Kidney Network. Cannulation of New Fistula – Policy and Procedure (Sample). midwestkidneynetwork.org.",
"5. Lok CE, Huber TS, Lee T, et al. KDOQI Vascular Access Guideline Work Group. Am J Kidney Dis. 2020;75(4 Suppl 2):S1–S164.",
"6. Brenner & Rector's The Kidney, 2-Volume Set. Chapter 63: Hemodialysis. Elsevier.",
"7. Comprehensive Clinical Nephrology, 7th Edition. Chapter: Vascular Access for Hemodialysis. Elsevier.",
"8. NIH Hemodialysis Fistula Maturation (HFM) Study Group. JAMA. 2016;316(19):1985–1994.",
]
for r in refs:
story.append(Paragraph(r, ref))
story.append(sp(4))
story.append(info_box(
"<b>Disclaimer:</b> This document is a clinical reference summary for educational purposes. "
"It does not replace institutional protocols, local policies, or individual physician judgment. "
"Always follow your facility's specific procedures and obtain appropriate physician orders before cannulating any vascular access."
))
return story
# ── Page template with header/footer ─────────────────────────────────────────
def on_first_page(canvas, doc):
pass # cover handles itself
def on_later_pages(canvas, doc):
canvas.saveState()
# Header
canvas.setFillColor(NAVY)
canvas.rect(MARGIN, H - 1.4*cm, W - 2*MARGIN, 0.7*cm, fill=1, stroke=0)
canvas.setFillColor(WHITE)
canvas.setFont("Helvetica-Bold", 8)
canvas.drawString(MARGIN + 5, H - 1.05*cm, "AV FISTULA CANNULATION PROTOCOL")
canvas.setFont("Helvetica", 8)
canvas.drawRightString(W - MARGIN - 5, H - 1.05*cm, "Clinical Reference | KDOQI 2019 | VASBI 2018")
# Footer
canvas.setFillColor(LGREY)
canvas.rect(MARGIN, 0.6*cm, W - 2*MARGIN, 0.5*cm, fill=1, stroke=0)
canvas.setFillColor(GREY)
canvas.setFont("Helvetica", 7.5)
canvas.drawString(MARGIN + 5, 0.78*cm, "For educational use only. Follow institutional protocols.")
canvas.drawRightString(W - MARGIN - 5, 0.78*cm, f"Page {doc.page}")
canvas.restoreState()
def on_first_page_template(canvas, doc):
canvas.saveState()
# First page footer only
canvas.setFillColor(LGREY)
canvas.rect(MARGIN, 0.6*cm, W - 2*MARGIN, 0.5*cm, fill=1, stroke=0)
canvas.setFillColor(GREY)
canvas.setFont("Helvetica", 7.5)
canvas.drawString(MARGIN + 5, 0.78*cm, "For educational use only. Follow institutional protocols.")
canvas.drawRightString(W - MARGIN - 5, 0.78*cm, "Page 1")
canvas.restoreState()
# ── Build PDF ─────────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=MARGIN, rightMargin=MARGIN,
topMargin=1.8*cm, bottomMargin=1.5*cm,
title="AV Fistula Cannulation Protocol",
author="Orris Clinical Reference",
subject="Hemodialysis Vascular Access – Cannulation Guidelines",
)
story = build_story()
doc.build(story, onFirstPage=on_first_page_template, onLaterPages=on_later_pages)
print(f"PDF generated: {OUTPUT}")
cd /home/daytona/workspace/fistula-cannulation && python3 generate_pdf.py 2>&1
ls -lh /home/daytona/workspace/fistula-cannulation/AV_Fistula_Cannulation_Protoc…
AV Fistula Cannulation Protocol
PDF Document · PDF
Create a reference PDF with fistula cannulation protocols and needle gauge charts
AV Fistula Cannulation Protocol
PDF Document · PDF
Generate a presentation on fistula maturation timeline and troubleshooting
mkdir -p /home/daytona/workspace/fistula-pptx && node -e "require('pptxgenjs'); …
~/fistula-pptx/build.js
"use strict";
const pptxgen = require("pptxgenjs");
const path = require("path");
const OUT = "/home/daytona/workspace/fistula-pptx/AV_Fistula_Maturation_Troubleshooting.pptx";
// ── Palette ────────────────────────────────────────────────────────────────
const C = {
navy: "1A3A5C",
teal: "0D7377",
tealLight: "14A085",
tealPale: "D6F0EE",
amber: "E07B00",
amberPale: "FFF4E0",
red: "C0392B",
redPale: "FDECEA",
green: "1B7A4A",
greenPale: "E8F5EE",
purple: "6C3483",
purplePale: "F3E8FA",
white: "FFFFFF",
offwhite: "F4F8FA",
lgrey: "E8EDF2",
grey: "5A5A5A",
darkgrey: "2C3E50",
};
let pres = new pptxgen();
pres.layout = "LAYOUT_16x9";
pres.title = "AV Fistula Maturation Timeline & Troubleshooting";
pres.author = "Orris Clinical Reference";
pres.subject = "Hemodialysis Vascular Access";
// ── Helper: full dark background ─────────────────────────────────────────
function darkBg(slide, color = C.navy) {
slide.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 5.625, fill: { color }, line: { color, width: 0 } });
}
// ── Helper: section label pill ────────────────────────────────────────────
function pill(slide, text, x, y, w = 2, color = C.teal) {
slide.addShape(pres.shapes.ROUNDED_RECTANGLE, { x, y, w, h: 0.28, fill: { color }, line: { color, width: 0 }, rectRadius: 0.04 });
slide.addText(text, { x, y: y + 0.01, w, h: 0.26, fontSize: 8, bold: true, color: C.white, align: "center", valign: "middle", margin: 0 });
}
// ── Helper: card (rounded rect with optional accent bar) ─────────────────
function card(slide, x, y, w, h, fillColor = C.white, accentColor = null, shadow = true) {
slide.addShape(pres.shapes.RECTANGLE, {
x, y, w, h,
fill: { color: fillColor },
line: { color: "D4DEE8", width: 0.5 },
shadow: shadow ? { type: "outer", color: "000000", blur: 5, offset: 2, angle: 135, opacity: 0.12 } : undefined,
});
if (accentColor) {
slide.addShape(pres.shapes.RECTANGLE, { x, y, w: 0.06, h, fill: { color: accentColor }, line: { color: accentColor, width: 0 } });
}
}
// ── Helper: horizontal divider line ──────────────────────────────────────
function hline(slide, x, y, w, color = C.lgrey) {
slide.addShape(pres.shapes.LINE, { x, y, w, h: 0, line: { color, width: 0.8 } });
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 1 — TITLE
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
darkBg(s, C.navy);
// Decorative teal band left
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 0.55, h: 5.625, fill: { color: C.teal }, line: { color: C.teal, width: 0 } });
// Accent arc — simulated with semi-transparent circle
s.addShape(pres.shapes.OVAL, { x: 6.5, y: -1.2, w: 5, h: 5, fill: { color: C.teal, transparency: 85 }, line: { color: C.teal, width: 0 } });
s.addShape(pres.shapes.OVAL, { x: 7.2, y: -0.4, w: 3.5, h: 3.5, fill: { color: C.tealLight, transparency: 90 }, line: { color: C.tealLight, width: 0 } });
// Eyebrow
pill(s, "HEMODIALYSIS VASCULAR ACCESS", 0.8, 0.85, 3.5, C.teal);
// Main title
s.addText("AV Fistula Maturation", { x: 0.8, y: 1.22, w: 8.2, h: 0.85, fontSize: 38, bold: true, color: C.white, fontFace: "Calibri", margin: 0 });
s.addText("Timeline & Troubleshooting", { x: 0.8, y: 1.98, w: 8.2, h: 0.72, fontSize: 38, bold: true, color: "7ECFD6", fontFace: "Calibri", margin: 0 });
hline(s, 0.8, 2.82, 4.5, C.tealLight);
s.addText("A comprehensive clinical reference for nephrology teams\nKDOQI 2019 | VASBI 2018 | NIH HFM Study", {
x: 0.8, y: 2.95, w: 6.5, h: 0.6, fontSize: 11.5, color: "9DC8CC", italics: true, margin: 0, lineSpacingMultiple: 1.3
});
// Bottom stat cards
const stats = [
{ val: "25%", label: "Primary failure\nrate" },
{ val: "8–12 wks", label: "Minimum\nmaturation time" },
{ val: "6 mm", label: "Target vein\ndiameter" },
{ val: "600 mL/min", label: "Target blood\nflow rate" },
];
stats.forEach((st, i) => {
const cx = 0.8 + i * 2.3;
card(s, cx, 4.0, 2.1, 1.2, "1E4A6A", null, false);
s.addText(st.val, { x: cx, y: 4.08, w: 2.1, h: 0.45, fontSize: 18, bold: true, color: "7ECFD6", align: "center", margin: 0 });
s.addText(st.label, { x: cx, y: 4.52, w: 2.1, h: 0.4, fontSize: 8, color: "8AB8C0", align: "center", margin: 0, lineSpacingMultiple: 1.2 });
});
// Slide number
s.addText("1", { x: 9.6, y: 5.2, w: 0.3, h: 0.2, fontSize: 8, color: "4A7080", align: "right", margin: 0 });
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 2 — AGENDA / OVERVIEW
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 5.625, fill: { color: C.offwhite }, line: { color: C.offwhite, width: 0 } });
// Header bar
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 0.75, fill: { color: C.navy }, line: { color: C.navy, width: 0 } });
s.addText("PRESENTATION OVERVIEW", { x: 0.35, y: 0, w: 9, h: 0.75, fontSize: 14, bold: true, color: C.white, valign: "middle", margin: 0, charSpacing: 2 });
s.addText("2", { x: 9.6, y: 0.25, w: 0.3, h: 0.2, fontSize: 8, color: "8AACB8", align: "right", margin: 0 });
const sections = [
{ num: "01", title: "Fistula Maturation Timeline", sub: "Week-by-week physiological changes and clinical milestones", color: C.teal },
{ num: "02", title: "Maturation Criteria", sub: "Rule of 6s, KDOQI 2019 updates, readiness assessment", color: C.navy },
{ num: "03", title: "Cannulation Progression", sub: "First cannulation protocol, needle gauge, BFR matching", color: C.tealLight },
{ num: "04", title: "Troubleshooting: Failure to Mature", sub: "Causes, assessment, and intervention strategies", color: C.amber },
{ num: "05", title: "Access Complications", sub: "Stenosis, thrombosis, aneurysm, infection — recognition & management", color: C.red },
{ num: "06", title: "Monitoring & Surveillance", sub: "Physical exam, flow monitoring, warning signs", color: C.green },
{ num: "07", title: "Key References", sub: "KDOQI 2019, VASBI 2018, NIH HFM Study, Karkhah 2023", color: C.grey },
];
sections.forEach((sec, i) => {
const row = Math.floor(i / 2);
const col = i % 2;
// last item spans full width
const isLast = i === sections.length - 1;
const cx = isLast ? 0.3 : 0.3 + col * 4.85;
const cy = 0.95 + row * 1.05;
const cw = isLast ? 9.4 : 4.6;
card(s, cx, cy, cw, 0.85, C.white, sec.color);
s.addText(sec.num, { x: cx + 0.15, y: cy + 0.05, w: 0.55, h: 0.35, fontSize: 16, bold: true, color: sec.color, margin: 0 });
s.addText(sec.title, { x: cx + 0.72, y: cy + 0.04, w: cw - 0.85, h: 0.35, fontSize: 11, bold: true, color: C.darkgrey, margin: 0 });
s.addText(sec.sub, { x: cx + 0.72, y: cy + 0.41, w: cw - 0.85, h: 0.3, fontSize: 8.5, color: C.grey, margin: 0 });
});
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 3 — MATURATION TIMELINE (visual)
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
darkBg(s, "0F2233");
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 0.7, fill: { color: C.teal }, line: { color: C.teal, width: 0 } });
s.addText("FISTULA MATURATION TIMELINE", { x: 0.3, y: 0, w: 8, h: 0.7, fontSize: 15, bold: true, color: C.white, valign: "middle", charSpacing: 2, margin: 0 });
s.addText("3", { x: 9.6, y: 0.25, w: 0.3, h: 0.2, fontSize: 8, color: "4A8090", align: "right", margin: 0 });
// Timeline spine line
s.addShape(pres.shapes.LINE, { x: 0.55, y: 3.12, w: 8.9, h: 0, line: { color: C.teal, width: 2 } });
// Milestone nodes
const milestones = [
{ x: 0.55, week: "Day 0\nSurgery", color: C.amber,
top: ["Arteriovenous\nanastomosis created", "Immediate\narterialization\nbegins"],
bot: ["Radial/brachial\nartery → cephalic/\nbasilic vein", "DO NOT cannulate"] },
{ x: 2.4, week: "Wk 1–2", color: C.tealLight,
top: ["Venous wall\nthickening begins", "Lumen diameter\nstarts expanding"],
bot: ["Vein must adapt\nto arterial pressure", "Observe only"] },
{ x: 4.25, week: "Wk 3–4", color: C.tealLight,
top: ["Visible vein\ncordification", "Blood flow\n↑ 5–10×"],
bot: ["Physical exam\nshows thrill + bruit", "Assess maturation"] },
{ x: 6.1, week: "Wk 6–8", color: C.green,
top: ["Vein wall\nfully muscularized", "Diameter ≥6 mm\nin many patients"],
bot: ["Earliest possible\nfirst cannulation", "Only with MD order"] },
{ x: 7.95, week: "Wk 8–12", color: C.green,
top: ["Optimal maturation\nwindow", "Flow ≥600 mL/min\nexpected"],
bot: ["Standard first\ncannulation target", "Start 17G, 200 mL/min"] },
];
milestones.forEach((m) => {
// Node circle
s.addShape(pres.shapes.OVAL, { x: m.x - 0.14, y: 3.0, w: 0.28, h: 0.28, fill: { color: m.color }, line: { color: C.white, width: 1 } });
// Week label (below spine)
s.addText(m.week, { x: m.x - 0.75, y: 3.32, w: 1.5, h: 0.45, fontSize: 8.5, bold: true, color: m.color, align: "center", margin: 0, lineSpacingMultiple: 1.2 });
// Top content (above spine) — connector line then text box
s.addShape(pres.shapes.LINE, { x: m.x, y: 1.85, w: 0, h: 1.15, line: { color: "3A6080", width: 0.75, dashType: "dash" } });
s.addShape(pres.shapes.RECTANGLE, { x: m.x - 0.75, y: 0.82, w: 1.5, h: 1.0, fill: { color: "162D40" }, line: { color: m.color, width: 0.75 } });
m.top.forEach((line, li) => {
s.addText(line, { x: m.x - 0.75, y: 0.86 + li * 0.44, w: 1.5, h: 0.42, fontSize: 7.5, color: C.white, align: "center", margin: 2, lineSpacingMultiple: 1.1 });
});
// Bottom content (below week label)
s.addShape(pres.shapes.LINE, { x: m.x, y: 3.77, w: 0, h: 0.52, line: { color: "3A6080", width: 0.75, dashType: "dash" } });
s.addShape(pres.shapes.RECTANGLE, { x: m.x - 0.75, y: 4.29, w: 1.5, h: 0.9, fill: { color: "162D40" }, line: { color: "3A6080", width: 0.5 } });
m.bot.forEach((line, li) => {
s.addText(line, { x: m.x - 0.75, y: 4.32 + li * 0.38, w: 1.5, h: 0.38, fontSize: 7.5, color: "9DC8CC", align: "center", margin: 2, lineSpacingMultiple: 1.1 });
});
});
// Arrow at end of timeline
s.addShape(pres.shapes.RIGHT_ARROW, { x: 9.45, y: 3.0, w: 0.42, h: 0.28, fill: { color: C.teal }, line: { color: C.teal, width: 0 } });
// Footer note
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 5.27, w: 10, h: 0.36, fill: { color: "0A1A2A" }, line: { color: "0A1A2A", width: 0 } });
s.addText("⚠ Early cannulation (<6 weeks) is associated with higher failure rates. Never cannulate without surgeon/nephrologist approval.", {
x: 0.3, y: 5.27, w: 9.4, h: 0.36, fontSize: 8, color: "F0A830", valign: "middle", italics: true, margin: 0
});
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 4 — MATURATION CRITERIA
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 5.625, fill: { color: C.offwhite }, line: { color: C.offwhite, width: 0 } });
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 0.72, fill: { color: C.navy }, line: { color: C.navy, width: 0 } });
s.addText("MATURATION CRITERIA", { x: 0.35, y: 0, w: 8, h: 0.72, fontSize: 14, bold: true, color: C.white, valign: "middle", charSpacing: 2, margin: 0 });
pill(s, "SECTION 02", 8.5, 0.22, 1.2, C.teal);
s.addText("4", { x: 9.6, y: 0.5, w: 0.3, h: 0.2, fontSize: 8, color: "8AACB8", align: "right", margin: 0 });
// Left column — Rule of 6s
card(s, 0.3, 0.88, 4.5, 3.2, C.white, C.teal);
s.addText("CLASSIC RULE OF 6s", { x: 0.5, y: 0.96, w: 4.1, h: 0.34, fontSize: 11, bold: true, color: C.teal, margin: 0 });
const rule6 = [
{ icon: "⌀", label: "Vein Diameter", val: "≥ 6 mm", note: "Ultrasound measurement" },
{ icon: "💧", label: "Blood Flow Rate", val: "≥ 600 mL/min", note: "NIH HFM Study target" },
{ icon: "↕", label: "Depth Below Skin", val: "≤ 6 mm", note: "Ideally ≤ 2 mm" },
{ icon: "⏱", label: "Maturation Time", val: "≥ 6 weeks", note: "8–12 weeks preferred" },
{ icon: "↔", label: "Usable Length", val: "≥ 6 cm", note: "For two-needle placement" },
];
rule6.forEach((r, i) => {
const ry = 1.42 + i * 0.5;
s.addShape(pres.shapes.RECTANGLE, { x: 0.5, y: ry, w: 4.1, h: 0.42, fill: { color: i % 2 === 0 ? C.tealPale : C.white }, line: { color: "D4E8E6", width: 0.3 } });
s.addText(r.label, { x: 0.62, y: ry + 0.04, w: 1.8, h: 0.18, fontSize: 8.5, bold: true, color: C.darkgrey, margin: 0 });
s.addText(r.note, { x: 0.62, y: ry + 0.22, w: 1.8, h: 0.16, fontSize: 7, color: C.grey, margin: 0, italics: true });
s.addText(r.val, { x: 2.5, y: ry + 0.07, w: 2.0, h: 0.28, fontSize: 11, bold: true, color: C.teal, align: "right", margin: 0 });
});
// Right column — KDOQI 2019 update + Functional maturity
card(s, 5.1, 0.88, 4.6, 1.48, C.amberPale, C.amber);
s.addText("KDOQI 2019 UPDATE", { x: 5.3, y: 0.96, w: 4.2, h: 0.3, fontSize: 11, bold: true, color: C.amber, margin: 0 });
s.addText([
{ text: "The NIH HFM Study found that meeting the Rule of 6s\nproduces successful maturation in only ", options: {} },
{ text: "~50% of cases.", options: { bold: true, color: C.red } },
{ text: "\nGreater depth (>2 mm) significantly worsens outcomes.\nCannulation readiness requires physician judgment\nbeyond the Rule of 6s alone.", options: {} }
], { x: 5.3, y: 1.32, w: 4.2, h: 1.0, fontSize: 8.5, color: C.darkgrey, margin: 0, lineSpacingMultiple: 1.35 });
card(s, 5.1, 2.5, 4.6, 1.1, C.tealPale, C.teal);
s.addText("FUNCTIONAL MATURITY (KDOQI 2019)", { x: 5.3, y: 2.58, w: 4.2, h: 0.3, fontSize: 10, bold: true, color: C.teal, margin: 0 });
s.addText("Fistula provides prescribed dialysis consistently\nwith 2 needles for >2/3 of sessions\nwithin 4 consecutive weeks.", {
x: 5.3, y: 2.92, w: 4.2, h: 0.65, fontSize: 9, color: C.darkgrey, margin: 0, lineSpacingMultiple: 1.4
});
card(s, 5.1, 3.75, 4.6, 0.98, C.greenPale, C.green);
s.addText("AV GRAFT — DIFFERENT TIMELINE", { x: 5.3, y: 3.82, w: 4.2, h: 0.28, fontSize: 10, bold: true, color: C.green, margin: 0 });
s.addText("Standard graft: 2–4 weeks post-insertion\nEarly cannulation graft: within 24 hours\n(per manufacturer instructions)", {
x: 5.3, y: 4.12, w: 4.2, h: 0.57, fontSize: 8.5, color: C.darkgrey, margin: 0, lineSpacingMultiple: 1.35
});
// Pre-cannulation exam bottom
card(s, 0.3, 4.15, 4.5, 1.1, C.white, C.navy);
s.addText("PRE-CANNULATION PHYSICAL EXAM", { x: 0.5, y: 4.22, w: 4.1, h: 0.28, fontSize: 9.5, bold: true, color: C.navy, margin: 0 });
const exam = ["LOOK: hematoma, infection, skin changes", "FEEL: continuous soft thrill along fistula", "LISTEN: low-pitched machinery bruit", "ARM ELEVATION: partial collapse = good outflow"];
exam.forEach((e, i) => {
s.addText("• " + e, { x: 0.55, y: 4.54 + i * 0.16, w: 4.0, h: 0.17, fontSize: 7.8, color: C.grey, margin: 0 });
});
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 5 — CANNULATION PROGRESSION + GAUGE CHART
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 5.625, fill: { color: "0C1E2E" }, line: { color: "0C1E2E", width: 0 } });
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 0.68, fill: { color: C.teal }, line: { color: C.teal, width: 0 } });
s.addText("CANNULATION PROGRESSION PROTOCOL", { x: 0.35, y: 0, w: 8.5, h: 0.68, fontSize: 14, bold: true, color: C.white, valign: "middle", charSpacing: 2, margin: 0 });
pill(s, "SECTION 03", 8.5, 0.2, 1.2, C.navy);
s.addText("5", { x: 9.6, y: 0.48, w: 0.3, h: 0.2, fontSize: 8, color: "4A8090", align: "right", margin: 0 });
// Week progression steps (left side)
const weeks = [
{ wk: "WK 1", g: "17G", bfr: "200–250 mL/min", color: C.amber,
notes: ["50% heparin dose (prevent hematoma)", "Two 17G if no other access; CVC as venous if available", "Stay ≥1.5–2 inches from anastomosis, 25° angle", "Chevron taping; no arm movement during treatment"] },
{ wk: "WK 2", g: "16G", bfr: "300 mL/min", color: C.tealLight,
notes: ["Only if Week 1 fully successful (no infiltration)", "Begin rotating cannulation sites (rope ladder)", "Continue monitoring for hematoma, pain, swelling"] },
{ wk: "WK 3+", g: "15–14G", bfr: "350–450+ mL/min", color: C.green,
notes: ["Progress toward prescribed gauge and BFR", "Full heparin dosing", "Transition to 2-needle only when consistent success"] },
];
weeks.forEach((w, i) => {
const wy = 0.88 + i * 1.48;
card(s, 0.3, wy, 5.9, 1.32, "122435", null, false);
s.addShape(pres.shapes.RECTANGLE, { x: 0.3, y: wy, w: 0.06, h: 1.32, fill: { color: w.color }, line: { color: w.color, width: 0 } });
// Week badge
s.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.5, y: wy + 0.1, w: 0.7, h: 0.3, fill: { color: w.color }, line: { color: w.color, width: 0 }, rectRadius: 0.04 });
s.addText(w.wk, { x: 0.5, y: wy + 0.1, w: 0.7, h: 0.3, fontSize: 8, bold: true, color: "0C1E2E", align: "center", valign: "middle", margin: 0 });
// Gauge
s.addText(w.g, { x: 1.28, y: wy + 0.06, w: 1.1, h: 0.44, fontSize: 20, bold: true, color: w.color, margin: 0 });
s.addText(w.bfr, { x: 2.45, y: wy + 0.12, w: 2.6, h: 0.34, fontSize: 10, color: "9DC8CC", bold: true, margin: 0 });
w.notes.forEach((n, ni) => {
s.addText("• " + n, { x: 0.5, y: wy + 0.56 + ni * 0.185, w: 5.55, h: 0.19, fontSize: 7.8, color: "8AACB8", margin: 0 });
});
});
// Right: Gauge-BFR chart
card(s, 6.45, 0.88, 3.25, 3.45, "122435", null, false);
s.addShape(pres.shapes.RECTANGLE, { x: 6.45, y: 0.88, w: 3.25, h: 0.36, fill: { color: C.teal }, line: { color: C.teal, width: 0 } });
s.addText("NEEDLE GAUGE vs BFR", { x: 6.55, y: 0.88, w: 3.05, h: 0.36, fontSize: 9.5, bold: true, color: C.white, valign: "middle", margin: 0, charSpacing: 1 });
const gaugeRows = [
{ bfr: "< 300 mL/min", g: "17G", bar: 1.5, color: C.amber },
{ bfr: "300–350 mL/min", g: "16G", bar: 2.0, color: C.tealLight },
{ bfr: "350–450 mL/min", g: "15G", bar: 2.5, color: C.green },
{ bfr: "> 450 mL/min", g: "14G", bar: 3.0, color: "8B5CF6" },
];
gaugeRows.forEach((gr, i) => {
const gy = 1.35 + i * 0.74;
s.addText(gr.bfr, { x: 6.55, y: gy, w: 2.8, h: 0.22, fontSize: 8, color: "9DC8CC", margin: 0 });
s.addShape(pres.shapes.RECTANGLE, { x: 6.55, y: gy + 0.25, w: gr.bar, h: 0.26, fill: { color: gr.color }, line: { color: gr.color, width: 0 } });
s.addText(gr.g, { x: 6.55 + gr.bar + 0.08, y: gy + 0.26, w: 0.55, h: 0.24, fontSize: 12, bold: true, color: gr.color, margin: 0 });
});
// CVC removal rule
s.addShape(pres.shapes.RECTANGLE, { x: 6.45, y: 4.5, w: 3.25, h: 0.83, fill: { color: C.redPale }, line: { color: C.red, width: 1 } });
s.addShape(pres.shapes.RECTANGLE, { x: 6.45, y: 4.5, w: 0.06, h: 0.83, fill: { color: C.red }, line: { color: C.red, width: 0 } });
s.addText("CATHETER REMOVAL RULE", { x: 6.6, y: 4.54, w: 3.0, h: 0.24, fontSize: 9, bold: true, color: C.red, margin: 0 });
s.addText("Do NOT remove CVC until patient has had\n6 CONSECUTIVE SUCCESSFUL cannulations\nat prescribed BFR and needle gauge.", {
x: 6.6, y: 4.78, w: 3.0, h: 0.5, fontSize: 7.8, color: C.darkgrey, margin: 0, lineSpacingMultiple: 1.3
});
// Infiltration rule bottom-left
s.addShape(pres.shapes.RECTANGLE, { x: 0.3, y: 4.5, w: 5.9, h: 0.83, fill: { color: "122435" }, line: { color: C.amber, width: 0.75 } });
s.addText("INFILTRATION ESCALATION", { x: 0.48, y: 4.54, w: 2.5, h: 0.24, fontSize: 9, bold: true, color: C.amber, margin: 0 });
const infilt = ["1st: Rest 1 week → restart with smaller gauge", "2nd: Rest 2 weeks → restart with smaller gauge", "3rd: Notify surgeon + nephrologist — STOP cannulation"];
infilt.forEach((inf, ii) => {
s.addText(`${ii + 1}. ${inf}`, { x: 0.48, y: 4.78 + ii * 0.17, w: 5.6, h: 0.18, fontSize: 7.8, color: ii === 2 ? C.red : "9DC8CC", margin: 0 });
});
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 6 — FAILURE TO MATURE: CAUSES & INTERVENTIONS
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 5.625, fill: { color: C.offwhite }, line: { color: C.offwhite, width: 0 } });
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 0.7, fill: { color: C.amber }, line: { color: C.amber, width: 0 } });
s.addText("TROUBLESHOOTING: FAILURE TO MATURE", { x: 0.35, y: 0, w: 8.5, h: 0.7, fontSize: 14, bold: true, color: C.white, valign: "middle", charSpacing: 2, margin: 0 });
pill(s, "SECTION 04", 8.5, 0.21, 1.2, C.navy);
s.addText("6", { x: 9.6, y: 0.48, w: 0.3, h: 0.2, fontSize: 8, color: "8AACB8", align: "right", margin: 0 });
// Stat callouts at top
const ftmStats = [
{ val: "25%", desc: "Primary non-maturation\nrate overall" },
{ val: "+25%", desc: "Need intervention to\nfacilitate maturation" },
{ val: "4–6 wks", desc: "Assess if no change\non physical exam" },
];
ftmStats.forEach((st, i) => {
card(s, 0.3 + i * 3.15, 0.82, 2.95, 0.92, C.white, C.amber);
s.addText(st.val, { x: 0.5 + i * 3.15, y: 0.88, w: 2.55, h: 0.4, fontSize: 22, bold: true, color: C.amber, align: "center", margin: 0 });
s.addText(st.desc, { x: 0.5 + i * 3.15, y: 1.26, w: 2.55, h: 0.38, fontSize: 8, color: C.grey, align: "center", margin: 0, lineSpacingMultiple: 1.2 });
});
// Left: Causes
card(s, 0.3, 1.86, 4.45, 3.44, C.white, C.red);
s.addText("CAUSES OF NON-MATURATION", { x: 0.5, y: 1.93, w: 4.05, h: 0.3, fontSize: 10.5, bold: true, color: C.red, margin: 0 });
const causes = [
{ cat: "Inflow Problem", items: ["Arterial inflow stenosis (most common)", "Kinking at anastomosis", "Low-output cardiac state"] },
{ cat: "Outflow Problem", items: ["Accessory/competing veins (blood steal)", "Central venous stenosis (prior CVC)", "Early venous stenosis/stricture"] },
{ cat: "Vein Issues", items: ["Small caliber vein (<2 mm pre-op)", "Scarred or previously accessed vein", "Deep vein (>6 mm depth)"] },
{ cat: "Patient Factors", items: ["Diabetes / peripheral vascular disease", "Female sex, obesity, older age", "Prior ipsilateral CVC placement"] },
];
let cy2 = 2.3;
causes.forEach((c) => {
s.addText(c.cat, { x: 0.5, y: cy2, w: 4.05, h: 0.22, fontSize: 8.5, bold: true, color: C.darkgrey, margin: 0 });
cy2 += 0.23;
c.items.forEach((item) => {
s.addText("– " + item, { x: 0.65, y: cy2, w: 3.9, h: 0.19, fontSize: 8, color: C.grey, margin: 0 });
cy2 += 0.2;
});
cy2 += 0.07;
});
// Right: Assessment + Intervention
card(s, 4.95, 1.86, 4.75, 1.6, C.white, C.teal);
s.addText("ASSESSMENT", { x: 5.15, y: 1.93, w: 4.35, h: 0.28, fontSize: 10.5, bold: true, color: C.teal, margin: 0 });
const assess = [
"Physical exam at 4–6 weeks post-creation",
"Duplex ultrasound: flow, diameter, depth, stenosis",
"Fistulography (gold standard for anatomical detail)",
"Identify inflow vs outflow problem",
"Check for accessory veins (competing outflow)",
];
assess.forEach((a, ai) => {
s.addText("• " + a, { x: 5.15, y: 2.26 + ai * 0.2, w: 4.35, h: 0.2, fontSize: 8, color: C.grey, margin: 0 });
});
card(s, 4.95, 3.6, 4.75, 1.7, C.white, C.green);
s.addText("INTERVENTIONS", { x: 5.15, y: 3.68, w: 4.35, h: 0.28, fontSize: 10.5, bold: true, color: C.green, margin: 0 });
const interventions = [
{ item: "Accessory vein ligation", detail: "Redirects flow to main fistula vein" },
{ item: "Percutaneous balloon angioplasty", detail: "For inflow/outflow stenosis" },
{ item: "Surgical revision", detail: "Anastomosis revision or jump graft" },
{ item: "Superficialization", detail: "For deep veins (>6 mm depth)" },
{ item: "Maturation assist devices", detail: "External banding for high-flow fistulas" },
];
interventions.forEach((inv, ii) => {
s.addText(inv.item, { x: 5.15, y: 4.02 + ii * 0.24, w: 2.4, h: 0.22, fontSize: 8, bold: true, color: C.darkgrey, margin: 0 });
s.addText(inv.detail, { x: 7.55, y: 4.02 + ii * 0.24, w: 2.05, h: 0.22, fontSize: 7.5, color: C.grey, margin: 0, italics: true });
});
// KDOQI 1-2-3 rule
s.addShape(pres.shapes.RECTANGLE, { x: 0.3, y: 5.28, w: 9.4, h: 0.25, fill: { color: C.amberPale }, line: { color: C.amber, width: 0.75 } });
s.addText("KDOQI 2019 \"1-2-3\" Rule: For each 1 AV access creation → ≤2 interventions to facilitate use → ≤3 interventions to maintain use per year", {
x: 0.5, y: 5.28, w: 9.2, h: 0.25, fontSize: 7.8, color: C.amber, valign: "middle", margin: 0, bold: true
});
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 7 — ACCESS COMPLICATIONS
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
darkBg(s, "0C1625");
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 0.7, fill: { color: C.red }, line: { color: C.red, width: 0 } });
s.addText("ACCESS COMPLICATIONS: RECOGNITION & MANAGEMENT", { x: 0.35, y: 0, w: 8.5, h: 0.7, fontSize: 13, bold: true, color: C.white, valign: "middle", charSpacing: 1.5, margin: 0 });
pill(s, "SECTION 05", 8.5, 0.21, 1.2, C.navy);
s.addText("7", { x: 9.6, y: 0.48, w: 0.3, h: 0.2, fontSize: 8, color: "4A5060", align: "right", margin: 0 });
const complications = [
{
title: "STENOSIS", color: C.red,
sx: ["Weak/discontinuous thrill", "High-pitched bruit", "Swelling of arm/hand", "Prolonged bleeding post-needling"],
mx: ["Duplex US first-line", "Fistulography for confirmation", "Percutaneous angioplasty", "Surgical revision if recurrent"]
},
{
title: "THROMBOSIS", color: C.amber,
sx: ["Loss of thrill/bruit", "Pulsatile (not thrill)", "Pain/tenderness", "No blood on needling"],
mx: ["Urgent referral (<24h)", "Thrombectomy/thrombolysis", "Treat underlying stenosis", "New access if not salvageable"]
},
{
title: "ANEURYSM", color: C.purple,
sx: ["Focal bulging/pulsatile mass", "Skin thinning/discoloration", "Area puncture pattern", "Rapid expansion"],
mx: ["Avoid further cannulation in area", "Monitor with US", "Surgical repair if skin breaking down", "Switch to rope ladder technique"]
},
{
title: "INFECTION", color: C.green,
sx: ["Redness, warmth, swelling", "Purulent discharge", "Fever, bacteremia", "Tenderness at cannulation site"],
mx: ["Blood cultures first", "IV antibiotics (anti-staph)", "Avoid buttonhole technique", "Surgical debridement if abscess"]
},
];
const cols = [
{ x: 0.3, y: 0.85 },
{ x: 5.15, y: 0.85 },
{ x: 0.3, y: 3.2 },
{ x: 5.15, y: 3.2 },
];
complications.forEach((comp, i) => {
const { x, y } = cols[i];
const cw = 4.65;
const ch = 2.15;
card(s, x, y, cw, ch, "162030", null, false);
s.addShape(pres.shapes.RECTANGLE, { x, y, w: cw, h: 0.36, fill: { color: comp.color }, line: { color: comp.color, width: 0 } });
s.addText(comp.title, { x: x + 0.12, y, w: cw - 0.2, h: 0.36, fontSize: 11, bold: true, color: C.white, valign: "middle", charSpacing: 1.5, margin: 0 });
s.addText("SIGNS", { x: x + 0.12, y: y + 0.44, w: 2.0, h: 0.22, fontSize: 8.5, bold: true, color: comp.color, margin: 0 });
comp.sx.forEach((sx, si) => {
s.addText("• " + sx, { x: x + 0.12, y: y + 0.66 + si * 0.19, w: 2.1, h: 0.19, fontSize: 7.8, color: "9DB5C8", margin: 0 });
});
s.addShape(pres.shapes.LINE, { x: x + 2.38, y: y + 0.44, w: 0, h: ch - 0.56, line: { color: "2A3A4A", width: 0.5 } });
s.addText("MANAGEMENT", { x: x + 2.52, y: y + 0.44, w: 2.0, h: 0.22, fontSize: 8.5, bold: true, color: C.teal, margin: 0 });
comp.mx.forEach((mx, mi) => {
s.addText("→ " + mx, { x: x + 2.52, y: y + 0.66 + mi * 0.19, w: 2.02, h: 0.19, fontSize: 7.8, color: "9DC8CC", margin: 0 });
});
});
// Footer
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 5.33, w: 10, h: 0.3, fill: { color: "080E18" }, line: { color: "080E18", width: 0 } });
s.addText("Steal syndrome (ischemic hand): Pain/pallor/pulselessness distal to fistula — urgent vascular referral required.", {
x: 0.3, y: 5.33, w: 9.4, h: 0.3, fontSize: 8, color: C.red, valign: "middle", italics: true, margin: 0
});
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 8 — MONITORING & SURVEILLANCE
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 5.625, fill: { color: C.offwhite }, line: { color: C.offwhite, width: 0 } });
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 0.7, fill: { color: C.green }, line: { color: C.green, width: 0 } });
s.addText("MONITORING & SURVEILLANCE", { x: 0.35, y: 0, w: 8.5, h: 0.7, fontSize: 14, bold: true, color: C.white, valign: "middle", charSpacing: 2, margin: 0 });
pill(s, "SECTION 06", 8.5, 0.21, 1.2, C.teal);
s.addText("8", { x: 9.6, y: 0.48, w: 0.3, h: 0.2, fontSize: 8, color: "8AACB8", align: "right", margin: 0 });
// Physical exam column
card(s, 0.3, 0.85, 4.5, 4.42, C.white, C.green);
s.addText("PRE-DIALYSIS PHYSICAL EXAM", { x: 0.5, y: 0.93, w: 4.1, h: 0.3, fontSize: 10.5, bold: true, color: C.green, margin: 0 });
s.addText("Perform at every session before cannulation", { x: 0.5, y: 1.26, w: 4.1, h: 0.22, fontSize: 8, italics: true, color: C.grey, margin: 0 });
const examSteps = [
{ step: "LOOK", detail: "Skin integrity, bruising, redness, swelling, wound or discharge, aneurysmal dilation, skin thinning" },
{ step: "FEEL", detail: "Continuous soft thrill over entire fistula (absence = thrombosis or severe stenosis). Check pulse augmentation." },
{ step: "LISTEN", detail: "Low-pitched continuous machinery bruit. High-pitched or systolic-only = stenosis upstream from stethoscope." },
{ step: "ELEVATE",detail: "Raise arm above heart level. Normal fistula partially collapses. Failure to collapse = outflow obstruction." },
{ step: "AUGMENT",detail: "Compress fistula proximally. Increased bounce distally = good arterial inflow. Absent = inflow stenosis." },
];
examSteps.forEach((e, i) => {
const ey = 1.56 + i * 0.7;
s.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.5, y: ey, w: 0.85, h: 0.26, fill: { color: C.green }, line: { color: C.green, width: 0 }, rectRadius: 0.04 });
s.addText(e.step, { x: 0.5, y: ey, w: 0.85, h: 0.26, fontSize: 8, bold: true, color: C.white, align: "center", valign: "middle", margin: 0 });
s.addText(e.detail, { x: 1.45, y: ey - 0.04, w: 3.25, h: 0.52, fontSize: 7.8, color: C.grey, margin: 0, lineSpacingMultiple: 1.25 });
});
// Right: surveillance + warning signs
card(s, 5.1, 0.85, 4.6, 2.18, C.white, C.teal);
s.addText("FLOW SURVEILLANCE (KDOQI 2019)", { x: 5.3, y: 0.93, w: 4.2, h: 0.3, fontSize: 10.5, bold: true, color: C.teal, margin: 0 });
s.addText("Kt/V and URR at least monthly (minimum Kt/V ≥1.2 per session)", { x: 5.3, y: 1.28, w: 4.2, h: 0.22, fontSize: 8.5, color: C.grey, margin: 0 });
const surveillance = [
"Access flow measurement (Qa) at regular intervals",
"Qa <600 mL/min or >25% decrease: refer for imaging",
"Static venous pressure >0.5 of mean arterial pressure: stenosis likely",
"Pre-pump arterial pressure increasingly negative: inflow problem",
"Clinical exam is primary; flow-based surveillance supplements it",
];
surveillance.forEach((sv, si) => {
s.addText("• " + sv, { x: 5.3, y: 1.54 + si * 0.265, w: 4.2, h: 0.25, fontSize: 8, color: C.grey, margin: 0 });
});
card(s, 5.1, 3.18, 4.6, 2.09, C.white, C.red);
s.addText("WARNING SIGNS — ACT IMMEDIATELY", { x: 5.3, y: 3.26, w: 4.2, h: 0.3, fontSize: 10, bold: true, color: C.red, margin: 0 });
const warnings = [
["Loss of thrill or bruit", "→ thrombosis until proven otherwise"],
["Sudden arm swelling", "→ central venous stenosis / thrombosis"],
["Hand pain/pallor/cold", "→ steal syndrome — urgent referral"],
["Fever + access tenderness","→ infected access — blood cultures now"],
["Skin necrosis over access","→ stop cannulation, vascular referral"],
];
warnings.forEach((w, wi) => {
s.addText("⚠ " + w[0], { x: 5.3, y: 3.62 + wi * 0.32, w: 2.4, h: 0.28, fontSize: 7.8, bold: true, color: C.red, margin: 0 });
s.addText(w[1], { x: 7.7, y: 3.62 + wi * 0.32, w: 1.85, h: 0.28, fontSize: 7.5, color: C.grey, margin: 0, italics: true });
});
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 9 — CANNULATION TECHNIQUES COMPARISON
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 5.625, fill: { color: "0C1625" }, line: { color: "0C1625", width: 0 } });
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 0.7, fill: { color: C.teal }, line: { color: C.teal, width: 0 } });
s.addText("CANNULATION TECHNIQUES", { x: 0.35, y: 0, w: 8.5, h: 0.7, fontSize: 14, bold: true, color: C.white, valign: "middle", charSpacing: 2, margin: 0 });
s.addText("9", { x: 9.6, y: 0.48, w: 0.3, h: 0.2, fontSize: 8, color: "4A8090", align: "right", margin: 0 });
const techniques = [
{
name: "ROPE LADDER", badge: "RECOMMENDED", badgeColor: C.green, color: C.green,
desc: "Cannulation sites rotate systematically along the entire length of the fistula vein.",
pros: ["Distributes puncture trauma evenly", "Allows vessel wall recovery between sessions", "Prevents focal aneurysm formation", "Reduces stenosis risk", "Most widely guideline-recommended"],
cons: ["Requires longer usable vein segment (≥6 cm)", "Needs careful site mapping and rotation discipline"],
x: 0.3,
},
{
name: "BUTTONHOLE", badge: "USE WITH CAUTION", badgeColor: C.amber, color: C.amber,
desc: "Same exact needle tract used every session. A collagen track forms; blunt needle used for ongoing cannulation.",
pros: ["Reduced pain at cannulation sites", "Lower hematoma rate for suited patients", "Good option for self-cannulation"],
cons: ["HIGH infection risk (esp. S. aureus / MRSA)", "Strict aseptic technique is mandatory", "Not suitable for all patients", "Guidelines increasingly cautious about routine use"],
x: 3.55,
},
{
name: "AREA PUNCTURE", badge: "AVOID", badgeColor: C.red, color: C.red,
desc: "Repeated cannulation in the same small zone without a formal buttonhole track.",
pros: ["None"],
cons: ["High risk of pseudoaneurysm formation", "Leads to stenosis and aneurysm", "Skin breakdown and rupture risk", "Refer to vascular team if identified"],
x: 6.8,
},
];
techniques.forEach((t) => {
const cw = t.name === "AREA PUNCTURE" ? 2.9 : 3.05;
const ch = 4.55;
card(s, t.x, 0.85, cw, ch, "142030", null, false);
s.addShape(pres.shapes.RECTANGLE, { x: t.x, y: 0.85, w: cw, h: 0.06, fill: { color: t.color }, line: { color: t.color, width: 0 } });
// Badge
s.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: t.x + 0.1, y: 0.97, w: cw - 0.2, h: 0.28, fill: { color: t.badgeColor }, line: { color: t.badgeColor, width: 0 }, rectRadius: 0.04 });
s.addText(t.badge, { x: t.x + 0.1, y: 0.97, w: cw - 0.2, h: 0.28, fontSize: 8, bold: true, color: "0C1625", align: "center", valign: "middle", margin: 0, charSpacing: 1 });
s.addText(t.name, { x: t.x + 0.12, y: 1.34, w: cw - 0.22, h: 0.32, fontSize: 13, bold: true, color: t.color, margin: 0 });
s.addText(t.desc, { x: t.x + 0.12, y: 1.7, w: cw - 0.22, h: 0.6, fontSize: 7.8, color: "9DB5C8", margin: 0, lineSpacingMultiple: 1.3 });
hline(s, t.x + 0.12, 2.36, cw - 0.24, "2A3A4A");
s.addText("✓ ADVANTAGES", { x: t.x + 0.12, y: 2.42, w: cw - 0.22, h: 0.22, fontSize: 8.5, bold: true, color: C.green, margin: 0 });
t.pros.forEach((p, pi) => {
s.addText("+ " + p, { x: t.x + 0.12, y: 2.66 + pi * 0.2, w: cw - 0.22, h: 0.2, fontSize: 7.5, color: C.greenPale === "E8F5EE" ? "70BF8A" : C.greenPale, margin: 0 });
});
const consY = 2.66 + t.pros.length * 0.2 + 0.12;
s.addText("✗ DISADVANTAGES", { x: t.x + 0.12, y: consY, w: cw - 0.22, h: 0.22, fontSize: 8.5, bold: true, color: C.red, margin: 0 });
t.cons.forEach((c, ci) => {
s.addText("– " + c, { x: t.x + 0.12, y: consY + 0.24 + ci * 0.2, w: cw - 0.22, h: 0.2, fontSize: 7.5, color: "C08080", margin: 0 });
});
});
// Footer
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 5.36, w: 10, h: 0.265, fill: { color: "070E1A" }, line: { color: "070E1A", width: 0 } });
s.addText("Single-needle dialysis: acceptable as a bridge during early maturation only. Lower Kt/V — increase session time to compensate. Keep CVC in situ.", {
x: 0.3, y: 5.36, w: 9.4, h: 0.265, fontSize: 7.8, color: "6A9AB0", valign: "middle", italics: true, margin: 0
});
}
// ══════════════════════════════════════════════════════════════════════════
// SLIDE 10 — REFERENCES + SUMMARY
// ══════════════════════════════════════════════════════════════════════════
{
const s = pres.addSlide();
darkBg(s, C.navy);
s.addShape(pres.shapes.OVAL, { x: 7.2, y: 3.5, w: 4.5, h: 4.5, fill: { color: C.teal, transparency: 88 }, line: { color: C.teal, width: 0 } });
s.addShape(pres.shapes.OVAL, { x: -1.5, y: -0.8, w: 4, h: 4, fill: { color: C.tealLight, transparency: 90 }, line: { color: C.tealLight, width: 0 } });
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 0.68, fill: { color: C.teal }, line: { color: C.teal, width: 0 } });
s.addText("KEY TAKEAWAYS & REFERENCES", { x: 0.35, y: 0, w: 8.5, h: 0.68, fontSize: 14, bold: true, color: C.white, valign: "middle", charSpacing: 2, margin: 0 });
pill(s, "SECTION 07", 8.5, 0.2, 1.2, C.navy);
s.addText("10", { x: 9.5, y: 0.47, w: 0.35, h: 0.2, fontSize: 8, color: "4A8090", align: "right", margin: 0 });
// Takeaways
s.addText("KEY TAKEAWAYS", { x: 0.3, y: 0.85, w: 4.5, h: 0.3, fontSize: 11, bold: true, color: "7ECFD6", margin: 0, charSpacing: 1 });
const takeaways = [
"Never cannulate a new AVF without surgeon/nephrologist order and ≥8 weeks maturation",
"Rule of 6s is a guide only — KDOQI 2019 confirms 50% success rate even when criteria met",
"Arterial needle: retrograde (toward anastomosis). Venous needle: antegrade (toward heart)",
"Match needle gauge to BFR: 17G → 16G → 15G → 14G. Progress weekly, only if no complications",
"Rope ladder technique is the safest long-term strategy; avoid area puncture entirely",
"Buttonhole technique carries high infection risk — use cautiously with strict asepsis",
"6 consecutive successful cannulations required before removing central venous catheter",
"Failure to mature rate is 25%; 25% more need intervention. Assess with duplex US at 4–6 weeks if no progress",
"Thrombosis = loss of thrill → urgent referral within 24 hours. Every hour matters.",
"Steal syndrome (hand ischemia) requires immediate vascular referral",
];
takeaways.forEach((t, i) => {
s.addText(`${i + 1}. ${t}`, { x: 0.3, y: 1.22 + i * 0.38, w: 5.6, h: 0.35, fontSize: 8, color: i < 3 ? "B0DDE2" : "8AACB8", margin: 0, lineSpacingMultiple: 1.1 });
});
// References
s.addShape(pres.shapes.RECTANGLE, { x: 6.1, y: 0.85, w: 3.6, h: 4.44, fill: { color: "132033" }, line: { color: "2A3A4A", width: 0.5 } });
s.addText("REFERENCES", { x: 6.28, y: 0.93, w: 3.2, h: 0.28, fontSize: 10, bold: true, color: "7ECFD6", margin: 0, charSpacing: 1 });
hline(s, 6.28, 1.25, 3.2, "2A4060");
const refs = [
["KDOQI 2019", "Clinical Practice Guideline for Vascular Access. Am J Kidney Dis. 2019;75(4 Suppl 2):S1–S164."],
["VASBI 2018", "Clinical Practice Recommendations for Needling of AV Fistulae. vasbi.org.uk"],
["Karkhah S et al. 2023", "Needle Direction and Distance of AVF Cannulation in HD Adequacy. Arch Acad Emerg Med. PMID: 37609532."],
["NIH HFM Study", "Hemodialysis Fistula Maturation Study. JAMA. 2016;316(19):1985–1994."],
["Brenner & Rector", "The Kidney, 2-Volume Set. Chap. 63: Hemodialysis. Elsevier."],
["Midwest Kidney Network", "Cannulation of New Fistula Policy & Procedure. midwestkidneynetwork.org"],
];
refs.forEach((r, ri) => {
s.addText(r[0], { x: 6.28, y: 1.34 + ri * 0.55, w: 3.2, h: 0.2, fontSize: 8, bold: true, color: C.teal, margin: 0 });
s.addText(r[1], { x: 6.28, y: 1.54 + ri * 0.55, w: 3.2, h: 0.28, fontSize: 7.2, color: "6A8898", margin: 0, lineSpacingMultiple: 1.15 });
});
// Bottom disclaimer
s.addShape(pres.shapes.RECTANGLE, { x: 0, y: 5.3, w: 10, h: 0.325, fill: { color: "0A1520" }, line: { color: "0A1520", width: 0 } });
s.addText("Clinical reference for educational purposes only. Does not replace institutional protocols, physician judgment, or patient-specific management. Always obtain appropriate orders.", {
x: 0.3, y: 5.3, w: 9.4, h: 0.325, fontSize: 7.5, color: "4A6878", valign: "middle", italics: true, margin: 0, align: "center"
});
}
// ── Write file ─────────────────────────────────────────────────────────────
pres.writeFile({ fileName: OUT })
.then(() => console.log("PPTX generated: " + OUT))
.catch(err => { console.error(err); process.exit(1); });
cd /home/daytona/workspace/fistula-pptx && node build.js 2>&1
ls -lh /home/daytona/workspace/fistula-pptx/AV_Fistula_Maturation_Troubleshootin…
AV Fistula Maturation Troubleshooting
Presentation · PPTX
| # | Slide | Design |
|---|---|---|
| 1 | Title | Dark navy with teal accents; 4 key stat cards at bottom (25% failure, 8-12 wks, 6mm, 600 mL/min) |
| 2 | Overview / Agenda | Light background; 7 numbered section cards with descriptions |
| 3 | Maturation Timeline | Dark slide with horizontal spine timeline - Day 0 Surgery → Wk 1-2 → Wk 3-4 → Wk 6-8 → Wk 8-12, with physiological milestones above and below each node |
| 4 | Maturation Criteria | Rule of 6s table, KDOQI 2019 "50% success" warning, functional maturity definition, AV graft timeline, pre-cannulation exam |
| 5 | Cannulation Progression | Dark slide; week-by-week protocol cards (Wk1/17G/200mL → Wk2/16G/300mL → Wk3+/14-15G/450mL+), needle gauge bar chart, catheter removal rule, infiltration escalation |
| 6 | Failure to Mature | Amber header; stat callouts (25% failure, +25% need intervention), causes grid (inflow/outflow/vein/patient), assessment checklist, 5-step intervention ladder |
| 7 | Complications | Dark red-accented; 4 complication cards - Stenosis, Thrombosis, Aneurysm, Infection - each with signs and management columns |
| 8 | Monitoring & Surveillance | Green-accented; 5-step physical exam (Look/Feel/Listen/Elevate/Augment), flow surveillance criteria, 5 warning signs requiring immediate action |
| 9 | Cannulation Techniques | Dark 3-column layout comparing Rope Ladder (green/recommended), Buttonhole (amber/caution), Area Puncture (red/avoid) |
| 10 | Takeaways & References | Dark slide; 10 key takeaways + 6 cited references panel |