Explain about descending tract

Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Finding Sources
Reading File
Finding Sources
Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Reading File
Loading Image
Loading Image
Loading Image
I now have comprehensive content from multiple authoritative textbooks. Let me compile the full explanation.

Descending Tracts of the Spinal Cord

Descending tracts carry motor commands from the brain downward to the spinal cord (and brainstem) to control voluntary movement, posture, balance, and autonomic function. They are broadly divided into two functional systems: the lateral pathways (for fine voluntary movement of distal limbs) and the ventromedial pathways (for posture and axial control).

Overview

Summary of major descending motor tracts and their origins
The motor cortex sends signals both directly to the spinal cord (via the corticospinal tract) and indirectly through brainstem relay nuclei (red nucleus, reticular formation, vestibular nuclei, and superior colliculus). All of these eventually converge on the lower motor neuron (LMN) in the spinal cord's ventral horn, which is the final common pathway to skeletal muscle.

1. Lateral Pathways

These control fine, skilled movements of the distal muscles - especially the arms, hands, and fingers.

A. Corticospinal Tract (Pyramidal Tract) - Most Important

This is the most clinically important descending motor pathway in the nervous system. It controls voluntary movement of the extremities.
Origin:
  • Over 50% of fibers arise from the primary motor cortex (Brodmann's area 4, precentral gyrus)
  • Remaining fibers from the premotor cortex (area 6), supplementary motor area (SMA), and parietal lobe (areas 3, 1, 2, 5, and 7)
  • Neurons are located in cortical layer V (lamina V); about 3% are giant Betz cells - the largest neurons in the human nervous system
Course:
  1. Fibers collect into the corona radiata (cerebral white matter)
  2. Pass through the posterior limb of the internal capsule (face most anterior, leg most posterior - somatotopic arrangement)
  3. Descend through the cerebral peduncles (middle third of basis pedunculi) in the midbrain
  4. Pass through the scattered fascicles of the ventral pons
  5. Collect into the medullary pyramids on the ventral surface of the medulla (hence "pyramidal tract")
  6. At the cervicomedullary junction, ~85% decussate at the pyramidal decussation and descend as the lateral corticospinal tract in the lateral white matter columns
  7. The remaining ~15% do NOT decussate and descend as the anterior (ventral) corticospinal tract
Termination:
  • Lateral CST axons synapse onto LMNs in the dorsolateral ventral horn and onto spinal interneurons, controlling distal flexor muscles
  • Many fibers in primates synapse directly on alpha motor neurons (monosynaptic connection) - key for precise fine motor control
Lateral corticospinal tract pathway from motor cortex to skeletal muscle
Corticobulbar tract: Fibers that project from cortex to brainstem motor nuclei (cranial nerve nuclei) rather than the spinal cord. These control the muscles of the face, jaw, tongue, and throat.
Function: Voluntary, skilled, fine movements of contralateral limbs and body.
Somatotopic organization in the lateral CST:
  • Upper extremity fibers are medial
  • Lower extremity fibers are lateral

B. Rubrospinal Tract

Origin: Red nucleus in the midbrain tegmentum. Input to the red nucleus comes from the same frontal cortex regions that contribute to the CST (an indirect "corticorubrospinal" pathway).
Course: Axons decussate immediately in the pons and descend in the lateral column of the spinal cord, parallel to and just anterior to the lateral CST.
Function: Controls fine movements of the arms and fingers. In non-primate mammals this is a major motor tract. In humans, due to primate evolution, this pathway is largely replaced by the direct CST, making it less significant clinically.

2. Ventromedial Pathways

These four tracts originate in the brainstem and control axial and proximal muscles for posture, balance, and reflex movements. They project to the ventromedial spinal gray matter.
Vestibulospinal and tectospinal tracts - ventromedial pathways

A. Vestibulospinal Tracts

Origin: Vestibular nuclei in the medulla (which receive input from CN VIII/vestibular labyrinth).
Two components:
  • Medial vestibulospinal tract: Projects bilaterally down the spinal cord; activates cervical circuits controlling neck and back muscles to stabilize the head
  • Lateral vestibulospinal tract: Projects ipsilaterally down to the lumbar spinal cord; facilitates extensor motor neurons of the legs to maintain upright posture against gravity
Function: Keeps head stable, maintains balance and upright posture. Facilitates extensor tone.

B. Tectospinal Tract

Origin: Superior colliculus of the midbrain (which receives input from the retina, visual/auditory/somatosensory cortex).
Course: Fibers decussate shortly after leaving the superior colliculus and descend to the cervical spinal cord only.
Function: Coordinates head and neck movements in response to visual, auditory, and somatosensory stimuli (e.g., reflexive turning of the head toward a sudden sound or flash of light).

C. Pontine (Medial) Reticulospinal Tract

Origin: Reticular formation of the pons.
Course: Descends in the anterior (ventral) funiculus, ipsilaterally.
Function: Facilitates antigravity (extensor) stretch reflexes; helps maintain standing posture by resisting the effects of gravity.

D. Medullary (Lateral) Reticulospinal Tract

Origin: Reticular formation of the medulla.
Course: Descends bilaterally in the lateral funiculus.
Function: Has the opposite effect to the pontine reticulospinal tract - it inhibits the antigravity muscles by liberating them from stretch reflex control. A fine balance between the two reticulospinal tracts is required during movement.

Summary Table

TractOriginDecussationLocation in CordControls
Lateral corticospinalPrimary motor cortex (area 4)Pyramidal decussation (medulla) - ~85%Lateral columnFine distal voluntary movement (contralateral)
Anterior corticospinalPrimary motor cortexNone (crosses at segmental level)Anterior columnAxial/proximal muscles (bilateral)
RubrospinalRed nucleus (midbrain)Immediately in ponsLateral columnFine arm/hand movements (contralateral)
Vestibulospinal (lateral)Lateral vestibular nucleusNone (ipsilateral)Anterior columnExtensor tone in legs, balance
Vestibulospinal (medial)Medial vestibular nucleusBilateralAnterior columnHead/neck posture
TectospinalSuperior colliculus (midbrain)Dorsal tegmental decussationAnterior columnHead-turning reflexes (cervical only)
Pontine reticulospinalPontine reticular formationNone (ipsilateral)Anterior columnFacilitates extensors (antigravity)
Medullary reticulospinalMedullary reticular formationBilateralLateral/anteriorInhibits antigravity stretch reflexes

Upper vs. Lower Motor Neuron Lesions

Damage to descending tracts produces upper motor neuron (UMN) signs, in contrast to LMN lesions:
FeatureUMN LesionLMN Lesion
WeaknessContralateral (CST lesion above decussation)Ipsilateral
ToneSpasticity (increased)Flaccidity (decreased)
ReflexesHyperreflexiaHyporeflexia / areflexia
Babinski signPresent (upgoing toe)Absent
AtrophyMild (disuse)Significant (denervation)
FasciculationsAbsentPresent
The Babinski sign (upward flexion of the big toe on plantar stimulation) is a hallmark of CST damage. Normal infants also exhibit it because their descending motor tracts have not yet fully myelinated.
Spasticity after CST lesions is thought to be caused not by CST damage itself, but by co-damage to descending inhibitory pathways that travel closely alongside the CST.

Sources:
  • Neuroanatomy through Clinical Cases, 3rd Edition - Lateral Corticospinal Tract section
  • Neuroscience: Exploring the Brain, 5th Edition - Descending Spinal Tracts chapter
  • Eric Kandel, Principles of Neural Science, 6th Edition - Descending Motor Commands chapter
  • Gray's Anatomy for Students - Lateral and Medial Motor Systems

Create a quick reference PDF comparing UMN vs LMN signs with clinical examples

Reading File
Reading File
Running Command

ls /home/daytona/workspace/ 2>/dev/null || echo "workspace empty"

Writing File

~/umn-lmn-ref/create_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, Table, TableStyle,
    HRFlowable, KeepTogether
)
from reportlab.lib.colors import HexColor
import os

output_path = "/home/daytona/workspace/umn-lmn-ref/UMN_vs_LMN_Quick_Reference.pdf"
os.makedirs("/home/daytona/workspace/umn-lmn-ref", exist_ok=True)

# ── Colour palette ──────────────────────────────────────────────────────────
DARK_BLUE   = HexColor("#1A3A5C")   # header / title
MID_BLUE    = HexColor("#2E6DA4")   # UMN column header
RED_BROWN   = HexColor("#C0392B")   # LMN column header
LIGHT_BLUE  = HexColor("#D6E8F8")   # UMN row shading (light)
LIGHT_RED   = HexColor("#FDECEA")   # LMN row shading (light)
PALE_GRAY   = HexColor("#F4F6F8")   # alternating row
DARK_GRAY   = HexColor("#2C3E50")   # body text
GOLD        = HexColor("#D4A017")   # accent / rule
WHITE       = colors.white
BLACK       = colors.black

doc = SimpleDocTemplate(
    output_path,
    pagesize=A4,
    rightMargin=1.8*cm, leftMargin=1.8*cm,
    topMargin=1.8*cm, bottomMargin=1.8*cm,
    title="UMN vs LMN Quick Reference",
    author="Orris Medical"
)

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

styles = getSampleStyleSheet()

def sty(name, **kw):
    base = styles.get(name, styles["Normal"])
    return ParagraphStyle(name + "_custom_" + str(id(kw)), parent=base, **kw)

title_sty = sty("Title",
    fontSize=22, textColor=WHITE, alignment=TA_CENTER,
    fontName="Helvetica-Bold", spaceAfter=0, spaceBefore=0)

subtitle_sty = sty("Normal",
    fontSize=10, textColor=HexColor("#BDD7EE"), alignment=TA_CENTER,
    fontName="Helvetica-Oblique", spaceAfter=0)

section_sty = sty("Heading2",
    fontSize=13, textColor=DARK_BLUE, fontName="Helvetica-Bold",
    spaceBefore=10, spaceAfter=4, borderPad=0)

body_sty = sty("Normal",
    fontSize=9, textColor=DARK_GRAY, fontName="Helvetica",
    leading=13, spaceAfter=3)

bold_body = sty("Normal",
    fontSize=9, textColor=DARK_GRAY, fontName="Helvetica-Bold", leading=13)

col_header_sty = sty("Normal",
    fontSize=10, textColor=WHITE, fontName="Helvetica-Bold",
    alignment=TA_CENTER, leading=14)

cell_sty = sty("Normal",
    fontSize=8.5, textColor=DARK_GRAY, fontName="Helvetica",
    leading=12, alignment=TA_LEFT)

cell_bold = sty("Normal",
    fontSize=8.5, textColor=DARK_GRAY, fontName="Helvetica-Bold",
    leading=12, alignment=TA_LEFT)

umncell = sty("Normal",
    fontSize=8.5, textColor=HexColor("#1A3A5C"), fontName="Helvetica",
    leading=12, alignment=TA_LEFT)

lmncell = sty("Normal",
    fontSize=8.5, textColor=HexColor("#7B1515"), fontName="Helvetica",
    leading=12, alignment=TA_LEFT)

note_sty = sty("Normal",
    fontSize=8, textColor=HexColor("#5D6D7E"), fontName="Helvetica-Oblique",
    leading=11, spaceAfter=2)

example_sty = sty("Normal",
    fontSize=8, textColor=HexColor("#196F3D"), fontName="Helvetica-Bold",
    leading=11)

# ── Helper: coloured title banner ────────────────────────────────────────────
def banner(story):
    banner_data = [[Paragraph("UMN vs LMN", title_sty)],
                   [Paragraph("Upper Motor Neuron vs Lower Motor Neuron — Quick Reference", subtitle_sty)]]
    banner_tbl = Table(banner_data, colWidths=[CONTENT_W])
    banner_tbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), DARK_BLUE),
        ("TOPPADDING",  (0,0), (-1,-1), 10),
        ("BOTTOMPADDING",(0,0),(-1,-1), 10),
        ("LEFTPADDING", (0,0), (-1,-1), 12),
        ("RIGHTPADDING",(0,0), (-1,-1), 12),
        ("ROUNDEDCORNERS", (0,0),(-1,-1), 6),
    ]))
    story.append(banner_tbl)
    story.append(Spacer(1, 10))

# ── Main comparison table ────────────────────────────────────────────────────
def main_table(story):
    story.append(Paragraph("Clinical Signs at a Glance", section_sty))
    story.append(HRFlowable(width=CONTENT_W, thickness=1.5, color=GOLD, spaceAfter=6))

    col_w = [CONTENT_W*0.26, CONTENT_W*0.37, CONTENT_W*0.37]

    rows = [
        # Header
        [
            Paragraph("Feature", col_header_sty),
            Paragraph("UMN Lesion", col_header_sty),
            Paragraph("LMN Lesion", col_header_sty),
        ],
        [
            Paragraph("Tone", cell_bold),
            Paragraph("Spasticity (clasp-knife)\nIncreased tone in\nflexors (arm) / extensors (leg)", umncell),
            Paragraph("Flaccidity\nDecreased / absent\nmuscle tone", lmncell),
        ],
        [
            Paragraph("Power", cell_bold),
            Paragraph("Weakness (contralateral\nto lesion if above decussation)", umncell),
            Paragraph("Weakness / paralysis\n(ipsilateral, segmental\nor peripheral distribution)", lmncell),
        ],
        [
            Paragraph("Deep Tendon\nReflexes", cell_bold),
            Paragraph("Hyperreflexia\nExaggerated DTRs\n(e.g. brisk knee jerk)", umncell),
            Paragraph("Hyporeflexia or\nAreflexia\n(loss of knee / ankle jerk)", lmncell),
        ],
        [
            Paragraph("Plantar\nResponse", cell_bold),
            Paragraph("Extensor (Babinski +ve)\nBig toe goes UP,\nfanning of other toes", umncell),
            Paragraph("Flexor (normal)\nAll toes curl DOWN\n(or no response)", lmncell),
        ],
        [
            Paragraph("Clonus", cell_bold),
            Paragraph("Present\n(sustained rhythmic\noscillation at ankle/knee)", umncell),
            Paragraph("Absent", lmncell),
        ],
        [
            Paragraph("Muscle\nAtrophy", cell_bold),
            Paragraph("Mild (disuse atrophy only)\noccurs late", umncell),
            Paragraph("Significant & early\nDenervation atrophy", lmncell),
        ],
        [
            Paragraph("Fasciculations", cell_bold),
            Paragraph("Absent", umncell),
            Paragraph("Present\n(spontaneous visible\ntwitching of muscle bundles)", lmncell),
        ],
        [
            Paragraph("Fibrillations\n(EMG)", cell_bold),
            Paragraph("Absent", umncell),
            Paragraph("Present on EMG\n(denervation potential)", lmncell),
        ],
        [
            Paragraph("Distribution\nof Weakness", cell_bold),
            Paragraph("Pyramidal pattern:\nExtensors weak in arm\nFlexors weak in leg\n(whole limb / hemibody)", umncell),
            Paragraph("Focal / segmental:\nSingle muscle group or\nperipheral nerve territory", lmncell),
        ],
        [
            Paragraph("Wasting", cell_bold),
            Paragraph("Absent initially;\nMild later (disuse)", umncell),
            Paragraph("Severe wasting\nof affected muscles", lmncell),
        ],
        [
            Paragraph("Coordination", cell_bold),
            Paragraph("May be impaired due\nto weakness", umncell),
            Paragraph("May be impaired due\nto weakness", lmncell),
        ],
    ]

    tbl = Table(rows, colWidths=col_w, repeatRows=1)

    style_cmds = [
        # Header row
        ("BACKGROUND", (0,0), (0,0), DARK_BLUE),
        ("BACKGROUND", (1,0), (1,0), MID_BLUE),
        ("BACKGROUND", (2,0), (2,0), RED_BROWN),
        ("TEXTCOLOR",  (0,0), (-1,0), WHITE),
        ("FONTNAME",   (0,0), (-1,0), "Helvetica-Bold"),
        ("FONTSIZE",   (0,0), (-1,0), 10),
        ("ALIGN",      (0,0), (-1,0), "CENTER"),
        ("VALIGN",     (0,0), (-1,0), "MIDDLE"),
        ("TOPPADDING", (0,0), (-1,0), 8),
        ("BOTTOMPADDING",(0,0),(-1,0),8),
        # Feature column
        ("BACKGROUND", (0,1), (0,-1), HexColor("#EAF0F7")),
        ("FONTNAME",   (0,1), (0,-1), "Helvetica-Bold"),
        # Alternating UMN / LMN shading
        ("GRID",       (0,0), (-1,-1), 0.4, HexColor("#BDC3C7")),
        ("ROWBACKGROUNDS", (1,1), (1,-1), [LIGHT_BLUE, WHITE]),
        ("ROWBACKGROUNDS", (2,1), (2,-1), [LIGHT_RED, HexColor("#FFF8F8")]),
        ("VALIGN",     (0,0), (-1,-1), "TOP"),
        ("TOPPADDING", (0,1), (-1,-1), 5),
        ("BOTTOMPADDING",(0,1),(-1,-1),5),
        ("LEFTPADDING",(0,0), (-1,-1), 6),
        ("RIGHTPADDING",(0,0),(-1,-1), 6),
        ("ROUNDEDCORNERS",(0,0),(-1,-1), 3),
    ]
    # Alternate full row background for better readability
    for i in range(1, len(rows)):
        bg = PALE_GRAY if i % 2 == 0 else WHITE
        style_cmds.append(("BACKGROUND", (0,i), (0,i), HexColor("#EAF0F7")))
        style_cmds.append(("BACKGROUND", (1,i), (1,i), LIGHT_BLUE if i % 2 == 1 else WHITE))
        style_cmds.append(("BACKGROUND", (2,i), (2,i), LIGHT_RED if i % 2 == 1 else HexColor("#FFF8F8")))

    tbl.setStyle(TableStyle(style_cmds))
    story.append(tbl)
    story.append(Spacer(1, 12))

# ── Lesion localisation table ────────────────────────────────────────────────
def location_table(story):
    story.append(Paragraph("Lesion Localisation", section_sty))
    story.append(HRFlowable(width=CONTENT_W, thickness=1.5, color=GOLD, spaceAfter=6))

    col_w = [CONTENT_W*0.30, CONTENT_W*0.22, CONTENT_W*0.48]

    rows = [
        [
            Paragraph("Location of Lesion", col_header_sty),
            Paragraph("Type", col_header_sty),
            Paragraph("Signs Produced", col_header_sty),
        ],
        [
            Paragraph("Motor cortex / corona radiata\n(e.g. stroke)", cell_bold),
            Paragraph("UMN", umncell),
            Paragraph("Contralateral hemiplegia (arm > leg usually)\nFace spared if below facial motor area", cell_sty),
        ],
        [
            Paragraph("Internal capsule\n(e.g. lacunar stroke)", cell_bold),
            Paragraph("UMN", umncell),
            Paragraph("Pure motor hemiplegia: face + arm + leg\n(all on contralateral side)", cell_sty),
        ],
        [
            Paragraph("Brainstem\n(e.g. Wallenberg, Weber)", cell_bold),
            Paragraph("UMN + CN", umncell),
            Paragraph("Crossed signs: ipsilateral CN palsy +\ncontralateral UMN limb signs", cell_sty),
        ],
        [
            Paragraph("Spinal cord\n(e.g. MS, cord compression)", cell_bold),
            Paragraph("UMN below lesion", umncell),
            Paragraph("Bilateral spastic paraplegia / quadriplegia;\nLevel can be determined by sensory level", cell_sty),
        ],
        [
            Paragraph("Anterior horn cell\n(e.g. polio, ALS*)", cell_bold),
            Paragraph("LMN", lmncell),
            Paragraph("Focal wasting + fasciculations; areflexia\nNo sensory loss (pure motor)", cell_sty),
        ],
        [
            Paragraph("Nerve root\n(e.g. disc prolapse)", cell_bold),
            Paragraph("LMN", lmncell),
            Paragraph("Dermatomal sensory loss + myotomal weakness\nReduced reflex in that segment", cell_sty),
        ],
        [
            Paragraph("Peripheral nerve\n(e.g. carpal tunnel, GBS)", cell_bold),
            Paragraph("LMN", lmncell),
            Paragraph("Weakness + wasting in nerve territory\n+ sensory loss; areflexia", cell_sty),
        ],
        [
            Paragraph("Neuromuscular junction\n(e.g. myasthenia gravis)", cell_bold),
            Paragraph("LMN (NMJ)", lmncell),
            Paragraph("Fatigable weakness; no wasting, no sensory\nloss, normal reflexes initially", cell_sty),
        ],
    ]

    tbl = Table(rows, colWidths=col_w, repeatRows=1)
    style_cmds = [
        ("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
        ("TEXTCOLOR",  (0,0), (-1,0), WHITE),
        ("FONTNAME",   (0,0), (-1,0), "Helvetica-Bold"),
        ("FONTSIZE",   (0,0), (-1,0), 9.5),
        ("ALIGN",      (0,0), (-1,0), "CENTER"),
        ("VALIGN",     (0,0), (-1,-1), "TOP"),
        ("GRID",       (0,0), (-1,-1), 0.4, HexColor("#BDC3C7")),
        ("TOPPADDING", (0,0), (-1,-1), 5),
        ("BOTTOMPADDING",(0,0),(-1,-1),5),
        ("LEFTPADDING",(0,0), (-1,-1), 6),
        ("RIGHTPADDING",(0,0),(-1,-1), 6),
    ]
    for i in range(1, len(rows)):
        bg = PALE_GRAY if i % 2 == 0 else WHITE
        style_cmds.append(("BACKGROUND", (0,i), (-1,i), bg))

    tbl.setStyle(TableStyle(style_cmds))
    story.append(tbl)
    story.append(Spacer(1, 12))

# ── Clinical examples boxes ──────────────────────────────────────────────────
def clinical_examples(story):
    story.append(Paragraph("Clinical Examples", section_sty))
    story.append(HRFlowable(width=CONTENT_W, thickness=1.5, color=GOLD, spaceAfter=6))

    half_w = (CONTENT_W - 6) / 2

    umn_cases = [
        ("<b>Stroke (MCA territory)</b>",
         "Sudden contralateral hemiplegia with face + arm > leg weakness. Brisk reflexes after initial flaccid phase. Babinski positive. Hemisensory loss if parietal cortex involved."),
        ("<b>Multiple Sclerosis</b>",
         "Young adult with relapsing-remitting spastic paraparesis. Lhermitte's sign (electric shock on neck flexion). Hyperreflexia, clonus, bilateral Babinski. Bladder involvement."),
        ("<b>Cervical Spondylotic Myelopathy</b>",
         "Elderly patient with stiff spastic gait, clumsy hands, hyperreflexia. UMN signs in legs, may show LMN signs at the level of compression (mixed picture)."),
        ("<b>Motor Neuron Disease (ALS)</b>",
         "Mixed UMN + LMN: hyperreflexia AND fasciculations present in the SAME muscle. Pathognomonic of ALS. Bulbar palsy also common."),
    ]

    lmn_cases = [
        ("<b>L4/L5 Disc Prolapse</b>",
         "Unilateral foot drop with L5 dermatomal sensory loss. Absent ankle jerk (S1 involvement if L5/S1 level). Straight leg raise test positive. Wasting of tibialis anterior."),
        ("<b>Guillain-Barre Syndrome</b>",
         "Ascending flaccid paralysis, areflexia, and glove-stocking sensory loss following a viral illness. Autonomic instability. Nerve conduction shows demyelination."),
        ("<b>Bell's Palsy (CN VII)</b>",
         "Unilateral complete facial weakness (upper + lower face involved - distinguishes from UMN cause). Loss of corneal reflex. Hyperacusis, altered taste."),
        ("<b>Carpal Tunnel Syndrome</b>",
         "Thenar wasting + weakness of thumb abduction. Sensory loss in lateral 3.5 fingers. Positive Phalen's and Tinel's sign. Worse at night."),
    ]

    def case_cell(cases, bg_color, header_text, header_color):
        inner_rows = [[Paragraph(header_text, ParagraphStyle("ch", fontSize=9.5,
            textColor=WHITE, fontName="Helvetica-Bold", alignment=TA_CENTER))]]
        for title, desc in cases:
            inner_rows.append([Paragraph(
                f'<font color="#1A3A5C"><b>{title.strip("<b>").strip("</b>")}</b></font><br/>'
                f'<font color="#2C3E50" size="7.5">{desc}</font>',
                ParagraphStyle("cc", fontSize=8, leading=11, fontName="Helvetica",
                               spaceAfter=2))])
        t = Table(inner_rows, colWidths=[half_w])
        t.setStyle(TableStyle([
            ("BACKGROUND", (0,0), (-1,0), header_color),
            ("BACKGROUND", (0,1), (-1,-1), bg_color),
            ("TOPPADDING",  (0,0), (-1,-1), 5),
            ("BOTTOMPADDING",(0,0),(-1,-1),5),
            ("LEFTPADDING", (0,0), (-1,-1), 7),
            ("RIGHTPADDING",(0,0), (-1,-1), 7),
            ("GRID",        (0,0), (-1,-1), 0.3, HexColor("#D5D8DC")),
        ]))
        return t

    umn_tbl = case_cell(umn_cases, LIGHT_BLUE, "UMN Clinical Examples", MID_BLUE)
    lmn_tbl = case_cell(lmn_cases, LIGHT_RED, "LMN Clinical Examples", RED_BROWN)

    combined = Table([[umn_tbl, lmn_tbl]], colWidths=[half_w + 3, half_w + 3])
    combined.setStyle(TableStyle([
        ("VALIGN", (0,0), (-1,-1), "TOP"),
        ("LEFTPADDING",  (0,0), (-1,-1), 0),
        ("RIGHTPADDING", (0,0), (-1,-1), 0),
        ("TOPPADDING",   (0,0), (-1,-1), 0),
        ("BOTTOMPADDING",(0,0), (-1,-1), 0),
    ]))
    story.append(combined)
    story.append(Spacer(1, 10))

# ── Key mnemonics box ────────────────────────────────────────────────────────
def mnemonics(story):
    story.append(Paragraph("Memory Aids", section_sty))
    story.append(HRFlowable(width=CONTENT_W, thickness=1.5, color=GOLD, spaceAfter=6))

    mnem_data = [
        [
            Paragraph("<b>UMN mnemonic: \"USHHHH\"</b><br/>"
                      "<font size='8'><b>U</b>pper motor = <b>S</b>pasticity, <b>H</b>yperreflexia, <b>H</b>ypertonia, '\"<b>H</b>\" sign (Babinski), <b>H</b>emiplegia pattern</font>",
                      ParagraphStyle("m1", fontSize=8.5, fontName="Helvetica", leading=13,
                                     textColor=DARK_GRAY)),
            Paragraph("<b>LMN mnemonic: \"FLAWS\"</b><br/>"
                      "<font size='8'><b>F</b>laccidity, <b>L</b>oss of reflexes (areflexia), <b>A</b>trophy, <b>W</b>asting, <b>F</b>asciculations</font>",
                      ParagraphStyle("m2", fontSize=8.5, fontName="Helvetica", leading=13,
                                     textColor=DARK_GRAY)),
        ],
        [
            Paragraph("<b>Babinski key rule:</b> <font size='8'>Present in UMN lesion AND normal infants (immature tracts). Absent in adults = normal.</font>",
                      ParagraphStyle("m3", fontSize=8.5, fontName="Helvetica", leading=13,
                                     textColor=DARK_GRAY)),
            Paragraph("<b>ALS special rule:</b> <font size='8'>BOTH UMN + LMN signs in the same limb = ALS until proven otherwise. Fasciculations WITH hyperreflexia is pathognomonic.</font>",
                      ParagraphStyle("m4", fontSize=8.5, fontName="Helvetica", leading=13,
                                     textColor=DARK_GRAY)),
        ],
    ]
    mnem_tbl = Table(mnem_data, colWidths=[CONTENT_W/2, CONTENT_W/2])
    mnem_tbl.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), HexColor("#FDFEFE")),
        ("BOX",        (0,0), (-1,-1), 1, HexColor("#AEB6BF")),
        ("INNERGRID",  (0,0), (-1,-1), 0.4, HexColor("#D5D8DC")),
        ("TOPPADDING",  (0,0), (-1,-1), 7),
        ("BOTTOMPADDING",(0,0),(-1,-1),7),
        ("LEFTPADDING", (0,0), (-1,-1), 8),
        ("RIGHTPADDING",(0,0), (-1,-1), 8),
        ("VALIGN",     (0,0), (-1,-1), "TOP"),
    ]))
    story.append(mnem_tbl)
    story.append(Spacer(1, 10))

# ── Reflex arc reminder ──────────────────────────────────────────────────────
def reflex_table(story):
    story.append(Paragraph("Common Reflexes and Spinal Levels", section_sty))
    story.append(HRFlowable(width=CONTENT_W, thickness=1.5, color=GOLD, spaceAfter=6))

    col_w = [CONTENT_W*0.30, CONTENT_W*0.18, CONTENT_W*0.18, CONTENT_W*0.34]
    rows = [
        [Paragraph("Reflex", col_header_sty), Paragraph("Level", col_header_sty),
         Paragraph("Nerve", col_header_sty), Paragraph("Absent in LMN / Exaggerated in UMN", col_header_sty)],
        [Paragraph("Biceps jerk", cell_sty), Paragraph("C5-C6", cell_sty),
         Paragraph("Musculocutaneous", cell_sty), Paragraph("Absent: C5/C6 radiculopathy, brachial neuritis", cell_sty)],
        [Paragraph("Supinator jerk", cell_sty), Paragraph("C5-C6", cell_sty),
         Paragraph("Radial", cell_sty), Paragraph("Inversion in C5/6 lesion (finger flexion instead)", cell_sty)],
        [Paragraph("Triceps jerk", cell_sty), Paragraph("C7", cell_sty),
         Paragraph("Radial", cell_sty), Paragraph("Absent: C7 radiculopathy (posterior disc)", cell_sty)],
        [Paragraph("Knee jerk (patellar)", cell_sty), Paragraph("L3-L4", cell_sty),
         Paragraph("Femoral", cell_sty), Paragraph("Absent: femoral neuropathy, L4 disc prolapse", cell_sty)],
        [Paragraph("Ankle jerk", cell_sty), Paragraph("S1", cell_sty),
         Paragraph("Sciatic/tibial", cell_sty), Paragraph("Absent: S1 radiculopathy, peripheral neuropathy", cell_sty)],
        [Paragraph("Plantar (Babinski)", cell_sty), Paragraph("L5-S1", cell_sty),
         Paragraph("Sciatic", cell_sty), Paragraph("Extensor response = UMN sign (pathological in adults)", cell_sty)],
        [Paragraph("Abdominal reflexes", cell_sty), Paragraph("T8-T12", cell_sty),
         Paragraph("Intercostal", cell_sty), Paragraph("Absent early in UMN lesion (before hyperreflexia)", cell_sty)],
    ]
    tbl = Table(rows, colWidths=col_w, repeatRows=1)
    style_cmds = [
        ("BACKGROUND", (0,0), (-1,0), DARK_BLUE),
        ("TEXTCOLOR",  (0,0), (-1,0), WHITE),
        ("FONTNAME",   (0,0), (-1,0), "Helvetica-Bold"),
        ("GRID",       (0,0), (-1,-1), 0.4, HexColor("#BDC3C7")),
        ("VALIGN",     (0,0), (-1,-1), "TOP"),
        ("TOPPADDING", (0,0), (-1,-1), 4),
        ("BOTTOMPADDING",(0,0),(-1,-1),4),
        ("LEFTPADDING",(0,0), (-1,-1), 6),
        ("RIGHTPADDING",(0,0),(-1,-1), 6),
    ]
    for i in range(1, len(rows)):
        bg = PALE_GRAY if i % 2 == 0 else WHITE
        style_cmds.append(("BACKGROUND", (0,i), (-1,i), bg))
    tbl.setStyle(TableStyle(style_cmds))
    story.append(tbl)
    story.append(Spacer(1, 8))

# ── Footer note ──────────────────────────────────────────────────────────────
def footer_note(story):
    note = ("* ALS = Amyotrophic Lateral Sclerosis. Note: Acute UMN lesions (e.g. acute stroke, acute spinal cord injury) "
            "may initially present with FLACCIDITY and AREFLEXIA (spinal shock / cerebral shock) before the classic "
            "UMN pattern of spasticity and hyperreflexia develops over days to weeks.")
    story.append(Paragraph(note, ParagraphStyle("fn", fontSize=7.5, textColor=HexColor("#717D7E"),
        fontName="Helvetica-Oblique", leading=10, borderPad=4,
        borderColor=HexColor("#AEB6BF"), borderWidth=0.5,
        backColor=HexColor("#F8F9FA"))))
    story.append(Spacer(1, 4))
    story.append(Paragraph("Orris Medical Quick Reference | July 2026",
        ParagraphStyle("credit", fontSize=7, textColor=HexColor("#AEB6BF"),
            fontName="Helvetica", alignment=TA_CENTER)))

# ── Build ─────────────────────────────────────────────────────────────────────
story = []
banner(story)
main_table(story)
location_table(story)
clinical_examples(story)
mnemonics(story)
reflex_table(story)
footer_note(story)

doc.build(story)
print(f"PDF created: {output_path}")
Running Command

cd /home/daytona/workspace/umn-lmn-ref && python create_pdf.py 2>&1

Running Command

ls -lh /home/daytona/workspace/umn-lmn-ref/

Your quick reference PDF is ready. Here is what it contains:

Your PDF:

UMN vs LMN Quick Reference

PDF Document · PDF


What's inside (A4, colour-coded):

  1. Clinical Signs at a Glance - Side-by-side comparison table covering:
    • Tone, power, DTRs, plantar response, clonus, atrophy, fasciculations, fibrillations, distribution of weakness, wasting, and coordination
  2. Lesion Localisation Table - Maps 8 anatomical sites (motor cortex, internal capsule, brainstem, spinal cord, anterior horn, nerve root, peripheral nerve, NMJ) to their expected signs and classic diseases
  3. Clinical Examples - 4 UMN examples (stroke, MS, cervical myelopathy, ALS) and 4 LMN examples (disc prolapse, GBS, Bell's palsy, carpal tunnel) with key distinguishing features
  4. Memory Aids - "USHHHH" for UMN and "FLAWS" for LMN, plus the ALS rule and Babinski note
  5. Common Reflexes table - 8 reflexes with spinal levels, nerves, and what lesion causes absence or exaggeration
  6. Important caveat note at the bottom: Acute UMN lesions initially present with flaccidity and areflexia (spinal shock) before the classic UMN pattern develops - a common exam trap.

Make pdf of easy and quick revision for ascending tract and descending tract with comparison of both

Finding Sources
Finding Sources
Reading File
Reading File
Writing File

~/tracts-revision/build_pdf.py

"""
Ascending & Descending Tracts — Quick Revision PDF
ReportLab-based, A4, colour-coded, exam-ready
"""

import os
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_RIGHT
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether, PageBreak
)
from reportlab.lib.colors import HexColor

os.makedirs("/home/daytona/workspace/tracts-revision", exist_ok=True)
OUT = "/home/daytona/workspace/tracts-revision/Spinal_Tracts_Quick_Revision.pdf"

W, H = A4
MARGIN = 1.6*cm
CONTENT_W = W - 2*MARGIN

# ── Palette ──────────────────────────────────────────────────────────────────
C_DARK_BG   = HexColor("#0D2137")   # page header bg
C_ASC_HDR   = HexColor("#1A6B3A")   # ascending header / accent
C_DESC_HDR  = HexColor("#8B1A1A")   # descending header / accent
C_ASC_LIGHT = HexColor("#D4EDDA")   # ascending row bg
C_DESC_LIGHT= HexColor("#FADBD8")   # descending row bg
C_GOLD      = HexColor("#D4A017")   # rule / accent
C_BODY      = HexColor("#1C2833")   # normal text
C_GRAY      = HexColor("#6D7C8A")   # footnotes / labels
C_WHITE     = colors.white
C_PALE      = HexColor("#F4F6F8")
C_BLUE_HDR  = HexColor("#154360")   # comparison header
C_BLUE_LIGHT= HexColor("#D6EAF8")
C_ORANGE    = HexColor("#BA6714")
C_ORANGE_L  = HexColor("#FDEBD0")

doc = SimpleDocTemplate(OUT, pagesize=A4,
    rightMargin=MARGIN, leftMargin=MARGIN,
    topMargin=MARGIN, bottomMargin=MARGIN,
    title="Spinal Tracts Quick Revision",
    author="Orris Medical")

# ── Style factory ─────────────────────────────────────────────────────────────
def S(parent="Normal", **kw):
    base = getSampleStyleSheet().get(parent, getSampleStyleSheet()["Normal"])
    return ParagraphStyle("_" + str(id(kw)), parent=base, **kw)

T_TITLE   = S("Normal", fontSize=24, textColor=C_WHITE, fontName="Helvetica-Bold",
              alignment=TA_CENTER, leading=28)
T_SUB     = S("Normal", fontSize=10, textColor=HexColor("#A9CCE3"), fontName="Helvetica-Oblique",
              alignment=TA_CENTER, leading=14)
T_H1      = S("Normal", fontSize=13, textColor=C_DARK_BG, fontName="Helvetica-Bold",
              spaceBefore=8, spaceAfter=3, leading=16)
T_H2_ASC  = S("Normal", fontSize=11, textColor=C_WHITE, fontName="Helvetica-Bold",
              alignment=TA_CENTER, leading=14)
T_H2_DESC = S("Normal", fontSize=11, textColor=C_WHITE, fontName="Helvetica-Bold",
              alignment=TA_CENTER, leading=14)
T_CELL    = S("Normal", fontSize=8, textColor=C_BODY, fontName="Helvetica", leading=11)
T_CELLB   = S("Normal", fontSize=8, textColor=C_BODY, fontName="Helvetica-Bold", leading=11)
T_CHDR    = S("Normal", fontSize=9, textColor=C_WHITE, fontName="Helvetica-Bold",
              alignment=TA_CENTER, leading=12)
T_NOTE    = S("Normal", fontSize=7.5, textColor=C_GRAY, fontName="Helvetica-Oblique", leading=10)
T_FOOT    = S("Normal", fontSize=7, textColor=C_GRAY, fontName="Helvetica", alignment=TA_CENTER)
T_MNEM    = S("Normal", fontSize=8.5, textColor=C_BODY, fontName="Helvetica", leading=13)
T_MNEM_B  = S("Normal", fontSize=9, textColor=C_DARK_BG, fontName="Helvetica-Bold", leading=13)

def P(txt, style=T_CELL): return Paragraph(txt, style)
def HR(): return HRFlowable(width=CONTENT_W, thickness=1.2, color=C_GOLD, spaceAfter=5)
def SP(h=6): return Spacer(1, h)

# ── Table helper ──────────────────────────────────────────────────────────────
def make_table(rows, col_widths, style_cmds, repeat=1):
    t = Table(rows, colWidths=col_widths, repeatRows=repeat)
    t.setStyle(TableStyle(style_cmds))
    return t

BASE_STYLE = [
    ("GRID",         (0,0), (-1,-1), 0.4, HexColor("#BFC9CA")),
    ("VALIGN",       (0,0), (-1,-1), "TOP"),
    ("TOPPADDING",   (0,0), (-1,-1), 5),
    ("BOTTOMPADDING",(0,0), (-1,-1), 5),
    ("LEFTPADDING",  (0,0), (-1,-1), 6),
    ("RIGHTPADDING", (0,0), (-1,-1), 6),
]

# ═══════════════════════════════════════════════════════════════════════════════
# PAGE HEADER BANNER
# ═══════════════════════════════════════════════════════════════════════════════
def banner(story):
    data = [
        [P("Spinal Tracts — Quick Revision", T_TITLE)],
        [P("Ascending (Sensory) &amp; Descending (Motor) Tracts | Easy Reference for Exams", T_SUB)],
    ]
    t = Table(data, colWidths=[CONTENT_W])
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0), (-1,-1), C_DARK_BG),
        ("TOPPADDING",    (0,0), (-1,-1), 10),
        ("BOTTOMPADDING", (0,0), (-1,-1), 10),
        ("LEFTPADDING",   (0,0), (-1,-1), 14),
        ("RIGHTPADDING",  (0,0), (-1,-1), 14),
    ]))
    story += [t, SP(10)]

# ═══════════════════════════════════════════════════════════════════════════════
# SECTION 1 — ASCENDING TRACTS DETAIL
# ═══════════════════════════════════════════════════════════════════════════════
def ascending_section(story):
    # Section heading bar
    hdr = Table([[P("ASCENDING TRACTS  (Sensory — carry signals TO brain)", T_H2_ASC)]],
                colWidths=[CONTENT_W])
    hdr.setStyle(TableStyle([
        ("BACKGROUND",    (0,0), (-1,-1), C_ASC_HDR),
        ("TOPPADDING",    (0,0), (-1,-1), 6),
        ("BOTTOMPADDING", (0,0), (-1,-1), 6),
        ("LEFTPADDING",   (0,0), (-1,-1), 10),
    ]))
    story += [hdr, SP(6)]

    # Intro note
    story.append(P(
        "<b>Key principle:</b> Ascending tracts carry sensory information (touch, pain, temperature, "
        "proprioception) from the body and limbs UP to the brain. They are classified into "
        "<b>two main systems</b>: the <b>Dorsal Column–Medial Lemniscal (DCML)</b> system and "
        "the <b>Anterolateral (Spinothalamic)</b> system. Cerebellar tracts are a third group.",
        T_CELL))
    story.append(SP(6))

    # ── 1A. DCML Pathway ──────────────────────────────────────────────────────
    story.append(P("1A. Dorsal Column – Medial Lemniscal (DCML) System", T_H1))
    story.append(HR())

    cw = [CONTENT_W*0.18, CONTENT_W*0.19, CONTENT_W*0.19, CONTENT_W*0.22, CONTENT_W*0.22]
    rows = [
        [P("Tract", T_CHDR), P("Modality", T_CHDR), P("1st Neuron\n(Cell Body)", T_CHDR),
         P("2nd Neuron\n(Crosses / Ascends)", T_CHDR), P("3rd Neuron &amp; Cortex", T_CHDR)],
        [P("Fasciculus Gracilis\n(Goll's column)", T_CELLB),
         P("Fine touch, vibration,\npropriception,\n2-point discrim.\nLower body\n(below T6)", T_CELL),
         P("DRG → enters ipsilateral\ndorsal column, ascends\nwithout crossing", T_CELL),
         P("Nucleus gracilis\n(medulla) → fibres cross\nmidline → medial\nlemniscus (contralateral)", T_CELL),
         P("VPL thalamus →\nprimary somatosensory\ncortex (S1,\npostcentral gyrus)", T_CELL)],
        [P("Fasciculus Cuneatus\n(Burdach's column)", T_CELLB),
         P("Fine touch, vibration,\npropriception,\n2-point discrim.\nUpper body\n(above T6)", T_CELL),
         P("DRG → ipsilateral\ndorsal column,\nascends without\ncrossing", T_CELL),
         P("Nucleus cuneatus\n(medulla) → fibres\ncross → medial\nlemniscus", T_CELL),
         P("VPL thalamus →\nS1 cortex\n(postcentral gyrus)", T_CELL)],
    ]
    cmds = list(BASE_STYLE) + [
        ("BACKGROUND", (0,0), (-1,0), C_ASC_HDR),
        ("BACKGROUND", (0,1), (-1,1), C_ASC_LIGHT),
        ("BACKGROUND", (0,2), (-1,2), HexColor("#EAFAF1")),
    ]
    story.append(make_table(rows, cw, cmds))
    story.append(SP(4))
    story.append(P(
        "<b>Remember (DCML):</b> 1st neuron enters and ascends IPSILATERAL → crosses in MEDULLA "
        "(not spinal cord) → 2nd neuron ascends as medial lemniscus → VPL thalamus → S1 cortex. "
        "Lesion below medulla = ipsilateral deficit. Lesion above medulla = contralateral deficit.",
        T_NOTE))
    story.append(SP(8))

    # ── 1B. Anterolateral / Spinothalamic ─────────────────────────────────────
    story.append(P("1B. Anterolateral (Spinothalamic) System", T_H1))
    story.append(HR())

    cw2 = [CONTENT_W*0.18, CONTENT_W*0.20, CONTENT_W*0.20, CONTENT_W*0.20, CONTENT_W*0.22]
    rows2 = [
        [P("Tract", T_CHDR), P("Modality", T_CHDR), P("1st Neuron", T_CHDR),
         P("2nd Neuron\n(Crosses)", T_CHDR), P("3rd Neuron &amp; Cortex", T_CHDR)],
        [P("Lateral\nSpinothalamic\nTract (LST)", T_CELLB),
         P("Pain\nTemperature\n(sharp, localised)", T_CELL),
         P("DRG → enters via\nLissauer's tract →\nsynapses in dorsal\nhorn (Rexed\nlamina I, II, V)", T_CELL),
         P("2nd neuron crosses\nvia anterior white\ncommissure within\n1-2 spinal segments\n→ contralateral\nlateral funiculus", T_CELL),
         P("VPL thalamus\n(+ intralaminar\nnuclei) → S1 cortex\n+ limbic system", T_CELL)],
        [P("Anterior\nSpinothalamic\nTract (AST)", T_CELLB),
         P("Crude (light)\ntouch\nPressure", T_CELL),
         P("DRG → dorsal horn\n(Rexed laminae\nVI–VII)", T_CELL),
         P("Crosses via anterior\nwhite commissure →\ncontralateral anterior\nfuniculus", T_CELL),
         P("VPL thalamus →\nS1 cortex\n(bilaterally\nrepresented)", T_CELL)],
        [P("Spinoreticular\nTract\n(Paleospinothal.)", T_CELLB),
         P("Poorly localised\n(burning) pain\nAffective component\nof pain", T_CELL),
         P("DRG → dorsal horn", T_CELL),
         P("Short axons → relay\nin brainstem reticular\nformation → bilateral\nascent", T_CELL),
         P("Intralaminar nuclei\nof thalamus →\nlimbic cortex", T_CELL)],
    ]
    cmds2 = list(BASE_STYLE) + [
        ("BACKGROUND", (0,0), (-1,0), HexColor("#1A6B3A")),
        ("BACKGROUND", (0,1), (-1,1), C_ASC_LIGHT),
        ("BACKGROUND", (0,2), (-1,2), HexColor("#EAFAF1")),
        ("BACKGROUND", (0,3), (-1,3), C_ASC_LIGHT),
    ]
    story.append(make_table(rows2, cw2, cmds2))
    story.append(SP(4))
    story.append(P(
        "<b>Remember (Spinothalamic):</b> 1st neuron enters → ascends 1–2 levels in Lissauer's tract "
        "→ synapses in dorsal horn → 2nd neuron CROSSES IN SPINAL CORD (anterior commissure) → "
        "ascends CONTRALATERAL. "
        "Somatotopy: sacral fibres outermost (superficial) at cervical level; cervical fibres innermost. "
        "Lesion = contralateral pain &amp; temperature loss BELOW lesion level.",
        T_NOTE))
    story.append(SP(8))

    # ── 1C. Cerebellar Tracts ──────────────────────────────────────────────────
    story.append(P("1C. Spinocerebellar Tracts (Unconscious Proprioception)", T_H1))
    story.append(HR())

    cw3 = [CONTENT_W*0.22, CONTENT_W*0.18, CONTENT_W*0.20, CONTENT_W*0.20, CONTENT_W*0.20]
    rows3 = [
        [P("Tract", T_CHDR), P("Modality", T_CHDR), P("Origin", T_CHDR),
         P("Course", T_CHDR), P("Destination", T_CHDR)],
        [P("Dorsal\nSpinocerebellar\n(Flechsig's)", T_CELLB),
         P("Unconscious\nproprioception\nLower limbs +\ninferior trunk", T_CELL),
         P("Clarke's column\n(nucleus dorsalis)\nC8–L2 → ipsilateral\nlateral funiculus", T_CELL),
         P("Does NOT cross\n→ ipsilateral\nlateral column\n→ inferior cerebellar\npeduncle", T_CELL),
         P("Ipsilateral\ncerebellum\n(vermis)", T_CELL)],
        [P("Ventral\nSpinocerebellar\n(Gowers')", T_CELLB),
         P("Unconscious\nproprioception\nLower limbs", T_CELL),
         P("Lumbar spinal\nborder cells\n(lamina V–VII)", T_CELL),
         P("Crosses TWICE\n(spinal cord then\npons) → superior\ncerebellar peduncle", T_CELL),
         P("Contralateral then\nrecrosses back to\nipsilateral cerebellum", T_CELL)],
        [P("Cuneocerebellar\n(Posterior ext.\narcuate fibres)", T_CELLB),
         P("Unconscious\nproprioception\nUpper limbs +\ntrunk (above T6)", T_CELL),
         P("Accessory cuneate\nnucleus (medulla)", T_CELL),
         P("Ipsilateral →\ninferior cerebellar\npeduncle", T_CELL),
         P("Ipsilateral\ncerebellum", T_CELL)],
        [P("Rostral\nSpinocerebellar", T_CELLB),
         P("Unconscious\nproprioception\nUpper limbs\n(functional)", T_CELL),
         P("Cervical enlargement\nlamina V–VII", T_CELL),
         P("Mainly ipsilateral\n→ superior / inferior\npeduncle", T_CELL),
         P("Ipsilateral\ncerebellum", T_CELL)],
    ]
    cmds3 = list(BASE_STYLE) + [
        ("BACKGROUND", (0,0), (-1,0), HexColor("#145A32")),
        ("BACKGROUND", (0,1), (-1,1), C_ASC_LIGHT),
        ("BACKGROUND", (0,2), (-1,2), HexColor("#EAFAF1")),
        ("BACKGROUND", (0,3), (-1,3), C_ASC_LIGHT),
        ("BACKGROUND", (0,4), (-1,4), HexColor("#EAFAF1")),
    ]
    story.append(make_table(rows3, cw3, cmds3))
    story.append(SP(4))
    story.append(P(
        "<b>Remember (Cerebellar):</b> Dorsal spinocerebellar = ipsilateral, does NOT cross. "
        "Ventral spinocerebellar = crosses TWICE (effectively ipsilateral). "
        "Cerebellar tracts = UNCONSCIOUS proprioception (no cortical awareness). "
        "Lesion → ipsilateral ataxia.",
        T_NOTE))


# ═══════════════════════════════════════════════════════════════════════════════
# SECTION 2 — DESCENDING TRACTS
# ═══════════════════════════════════════════════════════════════════════════════
def descending_section(story):
    story.append(PageBreak())

    hdr = Table([[P("DESCENDING TRACTS  (Motor — carry signals FROM brain)", T_H2_DESC)]],
                colWidths=[CONTENT_W])
    hdr.setStyle(TableStyle([
        ("BACKGROUND",    (0,0), (-1,-1), C_DESC_HDR),
        ("TOPPADDING",    (0,0), (-1,-1), 6),
        ("BOTTOMPADDING", (0,0), (-1,-1), 6),
        ("LEFTPADDING",   (0,0), (-1,-1), 10),
    ]))
    story += [hdr, SP(6)]

    story.append(P(
        "<b>Key principle:</b> Descending tracts carry motor commands DOWN from the brain to spinal "
        "cord lower motor neurons (LMNs). Divided into <b>Lateral pathways</b> (fine voluntary "
        "movement of distal muscles) and <b>Ventromedial (Anteromedial) pathways</b> "
        "(posture, balance, axial/proximal muscles).",
        T_CELL))
    story.append(SP(6))

    # ── 2A. Lateral Pathways ───────────────────────────────────────────────────
    story.append(P("2A. Lateral Pathways (Fine Voluntary Movement)", T_H1))
    story.append(HR())

    cw = [CONTENT_W*0.20, CONTENT_W*0.18, CONTENT_W*0.18, CONTENT_W*0.22, CONTENT_W*0.22]
    rows = [
        [P("Tract", T_CHDR), P("Origin", T_CHDR), P("Decussation", T_CHDR),
         P("Cord Position &amp; Course", T_CHDR), P("Function", T_CHDR)],
        [P("Lateral\nCorticospinal\nTract (LCST)\n~85%", T_CELLB),
         P("Primary motor cortex\n(area 4, layer V)\nPremotor (area 6)\nSMA, parietal cortex", T_CELL),
         P("Pyramidal\ndecussation\nat cervicomedullary\njunction (medulla)", T_CELL),
         P("Lateral funiculus\n(posterior part)\nSomatotopy:\nArm medial,\nLeg lateral", T_CELL),
         P("Voluntary fine\nmovement of\ncontralateral\ndistal limbs\n(fingers, hand)", T_CELL)],
        [P("Anterior\nCorticospinal\nTract (ACST)\n~15%", T_CELLB),
         P("Primary motor cortex\n(area 4, layer V)", T_CELL),
         P("Crosses at\nsegmental level\n(anterior commissure)", T_CELL),
         P("Anterior funiculus\n(medial)", T_CELL),
         P("Axial + proximal\nmuscles, bilateral\ncontrol", T_CELL)],
        [P("Rubrospinal\nTract", T_CELLB),
         P("Red nucleus\n(midbrain\ntegmentum)", T_CELL),
         P("Immediate\ndecussation\nin ventral pons\n(dorsal tegmental)", T_CELL),
         P("Lateral funiculus\n(anterior to LCST)\nOnly to upper\ncervical cord", T_CELL),
         P("Fine arm/hand\nmovement\n(minor in humans;\nreplaced by CST\nin evolution)", T_CELL)],
    ]
    cmds = list(BASE_STYLE) + [
        ("BACKGROUND", (0,0), (-1,0), C_DESC_HDR),
        ("BACKGROUND", (0,1), (-1,1), C_DESC_LIGHT),
        ("BACKGROUND", (0,2), (-1,2), HexColor("#FDEDEC")),
        ("BACKGROUND", (0,3), (-1,3), C_DESC_LIGHT),
    ]
    story.append(make_table(rows, cw, cmds))
    story.append(SP(4))
    story.append(P(
        "<b>Corticobulbar tract:</b> Fibres from motor cortex that project to <i>brainstem cranial nerve "
        "nuclei</i> (rather than spinal cord) — controls face, jaw, tongue, palate, pharynx. "
        "Most CN nuclei receive BILATERAL cortical input except lower face (CN VII) and hypoglossal "
        "(CN XII) which are predominantly contralateral — clinically important in central vs peripheral "
        "facial palsy distinction.",
        T_NOTE))
    story.append(SP(8))

    # ── 2B. Ventromedial Pathways ──────────────────────────────────────────────
    story.append(P("2B. Ventromedial (Anteromedial) Pathways (Posture &amp; Balance)", T_H1))
    story.append(HR())

    cw2 = [CONTENT_W*0.22, CONTENT_W*0.18, CONTENT_W*0.17, CONTENT_W*0.21, CONTENT_W*0.22]
    rows2 = [
        [P("Tract", T_CHDR), P("Origin", T_CHDR), P("Decussation", T_CHDR),
         P("Cord Position", T_CHDR), P("Function", T_CHDR)],
        [P("Lateral\nVestibulospinal\nTract", T_CELLB),
         P("Lateral vestibular\nnucleus (Deiters')\nin medulla", T_CELL),
         P("None\n(Ipsilateral)", T_CELL),
         P("Anterior funiculus\n→ full length\nof cord", T_CELL),
         P("Facilitates EXTENSOR\nmotor neurons\n→ maintains upright\nposture / balance", T_CELL)],
        [P("Medial\nVestibulospinal\nTract", T_CELLB),
         P("Medial vestibular\nnucleus (medulla)", T_CELL),
         P("Bilateral\n(crosses partially)", T_CELL),
         P("Anterior funiculus\n→ cervical cord\nonly", T_CELL),
         P("Head &amp; neck\nposture, stabilises\nhead during\nbody movement", T_CELL)],
        [P("Tectospinal\nTract", T_CELLB),
         P("Superior colliculus\n(midbrain)\n[vision + auditory\ninput]", T_CELL),
         P("Dorsal tegmental\ndecussation\n(immediately)", T_CELL),
         P("Anterior funiculus\n→ cervical cord\nonly (C1-C4)", T_CELL),
         P("Reflex head &amp; neck\nturning toward\nvisual / auditory\nstimuli", T_CELL)],
        [P("Pontine\nReticulospinal\nTract\n(Medial RST)", T_CELLB),
         P("Pontine reticular\nformation (PMRF)\n= nucleus\nreticularis pontis", T_CELL),
         P("None\n(Ipsilateral)", T_CELL),
         P("Anterior funiculus\n(medial)", T_CELL),
         P("FACILITATES\nantigravity extensor\nstretch reflexes\n→ maintains\nstanding posture", T_CELL)],
        [P("Medullary\nReticulospinal\nTract\n(Lateral RST)", T_CELLB),
         P("Medullary reticular\nformation\n= nucleus\nreticularis gigantocellularis", T_CELL),
         P("Bilateral\n(partly crosses)", T_CELL),
         P("Lateral funiculus\n(anterior part)", T_CELL),
         P("INHIBITS\nantigravity muscles;\nliberates them\nfrom reflex control\n→ enables movement", T_CELL)],
    ]
    cmds2 = list(BASE_STYLE) + [
        ("BACKGROUND", (0,0), (-1,0), HexColor("#6E2C2C")),
        ("BACKGROUND", (0,1), (-1,1), C_DESC_LIGHT),
        ("BACKGROUND", (0,2), (-1,2), HexColor("#FDEDEC")),
        ("BACKGROUND", (0,3), (-1,3), C_DESC_LIGHT),
        ("BACKGROUND", (0,4), (-1,4), HexColor("#FDEDEC")),
        ("BACKGROUND", (0,5), (-1,5), C_DESC_LIGHT),
    ]
    story.append(make_table(rows2, cw2, cmds2))
    story.append(SP(4))
    story.append(P(
        "<b>Reticulospinal clinical note:</b> The pontine RST facilitates extensors; medullary RST "
        "inhibits them. In an upper brainstem (midbrain) lesion, the medullary RST is also cut, "
        "leaving unopposed pontine facilitation → <b>decerebrate rigidity</b> (all four limbs extended). "
        "In a lower brainstem lesion sparing the medullary RST → <b>decorticate posture</b> (arm "
        "flexion, leg extension).",
        T_NOTE))


# ═══════════════════════════════════════════════════════════════════════════════
# SECTION 3 — MASTER COMPARISON TABLE
# ═══════════════════════════════════════════════════════════════════════════════
def comparison_section(story):
    story.append(PageBreak())

    hdr = Table([[P("ASCENDING vs DESCENDING — Master Comparison", T_H2_ASC)]],
                colWidths=[CONTENT_W])
    hdr.setStyle(TableStyle([
        ("BACKGROUND",    (0,0), (-1,-1), C_BLUE_HDR),
        ("TOPPADDING",    (0,0), (-1,-1), 6),
        ("BOTTOMPADDING", (0,0), (-1,-1), 6),
        ("LEFTPADDING",   (0,0), (-1,-1), 10),
    ]))
    story += [hdr, SP(6)]

    cw = [CONTENT_W*0.22, CONTENT_W*0.39, CONTENT_W*0.39]
    rows = [
        [P("Feature", T_CHDR),
         P("ASCENDING Tracts (Sensory)", T_CHDR),
         P("DESCENDING Tracts (Motor)", T_CHDR)],
        [P("Direction", T_CELLB),
         P("Body/periphery → Spinal cord → Brain", T_CELL),
         P("Brain → Spinal cord → Muscle / effector", T_CELL)],
        [P("Function", T_CELLB),
         P("Carry sensory information: touch, pain,\ntemperature, proprioception, vibration", T_CELL),
         P("Carry motor commands: voluntary movement,\nposture, balance, reflex control", T_CELL)],
        [P("Neuron order", T_CELLB),
         P("3 neurons:\n1st = DRG → 2nd = spinal cord/medulla\n→ 3rd = thalamus → cortex", T_CELL),
         P("2 neurons (UMN + LMN):\nUMN = cortex → spinal cord\nLMN = spinal cord → muscle", T_CELL)],
        [P("Where do fibres\ncross (decussate)?", T_CELLB),
         P("DCML: Medulla (nucleus gracilis/cuneatus)\nSpinothalamic: Spinal cord\n(anterior commissure, 1–2 segments above entry)", T_CELL),
         P("CST (lateral): Medulla (pyramidal decussation)\nCST (anterior): Spinal cord (segmental)\nRubrospinal: Immediately in pons\nVestibulo/Tecto/Reticulospinal: Mostly ipsilateral", T_CELL)],
        [P("Side of cord\n(at spinal level)", T_CELLB),
         P("DCML: Ipsilateral dorsal column\nSpinothalamic: Contralateral anterolateral", T_CELL),
         P("LCST: Contralateral lateral column\nACT: Ipsilateral anterior column\nVentromedial: Anterior column (mostly)", T_CELL)],
        [P("Cortical destination\n/ origin", T_CELLB),
         P("Primary somatosensory cortex (S1)\n= postcentral gyrus (areas 3, 1, 2)\nCerebellar tracts → cerebellum (no cortex)", T_CELL),
         P("Primary motor cortex (M1)\n= precentral gyrus (area 4)\nPremotor / SMA (area 6)", T_CELL)],
        [P("Thalamic relay", T_CELLB),
         P("VPL nucleus of thalamus\n(sensory relay for body + limbs)\nVPM for face (trigeminal)", T_CELL),
         P("VL nucleus of thalamus\n(motor relay — input from cerebellum\nand basal ganglia to motor cortex)", T_CELL)],
        [P("Key clinical sign\nif damaged", T_CELLB),
         P("Loss of specific sensory modality\nbelow lesion level\n(pattern depends on tract affected)", T_CELL),
         P("Upper Motor Neuron signs if LCST\n(spasticity, hyperreflexia, Babinski)\nLower Motor Neuron signs at level", T_CELL)],
        [P("Somatotopic\norganisation", T_CELLB),
         P("Spinothalamic: Sacral outermost\n(clinically: central cord → sacral sparing)\nDCML: Sacral medial, cervical lateral", T_CELL),
         P("LCST: Arm medial, leg lateral\nInternal capsule: Face ant, leg post\n(Homunculus preserved throughout)", T_CELL)],
        [P("Effect of complete\nspinal cord lesion", T_CELLB),
         P("All sensation lost below level\n(DCML + spinothalamic both cut)", T_CELL),
         P("UMN paralysis below level\n(initially flaccid — spinal shock\nthen spastic with hyperreflexia)", T_CELL)],
        [P("Cord syndrome\nexample", T_CELLB),
         P("Brown-Sequard: ipsilateral DCML\nloss + contralateral spinothalamic loss\n= hemisection of cord", T_CELL),
         P("Brown-Sequard: ipsilateral UMN\nparalysis below lesion level", T_CELL)],
    ]
    cmds = list(BASE_STYLE) + [
        ("BACKGROUND", (0,0), (0,0), C_BLUE_HDR),
        ("BACKGROUND", (1,0), (1,0), C_ASC_HDR),
        ("BACKGROUND", (2,0), (2,0), C_DESC_HDR),
        ("BACKGROUND", (0,1), (0,-1), HexColor("#EBF5FB")),
        ("FONTNAME",   (0,1), (0,-1), "Helvetica-Bold"),
        ("FONTSIZE",   (0,1), (0,-1), 8),
    ]
    for i in range(1, len(rows)):
        bg_asc  = C_ASC_LIGHT if i % 2 == 1 else HexColor("#EAFAF1")
        bg_desc = C_DESC_LIGHT if i % 2 == 1 else HexColor("#FDEDEC")
        cmds.append(("BACKGROUND", (1,i), (1,i), bg_asc))
        cmds.append(("BACKGROUND", (2,i), (2,i), bg_desc))
    story.append(make_table(rows, cw, cmds))
    story.append(SP(8))


# ═══════════════════════════════════════════════════════════════════════════════
# SECTION 4 — BROWN-SEQUARD + CORD SYNDROMES
# ═══════════════════════════════════════════════════════════════════════════════
def cord_syndromes(story):
    story.append(P("Spinal Cord Syndromes — Tract Lesion Patterns", T_H1))
    story.append(HR())

    cw = [CONTENT_W*0.22, CONTENT_W*0.26, CONTENT_W*0.26, CONTENT_W*0.26]
    rows = [
        [P("Syndrome", T_CHDR), P("Tracts Affected", T_CHDR),
         P("Signs &amp; Symptoms", T_CHDR), P("Classic Cause", T_CHDR)],
        [P("Brown-Sequard\n(Hemisection)", T_CELLB),
         P("LCST + DCML (ipsilateral)\nSpinothalamic (contralateral)", T_CELL),
         P("Ipsilateral: UMN motor loss\n+ proprioception/vibration loss\nContralateral: pain &amp;\ntemperature loss (1–2 levels below)", T_CELL),
         P("Penetrating spinal\ntrauma, MS,\ntumour", T_CELL)],
        [P("Central Cord\nSyndrome", T_CELLB),
         P("Central grey matter\n+ crossing spinothalamic\nfibres first affected", T_CELL),
         P("Cape distribution:\nBilateral pain &amp; temp loss\n(arms > legs)\nMotor weakness arms > legs\nSacral sensation SPARED", T_CELL),
         P("Hyperextension in\ncervical spondylosis;\nSyringomyelia", T_CELL)],
        [P("Anterior Cord\nSyndrome", T_CELLB),
         P("Spinothalamic (bilateral)\n+ Corticospinal (bilateral)\nDCML spared", T_CELL),
         P("Bilateral motor paralysis +\nbilateral pain &amp; temp loss\nbelow lesion\nPropriocepion &amp; vibration\nINTACT", T_CELL),
         P("Anterior spinal\nartery infarct", T_CELL)],
        [P("Posterior Cord\nSyndrome", T_CELLB),
         P("DCML (bilateral)\nSpinothalaamic spared", T_CELL),
         P("Loss of proprioception,\nvibration, fine touch\nSensory ataxia, Romberg +ve\nPain &amp; temp INTACT", T_CELL),
         P("Tabes dorsalis\n(syphilis), B12\ndeficiency", T_CELL)],
        [P("Conus Medullaris\nSyndrome", T_CELLB),
         P("S3–S5 segments\n(LMN + UMN mix)", T_CELL),
         P("Saddle anaesthesia\nBladder/bowel/\nsexual dysfunction\nMixed UMN + LMN\nleg signs", T_CELL),
         P("L1 fracture,\ntumour, disc prolapse", T_CELL)],
    ]
    cmds = list(BASE_STYLE) + [
        ("BACKGROUND", (0,0), (-1,0), C_BLUE_HDR),
    ]
    for i in range(1, len(rows)):
        bg = C_PALE if i % 2 == 0 else C_WHITE
        cmds.append(("BACKGROUND", (0,i), (-1,i), bg))
    cmds.append(("BACKGROUND", (0,1), (-1,1), HexColor("#FEF9E7")))  # BS highlight
    story.append(make_table(rows, cw, cmds))
    story.append(SP(8))


# ═══════════════════════════════════════════════════════════════════════════════
# SECTION 5 — QUICK MNEMONICS + EXAM TIPS
# ═══════════════════════════════════════════════════════════════════════════════
def mnemonics_section(story):
    story.append(P("Quick Mnemonics &amp; Exam Tips", T_H1))
    story.append(HR())

    tips = [
        ("<b>DCML crossing rule:</b>",
         "\"Goes UP FIRST, crosses in MEDULLA\" — fibres travel ipsilaterally until the medulla, "
         "then cross. Lesion at or below medulla = ipsilateral deficit."),
        ("<b>Spinothalamic crossing rule:</b>",
         "\"Crosses SOON &amp; BELOW\" — crosses in spinal cord within 1–2 segments of entry. "
         "Lesion = contralateral pain/temp loss. Level of sensory loss is 1–2 levels BELOW lesion."),
        ("<b>LCST crossing rule:</b>",
         "\"Crosses in MEDULLA at pyramidal decussation\" — contralateral UMN signs below lesion. "
         "Above decussation = contralateral; Below decussation = ipsilateral weakness."),
        ("<b>Somatotopy trick (spinothalamic):</b>",
         "\"SALE\" from outside in at cervical level: Sacral – Lumbar – Thoracic – cErvical "
         "(outermost to innermost). Central cord lesion spares sacral = sacral sparing."),
        ("<b>Dorsal column fibres:</b>",
         "Gracilis (medial) = lower body (graceful legs). Cuneatus (lateral) = upper body/arms. "
         "Mnemonic: \"Grace is thin (medial, lower)\""),
        ("<b>Cerebellar tracts memory:</b>",
         "Dorsal = \"DOES NOT cross\" (ipsilateral). Ventral = \"crosses TWICE\" (still ipsilateral). "
         "Both go to the SAME side cerebellum as origin."),
        ("<b>Decerebrate vs Decorticate:</b>",
         "Decerebrate (midbrain lesion) = ALL four limbs EXTENDED (arms + legs straight). "
         "Decorticate (cortical/internal capsule) = Arms FLEXED, legs extended. "
         "Mnemonic: deCORticate = COR = arms toward CORe (flex toward chest)"),
        ("<b>Brown-Sequard shortcut:</b>",
         "Ipsilateral side = Motor loss + Fine touch/proprioception loss. "
         "Contralateral side = Pain &amp; temperature loss. "
         "Mnemonic: \"Same side suffers motor; opposite side loses pain\""),
    ]

    half = (CONTENT_W - 4) / 2
    tip_rows = []
    for i in range(0, len(tips), 2):
        left = tips[i]
        right = tips[i+1] if i+1 < len(tips) else ("", "")
        def make_cell(tip):
            return P(f'<font color="#154360">{tip[0]}</font><br/>'
                     f'<font color="#2C3E50" size="7.5">{tip[1]}</font>',
                     S("Normal", fontSize=8, leading=11, fontName="Helvetica"))
        tip_rows.append([make_cell(left), make_cell(right)])

    mnem_tbl = Table(tip_rows, colWidths=[half, half])
    mnem_tbl.setStyle(TableStyle([
        ("BACKGROUND",    (0,0), (-1,-1), HexColor("#F8F9FA")),
        ("BOX",           (0,0), (-1,-1), 0.8, HexColor("#AEB6BF")),
        ("INNERGRID",     (0,0), (-1,-1), 0.4, HexColor("#D5D8DC")),
        ("TOPPADDING",    (0,0), (-1,-1), 6),
        ("BOTTOMPADDING", (0,0), (-1,-1), 6),
        ("LEFTPADDING",   (0,0), (-1,-1), 8),
        ("RIGHTPADDING",  (0,0), (-1,-1), 8),
        ("VALIGN",        (0,0), (-1,-1), "TOP"),
    ]))
    story.append(mnem_tbl)
    story.append(SP(8))


# ═══════════════════════════════════════════════════════════════════════════════
# SECTION 6 — ONE-LINE FLASH SUMMARY TABLE
# ═══════════════════════════════════════════════════════════════════════════════
def flash_summary(story):
    story.append(P("Flash Summary — All Tracts at a Glance", T_H1))
    story.append(HR())

    cw = [CONTENT_W*0.22, CONTENT_W*0.10, CONTENT_W*0.17, CONTENT_W*0.17, CONTENT_W*0.17, CONTENT_W*0.17]
    rows = [
        [P("Tract", T_CHDR), P("Type", T_CHDR), P("Crosses Where?", T_CHDR),
         P("Cord Column", T_CHDR), P("Modality / Function", T_CHDR), P("Destination", T_CHDR)],
        # Ascending
        [P("Fasciculus Gracilis", T_CELLB), P("ASC", S("Normal",fontSize=8,textColor=C_ASC_HDR,fontName="Helvetica-Bold")),
         P("Medulla (nucleus gracilis)", T_CELL), P("Dorsal (medial)", T_CELL),
         P("Proprioception, vibration,\nfine touch (lower body)", T_CELL), P("VPL → S1 cortex", T_CELL)],
        [P("Fasciculus Cuneatus", T_CELLB), P("ASC", S("Normal",fontSize=8,textColor=C_ASC_HDR,fontName="Helvetica-Bold")),
         P("Medulla (nucleus cuneatus)", T_CELL), P("Dorsal (lateral)", T_CELL),
         P("Proprioception, vibration,\nfine touch (upper body)", T_CELL), P("VPL → S1 cortex", T_CELL)],
        [P("Lateral Spinothalamic", T_CELLB), P("ASC", S("Normal",fontSize=8,textColor=C_ASC_HDR,fontName="Helvetica-Bold")),
         P("Spinal cord\n(ant. commissure)", T_CELL), P("Anterolateral", T_CELL),
         P("Pain, Temperature", T_CELL), P("VPL → S1 cortex", T_CELL)],
        [P("Anterior Spinothalamic", T_CELLB), P("ASC", S("Normal",fontSize=8,textColor=C_ASC_HDR,fontName="Helvetica-Bold")),
         P("Spinal cord\n(ant. commissure)", T_CELL), P("Anterolateral", T_CELL),
         P("Crude touch, Pressure", T_CELL), P("VPL → S1 cortex", T_CELL)],
        [P("Dorsal Spinocerebellar", T_CELLB), P("ASC", S("Normal",fontSize=8,textColor=C_ASC_HDR,fontName="Helvetica-Bold")),
         P("Does NOT cross", T_CELL), P("Lateral (posterior)", T_CELL),
         P("Unconscious proprioception\n(lower limbs)", T_CELL), P("Ipsilateral cerebellum", T_CELL)],
        [P("Ventral Spinocerebellar", T_CELLB), P("ASC", S("Normal",fontSize=8,textColor=C_ASC_HDR,fontName="Helvetica-Bold")),
         P("Crosses TWICE", T_CELL), P("Lateral (anterior)", T_CELL),
         P("Unconscious proprioception\n(lower limbs)", T_CELL), P("Ipsilateral cerebellum", T_CELL)],
        # Descending
        [P("Lateral Corticospinal", T_CELLB), P("DESC", S("Normal",fontSize=8,textColor=C_DESC_HDR,fontName="Helvetica-Bold")),
         P("Medulla (pyramidal\ndecussation)", T_CELL), P("Lateral (posterior)", T_CELL),
         P("Voluntary fine movement\n(distal, contralateral)", T_CELL), P("Ventral horn LMN", T_CELL)],
        [P("Anterior Corticospinal", T_CELLB), P("DESC", S("Normal",fontSize=8,textColor=C_DESC_HDR,fontName="Helvetica-Bold")),
         P("Spinal cord\n(segmental)", T_CELL), P("Anterior", T_CELL),
         P("Axial/proximal muscles\n(bilateral)", T_CELL), P("Ventral horn LMN", T_CELL)],
        [P("Rubrospinal", T_CELLB), P("DESC", S("Normal",fontSize=8,textColor=C_DESC_HDR,fontName="Helvetica-Bold")),
         P("Immediately in pons", T_CELL), P("Lateral (anterior)", T_CELL),
         P("Fine arm movement\n(minor in humans)", T_CELL), P("Ventral horn LMN", T_CELL)],
        [P("Lateral Vestibulospinal", T_CELLB), P("DESC", S("Normal",fontSize=8,textColor=C_DESC_HDR,fontName="Helvetica-Bold")),
         P("None (ipsilateral)", T_CELL), P("Anterior", T_CELL),
         P("Facilitates extensors\n(balance/posture)", T_CELL), P("Ventral horn LMN", T_CELL)],
        [P("Medial Vestibulospinal", T_CELLB), P("DESC", S("Normal",fontSize=8,textColor=C_DESC_HDR,fontName="Helvetica-Bold")),
         P("Bilateral", T_CELL), P("Anterior", T_CELL),
         P("Head/neck posture", T_CELL), P("Cervical LMN", T_CELL)],
        [P("Tectospinal", T_CELLB), P("DESC", S("Normal",fontSize=8,textColor=C_DESC_HDR,fontName="Helvetica-Bold")),
         P("Dorsal tegmental\ndecussation", T_CELL), P("Anterior", T_CELL),
         P("Reflex head-turn to\naudio-visual stimuli", T_CELL), P("Cervical LMN", T_CELL)],
        [P("Pontine Reticulospinal", T_CELLB), P("DESC", S("Normal",fontSize=8,textColor=C_DESC_HDR,fontName="Helvetica-Bold")),
         P("None (ipsilateral)", T_CELL), P("Anterior (medial)", T_CELL),
         P("Facilitates extensor\nstretch reflexes", T_CELL), P("Ventral horn LMN", T_CELL)],
        [P("Medullary Reticulospinal", T_CELLB), P("DESC", S("Normal",fontSize=8,textColor=C_DESC_HDR,fontName="Helvetica-Bold")),
         P("Bilateral", T_CELL), P("Lateral (anterior)", T_CELL),
         P("Inhibits antigravity\nmuscles", T_CELL), P("Ventral horn LMN", T_CELL)],
    ]
    cmds = list(BASE_STYLE) + [
        ("BACKGROUND", (0,0), (-1,0), C_BLUE_HDR),
        ("FONTSIZE",   (0,0), (-1,0), 8.5),
    ]
    # Shading by type
    for i in range(1, len(rows)):
        if i <= 7:   # ascending
            bg = C_ASC_LIGHT if i % 2 == 1 else HexColor("#EAFAF1")
        else:        # descending
            bg = C_DESC_LIGHT if i % 2 == 1 else HexColor("#FDEDEC")
        cmds.append(("BACKGROUND", (0,i), (-1,i), bg))
    story.append(make_table(rows, cw, cmds))
    story.append(SP(6))


# ═══════════════════════════════════════════════════════════════════════════════
# FOOTER
# ═══════════════════════════════════════════════════════════════════════════════
def footer(story):
    notes = (
        "Notes: DRG = Dorsal Root Ganglion | VPL = Ventroposterolateral nucleus of thalamus | "
        "VPM = Ventroposteromedial | S1 = Primary Somatosensory Cortex | M1 = Primary Motor Cortex | "
        "UMN = Upper Motor Neuron | LMN = Lower Motor Neuron | ASC = Ascending | DESC = Descending | "
        "LCST = Lateral Corticospinal Tract | DCML = Dorsal Column-Medial Lemniscal | "
        "SMA = Supplementary Motor Area | RST = Reticulospinal Tract"
    )
    story.append(Paragraph(notes, S("Normal", fontSize=7, textColor=C_GRAY,
        fontName="Helvetica-Oblique", leading=10)))
    story.append(SP(4))
    story.append(Paragraph("Orris Medical — Spinal Tracts Quick Revision | July 2026",
        S("Normal", fontSize=7.5, textColor=HexColor("#AEB6BF"),
          fontName="Helvetica", alignment=TA_CENTER)))


# ── BUILD ─────────────────────────────────────────────────────────────────────
story = []
banner(story)
ascending_section(story)
descending_section(story)
comparison_section(story)
cord_syndromes(story)
mnemonics_section(story)
flash_summary(story)
footer(story)

doc.build(story)
print(f"Done: {OUT}")
Running Command

cd /home/daytona/workspace/tracts-revision && python build_pdf.py 2>&1

Running Command

ls -lh /home/daytona/workspace/tracts-revision/

Your PDF is ready to download:

Spinal Tracts Quick Revision

PDF Document · PDF


What's inside (A4, colour-coded — Green = Ascending, Red = Descending, Blue = Comparison):

Page 1 — Ascending Tracts
  • DCML System (Fasciculus Gracilis + Cuneatus): origin, where they cross (medulla), cord column, modality, destination
  • Anterolateral/Spinothalamic System (Lateral ST, Anterior ST, Spinoreticular): crossing in spinal cord, somatotopy note
  • Spinocerebellar Tracts (Dorsal, Ventral, Cuneocerebellar, Rostral): unconscious proprioception, ipsilateral vs. double-crossing rules
Page 2 — Descending Tracts
  • Lateral pathways (Lateral CST, Anterior CST, Rubrospinal): decussation site, cord column, function
  • Ventromedial pathways (Lateral + Medial Vestibulospinal, Tectospinal, Pontine + Medullary Reticulospinal): posture, balance, facilitation vs inhibition
  • Corticobulbar tract note (central vs peripheral facial palsy)
Page 3 — Comparison + Clinical Application
  • Master 12-row comparison table: direction, neuron order, crossing site, cord column, cortex, thalamic relay, clinical signs, somatotopy - side by side ascending vs descending
  • Cord syndrome table (Brown-Sequard, Central cord, Anterior cord, Posterior cord, Conus medullaris) - which tracts are cut and what signs result
  • 8 mnemonics including SALE somatotopy, crossing rules, decerebrate vs decorticate, Brown-Sequard shortcut
  • Flash summary table - all 14 tracts in one glance with type/crossing/column/function/destination
This is a shared conversation. Sign in to Orris to start your own chat.