Sensory examination Normal and pathology along with causes

Reading File
Finding Sources
Finding Sources
Reading File
Reading File
Reading File
Reading File
Reading File
Finding Sources
Reading File
Reading File
Reading File
Reading File
Reading File
Loading Image
Loading Image
Reading File
Reading File
Loading Image
I now have comprehensive material. Let me compose a thorough, well-structured answer.

Sensory Examination: Normal Findings and Pathology with Causes

Sources: Adams & Victor's Principles of Neurology 12e, Harrison's Principles of Internal Medicine 22e, Neuroanatomy through Clinical Cases 3e

1. Anatomical Basis - The Two Major Sensory Pathways

Understanding the examination requires knowing which fiber goes where:
PathwayFibers carriedRouteDecussation
Posterior column - Medial lemniscusVibration, joint position sense (proprioception), discriminative touch, 2-point discriminationEnters dorsal horn → ascends ipsilaterally in posterior column → crosses in medulla → medial lemniscus → VPL thalamus → parietal cortexAt medulla
Anterolateral (spinothalamic)Pain, temperature, crude touchEnters dorsal horn → crosses within 1-2 segments via anterior commissure → ascends contralaterally → VPL thalamus → parietal cortexIn spinal cord (1-2 levels above entry)
Fiber types:
  • Large myelinated A-α fibers: touch, pressure, vibration, proprioception
  • Small myelinated A-δ fibers: pain (fast/sharp), cold temperature
  • Unmyelinated C fibers: pain (slow/burning), warmth, itch

2. Sensory Modalities Tested and Normal Technique

Primary Modalities

A. Light Touch
  • Tool: wisp of cotton or fingertip
  • Technique: single gentle touches, patient says "yes" when felt with eyes closed
  • Normal: detected equally in all regions; moving stimulus is more sensitive than stationary
B. Pain (Superficial)
  • Tool: new sharp pin
  • Technique: ask if stimulus feels "sharp" (not just contact); deliver ~1 per second, not over same spot
  • Normal: sharp sensation everywhere; ask patient to rate on 1-10 scale when comparing areas
  • Quantitative: Wartenberg wheel (pinwheel) historically used; now thermal algesimeters for research
C. Temperature
  • Tool: tuning fork (warm one side by rubbing, apply alternating sides); or test tubes with warm/cold water
  • Technique: binary choice - "warm or cold?"
  • Normal: correct identification of warm vs. cold
  • A-δ fibers carry cold sensation; C fibers carry warmth
D. Vibration
  • Tool: 128 Hz tuning fork applied to distal bony prominences (great toe, medial malleolus, patella, iliac crest; index finger, wrist, elbow, shoulder)
  • Technique: compare patient's perception to examiner's own; note level where sensation extinguishes
  • Normal: felt equally bilaterally; duration of perception comparable to examiner
  • Key: if lost at ankle but present at knee → length-dependent peripheral neuropathy; if lost at iliac crest → spinal cord lesion level
E. Joint Position Sense (Proprioception)
  • Tool: examiner grasps digit laterally (not dorsally, to avoid pressure cues)
  • Technique: move 1-2 mm up or down; patient reports direction with eyes closed
  • Normal: even small 1-2 mm excursions correctly identified
  • Romberg test: stands feet together, eyes open then closed. Positive Romberg (falls when eyes closed) = loss of proprioception (not cerebellar - cerebellar patients are unsteady with eyes open too)

Cortical / Discriminative Sensation

(Test only when primary modalities are intact - these require parietal cortex integration)
TestTechniqueNormal Threshold
Two-point discriminationCompass applied simultaneously; minimum distance perceived as two distinct pointsFingertip: 3-5 mm; palm: 8-15 mm; dorsum hand/foot: 20-30 mm; trunk: 4-7 cm
StereognosisPatient identifies object by touch alone (coin, key, paperclip) with eyes closedCorrect identification
GraphesthesiaNumber or letter written on skin surfaceCorrect identification
Double simultaneous stimulation (DSS)Both hands touched simultaneously; patient identifies which side(s) touchedBoth sides identified correctly
Point localization (topognosis)Touch a point; patient points to it with eyes closedAccurate localization

3. Normal vs. Abnormal - What to Look For

FindingNormalAbnormal
Light touchSymmetric, accurateAbsent = anesthesia; Reduced = hypesthesia; Exaggerated = hyperesthesia
PainSymmetric sharp sensationAbsent = analgesia; Reduced = hypalgesia; Exaggerated = hyperalgesia
TemperatureCorrect warm/cold distinctionAbsent = thermoanesthesia; Inverted = rare
VibrationSymmetric; felt as long as examinerLost distally first in neuropathy
Proprioception1-2 mm excursions correctly identifiedLoss → sensory ataxia, positive Romberg
DSSBoth sides perceivedExtinction of one side → contralateral parietal lesion
StereognosisObjects identified correctlyAstereognosis → parietal/posterior column lesion
Terminology for abnormal sensations:
  • Paresthesia: spontaneous tingling, pins-and-needles (large fiber ectopic discharge)
  • Dysesthesia: unpleasant sensation to a normally non-painful stimulus
  • Allodynia: pain from a non-noxious stimulus (e.g., light touch is painful)
  • Hyperpathia: exaggerated response to a stimulus, with persistence/spread
  • Anesthesia dolorosa: pain in an area that is objectively numb

4. Pathological Patterns and Their Causes

The key to sensory examination is pattern recognition to localize the lesion:
Spinal cord sensory syndromes - cross-sections showing each pattern
Patterns of sensory loss by lesion location - cortical/thalamic, lateral medullary, and peripheral nerve lesions

A. Peripheral Nerve (Mononeuropathy)

  • Pattern: Sensory loss in a specific anatomical nerve distribution (e.g., median nerve - lateral 3½ fingers; ulnar nerve - medial 1½ fingers + hypothenar)
  • All modalities affected in territory of that nerve
  • Associated: LMN weakness, reduced/absent reflex in that distribution
  • Causes: compression (carpal tunnel syndrome, Saturday night palsy - radial nerve), trauma, vasculitis, leprosy (selective for cooler skin areas), diabetes

B. Polyneuropathy (Peripheral Neuropathy)

  • Pattern: "Glove and stocking" - bilateral symmetric, starting distally, longest fibers first (length-dependent)
  • Vibration lost first at great toe; then ankles; then knees (length-dependent gradient)
  • Areflexia or hyporeflexia (ankle jerks lost first)
  • Causes:
    • Diabetes mellitus (commonest worldwide)
    • Alcohol excess
    • Vitamin B12 deficiency (subacute combined degeneration - posterior column + lateral column)
    • Chemotherapy (vincristine, cisplatin, taxanes)
    • Guillain-Barré syndrome (acute)
    • Chronic inflammatory demyelinating polyneuropathy (CIDP)
    • Amyloidosis (preferentially small fiber - pain/temperature > vibration)
    • Hereditary: Charcot-Marie-Tooth disease
    • Renal failure (uraemic neuropathy)
    • Hypothyroidism, HIV, Lyme disease, paraneoplastic

C. Radiculopathy (Nerve Root)

  • Pattern: Dermatomal sensory loss - a band or strip following a dermatome
  • Asymmetrical; reflex loss limited to affected root
  • Associated: root-distribution pain (radicular pain) that radiates from spine
  • Causes: disc herniation (L4/L5/S1 most common lumbar; C5/C6/C7 most common cervical), spondylosis, foraminal stenosis, herpes zoster (also causes vesicles in that dermatome), tumour, arachnoiditis

D. Dorsal Root Ganglionopathy (Ganglionopathy / Sensory Neuronopathy)

  • Pattern: All modalities affected including proximal areas (non-length-dependent); sensory ataxia prominent; Romberg positive
  • Areflexia
  • May be asymmetric, multifocal
  • Causes: paraneoplastic (anti-Hu antibody with small cell lung cancer), Sjögren's syndrome, cisplatin toxicity, vitamin B6 (pyridoxine) toxicity, idiopathic

E. Spinal Cord Syndromes

i. Complete Transverse Lesion

  • Pattern: ALL modalities lost BELOW the level of the lesion (bilateral)
  • Sharp sensory level on trunk (often 1-2 segments below actual lesion)
  • Hyperesthesia at upper margin of anesthetic zone
  • Associated: UMN weakness + bladder/bowel dysfunction below level
  • Causes: trauma, multiple sclerosis, transverse myelitis, cord compression (tumour, epidural abscess, haematoma), infarction

ii. Brown-Séquard Syndrome (Hemisection)

  • Pattern (the classic crossing pattern):
    • Ipsilateral: loss of vibration + proprioception below lesion (posterior column ipsilateral)
    • Contralateral: loss of pain + temperature, beginning 2-3 segments below lesion (spinothalamic crossed)
    • Ipsilateral: UMN weakness below lesion
  • Causes: stab wound (most classic), MS, tumour, radiation, disc herniation

iii. Syringomyelic Syndrome (Central Cord / Anterior Commissure)

  • Pattern: "Cape distribution" - bilateral loss of pain and temperature over neck, shoulders, and arms; touch and proprioception PRESERVED (= dissociated sensory loss)
  • Due to destruction of crossing spinothalamic fibers in anterior commissure
  • Causes: syringomyelia (most common in cervical region), intramedullary tumour (ependymoma, astrocytoma), trauma, haemorrhage

iv. Posterior Column Syndrome

  • Pattern: Loss of vibration + proprioception bilaterally below lesion; pain/temperature relatively spared; sensory ataxia; Romberg positive; tendon reflexes preserved
  • Paresthesias as "band-like" sensations, Lhermitte's sign (electric shock down spine on neck flexion in cervical lesions)
  • Causes: multiple sclerosis, subacute combined degeneration (B12 deficiency - also affects lateral columns), tabes dorsalis (neurosyphilis - here reflexes are LOST because dorsal roots also affected)

v. Tabetic Syndrome (Posterior Root/Posterior Column)

  • Pattern: Prominent loss of vibration + position sense in feet; sensory ataxia; Romberg positive; areflexia (distinguishes from pure posterior column lesion); Charcot joints; lightning pains
  • Causes: neurosyphilis (tabes dorsalis), diabetes, paraneoplastic

vi. Anterior Spinal Artery Syndrome

  • Pattern: Loss of pain + temperature below level; vibration + proprioception PRESERVED (posterior columns spared as they are supplied by posterior spinal arteries)
  • Associated: UMN weakness below level; bladder/bowel dysfunction
  • Causes: aortic aneurysm repair/rupture, thromboembolism, hypotension, disc prolapse

F. Brainstem Lesions

Lateral Medullary Syndrome (Wallenberg Syndrome)

  • Pattern: Classic alternating sensory loss -
    • Ipsilateral face: loss of pain + temperature (spinal trigeminal nucleus/tract)
    • Contralateral body: loss of pain + temperature (spinothalamic tract)
    • Vibration/proprioception spared
  • Associated: ipsilateral Horner's, dysphagia, hoarseness, vertigo, ataxia
  • Causes: posterior inferior cerebellar artery (PICA) occlusion - commonly due to vertebral artery atherosclerosis

Medial Medullary Syndrome

  • Pattern: Contralateral loss of vibration + proprioception (medial lemniscus affected)
  • Pain/temperature relatively spared
  • Associated: ipsilateral tongue weakness (CN XII), contralateral hemiplegia
  • Causes: anterior spinal artery branch occlusion
Patterns of sensory loss by lesion level (primary somatosensory cortex/thalamic vs. lateral pontine/medullary)

G. Thalamic Lesions (VPL/VPM Nuclei)

  • Pattern: Contralateral hemisensory loss - face + arm + leg (all modalities)
  • Face, hand, and foot often more severely affected than trunk
  • Dejerine-Roussy (thalamic pain) syndrome: after partial recovery, spontaneous burning, agonizing pain on affected side; hyperalgesia with hyperpathia; aggravated by cold, emotional disturbance, even music
  • Causes: thalamic infarct (most common - lacunar infarction), haemorrhage, tumour

H. Cortical (Parietal Lobe) Lesions

  • Pattern: Primary modalities often relatively spared; cortical sensory loss predominates:
    • Astereognosis
    • Agraphesthesia
    • Loss of two-point discrimination
    • Sensory extinction/inattention (double simultaneous stimulation - contralateral side extinguishes)
    • Sensory neglect (especially non-dominant hemisphere)
    • Impaired point localization (topagnosia)
  • Verger-Dejerine syndrome (anterior parietal): discriminative loss, preserved primary modalities
  • Dejerine-Mouzon syndrome (posterior parietal): severe impairment of primary modalities resembling thalamic lesion
  • Causes: stroke (MCA territory), tumour, trauma, MS, cortical vein thrombosis

5. Localizing Summary Table

Level of LesionPatternModalities LostLaterality
Single peripheral nerveSpecific nerve territoryAllUnilateral
PolyneuropathyGlove and stockingAll (distally)Bilateral
Nerve rootDermatomal bandAllUnilateral
GanglionopathyNon-length-dependent, proximalAllCan be bilateral/multifocal
Brown-SéquardIpsi: vibration/proprioception; Contra: pain/tempDissociatedSplit
Syringomyelia (central cord)Cape distribution, dissociatedPain/temp (touch spared)Bilateral
Anterior cordBelow levelPain/temp (vibration spared)Bilateral
Posterior columnBelow levelVibration/proprioception (pain spared)Bilateral
Complete cord transectionBelow level - sharp levelAllBilateral
Lateral medullaIpsi face + contra bodyPain/tempAlternating
Medial medullaContra bodyVibration/proprioceptionContralateral
ThalamusContra hemi (face+arm+leg)AllContralateral
Parietal cortexContra hemiCortical (discriminative)Contralateral

6. Key Practical Points

  1. Always test distally before proximally - most pathology starts distally.
  2. Proceed from abnormal toward normal when demarcating a sensory level - you will detect the boundary more precisely.
  3. Age effect: vibration is the modality most commonly reduced in normal aging, especially at the toes - do not over-interpret mildly reduced ankle vibration in elderly patients.
  4. Romberg test is a test of proprioception, not cerebellar function. The cerebellum compensates during eye opening; proprioceptive loss is only "unmasked" when vision is removed.
  5. Cortical tests (stereognosis, graphesthesia, DSS) are only meaningful if primary sensation is intact.
  6. Functional/non-organic sensory loss features: non-dermatomal; splitting the midline exactly (organic lesions do not split the midline because dermatomes overlap); inconsistent on repeated testing; patient says "no" to stimulus (instead of "I don't feel it").

Adams & Victor's Principles of Neurology 12e, pp. 174-184 | Harrison's Principles of Internal Medicine 22e, p. 3425 | Neuroanatomy through Clinical Cases 3e, pp. 314-315

Provide the downloadable pdf of the same

Reading File
Running Command

mkdir -p /tmp/workspace/sensory-exam && ls /tmp/workspace/sensory-exam/

Writing File

~/sensory-exam/generate_pdf.py

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

OUTPUT = "/tmp/workspace/sensory-exam/Sensory_Examination.pdf"

doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    rightMargin=2*cm, leftMargin=2*cm,
    topMargin=2.2*cm, bottomMargin=2.2*cm,
    title="Sensory Examination: Normal & Pathology",
    author="Orris Medical"
)

styles = getSampleStyleSheet()

# ── Custom styles ────────────────────────────────────────────────────────────
NAVY   = colors.HexColor("#1a3557")
TEAL   = colors.HexColor("#1a7a7a")
LGRAY  = colors.HexColor("#f0f4f8")
DGRAY  = colors.HexColor("#4a4a4a")
ORANGE = colors.HexColor("#c45000")
WHITE  = colors.white

title_style = ParagraphStyle("TitleStyle", parent=styles["Title"],
    fontSize=22, textColor=WHITE, alignment=TA_CENTER,
    spaceAfter=4, fontName="Helvetica-Bold", leading=28)

subtitle_style = ParagraphStyle("SubtitleStyle", parent=styles["Normal"],
    fontSize=11, textColor=colors.HexColor("#cce0ff"), alignment=TA_CENTER,
    spaceAfter=2, fontName="Helvetica", leading=14)

h1_style = ParagraphStyle("H1", parent=styles["Heading1"],
    fontSize=14, textColor=WHITE, fontName="Helvetica-Bold",
    spaceBefore=12, spaceAfter=4, leading=18,
    backColor=NAVY, leftIndent=-0.5*cm, rightIndent=-0.5*cm,
    borderPad=6)

h2_style = ParagraphStyle("H2", parent=styles["Heading2"],
    fontSize=12, textColor=NAVY, fontName="Helvetica-Bold",
    spaceBefore=8, spaceAfter=3, leading=16,
    borderPadding=(0,0,2,0))

h3_style = ParagraphStyle("H3", parent=styles["Heading3"],
    fontSize=11, textColor=TEAL, fontName="Helvetica-BoldOblique",
    spaceBefore=6, spaceAfter=2, leading=14)

body_style = ParagraphStyle("Body", parent=styles["Normal"],
    fontSize=9.5, textColor=DGRAY, fontName="Helvetica",
    spaceBefore=2, spaceAfter=2, leading=13, alignment=TA_JUSTIFY)

bullet_style = ParagraphStyle("Bullet", parent=body_style,
    leftIndent=14, bulletIndent=4, spaceBefore=1, spaceAfter=1)

small_style = ParagraphStyle("Small", parent=body_style,
    fontSize=8, textColor=colors.HexColor("#666666"), fontName="Helvetica-Oblique")

bold_inline = '<font name="Helvetica-Bold">'

def H1(txt):
    return Paragraph(f"  {txt}", h1_style)

def H2(txt):
    return Paragraph(txt, h2_style)

def H3(txt):
    return Paragraph(txt, h3_style)

def P(txt):
    return Paragraph(txt, body_style)

def B(txt):
    return Paragraph(f"<bullet>&bull;</bullet> {txt}", bullet_style)

def SP(n=6):
    return Spacer(1, n)

def HR():
    return HRFlowable(width="100%", thickness=0.5, color=colors.HexColor("#cccccc"), spaceAfter=4, spaceBefore=4)

def tbl_style(header_color=NAVY):
    return TableStyle([
        ('BACKGROUND',   (0,0), (-1,0), header_color),
        ('TEXTCOLOR',    (0,0), (-1,0), WHITE),
        ('FONTNAME',     (0,0), (-1,0), 'Helvetica-Bold'),
        ('FONTSIZE',     (0,0), (-1,0), 8.5),
        ('ROWBACKGROUNDS',(0,1),(-1,-1),[WHITE, LGRAY]),
        ('FONTNAME',     (0,1), (-1,-1), 'Helvetica'),
        ('FONTSIZE',     (0,1), (-1,-1), 8),
        ('TEXTCOLOR',    (0,1), (-1,-1), DGRAY),
        ('GRID',         (0,0), (-1,-1), 0.4, colors.HexColor("#bbbbbb")),
        ('VALIGN',       (0,0), (-1,-1), 'MIDDLE'),
        ('TOPPADDING',   (0,0), (-1,-1), 4),
        ('BOTTOMPADDING',(0,0), (-1,-1), 4),
        ('LEFTPADDING',  (0,0), (-1,-1), 6),
        ('RIGHTPADDING', (0,0), (-1,-1), 6),
        ('WORDWRAP',     (0,0), (-1,-1), True),
    ])

# ─────────────────────────── TITLE BLOCK ─────────────────────────────────────
def title_block():
    data = [[Paragraph("SENSORY EXAMINATION", title_style)],
            [Paragraph("Normal Findings · Pathological Patterns · Causes · Localisation", subtitle_style)],
            [Paragraph("Sources: Adams & Victor's Principles of Neurology 12e | Harrison's Internal Medicine 22e | Neuroanatomy through Clinical Cases 3e", subtitle_style)]]
    t = Table(data, colWidths=[17*cm])
    t.setStyle(TableStyle([
        ('BACKGROUND', (0,0), (-1,-1), NAVY),
        ('TOPPADDING',    (0,0), (-1,-1), 8),
        ('BOTTOMPADDING', (0,0), (-1,-1), 8),
        ('LEFTPADDING',   (0,0), (-1,-1), 12),
        ('RIGHTPADDING',  (0,0), (-1,-1), 12),
        ('ROUNDEDCORNERS',[6]),
    ]))
    return t

# ───────────────────────── CONTENT ───────────────────────────────────────────
story = []

story.append(title_block())
story.append(SP(14))

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 1: Anatomical Basis
# ══════════════════════════════════════════════════════════════════════════════
story.append(H1("1. Anatomical Basis — The Two Major Sensory Pathways"))
story.append(SP(4))

story.append(P("<b>Two parallel pathways carry distinct sensory modalities from periphery to cortex. Their anatomical separation is the key to understanding dissociated sensory loss patterns.</b>"))
story.append(SP(6))

pathway_data = [
    ["Pathway", "Fibers Carried", "Route", "Where it Crosses"],
    ["Posterior Column–\nMedial Lemniscus",
     "Vibration, joint position (proprioception),\ndiscriminative touch,\ntwo-point discrimination",
     "Enters dorsal horn → ascends IPSILATERALLY in posterior column (fasciculus gracilis/cuneatus) → decussates in medulla → medial lemniscus → VPL thalamus → parietal cortex (S1)",
     "Medulla (internal arcuate fibers)"],
    ["Anterolateral\n(Spinothalamic)",
     "Pain, temperature,\ncrude touch, itch",
     "Enters dorsal horn (Rexed laminae I, IV–V) → crosses via ANTERIOR COMMISSURE within 1–2 segments → ascends contralaterally → VPL thalamus → parietal cortex",
     "Spinal cord (1–2 levels above entry)"],
]
pt = Table(pathway_data, colWidths=[3.2*cm, 4.5*cm, 6.3*cm, 3*cm])
pt.setStyle(tbl_style(NAVY))
story.append(pt)
story.append(SP(6))

story.append(H2("Fiber Types and Their Sensory Roles"))
fiber_data = [
    ["Fiber Type", "Myelination", "Conduction", "Sensation Carried"],
    ["A-α (Group Ia/II)", "Heavily myelinated", "70–120 m/s", "Touch, pressure, vibration, proprioception"],
    ["A-δ (Group III)",   "Lightly myelinated", "5–30 m/s",   "Sharp/fast pain, cold temperature"],
    ["C (Group IV)",      "Unmyelinated",       "0.5–2 m/s",  "Slow/burning pain, warmth, itch, autonomic"],
]
ft = Table(fiber_data, colWidths=[3.2*cm, 3.5*cm, 3.5*cm, 6.8*cm])
ft.setStyle(tbl_style(TEAL))
story.append(ft)
story.append(SP(4))

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 2: Modalities and Normal Technique
# ══════════════════════════════════════════════════════════════════════════════
story.append(PageBreak())
story.append(H1("2. Sensory Modalities Tested — Normal Technique"))
story.append(SP(4))

story.append(H2("A. Primary Modalities"))

story.append(H3("i. Light Touch"))
story.append(B("Tool: Wisp of cotton or examiner's fingertip"))
story.append(B("Technique: Single gentle touches; patient says 'yes' with eyes closed"))
story.append(B("Normal: Detected equally bilaterally; moving stimulus more sensitive than stationary"))
story.append(B("Von Frey hair used for quantitative threshold testing in research"))
story.append(SP(4))

story.append(H3("ii. Pain (Superficial)"))
story.append(B("Tool: New, disposable sharp pin"))
story.append(B("Technique: Ask patient to report 'sharpness', not mere contact; ~1 stimulus/second; not over the same spot (summation causes false hyperalgesia)"))
story.append(B("Useful comparison: ask patient to rate sensation on 0–10 scale in two areas simultaneously"))
story.append(B("Abnormal area boundary: demarcate by moving from numb → normal region"))
story.append(SP(4))

story.append(H3("iii. Temperature"))
story.append(B("Tool: Tuning fork (one side rubbed warm, apply alternating sides); or test tubes with warm (40–45°C) and cold (5–10°C) water"))
story.append(B("Technique: Binary choice — 'warm or cold?' Useful for corroborating a zone of hypalgesia"))
story.append(B("Normal: Correct identification of warm vs. cold everywhere"))
story.append(B("Clinical note: Cold carried by A-δ fibers; warmth by C fibers — differentially affected in small-fiber neuropathies"))
story.append(SP(4))

story.append(H3("iv. Vibration"))
story.append(B("Tool: 128 Hz tuning fork applied to distal bony prominences"))
story.append(B("Sites tested (distal → proximal): Great toe → medial malleolus → patella → anterior iliac crest; Index finger → wrist → elbow → shoulder"))
story.append(B("Technique: Compare patient's perception duration to examiner's own; quantitative tuning forks (0–8 scale) available"))
story.append(B("Normal: Symmetric bilaterally; perceived at least as long as the examiner"))
story.append(B("<b>Key pattern:</b> Loss at ankle but preserved at knee → length-dependent peripheral neuropathy"))
story.append(B("<b>Key pattern:</b> Loss at iliac crest level → spinal cord lesion at that level"))
story.append(B("Age effect: Mildly reduced vibration at great toe is normal in elderly — do not over-interpret"))
story.append(SP(4))

story.append(H3("v. Joint Position Sense (Proprioception)"))
story.append(B("Technique: Grasp digit LATERALLY (not dorsally — to avoid pressure cues); move 1–2 mm up or down; patient reports direction with eyes closed"))
story.append(B("Start distally (distal phalanx of great toe or index finger); move proximally if abnormal"))
story.append(B("Normal: Even 1–2 mm excursions correctly identified"))
story.append(SP(4))

story.append(H3("vi. Romberg Test (Proprioception)"))
story.append(B("Method: Patient stands, feet as close together as needed for balance, eyes open; then closes eyes"))
story.append(B("<b>Positive Romberg</b>: Loses balance on eye closure = proprioceptive loss (NOT cerebellar)"))
story.append(B("Cerebellar patients are unsteady with eyes OPEN; proprioceptive loss is unmasked only by removing visual compensation"))
story.append(SP(8))

story.append(H2("B. Cortical / Discriminative Sensation"))
story.append(P("<i>Only meaningful when primary modalities are confirmed to be intact. Requires intact parietal cortex integration.</i>"))
story.append(SP(4))

cortical_data = [
    ["Test", "Technique", "Normal", "Abnormality Name"],
    ["Two-point discrimination",
     "Compass applied simultaneously; find minimum distance perceived as two distinct points",
     "Fingertip: 3–5 mm\nPalm: 8–15 mm\nDorsum hand/foot: 20–30 mm\nTrunk: 4–7 cm",
     "Widened threshold"],
    ["Stereognosis",
     "Patient identifies object by touch alone (coin, key, paperclip) — eyes closed",
     "Correct identification",
     "Astereognosis"],
    ["Graphesthesia",
     "Examiner writes number or letter on skin; patient identifies",
     "Correct identification",
     "Agraphesthesia"],
    ["Double Simultaneous Stimulation (DSS)",
     "Touch both hands simultaneously; patient identifies which side(s) touched",
     "Both sides perceived",
     "Extinction of contralateral side"],
    ["Point Localization (Topognosis)",
     "Touch a point; patient points to it with eyes closed",
     "Accurate localization",
     "Topagnosia"],
]
ct = Table(cortical_data, colWidths=[3.5*cm, 4.5*cm, 3.5*cm, 3.5*cm])
ct.setStyle(tbl_style(TEAL))
story.append(ct)
story.append(SP(8))

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 3: Normal vs Abnormal Findings
# ══════════════════════════════════════════════════════════════════════════════
story.append(PageBreak())
story.append(H1("3. Normal vs. Abnormal Findings"))
story.append(SP(4))

story.append(H2("A. Quantitative Terms for Sensory Findings"))
quant_data = [
    ["Prefix/Term", "Meaning"],
    ["Anesthesia / Analgesia / Thermoanesthesia", "Complete absence of touch / pain / temperature"],
    ["Hypesthesia / Hypalgesia",                  "Reduced sensation of touch / pain"],
    ["Hyperesthesia / Hyperalgesia",              "Exaggerated perception of touch / pain"],
    ["Allodynia",                                 "Pain produced by a normally non-painful stimulus (e.g., light touch causes pain)"],
    ["Dysesthesia",                               "Unpleasant abnormal sensation (spontaneous or evoked)"],
    ["Paresthesia",                               "Spontaneous tingling, pins-and-needles (ectopic discharge in large fibers)"],
    ["Hyperpathia",                               "Exaggerated pain response with raised threshold + persistence/spread after stimulus"],
    ["Anesthesia dolorosa",                       "Pain in an area that is objectively numb (e.g., post-nerve injury)"],
    ["Dissociated sensory loss",                  "Loss of one modality (e.g., pain/temperature) with preservation of another (e.g., touch/vibration) — hallmark of syringomyelia or anterior cord syndrome"],
]
qt = Table(quant_data, colWidths=[7*cm, 10*cm])
qt.setStyle(tbl_style(ORANGE))
story.append(qt)
story.append(SP(8))

story.append(H2("B. Sensory Symptoms and Their Fiber Basis"))
fiber_sx = [
    ["Symptom", "Fiber Type Involved", "Example Cause"],
    ["Tingling / buzzing paresthesia",    "Large myelinated (A-α); posterior columns", "Nerve compression, B12 deficiency, MS"],
    ["Burning pain",                      "C fibers (unmyelinated)",                   "Small-fiber neuropathy, diabetes, CRPS"],
    ["Sharp / lancinating pain",          "A-δ fibers",                                "Tabes dorsalis, root compression"],
    ["Band-like sensation on trunk/limb", "Large fibers — posterior column disease",   "MS, cervical spondylosis, B12 deficiency"],
    ["Pseudocramp (no actual contraction)","Muscle proprioceptors",                    "Posterior column disease"],
    ["Hot/cold reversal (allodynia to temp)","A-δ + C fibers",                        "Ciguatera poisoning, oxaliplatin neuropathy"],
    ["Vibratory paresthesias",            "Posterior column / cerebral disease",       "MS, thalamic lesion (rare)"],
    ["Lhermitte's sign (electric shock on neck flexion)", "Posterior columns (cervical)", "MS, cervical cord compression, subacute combined degeneration"],
]
fs = Table(fiber_sx, colWidths=[4.5*cm, 4.5*cm, 8*cm])
fs.setStyle(tbl_style(NAVY))
story.append(fs)

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 4: Pathological Patterns and Causes
# ══════════════════════════════════════════════════════════════════════════════
story.append(PageBreak())
story.append(H1("4. Pathological Patterns and Their Causes"))
story.append(SP(4))

story.append(H2("A. Peripheral Nerve (Mononeuropathy)"))
story.append(P("<b>Pattern:</b> Sensory loss in the specific anatomical territory of ONE nerve. All modalities affected within that territory. Associated with LMN-type weakness and reduced reflex in that distribution."))
story.append(SP(3))
story.append(B("<b>Median nerve</b>: Lateral 3½ fingers (thumb, index, middle, half ring) + thenar eminence — carpal tunnel syndrome (commonest entrapment), trauma"))
story.append(B("<b>Ulnar nerve</b>: Medial 1½ fingers (little + half ring) + hypothenar — cubital tunnel, leprosy"))
story.append(B("<b>Radial nerve</b>: Dorsal lateral hand/wrist drop — 'Saturday night palsy' (compression in spiral groove)"))
story.append(B("<b>Common peroneal nerve</b>: Dorsum foot + lateral leg — foot drop — fibular head compression"))
story.append(B("<b>Lateral femoral cutaneous nerve</b>: Lateral thigh burning/numbness — meralgia paresthetica"))
story.append(B("<b>Causes:</b> Compression, trauma, diabetes, vasculitis, leprosy (cooler skin areas selectively affected), infiltration (lymphoma, amyloid)"))
story.append(SP(6))

story.append(H2("B. Polyneuropathy (Peripheral Neuropathy)"))
story.append(P("<b>Pattern:</b> Bilateral symmetric 'glove and stocking' distribution — distal-to-proximal gradient (length-dependent). Longest fibers fail first. Vibration lost first at great toes; ankle jerks lost first."))
story.append(SP(3))
poly_causes = [
    ["Category", "Causes"],
    ["Metabolic / Endocrine",  "Diabetes mellitus (commonest worldwide), hypothyroidism, uraemia (renal failure), hepatic failure, porphyria"],
    ["Nutritional / Toxic",    "Vitamin B12 deficiency, thiamine (B1) deficiency, alcohol excess, pyridoxine (B6) excess, heavy metals (lead, arsenic, thallium)"],
    ["Drugs",                  "Vincristine, cisplatin, taxanes, metronidazole, isoniazid (without B6), amiodarone, nitrofurantoin"],
    ["Inflammatory / Immune",  "Guillain-Barré syndrome (acute demyelinating), CIDP (chronic), multifocal motor neuropathy, vasculitis, sarcoidosis"],
    ["Hereditary",             "Charcot-Marie-Tooth (CMT) — commonest hereditary neuropathy; hereditary amyloidosis (TTR)"],
    ["Infection",              "HIV, leprosy, Lyme disease, diphtheria"],
    ["Paraprotein / Infiltrative", "Monoclonal gammopathy (MGUS, myeloma), amyloidosis (AL), cryoglobulinaemia"],
    ["Paraneoplastic",         "Anti-Hu (ANNA-1) antibody — small cell lung carcinoma; sensory neuronopathy"],
]
pct = Table(poly_causes, colWidths=[4.5*cm, 12.5*cm])
pct.setStyle(tbl_style(TEAL))
story.append(pct)
story.append(SP(6))

story.append(H2("C. Radiculopathy (Nerve Root)"))
story.append(P("<b>Pattern:</b> Dermatomal band or strip of sensory loss. Unilateral. Radicular pain radiates from spine. Reflex loss limited to affected root."))
story.append(SP(3))
story.append(B("Lumbar: L4 — medial leg/foot, knee jerk reduced; L5 — dorsum foot/big toe, no specific reflex; S1 — lateral foot/sole, ankle jerk reduced"))
story.append(B("Cervical: C5 — shoulder/lateral arm; C6 — thumb/index, biceps jerk reduced; C7 — middle finger, triceps jerk reduced; C8 — ring/little fingers"))
story.append(B("<b>Causes:</b> Intervertebral disc herniation (L4/5/S1 lumbar; C5/6/7 cervical), spondylosis/foraminal stenosis, herpes zoster (also produces vesicles in that dermatome), tumour, epidural abscess, arachnoiditis"))
story.append(SP(6))

story.append(H2("D. Dorsal Root Ganglionopathy (Sensory Neuronopathy)"))
story.append(P("<b>Pattern:</b> Non-length-dependent — proximal areas ALSO affected early. ALL modalities affected (cell body destroyed). Prominent sensory ataxia; Romberg positive; areflexia. May be asymmetric, multifocal (pseudoataxic)."))
story.append(SP(3))
story.append(B("<b>Paraneoplastic:</b> Anti-Hu antibody (ANNA-1) — small cell lung cancer"))
story.append(B("<b>Sjögren's syndrome:</b> Immune-mediated destruction of dorsal root ganglia"))
story.append(B("<b>Drugs:</b> Cisplatin, carboplatin, pyridoxine (B6) toxicity"))
story.append(B("<b>Infectious:</b> Varicella-zoster virus ganglionitis"))
story.append(B("<b>Idiopathic</b>"))
story.append(SP(8))

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 5: Spinal Cord Syndromes
# ══════════════════════════════════════════════════════════════════════════════
story.append(PageBreak())
story.append(H1("5. Spinal Cord Sensory Syndromes"))
story.append(SP(4))

cord_data = [
    ["Syndrome", "Lesion Site", "Sensory Pattern", "Other Features", "Common Causes"],
    ["Complete Transverse\nMyelopathy",
     "All tracts at one level",
     "ALL modalities lost BELOW level\n(sharp sensory level on trunk;\nhyperaesthesia at upper margin)",
     "UMN weakness below level\nBladder/bowel dysfunction\nAutonomic disturbance",
     "Trauma, MS, transverse myelitis,\ntumour compression, epidural abscess,\nhaematoma, cord infarction"],
    ["Brown-Séquard\n(Hemisection)",
     "Ipsilateral half-cord",
     "IPSILATERAL: loss of vibration +\nproprioception (posterior column)\nCONTRALATERAL: loss of pain +\ntemperature, 2–3 levels below\n(spinothalamic — already crossed)",
     "Ipsilateral UMN weakness\nbelow lesion",
     "Stab wound (classic), MS,\ntumour, radiation, disc herniation"],
    ["Syringomyelic\n(Central Cord)",
     "Anterior commissure\n(crossing spinothalamic fibers)",
     "BILATERAL loss of pain +\ntemperature in 'cape' distribution\n(neck, shoulders, arms)\nTouch + proprioception PRESERVED\n= DISSOCIATED sensory loss",
     "Segmental amyotrophy\nReflex loss in affected segments\nLater: long tract signs",
     "Syringomyelia (commonest cervical),\nintramedullary tumour (ependymoma,\nastrocytoma), trauma, haemorrhage"],
    ["Posterior Column",
     "Dorsal columns\n(fasciculus gracilis/cuneatus)",
     "BILATERAL loss of vibration +\nproprioception below level\nPain/temperature SPARED\nSensory ataxia; Romberg positive\nParaesthesias; Lhermitte's sign",
     "Tendon reflexes PRESERVED\n(unlike tabetic — key distinction)",
     "MS (most common), subacute combined\ndegeneration (B12 deficiency),\ncervical spondylotic myelopathy,\nFriedreich's ataxia"],
    ["Tabetic Syndrome",
     "Posterior roots +\nposterior columns",
     "Same as posterior column but\nAREFLEXIA (roots involved)\nLightning/lancinating pains\nCharcot joints; Romberg positive",
     "Areflexia (distinguishes from\npure posterior column lesion)",
     "Tabes dorsalis (neurosyphilis),\ndiabetes, paraneoplastic"],
    ["Anterior Spinal\nArtery Syndrome",
     "Anterior 2/3 of cord\n(posterior columns spared —\nsupplied by posterior\nspinal arteries)",
     "BILATERAL loss of pain +\ntemperature below level\nVibration + proprioception\nPRESERVED",
     "UMN weakness below level\nBladder/bowel dysfunction\nOnset sudden (vascular)",
     "Aortic surgery/aneurysm,\nthromboembolism, atherosclerosis,\nhypotension, anterior disc prolapse"],
]
cord_t = Table(cord_data, colWidths=[2.8*cm, 2.8*cm, 4.2*cm, 3.5*cm, 3.7*cm])
cord_t.setStyle(tbl_style(NAVY))
story.append(cord_t)
story.append(SP(8))

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 6: Brainstem
# ══════════════════════════════════════════════════════════════════════════════
story.append(H1("6. Brainstem Sensory Syndromes"))
story.append(SP(4))

bs_data = [
    ["Syndrome", "Lesion", "Sensory Pattern", "Associated Features", "Causes"],
    ["Lateral Medullary\n(Wallenberg) Syndrome",
     "Lateral medulla — spinothalamic tract + spinal trigeminal nucleus/tract",
     "ALTERNATING pattern:\nIPSILATERAL FACE: pain + temp loss\n(spinal trigeminal nucleus)\nCONTRALATERAL BODY: pain + temp loss\n(spinothalamic tract)\nVibration/proprioception SPARED",
     "Ipsilateral Horner's syndrome\nDysphagia, hoarseness (CN IX, X)\nIPSILATERAL ataxia (cerebellar)\nVertigo, nystagmus (vestibular)\nHiccups",
     "PICA occlusion (most common)\nVertebral artery atherosclerosis\nor dissection"],
    ["Medial Medullary\nSyndrome",
     "Medial medulla — medial lemniscus + pyramid + CN XII",
     "CONTRALATERAL BODY:\nVibration + proprioception loss\n(medial lemniscus)\nPain/temperature relatively spared",
     "Ipsilateral tongue deviation\n(CN XII palsy)\nContralateral hemiplegia\n(pyramidal)",
     "Anterior spinal artery branch\nocclusion; vertebral artery\nthrombosis"],
    ["Pontine Lesion\n(Lateral Pons)",
     "Lateral pons — spinothalamic + ipsilateral trigeminal",
     "Same alternating pattern as lateral medullary — ipsilateral facial + contralateral body pain/temp loss",
     "Ipsilateral CN VI, VII palsy\nAtaxia, nystagmus",
     "Infarction, MS, tumour"],
    ["Midbrain / Upper Pons",
     "Less common — contralateral somatosensory deficits including face, arm and leg",
     "Contralateral hemisensory loss (all modalities — face + body)",
     "Associated motor, CN III/IV palsy depending on exact location",
     "Infarction, tumour, MS"],
]
bs_t = Table(bs_data, colWidths=[3*cm, 3.5*cm, 4.5*cm, 3*cm, 3*cm])
bs_t.setStyle(tbl_style(TEAL))
story.append(bs_t)
story.append(SP(8))

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 7: Thalamus and Cortex
# ══════════════════════════════════════════════════════════════════════════════
story.append(PageBreak())
story.append(H1("7. Thalamic and Cortical Lesions"))
story.append(SP(4))

story.append(H2("A. Thalamic Lesions (VPL / VPM Nuclei)"))
story.append(P("<b>Pattern:</b> Contralateral hemisensory loss — face + arm + leg (all modalities). Face, hand (especially lips and fingertips), and foot more severely affected than trunk. Sometimes present without motor deficit (pure sensory stroke — lacunar)."))
story.append(SP(4))
story.append(P("<b>Dejerine-Roussy Syndrome (Thalamic Pain Syndrome):</b> After partial thalamic recovery, spontaneous burning/agonizing pain develops on the affected side. Paradox: elevated pain threshold (stronger stimulus needed to evoke pain — hypalgesia) combined with exaggerated, lingering response to stimuli that do get through (hyperpathia). Cold stimuli, emotion, loud noise, even music may aggravate. One of the most distressing pain syndromes in neurology."))
story.append(SP(4))
story.append(B("<b>Causes:</b> Thalamic infarction (lacunar — most common), thalamic haemorrhage, tumour, MS, arteriovenous malformation"))
story.append(SP(8))

story.append(H2("B. Parietal Lobe (Cortical) Lesions"))
story.append(P("<b>Primary modalities are often relatively PRESERVED</b> (unless lesion is extensive). The hallmark is loss of <b>discriminative (cortical) sensation</b>:"))
story.append(SP(3))

cortical_syndromes = [
    ["Syndrome / Feature", "Pattern", "Lesion Location", "Causes"],
    ["Verger-Dejerine Syndrome\n(Anterior Parietal)",
     "Discriminative loss predominates: astereognosis, agraphesthesia, widened 2-point threshold, topagnosia, impaired position sense.\nPrimary modalities relatively preserved.",
     "Postcentral gyrus (S1)\nAnterior parietal lobe",
     "Stroke (MCA), tumour, trauma, MS"],
    ["Dejerine-Mouzon Syndrome\n(Posterior Parietal)",
     "SEVERE impairment of primary modalities (pain, thermal, tactile) — simulates thalamic lesion.\nVibratory sense relatively spared.\nMotor variable.",
     "Posterior parietal lobe\n(more extensive/deep lesion)",
     "Stroke, tumour"],
    ["Sensory Extinction / Inattention",
     "With bilateral simultaneous stimulation — contralateral side EXTINGUISHES.\nEach side perceived correctly when tested alone.\nSensory neglect (especially non-dominant hemisphere lesion).",
     "Parietal lobe (often\nnon-dominant hemisphere)",
     "Stroke, tumour, TBI"],
    ["Cortical Sensory Loss\n(Pure)",
     "All primary modalities intact.\nAstereognosis, agraphesthesia, impaired DSS only.",
     "Isolated parietal cortex S1",
     "Small cortical infarct, focal MS"],
]
cs_t = Table(cortical_syndromes, colWidths=[3.5*cm, 5.5*cm, 3.5*cm, 4.5*cm])
cs_t.setStyle(tbl_style(ORANGE))
story.append(cs_t)
story.append(SP(8))

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 8: Master Localisation Table
# ══════════════════════════════════════════════════════════════════════════════
story.append(PageBreak())
story.append(H1("8. Master Localisation Summary Table"))
story.append(SP(4))

master_data = [
    ["Level of Lesion", "Sensory Pattern", "Modalities Lost", "Side Affected", "Key Associated Features"],
    ["Single Peripheral Nerve\n(Mononeuropathy)",
     "Specific nerve territory",
     "All modalities in territory",
     "Unilateral",
     "LMN weakness; reflex loss in that nerve's distribution"],
    ["Polyneuropathy",
     "Glove and stocking\n(bilateral, distal > proximal)",
     "All; may be preferential\n(large fiber or small fiber)",
     "Bilateral, symmetric",
     "Hyporeflexia/areflexia (ankle jerks first); length-dependent vibration loss"],
    ["Nerve Root\n(Radiculopathy)",
     "Dermatomal band",
     "All in dermatome",
     "Unilateral",
     "Radicular pain; reflex loss at that root level"],
    ["Ganglionopathy",
     "Non-length-dependent;\nproximal areas also affected",
     "All modalities",
     "Bilateral or multifocal",
     "Prominent sensory ataxia; areflexia; no motor weakness"],
    ["Brown-Séquard\n(Hemisection)",
     "Ipsi: vibration/proprioception\nContra: pain/temp (2–3 levels below)",
     "Dissociated (split)",
     "Crossed (split left-right)",
     "Ipsilateral UMN weakness; ipsilateral posterior column + contralateral spinothalamic"],
    ["Syringomyelia\n(Central Cord)",
     "Cape/shawl distribution\nBilateral pain/temp loss",
     "Pain + temperature\n(Touch SPARED = dissociated)",
     "Bilateral",
     "Segmental amyotrophy; dissociated sensory loss is hallmark"],
    ["Anterior Cord Syndrome",
     "Below level\nBilateral pain/temp loss",
     "Pain + temperature\n(Vibration/proprioception SPARED)",
     "Bilateral",
     "Sudden onset; bilateral UMN weakness; bladder/bowel loss"],
    ["Posterior Column",
     "Below level",
     "Vibration + proprioception\n(Pain/temp SPARED)",
     "Bilateral",
     "Sensory ataxia; Romberg positive; Lhermitte's sign; reflexes preserved"],
    ["Complete Cord Transection",
     "Sharp level on trunk —\nall below level",
     "ALL modalities",
     "Bilateral",
     "Spinal shock; UMN signs below; autonomic dysfunction"],
    ["Lateral Medulla\n(Wallenberg)",
     "Alternating: ipsi face +\ncontra body",
     "Pain + temperature\n(Vibration/proprioception SPARED)",
     "Crossed / alternating",
     "Ipsilateral Horner's, dysphagia, ataxia, vertigo"],
    ["Medial Medulla",
     "Contra body",
     "Vibration + proprioception\n(Pain/temp SPARED)",
     "Contralateral",
     "Ipsilateral CN XII palsy; contralateral hemiplegia"],
    ["Thalamus (VPL/VPM)",
     "Contralateral hemisphere\n(face + arm + leg)",
     "ALL modalities\n(position sense most affected)",
     "Contralateral",
     "Dejerine-Roussy pain syndrome; may occur without hemiparesis (pure sensory stroke)"],
    ["Parietal Cortex (S1)",
     "Contralateral hemisphere\nDiscriminative loss predominates",
     "Cortical sensory loss\n(stereognosis, graphesthesia, DSS, 2-point)",
     "Contralateral",
     "Sensory extinction; neglect (non-dominant); primary modalities relatively preserved"],
]
master_t = Table(master_data, colWidths=[3*cm, 3.5*cm, 3.5*cm, 2.5*cm, 4.5*cm])
master_t.setStyle(tbl_style(NAVY))
story.append(master_t)

# ══════════════════════════════════════════════════════════════════════════════
# SECTION 9: Practical Examination Tips
# ══════════════════════════════════════════════════════════════════════════════
story.append(PageBreak())
story.append(H1("9. Practical Examination Tips & Pitfalls"))
story.append(SP(6))

tips = [
    ("<b>Test distally before proximally</b> — most pathology starts distally; start at feet, move upward.", NAVY),
    ("<b>Demarcate from abnormal toward normal</b> — you will detect the boundary of sensory loss more precisely moving from numb toward normal area.", TEAL),
    ("<b>Romberg vs. cerebellar:</b> Romberg tests proprioception, not cerebellar function. Cerebellar patients are unsteady with eyes OPEN. Romberg is positive only when vision is removed (proprioceptive loss).", NAVY),
    ("<b>Cortical tests require intact primary sensation</b> — stereognosis, graphesthesia, and DSS are only interpretable if touch is intact first.", TEAL),
    ("<b>Age effect on vibration:</b> Mildly reduced vibration at the great toe/ankle is normal in elderly patients due to age-related large fiber loss. Compare symmetry and compare with knees before concluding neuropathy.", NAVY),
    ("<b>Double simultaneous stimulation</b> is an excellent quick screen for parietal lesion — patient may miss contralateral side when tested simultaneously even if they detect it correctly when tested alone (extinction).", TEAL),
    ("<b>Functional (non-organic) sensory loss patterns:</b> Exact midline splitting (organic lesions don't split the midline — dermatomes overlap); non-dermatomal distribution; inconsistent on repetition; patient says 'no' to stimulus (instead of 'I can't feel it').", ORANGE),
    ("<b>Sensory level on trunk = spinal cord lesion</b> — demarcate using pin and vibration over dorsal vertebral spines + iliac crests. The actual cord lesion is typically 1–2 segments ABOVE the sensory level.", NAVY),
    ("<b>Dissociated sensory loss</b> (pain/temp lost, touch preserved) = either syringomyelia (central cord) or anterior cord syndrome. The opposite (touch lost, pain/temp preserved) = posterior cord lesion.", TEAL),
    ("<b>Glove-and-stocking + areflexia</b> = peripheral neuropathy until proven otherwise.", ORANGE),
]
for txt, col in tips:
    tip_t = Table([[Paragraph(txt, ParagraphStyle("tip", parent=body_style, fontSize=9.5, leading=13))]],
                  colWidths=[17*cm])
    tip_t.setStyle(TableStyle([
        ('BACKGROUND',    (0,0), (-1,-1), colors.HexColor("#f8f9fa")),
        ('LEFTPADDING',   (0,0), (-1,-1), 10),
        ('RIGHTPADDING',  (0,0), (-1,-1), 10),
        ('TOPPADDING',    (0,0), (-1,-1), 6),
        ('BOTTOMPADDING', (0,0), (-1,-1), 6),
        ('LINEAFTER',     (0,0), (0,-1), 4, col),
        ('LINEBEFORE',    (0,0), (0,-1), 4, col),
        ('ROUNDEDCORNERS', [4]),
    ]))
    story.append(tip_t)
    story.append(SP(5))

story.append(SP(10))
HR2 = HRFlowable(width="100%", thickness=1, color=NAVY, spaceAfter=6, spaceBefore=6)
story.append(HR2)
story.append(Paragraph(
    "Sources: Adams &amp; Victor's Principles of Neurology 12e (pp. 174–184) | Harrison's Principles of Internal Medicine 22e (p. 3425) | Neuroanatomy through Clinical Cases 3e (pp. 314–315)",
    small_style))
story.append(Paragraph("Generated by Orris Medical AI | July 2026", small_style))

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

cd /tmp/workspace/sensory-exam && python generate_pdf.py 2>&1

Running Command

ls -lh /tmp/workspace/sensory-exam/Sensory_Examination.pdf

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

Sensory Examination

PDF Document · PDF

What's inside (9 structured sections, ~27 KB):
  1. Anatomical Basis - Two major pathways (posterior column-medial lemniscus vs. anterolateral/spinothalamic) with fiber type table
  2. Sensory Modalities & Normal Technique - Light touch, pain, temperature, vibration, joint position sense, Romberg test, and all cortical tests (stereognosis, graphesthesia, DSS, two-point discrimination)
  3. Normal vs. Abnormal Findings - Terminology table (anesthesia, hypesthesia, allodynia, dysesthesia, paresthesia, dissociated loss, etc.) + symptom-to-fiber mapping
  4. Pathological Patterns & Causes - Mononeuropathy, polyneuropathy (with full causes table), radiculopathy, ganglionopathy
  5. Spinal Cord Syndromes - Complete transection, Brown-Séquard, syringomyelia, posterior column, tabetic, anterior spinal artery syndrome
  6. Brainstem Syndromes - Wallenberg (lateral medullary), medial medullary, pontine, midbrain
  7. Thalamic & Cortical Lesions - Dejerine-Roussy syndrome, Verger-Dejerine, Dejerine-Mouzon, sensory extinction/neglect
  8. Master Localisation Table - All 13 levels in one quick-reference table
  9. Practical Tips & Pitfalls - 10 high-yield clinical pearls (including functional sensory loss identification)
This is a shared conversation. Sign in to Orris to start your own chat.