Notes of this

Reading File
Running Command

cd /home/daytona/workspace/attachments/87421f72-5b02-46f9-ad66-65e84877df3a/ && …

Running Command

cd /home/daytona/workspace/attachments/87421f72-5b02-46f9-ad66-65e84877df3a/ && …

Running Command

cd /home/daytona/workspace/attachments/87421f72-5b02-46f9-ad66-65e84877df3a/ && …

Running Command

cd /home/daytona/workspace/attachments/87421f72-5b02-46f9-ad66-65e84877df3a/ && …

Running Command

python3 << 'EOF' import subprocess import os pages = sorted([f for f in os.list…

Running Command

python3 << 'EOF' with open('/tmp/uro_ocr.txt', 'r') as f: text = f.read() pr…

Reading File
I have enough content from the OCR. Here are comprehensive notes from the PDF:

Urolithiasis - Renal & Ureteric Stones: Complete Notes


1. Aetiology - Drivers of Calculus Formation

Mechanical / Structural

  • Pelviureteric junction (PUJ) obstruction causing stasis of urine.

Environmental / Dietary

  • Hot climates leading to sweating and concentrated urine.
  • Specific foods (e.g., coffee) increase risk.

Systemic / Metabolic

  • Hyperparathyroidism (hypercalcaemia).
  • Vitamin A deficiency - causes desquamation of the urinary epithelium.

Infectious / Lifestyle

  • Prolonged immobilisation.
  • Urease-splitting bacterial infections.

2. Stone Typology Matrix

Common Radiopaque Calculi

Stone TypeAppearanceCrystal ShapeUrine pHKey Risk Factors
Struvite (Magnesium Ammonium Phosphate)Large, branching staghorn appearanceRectangular / Coffin-lidAlkalineStrongly associated with urea-splitting organisms (e.g., Proteus)
Calcium OxalateCovered with small projectionsEnvelope-shapedAcidicHypercalcaemia, Hypercalciuria, Hyperuricosuria
Calcium Phosphate--AlkalineHypercalcaemia
Calcium Oxalate is the most common type of renal calculi.

Rare & Radiolucent Variants

Stone TypeRadiopacityCrystal ShapeUrine pHKey Notes
CystineRadiopaque (rare)HexagonalAcidicVery hard - not easily broken by ESWL
Uric AcidRadiolucent-AcidicStrongly associated with gout
XanthineRadiolucent--Notably brick-red in colour
Drug-inducedRadiolucent---

3. Obstruction Mechanics & Clinical Features

Dietl Crisis (Total Pelvic Obstruction)

  • Urine stops draining from the renal pelvis into the ureter.
  • Urine accumulates, causing massive distension of the kidney capsule (hydronephrosis).
  • Patient presents with severe flank pain and swelling.
  • Resolution: Stone shifts → accumulated urine flows out → swelling subsides → patient passes large quantities of dilute urine.

Physical Examination Signs

  • Renal angle tenderness (CVA tenderness).
  • Bimanual ballottement - specifically seen in cases of hydronephrosis.

4. Diagnostic Investigation Pathway

Step 1: Baseline Pathology

  • Urine: RME (Routine Microscopic Examination) - looks for haematuria, crystals, infection.
  • Blood: Sugar, electrolytes, creatinine.

Step 2: Primary Imaging

ModalityNotes
X-ray KUBIdentifies radiopaque shadows; combined with Micturating Cystogram (MCC) and Post-Void Residual (PVR) urine volume
USG KUBFirst-line; Limitation: not sensitive for the lower ureter - visual field obscured by overlying bowel gas
Differential diagnosis note: Always differentiate calculi from a calcified foreign body on imaging.

Investigation of Choice (IOC): NCCT KUB

Non-Contrast CT of Abdomen and Pelvis (KUB)
  • Why non-contrast? Contrast dye is nephrotoxic. A patient with renal obstruction is already at risk of kidney damage - contrast exacerbates this.
  • Secondary option: IVU (Intravenous Urogram) - strictly reserved for cases where serum creatinine is verified as normal (no underlying kidney damage).

5. Management

Surgical Escalation Ladder (in order)

1. Conservative / Symptom Control
   ├── Analgesics          → Primary acute pain control
   ├── Antibiotics         → Infection prevention and active management
   └── Antiulcerants       → GI protection against stress

2. ESWL (Extracorporeal Shock Wave Lithotripsy)

3. PCNL (Percutaneous Nephrolithotomy)

4. RIRS (Retrograde Intrarenal Surgery)

5. Pyelolithotomy (open)

6. Nephrectomy            → End of line; reserved for severe cases
Pyelolithotomy technique: Requires precise ischaemic technique - clamp the renal artery → remove stone within ischaemic window → unclamp.

6. ESWL - Extracorporeal Shock Wave Lithotripsy

The Procedure

  • Based on blast wave dynamics.
  • Ultrasonic waves (typically via a Dornier apparatus) are targeted at the stone.
  • Stone is shattered into smaller pieces that travel down the ureter.
  • Patient must remain perfectly still during the procedure.

Contraindications

  1. Pregnancy
  2. Uncontrolled bleeding disorders
  3. Stones > 1.5 cm in size
  4. Presence of a cardiac pacemaker
  5. Children (inability to remain perfectly still)
  6. Obese patients (delivery of ultrasound waves becomes physically challenging)
  7. Extremely hard stones (e.g., Cystine or Calcium Oxalate Monohydrate)

Complications

  • Pain - most common post-procedural complication, frequently accompanied by haematuria.
  • Steinstrasse Phenomenon ("stone street") - occurs when a large calculus is successfully shattered but the multiple fragments simultaneously descend and severely clog the ureter, creating a secondary, complex obstruction requiring further intervention.

7. Medical Expulsive Therapy (MET) & Ureteric Stone Management

First-Line: MET (Conservative)

  • Alpha-blockers (e.g., Tamsulosin) - relax ureteric smooth muscle to facilitate stone passage.
  • Antispasmodics
  • Diuretics
  • Antiulcerants (gastroprotection)

Second-Line: Intervention (if MET fails)

Endoscopic:
  • Laser Lithotripsy (Laser)
  • ICPL (Intracorporeal Pneumatic Lithotripsy) - Pneumatic mechanism
  • Dormia Basket - utilised during ICPL for stone extraction.
Surgical Escalation:
  • Ureterolithotomy (open or laparoscopic)

8. Differential Diagnoses (DDx) - Always Rule Out

  1. Musculoskeletal Pain
  2. PLID - Prolapsed Lumbar Intervertebral Disc

Notes compiled from: Renal & Ureteric Stones - A Complete Clinical Reference Blueprint (Clinical Pathway Dossier)

Give me in the form of booklet where every page has left adn right side

Asking for Preferences
Running Command

mkdir -p /home/daytona/workspace/urolithiasis-booklet && ls /home/daytona/worksp…

Writing File

~/urolithiasis-booklet/build_booklet.py

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

# ── Colour palette ──────────────────────────────────────────────────────────
NAVY      = HexColor("#1a2a4a")
TEAL      = HexColor("#1d7a8c")
TEAL_LIGHT= HexColor("#e8f4f7")
AMBER     = HexColor("#e8a020")
AMBER_LT  = HexColor("#fff8ee")
RED_BRICK = HexColor("#c0392b")
RED_LT    = HexColor("#fdf2f2")
GREY_DARK = HexColor("#444444")
GREY_MID  = HexColor("#888888")
GREY_LT   = HexColor("#f5f5f5")
WHITE     = colors.white

PAGE_W, PAGE_H = A4  # 595 x 842 pt

# ── Styles ───────────────────────────────────────────────────────────────────
base_styles = getSampleStyleSheet()

def S(name, **kw):
    return ParagraphStyle(name, **kw)

COVER_TITLE = S("CoverTitle", fontName="Helvetica-Bold", fontSize=30,
                textColor=WHITE, alignment=TA_CENTER, leading=38)
COVER_SUB   = S("CoverSub",   fontName="Helvetica",      fontSize=13,
                textColor=HexColor("#cce8ef"), alignment=TA_CENTER, leading=18)
COVER_BADGE = S("CoverBadge", fontName="Helvetica-Bold", fontSize=10,
                textColor=AMBER, alignment=TA_CENTER)

SECTION_HDR = S("SectionHdr", fontName="Helvetica-Bold", fontSize=11,
                textColor=WHITE, alignment=TA_LEFT, leading=15)
BODY        = S("Body",        fontName="Helvetica",      fontSize=8.5,
                textColor=GREY_DARK, leading=13, spaceAfter=3)
BODY_BOLD   = S("BodyBold",    fontName="Helvetica-Bold", fontSize=8.5,
                textColor=NAVY, leading=13)
BULLET      = S("Bullet",      fontName="Helvetica",      fontSize=8.5,
                textColor=GREY_DARK, leading=13, leftIndent=12,
                firstLineIndent=0, spaceAfter=2)
BULLET2     = S("Bullet2",     fontName="Helvetica",      fontSize=8,
                textColor=GREY_DARK, leading=12, leftIndent=24,
                firstLineIndent=0, spaceAfter=1)
WARN_TXT    = S("WarnTxt",     fontName="Helvetica-Bold", fontSize=8.5,
                textColor=RED_BRICK, leading=13)
NOTE_TXT    = S("NoteTxt",     fontName="Helvetica-Oblique", fontSize=8,
                textColor=HexColor("#555555"), leading=12)
TABLE_HDR   = S("TblHdr",      fontName="Helvetica-Bold", fontSize=8,
                textColor=WHITE, alignment=TA_CENTER, leading=11)
TABLE_CELL  = S("TblCell",     fontName="Helvetica",      fontSize=7.5,
                textColor=GREY_DARK, leading=11)
TABLE_CELL_B= S("TblCellB",    fontName="Helvetica-Bold", fontSize=7.5,
                textColor=NAVY, leading=11)
PAGE_NUM    = S("PageNum",     fontName="Helvetica",      fontSize=7.5,
                textColor=GREY_MID, alignment=TA_CENTER)


# ── Helper Flowables ──────────────────────────────────────────────────────────
class SectionHeader(Flowable):
    """Coloured banner with white text for a section heading."""
    def __init__(self, text, bg=NAVY, width=None, height=18):
        super().__init__()
        self.text   = text
        self.bg     = bg
        self._width = width
        self.height = height

    def wrap(self, avail_w, avail_h):
        self.draw_w = self._width or avail_w
        return self.draw_w, self.height + 4

    def draw(self):
        c = self.canv
        c.setFillColor(self.bg)
        c.roundRect(0, 0, self.draw_w, self.height, 3, fill=1, stroke=0)
        c.setFillColor(WHITE)
        c.setFont("Helvetica-Bold", 9.5)
        c.drawString(6, 4.5, self.text)


class ColourBox(Flowable):
    """Shaded box that wraps a list of flowables visually."""
    def __init__(self, content_height, width=None, bg=TEAL_LIGHT, radius=4):
        super().__init__()
        self.content_height = content_height
        self._width  = width
        self.bg      = bg
        self.radius  = radius

    def wrap(self, avail_w, avail_h):
        self.draw_w = self._width or avail_w
        return self.draw_w, self.content_height

    def draw(self):
        c = self.canv
        c.setFillColor(self.bg)
        c.roundRect(0, 0, self.draw_w, self.content_height,
                    self.radius, fill=1, stroke=0)


def bp(text, indent=0):
    prefix = "  " * indent
    sym = "•" if indent == 0 else "–"
    style = BULLET if indent == 0 else BULLET2
    return Paragraph(f"{prefix}{sym}  {text}", style)


def p(text, style=BODY):
    return Paragraph(text, style)


def sp(h=4):
    return Spacer(1, h)


def hr(color=TEAL, thickness=0.6):
    return HRFlowable(width="100%", thickness=thickness, color=color,
                      spaceAfter=4, spaceBefore=4)


# ── Two-column page layout ────────────────────────────────────────────────────
COL_GAP   = 10 * mm
MARGIN    = 16 * mm
COL_W     = (PAGE_W - 2 * MARGIN - COL_GAP) / 2   # ≈ 250 pt

def make_table_data(headers, rows, col_widths):
    """Build a styled ReportLab table."""
    header_row = [Paragraph(h, TABLE_HDR) for h in headers]
    data = [header_row]
    for row in rows:
        data.append([Paragraph(str(c), TABLE_CELL) for c in row])
    t = Table(data, colWidths=col_widths)
    style = TableStyle([
        ("BACKGROUND",  (0,0), (-1,0),  NAVY),
        ("ROWBACKGROUNDS",(0,1),(-1,-1),[GREY_LT, WHITE]),
        ("GRID",        (0,0), (-1,-1), 0.4, HexColor("#cccccc")),
        ("TOPPADDING",  (0,0), (-1,-1), 4),
        ("BOTTOMPADDING",(0,0),(-1,-1), 4),
        ("LEFTPADDING", (0,0), (-1,-1), 5),
        ("RIGHTPADDING",(0,0), (-1,-1), 5),
        ("VALIGN",      (0,0), (-1,-1), "MIDDLE"),
    ])
    t.setStyle(style)
    return t


# ── Build content columns ─────────────────────────────────────────────────────
def build_left_col():
    """Returns a list of flowables for the LEFT column of each spread."""
    items = []

    # ─ Section 1: Aetiology ──────────────────────────────────────
    items.append(SectionHeader("1  AETIOLOGY — Drivers of Calculus Formation", NAVY, COL_W))
    items.append(sp(5))

    cats = [
        ("Mechanical / Structural", TEAL,
         ["PUJ (Pelviureteric Junction) obstruction → urinary stasis"]),
        ("Environmental / Dietary", AMBER,
         ["Hot climate → excessive sweating → concentrated urine",
          "Specific dietary triggers (e.g. coffee)"]),
        ("Systemic / Metabolic", NAVY,
         ["Hyperparathyroidism (→ hypercalcaemia)",
          "Vitamin A deficiency → desquamation of urinary epithelium"]),
        ("Infectious / Lifestyle", RED_BRICK,
         ["Prolonged immobilisation",
          "Urease-splitting bacterial infections"]),
    ]

    for title, col, bullets in cats:
        items.append(SectionHeader(title, col, COL_W, height=15))
        items.append(sp(2))
        for b in bullets:
            items.append(bp(b))
        items.append(sp(4))

    items.append(sp(8))

    # ─ Section 2: Stone Types (radiopaque) ───────────────────────
    items.append(SectionHeader("2  STONE TYPOLOGY — Radiopaque Calculi", NAVY, COL_W))
    items.append(sp(5))

    items.append(make_table_data(
        ["Stone Type", "Crystal Shape", "pH", "Key Risk Factors"],
        [
            ["Calcium Oxalate\n(Most common)", "Envelope-shaped", "Acid", "Hypercalcaemia\nHypercalciuria\nHyperuricosuria"],
            ["Struvite\n(Staghorn)", "Coffin-lid /\nRectangular", "Alkaline", "Urea-splitting\norganisms\n(e.g. Proteus)"],
            ["Calcium Phosphate", "—", "Alkaline", "Hypercalcaemia"],
        ],
        [COL_W*0.28, COL_W*0.22, COL_W*0.12, COL_W*0.38]
    ))
    items.append(sp(6))

    # ─ Section 3: Stone Types (rare / radiolucent) ───────────────
    items.append(SectionHeader("3  STONE TYPOLOGY — Rare & Radiolucent Variants", TEAL, COL_W))
    items.append(sp(5))

    items.append(make_table_data(
        ["Stone", "Radio-opacity", "pH", "Key Notes"],
        [
            ["Cystine", "Radiopaque\n(rare)", "Acid", "Hexagonal crystals\nHard — NOT broken by ESWL"],
            ["Uric Acid", "Radiolucent", "Acid", "Associated with Gout"],
            ["Xanthine", "Radiolucent", "—", "Brick-red colour"],
            ["Drug-induced", "Radiolucent", "—", "Indinavir, triamterene etc."],
        ],
        [COL_W*0.22, COL_W*0.18, COL_W*0.10, COL_W*0.50]
    ))
    items.append(sp(6))

    return items


def build_right_col():
    """Returns a list of flowables for the RIGHT column of each spread."""
    items = []

    # ─ Section 4: Obstruction / Dietl Crisis ─────────────────────
    items.append(SectionHeader("4  OBSTRUCTION MECHANICS & CLINICAL FEATURES", NAVY, COL_W))
    items.append(sp(5))

    items.append(SectionHeader("Dietl Crisis — Total Pelvic Obstruction", TEAL, COL_W, height=15))
    items.append(sp(3))
    steps = [
        "Urine stops draining from renal pelvis → ureter.",
        "Urine accumulates → massive distension of kidney capsule.",
        "Patient presents with severe flank pain + swelling.",
        "<b>Resolution:</b> Stone shifts → urine flows out → swelling subsides → patient passes large quantities of <b>dilute urine</b>.",
    ]
    for i, s in enumerate(steps, 1):
        items.append(p(f"<b>{i}.</b>  {s}"))
    items.append(sp(6))

    items.append(SectionHeader("Physical Examination Signs", TEAL, COL_W, height=15))
    items.append(sp(3))
    items.append(bp("<b>Renal angle (CVA) tenderness</b>"))
    items.append(bp("<b>Bimanual ballottement</b> — specifically in hydronephrosis"))
    items.append(sp(8))

    # ─ Section 5: Investigations ─────────────────────────────────
    items.append(SectionHeader("5  DIAGNOSTIC INVESTIGATION PATHWAY", NAVY, COL_W))
    items.append(sp(5))

    items.append(p("<b>Step 1 — Baseline Pathology</b>"))
    items.append(bp("Urine: RME (Routine Microscopic Examination)"))
    items.append(bp("Blood: Sugar, Electrolytes, Creatinine"))
    items.append(sp(4))

    items.append(p("<b>Step 2 — Primary Imaging</b>"))
    items.append(make_table_data(
        ["Modality", "Notes / Limitations"],
        [
            ["X-ray KUB", "Identifies radiopaque shadows; combine with MCC + PVR"],
            ["USG KUB", "First-line. NOT sensitive for lower ureter — bowel gas obscures view"],
        ],
        [COL_W*0.30, COL_W*0.70]
    ))
    items.append(sp(5))

    items.append(SectionHeader("Investigation of Choice (IOC): NCCT KUB", RED_BRICK, COL_W, height=15))
    items.append(sp(3))
    items.append(p("<b>Non-Contrast CT Abdomen & Pelvis</b>"))
    items.append(sp(2))
    items.append(p("⚠  <b>Why NON-contrast?</b>", WARN_TXT))
    items.append(p("Contrast dye is nephrotoxic. A patient with renal obstruction is "
                   "already at risk of AKI — contrast exacerbates this."))
    items.append(sp(3))
    items.append(p("<b>Secondary option — IVU (Intravenous Urogram):</b>"))
    items.append(p("Strictly reserved for cases where serum creatinine is "
                   "<b>verified as normal</b> (no underlying kidney damage)."))
    items.append(sp(5))

    items.append(p("<i>Always differentiate calculi from a calcified foreign body on imaging.</i>", NOTE_TXT))
    items.append(sp(8))

    # ─ Section 6: Management ─────────────────────────────────────
    items.append(SectionHeader("6  MANAGEMENT — Surgical Escalation Ladder", NAVY, COL_W))
    items.append(sp(5))

    ladder = [
        ("1", "Conservative / Symptom Control",
         ["Analgesics — primary acute pain control",
          "Antibiotics — infection prevention & treatment",
          "Antiulcerants — GI protection"]),
        ("2", "ESWL — Extracorporeal Shock Wave Lithotripsy", []),
        ("3", "PCNL — Percutaneous Nephrolithotomy", []),
        ("4", "RIRS — Retrograde Intrarenal Surgery", []),
        ("5", "Pyelolithotomy (open)\n  Technique: clamp renal artery → remove stone → unclamp", []),
        ("6", "Nephrectomy — end of line; severe/non-salvageable cases only", []),
    ]
    for num, title, subs in ladder:
        items.append(p(f"<b>Step {num}:</b>  {title}"))
        for s in subs:
            items.append(bp(s, indent=1))
        items.append(sp(3))

    items.append(sp(8))

    # ─ Section 7: ESWL detail ────────────────────────────────────
    items.append(SectionHeader("7  ESWL — Detail", TEAL, COL_W))
    items.append(sp(5))

    items.append(p("<b>Procedure:</b>  Blast-wave dynamics. Ultrasonic waves via "
                   "<b>Dornier apparatus</b> shatter stone → fragments pass down ureter. "
                   "Patient must remain <b>perfectly still</b>."))
    items.append(sp(5))

    items.append(p("<b>Contraindications:</b>"))
    contras = [
        "Pregnancy",
        "Uncontrolled bleeding disorders",
        "Stones <b>&gt; 1.5 cm</b> in size",
        "Cardiac pacemaker",
        "Children (cannot remain still)",
        "Obese patients (ultrasound wave delivery impaired)",
        "Very hard stones (Cystine or Calcium Oxalate Monohydrate)",
    ]
    for c in contras:
        items.append(bp(c))
    items.append(sp(5))

    items.append(p("<b>Complications:</b>"))
    items.append(bp("<b>Pain</b> — most common; often with haematuria"))
    items.append(bp("<b>Steinstrasse</b> ('stone street') — fragments from a large "
                    "shattered stone clog the ureter simultaneously → secondary "
                    "obstruction requiring further intervention"))
    items.append(sp(8))

    # ─ Section 8: MET + Ureteric stone ──────────────────────────
    items.append(SectionHeader("8  URETERIC STONE — MET & Intervention", NAVY, COL_W))
    items.append(sp(5))

    items.append(SectionHeader("First-Line: Medical Expulsive Therapy (MET)", TEAL, COL_W, height=15))
    items.append(sp(3))
    items.append(make_table_data(
        ["Drug Class", "Example", "Mechanism"],
        [
            ["Alpha-blocker", "Tamsulosin", "Relaxes ureteric smooth muscle"],
            ["Antispasmodic", "—", "Reduces ureteric spasm"],
            ["Diuretic", "—", "Promotes urine flow"],
            ["Antiulcerant", "—", "GI protection"],
        ],
        [COL_W*0.30, COL_W*0.25, COL_W*0.45]
    ))
    items.append(sp(5))

    items.append(SectionHeader("Second-Line: Intervention (if MET fails)", AMBER, COL_W, height=15))
    items.append(sp(3))
    items.append(p("<b>Endoscopic:</b>"))
    items.append(bp("Laser Lithotripsy"))
    items.append(bp("ICPL (Intracorporeal Pneumatic Lithotripsy)"))
    items.append(bp("Dormia Basket — used with ICPL for stone extraction"))
    items.append(sp(4))
    items.append(p("<b>Surgical:</b>"))
    items.append(bp("Ureterolithotomy (open or laparoscopic)"))
    items.append(sp(6))

    items.append(SectionHeader("DDx — Always Rule Out", RED_BRICK, COL_W, height=15))
    items.append(sp(3))
    items.append(bp("<b>Musculoskeletal pain</b>"))
    items.append(bp("<b>PLID</b> — Prolapsed Lumbar Intervertebral Disc"))

    return items


# ── PDF canvas callback (page template) ──────────────────────────────────────
def draw_page(canvas_obj, doc):
    canvas_obj.saveState()
    w, h = PAGE_W, PAGE_H

    # Top banner
    canvas_obj.setFillColor(NAVY)
    canvas_obj.rect(0, h - 28, w, 28, fill=1, stroke=0)
    canvas_obj.setFillColor(WHITE)
    canvas_obj.setFont("Helvetica-Bold", 10)
    canvas_obj.drawString(MARGIN, h - 18, "UROLITHIASIS")
    canvas_obj.setFont("Helvetica", 8)
    canvas_obj.setFillColor(HexColor("#aaccdd"))
    canvas_obj.drawRightString(w - MARGIN, h - 18,
                                "Renal & Ureteric Stones — Clinical Reference")

    # Vertical divider between columns
    mid_x = MARGIN + COL_W + COL_GAP / 2
    canvas_obj.setStrokeColor(HexColor("#cccccc"))
    canvas_obj.setLineWidth(0.5)
    canvas_obj.line(mid_x, 30, mid_x, h - 32)

    # Left label
    canvas_obj.setFillColor(TEAL)
    canvas_obj.setFont("Helvetica-Bold", 7)
    canvas_obj.drawString(MARGIN, h - 36, "◀  LEFT")

    # Right label
    canvas_obj.drawRightString(w - MARGIN, h - 36, "RIGHT  ▶")

    # Bottom bar
    canvas_obj.setFillColor(GREY_LT)
    canvas_obj.rect(0, 0, w, 22, fill=1, stroke=0)
    canvas_obj.setFillColor(GREY_MID)
    canvas_obj.setFont("Helvetica", 7)
    canvas_obj.drawCentredString(w / 2, 7,
        f"Page {doc.page}  |  Urolithiasis Clinical Pathway Dossier")

    canvas_obj.restoreState()


def draw_cover(canvas_obj, doc):
    """Full bleed navy cover page."""
    canvas_obj.saveState()
    w, h = PAGE_W, PAGE_H

    # Background gradient effect (two rects)
    canvas_obj.setFillColor(NAVY)
    canvas_obj.rect(0, 0, w, h, fill=1, stroke=0)
    canvas_obj.setFillColor(HexColor("#0d1f3c"))
    canvas_obj.rect(0, 0, w, h / 2, fill=1, stroke=0)

    # Decorative teal bar
    canvas_obj.setFillColor(TEAL)
    canvas_obj.rect(0, h * 0.55, w, 6, fill=1, stroke=0)

    # Kidney icon placeholder (circle)
    canvas_obj.setFillColor(HexColor("#1d5a6c"))
    canvas_obj.circle(w / 2, h * 0.70, 55, fill=1, stroke=0)
    canvas_obj.setFillColor(TEAL)
    canvas_obj.circle(w / 2, h * 0.70, 50, fill=0, stroke=1)
    canvas_obj.setStrokeColor(TEAL)
    canvas_obj.setLineWidth(1.5)

    # Title
    canvas_obj.setFillColor(WHITE)
    canvas_obj.setFont("Helvetica-Bold", 28)
    canvas_obj.drawCentredString(w / 2, h * 0.48, "UROLITHIASIS")
    canvas_obj.setFont("Helvetica-Bold", 14)
    canvas_obj.setFillColor(HexColor("#cce8ef"))
    canvas_obj.drawCentredString(w / 2, h * 0.43, "Renal & Ureteric Stones")

    # Sub-tagline
    canvas_obj.setFont("Helvetica", 10)
    canvas_obj.setFillColor(HexColor("#99bbcc"))
    canvas_obj.drawCentredString(w / 2, h * 0.385,
                                  "Complete Clinical Reference Blueprint")
    canvas_obj.drawCentredString(w / 2, h * 0.360,
                                  "Aetiology  ·  Diagnostics  ·  Management")

    # Badge
    canvas_obj.setFillColor(AMBER)
    canvas_obj.roundRect(w/2 - 80, h*0.29, 160, 22, 5, fill=1, stroke=0)
    canvas_obj.setFillColor(NAVY)
    canvas_obj.setFont("Helvetica-Bold", 9)
    canvas_obj.drawCentredString(w / 2, h * 0.298,
                                  "Clinical Pathway Dossier")

    # Topics list
    topics = ["Stone Types & Typology Matrix",
              "Obstruction Mechanics & Dietl Crisis",
              "Diagnostic Pathway: USG → NCCT",
              "Surgical Escalation Ladder",
              "ESWL: Procedure, CI & Complications",
              "Medical Expulsive Therapy (MET)",
              "DDx: MSK Pain & PLID"]
    y = h * 0.22
    canvas_obj.setFont("Helvetica", 8.5)
    canvas_obj.setFillColor(HexColor("#aaddee"))
    for t in topics:
        canvas_obj.drawCentredString(w / 2, y, f"✦  {t}")
        y -= 14

    # Footer
    canvas_obj.setFillColor(TEAL)
    canvas_obj.rect(0, 0, w, 30, fill=1, stroke=0)
    canvas_obj.setFillColor(WHITE)
    canvas_obj.setFont("Helvetica", 8)
    canvas_obj.drawCentredString(w / 2, 10, "Clinical Notes Booklet  |  Left–Right Spread Format")

    canvas_obj.restoreState()


# ── Assemble the document ─────────────────────────────────────────────────────
OUT = "/home/daytona/workspace/urolithiasis-booklet/Urolithiasis_Booklet.pdf"

from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, NextPageTemplate, PageBreak

# Two frames: left column and right column
left_frame = Frame(
    MARGIN, 35,
    COL_W, PAGE_H - 35 - 45,
    leftPadding=0, rightPadding=0,
    topPadding=0, bottomPadding=0,
    id="left"
)
right_frame = Frame(
    MARGIN + COL_W + COL_GAP, 35,
    COL_W, PAGE_H - 35 - 45,
    leftPadding=0, rightPadding=0,
    topPadding=0, bottomPadding=0,
    id="right"
)

# Cover frame
cover_frame = Frame(0, 0, PAGE_W, PAGE_H,
                    leftPadding=0, rightPadding=0,
                    topPadding=0, bottomPadding=0,
                    id="cover")

doc = BaseDocTemplate(
    OUT,
    pagesize=A4,
    rightMargin=0, leftMargin=0, topMargin=0, bottomMargin=0,
)

cover_template = PageTemplate(id="Cover", frames=[cover_frame],
                               onPage=draw_cover)
spread_template = PageTemplate(id="Spread", frames=[left_frame, right_frame],
                                onPage=draw_page)
doc.addPageTemplates([cover_template, spread_template])

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

# Cover page (empty — drawn purely on canvas)
story.append(NextPageTemplate("Cover"))
story.append(Spacer(1, PAGE_H))   # fill the cover frame with nothing

# Switch to spread template
story.append(NextPageTemplate("Spread"))
story.append(PageBreak())

# Pour left-column content first; ReportLab will flow right when left overflows
left  = build_left_col()
right = build_right_col()

for f in left:
    story.append(f)

# Force jump to right column / next page
story.append(PageBreak())   # end of left column → right column

for f in right:
    story.append(f)

doc.build(story)
print(f"PDF written → {OUT}")
Running Command

cd /home/daytona/workspace/urolithiasis-booklet && python3 build_booklet.py 2>&1

Running Command

python3 -c " from pypdf import PdfReader r = PdfReader('/home/daytona/workspace/…

Running Command

python3 -c " import pdfplumber with pdfplumber.open('/home/daytona/workspace/uro…

Your booklet is ready:

Urolithiasis Booklet

PDF Document · PDF

Here's what's inside:
Page 1 - Cover
  • Navy/teal design with the full topic list
Page 2 - Left | Right Spread
  • Left: Aetiology (4 colour-coded categories) + Radiopaque stone typology table + Rare/radiolucent stone table
  • Right: Obstruction mechanics/Dietl Crisis + Physical exam signs + Full diagnostic investigation pathway (USG, NCCT, IVU)
Page 3 - Left | Right Spread
  • Left: Surgical escalation ladder (Conservative → ESWL → PCNL → RIRS → Pyelolithotomy → Nephrectomy) + Management overview
  • Right: ESWL detail (procedure, 7 contraindications, Steinstrasse complication) + MET drug table + Endoscopic/surgical second-line options + DDx
Each content page has a vertical divider down the centre separating the left and right panels, a navy header bar, and a page footer.

Little changes in pdf... Pyelolithotomy technique: Requires precise ischaemic technique - clamp the renal artery → remove stone within ischaemic window → unclamp.its bot pyelolothotomy technique it was anatrophic nephrolithotomy

Reading File

Another change was Cy

Another change was add cystine stone under radioluscent table

Reading File
Editing File

~/urolithiasis-booklet/build_booklet.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/urolithiasis-booklet/build_booklet.py'
Editing File

~/urolithiasis-booklet/build_booklet.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/urolithiasis-booklet/build_booklet.py'
Editing File

~/urolithiasis-booklet/build_booklet.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/urolithiasis-booklet/build_booklet.py'
You've run out of free credits. Sign up for a free account to continue using Orris.
This is a shared conversation. Sign in to Orris to start your own chat.