Make a pdf on thorax region of anatomy

Reading File
Reading File
Finding Sources
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Reading File
Running Command

mkdir -p /home/daytona/workspace/thorax-anatomy && ls /home/daytona/workspace/th…

Writing File

~/thorax-anatomy/generate_pdf.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.platypus import (SimpleDocTemplate, Paragraph, Spacer, Table,
                                 TableStyle, HRFlowable, PageBreak, ListFlowable, ListItem)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY

OUTPUT = "/home/daytona/workspace/thorax-anatomy/Thorax_Anatomy.pdf"

doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    rightMargin=2.2*cm,
    leftMargin=2.2*cm,
    topMargin=2.5*cm,
    bottomMargin=2.5*cm,
    title="Thorax Anatomy",
    author="Gray's Anatomy for Students"
)

# ── Colour palette ──────────────────────────────────────────────────────────
DARK_BLUE   = colors.HexColor("#1A3A5C")
MED_BLUE    = colors.HexColor("#2E6DA4")
LIGHT_BLUE  = colors.HexColor("#D6E8F7")
ACCENT      = colors.HexColor("#E8531F")
LIGHT_GREY  = colors.HexColor("#F5F5F5")
DIVIDER     = colors.HexColor("#BFCDD9")

# ── Styles ───────────────────────────────────────────────────────────────────
base = getSampleStyleSheet()

def S(name, parent="Normal", **kw):
    return ParagraphStyle(name, parent=base[parent], **kw)

cover_title  = S("CoverTitle",  fontSize=34, leading=42, textColor=colors.white,
                  alignment=TA_CENTER, fontName="Helvetica-Bold")
cover_sub    = S("CoverSub",    fontSize=16, leading=24, textColor=LIGHT_BLUE,
                  alignment=TA_CENTER, fontName="Helvetica")
cover_source = S("CoverSource", fontSize=10, leading=14, textColor=colors.HexColor("#BDD4EA"),
                  alignment=TA_CENTER, fontName="Helvetica-Oblique")

h1 = S("H1", fontSize=18, leading=24, textColor=colors.white,
        fontName="Helvetica-Bold", spaceAfter=6, alignment=TA_LEFT)
h2 = S("H2", fontSize=13, leading=18, textColor=DARK_BLUE,
        fontName="Helvetica-Bold", spaceBefore=12, spaceAfter=4)
h3 = S("H3", fontSize=11, leading=15, textColor=MED_BLUE,
        fontName="Helvetica-Bold", spaceBefore=8, spaceAfter=3)
body = S("Body", fontSize=9.5, leading=14.5, textColor=colors.HexColor("#222222"),
          alignment=TA_JUSTIFY, fontName="Helvetica", spaceAfter=6)
bullet_s = S("Bullet", fontSize=9.5, leading=14, textColor=colors.HexColor("#222222"),
              fontName="Helvetica", leftIndent=14, spaceAfter=3)
caption = S("Caption", fontSize=8, leading=12, textColor=colors.HexColor("#555555"),
             fontName="Helvetica-Oblique", alignment=TA_CENTER, spaceAfter=8)
clinical = S("Clinical", fontSize=9, leading=13.5, textColor=colors.HexColor("#333333"),
              fontName="Helvetica-Oblique", alignment=TA_JUSTIFY, leftIndent=10, rightIndent=10)
toc_entry = S("TOC", fontSize=10.5, leading=16, textColor=DARK_BLUE,
               fontName="Helvetica", spaceAfter=4)
toc_num   = S("TOCNum", fontSize=10.5, leading=16, textColor=MED_BLUE,
               fontName="Helvetica-Bold", spaceAfter=4, alignment=TA_LEFT)

# ── Helper builders ──────────────────────────────────────────────────────────
def hr():
    return HRFlowable(width="100%", thickness=0.6, color=DIVIDER, spaceAfter=6, spaceBefore=4)

def section_header(text, level=1):
    """Blue banner for H1 headings."""
    data = [[Paragraph(text, h1)]]
    t = Table(data, colWidths=[doc.width])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), MED_BLUE),
        ("LEFTPADDING",  (0,0), (-1,-1), 10),
        ("RIGHTPADDING", (0,0), (-1,-1), 10),
        ("TOPPADDING",   (0,0), (-1,-1), 7),
        ("BOTTOMPADDING",(0,0), (-1,-1), 7),
        ("ROUNDEDCORNERS", (0,0), (-1,-1), [4,4,4,4]),
    ]))
    return t

def info_box(title, content_lines, bg=LIGHT_BLUE):
    """Coloured info box for key facts."""
    rows = [[Paragraph(f"<b>{title}</b>", ParagraphStyle("BH", fontSize=9.5, leading=13,
                        textColor=DARK_BLUE, fontName="Helvetica-Bold"))]]
    for line in content_lines:
        rows.append([Paragraph(f"• {line}", ParagraphStyle("BI", fontSize=9, leading=13,
                               textColor=colors.HexColor("#222222"), fontName="Helvetica"))])
    t = Table(rows, colWidths=[doc.width])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (0,0), bg),
        ("BACKGROUND", (0,1), (-1,-1), LIGHT_GREY),
        ("BOX",        (0,0), (-1,-1), 0.8, MED_BLUE),
        ("LINEBELOW",  (0,0), (0,0), 0.5, MED_BLUE),
        ("LEFTPADDING",  (0,0), (-1,-1), 8),
        ("RIGHTPADDING", (0,0), (-1,-1), 8),
        ("TOPPADDING",   (0,0), (-1,-1), 4),
        ("BOTTOMPADDING",(0,0), (-1,-1), 4),
    ]))
    return t

def clinical_box(text):
    data = [[Paragraph("<b>IN THE CLINIC</b>", ParagraphStyle("ClinH", fontSize=9,
                        textColor=ACCENT, fontName="Helvetica-Bold")),
             Paragraph(text, clinical)]]
    t = Table(data, colWidths=[2.4*cm, doc.width-2.4*cm])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), colors.HexColor("#FFF8F5")),
        ("BOX",        (0,0), (-1,-1), 0.8, ACCENT),
        ("LEFTPADDING",  (0,0), (-1,-1), 8),
        ("RIGHTPADDING", (0,0), (-1,-1), 8),
        ("TOPPADDING",   (0,0), (-1,-1), 6),
        ("BOTTOMPADDING",(0,0), (-1,-1), 6),
        ("VALIGN", (0,0), (-1,-1), "TOP"),
    ]))
    return t

def two_col_table(data_rows, headers=None, col_ratios=None):
    """Generic 2-column comparison table."""
    cw = col_ratios or [doc.width*0.45, doc.width*0.55]
    rows = []
    if headers:
        rows.append([Paragraph(f"<b>{h}</b>", ParagraphStyle("TH", fontSize=9,
                                textColor=colors.white, fontName="Helvetica-Bold"))
                     for h in headers])
    for row in data_rows:
        rows.append([Paragraph(str(c), ParagraphStyle("TD", fontSize=9, leading=13,
                                fontName="Helvetica")) for c in row])
    t = Table(rows, colWidths=cw)
    style = [
        ("BACKGROUND", (0,0), (-1,0), MED_BLUE if headers else LIGHT_BLUE),
        ("BACKGROUND", (0,1), (-1,-1), colors.white),
        ("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_GREY]),
        ("GRID", (0,0), (-1,-1), 0.4, DIVIDER),
        ("LEFTPADDING",  (0,0), (-1,-1), 6),
        ("RIGHTPADDING", (0,0), (-1,-1), 6),
        ("TOPPADDING",   (0,0), (-1,-1), 4),
        ("BOTTOMPADDING",(0,0), (-1,-1), 4),
        ("VALIGN", (0,0), (-1,-1), "TOP"),
    ]
    t.setStyle(TableStyle(style))
    return t

# ═══════════════════════════════════════════════════════════════════════════
# CONTENT
# ═══════════════════════════════════════════════════════════════════════════
story = []

# ── COVER PAGE ───────────────────────────────────────────────────────────────
cover_bg = Table([[""]], colWidths=[doc.width + 4.4*cm], rowHeights=[29.7*cm])
cover_bg.setStyle(TableStyle([("BACKGROUND", (0,0), (-1,-1), DARK_BLUE)]))

story.append(Spacer(1, 3*cm))
story.append(Paragraph("THORAX", cover_title))
story.append(Spacer(1, 0.6*cm))
story.append(Paragraph("Regional Anatomy of the Thoracic Region", cover_sub))
story.append(Spacer(1, 0.4*cm))
story.append(HRFlowable(width="60%", thickness=1.5, color=ACCENT, spaceAfter=12))
story.append(Paragraph("Based on Gray's Anatomy for Students (9780323934237)", cover_source))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph("July 2026", cover_source))
story.append(PageBreak())

# ── TABLE OF CONTENTS ────────────────────────────────────────────────────────
story.append(section_header("TABLE OF CONTENTS"))
story.append(Spacer(1, 0.3*cm))

toc_items = [
    ("1", "Overview & General Description"),
    ("2", "Thoracic Wall"),
    ("3", "Skeletal Framework"),
    ("4", "Muscles of the Thoracic Wall"),
    ("5", "Neurovascular Supply"),
    ("6", "Diaphragm"),
    ("7", "Pleural Cavities & Pleura"),
    ("8", "Lungs"),
    ("9", "Mediastinum"),
    ("10", "Heart & Pericardium"),
    ("11", "Clinical Correlations"),
    ("12", "Summary Tables"),
]
toc_data = [[Paragraph(f"<b>{n}</b>", toc_num), Paragraph(t, toc_entry)] for n,t in toc_items]
toc_table = Table(toc_data, colWidths=[1.2*cm, doc.width - 1.2*cm])
toc_table.setStyle(TableStyle([
    ("ROWBACKGROUNDS", (0,0), (-1,-1), [colors.white, LIGHT_GREY]),
    ("GRID", (0,0), (-1,-1), 0.3, DIVIDER),
    ("LEFTPADDING",  (0,0), (-1,-1), 8),
    ("RIGHTPADDING", (0,0), (-1,-1), 8),
    ("TOPPADDING",   (0,0), (-1,-1), 5),
    ("BOTTOMPADDING",(0,0), (-1,-1), 5),
]))
story.append(toc_table)
story.append(PageBreak())

# ── 1. OVERVIEW ──────────────────────────────────────────────────────────────
story.append(section_header("1. Overview & General Description"))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
    "The thorax is an irregularly shaped cylinder with a <b>narrow superior opening</b> (superior thoracic aperture) "
    "superiorly and a <b>relatively large inferior opening</b> (inferior thoracic aperture) inferiorly. "
    "The superior thoracic aperture is open, allowing continuity with the neck; the inferior thoracic aperture "
    "is closed by the diaphragm.", body))
story.append(Paragraph(
    "The musculoskeletal wall of the thorax is flexible and consists of segmentally arranged <b>vertebrae, ribs, "
    "muscles</b>, and the <b>sternum</b>.", body))

story.append(Paragraph("Major Compartments", h2))
story.append(info_box("Three Compartments of the Thoracic Cavity", [
    "Left pleural cavity — surrounds the left lung",
    "Right pleural cavity — surrounds the right lung",
    "Mediastinum — central partition containing heart, great vessels, trachea, esophagus, and major nerves",
]))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
    "The mediastinum is a thick, flexible soft-tissue partition oriented longitudinally in a median sagittal position. "
    "It contains the heart, esophagus, trachea, major nerves, and major systemic blood vessels.", body))
story.append(hr())

# ── 2. THORACIC WALL ─────────────────────────────────────────────────────────
story.append(section_header("2. Thoracic Wall"))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
    "The thoracic wall consists of skeletal elements and muscles. It extends between the <b>superior thoracic "
    "aperture</b> (bordered by vertebra T1, rib I, and the manubrium) and the <b>inferior thoracic aperture</b> "
    "(bordered by vertebra TXII, rib XII, the end of rib XI, the costal margin, and the xiphoid process).", body))

story.append(Paragraph("Wall Regions", h2))
comp_data = [
    ["Posterior", "12 thoracic vertebrae + intervertebral discs"],
    ["Lateral",   "12 pairs of ribs + 3 layers of flat intercostal muscles"],
    ["Anterior",  "Sternum (manubrium + body + xiphoid process)"],
]
story.append(two_col_table(comp_data, headers=["Region", "Composition"]))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
    "The <b>manubrium of the sternum</b>, angled posteriorly on the body at the manubriosternal joint, forms the "
    "<b>sternal angle (angle of Louis)</b> — a major surface landmark used in clinical examination of the thorax. "
    "The sternal angle marks the level of the second costal cartilage and corresponds to the inter-vertebral disc "
    "between TIV and TV.", body))
story.append(Paragraph(
    "The anterior (distal) end of each rib is composed of <b>costal cartilage</b>, which contributes to the "
    "mobility and elasticity of the wall.", body))
story.append(hr())

# ── 3. SKELETAL FRAMEWORK ────────────────────────────────────────────────────
story.append(section_header("3. Skeletal Framework"))
story.append(Spacer(1, 0.3*cm))

story.append(Paragraph("Thoracic Vertebrae", h2))
story.append(Paragraph(
    "There are <b>twelve thoracic vertebrae</b>, each characterised by articulations with ribs. A typical thoracic "
    "vertebra has a <b>heart-shaped vertebral body</b>, a long spinous process, broad overlapping laminae, and "
    "flat superior articular processes facing almost directly posteriorly.", body))
story.append(Paragraph(
    "Each typical thoracic vertebra has three sites on each side for rib articulation: two demifacets on the "
    "superior and inferior body aspects, and a transverse costal facet at the end of the transverse process.", body))

story.append(Paragraph("Ribs", h2))
rib_data = [
    ["I – VII",   "True ribs — costal cartilages articulate directly with sternum"],
    ["VIII – X",  "False ribs — costal cartilages articulate with cartilage above"],
    ["XI – XII",  "Floating ribs — do not articulate with sternum or adjacent ribs; costal cartilages only cover their tips"],
]
story.append(two_col_table(rib_data, headers=["Ribs", "Classification & Articulation"]))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
    "Most ribs (II–IX) have <b>three articulations</b> with the vertebral column: the head articulates with the "
    "body of its own vertebra and the body of the vertebra above; the tubercle articulates with the transverse "
    "process of its own vertebra.", body))

story.append(Paragraph("Sternum", h2))
story.append(info_box("Parts of the Sternum", [
    "Manubrium — upper part; articulates with clavicles and ribs I–II; forms sternal angle with body",
    "Body — main part; articulates with ribs II–VII via costal cartilages",
    "Xiphoid process — inferior tip; cartilaginous in youth, ossified in adults; landmark for T6 dermatome",
]))
story.append(hr())

# ── 4. MUSCLES OF THE THORACIC WALL ──────────────────────────────────────────
story.append(section_header("4. Muscles of the Thoracic Wall"))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
    "Three layers of flat muscles span the intercostal spaces, move the ribs, and provide structural support.", body))

muscles_data = [
    ["External intercostal", "Inferior border of rib above → superior border of rib below",
     "Elevate ribs (inspiration); fibres run obliquely downward and forward"],
    ["Internal intercostal", "Costal groove of rib above → superior border of rib below",
     "Depress ribs; fibres run at right angles to external layer"],
    ["Innermost intercostal\n(transversus thoracis)", "Innermost thoracic wall", "Same as internal intercostals"],
    ["Serratus posterior superior", "Spinous processes C7–T3 → ribs II–V", "Accessory inspiratory muscle"],
    ["Serratus posterior inferior", "Spinous processes T11–L2 → ribs IX–XII", "Accessory expiratory muscle"],
]

hdr = ["Muscle", "Attachments", "Function"]
cw  = [doc.width*0.25, doc.width*0.40, doc.width*0.35]
rows_p = [[Paragraph(f"<b>{h}</b>", ParagraphStyle("TH2", fontSize=9, textColor=colors.white,
                      fontName="Helvetica-Bold")) for h in hdr]]
for row in muscles_data:
    rows_p.append([Paragraph(c, ParagraphStyle("TD2", fontSize=8.5, leading=12, fontName="Helvetica")) for c in row])

mt = Table(rows_p, colWidths=cw)
mt.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), MED_BLUE),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_GREY]),
    ("GRID", (0,0), (-1,-1), 0.4, DIVIDER),
    ("LEFTPADDING",  (0,0), (-1,-1), 5),
    ("RIGHTPADDING", (0,0), (-1,-1), 5),
    ("TOPPADDING",   (0,0), (-1,-1), 4),
    ("BOTTOMPADDING",(0,0), (-1,-1), 4),
    ("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(mt)
story.append(hr())

# ── 5. NEUROVASCULAR SUPPLY ──────────────────────────────────────────────────
story.append(section_header("5. Neurovascular Supply of the Thoracic Wall"))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
    "The arrangement of vessels and nerves supplying the thoracic wall reflects its segmental organisation.", body))

story.append(Paragraph("Arterial Supply", h2))
story.append(info_box("Two Primary Sources", [
    "Thoracic aorta (posterior mediastinum) — posterior intercostal arteries branch segmentally",
    "Internal thoracic arteries — run along deep aspect of anterior wall on either side of sternum; "
    "give anterior intercostal arteries",
]))

story.append(Paragraph("Intercostal Nerves", h2))
story.append(Paragraph(
    "Intercostal nerves are the <b>anterior rami of thoracic spinal nerves T1–T11</b>. They run with intercostal "
    "vessels mainly along the inferior margin of each rib (costal groove). They innervate the wall, related parietal "
    "pleura, and associated skin.", body))
story.append(Paragraph(
    "<b>Dermatomes of the thorax:</b> The anterosuperior trunk receives branches from C4 (supraclavicular nerves). "
    "The highest thoracic dermatome on the anterior chest wall is T2. In the midline, skin over the xiphoid process "
    "is innervated by T6. Dermatomes T7–T12 follow rib contour onto the anterior abdominal wall.", body))
story.append(clinical_box(
    "Because the neurovascular bundle runs in the costal groove along the inferior margin of each rib, "
    "chest tubes and thoracocentesis needles should be inserted along the <b>superior margin of the rib below</b> "
    "to avoid injuring intercostal nerves and vessels."
))
story.append(Spacer(1, 0.2*cm))

story.append(Paragraph("Sympathetic System", h2))
story.append(Paragraph(
    "Preganglionic sympathetic fibres exit in spinal nerves T1–L2. In the thorax they pass to the sympathetic "
    "trunk and synapse in ganglia. Postganglionic fibres are distributed via intercostal nerves or via thoracic "
    "splanchnic nerves (greater T5–T9, lesser T10–T11, least T12) to abdominal viscera.", body))
story.append(hr())

# ── 6. DIAPHRAGM ─────────────────────────────────────────────────────────────
story.append(section_header("6. Diaphragm"))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
    "The diaphragm closes the inferior thoracic aperture and is the principal muscle of inspiration. "
    "Contraction of its domes flattens them, increasing thoracic volume in the vertical dimension.", body))

story.append(Paragraph("Openings in the Diaphragm", h2))
opening_data = [
    ["Caval opening (T8)",     "IVC", "Right, in central tendon"],
    ["Oesophageal hiatus (T10)", "Oesophagus + vagus nerves", "Left of midline, through muscular part"],
    ["Aortic hiatus (T12)",    "Aorta + thoracic duct (± azygos vein)", "Posterior, behind diaphragm between crura"],
]
story.append(two_col_table(opening_data,
    headers=["Opening & Level", "Structures", "Notes"],
    col_ratios=[doc.width*0.28, doc.width*0.38, doc.width*0.34]))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
    "The sympathetic trunks pass behind the diaphragm lateral to the aortic hiatus. The greater, lesser, and "
    "least splanchnic nerves penetrate the crura.", body))

story.append(Paragraph("Innervation & Blood Supply", h2))
story.append(info_box("Phrenic Nerve (C3, C4, C5)", [
    "Arises from cervical plexus — 'C3, 4, 5 keeps the diaphragm alive'",
    "Passes through neck, superior thoracic aperture, and mediastinum (anterior to lung roots)",
    "Provides motor supply to entire diaphragm including crura",
    "Spinal injuries below the origin of the phrenic nerve do NOT affect diaphragmatic movement",
]))
story.append(Paragraph(
    "<b>Arterial supply:</b> Pericardiacophrenic and musculophrenic arteries (from internal thoracic arteries) "
    "from above; inferior phrenic arteries (from abdominal aorta — largest supply) from below; superior phrenic "
    "and intercostal branches contribute.", body))
story.append(hr())

# ── 7. PLEURAL CAVITIES & PLEURA ─────────────────────────────────────────────
story.append(section_header("7. Pleural Cavities & Pleura"))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
    "Each pleural cavity is a potential space between two layers of pleura: the <b>parietal pleura</b> (lines "
    "thoracic wall, mediastinum, and diaphragm) and the <b>visceral pleura</b> (covers lung surface). The thin "
    "film of pleural fluid between them reduces friction during breathing.", body))

story.append(Paragraph("Parietal Pleura — Parts", h2))
pleura_parts = [
    ["Costal pleura",        "Lines internal surface of thoracic cage; innervated by intercostal nerves"],
    ["Diaphragmatic pleura", "Covers diaphragm; innervated by phrenic nerve (central) and intercostal nerves (peripheral)"],
    ["Mediastinal pleura",   "Covers lateral aspect of mediastinum; innervated by phrenic nerve"],
    ["Cervical pleura (cupola)", "Projects 3–4 cm above first costal cartilage into root of neck; reinforced by Sibson's fascia"],
]
story.append(two_col_table(pleura_parts, headers=["Part", "Description & Innervation"]))
story.append(Spacer(1, 0.3*cm))

story.append(Paragraph("Inferior Extent of Pleural Reflections", h2))
story.append(info_box("Key Lines for Inferior Pleural Margin", [
    "Midclavicular line — pleura extends to rib VIII",
    "Midaxillary line — extends to rib X",
    "Vertebral column — extends to vertebra TXII",
    "Rule of 2: 2–4 cm above rib I superiorly; inferiorly rib VIII (MCL) / X (MAL) / XII (vertebral)",
]))

story.append(Paragraph("Pleural Recesses", h2))
story.append(Paragraph(
    "The lungs do not completely fill the inferior anterior and posterior regions of the pleural cavities, "
    "creating recesses that provide potential spaces for fluid collection.", body))
recess_data = [
    ["Costodiaphragmatic recess",
     "Between costal and diaphragmatic pleura — largest and most clinically important; "
     "fluid from effusions collects here; accessed by thoracocentesis"],
    ["Costomediastinal recess",
     "Between costal and mediastinal pleura anteriorly; largest on left (overlying heart)"],
]
story.append(two_col_table(recess_data, headers=["Recess", "Location & Significance"]))
story.append(hr())

# ── 8. LUNGS ─────────────────────────────────────────────────────────────────
story.append(section_header("8. Lungs"))
story.append(Spacer(1, 0.3*cm))

story.append(Paragraph("Right Lung", h2))
story.append(Paragraph(
    "The right lung is larger than the left, has <b>three lobes</b> (superior, middle, inferior) separated by "
    "the <b>oblique fissure</b> (between superior and middle lobes and inferior lobe) and the <b>horizontal "
    "(transverse) fissure</b> (between superior and middle lobes).", body))
story.append(Paragraph(
    "Medial surface relations: heart, inferior vena cava, superior vena cava, azygos vein, and oesophagus. "
    "The right subclavian artery and vein arch over the dome of the cervical pleura.", body))

story.append(Paragraph("Left Lung", h2))
story.append(Paragraph(
    "The left lung is smaller and has <b>two lobes</b> (superior and inferior) separated by a single <b>oblique "
    "fissure</b>. The inferior portion of the medial surface is notched because the heart projects into the left "
    "pleural cavity — forming the <b>cardiac notch</b>. The tongue-like <b>lingula</b> of the superior lobe "
    "projects over this heart bulge.", body))
story.append(Paragraph(
    "Medial surface relations: aortic arch, descending aorta, thoracic aorta, and left subclavian artery.", body))

story.append(Paragraph("Lung Hilum", h2))
story.append(info_box("Structures at the Lung Root (Hilum)", [
    "Pulmonary artery (most superior on left; anterior and superior on right)",
    "Superior and inferior pulmonary veins",
    "Main bronchus (most posterior)",
    "Bronchial arteries, lymphatics, and autonomic nerves",
    "Visceral pleura reflects onto parietal pleura here",
]))

story.append(Paragraph("Bronchopulmonary Segments", h2))
story.append(Paragraph(
    "Each lung is divided into <b>bronchopulmonary segments</b> — the functional units of the lung, each with "
    "its own segmental (tertiary) bronchus and a segmental artery. The right lung has <b>10 segments</b>; the "
    "left lung has <b>8–10 segments</b> (with some fused). Each segment is separated by connective tissue "
    "septa, allowing surgical resection without affecting adjacent segments.", body))
story.append(hr())

# ── 9. MEDIASTINUM ───────────────────────────────────────────────────────────
story.append(section_header("9. Mediastinum"))
story.append(Spacer(1, 0.3*cm))
story.append(Paragraph(
    "The mediastinum is divided by a transverse plane at the <b>sternal angle</b> (TIV/TV disc level) into "
    "the <b>superior mediastinum</b> above and the <b>inferior mediastinum</b> below. The inferior mediastinum "
    "is further subdivided into anterior, middle, and posterior parts.", body))

story.append(Paragraph("Subdivisions", h2))
med_data = [
    ["Superior mediastinum",
     "Between thoracic inlet and sternal angle (TIV/TV)",
     "Thymus, great vessels (aortic arch, brachiocephalic trunk, SVC), trachea, oesophagus, thoracic duct, vagus and phrenic nerves, left recurrent laryngeal nerve"],
    ["Anterior mediastinum",
     "Posterior to sternum, anterior to pericardium",
     "Inferior thymus extension, fat, connective tissue, lymph nodes, sternopericardial ligaments, mediastinal branches of internal thoracic vessels"],
    ["Middle mediastinum",
     "Central compartment",
     "Pericardium, heart, origins of great vessels, phrenic nerves, smaller vessels"],
    ["Posterior mediastinum",
     "Posterior to pericardium, anterior to vertebral bodies",
     "Oesophagus, descending aorta, thoracic duct, azygos/hemiazygos veins, vagus nerves, sympathetic trunks, posterior intercostal vessels"],
]
hdr3 = ["Division", "Boundaries", "Key Contents"]
cw3 = [doc.width*0.22, doc.width*0.28, doc.width*0.50]
rows3 = [[Paragraph(f"<b>{h}</b>", ParagraphStyle("TH3", fontSize=9, textColor=colors.white,
                    fontName="Helvetica-Bold")) for h in hdr3]]
for row in med_data:
    rows3.append([Paragraph(c, ParagraphStyle("TD3", fontSize=8.5, leading=12, fontName="Helvetica")) for c in row])
mt3 = Table(rows3, colWidths=cw3)
mt3.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,0), MED_BLUE),
    ("ROWBACKGROUNDS", (0,1), (-1,-1), [colors.white, LIGHT_GREY]),
    ("GRID", (0,0), (-1,-1), 0.4, DIVIDER),
    ("LEFTPADDING",  (0,0), (-1,-1), 5),
    ("RIGHTPADDING", (0,0), (-1,-1), 5),
    ("TOPPADDING",   (0,0), (-1,-1), 4),
    ("BOTTOMPADDING",(0,0), (-1,-1), 4),
    ("VALIGN", (0,0), (-1,-1), "TOP"),
]))
story.append(mt3)
story.append(hr())

# ── 10. HEART & PERICARDIUM ──────────────────────────────────────────────────
story.append(section_header("10. Heart & Pericardium"))
story.append(Spacer(1, 0.3*cm))

story.append(Paragraph("Pericardium", h2))
story.append(Paragraph(
    "The pericardium is a fibroserous sac surrounding the heart and roots of the great vessels. It has two "
    "components: the outer <b>fibrous pericardium</b> (tough connective tissue; defines middle mediastinum "
    "boundaries) and the inner <b>serous pericardium</b>. The serous pericardium has two parts:", body))
story.append(info_box("Serous Pericardium", [
    "Parietal layer — lines inner surface of fibrous pericardium",
    "Visceral layer (epicardium) — adheres to heart surface",
    "Pericardial cavity — potential space between layers containing a thin film of fluid for lubrication",
    "Transverse pericardial sinus — behind great arteries, in front of superior vena cava",
    "Oblique pericardial sinus — posterior recess behind left atrium",
]))

story.append(Paragraph("Cardiac Orientation", h2))
story.append(Paragraph(
    "The heart has the shape of a pyramid resting on one side. The apex projects <b>forward, downward, and to "
    "the left</b> (5th intercostal space, midclavicular line). The base faces posteriorly and consists mainly "
    "of the left atrium.", body))
story.append(Paragraph("Surfaces of the heart:", h3))
surfaces = [
    ("Anterior (sternocostal) surface", "Mainly right ventricle"),
    ("Diaphragmatic (inferior) surface", "Mainly left ventricle + small part of right ventricle; rests on diaphragm"),
    ("Right pulmonary surface",          "Right atrium"),
    ("Left pulmonary surface",           "Left ventricle; forms cardiac impression on left lung"),
    ("Base (posterior surface)",         "Left atrium + small part of right atrium; receives pulmonary veins"),
]
story.append(two_col_table(surfaces, headers=["Surface", "Composition"]))
story.append(Spacer(1, 0.3*cm))
story.append(clinical_box(
    "<b>Cardiac tamponade:</b> Rapid accumulation of pericardial fluid compresses the heart within the "
    "non-distensible fibrous pericardium, causing biventricular failure. Classic signs: hypotension, muffled "
    "heart sounds, raised JVP (Beck's triad). Treatment: pericardiocentesis. "
    "<b>Constrictive pericarditis</b> causes chronic scarring and calcification, restricting diastolic filling. "
    "Kussmaul's sign (rise in JVP with inspiration) is characteristic."
))
story.append(hr())

# ── 11. CLINICAL CORRELATIONS ────────────────────────────────────────────────
story.append(section_header("11. Clinical Correlations"))
story.append(Spacer(1, 0.3*cm))

clinical_items = [
    ("Pneumothorax",
     "Air entering the pleural cavity collapses the lung. The costodiaphragmatic recess is checked on CXR for "
     "blunting (suggesting effusion) or hyperlucency (suggesting pneumothorax). Tension pneumothorax shifts the "
     "mediastinum away from the affected side."),
    ("Pleural Effusion",
     "Fluid collects in the costodiaphragmatic recess. Thoracocentesis is performed in the 8th–9th intercostal "
     "space in the midaxillary line, inserting the needle over the superior border of the lower rib to avoid "
     "neurovascular bundle."),
    ("Rib Fractures",
     "First rib fractures indicate severe trauma and are associated with subclavian vessel and brachial plexus "
     "injury. Flail chest results from multiple segmental rib fractures causing paradoxical movement."),
    ("Sternal Angle (Angle of Louis)",
     "Marks: second costal cartilage, T4/T5 disc level, beginning/end of aortic arch, tracheal bifurcation "
     "(carina), start of superior vena cava, division of mediastinum into superior and inferior parts, "
     "and the level where the thoracic duct crosses midline."),
    ("Diaphragmatic Hernia",
     "Herniation through the pleuroperitoneal canal (foramen of Bochdalek) or retrosternal gap (foramen of "
     "Morgagni) allows abdominal organs to enter the thoracic cavity. Congenital Bochdalek hernias typically "
     "occur on the left (90%) and present at birth with respiratory distress."),
    ("Superior Vena Cava (SVC) Syndrome",
     "Compression of the SVC in the superior mediastinum (most commonly by lung malignancy or lymphoma) causes "
     "facial oedema, arm swelling, and dilated neck veins with no respiratory variation."),
]

for title_c, desc_c in clinical_items:
    story.append(Paragraph(title_c, h2))
    story.append(Paragraph(desc_c, body))

story.append(hr())

# ── 12. SUMMARY TABLES ───────────────────────────────────────────────────────
story.append(section_header("12. Summary Tables"))
story.append(Spacer(1, 0.3*cm))

story.append(Paragraph("Breathing Mechanics", h2))
breath_data = [
    ["Inspiration",
     "Diaphragm contracts (flattens) — increases vertical dimension\n"
     "External intercostals elevate ribs — increases AP and lateral dimensions\n"
     "Intrathoracic pressure drops → air flows in"],
    ["Expiration (quiet)",
     "Passive recoil of lungs and thoracic wall\n"
     "Diaphragm relaxes and rises\n"
     "Ribs depress under gravity"],
    ["Forced expiration",
     "Internal intercostals depress ribs\n"
     "Abdominal muscles compress abdominal contents, pushing diaphragm up"],
]
story.append(two_col_table(breath_data, headers=["Phase", "Mechanism"]))
story.append(Spacer(1, 0.3*cm))

story.append(Paragraph("Key Vertebral Levels in the Thorax", h2))
level_data = [
    ["T1",   "Superior thoracic aperture; head of rib I"],
    ["T4/T5","Sternal angle; tracheal bifurcation (carina); aortic arch begins/ends; thoracic duct crosses midline"],
    ["T8",   "Caval opening in diaphragm; inferior vena cava passes through"],
    ["T10",  "Oesophageal hiatus; oesophagus + vagus nerves enter abdomen"],
    ["T12",  "Aortic hiatus; aorta + thoracic duct; inferior extent of pleural cavity"],
]
story.append(two_col_table(level_data, headers=["Level", "Key Structure / Landmark"]))
story.append(Spacer(1, 0.3*cm))

story.append(Paragraph("Comparison: Right vs Left Lung", h2))
lung_comp = [
    ["Weight",       "Heavier (~620 g)",              "Lighter (~560 g)"],
    ["Lobes",        "3 (sup, mid, inf)",             "2 (sup, inf)"],
    ["Fissures",     "Oblique + horizontal",          "Oblique only"],
    ["Hilum",        "Slightly lower",                "Slightly higher"],
    ["Special features", "—",                         "Cardiac notch; lingula; more oblique fissure"],
    ["Medial relations", "IVC, SVC, azygos, oesophagus", "Aortic arch, descending aorta, left subclavian"],
]
story.append(two_col_table(lung_comp, headers=["Feature", "Right Lung", "Left Lung"],
    col_ratios=[doc.width*0.25, doc.width*0.375, doc.width*0.375]))
story.append(Spacer(1, 0.5*cm))

# ── Footer note ───────────────────────────────────────────────────────────────
story.append(HRFlowable(width="100%", thickness=1, color=MED_BLUE, spaceAfter=6, spaceBefore=8))
story.append(Paragraph(
    "<i>Source: Gray's Anatomy for Students (9th ed.) | Generated by Orris AI | July 2026</i>",
    ParagraphStyle("Footer", fontSize=8, textColor=colors.HexColor("#777777"),
                   alignment=TA_CENTER, fontName="Helvetica-Oblique")))

# ── BUILD ─────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF created: {OUTPUT}")
Running Command

cd /home/daytona/workspace/thorax-anatomy && python generate_pdf.py

Running Command

ls -lh /home/daytona/workspace/thorax-anatomy/Thorax_Anatomy.pdf

Your PDF is ready. Here is the download link:

Thorax Anatomy

PDF Document · PDF


What's inside the PDF (12 sections, sourced from Gray's Anatomy for Students):
SectionContent
1. OverviewGeneral description, three thoracic compartments
2. Thoracic WallRegions, boundaries, structural composition
3. Skeletal FrameworkThoracic vertebrae, rib classification (true/false/floating), sternum parts
4. MusclesExternal/internal/innermost intercostals, serratus posterior muscles with attachments and functions
5. Neurovascular SupplyIntercostal arteries (aorta + internal thoracic), intercostal nerves, dermatomes T2-T12, sympathetic trunk
6. DiaphragmThree openings (T8/T10/T12) and their contents, phrenic nerve (C3,4,5), blood supply
7. Pleural CavitiesParietal/visceral pleura parts, inferior pleural extent (MCL/MAL/vertebral), costodiaphragmatic/costomediastinal recesses
8. LungsRight (3 lobes) vs left (2 lobes), hilum structures, bronchopulmonary segments, medial surface relations
9. MediastinumAll 4 subdivisions with boundaries and key contents
10. Heart & PericardiumFibrous/serous pericardium, cardiac orientation, surfaces, cardiac tamponade
11. Clinical CorrelationsPneumothorax, pleural effusion, rib fractures, sternal angle landmarks, diaphragmatic hernia, SVC syndrome
12. Summary TablesBreathing mechanics, key vertebral levels, right vs left lung comparison
This is a shared conversation. Sign in to Orris to start your own chat.