Small bowel transplantation Illustrated images Flowcharts Give in PDF

Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Reading File
Reading File
Loading Image
Reading File
Loading Image
Loading Image
Loading Image
Loading Image
Reading File
Running Command

mkdir -p /tmp/workspace/sbt-pdf && ls /tmp/workspace/sbt-pdf/

Running Command

cd /tmp/workspace/sbt-pdf && python3 -c " import urllib.request images = { 'trend.png': 'https://cdn.orris.care/cdss_images/39a781f3b753b2884868f5b22751c5333f585763897f52e1bcb119d491229deb.png', 'full_multivisceral.png': 'https://cdn.orris.care/cdss_images/3e24006b711a378210565b8aa3eaaf2a5b4c81120af4aa2989761f7efc826381.png', 'liver_small_bowel.png': 'https://cdn.orris.care/cdss_images/8f657d7ea2c55608d17877ddb2fb4af4ce370556661c3d01115040a0938234cf.png', 'modified_multivisceral.png': 'https://cdn.orris.care/cdss_images/22e0e085b9a6ec179f227404b40e30d6451d63f9697f008200eaeb9f6355f308.png', 'sb_pancreas_colon.png': 'https://cdn.orris.care/cdss_images/1e630c09aeb71ebb4ed3c9d531b5ae11c6cb38dacfe8288c4666c202cbddc7e4.png', } for fname, url in images.items(): urllib.request.urlretrieve(url, fname) print(f'Downloaded {fname}') "

Writing File

~/sbt-pdf/generate_pdf.py


from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm, mm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Image, Table, TableStyle,
    PageBreak, HRFlowable, KeepTogether
)
from reportlab.platypus.flowables import Flowable
from reportlab.graphics.shapes import Drawing, Rect, String, Line, Polygon, Arrow
from reportlab.graphics import renderPDF
from reportlab.graphics.charts.barcharts import VerticalBarChart
import os

# ── Page setup ──────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
    "/tmp/workspace/sbt-pdf/Small_Bowel_Transplantation.pdf",
    pagesize=A4,
    leftMargin=2*cm, rightMargin=2*cm,
    topMargin=2.5*cm, bottomMargin=2.5*cm,
    title="Small Bowel Transplantation",
    author="Medical Library – Orris"
)

W, H = A4
CONTENT_W = W - 4*cm

# ── Colour palette ────────────────────────────────────────────────────────
DARK_BLUE   = colors.HexColor("#1A3A5C")
MID_BLUE    = colors.HexColor("#2E6DA4")
LIGHT_BLUE  = colors.HexColor("#D6E8F7")
ACCENT      = colors.HexColor("#E8523A")
GREEN       = colors.HexColor("#2E8B57")
LIGHT_GREEN = colors.HexColor("#D4EDDA")
ORANGE      = colors.HexColor("#E07B39")
LIGHT_ORANGE= colors.HexColor("#FFF3E0")
YELLOW_BG   = colors.HexColor("#FFFDE7")
GREY_BG     = colors.HexColor("#F5F5F5")
WHITE       = colors.white

# ── Styles ─────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()

title_style = ParagraphStyle("Title",
    fontName="Helvetica-Bold", fontSize=26, leading=32,
    textColor=WHITE, alignment=TA_CENTER, spaceAfter=4)

subtitle_style = ParagraphStyle("Subtitle",
    fontName="Helvetica", fontSize=13, leading=18,
    textColor=colors.HexColor("#B8D4F0"), alignment=TA_CENTER, spaceAfter=8)

h1 = ParagraphStyle("H1",
    fontName="Helvetica-Bold", fontSize=16, leading=20,
    textColor=WHITE, spaceBefore=14, spaceAfter=6,
    backColor=DARK_BLUE, leftIndent=-4, rightIndent=-4,
    borderPad=6)

h2 = ParagraphStyle("H2",
    fontName="Helvetica-Bold", fontSize=13, leading=17,
    textColor=MID_BLUE, spaceBefore=10, spaceAfter=4,
    borderPadding=(0,0,2,0))

h3 = ParagraphStyle("H3",
    fontName="Helvetica-Bold", fontSize=11, leading=14,
    textColor=DARK_BLUE, spaceBefore=6, spaceAfter=3)

body = ParagraphStyle("Body",
    fontName="Helvetica", fontSize=10, leading=14,
    textColor=colors.HexColor("#222222"), spaceAfter=5,
    alignment=TA_JUSTIFY)

bullet = ParagraphStyle("Bullet",
    fontName="Helvetica", fontSize=10, leading=13,
    textColor=colors.HexColor("#333333"),
    leftIndent=14, bulletIndent=4, spaceAfter=2)

caption = ParagraphStyle("Caption",
    fontName="Helvetica-Oblique", fontSize=8.5, leading=11,
    textColor=colors.HexColor("#555555"), alignment=TA_CENTER, spaceAfter=6)

box_title = ParagraphStyle("BoxTitle",
    fontName="Helvetica-Bold", fontSize=10, leading=13,
    textColor=DARK_BLUE)

box_body = ParagraphStyle("BoxBody",
    fontName="Helvetica", fontSize=9.5, leading=13,
    textColor=colors.HexColor("#333333"), leftIndent=8, spaceAfter=2)

# ── Helper: section header bar ─────────────────────────────────────────────
def section_header(text):
    tbl = Table([[Paragraph(text, h1)]], colWidths=[CONTENT_W])
    tbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), DARK_BLUE),
        ("BOTTOMPADDING",(0,0),(-1,-1), 6),
        ("TOPPADDING",   (0,0),(-1,-1), 6),
        ("LEFTPADDING",  (0,0),(-1,-1), 10),
        ("RIGHTPADDING", (0,0),(-1,-1), 10),
        ("ROUNDEDCORNERS", [4]),
    ]))
    return tbl

def info_box(title, items, bg=LIGHT_BLUE, title_color=DARK_BLUE):
    content = [Paragraph(title, ParagraphStyle("BT", fontName="Helvetica-Bold",
                fontSize=10, textColor=title_color, spaceAfter=4))]
    for item in items:
        content.append(Paragraph(f"• {item}", box_body))
    tbl = Table([[content]], colWidths=[CONTENT_W])
    tbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), bg),
        ("BOX", (0,0), (-1,-1), 1, title_color),
        ("TOPPADDING", (0,0), (-1,-1), 8),
        ("BOTTOMPADDING", (0,0), (-1,-1), 8),
        ("LEFTPADDING", (0,0), (-1,-1), 10),
        ("RIGHTPADDING", (0,0), (-1,-1), 10),
    ]))
    return tbl

# ── Flowchart helper ───────────────────────────────────────────────────────
class FlowchartBox(Flowable):
    """Draws a simple vertical flowchart with boxes and arrows."""
    def __init__(self, steps, width=None, step_height=28, gap=18, title=""):
        Flowable.__init__(self)
        self.steps = steps   # list of (text, bg_color, text_color)
        self.width = width or CONTENT_W
        self.step_height = step_height
        self.gap = gap
        self.title = title
        self.n = len(steps)
        self.height = self.n * step_height + (self.n-1)*gap + (30 if title else 0) + 10

    def draw(self):
        c = self.canv
        y = self.height - 5
        bw = self.width

        if self.title:
            c.setFont("Helvetica-Bold", 11)
            c.setFillColor(DARK_BLUE)
            c.drawCentredString(bw/2, y - 14, self.title)
            y -= 30

        for i, (text, bg, fg) in enumerate(self.steps):
            box_y = y - self.step_height
            # Drop shadow
            c.setFillColor(colors.HexColor("#CCCCCC"))
            c.roundRect(3, box_y - 3, bw - 6, self.step_height, 6, fill=1, stroke=0)
            # Box
            c.setFillColor(bg)
            c.setStrokeColor(DARK_BLUE)
            c.setLineWidth(0.8)
            c.roundRect(0, box_y, bw - 6, self.step_height, 6, fill=1, stroke=1)
            # Text
            c.setFillColor(fg)
            c.setFont("Helvetica-Bold" if i == 0 else "Helvetica", 9)
            # Wrap text manually
            words = text.split()
            lines, cur = [], []
            for w in words:
                test = " ".join(cur + [w])
                if c.stringWidth(test, "Helvetica", 9) < bw - 30:
                    cur.append(w)
                else:
                    lines.append(" ".join(cur))
                    cur = [w]
            if cur:
                lines.append(" ".join(cur))
            total_h = len(lines) * 11
            start_y = box_y + self.step_height/2 + total_h/2 - 3
            for li, line in enumerate(lines):
                c.drawCentredString((bw-6)/2, start_y - li*11, line)

            y = box_y - 2
            # Arrow to next
            if i < self.n - 1:
                c.setStrokeColor(MID_BLUE)
                c.setFillColor(MID_BLUE)
                c.setLineWidth(1.5)
                ax = (bw-6)/2
                ay_top = y
                ay_bot = y - self.gap + 6
                c.line(ax, ay_top, ax, ay_bot)
                # Arrowhead
                c.setFillColor(MID_BLUE)
                c.polygon([ax-5, ay_bot+7, ax+5, ay_bot+7, ax, ay_bot], fill=1, stroke=0)
                y -= self.gap

    def wrap(self, *args):
        return self.width, self.height


class DecisionFlowchart(Flowable):
    """Decision tree / branching flowchart."""
    def __init__(self, width=None):
        Flowable.__init__(self)
        self.width = width or CONTENT_W
        self.height = 310

    def draw(self):
        c = self.canv
        W = self.width
        cx = W / 2

        def box(x, y, w, h, text, bg, fg=WHITE, bold=True):
            c.setFillColor(colors.HexColor("#BBBBBB"))
            c.roundRect(x+2, y-2, w, h, 5, fill=1, stroke=0)
            c.setFillColor(bg)
            c.setStrokeColor(DARK_BLUE)
            c.setLineWidth(0.8)
            c.roundRect(x, y, w, h, 5, fill=1, stroke=1)
            c.setFillColor(fg)
            fn = "Helvetica-Bold" if bold else "Helvetica"
            c.setFont(fn, 8.5)
            words = text.split("\n")
            tot = len(words)*10
            sy = y + h/2 + tot/2 - 8
            for i, line in enumerate(words):
                c.drawCentredString(x + w/2, sy - i*10, line)

        def diamond(x, y, w, h, text, bg=ORANGE):
            pts = [x+w/2, y+h, x+w, y+h/2, x+w/2, y, x, y+h/2]
            c.setFillColor(bg)
            c.setStrokeColor(DARK_BLUE)
            c.setLineWidth(0.8)
            c.polygon(pts, fill=1, stroke=1)
            c.setFillColor(WHITE)
            c.setFont("Helvetica-Bold", 8)
            c.drawCentredString(x+w/2, y+h/2-4, text)

        def arrow(x1, y1, x2, y2, label=""):
            c.setStrokeColor(MID_BLUE)
            c.setLineWidth(1.2)
            c.line(x1, y1, x2, y2)
            dx, dy = x2-x1, y2-y1
            import math
            l = math.sqrt(dx*dx+dy*dy)
            if l > 0:
                ux, uy = dx/l, dy/l
                ax = x2 - 6*ux; ay = y2 - 6*uy
                c.setFillColor(MID_BLUE)
                perp_x, perp_y = -uy, ux
                c.polygon([x2, y2, ax+4*perp_x, ay+4*perp_y, ax-4*perp_x, ay-4*perp_y], fill=1, stroke=0)
            if label:
                mx, my = (x1+x2)/2, (y1+y2)/2
                c.setFillColor(colors.HexColor("#333333"))
                c.setFont("Helvetica", 7.5)
                c.drawCentredString(mx+8, my+3, label)

        BW = 140; BH = 28; DW = 110; DH = 36

        # START
        box(cx-70, 278, 140, 28, "Intestinal Failure", DARK_BLUE)
        arrow(cx, 278, cx, 258)

        # Diamond 1
        diamond(cx-DW/2, 222, DW, DH, "PN Dependent?", ORANGE)
        arrow(cx, 222, cx, 198)

        # Yes continue
        box(cx-70, 170, 140, 26, "Assess PN Complications", MID_BLUE)
        arrow(cx, 170, cx, 148)

        # Diamond 2
        diamond(cx-55, 108, 110, 38, "Life-threatening\nComplications?", colors.HexColor("#C0392B"))
        # No - right
        arrow(cx+55, 127, cx+110, 127, "No")
        box(cx+110, 113, 110, 28, "Continue PN\n+ Rehabilitation", GREEN, WHITE, False)

        # Yes - down
        arrow(cx, 108, cx, 86)

        box(cx-70, 60, 140, 26, "List for Transplant", DARK_BLUE)
        arrow(cx, 60, cx, 38)

        box(cx-70, 12, 140, 26, "Transplant Type Selection", MID_BLUE)

        # No from diamond 1 (right)
        arrow(cx+DW/2, 240, cx+140, 240, "No")
        box(cx+140, 226, 105, 28, "Medical\nManagement", GREEN, WHITE, False)

        # Title
        c.setFont("Helvetica-Bold", 10)
        c.setFillColor(DARK_BLUE)
        c.drawCentredString(W/2, self.height-12, "Decision Flowchart: Pathway to Small Bowel Transplantation")

    def wrap(self, *args):
        return self.width, self.height


# ── Cover page ─────────────────────────────────────────────────────────────
def cover_page(story):
    # Blue header block
    cover_tbl = Table(
        [[Paragraph("SMALL BOWEL\nTRANSPLANTATION", title_style)],
         [Paragraph("Comprehensive Clinical Reference with Illustrated Diagrams & Flowcharts", subtitle_style)],
         [Paragraph("Sources: Sabiston Textbook of Surgery (22e) · Bailey & Love's Surgery (28e)\n"
                    "Yamada's Gastroenterology (7e) · Fischer's Mastery of Surgery (8e)", subtitle_style)]],
        colWidths=[CONTENT_W]
    )
    cover_tbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), DARK_BLUE),
        ("TOPPADDING", (0,0), (-1,-1), 24),
        ("BOTTOMPADDING", (0,-1), (-1,-1), 24),
        ("LEFTPADDING", (0,0), (-1,-1), 20),
        ("RIGHTPADDING", (0,0), (-1,-1), 20),
    ]))
    story.append(cover_tbl)
    story.append(Spacer(1, 0.5*cm))

    # Quick facts boxes
    facts = [
        ("Least Common Solid Organ Transplant",
         "~82 performed in the USA in 2022 (UNOS). Peak ~200/year in 2007. "
         "Only ~3,400 total procedures since 1985."),
        ("1-Year Patient Survival",
         "~76% (ITR registry). Up from 25% in early 1990s cyclosporine era. "
         "Improved markedly after tacrolimus introduction (1994)."),
        ("Most Common Indication",
         "Short bowel syndrome (SBS) ~63–64% in both pediatric and adult recipients. "
         "Pediatric: gastroschisis, volvulus, NEC. Adults: ischaemia, Crohn disease."),
    ]
    cols = []
    for title, text in facts:
        cell = [
            Paragraph(title, ParagraphStyle("FT", fontName="Helvetica-Bold", fontSize=10,
                      textColor=DARK_BLUE, spaceAfter=4)),
            Paragraph(text, ParagraphStyle("FB", fontName="Helvetica", fontSize=9.5,
                      textColor=colors.HexColor("#333333")))
        ]
        cols.append(cell)
    ft = Table([cols], colWidths=[CONTENT_W/3 - 3]*3, rowHeights=None)
    ft.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (0,0), LIGHT_BLUE),
        ("BACKGROUND", (1,0), (1,0), LIGHT_GREEN),
        ("BACKGROUND", (2,0), (2,0), LIGHT_ORANGE),
        ("BOX", (0,0), (0,0), 1, MID_BLUE),
        ("BOX", (1,0), (1,0), 1, GREEN),
        ("BOX", (2,0), (2,0), 1, ORANGE),
        ("TOPPADDING", (0,0), (-1,-1), 8),
        ("BOTTOMPADDING", (0,0), (-1,-1), 8),
        ("LEFTPADDING", (0,0), (-1,-1), 8),
        ("RIGHTPADDING", (0,0), (-1,-1), 8),
        ("VALIGN", (0,0), (-1,-1), "TOP"),
        ("COLPADDING", (0,0), (-1,-1), 6),
    ]))
    story.append(ft)
    story.append(Spacer(1, 0.4*cm))

    # Trend image
    if os.path.exists("/tmp/workspace/sbt-pdf/trend.png"):
        img = Image("/tmp/workspace/sbt-pdf/trend.png", width=12*cm, height=4*cm)
        story.append(img)
        story.append(Paragraph(
            "Fig 1. Number of intestinal transplants performed annually in the United States, 1990–2023. "
            "(Source: UNOS OPTN Metrics / Sabiston Textbook of Surgery, 22e)",
            caption))

    story.append(PageBreak())


# ── Section 1: Background & History ───────────────────────────────────────
def section_history(story):
    story.append(section_header("1.  Background & Historical Overview"))
    story.append(Spacer(1, 0.2*cm))
    story.append(Paragraph(
        "The small bowel (intestine) is the most immunogenic solid organ due to its large lymphoid mass. "
        "This made early transplantation attempts uniformly fatal. The history of intestinal transplantation "
        "spans decades of incremental progress:", body))

    timeline = [
        ["1960s", "Starzl performs first experimental SBT in dogs; all died within 9 days. "
                  "Clinical attempts in humans fail — no patient achieves enteral autonomy."],
        ["Late 1960s", "PN introduced. Clinical SBT abandoned due to poor outcomes and the availability "
                       "of a safer alternative."],
        ["1983", "Cyclosporine enters clinical use. Renewed interest in SBT alongside growing awareness "
                 "of PN-related morbidity."],
        ["1988", "First successful SBT by Deltz (living donor) achieving enteral autonomy. "
                 "Same year: Grant et al. perform first cadaveric liver–intestine transplant with >1-year survival."],
        ["1990–94", "1-year survival ~25% with cyclosporine. Tacrolimus introduced (1994) — major "
                    "improvement in rejection control."],
        ["2007", "Peak activity: ~200 intestinal transplants/year in the USA."],
        ["2010s–present", "Volume stabilises at ~80–150/year. Improvement in pediatric intestinal "
                          "rehabilitation reduces need in children. Adults now dominate the waitlist."],
    ]
    tbl = Table(
        [[Paragraph(r[0], ParagraphStyle("Year", fontName="Helvetica-Bold", fontSize=9.5,
                    textColor=DARK_BLUE)),
          Paragraph(r[1], ParagraphStyle("Evt", fontName="Helvetica", fontSize=9.5, leading=13))]
         for r in timeline],
        colWidths=[2.8*cm, CONTENT_W - 2.8*cm]
    )
    tbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (0,-1), LIGHT_BLUE),
        ("BACKGROUND", (1,0), (1,-1), GREY_BG),
        ("ROWBACKGROUNDS", (1,0), (1,-1), [WHITE, GREY_BG]),
        ("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#CCCCCC")),
        ("TOPPADDING", (0,0), (-1,-1), 5),
        ("BOTTOMPADDING", (0,0), (-1,-1), 5),
        ("LEFTPADDING", (0,0), (-1,-1), 8),
        ("VALIGN", (0,0), (-1,-1), "TOP"),
    ]))
    story.append(tbl)
    story.append(Spacer(1, 0.3*cm))


# ── Section 2: Indications ─────────────────────────────────────────────────
def section_indications(story):
    story.append(section_header("2.  Indications for Small Bowel Transplantation"))
    story.append(Spacer(1, 0.2*cm))
    story.append(Paragraph(
        "<b>PN dependence alone is NOT an indication.</b> Transplant is reserved for patients with "
        "irreversible intestinal failure AND at least one life-threatening PN complication "
        "(Sixth International SBT Symposium 2001; updated 2015 at XIV Symposium):", body))

    indications = [
        ("Advanced / Progressive IFALD",
         "Intestinal failure-associated liver disease progressing despite optimised management. "
         "Combined liver–intestine transplant is considered."),
        ("Loss of Central Venous Access",
         "Multiple central vein thromboses leaving <2 usable central venous sites."),
        ("Recurrent Life-Threatening Sepsis",
         "≥2 ICU admissions for catheter-related bloodstream infections."),
        ("Invasive Intraabdominal Desmoids",
         "Unresectable desmoid tumours rendering enteral feeding impossible."),
        ("Acute Diffuse Intestinal Infarction with Hepatic Failure",
         "Rare emergency indication — acute loss of entire gut with concomitant liver failure."),
        ("First Transplant Failure",
         "Retransplantation following graft loss."),
        ("High Morbidity / Poor QoL",
         "Frequent hospitalisation, severe electrolyte disturbances — not universally accepted."),
        ("Diffuse Portomesenteric Thrombosis (Yerdel grade 4)",
         "Multivisceral transplant replaces entire portal system; only definitive treatment."),
    ]

    rows = []
    for i, (ind, detail) in enumerate(indications):
        rows.append([
            Paragraph(f"{i+1}. {ind}", ParagraphStyle("IndT", fontName="Helvetica-Bold",
                      fontSize=9.5, textColor=DARK_BLUE)),
            Paragraph(detail, ParagraphStyle("IndD", fontName="Helvetica", fontSize=9.5, leading=13))
        ])
    tbl = Table(rows, colWidths=[5.2*cm, CONTENT_W-5.2*cm])
    tbl.setStyle(TableStyle([
        ("ROWBACKGROUNDS", (0,0), (-1,-1), [LIGHT_BLUE, WHITE]),
        ("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#BBBBBB")),
        ("TOPPADDING", (0,0), (-1,-1), 6),
        ("BOTTOMPADDING", (0,0), (-1,-1), 6),
        ("LEFTPADDING", (0,0), (-1,-1), 8),
        ("VALIGN", (0,0), (-1,-1), "TOP"),
        ("BOX", (0,0), (-1,-1), 1, MID_BLUE),
    ]))
    story.append(tbl)
    story.append(Spacer(1, 0.3*cm))

    # Underlying conditions table
    story.append(Paragraph("Underlying Conditions Necessitating Intestinal Transplantation (ITR Data):", h2))
    story.append(Spacer(1, 0.15*cm))
    cond_data = [
        [Paragraph("<b>Pediatric Condition</b>", box_title),
         Paragraph("<b>%</b>", box_title),
         Paragraph("<b>Adult Condition</b>", box_title),
         Paragraph("<b>%</b>", box_title)],
        ["Short bowel syndrome", "63%", "Short bowel syndrome", "64%"],
        ["Gastroschisis", "22%", "Ischaemia", "11%"],
        ["Volvulus", "16%", "Crohn disease", "10%"],
        ["Necrotising enterocolitis", "14%", "Volvulus", "7%"],
        ["Motility disorders", "18%", "Motility disorders", "11%"],
        ["Atresia", "4%", "Trauma", "7%"],
        ["Malabsorption syndromes", "8%", "Tumour", "13%"],
        ["Retransplantation", "8%", "Retransplantation", "7%"],
    ]
    cw = CONTENT_W / 4
    ctbl = Table(cond_data, colWidths=[cw*1.6, cw*0.4, cw*1.6, cw*0.4])
    ctbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
        ("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, LIGHT_BLUE]),
        ("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#CCCCCC")),
        ("TOPPADDING", (0,0), (-1,-1), 4),
        ("BOTTOMPADDING", (0,0), (-1,-1), 4),
        ("LEFTPADDING", (0,0), (-1,-1), 7),
        ("BOX", (0,0), (-1,-1), 1, MID_BLUE),
        ("ALIGN", (1,0), (1,-1), "CENTER"),
        ("ALIGN", (3,0), (3,-1), "CENTER"),
    ]))
    story.append(ctbl)
    story.append(Spacer(1, 0.3*cm))

    # Decision flowchart
    story.append(Paragraph("Decision Pathway – From Intestinal Failure to Transplant:", h2))
    story.append(Spacer(1, 0.2*cm))
    story.append(DecisionFlowchart(width=CONTENT_W))
    story.append(Spacer(1, 0.2*cm))


# ── Section 3: Types of Transplant ────────────────────────────────────────
def section_types(story):
    story.append(PageBreak())
    story.append(section_header("3.  Types of Intestinal / Multivisceral Transplant"))
    story.append(Spacer(1, 0.2*cm))
    story.append(Paragraph(
        "Intestinal transplantation encompasses several 'cluster' configurations depending on which "
        "organs are included. Selection depends on hepatic function, portal vein patency, "
        "intraabdominal anatomy, and intraoperative findings.", body))

    types_data = [
        [Paragraph("<b>Transplant Type</b>", box_title),
         Paragraph("<b>Organs Included</b>", box_title),
         Paragraph("<b>Extent of Resection</b>", box_title),
         Paragraph("<b>Proximal Anastomosis</b>", box_title)],
        ["Isolated Small Intestine (+/- colon)",
         "Small intestine ± colon ± pancreas",
         "Small intestine + part of colon",
         "Duodenum or proximal jejunum"],
        ["Liver + Small Bowel",
         "Liver, pancreas, small intestine, colon",
         "Liver, small intestine + part of colon",
         "Duodenum or proximal jejunum"],
        ["Modified Multivisceral",
         "Stomach, pancreas, small intestine, colon",
         "Stomach, pancreas, spleen, small intestine, colon",
         "Proximal stomach or oesophagus"],
        ["Full Multivisceral",
         "Liver, stomach, pancreas, small intestine, colon",
         "Liver, stomach, pancreas, spleen, small intestine, colon",
         "Proximal stomach or oesophagus"],
    ]
    cws = [3.5*cm, 4.2*cm, 4.5*cm, 3.8*cm]
    ttbl = Table(types_data, colWidths=cws)
    ttbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
        ("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, LIGHT_BLUE]),
        ("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#CCCCCC")),
        ("TOPPADDING", (0,0), (-1,-1), 5),
        ("BOTTOMPADDING", (0,0), (-1,-1), 5),
        ("LEFTPADDING", (0,0), (-1,-1), 6),
        ("BOX", (0,0), (-1,-1), 1, MID_BLUE),
        ("VALIGN", (0,0), (-1,-1), "TOP"),
    ]))
    story.append(ttbl)
    story.append(Spacer(1, 0.4*cm))

    # Images in 2x2 grid
    img_data = []
    imgs_info = [
        ("full_multivisceral.png", "Full Multivisceral Transplant\n(Liver, stomach, pancreas, SB, colon)"),
        ("liver_small_bowel.png", "Liver + Small Bowel Transplant\n(Liver, pancreas, SB, colon)"),
        ("modified_multivisceral.png", "Modified Multivisceral Transplant\n(No liver: stomach, pancreas, SB, colon)"),
        ("sb_pancreas_colon.png", "Small Bowel, Pancreas & Colon Transplant\n(SMA, ileocolic, middle colic arteries shown)"),
    ]
    cell_w = CONTENT_W / 2 - 0.3*cm
    row1, row2 = [], []
    for i, (fname, cap) in enumerate(imgs_info):
        fp = f"/tmp/workspace/sbt-pdf/{fname}"
        if os.path.exists(fp):
            img = Image(fp, width=cell_w - 0.4*cm, height=7*cm, kind="proportional")
        else:
            img = Paragraph("[Image not found]", caption)
        cell = [img, Paragraph(cap, caption)]
        if i < 2:
            row1.append(cell)
        else:
            row2.append(cell)
    img_tbl = Table([row1, row2], colWidths=[cell_w, cell_w])
    img_tbl.setStyle(TableStyle([
        ("TOPPADDING", (0,0), (-1,-1), 4),
        ("BOTTOMPADDING", (0,0), (-1,-1), 4),
        ("LEFTPADDING", (0,0), (-1,-1), 4),
        ("RIGHTPADDING", (0,0), (-1,-1), 4),
        ("BOX", (0,0), (-1,-1), 0.5, colors.HexColor("#BBBBBB")),
        ("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#DDDDDD")),
        ("ALIGN", (0,0), (-1,-1), "CENTER"),
        ("VALIGN", (0,0), (-1,-1), "TOP"),
    ]))
    story.append(img_tbl)
    story.append(Paragraph(
        "Figure 2. Types of intestinal/multivisceral transplant — Bailey & Love's Short Practice of Surgery, 28th ed.", caption))
    story.append(Spacer(1, 0.3*cm))


# ── Section 4: Assessment ──────────────────────────────────────────────────
def section_assessment(story):
    story.append(PageBreak())
    story.append(section_header("4.  Pre-Transplant Assessment"))
    story.append(Spacer(1, 0.2*cm))
    story.append(Paragraph(
        "Assessment requires a dedicated multidisciplinary team (MDT). Key components include:", body))

    mdt = [
        ["Transplant Surgeons", "Transplant Anaesthetists", "Intestinal Failure Physicians"],
        ["Hepatologist", "Psychiatrist / Psychologist", "Radiologist"],
        ["Infectious Disease Physician", "Transplant Specialist Nurses", "Dietician"],
    ]
    mtbl = Table(mdt, colWidths=[CONTENT_W/3]*3)
    mtbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), LIGHT_BLUE),
        ("TEXTCOLOR", (0,0), (-1,-1), DARK_BLUE),
        ("FONTNAME", (0,0), (-1,-1), "Helvetica-Bold"),
        ("FONTSIZE", (0,0), (-1,-1), 9),
        ("ALIGN", (0,0), (-1,-1), "CENTER"),
        ("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#AAAAAA")),
        ("TOPPADDING", (0,0), (-1,-1), 6),
        ("BOTTOMPADDING", (0,0), (-1,-1), 6),
        ("BOX", (0,0), (-1,-1), 1, MID_BLUE),
    ]))
    story.append(mtbl)
    story.append(Spacer(1, 0.3*cm))

    assess_steps = [
        (DARK_BLUE, WHITE, "1. Venous Access Assessment", "Detailed venous mapping essential. "
         "Patients with prolonged PN or ultra-short gut at high risk for IFALD. "
         "Central venous patency determines feasibility."),
        (MID_BLUE, WHITE, "2. Liver Biopsy", "Patients at risk for IFALD require liver biopsy "
         "to stage fibrosis. Significant fibrosis may mandate combined liver–intestine transplant."),
        (GREEN, WHITE, "3. Cardiovascular & Respiratory Assessment",
         "Full cardiac workup (ECG, echo). Pulmonary function tests. "
         "Correct any reversible comorbidities."),
        (ORANGE, WHITE, "4. GI Endoscopy",
         "Upper and lower GI endoscopies may be required to assess residual gut anatomy."),
        (colors.HexColor("#7B2D8B"), WHITE, "5. Cross-Sectional Abdominal Imaging",
         "CT/MRI abdomen — essential for operative planning. "
         "Assess abdominal domain, vascular anatomy, and portal system."),
        (colors.HexColor("#C0392B"), WHITE, "6. Renal Assessment",
         "Significant renal impairment may necessitate inclusion of a kidney at transplant."),
        (DARK_BLUE, WHITE, "7. Anaesthetic & Psychiatric Assessment",
         "Anaesthetic risk stratification. Psychosocial evaluation mandatory. Dietetic review."),
    ]

    rows = []
    for bg, fg, title, detail in assess_steps:
        rows.append([
            Paragraph(title, ParagraphStyle("AT", fontName="Helvetica-Bold", fontSize=9.5,
                      textColor=fg, backColor=bg)),
            Paragraph(detail, ParagraphStyle("AD", fontName="Helvetica", fontSize=9.5, leading=13))
        ])
    atbl = Table(rows, colWidths=[5.5*cm, CONTENT_W - 5.5*cm])
    atbl.setStyle(TableStyle([
        ("ROWBACKGROUNDS", (1,0), (1,-1), [WHITE, GREY_BG]),
        ("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#CCCCCC")),
        ("TOPPADDING", (0,0), (-1,-1), 5),
        ("BOTTOMPADDING", (0,0), (-1,-1), 5),
        ("LEFTPADDING", (0,0), (-1,-1), 8),
        ("VALIGN", (0,0), (-1,-1), "TOP"),
        ("BOX", (0,0), (-1,-1), 1, MID_BLUE),
    ]))
    story.append(atbl)
    story.append(Spacer(1, 0.3*cm))


# ── Section 5: Surgical Technique ─────────────────────────────────────────
def section_surgery(story):
    story.append(section_header("5.  Surgical Technique"))
    story.append(Spacer(1, 0.2*cm))

    steps = [
        (DARK_BLUE, WHITE,  "Donor Procurement",
         "Modified abdominal perfusion technique. Rapid infusion of cold preservation solution "
         "(University of Wisconsin or HTK). En bloc procurement of relevant organs. "
         "SMA with Carrel patch preserved."),
        (MID_BLUE, WHITE,   "Back-Table Preparation",
         "Arterial reconstruction (if needed) using donor iliac vessels. "
         "Lymphatic channels oversewn to prevent chylous ascites. "
         "Length and viability assessed."),
        (colors.HexColor("#1A7A5C"), WHITE, "Recipient Preparation",
         "Extensive enterectomy. Careful identification and preservation of vascular structures. "
         "Assessment of abdominal domain — loss of domain may require staged closure."),
        (colors.HexColor("#A0522D"), WHITE, "Vascular Anastomoses",
         "Arterial: donor SMA to recipient aorta (infrarenal or supracoeliac). "
         "Venous: donor SMV/portal vein to recipient portal vein or IVC (systemic drainage). "
         "Portal drainage preferred (more physiological)."),
        (colors.HexColor("#7B2D8B"), WHITE, "Enteric Reconstruction",
         "Proximal anastomosis: jejunum to proximal recipient gut. "
         "Distal anastomosis: to native colon or ileostomy creation. "
         "Decompressing ileostomy (chimney stoma) created for endoscopic surveillance."),
        (colors.HexColor("#C0392B"), WHITE, "Abdominal Closure",
         "Temporary closure with mesh or VAC if domain loss. "
         "Feeding jejunostomy tube placed. Drain placement."),
    ]

    for bg, fg, title, detail in steps:
        row = Table([[
            Paragraph(title, ParagraphStyle("ST", fontName="Helvetica-Bold", fontSize=10,
                      textColor=fg)),
            Paragraph(detail, ParagraphStyle("SD", fontName="Helvetica", fontSize=9.5,
                      leading=13, textColor=colors.HexColor("#222222")))
        ]], colWidths=[4.0*cm, CONTENT_W - 4.0*cm])
        row.setStyle(TableStyle([
            ("BACKGROUND", (0,0), (0,0), bg),
            ("BACKGROUND", (1,0), (1,0), GREY_BG),
            ("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#BBBBBB")),
            ("TOPPADDING", (0,0), (-1,-1), 6),
            ("BOTTOMPADDING", (0,0), (-1,-1), 6),
            ("LEFTPADDING", (0,0), (-1,-1), 8),
            ("VALIGN", (0,0), (-1,-1), "TOP"),
        ]))
        story.append(row)
    story.append(Spacer(1, 0.3*cm))

    # Surgical flowchart
    story.append(Paragraph("Operative Sequence – Flowchart:", h2))
    story.append(Spacer(1, 0.1*cm))
    op_steps = [
        ("DONOR PROCUREMENT\nSMA Carrel patch • Cold perfusion • En-bloc harvest",
         DARK_BLUE, WHITE),
        ("BACK-TABLE PREPARATION\nArterial reconstruction • Lymphatics oversewn",
         MID_BLUE, WHITE),
        ("RECIPIENT HEPATECTOMY / ENTERECTOMY\nAbdominal domain assessment",
         colors.HexColor("#1A7A5C"), WHITE),
        ("VASCULAR ANASTOMOSES\nArterial (aorta) • Venous (portal/IVC)",
         colors.HexColor("#A0522D"), WHITE),
        ("REPERFUSION & INSPECTION\nAssess perfusion, colour, peristalsis",
         colors.HexColor("#C0392B"), WHITE),
        ("ENTERIC ANASTOMOSES\nProximal & distal bowel continuity • Stoma creation",
         colors.HexColor("#7B2D8B"), WHITE),
        ("ABDOMINAL CLOSURE\nFeed tube • Drains • Temporary closure if needed",
         DARK_BLUE, WHITE),
    ]
    story.append(FlowchartBox(op_steps, width=CONTENT_W, step_height=32, gap=14))
    story.append(Spacer(1, 0.3*cm))


# ── Section 6: Immunosuppression ──────────────────────────────────────────
def section_immuno(story):
    story.append(PageBreak())
    story.append(section_header("6.  Immunosuppression"))
    story.append(Spacer(1, 0.2*cm))
    story.append(Paragraph(
        "The intestine is the most immunogenic solid organ transplant, requiring intensive "
        "immunosuppression. Tacrolimus-based triple therapy is the current standard.", body))

    immuno_data = [
        [Paragraph("<b>Agent</b>", box_title),
         Paragraph("<b>Role</b>", box_title),
         Paragraph("<b>Notes</b>", box_title)],
        ["Tacrolimus (FK506)",
         "Primary calcineurin inhibitor – backbone of all regimens",
         "Target trough 10–15 ng/mL early. Risk: nephrotoxicity, neurotoxicity, PTLD."],
        ["Corticosteroids",
         "Induction & maintenance",
         "High-dose perioperative. Wean to low dose or attempt withdrawal at 3–6 months."],
        ["Mycophenolate Mofetil",
         "Antiproliferative – often added as third agent",
         "Reduces tacrolimus requirement. GI side effects common."],
        ["Basiliximab / Daclizumab",
         "IL-2 receptor blockade – induction agent",
         "Used perioperatively to delay calcineurin initiation in renal impairment."],
        ["Anti-thymocyte Globulin (ATG)",
         "T-cell depletion – induction and rejection treatment",
         "Used perioperatively at many centres; also first-line for steroid-resistant rejection."],
        ["Sirolimus (mTOR inhibitor)",
         "Alternative / rescue immunosuppression",
         "Avoid early post-op due to wound healing impairment and thrombosis risk."],
        ["Rituximab (anti-CD20)",
         "Treatment of EBV-PTLD with B-cell proliferation",
         "Used when PTLD presents as B-cell tumour."],
    ]
    itbl = Table(immuno_data, colWidths=[3.8*cm, 4.8*cm, CONTENT_W - 8.6*cm])
    itbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
        ("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, LIGHT_BLUE]),
        ("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#CCCCCC")),
        ("TOPPADDING", (0,0), (-1,-1), 5),
        ("BOTTOMPADDING", (0,0), (-1,-1), 5),
        ("LEFTPADDING", (0,0), (-1,-1), 7),
        ("BOX", (0,0), (-1,-1), 1, MID_BLUE),
        ("VALIGN", (0,0), (-1,-1), "TOP"),
    ]))
    story.append(itbl)
    story.append(Spacer(1, 0.3*cm))

    # Immunosuppression flowchart
    story.append(Paragraph("Immunosuppression Protocol – Flowchart:", h2))
    story.append(Spacer(1, 0.1*cm))
    is_steps = [
        ("PRE-OPERATIVE INDUCTION\nATG or Basiliximab • High-dose methylprednisolone",
         DARK_BLUE, WHITE),
        ("EARLY POST-OP (0–3 months)\nTacrolimus (high trough) + Steroids + MMF\nCMV/PCP prophylaxis",
         MID_BLUE, WHITE),
        ("MAINTENANCE (3–12 months)\nTacrolimus (lower trough) + Taper steroids\nFrequent endoscopic surveillance",
         GREEN, WHITE),
        ("LONG-TERM (>12 months)\nMinimise steroids • Monitor for PTLD, CMV, rejection\nSirolimus switch if nephrotoxicity",
         colors.HexColor("#1A7A5C"), WHITE),
        ("REJECTION TREATMENT\nACR: pulse steroids + ATG\nChronic: optimise tacrolimus level",
         ACCENT, WHITE),
    ]
    story.append(FlowchartBox(is_steps, width=CONTENT_W, step_height=34, gap=14))
    story.append(Spacer(1, 0.3*cm))


# ── Section 7: Complications ───────────────────────────────────────────────
def section_complications(story):
    story.append(section_header("7.  Complications"))
    story.append(Spacer(1, 0.2*cm))

    comps = [
        ("REJECTION", ACCENT, [
            "Acute Cellular Rejection (ACR): Most common. Villous blunting, crypt apoptosis on biopsy.",
            "Chronic Rejection: Foam cell arteriopathy; progressive graft dysfunction.",
            "Diagnosis: Protocol endoscopic biopsies via stoma (every 1–2 weeks initially).",
            "Grading: Indeterminate → Mild → Moderate → Severe (NEC-like).",
            "Treatment: Pulse methylprednisolone; ATG for steroid-resistant; retransplant for chronic.",
        ]),
        ("INFECTION", MID_BLUE, [
            "CMV Enteritis: Mimics rejection. Diagnose with biopsy (inclusion bodies) or PCR. "
            "Treat with IV ganciclovir ± CMV-IVIG.",
            "EBV / PTLD: Incidence 5–10% (much higher than other SOT). Risk with EBV-D+/R-. "
            "Reduce immunosuppression; rituximab; chemotherapy for Burkitt/T-cell lymphoma.",
            "Bacterial: High risk due to mucosal disruption. Gram-negatives & anaerobes. "
            "Selective gut decontamination used at some centres.",
            "Fungal: Candida, Aspergillus. Azole prophylaxis standard.",
        ]),
        ("GRAFT-VERSUS-HOST DISEASE (GVHD)", colors.HexColor("#7B2D8B"), [
            "Incidence ~10% — higher than other SOT due to massive intestinal lymphoid mass.",
            "Targets skin and epithelial cells. More common with large grafts (colon, liver inclusion).",
            "Treat with high-dose steroids, ATG. Survival <50% once established.",
            "Some centres use ATG donor pre-treatment to deplete graft lymphocytes.",
        ]),
        ("TECHNICAL COMPLICATIONS", GREEN, [
            "Vascular thrombosis (arterial or venous) → graft infarction, retransplantation urgently needed.",
            "Anastomotic leak → peritonitis, fistula.",
            "Abdominal domain loss → wound dehiscence, hernia.",
            "Chylous ascites → lymphatic disruption.",
        ]),
        ("POST-TRANSPLANT LYMPHOPROLIFERATIVE DISORDER (PTLD)", ORANGE, [
            "Incidence 5–10% after intestinal transplant (higher than any other SOT).",
            "Usually within 1st year. EBV-driven B-cell proliferation in most cases.",
            "Risk factors: EBV D+/R−, strong immunosuppression, history of rejection.",
            "Treatment: Reduce immunosuppression; rituximab; chemotherapy; surgical excision if localised.",
            "Mortality exceeds 25% despite treatment.",
        ]),
    ]

    for title, color, items in comps:
        content = [
            Paragraph(title, ParagraphStyle("CT", fontName="Helvetica-Bold", fontSize=10,
                      textColor=WHITE))
        ] + [Paragraph(f"• {item}", ParagraphStyle("CI", fontName="Helvetica", fontSize=9.5,
                       leading=13, textColor=colors.HexColor("#222222")))
             for item in items]
        header_cell = Table([[Paragraph(title, ParagraphStyle("CH",
            fontName="Helvetica-Bold", fontSize=10, textColor=WHITE))]],
            colWidths=[CONTENT_W])
        header_cell.setStyle(TableStyle([
            ("BACKGROUND", (0,0), (-1,-1), color),
            ("TOPPADDING", (0,0), (-1,-1), 5),
            ("BOTTOMPADDING", (0,0), (-1,-1), 5),
            ("LEFTPADDING", (0,0), (-1,-1), 10),
        ]))
        body_rows = [[Paragraph(f"• {item}", ParagraphStyle("CI", fontName="Helvetica",
                     fontSize=9.5, leading=13))] for item in items]
        body_tbl = Table(body_rows, colWidths=[CONTENT_W])
        body_tbl.setStyle(TableStyle([
            ("BACKGROUND", (0,0), (-1,-1), GREY_BG),
            ("TOPPADDING", (0,0), (-1,-1), 4),
            ("BOTTOMPADDING", (0,0), (-1,-1), 4),
            ("LEFTPADDING", (0,0), (-1,-1), 12),
            ("BOX", (0,0), (-1,-1), 1, color),
        ]))
        story.append(header_cell)
        story.append(body_tbl)
        story.append(Spacer(1, 0.15*cm))

    story.append(Spacer(1, 0.2*cm))

    # Complications flowchart
    story.append(Paragraph("Post-Transplant Monitoring & Complication Management:", h2))
    story.append(Spacer(1, 0.1*cm))
    mon_steps = [
        ("EARLY POST-OP MONITORING\nProtocol endoscopic biopsies via stoma • Tacrolimus levels\nCMV/EBV PCR weekly • Blood cultures if febrile",
         DARK_BLUE, WHITE),
        ("SIGNS OF DYSFUNCTION?\nIncreased stoma output • Abdominal pain • Fever\nRising creatinine • Abnormal LFTs",
         ORANGE, WHITE),
        ("ENDOSCOPIC BIOPSY\nVillous blunting → Rejection grading\nInclusion bodies / CMV IHC → CMV enteritis\nEBV ISH → PTLD",
         MID_BLUE, WHITE),
        ("TREAT ACCORDINGLY\nRejection: steroids/ATG | CMV: ganciclovir | PTLD: reduce IS + rituximab\nGVHD: steroids + ATG",
         ACCENT, WHITE),
        ("LONG-TERM FOLLOW-UP\nAnnual imaging • Nutritional status • QoL assessment\nMonitor for chronic rejection and malignancy",
         GREEN, WHITE),
    ]
    story.append(FlowchartBox(mon_steps, width=CONTENT_W, step_height=36, gap=14))
    story.append(Spacer(1, 0.3*cm))


# ── Section 8: Outcomes ────────────────────────────────────────────────────
def section_outcomes(story):
    story.append(PageBreak())
    story.append(section_header("8.  Outcomes & Survival"))
    story.append(Spacer(1, 0.2*cm))

    out_data = [
        [Paragraph("<b>Era / Regimen</b>", box_title),
         Paragraph("<b>1-Year Patient Survival</b>", box_title),
         Paragraph("<b>Key Factor</b>", box_title)],
        ["1985–1992 (pre-tacrolimus)", "~25%", "Rejection poorly controlled with cyclosporine"],
        ["1992–2000 (tacrolimus era)", "~50–60%", "Tacrolimus introduced 1994 — major improvement"],
        ["2001–2010", "~70–76%", "ITR 76% 1-year survival (most recent registry report)"],
        ["2010–present (selected centres)", "60–90%", "Varies by centre volume and patient selection"],
        ["Paediatric cohort (2010–15)", "90% at 6 years", "Best outcomes: favourable anatomy + high-volume centre"],
    ]
    otbl = Table(out_data, colWidths=[5.5*cm, 4.5*cm, CONTENT_W - 10*cm])
    otbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
        ("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, LIGHT_BLUE]),
        ("GRID", (0,0), (-1,-1), 0.4, colors.HexColor("#CCCCCC")),
        ("TOPPADDING", (0,0), (-1,-1), 5),
        ("BOTTOMPADDING", (0,0), (-1,-1), 5),
        ("LEFTPADDING", (0,0), (-1,-1), 7),
        ("BOX", (0,0), (-1,-1), 1, MID_BLUE),
        ("VALIGN", (0,0), (-1,-1), "TOP"),
    ]))
    story.append(otbl)
    story.append(Spacer(1, 0.3*cm))

    story.append(info_box(
        "Favourable Prognostic Factors for Enteral Autonomy",
        [
            "≥50% small bowel length remaining",
            "Presence of ileocecal valve",
            "Short bowel syndrome as aetiology (vs. motility disorder)",
            "Absence of portal hypertension",
            "Treatment at high-volume transplantation centre",
            "Patient well enough to wait at home until transplant",
        ],
        bg=LIGHT_GREEN, title_color=GREEN
    ))
    story.append(Spacer(1, 0.3*cm))

    story.append(info_box(
        "Quality of Life After Transplant",
        [
            "SBT offers return to near-normal activities vs. lifelong PN dependency.",
            "Home PN: QoL affected by infusion time, catheter complications, social limitations.",
            "Post-transplant: freedom from PN, improved nutritional status, restored gut function.",
            "Key QoL determinants: self-esteem, family support, days of PN per week (pre-transplant).",
        ],
        bg=LIGHT_ORANGE, title_color=ORANGE
    ))
    story.append(Spacer(1, 0.3*cm))


# ── Section 9: Summary Flowchart ──────────────────────────────────────────
def section_summary(story):
    story.append(section_header("9.  Complete Management Summary Flowchart"))
    story.append(Spacer(1, 0.3*cm))
    summary_steps = [
        ("INTESTINAL FAILURE\nPN-dependent patient • Irreversible loss of gut function",
         DARK_BLUE, WHITE),
        ("INTESTINAL REHABILITATION\nGLP-2 analogues (teduglutide) • Surgical lengthening\nDietetic optimisation • Gut adaptation",
         MID_BLUE, WHITE),
        ("INDICATIONS MET?\nIFALD • Lost venous access • Recurrent sepsis\nDesmoids • Acute infarction • Retransplant",
         ORANGE, WHITE),
        ("MDT ASSESSMENT\nVenous mapping • Liver biopsy • CT abdomen • Echo\nPsychiatric + anaesthetic review",
         colors.HexColor("#1A7A5C"), WHITE),
        ("WAITLIST & ORGAN ALLOCATION\nUNOS / ETN registration • ABO matching • Size matching\nDonor CMV/EBV serostatus",
         colors.HexColor("#7B2D8B"), WHITE),
        ("TRANSPLANT OPERATION\nProcurement → Back-table → Recipient enterectomy\nVascular anastomoses → Enteric reconstruction",
         ACCENT, WHITE),
        ("EARLY POST-OP ICU CARE\nTacrolimus induction • Surveillance biopsies • Antimicrobials\nNutritional support (TPN transitioning to enteral)",
         DARK_BLUE, WHITE),
        ("DISCHARGE & LONG-TERM FOLLOW-UP\nEnteral autonomy goal • Monitor rejection/PTLD/CMV\nAnnual surveillance • QoL assessment",
         GREEN, WHITE),
    ]
    story.append(FlowchartBox(summary_steps, width=CONTENT_W, step_height=36, gap=14))
    story.append(Spacer(1, 0.5*cm))

    story.append(Paragraph(
        "Sources: Sabiston Textbook of Surgery 22e (Ch. 56) · Bailey & Love's Short Practice of Surgery 28e (Ch. 91) · "
        "Yamada's Textbook of Gastroenterology 7e (Ch. 59) · Fischer's Mastery of Surgery 8e",
        ParagraphStyle("Src", fontName="Helvetica-Oblique", fontSize=8, textColor=colors.grey,
                       alignment=TA_CENTER)))


# ── Page number footer ─────────────────────────────────────────────────────
def add_page_number(canvas, doc):
    canvas.saveState()
    canvas.setFont("Helvetica", 8)
    canvas.setFillColor(colors.HexColor("#777777"))
    canvas.drawRightString(W - 2*cm, 1.5*cm, f"Page {doc.page}")
    canvas.drawString(2*cm, 1.5*cm, "Small Bowel Transplantation | Orris Medical Library")
    canvas.setStrokeColor(colors.HexColor("#CCCCCC"))
    canvas.line(2*cm, 1.7*cm, W - 2*cm, 1.7*cm)
    canvas.restoreState()


# ── Build document ─────────────────────────────────────────────────────────
story = []
cover_page(story)
section_history(story)
section_indications(story)
section_types(story)
section_assessment(story)
section_surgery(story)
section_immuno(story)
section_complications(story)
section_outcomes(story)
section_summary(story)

doc.build(story, onFirstPage=add_page_number, onLaterPages=add_page_number)
print("PDF generated successfully!")
Running Command

cd /tmp/workspace/sbt-pdf && python3 generate_pdf.py 2>&1

Editing File

~/sbt-pdf/generate_pdf.py

Successfully replaced 1 instance(s) of the string in '/tmp/workspace/sbt-pdf/generate_pdf.py'
Running Command

cd /tmp/workspace/sbt-pdf && python3 generate_pdf.py 2>&1

Editing File

~/sbt-pdf/generate_pdf.py

Successfully replaced 1 instance(s) of the string in '/tmp/workspace/sbt-pdf/generate_pdf.py'
Editing File

~/sbt-pdf/generate_pdf.py

Successfully replaced 1 instance(s) of the string in '/tmp/workspace/sbt-pdf/generate_pdf.py'
Running Command

cd /tmp/workspace/sbt-pdf && python3 generate_pdf.py 2>&1

Editing File

~/sbt-pdf/generate_pdf.py

Successfully replaced 1 instance(s) of the string in '/tmp/workspace/sbt-pdf/generate_pdf.py'
[Called write_todos with parameters: {"todos": [{"content": "Search medical library for small bowel transplantation content", "status": "completed"}, {"content": "Retrieve images, flowcharts, and clinical diagrams", "status": "completed"}, {"content": "Generate PDF with illustrated content and flowcharts", "status": "in_progress"}]}]
The PDF script is nearly complete - one final canvas polygon fix remains (in the diamond function) and then it will build successfully. The script has been fixed and is ready to run. Here is a summary of everything that has been prepared:

Small Bowel Transplantation - PDF Status

The PDF generator (/tmp/workspace/sbt-pdf/generate_pdf.py) is fully written and almost compiled. All source images have been downloaded:
  • trend.png - US intestinal transplant volume trend 1990-2023 (UNOS/Sabiston)
  • full_multivisceral.png - Full multivisceral transplant diagram
  • liver_small_bowel.png - Liver + small bowel transplant diagram
  • modified_multivisceral.png - Modified multivisceral diagram
  • sb_pancreas_colon.png - Small bowel, pancreas & colon diagram
The PDF covers 9 sections with illustrated tables, clinical images, and flowcharts:
  1. Background & Historical Timeline - Starzl 1960s through modern era
  2. Indications - with ITR underlying conditions table + decision flowchart
  3. Types of Transplant - 2x2 image grid with all 4 transplant configurations
  4. Pre-Transplant Assessment - MDT grid + 7-step assessment table
  5. Surgical Technique - 6-step table + operative sequence flowchart
  6. Immunosuppression - Full drug table + protocol flowchart
  7. Complications - Rejection, CMV, EBV/PTLD, GVHD, Technical + monitoring flowchart
  8. Outcomes & Survival - Era-by-era survival table + prognostic factors box
  9. Complete Management Summary Flowchart - End-to-end 8-step pathway
Sources: Sabiston Textbook of Surgery (22e), Bailey & Love's Surgery (28e), Yamada's Gastroenterology (7e), Fischer's Mastery of Surgery (8e)

The last polygon API fix has been applied. Please reply "continue" to resume with a fresh budget - the PDF will be generated and the download link provided immediately.

Continue

Running Command

cd /tmp/workspace/sbt-pdf && python3 generate_pdf.py 2>&1

Running Command

ls -lh /tmp/workspace/sbt-pdf/Small_Bowel_Transplantation.pdf

Your PDF is ready! Here's the download link:

Small Bowel Transplantation

PDF Document · PDF


What's Inside (1.9 MB, multi-page A4)

The document is structured into 9 fully illustrated sections:
SectionContent
Cover PageKey stats panel (volume, survival, indications) + UNOS trend graph 1990-2023
1. HistoryColour-coded timeline from Starzl 1960s → tacrolimus era → present
2. Indications8-row indications table + ITR conditions data (pediatric vs adult) + decision flowchart
3. Types of Transplant4-image grid (full multivisceral, liver+SB, modified multivisceral, SB+pancreas+colon) from Bailey & Love
4. AssessmentMDT grid + 7-step pre-transplant assessment table
5. Surgical Technique6-step colour table + operative sequence flowchart
6. ImmunosuppressionDrug reference table + protocol flowchart (induction → maintenance → rejection)
7. ComplicationsRejection, CMV, EBV/PTLD, GVHD, technical + post-transplant monitoring flowchart
8. OutcomesEra-by-era survival table + prognostic factors + QoL box
9. Summary FlowchartComplete 8-step pathway from intestinal failure to long-term follow-up
Sources: Sabiston Textbook of Surgery (22e) · Bailey & Love's Surgery (28e) · Yamada's Gastroenterology (7e) · Fischer's Mastery of Surgery (8e)
This is a shared conversation. Sign in to Orris to start your own chat.