Dns surgery procedure

| Instrument | Purpose |
|---|---|
| Cottle elevator | Mucosal flap elevation |
| Killian/Cottle nasal speculum | Retraction and visualization |
| Watson-Williams forceps | Cartilage removal (preferred over Jansen-Middleton) |
| Becker septal scissors | Bony septum cuts |
| 4-mm curved unguarded osteotome | Bony contribution to floor deviations |
| No. 15 blade | Cartilage incisions |
| Complication | Cause/Notes |
|---|---|
| Persistent nasal obstruction | Most common; often from inadequate treatment of posterior bony spurs |
| Septal hematoma | When quilting stitch is omitted |
| Septal perforation | Bilateral mucoperichondrial tears that are not repaired |
| Saddle nose / tip ptosis | Overresection of caudal septum or loss of L-strut support |
| Synechiae | Traumatic suturing causing adhesions between septum and turbinate |
| Rhinorrhea | May persist for months |
| Infection | Rare |
Create a summary PDF of septoplasty techniques and step-by-step procedures
ls -la /tmp/workspace/ 2>/dev/null || echo "workspace does not exist"
mkdir -p /tmp/workspace/septoplasty-pdf
~/septoplasty-pdf/generate_pdf.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, ListFlowable, ListItem
)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus import PageBreak
OUTPUT = "/tmp/workspace/septoplasty-pdf/Septoplasty_Summary.pdf"
# ── Colour palette ──────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1B3A5C")
TEAL = colors.HexColor("#1A7A7A")
LIGHT_BG = colors.HexColor("#EAF4F4")
ORANGE = colors.HexColor("#C65C1A")
GREY_RULE = colors.HexColor("#AAAAAA")
WHITE = colors.white
DARK_TEXT = colors.HexColor("#1C1C1C")
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=18*mm, rightMargin=18*mm,
topMargin=20*mm, bottomMargin=20*mm,
title="Septoplasty – DNS Surgery Summary",
author="Orris Medical Library",
subject="Deviated Nasal Septum Surgery Procedure"
)
W, H = A4
CONTENT_W = W - 36*mm
styles = getSampleStyleSheet()
# ── Custom styles ────────────────────────────────────────────────────────────
def make_style(name, parent="Normal", **kw):
s = ParagraphStyle(name, parent=styles[parent], **kw)
styles.add(s)
return s
COVER_TITLE = make_style("CoverTitle", fontSize=28, textColor=WHITE,
fontName="Helvetica-Bold", leading=34,
alignment=TA_CENTER, spaceAfter=6)
COVER_SUB = make_style("CoverSub", fontSize=14, textColor=colors.HexColor("#BFE4E4"),
fontName="Helvetica", leading=18,
alignment=TA_CENTER, spaceAfter=4)
COVER_BODY = make_style("CoverBody", fontSize=10, textColor=colors.HexColor("#D8EFEF"),
fontName="Helvetica", leading=14,
alignment=TA_CENTER)
H1 = make_style("H1", fontSize=15, textColor=WHITE, fontName="Helvetica-Bold",
leading=19, spaceBefore=0, spaceAfter=0, alignment=TA_LEFT)
H2 = make_style("H2", fontSize=12, textColor=NAVY, fontName="Helvetica-Bold",
leading=16, spaceBefore=10, spaceAfter=4)
H3 = make_style("H3", fontSize=10.5, textColor=TEAL, fontName="Helvetica-Bold",
leading=14, spaceBefore=7, spaceAfter=2)
BODY = make_style("BODY", fontSize=9.5, textColor=DARK_TEXT,
fontName="Helvetica", leading=14, spaceAfter=4,
alignment=TA_JUSTIFY)
BULLET = make_style("BULLET", fontSize=9.5, textColor=DARK_TEXT,
fontName="Helvetica", leading=14, leftIndent=12,
spaceAfter=3)
STEP_NUM = make_style("STEPNUM", fontSize=11, textColor=WHITE,
fontName="Helvetica-Bold", leading=14,
alignment=TA_CENTER)
STEP_BODY = make_style("STEPBODY", fontSize=9.5, textColor=DARK_TEXT,
fontName="Helvetica", leading=13, spaceAfter=3,
alignment=TA_JUSTIFY)
STEP_HEAD = make_style("STEPHEAD", fontSize=10.5, textColor=NAVY,
fontName="Helvetica-Bold", leading=14, spaceAfter=2)
CAPTION = make_style("CAPTION", fontSize=8, textColor=colors.HexColor("#555555"),
fontName="Helvetica-Oblique", leading=10,
alignment=TA_CENTER, spaceAfter=6)
SOURCE = make_style("SOURCE", fontSize=7.5, textColor=colors.HexColor("#777777"),
fontName="Helvetica-Oblique", leading=10)
WARN = make_style("WARN", fontSize=9, textColor=ORANGE,
fontName="Helvetica-Bold", leading=12,
leftIndent=8, spaceAfter=3)
# ── Helper: section header band ──────────────────────────────────────────────
def section_band(title):
tbl = Table([[Paragraph(title, H1)]], colWidths=[CONTENT_W])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), NAVY),
("TOPPADDING", (0,0), (-1,-1), 7),
("BOTTOMPADDING",(0,0),(-1,-1), 7),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING",(0,0), (-1,-1), 10),
("ROUNDEDCORNERS", [4]),
]))
return tbl
def teal_band(title):
tbl = Table([[Paragraph(title, H1)]], colWidths=[CONTENT_W])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), TEAL),
("TOPPADDING", (0,0), (-1,-1), 6),
("BOTTOMPADDING",(0,0),(-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 10),
("RIGHTPADDING",(0,0), (-1,-1), 10),
]))
return tbl
def hr():
return HRFlowable(width="100%", thickness=0.5, color=GREY_RULE, spaceAfter=4, spaceBefore=4)
def sp(h=4):
return Spacer(1, h)
def bullet(text):
return Paragraph(f"• {text}", BULLET)
# ── Step card helper ─────────────────────────────────────────────────────────
def step_card(num, title, body_lines):
num_cell = Paragraph(str(num), STEP_NUM)
head_cell = Paragraph(title, STEP_HEAD)
body_paras = [Paragraph(line, STEP_BODY) for line in body_lines]
num_tbl = Table([[num_cell]], colWidths=[10*mm], rowHeights=[10*mm])
num_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), TEAL),
("ALIGN", (0,0),(-1,-1), "CENTER"),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("ROUNDEDCORNERS",[4]),
]))
right_content = [head_cell] + body_paras
right_tbl = Table([[p] for p in right_content], colWidths=[CONTENT_W - 16*mm])
right_tbl.setStyle(TableStyle([
("LEFTPADDING", (0,0),(-1,-1), 0),
("RIGHTPADDING",(0,0),(-1,-1), 0),
("TOPPADDING", (0,0),(-1,-1), 0),
("BOTTOMPADDING",(0,0),(-1,-1), 1),
]))
outer = Table([[num_tbl, right_tbl]], colWidths=[12*mm, CONTENT_W-12*mm])
outer.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), LIGHT_BG),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
("LEFTPADDING", (0,0),(-1,-1), 6),
("RIGHTPADDING", (0,0),(-1,-1), 6),
("VALIGN", (0,0),(-1,-1), "TOP"),
("BOX", (0,0),(-1,-1), 0.5, TEAL),
]))
return [outer, sp(5)]
# ── Warning box ──────────────────────────────────────────────────────────────
def warn_box(text):
tbl = Table([[Paragraph(f"⚠ {text}", WARN)]], colWidths=[CONTENT_W])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), colors.HexColor("#FFF3E0")),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
("LEFTPADDING", (0,0),(-1,-1), 8),
("RIGHTPADDING", (0,0),(-1,-1), 8),
("BOX", (0,0),(-1,-1), 0.8, ORANGE),
]))
return [tbl, sp(5)]
# ═══════════════════════════════════════════════════════════════════════════
# Build story
# ═══════════════════════════════════════════════════════════════════════════
story = []
# ── COVER PAGE ───────────────────────────────────────────────────────────────
cover_bg = Table(
[[Paragraph("SEPTOPLASTY", COVER_TITLE)],
[Paragraph("DNS (Deviated Nasal Septum) Surgery", COVER_SUB)],
[sp(8)],
[Paragraph("Techniques • Step-by-Step Procedure • Complications • Post-op Care", COVER_BODY)],
[sp(14)],
[Paragraph("Sources: Scott-Brown's Otorhinolaryngology HNS Vol 1 | Cummings Otolaryngology HNS", COVER_BODY)],
],
colWidths=[CONTENT_W]
)
cover_bg.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), NAVY),
("TOPPADDING", (0,0),(-1,-1), 30),
("BOTTOMPADDING", (0,0),(-1,-1), 30),
("LEFTPADDING", (0,0),(-1,-1), 20),
("RIGHTPADDING", (0,0),(-1,-1), 20),
]))
story += [cover_bg, sp(12)]
disclaimer_tbl = Table([[Paragraph(
"This document is an educational summary for medical students and ENT residents. "
"Always refer to primary textbooks and consultant guidance for clinical decision-making.",
CAPTION)]], colWidths=[CONTENT_W])
disclaimer_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), colors.HexColor("#F4F4F4")),
("BOX", (0,0),(-1,-1), 0.5, GREY_RULE),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
("LEFTPADDING", (0,0),(-1,-1), 8),
("RIGHTPADDING", (0,0),(-1,-1), 8),
]))
story += [disclaimer_tbl, PageBreak()]
# ══════════════════════════════════════════════════════════════════
# SECTION 1 – OVERVIEW
# ══════════════════════════════════════════════════════════════════
story += [section_band("1. Overview & Definition"), sp(8)]
story += [
Paragraph("What is Septoplasty?", H2),
Paragraph(
"Septoplasty is the surgical correction of a Deviated Nasal Septum (DNS) to relieve nasal obstruction. "
"The term derives from the Greek meaning 'to reshape or mold the septum.' Modern surgery emphasizes "
"<b>reconstruction and preservation</b> of structural support rather than aggressive excision, aiming to "
"maximise symptomatic improvement while minimising operative risk.",
BODY),
sp(4),
Paragraph("Indications", H2),
]
indications = [
"Nasal obstruction due to cartilaginous or bony septal deviation",
"Septal spurs causing unilateral or bilateral obstruction",
"Recurrent sinusitis with impaired mucociliary drainage",
"Concomitant endoscopic sinus surgery (ESS) requiring septal access",
"Nasal component of obstructive sleep apnoea (OSA)",
"Source cartilage harvest for rhinoplasty grafts",
]
for i in indications:
story.append(bullet(i))
story.append(sp(6))
# L-strut concept box
l_strut_tbl = Table([[
Paragraph("<b>The L-Strut Concept</b>", H3),
Paragraph(
"The L-strut (dorsal + caudal arms of the quadrilateral cartilage) must be preserved intact. "
"A minimum of <b>1 cm</b> of both struts must remain to provide nasal tip and dorsal support. "
"Violation leads to saddle nose deformity or tip ptosis.",
STEP_BODY)
]], colWidths=[48*mm, CONTENT_W-52*mm])
l_strut_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,-1), LIGHT_BG),
("BACKGROUND", (1,0),(1,-1), colors.HexColor("#F0FAFA")),
("BOX", (0,0),(-1,-1), 0.8, TEAL),
("INNERGRID", (0,0),(-1,-1), 0.4, TEAL),
("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), "MIDDLE"),
]))
story += [l_strut_tbl, sp(8)]
story.append(PageBreak())
# ══════════════════════════════════════════════════════════════════
# SECTION 2 – STEP-BY-STEP PROCEDURE
# ══════════════════════════════════════════════════════════════════
story += [section_band("2. Step-by-Step Surgical Procedure"), sp(8)]
steps = [
(1, "Pre-operative Assessment",
["Full nasal endoscopy to map the deviation (cartilaginous, bony, or L-strut).",
"Anterior rhinoscopy, CT scan of PNS if sinus disease is suspected.",
"Assess for caudal dislocation, spur formation, S-shaped deformity.",
"Consent: discuss risk of persistent obstruction, haematoma, perforation, saddle nose."]),
(2, "Patient Positioning & Preparation",
["Supine position with head slightly elevated (reverse Trendelenburg ~15°) to reduce mucosal congestion.",
"Topical vasoconstrictors applied: 4% cocaine solution or oxymetazoline on cotton pledgets bilaterally.",
"IV pre-medication: fentanyl + midazolam (stabilises against vasopressor cardiac effects).",
"Infiltrative local anaesthetic: lidocaine with 1:100,000 or 1:200,000 epinephrine injected submucosally.",
"Wait 5-10 min for full vasoconstriction before incision."]),
(3, "Anaesthesia",
["General anaesthesia (most common) OR local anaesthesia with IV sedation.",
"Monitor for cocaine toxicity: pupil constriction, hypotension, vomiting, arrhythmia.",
"Throat pack placed to prevent blood from entering the oropharynx."]),
(4, "Incision",
["Killian (intercartilaginous) incision: 1-2 cm posterior to caudal septum — for body deformities only.",
"Hemitransfixion incision: at caudal edge of septum — provides access to the entire septum and L-strut (preferred).",
"Extended hemitransfixion: if nasal floor access is needed.",
"Bilateral transfixion: for S-shaped deformities requiring bilateral flap elevation."]),
(5, "Mucoperichondrial Flap Elevation",
["Identify the correct subperichondrial plane (avascular = minimal bleeding).",
"Raise the flap on the CONCAVE side first using a Cottle elevator (preserves contralateral mucosa).",
"Extend the flap anteriorly as far cephalically as possible, then change direction posteriorly.",
"Raise bilateral flaps only when required (S-shaped deformity, bilateral suture placement).",
"Flap raised to expose the quadrilateral cartilage, perpendicular plate of ethmoid, and vomer."]),
(6, "Addressing the Deviation",
["Choose technique(s) based on type/location of deviation — see Section 3 for details.",
"Disarticulate osseocartilaginous junction if bony attachment is the cause of dorsal deviation.",
"Use Becker septal scissors for superior/inferior cuts in bony septum before mobilising bony fragments.",
"NEVER manipulate the superior bony septum without a superior incision first (risk of cribriform injury).",
"Preserve the L-strut (minimum 1 cm caudal and dorsal).",
"Harvest cartilage grafts (from excised segments) if rhinoplasty grafting is planned."]),
(7, "Closure",
["Replace mucosal flaps and approximate with quilting sutures (5-0 plain gut) to prevent haematoma.",
"Transseptal mattress sutures prevent dead space; no tight packing required if no osteotomy performed.",
"Silastic internal splints: used ONLY if mucosa is excoriated or perforated.",
"Light nasal packing (gentamicin cream-impregnated nonstick cotton) if turbinate surgery or osteotomies done.",
"Remove throat pack; confirm haemostasis before extubation."]),
(8, "Post-operative Care",
["Pack removed on day 1 post-op.",
"Saline nasal irrigation 4x/day from day 1.",
"Antibiotic ointment in vestibule from 24 hours post-op.",
"Gentle suctioning on post-op days 5-10.",
"No vigorous nose blowing for 3 weeks.",
"No strenuous exercise for 6 weeks.",
"Review at 1-2 weeks for wound check; endoscopy at 4-6 weeks."]),
]
for num, title, lines in steps:
story += step_card(num, title, lines)
story.append(sp(4))
story.append(PageBreak())
# ══════════════════════════════════════════════════════════════════
# SECTION 3 – TECHNIQUES
# ══════════════════════════════════════════════════════════════════
story += [section_band("3. Surgical Techniques"), sp(8)]
story += [
Paragraph("The deviated septum can be addressed by four main strategies, used alone or in combination:", BODY),
sp(4),
]
techniques = [
("A. Cutting Techniques", [
("Scoring", "Scoring of the concave surface weakens the cartilage, allowing it to spring straight. Scar tissue in the grooves fixes it. Scored segments are usually splinted with a batten graft for reliability."),
("Swinging Door", "Excess caudal L-strut cartilage is excised, allowing the septum to swing to the midline. The septum is then anchored to the anterior nasal spine with 4-0 PDS sutures (through a drilled hole in the bone)."),
("Osseocartilaginous Junction Disarticulation", "Required when bony attachment to the perpendicular plate of ethmoid causes dorsal deviation. The junction is disarticulated all the way through."),
]),
("B. Grafting (Splinting) Techniques", [
("Batten Graft", "A cartilage graft placed alongside the scored segment to hold it straight while scar tissue matures. Reduces risk from under/over-scoring."),
("Spreader Grafts", "Placed between the upper lateral cartilages and septum; helps straighten the dorsal septum and widen the internal nasal valve."),
("PDS Sheet / Ethmoid Plate Splint", "In extracorporeal septoplasty, fragmented pieces are reassembled (jigsaw puzzle) against a thin ethmoid bone graft or PDS sheet using 5-0 PDS sutures."),
]),
("C. Suturing Techniques", [
("Anterior Nasal Spine Fixation", "4-0 PDS sutures through a drilled hole in the anterior nasal spine for caudal stabilisation."),
("Upper Lateral Cartilage Fixation", "5-0 Prolene or PDS sutures to reattach the neo-septum to the upper laterals after extracorporeal reconstruction."),
("Quilting Sutures", "5-0 plain gut transseptal sutures at closure to obliterate dead space and prevent septal haematoma."),
]),
("D. Relocating Techniques", [
("Repositioning to Midline", "After all attachments are released, the freed septum is physically repositioned to the midline and held with sutures or packing."),
]),
]
for tech_title, subtechs in techniques:
story += [teal_band(tech_title), sp(5)]
for name, desc in subtechs:
row = Table([[
Paragraph(name, STEP_HEAD),
Paragraph(desc, STEP_BODY),
]], colWidths=[40*mm, CONTENT_W-44*mm])
row.setStyle(TableStyle([
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 6),
("RIGHTPADDING", (0,0),(-1,-1), 6),
("VALIGN", (0,0),(-1,-1), "TOP"),
("BOX", (0,0),(-1,-1), 0.4, GREY_RULE),
("BACKGROUND", (0,0),(0,-1), LIGHT_BG),
]))
story += [row, sp(4)]
story.append(sp(4))
story.append(PageBreak())
# ══════════════════════════════════════════════════════════════════
# SECTION 4 – SPECIAL APPROACHES
# ══════════════════════════════════════════════════════════════════
story += [section_band("4. Special Approaches"), sp(8)]
special = [
("Endoscopic Septoplasty",
"Introduced by Giles et al. (1994). Mucoperichondrium is incised just caudal to the deviation, "
"and the flap is elevated circumferentially around it. Useful for limited deviations, isolated spurs, "
"and concurrent ESS. NOT adequate for caudal deflections, high dorsal deviations, or complex deformities "
"due to limited flap elevation.",
"Best for: limited/isolated spur, concurrent ESS, revision with targeted access."),
("External Approach (Open Septorhinoplasty)",
"A columellar incision (inverted-V or stepped) combined with bilateral marginal incisions provides "
"full exposure of the septal L-strut under direct vision. Preferred for complex dorsal deformities "
"and combined aesthetic-functional cases.",
"Best for: complex L-strut deformity, combined rhinoplasty, extracorporeal work."),
("Extracorporeal Septoplasty",
"For severely fractured/deformed septa. The entire septum is removed in one piece, reshaped on the "
"back table (re-orientation or jigsaw reconstruction with ethmoid/PDS splint), then reinserted and "
"fixed at: (1) maxillary crest groove, (2) anterior nasal spine — 4-0 PDS, "
"(3) upper lateral cartilages — 5-0 Prolene/PDS, (4) nasal bones at K-stone.",
"Best for: severely fractured/multi-piece septum, failed prior septoplasty."),
("Paediatric Septoplasty",
"Generally deferred until growth is complete (≥17 years in females, ≥18 in males) due to risk of "
"disrupting nasal growth centres. Conservative resection only when obstruction is severe. "
"Avoid anterior nasal spine manipulation.",
"Best for: severe symptomatic DNS in adolescents — conservative, limited approach only."),
]
for title, desc, indic in special:
tbl = Table([
[Paragraph(title, H2)],
[Paragraph(desc, BODY)],
[Paragraph(f"<b>Indication: </b>{indic}", WARN)],
], colWidths=[CONTENT_W])
tbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), LIGHT_BG),
("BACKGROUND", (0,1),(0,-1), colors.white),
("BOX", (0,0),(-1,-1), 0.8, TEAL),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
("LEFTPADDING", (0,0),(-1,-1), 10),
("RIGHTPADDING", (0,0),(-1,-1), 10),
]))
story += [tbl, sp(6)]
story.append(PageBreak())
# ══════════════════════════════════════════════════════════════════
# SECTION 5 – INSTRUMENTS
# ══════════════════════════════════════════════════════════════════
story += [section_band("5. Instruments"), sp(8)]
inst_data = [
["Instrument", "Purpose"],
["Cottle elevator", "Subperichondrial/periosteal flap elevation"],
["Killian / Cottle nasal speculum", "Nasal retraction and visualisation"],
["Watson-Williams forceps (wide-mouth)", "Cartilage/bone removal (preferred; less risk of inadvertent cuts)"],
["Jansen-Middleton forceps", "Bone/cartilage removal (avoid — risk of cutting reusable cartilage)"],
["Becker septal scissors", "Cuts in bony septum above/below deviation or spur"],
["4-mm curved unguarded osteotome", "Bony contribution to nasal floor and crest deviations"],
["Ballenger swivel knife", "Older instrument; propensity to tear membranes — use cautiously"],
["No. 15 blade", "Cartilage incisions; risk of contralateral injury if used aggressively"],
["Asch forceps", "Historical; closed reduction of cartilaginous deviations (largely abandoned)"],
["Fissure burr / drill", "Creating groove in maxillary crest; drilling hole in anterior nasal spine"],
]
inst_tbl = Table(inst_data, colWidths=[55*mm, CONTENT_W-57*mm])
inst_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,0), 9.5),
("FONTNAME", (0,1),(-1,-1), "Helvetica"),
("FONTSIZE", (0,1),(-1,-1), 9),
("ROWBACKGROUNDS",(0,1),(-1,-1), [colors.white, LIGHT_BG]),
("GRID", (0,0),(-1,-1), 0.4, GREY_RULE),
("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"),
("ALIGN", (0,0),(-1,0), "CENTER"),
]))
story += [inst_tbl, sp(10), PageBreak()]
# ══════════════════════════════════════════════════════════════════
# SECTION 6 – COMPLICATIONS
# ══════════════════════════════════════════════════════════════════
story += [section_band("6. Complications"), sp(8)]
comp_data = [
["Complication", "Frequency", "Cause / Notes"],
["Persistent nasal obstruction", "Most common", "Inadequate resection of posterior bony spurs; revision septoplasty required"],
["Septal haematoma", "Uncommon", "Failure to use quilting sutures; requires urgent drainage to prevent avascular necrosis"],
["Septal perforation", "Uncommon", "Bilateral mucosal tears not repaired; smoking; infection"],
["Saddle nose / tip ptosis", "Rare", "Overresection of caudal septum or loss of L-strut support"],
["Synechiae (adhesions)", "Uncommon", "Traumatic suturing; septum-turbinate contact; requires division"],
["Rhinorrhoea", "Common (transient)", "Persistent rhinorrhoea may last a few months postoperatively"],
["Infection", "Rare", "Prophylactic antibiotics; Toxic shock syndrome reported (rare)"],
["Anosmia / hyposmia", "Rare", "Upper nasal mucosal trauma"],
["Intracranial injury / CSF leak", "Very rare", "Superior septal manipulation without prior superior incision"],
]
comp_tbl = Table(comp_data, colWidths=[52*mm, 32*mm, CONTENT_W-88*mm])
comp_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), ORANGE),
("TEXTCOLOR", (0,0),(-1,0), WHITE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0),(-1,0), 9.5),
("FONTNAME", (0,1),(-1,-1), "Helvetica"),
("FONTSIZE", (0,1),(-1,-1), 9),
("ROWBACKGROUNDS",(0,1),(-1,-1), [colors.white, colors.HexColor("#FFF8F4")]),
("GRID", (0,0),(-1,-1), 0.4, GREY_RULE),
("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"),
("ALIGN", (0,0),(-1,0), "CENTER"),
]))
story += [comp_tbl, sp(8)]
story += warn_box(
"Septal haematoma is a surgical emergency — evacuate within 24-48 hours to prevent "
"avascular necrosis of the cartilage and 'saddle nose' deformity."
)
story.append(PageBreak())
# ══════════════════════════════════════════════════════════════════
# SECTION 7 – QUICK REFERENCE CARD
# ══════════════════════════════════════════════════════════════════
story += [section_band("7. Quick Reference Summary"), sp(8)]
qr_data = [
["Parameter", "Key Point"],
["Incision of choice", "Hemitransfixion (full L-strut access)"],
["Flap plane", "Subperichondrial / subperiosteal (avascular)"],
["L-strut minimum", "1 cm caudal + 1 cm dorsal preserved"],
["L-strut fixation suture", "4-0 PDS to anterior nasal spine"],
["Haematoma prevention", "Quilting suture (5-0 plain gut)"],
["Packing (no osteotomy)", "Quilting stitch alone; avoid tight gauze"],
["Packing (with osteotomy/turbinate Sx)", "Light gentamicin cream-impregnated cotton; remove day 1"],
["Splints", "Soft Silastic only if mucosa excoriated/perforated"],
["Saline irrigation", "4x/day from day 1"],
["Nose blowing", "Gentle only after week 3"],
["Return to exercise", "After 6 weeks"],
["Extracorporeal fixation points", "Maxillary crest + ANS (4-0 PDS) + ULC (5-0 Prolene/PDS) + K-stone"],
["Cribriform protection", "Superior septal incision before ANY superior bony manipulation"],
]
qr_tbl = Table(qr_data, colWidths=[62*mm, CONTENT_W-64*mm])
qr_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,0), 9.5),
("FONTNAME", (0,1),(-1,-1), "Helvetica"),
("FONTSIZE", (0,1),(-1,-1), 9),
("ROWBACKGROUNDS",(0,1),(-1,-1), [colors.white, LIGHT_BG]),
("GRID", (0,0),(-1,-1), 0.4, GREY_RULE),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 8),
("RIGHTPADDING", (0,0),(-1,-1), 8),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("ALIGN", (0,0),(-1,0), "CENTER"),
("FONTNAME", (0,1),(-1,-1), "Helvetica"),
("FONTNAME", (0,1),(0,-1), "Helvetica-Bold"),
]))
story += [qr_tbl, sp(12)]
# ── Sources footer ────────────────────────────────────────────────────────────
story += [
hr(),
Paragraph("<b>References / Sources:</b>", SOURCE),
Paragraph(
"1. Scott-Brown's Otorhinolaryngology Head & Neck Surgery, Vol 1 (ISBN 9781138094611) — Chapter 103: Septoplasty.",
SOURCE),
Paragraph(
"2. Cummings Otolaryngology Head and Neck Surgery (ISBN 9780323612173) — Chapter 29: Nasal Obstruction & Septoplasty.",
SOURCE),
Paragraph(
"3. Textbook of Family Medicine 9e (ISBN 9780323239905) — Deviated Septum.",
SOURCE),
sp(4),
Paragraph("Generated by Orris Medical Library — August 2026. For educational use only.", SOURCE),
]
# ── Build ─────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF saved to: {OUTPUT}")
python /tmp/workspace/septoplasty-pdf/generate_pdf.py
ls -lh /tmp/workspace/septoplasty-pdf/Septoplasty_Summary.pdf
Septoplasty Summary
PDF Document · PDF
| Section | Content |
|---|---|
| Cover Page | Title, subtitle, source attribution |
| 1. Overview & Definition | What is septoplasty, indications, L-strut concept box |
| 2. Step-by-Step Procedure | 8 numbered step cards: pre-op → positioning → anaesthesia → incision → flap elevation → addressing deviation → closure → post-op care |
| 3. Surgical Techniques | Four strategies: Cutting, Grafting, Suturing, Relocating — each with named subtechniques |
| 4. Special Approaches | Endoscopic, External, Extracorporeal, and Paediatric septoplasty |
| 5. Instruments | Colour-coded table of all key instruments and their purposes |
| 6. Complications | Table with frequency + causes; includes haematoma warning box |
| 7. Quick Reference Card | 14-row colour summary of all key parameters for rapid revision |