Learn about Parkinsonism

I'll start by reading the medical library skill, then search for comprehensive information on Parkinsonism in parallel.
Searching sources...
Reading File
Now let me search for Parkinsonism across multiple dimensions in parallel:
Finding Sources
Finding Sources
Searching Images

Parkinson disease pathology Lewy bodies substantia nigra

This composite image presents neuropathological findings from two siblings with Parkinson’s disease. Panel A contains macroscopic brain specimens: images 1 and 2 show the substantia nigra and cerebellum with evidence of depigmentation; images 3 and 4 display coronal sections through the basal ganglia and cortical regions, demonstrating mild ventricular enlargement and cortical atrophy. Panel B presents microscopic immunohistochemistry for alpha-synuclein pathology. Images B1 and B3 illustrate the substantia nigra, highlighting dark-stained Lewy neurites (thread-like processes) and classical Lewy bodies (rounded cytoplasmic inclusions). Images B2 and B4 show cortical sections containing cortical Lewy bodies, which appear as less defined, round inclusions within neuronal soma. The pathology demonstrates the characteristic widespread distribution of alpha-synuclein aggregates in genetic or familial Parkinson’s disease, involving both brainstem and cortical regions. This visual resource is intended for educational use in neurology and pathology to distinguish between macroscopic neurodegeneration and microscopic proteinaceous inclusions.

This composite image presents neuropathological findings from two siblings with Parkinson’s disease. Panel A contains macroscopic brain specimens: images 1 and 2 show the substantia nigra and cerebellum with evidence of depigmentation; images 3 and 4 display coronal sections through the basal ganglia and cortical regions, demonstrating mild ventricular enlargement and cortical atrophy. Panel B presents microscopic immunohistochemistry for alpha-synuclein pathology. Images B1 and B3 illustrate the substantia nigra, highlighting dark-stained Lewy neurites (thread-like processes) and classical Lewy bodies (rounded cytoplasmic inclusions). Images B2 and B4 show cortical sections containing cortical Lewy bodies, which appear as less defined, round inclusions within neuronal soma. The pathology demonstrates the characteristic widespread distribution of alpha-synuclein aggregates in genetic or familial Parkinson’s disease, involving both brainstem and cortical regions. This visual resource is intended for educational use in neurology and pathology to distinguish between macroscopic neurodegeneration and microscopic proteinaceous inclusions.

Educational medical illustration titled 'Neurodegenerative Diseases and Types of Neurons Affected' featuring a sagittal cross-section of the human brain alongside specialized neuronal diagrams. The brain section highlights key anatomical areas susceptible to degeneration: the striatum (green) for Huntington’s Disease (HD), cortical and hippocampal regions (pink neurons) for Alzheimer’s Disease (AD), the substantia nigra and midbrain (red) for Parkinson’s Disease (PD), and the brainstem and spinal pathways (orange) for Amyotrophic Lateral Sclerosis (ALS). The diagram categorizes specific neuronal vulnerabilities: Medium Spiny Neurons in HD, Pyramidal neurons in AD, and Motor neuron degeneration in ALS. For Parkinson's Disease, detailed insets illustrate the pathophysiology of dopaminergic neurons, showing the impairment and loss of melanated cells, alpha-synuclein protein aggregation, and the formation of Lewy bodies. The visual serves as a summary of the neuroanatomical localization and cellular pathology characteristic of major neurodegenerative disorders.

Educational medical illustration titled 'Neurodegenerative Diseases and Types of Neurons Affected' featuring a sagittal cross-section of the human brain alongside specialized neuronal diagrams. The brain section highlights key anatomical areas susceptible to degeneration: the striatum (green) for Huntington’s Disease (HD), cortical and hippocampal regions (pink neurons) for Alzheimer’s Disease (AD), the substantia nigra and midbrain (red) for Parkinson’s Disease (PD), and the brainstem and spinal pathways (orange) for Amyotrophic Lateral Sclerosis (ALS). The diagram categorizes specific neuronal vulnerabilities: Medium Spiny Neurons in HD, Pyramidal neurons in AD, and Motor neuron degeneration in ALS. For Parkinson's Disease, detailed insets illustrate the pathophysiology of dopaminergic neurons, showing the impairment and loss of melanated cells, alpha-synuclein protein aggregation, and the formation of Lewy bodies. The visual serves as a summary of the neuroanatomical localization and cellular pathology characteristic of major neurodegenerative disorders.

This medical schematic diagram illustrates the Braak staging model of alpha-synuclein pathology progression in Parkinson's disease. The image features a sagittal view of the human brain overlaid with color-coded regions and directional arrows to depict the caudo-rostral spread of Lewy bodies and Lewy neurites. The progression is categorized into six stages starting from a blue arrow representing the peripheral and enteric nervous systems. The pathological ascent is shown sequentially through the medulla oblongata (orange), the pontine tegmentum (green), and into the basal midbrain and forebrain (pink), which includes the substantia nigra. From these subcortical structures, yellow arrows indicate the spread to the temporal mesocortex and allocortex (light yellow), eventually reaching the neocortex (grey) as shown by white arrows. This visual model highlights how neurodegeneration moves from the lower brainstem to higher cortical regions, correlating with the clinical transition from motor symptoms to cognitive dysfunction and dementia.

This medical schematic diagram illustrates the Braak staging model of alpha-synuclein pathology progression in Parkinson's disease. The image features a sagittal view of the human brain overlaid with color-coded regions and directional arrows to depict the caudo-rostral spread of Lewy bodies and Lewy neurites. The progression is categorized into six stages starting from a blue arrow representing the peripheral and enteric nervous systems. The pathological ascent is shown sequentially through the medulla oblongata (orange), the pontine tegmentum (green), and into the basal midbrain and forebrain (pink), which includes the substantia nigra. From these subcortical structures, yellow arrows indicate the spread to the temporal mesocortex and allocortex (light yellow), eventually reaching the neocortex (grey) as shown by white arrows. This visual model highlights how neurodegeneration moves from the lower brainstem to higher cortical regions, correlating with the clinical transition from motor symptoms to cognitive dysfunction and dementia.

This composite educational graphic presents multi-modal diagnostic data investigating 18F-AV-1451 (tau PET tracer) retention in neurodegenerative synucleinopathies compared to Alzheimer’s Disease (AD).

This composite educational graphic presents multi-modal diagnostic data investigating 18F-AV-1451 (tau PET tracer) retention in neurodegenerative synucleinopathies compared to Alzheimer’s Disease (AD).

Excellent results. Now let me read the key textbook sections in parallel:
Reading File
Reading File
Finding Sources
Finding Sources
Searching Images

Parkinsonism clinical features tremor rigidity bradykinesia posture

Good data. Now let me read the key neurology block for the full Parkinsonism section and also get pharmacology details:
Let me get more details on the causes/classification and pharmacology from Harrison's and Katzung:
Reading File
Reading File
Searching PubMed

Parkinson disease management guidelines

I now have rich data from multiple authoritative sources. Let me compile the comprehensive answer:
Loading Image
Loading Image
I now have comprehensive information to deliver a thorough, well-structured answer on Parkinsonism. Here it is:

Parkinsonism - A Comprehensive Overview

1. Definition and the TRAP Acronym

Parkinsonism is a clinical syndrome defined by a combination of six cardinal motor features:
  1. Tremor at rest
  2. Rigidity
  3. Akinesia / bradykinesia
  4. Postural instability
  5. Flexed posture
  6. Freezing (motor blocks)
The four dominant features are captured by the acronym TRAP (Tremor, Rigidity, Akinesia, Postural instability). These arise from dysfunction of the basal ganglia, specifically depletion of dopaminergic neurons in the substantia nigra pars compacta (SNc).
  • Bradley and Daroff's Neurology in Clinical Practice

2. Classification - Causes of Parkinsonism

Parkinsonism is not a single disease but a syndrome with many causes:
CategoryExamples
Parkinson's Disease (PD)Sporadic (most common), Genetic (SNCA, LRRK2, Parkin, PINK1, DJ-1)
Atypical ParkinsonismMultiple System Atrophy (MSA-c, MSA-p), Progressive Supranuclear Palsy (PSP), Corticobasal Syndrome
Secondary ParkinsonismDrug-induced, Vascular, Tumor, Infection, Normal-pressure hydrocephalus, Trauma, Toxins (MPTP, CO, manganese, cyanide)
Other NeurodegenerativeWilson's disease, Huntington's disease, Alzheimer's with parkinsonism, Prion diseases, SCA3
  • Harrison's Principles of Internal Medicine, 22E

3. Parkinson's Disease (PD) - The Most Common Form

Epidemiology

PD is the most common cause of idiopathic parkinsonism. It affects ~1% of people over 60 years of age and ~3% over 80. Men are slightly more affected than women.

Pathology

The hallmark is loss of melanized dopaminergic neurons in the SNc and the presence of Lewy bodies - intraneuronal eosinophilic cytoplasmic inclusions containing misfolded alpha-synuclein. Grossly, the SNc shows depigmentation.
Neuropathology of PD: Gross depigmentation of substantia nigra (top row) and microscopic alpha-synuclein Lewy bodies and Lewy neurites (bottom row) in familial PD

Braak Staging

The Braak model proposes that alpha-synuclein pathology begins in the peripheral/enteric nervous system and ascends caudo-rostrally through the brainstem to ultimately involve the neocortex. This explains the pre-motor features (constipation, anosmia, REM sleep behavior disorder) that precede classic motor symptoms by years to decades.
Braak staging of alpha-synuclein spread: from peripheral/enteric nervous systems (blue) ascending through medulla, pons, basal midbrain, mesocortex, to neocortex
  • Harrison's Principles of Internal Medicine, 22E

4. Genetics

Less than 10% of PD has a causative mutation, but the known genes are important for understanding pathogenesis:
Gene (PARK locus)InheritanceProteinNotes
SNCA (PARK1)Autosomal DominantAlpha-synucleinRare; missense + duplications/triplications
Parkin (PARK2)Autosomal RecessiveParkinUp to 50% of early-onset PD
PINK1 (PARK6)Autosomal RecessivePTEN-induced kinase 1Early onset
DJ-1 (PARK7)Autosomal RecessiveDJ-1Early onset
LRRK2 (PARK8)Autosomal DominantLRRK2 (dardarin)Common in North Africans, Ashkenazi Jews
  • Bradley and Daroff's Neurology in Clinical Practice

5. Clinical Features

Motor (Early)

  • Tremor: Pill-rolling, 4-6 Hz, at rest; diminishes with voluntary movement
  • Rigidity: "Cogwheel" or "lead-pipe" resistance throughout range of motion
  • Bradykinesia: Slowing and reduced amplitude of movements; micrographia, hypomimia (masked facies), hypophonia
  • Postural instability: Loss of righting reflexes - tested by the "pull test" (retropulsion)

Non-Motor Features

  • Pre-motor: Anosmia, constipation, REM sleep behavior disorder (RBD), cardiac sympathetic denervation
  • Autonomic: Orthostatic hypotension, constipation, urinary dysfunction, erectile dysfunction, seborrhea
  • Neuropsychiatric: Depression, anxiety, apathy, hallucinations, impulse control disorders
  • Cognitive: Mild cognitive impairment progressing to PD dementia (PDD) in ~80% after 20 years
  • Sleep: RBD, excessive daytime somnolence, insomnia

Motor Complications (Advanced Disease)

  • Wearing-off: End-of-dose deterioration as levodopa effect wanes
  • Dyskinesias: Choreiform involuntary movements at peak levodopa dose
  • On-off fluctuations: Unpredictable switching between mobile ("on") and immobile ("off") states
  • Freezing of gait: Sudden inability to initiate or continue walking

6. Pathophysiology - Basal Ganglia Circuit

The basal ganglia circuit has two pathways:
  • Direct pathway: Striatum → GPi (inhibit) → Thalamus disinhibited → Cortex activated (facilitates movement)
  • Indirect pathway: Striatum → GPe → STN → GPi (excites GPi) → Thalamus inhibited → Cortex suppressed (inhibits movement)
In PD, dopamine depletion from the nigrostriatal pathway reduces D1-mediated direct pathway activity and reduces D2-mediated indirect pathway inhibition, leading to net thalamic inhibition and reduced motor cortex output - producing bradykinesia and akinesia.
Nigrostriatal dopaminergic pathway from substantia nigra (SN) to striatum (STR) - tractography visualization

7. Diagnosis

Diagnosis of PD is clinical, based on MDS (Movement Disorder Society) criteria:
  • Essential: Bradykinesia + at least one of: rest tremor or rigidity
  • Supportive features: Unilateral onset, rest tremor, good levodopa response, levodopa-induced dyskinesias, anosmia
  • Red flags (suggest atypical PD): Early falls, early autonomic failure, cerebellar features, supranuclear gaze palsy, rapid progression, symmetric onset, poor levodopa response
  • Imaging: DaTscan (dopamine transporter SPECT) can support diagnosis; MRI to exclude secondary causes
  • Labs: To exclude Wilson's disease (ceruloplasmin, copper), thyroid disorders

8. Treatment

Pharmacological Management

1. Levodopa + Carbidopa (First-line, most effective)

Levodopa is the gold standard. Carbidopa (a peripheral DOPA decarboxylase inhibitor) prevents peripheral conversion to dopamine, reducing nausea and allowing more levodopa to reach the brain. Standard formulations: Sinemet (carbidopa/levodopa). Extended-release formulations help reduce motor fluctuations.
  • Neuroanatomy through Clinical Cases, 3rd Ed.; Katzung Basic and Clinical Pharmacology, 16th Ed.

2. Dopamine Agonists

Used as monotherapy in early disease or as adjuncts to levodopa. Non-ergoline agents are preferred:
  • Pramipexole (D2/D3 agonist): 0.5-1.5 mg TID; renally excreted
  • Ropinirole (D2 agonist): 2-8 mg TID; metabolized by CYP1A2
  • Rotigotine (transdermal patch): 2-6 mg/24h; daily continuous stimulation
  • Side effects: nausea, postural hypotension, somnolence, impulse control disorders, hallucinations

3. MAO-B Inhibitors

  • Selegiline, Rasagiline: Reduce dopamine breakdown; used as early monotherapy or adjuncts. Mild symptomatic benefit; possible neuroprotective effects (under investigation).

4. COMT Inhibitors

  • Entacapone, Tolcapone: Block peripheral catechol-O-methyltransferase to prolong levodopa effect and reduce "wearing-off". Used as adjuncts to levodopa.

5. Amantadine

  • Mechanism unclear - likely potentiates dopamine release/reuptake inhibition; also NMDA receptor antagonist. Useful for mild early symptoms and levodopa-induced dyskinesias. Side effects: livedo reticularis, peripheral edema, hallucinations, confusion.

6. Anticholinergics (Trihexyphenidyl, Benztropine)

  • Improve tremor and rigidity but have little effect on bradykinesia. Avoid in elderly (confusion, cognitive impairment). Useful in young patients with predominant tremor.

7. Adenosine A2A Antagonist

  • Istradefylline (caffeine analog): Reduces "off" periods as an adjunct to carbidopa/levodopa. 20-40 mg daily.
  • Katzung Basic and Clinical Pharmacology, 16th Ed.

Surgical Treatment

  • Deep Brain Stimulation (DBS): High-frequency stimulation of the subthalamic nucleus (STN) or globus pallidus internus (GPi). Indicated in advanced PD with motor fluctuations not controlled by medications. A 2025 German DBS guideline (PMID 39985674) provides updated evidence-based recommendations.
  • Focused ultrasound thalamotomy: For medication-refractory tremor-dominant PD.

Non-Pharmacological

  • Physiotherapy (gait training, balance, exercise)
  • Speech therapy (hypophonia, dysphagia)
  • Occupational therapy
  • Psychological support for depression/anxiety

9. Atypical Parkinsonism ("Parkinson-Plus" Syndromes)

These are distinguished from PD by poor levodopa response and additional features:
ConditionKey Features
MSA-P (Striatonigral degeneration)Parkinsonism + autonomic failure + cerebellar features; symmetric onset
MSA-C (Olivopontocerebellar atrophy)Predominantly cerebellar ataxia + parkinsonism
PSP (Progressive Supranuclear Palsy)Vertical gaze palsy, early falls, neck rigidity, symmetric
Corticobasal SyndromeAsymmetric, limb apraxia, cortical sensory loss, alien limb phenomenon
DLB (Dementia with Lewy Bodies)Dementia before/concurrently with parkinsonism, visual hallucinations, fluctuating cognition

10. Drug-Induced Parkinsonism

The most common secondary cause. Caused by D2 receptor blockade in the striatum, disrupting dopaminergic inhibition and increasing cholinergic activity. Common offenders:
  • Typical antipsychotics (haloperidol, chlorpromazine)
  • Atypical antipsychotics (risperidone, olanzapine - less common)
  • Metoclopramide, prochlorperazine (antiemetics)
  • Reserpine (depletes dopamine stores)
  • Valproate (mechanism unclear)
Management: stop the offending drug; symptoms typically resolve within weeks to months. Anticholinergics can provide symptomatic relief.
  • Stahl's Essential Psychopharmacology; Kaplan & Sadock's Synopsis of Psychiatry

11. Prognosis

PD is progressive but variable. Average life expectancy is close to normal in early-diagnosed patients with good dopaminergic response. Key prognostic factors:
  • Age of onset (younger = slower progression)
  • Tremor-dominant subtype (better prognosis than akinetic-rigid)
  • Cognitive decline and dementia worsen quality of life
  • Falls, dysphagia, and autonomic failure are major late complications
  • ~80% develop dementia within 20 years

Sources:
  • Bradley and Daroff's Neurology in Clinical Practice (primary neurology reference)
  • Harrison's Principles of Internal Medicine, 22E (classification and pathology)
  • Katzung's Basic and Clinical Pharmacology, 16th Ed. (drug mechanisms)
  • Stahl's Essential Psychopharmacology (drug-induced parkinsonism)
  • Neuroanatomy through Clinical Cases, 3rd Ed. (levodopa mechanism)
  • German DBS Guidelines, J Neurology 2025 (PMID: 39985674)

Make a diagnosis flowchart for differentiating PD from atypical parkinsonism syndromes

Finding Sources
Finding Sources
Reading File
Reading File
Reading File
I have all the clinical detail I need. Now let me build the flowchart as a high-quality downloadable file using Python/matplotlib:
Running Command

mkdir -p /tmp/workspace/parkinsonism-flowchart && ls /tmp/workspace/parkinsonism-flowchart/

Writing File

~/parkinsonism-flowchart/flowchart.py

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.patches import FancyBboxPatch, FancyArrowPatch
import textwrap

fig, ax = plt.subplots(figsize=(26, 34))
ax.set_xlim(0, 26)
ax.set_ylim(0, 34)
ax.axis('off')
fig.patch.set_facecolor('#F7F9FC')

# ── colour palette ──────────────────────────────────────────────────────────
C_START   = '#1A3A5C'   # dark navy   – entry node
C_QUESTION= '#2471A3'   # medium blue – decision diamonds
C_SECONDARY='#117A65'   # teal        – secondary parkinsonism
C_PD      = '#1E8449'   # green       – PD confirmed
C_MSA     = '#6C3483'   # purple      – MSA
C_PSP     = '#922B21'   # red         – PSP
C_CBS     = '#B7950B'   # gold        – CBS
C_DLB     = '#1A5276'   # dark blue   – DLB
C_ARROW   = '#555555'
C_REDFLG  = '#C0392B'
C_SUPPORT = '#1A6F24'
TEXT_LIGHT= 'white'
TEXT_DARK = '#1A1A1A'

def box(ax, cx, cy, w, h, text, facecolor, textcolor=TEXT_LIGHT,
        fontsize=9, bold=False, style='round,pad=0.15', wrap=True,
        linespacing=1.4):
    rx, ry = cx - w/2, cy - h/2
    fancy = FancyBboxPatch((rx, ry), w, h,
                           boxstyle=style,
                           facecolor=facecolor,
                           edgecolor='white', linewidth=1.5,
                           zorder=3)
    ax.add_patch(fancy)
    if wrap:
        lines = textwrap.wrap(text, width=int(w*8.5))
        text_to_show = '\n'.join(lines)
    else:
        text_to_show = text
    ax.text(cx, cy, text_to_show,
            ha='center', va='center', fontsize=fontsize,
            color=textcolor, fontweight='bold' if bold else 'normal',
            linespacing=linespacing, zorder=4,
            multialignment='center')

def diamond(ax, cx, cy, w, h, text, facecolor, textcolor=TEXT_LIGHT, fontsize=8.5):
    from matplotlib.patches import Polygon
    pts = [(cx, cy+h/2), (cx+w/2, cy), (cx, cy-h/2), (cx-w/2, cy)]
    poly = Polygon(pts, closed=True, facecolor=facecolor,
                   edgecolor='white', linewidth=1.5, zorder=3)
    ax.add_patch(poly)
    lines = textwrap.wrap(text, width=int(w*7))
    ax.text(cx, cy, '\n'.join(lines),
            ha='center', va='center', fontsize=fontsize,
            color=textcolor, fontweight='bold', zorder=4,
            multialignment='center', linespacing=1.3)

def arrow(ax, x1, y1, x2, y2, label='', label_side='right', color=C_ARROW):
    ax.annotate('', xy=(x2, y2), xytext=(x1, y1),
                arrowprops=dict(arrowstyle='->', color=color,
                                lw=1.8, connectionstyle='arc3,rad=0'),
                zorder=2)
    if label:
        mx, my = (x1+x2)/2, (y1+y2)/2
        offset = 0.18 if label_side == 'right' else -0.18
        ax.text(mx + offset, my, label, ha='center', va='center',
                fontsize=7.5, color=color, fontweight='bold',
                bbox=dict(facecolor='white', edgecolor='none', alpha=0.85, pad=1))

def label_on_arrow(ax, x, y, text, color='#333333'):
    ax.text(x, y, text, ha='center', va='center', fontsize=7.5,
            color=color, fontweight='bold',
            bbox=dict(facecolor='white', edgecolor='none', alpha=0.9, pad=1.5))

# ── TITLE ────────────────────────────────────────────────────────────────────
ax.text(13, 33.4,
        'Differential Diagnosis: Parkinson\'s Disease vs. Atypical Parkinsonism Syndromes',
        ha='center', va='center', fontsize=15, fontweight='bold', color='#1A3A5C')
ax.text(13, 33.0,
        'Based on MDS Clinical Diagnostic Criteria  |  Harrison\'s & Bradley\'s Neurology',
        ha='center', va='center', fontsize=8.5, color='#555555', style='italic')

# ── ROW 0: Entry ─────────────────────────────────────────────────────────────
box(ax, 13, 32.2, 9, 0.7,
    'PATIENT PRESENTS WITH PARKINSONISM\n(Bradykinesia + Rigidity and/or Rest Tremor)',
    C_START, fontsize=10, bold=True)

arrow(ax, 13, 31.85, 13, 31.3)

# ── ROW 1: Exclude secondary ─────────────────────────────────────────────────
diamond(ax, 13, 30.8, 9.5, 1.0,
        'Identifiable secondary cause?\n(Drugs · Vascular · Toxins · Tumor · NPH · Infection · Metabolic)',
        C_QUESTION, fontsize=8.5)

# YES → left branch
arrow(ax, 8.25, 30.8, 4.5, 30.8, color=C_SECONDARY)
label_on_arrow(ax, 6.3, 30.95, 'YES', color=C_SECONDARY)
box(ax, 3.0, 30.8, 2.8, 0.75,
    'SECONDARY\nPARKINSONISM\n(Treat underlying cause)',
    C_SECONDARY, fontsize=8)

# NO ↓
arrow(ax, 13, 30.3, 13, 29.65)
label_on_arrow(ax, 13.5, 29.95, 'NO', color='#333')

# ── ROW 2: Levodopa trial ─────────────────────────────────────────────────────
diamond(ax, 13, 29.2, 9.5, 0.9,
        'Sustained, marked response to Levodopa trial?',
        C_QUESTION)

# YES ↓ (tentative PD direction)
arrow(ax, 13, 28.75, 13, 28.1)
label_on_arrow(ax, 13.5, 28.4, 'YES', color='#333')

# POOR RESPONSE → right
arrow(ax, 17.75, 29.2, 21.5, 29.2, color=C_MSA)
label_on_arrow(ax, 19.6, 29.35, 'POOR / NO', color=C_MSA)
box(ax, 23.0, 29.2, 3.6, 0.75,
    'Consider Atypical\nParkinsonism ↓',
    C_MSA, fontsize=8)

# ── ROW 3: Red flags check ───────────────────────────────────────────────────
box(ax, 13, 27.55, 11, 1.05,
    'Check for RED FLAGS  (if present, must be outweighed by supportive features)',
    C_REDFLG, fontsize=8.5, bold=True)

# Red flag detail box
redflags_text = (
    "• Early severe autonomic failure (within 1st year)\n"
    "• Recurrent falls in first year\n"
    "• Supranuclear vertical gaze palsy\n"
    "• Cerebellar signs\n"
    "• Bilateral symmetric onset\n"
    "• Rapid progression to wheelchair ≤5 yrs\n"
    "• Absence of non-motor features of PD\n"
    "• Inspiratory stridor / respiratory disturbance\n"
    "• Alien limb phenomenon / apraxia\n"
    "• Levodopa-induced severe dyskinesias absent"
)
ax.text(7.8, 25.8, redflags_text,
        ha='left', va='top', fontsize=7.8, color='#6B0000',
        bbox=dict(facecolor='#FFF5F5', edgecolor='#C0392B',
                  linewidth=1.2, boxstyle='round,pad=0.5'),
        linespacing=1.5, zorder=4)

ax.text(7.5, 26.95, 'RED FLAGS:', ha='left', va='center',
        fontsize=8, color=C_REDFLG, fontweight='bold')

# Supportive features box
support_text = (
    "• Unilateral onset\n"
    "• Clear rest tremor (pill-rolling)\n"
    "• Excellent & sustained levodopa response\n"
    "• Levodopa-induced dyskinesias\n"
    "• Anosmia / hyposmia\n"
    "• Cardiac sympathetic denervation (MIBG)\n"
    "• Asymmetric striatal DAT loss (DaTscan)\n"
    "• REM sleep behaviour disorder (RBD)"
)
ax.text(15.0, 25.8, support_text,
        ha='left', va='top', fontsize=7.8, color='#0A4A1A',
        bbox=dict(facecolor='#F0FFF4', edgecolor='#1E8449',
                  linewidth=1.2, boxstyle='round,pad=0.5'),
        linespacing=1.5, zorder=4)
ax.text(15.0, 26.95, 'SUPPORTIVE FEATURES:', ha='left', va='center',
        fontsize=8, color=C_SUPPORT, fontweight='bold')

arrow(ax, 13, 27.02, 13, 24.5)

# ── ROW 4: Diagnostic decision ───────────────────────────────────────────────
diamond(ax, 13, 24.0, 9.5, 0.9,
        'Red flags absent OR outweighed by ≥2 supportive features?',
        C_QUESTION)

# YES ↓ → PD
arrow(ax, 13, 23.55, 13, 22.85)
label_on_arrow(ax, 13.5, 23.2, 'YES', color='#333')
box(ax, 13, 22.4, 7.5, 0.8,
    'CLINICALLY ESTABLISHED  PARKINSON\'S DISEASE',
    C_PD, fontsize=10, bold=True)

# PD features sub-box
pd_detail = (
    "Imaging: DaTscan – asymmetric posterior putamen ↓ dopamine uptake\n"
    "Pathology: Lewy bodies (α-synuclein) in SNc  |  SNc depigmentation\n"
    "Genetics: Consider SNCA, LRRK2, Parkin, PINK1, DJ-1 if onset <50 yrs\n"
    "Progression: Usually slow; responds to levodopa for years"
)
ax.text(13, 21.65, pd_detail,
        ha='center', va='center', fontsize=8, color='#0A3A1A',
        bbox=dict(facecolor='#EAF9ED', edgecolor=C_PD, linewidth=1, boxstyle='round,pad=0.4'),
        linespacing=1.5, zorder=4)

# NO → right: Atypical parkinsonism pathway
arrow(ax, 17.75, 24.0, 21.5, 24.0, color=C_MSA)
label_on_arrow(ax, 19.6, 24.15, 'NO / FLAG', color=C_MSA)

# ── ATYPICAL PARKINSONISM COLUMN ──────────────────────────────────────────────
ax.text(23.0, 27.7, 'ATYPICAL PARKINSONISM', ha='center', va='center',
        fontsize=9, fontweight='bold', color='white',
        bbox=dict(facecolor='#922B21', edgecolor='white', linewidth=1.5,
                  boxstyle='round,pad=0.4'), zorder=4)

arrow(ax, 23.0, 27.35, 23.0, 26.7, color=C_REDFLG)

# sub-question
diamond(ax, 23.0, 26.2, 5.5, 0.9,
        'Key distinguishing features?',
        '#7D3C98')

# Arrows downward from diamond to 4 boxes
arrow(ax, 23.0, 25.75, 23.0, 25.15, color='#555')

# ── 4 Atypical boxes ─────────────────────────────────────────────────────────
# PSP
box(ax, 20.2, 24.45, 4.5, 1.1,
    'PSP\n(Progressive Supranuclear Palsy)',
    C_PSP, fontsize=8, bold=True)
psp_txt = ("↑ Vertical gaze palsy\n"
           "↑ Early falls (retropulsion)\n"
           "↑ Axial > limb rigidity\n"
           "↑ Neck hyperextension\n"
           "→ Hummingbird sign (MRI)")
ax.text(20.2, 23.5, psp_txt, ha='center', va='top', fontsize=7.5,
        color='#4A0E09',
        bbox=dict(facecolor='#FDEDEC', edgecolor=C_PSP, linewidth=0.8,
                  boxstyle='round,pad=0.3'), linespacing=1.4, zorder=4)

# MSA
box(ax, 25.0, 24.45, 4.5, 1.1,
    'MSA\n(Multiple System Atrophy)',
    C_MSA, fontsize=8, bold=True)
msa_txt = ("↑ Early autonomic failure\n"
           "↑ Cerebellar signs (MSA-C)\n"
           "↑ Inspiratory stridor\n"
           "↑ Rapid progression\n"
           "→ Hot cross bun sign (MRI)")
ax.text(25.0, 23.5, msa_txt, ha='center', va='top', fontsize=7.5,
        color='#3B1A5A',
        bbox=dict(facecolor='#F5EEF8', edgecolor=C_MSA, linewidth=0.8,
                  boxstyle='round,pad=0.3'), linespacing=1.4, zorder=4)

# CBS
box(ax, 20.2, 22.1, 4.5, 1.1,
    'CBS\n(Corticobasal Syndrome)',
    C_CBS, fontsize=8, bold=True)
cbs_txt = ("↑ Alien limb phenomenon\n"
           "↑ Cortical sensory loss\n"
           "↑ Limb apraxia\n"
           "↑ Asymmetric limb dystonia\n"
           "→ Asymmetric cortical atrophy")
ax.text(20.2, 21.15, cbs_txt, ha='center', va='top', fontsize=7.5,
        color='#4A3B00',
        bbox=dict(facecolor='#FDFCE0', edgecolor=C_CBS, linewidth=0.8,
                  boxstyle='round,pad=0.3'), linespacing=1.4, zorder=4)

# DLB
box(ax, 25.0, 22.1, 4.5, 1.1,
    'DLB\n(Dementia with Lewy Bodies)',
    C_DLB, fontsize=8, bold=True)
dlb_txt = ("↑ Dementia before/≤1yr motor\n"
           "↑ Recurrent visual hallucinations\n"
           "↑ Fluctuating cognition\n"
           "↑ Neuroleptic sensitivity\n"
           "→ Reduced MIBG uptake")
ax.text(25.0, 21.15, dlb_txt, ha='center', va='top', fontsize=7.5,
        color='#0A2A40',
        bbox=dict(facecolor='#EAF2FF', edgecolor=C_DLB, linewidth=0.8,
                  boxstyle='round,pad=0.3'), linespacing=1.4, zorder=4)

# Small arrows from diamond to atypical boxes
arrow(ax, 21.0, 25.75, 20.2, 24.95, color='#777')
arrow(ax, 23.0, 25.75, 25.0, 24.95, color='#777')
ax.annotate('', xy=(20.2, 22.6), xytext=(20.2, 23.85),
            arrowprops=dict(arrowstyle='->', color='#777', lw=1.5), zorder=2)
ax.annotate('', xy=(25.0, 22.6), xytext=(25.0, 23.85),
            arrowprops=dict(arrowstyle='->', color='#777', lw=1.5), zorder=2)

# ── INVESTIGATION BOX ─────────────────────────────────────────────────────────
inv_text = (
    "KEY INVESTIGATIONS\n\n"
    "• DaTscan / FP-CIT SPECT: Reduced & asymmetric posterior putamen uptake in PD/APS (not in drug-induced or ET)\n"
    "• Brain MRI: Normal in PD | Hummingbird sign (PSP) | Hot cross bun sign (MSA) | Asymm. cortical atrophy (CBS)\n"
    "• MIBG cardiac scintigraphy: Reduced in PD & DLB; typically preserved in MSA/PSP\n"
    "• Autonomic testing: Tilt-table, urodynamics (severe early failure → MSA)\n"
    "• Neuropsychology: Profile differs — subcortical (PD) vs. frontal (PSP) vs. cortical (CBS/DLB)\n"
    "• Levodopa challenge (≥600 mg/day × 4 wks): ≥30% UPDRS improvement = strong PD support\n"
    "• Genetics: SNCA, LRRK2, Parkin, PINK1, GBA1 — consider if age <50 or family history"
)
ax.text(13, 19.5, inv_text,
        ha='center', va='center', fontsize=8.5, color='#1A1A1A',
        bbox=dict(facecolor='#EEF4FB', edgecolor='#2471A3', linewidth=1.5,
                  boxstyle='round,pad=0.6'), linespacing=1.6, zorder=4)

arrow(ax, 13, 21.0, 13, 20.55, color='#2471A3')

# ── OUTCOME / TREATMENT GUIDANCE ─────────────────────────────────────────────
tx_text = (
    "TREATMENT IMPLICATIONS\n\n"
    "PD:  Levodopa/carbidopa (gold standard) · Dopamine agonists · MAO-B inhibitors · DBS for advanced motor fluctuations\n"
    "PSP / CBS:  Poor levodopa response · Supportive care · Physiotherapy · Falls prevention\n"
    "MSA:  Modest levodopa response (30-40%) · Treat autonomic failure (fludrocortisone, midodrine) · CPAP for stridor\n"
    "DLB:  Avoid typical antipsychotics (severe sensitivity) · AChEIs for hallucinations/cognition · Low-dose quetiapine if needed"
)
ax.text(13, 17.5, tx_text,
        ha='center', va='center', fontsize=8.5, color='#1A1A1A',
        bbox=dict(facecolor='#F0FFF4', edgecolor=C_PD, linewidth=1.5,
                  boxstyle='round,pad=0.6'), linespacing=1.6, zorder=4)

arrow(ax, 13, 18.45, 13, 18.22, color=C_PD)

# ── LEGEND ───────────────────────────────────────────────────────────────────
legend_items = [
    (C_START,     'Entry / Syndrome definition'),
    (C_QUESTION,  'Decision point'),
    (C_SECONDARY, 'Secondary Parkinsonism'),
    (C_PD,        "Parkinson's Disease"),
    (C_PSP,       'PSP'),
    (C_MSA,       'MSA'),
    (C_CBS,       'Corticobasal Syndrome'),
    (C_DLB,       'Dementia with Lewy Bodies'),
    (C_REDFLG,    'Red flags'),
]
lx, ly = 0.5, 16.5
ax.text(lx, ly+0.3, 'LEGEND', ha='left', fontsize=8.5, fontweight='bold', color='#333')
for i, (col, lbl) in enumerate(legend_items):
    yy = ly - 0.42 * (i+1)
    rect = FancyBboxPatch((lx, yy-0.15), 0.55, 0.30,
                          boxstyle='round,pad=0.05',
                          facecolor=col, edgecolor='white', linewidth=0.8, zorder=3)
    ax.add_patch(rect)
    ax.text(lx+0.7, yy, lbl, ha='left', va='center', fontsize=8, color='#333')

# footer
ax.text(13, 0.25,
        'Sources: Harrison\'s Principles of Internal Medicine 22E · Bradley & Daroff\'s Neurology in Clinical Practice · '
        'MDS Clinical Diagnostic Criteria for PD (Berg et al.) · Katzung Basic & Clinical Pharmacology 16E',
        ha='center', va='center', fontsize=7, color='#777', style='italic')

plt.tight_layout(pad=0.5)
plt.savefig('/tmp/workspace/parkinsonism-flowchart/PD_vs_Atypical_Parkinsonism_Flowchart.png',
            dpi=180, bbox_inches='tight', facecolor=fig.get_facecolor())
print("Saved PNG")

plt.savefig('/tmp/workspace/parkinsonism-flowchart/PD_vs_Atypical_Parkinsonism_Flowchart.pdf',
            bbox_inches='tight', facecolor=fig.get_facecolor())
print("Saved PDF")
Running Command

cd /tmp/workspace/parkinsonism-flowchart && python flowchart.py 2>&1

Reading File
The files generated successfully. Let me verify file sizes and display the image:
Running Command

ls -lh /tmp/workspace/parkinsonism-flowchart/

Your flowchart is ready! Here are the download links:

PD vs Atypical Parkinsonism Flowchart

Image · PNG

PD vs Atypical Parkinsonism Flowchart

PDF Document · PDF


Here is what the flowchart covers, step by step:
Step 1 - Entry: Patient presents with parkinsonism (bradykinesia + rigidity/tremor).
Step 2 - Exclude secondary causes first: Drug-induced, vascular, toxin, NPH, tumor, infection, metabolic. If identified → treat the underlying cause and diagnose Secondary Parkinsonism.
Step 3 - Levodopa trial: A sustained, marked response (≥30% UPDRS improvement) favors PD. Poor/no response raises strong suspicion for atypical parkinsonism.
Step 4 - Red flags vs. supportive features (MDS Criteria):
  • Red flags (orange box): early falls, vertical gaze palsy, cerebellar signs, symmetric onset, rapid progression, early severe autonomic failure, alien limb
  • Supportive features (green box): unilateral onset, rest tremor, excellent levodopa response, anosmia, RBD, asymmetric DaTscan
Step 5 - Diagnostic decision: If red flags are absent or outweighed by ≥2 supportive features → Clinically Established PD. If red flags dominate → workup for atypical syndromes.
Atypical column branches into four diagnoses with key distinguishing features and MRI signatures:
  • PSP - vertical gaze palsy, early retropulsion falls, hummingbird sign
  • MSA - early autonomic failure, cerebellar signs, hot cross bun sign
  • CBS - alien limb, cortical sensory loss, apraxia, asymmetric atrophy
  • DLB - dementia before/concurrent with motor onset, visual hallucinations, neuroleptic sensitivity
Investigations box covers DaTscan, MRI patterns, MIBG scintigraphy, autonomic testing, levodopa challenge, and genetics.
Treatment implications for each diagnosis are summarized at the bottom.
Sources: Harrison's Principles of Internal Medicine 22E, Bradley & Daroff's Neurology in Clinical Practice, MDS Clinical Diagnostic Criteria (Berg et al.), Katzung Pharmacology 16E

Make a clinical vignette workbook with case studies

Asking for Preferences

What format should the workbook be in? · What level is this workbook aimed at? · How many case studies would you like?

A comprehensive PDF workbook with 10+ specialist-level cases. Let me read the PDF skill and pull clinical details from the textbooks simultaneously.
Reading File
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
Finding Sources
I have all the clinical data I need. Now let me build the comprehensive PDF workbook:

Make a clinical vignette workbook with case studies

Let me confirm the details before starting.
Asking for Preferences

What format should the workbook be in? · What level is this aimed at? · How many case studies?

Your credits are exhausted. You can purchase a top-up or subscribe to a plan to continue using Orris. If you're already subscribed, your daily credits will reset tomorrow.

Make a clinical vignette workbook with case studies

Building a comprehensive PDF workbook with 12 specialist-level cases on Parkinsonism. Let me get everything set up.
Reading File
Running Command

mkdir -p /tmp/workspace/parkinsonism-workbook && ls /tmp/workspace/parkinsonism-workbook/

Make a clinical vignette workbook with case studies

Building a comprehensive PDF workbook - 12 specialist-level Parkinsonism case studies. Starting now.
Running Command

mkdir -p /tmp/workspace/parkinsonism-workbook

Can you make infographic explaining and differentiateing various forms of parkinsonism

Generating Image

A detailed medical infographic titled "Forms of Parkinsonism: Differentiation Guide" showing 6 distinct panels comparing different types of parkinsonism. The infographic should include: 1. PARKINSON'S DISEASE (PD) - green panel: asymmetric onset, rest tremor (pill-rolling), excellent levodopa response, Lewy bodies (alpha-synuclein), slow progression, anosmia/RBD as premotor features, DaTscan shows asymmetric posterior putamen loss 2. PROGRESSIVE SUPRANUCLEAR PALSY (PSP) - red panel: vertical supranuclear gaze palsy (downward gaze palsy), early falls (retropulsion), axial rigidity, neck hyperextension, "hummingbird sign" on MRI, poor levodopa response, tau pathology 3. MULTIPLE SYSTEM ATROPHY (MSA) - purple panel: early severe autonomic failure (orthostatic hypotension, urinary incontinence), cerebellar ataxia (MSA-C) or parkinsonism (MSA-P), inspiratory stridor, "hot cross bun sign" on MRI, alpha-synuclein in oligodendrocytes, poor levodopa response 4. CORTICOBASAL SYNDROME (CBS) - orange panel: markedly asymmetric, alien limb phenomenon, ideomotor apraxia, cortical sensory loss, myoclonus, limb dystonia, asymmetric cortical atrophy on MRI, tau pathology 5. DEMENTIA WITH LEWY BODIES (DLB) - blue panel: dementia onset before or within 1 year of motor symptoms, recurrent vivid visual hallucinations, fluctuating cognition/alertness, REM sleep behavior disorder, severe neuroleptic sensitivity, reduced MIBG uptake 6. DRUG-INDUCED / SECONDARY PARKINSONISM - gray panel: symmetric onset, history of dopamine antagonist (antipsychotics, metoclopramide), resolves on stopping drug, no DaTscan abnormality, also: vascular (lower-body gait disorder, white matter lesions), toxins (MPTP, manganese) Include a small comparison table at bottom showing: Tremor type, Levodopa response, Onset symmetry, Key imaging finding, Pathology for each type. Clean modern medical style, color-coded, professional clinical reference quality.

Forms of Parkinsonism infographic
Here is your infographic covering all six major forms. Here is a quick guide to what each panel highlights:
Parkinson's Disease (green) - the reference point. Asymmetric onset, pill-rolling rest tremor, excellent levodopa response, Lewy body (alpha-synuclein) pathology, slow progression. Pre-motor clues: anosmia, constipation, REM sleep behaviour disorder.
PSP (red) - the key giveaway is vertical supranuclear gaze palsy (especially downgaze) + early unprovoked falls with retropulsion. Axial > limb rigidity, neck hyperextension, "hummingbird sign" on MRI sagittal. Tau pathology. Poor levodopa response.
MSA (purple) - early severe autonomic failure (orthostatic hypotension, urinary incontinence, stridor) + cerebellar ataxia (MSA-C) or parkinsonism (MSA-P). "Hot cross bun" sign in the pons on MRI. Alpha-synuclein in oligodendrocytes. Poor levodopa response.
Corticobasal Syndrome (orange) - dramatically asymmetric. Alien limb phenomenon (the hand "acts on its own"), ideomotor apraxia, cortical sensory loss, myoclonus, limb dystonia. Asymmetric frontoparietal atrophy on MRI. Tau pathology. Levodopa-unresponsive.
DLB (blue) - dementia onset before or within 1 year of motor symptoms (vs. PD dementia which comes late). Recurrent, well-formed visual hallucinations, fluctuating alertness, REM sleep behaviour disorder. Severe, sometimes fatal neuroleptic sensitivity. Reduced MIBG cardiac uptake.
Drug-induced / Secondary (gray) - symmetric onset, clear temporal link to a dopamine antagonist (antipsychotics, metoclopramide, prochlorperazine). Normal DaTscan (dopaminergic terminals intact). Resolves weeks-months after stopping the offending drug. Vascular parkinsonism shows lower-body predominant gait disorder with periventricular white matter lesions.

Generate a differential diagnosis checklist for rapid clinical assessment

Generating a printable, clinic-ready differential diagnosis checklist as a downloadable PDF.
Writing File

~/parkinsonism-workbook/checklist.py

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm, cm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT
from reportlab.platypus import (
    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
    HRFlowable, KeepTogether
)
from reportlab.graphics.shapes import Drawing, Rect, String, Circle, Line
from reportlab.graphics import renderPDF
from reportlab.platypus.flowables import Flowable
import os

OUT = "/tmp/workspace/parkinsonism-workbook/Parkinsonism_DDx_Checklist.pdf"

# ── Colours ──────────────────────────────────────────────────────────────────
NAVY    = colors.HexColor("#1A3A5C")
TEAL    = colors.HexColor("#117A65")
GREEN   = colors.HexColor("#1E8449")
RED     = colors.HexColor("#922B21")
PURPLE  = colors.HexColor("#6C3483")
ORANGE  = colors.HexColor("#B7770D")
STEEL   = colors.HexColor("#2471A3")
GREY    = colors.HexColor("#566573")
LGREY   = colors.HexColor("#F2F3F4")
MGREY   = colors.HexColor("#D5D8DC")
WHITE   = colors.white
BLACK   = colors.HexColor("#1A1A1A")
WARN    = colors.HexColor("#C0392B")
GOLD    = colors.HexColor("#D4AC0D")

# ── Document ─────────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
    OUT, pagesize=A4,
    leftMargin=14*mm, rightMargin=14*mm,
    topMargin=14*mm, bottomMargin=14*mm,
    title="Parkinsonism Differential Diagnosis Checklist",
    author="Orris Medical"
)

W = A4[0] - 28*mm   # usable width

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

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

sTitle = S("sTitle", fontSize=18, textColor=WHITE, alignment=TA_CENTER,
           fontName="Helvetica-Bold", leading=22)
sSub   = S("sSub",   fontSize=9,  textColor=WHITE, alignment=TA_CENTER,
           fontName="Helvetica", leading=12)
sH1    = S("sH1",    fontSize=11, textColor=WHITE, fontName="Helvetica-Bold",
           leading=14, leftIndent=4)
sH2    = S("sH2",    fontSize=9,  textColor=NAVY,  fontName="Helvetica-Bold",
           leading=12)
sBody  = S("sBody",  fontSize=8,  textColor=BLACK, fontName="Helvetica",
           leading=11, leftIndent=4)
sBold  = S("sBold",  fontSize=8,  textColor=BLACK, fontName="Helvetica-Bold",
           leading=11)
sWarn  = S("sWarn",  fontSize=7.5,textColor=WARN,  fontName="Helvetica-Bold",
           leading=10)
sNote  = S("sNote",  fontSize=7,  textColor=GREY,  fontName="Helvetica",
           leading=10, alignment=TA_CENTER)
sSmall = S("sSmall", fontSize=7.5,textColor=BLACK, fontName="Helvetica",
           leading=10)
sCheck = S("sCheck", fontSize=8,  textColor=BLACK, fontName="Helvetica",
           leading=12, leftIndent=8)

# ── Helpers ──────────────────────────────────────────────────────────────────
def coloured_header(text, sub, colour, w=W):
    data = [[Paragraph(text, sTitle)], [Paragraph(sub, sSub)]]
    t = Table(data, colWidths=[w])
    t.setStyle(TableStyle([
        ("BACKGROUND", (0,0), (-1,-1), colour),
        ("TOPPADDING",    (0,0), (-1,-1), 6),
        ("BOTTOMPADDING", (0,0), (-1,-1), 6),
        ("LEFTPADDING",   (0,0), (-1,-1), 8),
        ("RIGHTPADDING",  (0,0), (-1,-1), 8),
        ("ROWBACKGROUNDS",(0,0),(-1,-1),[colour]),
    ]))
    return t

def section_header(text, colour, w=W):
    t = Table([[Paragraph(text, sH1)]], colWidths=[w])
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,-1), colour),
        ("TOPPADDING",    (0,0),(-1,-1), 4),
        ("BOTTOMPADDING", (0,0),(-1,-1), 4),
        ("LEFTPADDING",   (0,0),(-1,-1), 8),
        ("RIGHTPADDING",  (0,0),(-1,-1), 8),
    ]))
    return t

def checkbox(label, indent=0):
    return Paragraph(f"&#9633;  {label}", sCheck)

def bullet(label, colour=BLACK):
    st = ParagraphStyle("bp", fontSize=8, textColor=colour,
                        fontName="Helvetica", leading=11, leftIndent=12,
                        bulletText="•", bulletIndent=4)
    return Paragraph(label, st)

def two_col_table(left_rows, right_rows, left_head, right_head,
                  lc=STEEL, rc=STEEL, w=W):
    hw = w / 2 - 1*mm
    head_style = S("th", fontSize=8.5, textColor=WHITE,
                   fontName="Helvetica-Bold", leading=11, alignment=TA_CENTER)
    header = [
        [Paragraph(left_head,  head_style),
         Paragraph(right_head, head_style)]
    ]
    rows = []
    max_r = max(len(left_rows), len(right_rows))
    for i in range(max_r):
        lv = left_rows[i]  if i < len(left_rows)  else ""
        rv = right_rows[i] if i < len(right_rows) else ""
        rows.append([
            checkbox(lv) if lv else Paragraph("", sBody),
            checkbox(rv) if rv else Paragraph("", sBody),
        ])
    data = header + rows
    cmds = [
        ("BACKGROUND",    (0,0),(0,0), lc),
        ("BACKGROUND",    (1,0),(1,0), rc),
        ("GRID",          (0,0),(-1,-1), 0.3, MGREY),
        ("TOPPADDING",    (0,0),(-1,-1), 2),
        ("BOTTOMPADDING", (0,0),(-1,-1), 2),
        ("LEFTPADDING",   (0,0),(-1,-1), 4),
        ("RIGHTPADDING",  (0,0),(-1,-1), 4),
        ("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, LGREY]),
        ("VALIGN",        (0,0),(-1,-1), "TOP"),
    ]
    t = Table(data, colWidths=[hw, hw])
    t.setStyle(TableStyle(cmds))
    return t

def shaded_box(content_rows, bg=LGREY, border=MGREY, w=W):
    data = [[r] for r in content_rows]
    t = Table(data, colWidths=[w])
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,-1), bg),
        ("BOX",           (0,0),(-1,-1), 0.5, border),
        ("TOPPADDING",    (0,0),(-1,-1), 2),
        ("BOTTOMPADDING", (0,0),(-1,-1), 2),
        ("LEFTPADDING",   (0,0),(-1,-1), 8),
        ("RIGHTPADDING",  (0,0),(-1,-1), 8),
        ("VALIGN",        (0,0),(-1,-1), "TOP"),
    ]))
    return t

def sp(h=4): return Spacer(1, h)
def hr(): return HRFlowable(width=W, thickness=0.5, color=MGREY)

# ── Comparison mega-table ─────────────────────────────────────────────────────
def comparison_table():
    cols = ["Feature", "PD", "PSP", "MSA", "CBS", "DLB", "Drug-Induced"]
    col_colours = [NAVY, GREEN, RED, PURPLE, ORANGE, STEEL, GREY]
    col_w = [28*mm, 26*mm, 26*mm, 26*mm, 26*mm, 26*mm, 24*mm]

    rows_data = [
        # Feature, PD, PSP, MSA, CBS, DLB, Drug-Induced
        ["Tremor",
         "Rest, pill-rolling, 4-6 Hz, asymm.",
         "Rare; postural if present",
         "Postural/action; rest tremor uncommon",
         "Postural/action; myoclonus common",
         "Rest tremor, mild",
         "Rest or none; symmetric"],
        ["Onset symmetry",
         "Asymmetric ✓",
         "Symmetric (axial dominant)",
         "Symmetric or mild asymm.",
         "Markedly asymmetric ✓",
         "Symmetric",
         "Symmetric ✓"],
        ["Levodopa response",
         "Excellent & sustained ✓",
         "Poor/absent",
         "Partial (30-40%) then fades",
         "Poor/absent",
         "Partial; can worsen neuropsych.",
         "No dopaminergic deficit"],
        ["Gaze palsy",
         "Absent",
         "Vertical (downgaze first) ✓✓",
         "Absent",
         "May develop horiz. + vert.",
         "Absent",
         "Absent"],
        ["Early falls",
         "Late (>3 yrs)",
         "Within 1st year ✓✓",
         "Late (autonomic > falls)",
         "Variable",
         "Early if motor prominent",
         "Variable"],
        ["Autonomic failure",
         "Mild-moderate (late)",
         "Mild",
         "Severe & early ✓✓",
         "Urinary (late)",
         "Moderate",
         "Drug-related hypotension"],
        ["Cognitive / neuropsych.",
         "Late dementia (PDD)",
         "Frontal/executive (early)",
         "Mild (late)",
         "Apraxia, aphasia, alien limb ✓✓",
         "Dementia ≤1 yr of motor ✓✓\nVisual hallucinations ✓✓",
         "Absent (drug effect)"],
        ["Cerebellar signs",
         "Absent",
         "Absent",
         "Ataxia (MSA-C) ✓",
         "Absent",
         "Absent",
         "Absent"],
        ["Key MRI finding",
         "Usually normal",
         "Hummingbird / penguin sign",
         "Hot cross bun sign (pons)",
         "Asymm. frontoparietal atrophy",
         "Usually normal or gen. atrophy",
         "Normal (WM lesions if vascular)"],
        ["DaTscan",
         "Reduced, asymm. post. putamen",
         "Reduced (symmetric)",
         "Reduced (symmetric)",
         "Reduced (asymmetric)",
         "Reduced",
         "Normal ✓ (key differentiator)"],
        ["MIBG cardiac",
         "Reduced ✓",
         "Preserved",
         "Preserved",
         "Preserved",
         "Reduced ✓",
         "Preserved"],
        ["Pathology",
         "Lewy bodies\n(α-synuclein)",
         "Tau (4R)\nNeurofibrillary tangles",
         "GCIs\n(α-synuclein in oligos)",
         "Tau (4R)\nCorticobasal inclusions",
         "Cortical Lewy bodies\n(α-synuclein)",
         "No primary pathology\n(iatrogenic)"],
        ["Progression",
         "Slow (10-20 yrs)",
         "Rapid (5-7 yrs)",
         "Rapid (6-10 yrs)",
         "Rapid (6-8 yrs)",
         "Variable",
         "Reverses on stopping drug"],
    ]

    style_h = ParagraphStyle("th2", fontSize=7.5, textColor=WHITE,
                              fontName="Helvetica-Bold", leading=10,
                              alignment=TA_CENTER)
    style_feat = ParagraphStyle("tf", fontSize=7.5, textColor=WHITE,
                                 fontName="Helvetica-Bold", leading=10,
                                 alignment=TA_LEFT)
    style_cell = ParagraphStyle("tc", fontSize=7, textColor=BLACK,
                                 fontName="Helvetica", leading=9.5,
                                 alignment=TA_LEFT)
    style_pos  = ParagraphStyle("tp", fontSize=7, textColor=GREEN,
                                 fontName="Helvetica-Bold", leading=9.5)

    header_row = [Paragraph(c, style_h if i > 0 else style_h) for i, c in enumerate(cols)]
    table_rows = [header_row]
    for row in rows_data:
        built = []
        for i, cell in enumerate(row):
            if i == 0:
                built.append(Paragraph(cell, style_feat))
            else:
                built.append(Paragraph(cell.replace("✓✓","<font color='#1E8449'><b>✓✓</b></font>").replace("✓","<font color='#1E8449'>✓</font>"), style_cell))
        table_rows.append(built)

    cmds = [
        ("BACKGROUND",    (0,0),(0,0), NAVY),
        ("BACKGROUND",    (1,0),(1,0), GREEN),
        ("BACKGROUND",    (2,0),(2,0), RED),
        ("BACKGROUND",    (3,0),(3,0), PURPLE),
        ("BACKGROUND",    (4,0),(4,0), ORANGE),
        ("BACKGROUND",    (5,0),(5,0), STEEL),
        ("BACKGROUND",    (6,0),(6,0), GREY),
        ("BACKGROUND",    (0,1),( 0,-1), colors.HexColor("#1A3A5C")),
        ("GRID",          (0,0),(-1,-1), 0.3, MGREY),
        ("TOPPADDING",    (0,0),(-1,-1), 3),
        ("BOTTOMPADDING", (0,0),(-1,-1), 3),
        ("LEFTPADDING",   (0,0),(-1,-1), 3),
        ("RIGHTPADDING",  (0,0),(-1,-1), 3),
        ("VALIGN",        (0,0),(-1,-1), "TOP"),
        ("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, LGREY]),
        ("BACKGROUND",    (0,1),(0,-1), NAVY),
    ]
    t = Table(table_rows, colWidths=col_w, repeatRows=1)
    t.setStyle(TableStyle(cmds))
    return t

# ── Red-flag table ────────────────────────────────────────────────────────────
def red_flag_table():
    flags = [
        ("Early severe autonomic failure (yr 1)",       "MSA"),
        ("Recurrent falls within first year",            "PSP / MSA"),
        ("Supranuclear vertical gaze palsy",             "PSP"),
        ("Cerebellar signs (ataxia, nystagmus)",         "MSA-C"),
        ("Bilateral symmetric onset",                    "Drug-induced / MSA / PSP"),
        ("Rapid progression to wheelchair ≤5 yrs",      "MSA / PSP"),
        ("Alien limb / ideomotor apraxia",               "CBS"),
        ("Dementia onset ≤1 year of motor symptoms",    "DLB"),
        ("Recurrent vivid visual hallucinations (early)","DLB"),
        ("Inspiratory stridor / laryngeal dysfunction",  "MSA"),
        ("Antipsychotic / antiemetic use",               "Drug-induced"),
        ("Pyramidal signs (Babinski, hyperreflexia)",    "MSA / CBS"),
        ("History of encephalitis / head trauma",        "Secondary"),
        ("Age <40 yrs at onset",                         "Genetic PD / Wilson's / DRD"),
        ("Absence of any non-motor PD features",         "Atypical / drug-induced"),
        ("No response to high-dose levodopa (≥1000 mg)", "Atypical parkinsonism"),
        ("Normal DaTscan",                               "Drug-induced / ET"),
        ("Normal MIBG cardiac uptake",                   "MSA / PSP / Drug-induced"),
    ]
    hs = ParagraphStyle("fh", fontSize=8, textColor=WHITE,
                        fontName="Helvetica-Bold", leading=11, alignment=TA_CENTER)
    cs = ParagraphStyle("fc", fontSize=7.5, textColor=BLACK,
                        fontName="Helvetica", leading=11)
    ds = ParagraphStyle("fd", fontSize=7.5, textColor=WARN,
                        fontName="Helvetica-Bold", leading=11)

    data = [[Paragraph("RED FLAG / FINDING", hs),
             Paragraph("", hs),
             Paragraph("SUGGESTS", hs)]]
    for flag, dx in flags:
        data.append([
            Paragraph("&#9940;", ParagraphStyle("ic", fontSize=10, textColor=WARN,
                                                 fontName="Helvetica-Bold", leading=11,
                                                 alignment=TA_CENTER)),
            Paragraph(flag, cs),
            Paragraph(dx, ds),
        ])

    t = Table(data, colWidths=[8*mm, 110*mm, 60*mm])
    cmds = [
        ("BACKGROUND",    (0,0),(-1,0), WARN),
        ("GRID",          (0,0),(-1,-1), 0.3, MGREY),
        ("TOPPADDING",    (0,0),(-1,-1), 3),
        ("BOTTOMPADDING", (0,0),(-1,-1), 3),
        ("LEFTPADDING",   (0,0),(-1,-1), 4),
        ("RIGHTPADDING",  (0,0),(-1,-1), 4),
        ("VALIGN",        (0,0),(-1,-1), "MIDDLE"),
        ("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE, colors.HexColor("#FEF9F9")]),
        ("SPAN",          (0,0),(0,0)),
    ]
    t.setStyle(TableStyle(cmds))
    return t

# ── Supportive-features table ─────────────────────────────────────────────────
def supportive_table():
    feats = [
        ("Clear rest tremor (pill-rolling 4-6 Hz)",       "Strong PD"),
        ("Unilateral onset",                               "Strong PD"),
        ("Excellent & sustained levodopa response",        "Strong PD"),
        ("Levodopa-induced dyskinesias",                   "Strong PD"),
        ("Anosmia / hyposmia",                             "PD > others"),
        ("REM sleep behaviour disorder (RBD)",             "PD / DLB / MSA"),
        ("Cardiac sympathetic denervation (low MIBG)",     "PD / DLB"),
        ("Asymmetric DAT loss on DaTscan",                 "PD / CBS"),
        ("Positive family history (1st degree)",           "Genetic PD"),
        ("Age <50 yrs at onset + AR inheritance",          "PARK2 / PINK1 / DJ-1"),
        ("Early constipation / autonomic (premotor yrs)",  "PD (Braak stage 1-2)"),
    ]
    hs = ParagraphStyle("sh", fontSize=8, textColor=WHITE,
                        fontName="Helvetica-Bold", leading=11, alignment=TA_CENTER)
    cs = ParagraphStyle("sc", fontSize=7.5, textColor=BLACK,
                        fontName="Helvetica", leading=11)
    ds = ParagraphStyle("sd", fontSize=7.5, textColor=GREEN,
                        fontName="Helvetica-Bold", leading=11)

    data = [[Paragraph("SUPPORTIVE FEATURE", hs),
             Paragraph("", hs),
             Paragraph("SUGGESTS", hs)]]
    for feat, dx in feats:
        data.append([
            Paragraph("&#10003;", ParagraphStyle("ic2", fontSize=10, textColor=GREEN,
                                                  fontName="Helvetica-Bold", leading=11,
                                                  alignment=TA_CENTER)),
            Paragraph(feat, cs),
            Paragraph(dx, ds),
        ])

    t = Table(data, colWidths=[8*mm, 110*mm, 60*mm])
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,0), GREEN),
        ("GRID",          (0,0),(-1,-1), 0.3, MGREY),
        ("TOPPADDING",    (0,0),(-1,-1), 3),
        ("BOTTOMPADDING", (0,0),(-1,-1), 3),
        ("LEFTPADDING",   (0,0),(-1,-1), 4),
        ("RIGHTPADDING",  (0,0),(-1,-1), 4),
        ("VALIGN",        (0,0),(-1,-1), "MIDDLE"),
        ("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, colors.HexColor("#F0FFF4")]),
    ]))
    return t

# ── Investigations checklist ──────────────────────────────────────────────────
def investigations_table():
    inv = [
        # (test, purpose, interpretation)
        ("DaTscan / FP-CIT SPECT",
         "Confirm nigrostriatal degeneration",
         "Reduced = PD/MSA/PSP/CBS. Normal = Drug-induced or ET"),
        ("Brain MRI (3T preferred)",
         "Exclude secondary causes; atypical patterns",
         "Hummingbird=PSP; Hot cross bun=MSA; Asymm. atrophy=CBS; WM lesions=Vascular"),
        ("MIBG cardiac scintigraphy",
         "Assess cardiac sympathetic innervation",
         "Reduced = PD or DLB. Preserved = MSA/PSP/Drug-induced"),
        ("Levodopa challenge (carbidopa/levodopa)",
         "Confirm dopaminergic response",
         "≥30% UPDRS-III improvement supports PD. Poor response → atypical"),
        ("Autonomic battery (tilt-table, urodynamics, sweat test)",
         "Quantify autonomic failure",
         "Severe early failure → MSA. Mild-moderate → PD"),
        ("Neuropsychological testing",
         "Characterise cognitive profile",
         "Subcortical=PD; Frontal/executive=PSP; Cortical/apraxia=CBS; Global+halluc.=DLB"),
        ("Serum ceruloplasmin + 24h urine copper",
         "Exclude Wilson's disease",
         "Mandatory if age <50 yrs"),
        ("Thyroid function tests (TSH, fT4)",
         "Exclude hypothyroid bradykinesia/tremor",
         "Hypothyroidism may mimic parkinsonism"),
        ("Genetic panel (SNCA, LRRK2, Parkin, PINK1, DJ-1, GBA1)",
         "Identify monogenic PD",
         "Parkin/PINK1: early onset AR. LRRK2: typical PD phenotype. GBA1: risk + severity"),
        ("EEG",
         "DLB workup (if cognitive symptoms)",
         "Posterior slow-wave activity with fluctuation supports DLB"),
        ("CSF alpha-synuclein seed amplification assay (SAA)",
         "Biomarker for synucleinopathy",
         "High sensitivity/specificity for PD/DLB/MSA (emerging standard)"),
        ("Full medication review",
         "Identify dopamine-blocking agents",
         "Antipsychotics, metoclopramide, prochlorperazine, reserpine, valproate"),
    ]
    hs = ParagraphStyle("ih", fontSize=8, textColor=WHITE,
                        fontName="Helvetica-Bold", leading=11, alignment=TA_CENTER)
    cs  = ParagraphStyle("ic3", fontSize=7.5, textColor=BLACK,
                         fontName="Helvetica-Bold", leading=10)
    ps  = ParagraphStyle("ip", fontSize=7, textColor=GREY,
                         fontName="Helvetica", leading=10)
    rs  = ParagraphStyle("ir", fontSize=7, textColor=STEEL,
                         fontName="Helvetica", leading=10)

    data = [[Paragraph("&#9633;", hs),
             Paragraph("INVESTIGATION", hs),
             Paragraph("PURPOSE", hs),
             Paragraph("KEY INTERPRETATION", hs)]]
    for test, purpose, interp in inv:
        data.append([
            Paragraph("&#9633;", ParagraphStyle("cb", fontSize=11, textColor=NAVY,
                                                 fontName="Helvetica-Bold", leading=14,
                                                 alignment=TA_CENTER)),
            Paragraph(test, cs),
            Paragraph(purpose, ps),
            Paragraph(interp, rs),
        ])

    t = Table(data, colWidths=[7*mm, 45*mm, 52*mm, 74*mm])
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,0), STEEL),
        ("GRID",          (0,0),(-1,-1), 0.3, MGREY),
        ("TOPPADDING",    (0,0),(-1,-1), 3),
        ("BOTTOMPADDING", (0,0),(-1,-1), 3),
        ("LEFTPADDING",   (0,0),(-1,-1), 4),
        ("RIGHTPADDING",  (0,0),(-1,-1), 4),
        ("VALIGN",        (0,0),(-1,-1), "TOP"),
        ("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, LGREY]),
    ]))
    return t

# ── Medication checklist table ─────────────────────────────────────────────────
def meds_table():
    drugs = [
        ("Levodopa/Carbidopa\n(Sinemet, Madopar)",
         "First-line; gold standard",
         "Nausea, dyskinesias, wearing-off, hallucinations, orthostasis",
         "PD (all stages); partial MSA"),
        ("Dopamine agonists\nPramipexole / Ropinirole / Rotigotine",
         "Early monotherapy; adjunct to LD",
         "ICD (gambling, hypersexuality), somnolence, hallucinations, nausea, oedema",
         "Early PD; smooth LD response in advanced PD"),
        ("MAO-B inhibitors\nSelegiline / Rasagiline / Safinamide",
         "Early monotherapy; adjunct; possible neuroprotection",
         "Insomnia, headache; serotonin syndrome (avoid SSRIs/SNRIs with selegiline)",
         "Early/mild PD; adjunct for wearing-off"),
        ("COMT inhibitors\nEntacapone / Tolcapone / Opicapone",
         "Prolong levodopa effect; reduce wearing-off",
         "Diarrhoea, dyskinesias, orange urine; Tolcapone: hepatotoxicity (monitor LFTs)",
         "Advanced PD with motor fluctuations"),
        ("Amantadine\n(immediate / extended release)",
         "NMDA antagonist; anti-dyskinetic",
         "Livedo reticularis, oedema, confusion, hallucinations; do NOT stop abruptly",
         "Mild early PD; dyskinesias in advanced PD (ER formulation)"),
        ("Istradefylline\n(Adenosine A2A antagonist)",
         "Reduce OFF-time",
         "Dyskinesias, dizziness, hallucinations, insomnia",
         "Advanced PD as adjunct to LD/CD"),
        ("Anticholinergics\nTrihexyphenidyl / Benztropine",
         "Tremor-dominant PD (young patients)",
         "Confusion, urinary retention, dry mouth, constipation, cognitive impairment",
         "AVOID in elderly; not for atypical syndromes"),
        ("AChEIs\nRivastigmine / Donepezil",
         "Cognitive symptoms in PDD/DLB",
         "Nausea, bradycardia, increased tremor (rivastigmine preferred in PDD)",
         "PDD (rivastigmine FDA-approved); DLB"),
        ("Fludrocortisone / Midodrine",
         "Orthostatic hypotension (MSA/PD)",
         "Supine hypertension, oedema (fludrocortisone); piloerection, urinary retention",
         "MSA and PD autonomic failure"),
        ("Clonazepam / Melatonin",
         "REM sleep behaviour disorder",
         "Clonazepam: sedation, fall risk, dependency; Melatonin: better tolerated",
         "RBD in PD/DLB/MSA"),
        ("Quetiapine / Clozapine\n(AVOID typicals & risperidone/olanzapine)",
         "Psychosis / hallucinations",
         "Clozapine requires WBC monitoring (agranulocytosis); quetiapine: sedation",
         "PD/DLB psychosis ONLY if AChEIs fail"),
        ("Pimavanserin\n(5-HT2A inverse agonist)",
         "PD psychosis (FDA approved)",
         "QT prolongation, falls, oedema",
         "PD-related psychosis; NOT approved for DLB"),
    ]
    hs  = ParagraphStyle("mh", fontSize=8,  textColor=WHITE, fontName="Helvetica-Bold",
                         leading=11, alignment=TA_CENTER)
    ds  = ParagraphStyle("md", fontSize=7.5,textColor=NAVY,  fontName="Helvetica-Bold", leading=10)
    ind = ParagraphStyle("mi", fontSize=7,  textColor=GREY,  fontName="Helvetica", leading=10)
    aes = ParagraphStyle("ma", fontSize=7,  textColor=WARN,  fontName="Helvetica", leading=10)
    ind2= ParagraphStyle("mu", fontSize=7,  textColor=GREEN, fontName="Helvetica-Bold", leading=10)

    data = [[Paragraph("&#9633;",     hs),
             Paragraph("DRUG",        hs),
             Paragraph("INDICATION",  hs),
             Paragraph("ADVERSE EFFECTS", hs),
             Paragraph("USE IN",      hs)]]
    for drug, ind_t, ae, use in drugs:
        data.append([
            Paragraph("&#9633;", ParagraphStyle("cb2", fontSize=11, textColor=NAVY,
                                                 fontName="Helvetica-Bold", leading=14,
                                                 alignment=TA_CENTER)),
            Paragraph(drug, ds),
            Paragraph(ind_t, ind),
            Paragraph(ae, aes),
            Paragraph(use, ind2),
        ])

    t = Table(data, colWidths=[7*mm, 40*mm, 38*mm, 55*mm, 38*mm])
    t.setStyle(TableStyle([
        ("BACKGROUND",    (0,0),(-1,0), TEAL),
        ("GRID",          (0,0),(-1,-1), 0.3, MGREY),
        ("TOPPADDING",    (0,0),(-1,-1), 3),
        ("BOTTOMPADDING", (0,0),(-1,-1), 3),
        ("LEFTPADDING",   (0,0),(-1,-1), 4),
        ("RIGHTPADDING",  (0,0),(-1,-1), 4),
        ("VALIGN",        (0,0),(-1,-1), "TOP"),
        ("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, LGREY]),
    ]))
    return t

# ── Per-diagnosis rapid assessment blocks ─────────────────────────────────────
def dx_block(title, colour, must_haves, against, investigations, management, w=W):
    title_s = ParagraphStyle("dxt", fontSize=9.5, textColor=WHITE,
                              fontName="Helvetica-Bold", leading=13)
    cell_s  = ParagraphStyle("dxc", fontSize=7.5, textColor=BLACK,
                              fontName="Helvetica", leading=11)
    head_s  = ParagraphStyle("dxh", fontSize=7.5, textColor=WHITE,
                              fontName="Helvetica-Bold", leading=11, alignment=TA_CENTER)
    cw = w / 4 - 1*mm

    # header row
    header = Table([[Paragraph(f"&#9633;  {title}", title_s)]],
                   colWidths=[w])
    header.setStyle(TableStyle([
        ("BACKGROUND",(0,0),(-1,-1), colour),
        ("TOPPADDING",(0,0),(-1,-1), 5),
        ("BOTTOMPADDING",(0,0),(-1,-1), 5),
        ("LEFTPADDING",(0,0),(-1,-1), 8),
    ]))

    def sub_col(heading, items, col_c):
        rows = [[Paragraph(heading, head_s)]]
        for item in items:
            rows.append([checkbox(item)])
        t = Table(rows, colWidths=[cw])
        t.setStyle(TableStyle([
            ("BACKGROUND",(0,0),(-1,0), col_c),
            ("GRID",(0,0),(-1,-1), 0.3, MGREY),
            ("TOPPADDING",(0,0),(-1,-1), 2),
            ("BOTTOMPADDING",(0,0),(-1,-1), 2),
            ("LEFTPADDING",(0,0),(-1,-1), 4),
            ("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE, LGREY]),
            ("VALIGN",(0,0),(-1,-1),"TOP"),
        ]))
        return t

    body = Table([[
        sub_col("MUST-HAVES",      must_haves,    colour),
        sub_col("POINTS AGAINST",  against,       WARN),
        sub_col("INVESTIGATIONS",  investigations, STEEL),
        sub_col("MANAGEMENT",      management,     TEAL),
    ]], colWidths=[cw]*4)
    body.setStyle(TableStyle([
        ("TOPPADDING",(0,0),(-1,-1),0),
        ("BOTTOMPADDING",(0,0),(-1,-1),0),
        ("LEFTPADDING",(0,0),(-1,-1),1),
        ("RIGHTPADDING",(0,0),(-1,-1),1),
        ("VALIGN",(0,0),(-1,-1),"TOP"),
    ]))

    outer = Table([[header],[body]], colWidths=[w])
    outer.setStyle(TableStyle([
        ("BOX",(0,0),(-1,-1), 0.8, colour),
        ("TOPPADDING",(0,0),(-1,-1),0),
        ("BOTTOMPADDING",(0,0),(-1,-1),0),
        ("LEFTPADDING",(0,0),(-1,-1),0),
        ("RIGHTPADDING",(0,0),(-1,-1),0),
    ]))
    return outer

# ═══════════════════════════════════════════════════════════════════════════════
#  BUILD STORY
# ═══════════════════════════════════════════════════════════════════════════════
story = []

# ── COVER HEADER ─────────────────────────────────────────────────────────────
story.append(coloured_header(
    "PARKINSONISM  ·  RAPID CLINICAL ASSESSMENT CHECKLIST",
    "Differential Diagnosis · Investigations · Management  |  Specialist Reference  |  August 2026",
    NAVY
))
story.append(sp(6))

# Purpose note
story.append(shaded_box([
    Paragraph("<b>Purpose:</b> This checklist supports rapid bedside differentiation of Parkinson's Disease (PD) from "
              "Atypical Parkinsonism (PSP, MSA, CBS, DLB) and Secondary Parkinsonism. Work through each section "
              "sequentially: confirm parkinsonism → screen for secondary causes → apply red flags → review supportive "
              "features → order targeted investigations → initiate appropriate management.",
              ParagraphStyle("note", fontSize=8, textColor=BLACK, fontName="Helvetica",
                             leading=12, leftIndent=4)),
    Paragraph("<b>Based on:</b> MDS Clinical Diagnostic Criteria for PD (Berg et al.) · Harrison's Principles of "
              "Internal Medicine 22E · Bradley & Daroff's Neurology in Clinical Practice · Katzung Pharmacology 16E",
              ParagraphStyle("src", fontSize=7, textColor=GREY, fontName="Helvetica",
                             leading=10, leftIndent=4)),
], bg=colors.HexColor("#EAF2FF"), border=STEEL))
story.append(sp(8))

# ── STEP 1: Confirm Parkinsonism ──────────────────────────────────────────────
story.append(section_header("STEP 1 · CONFIRM PARKINSONISM  (all three criteria must be assessed)", NAVY))
story.append(sp(3))

step1_data = [
    [Paragraph("<b>ESSENTIAL (required)</b>", ParagraphStyle("s1h", fontSize=8, textColor=WHITE,
               fontName="Helvetica-Bold", leading=11, alignment=TA_CENTER)),
     Paragraph("<b>CORE MOTOR FEATURES  (TRAP)</b>", ParagraphStyle("s1h2", fontSize=8, textColor=WHITE,
               fontName="Helvetica-Bold", leading=11, alignment=TA_CENTER)),
     Paragraph("<b>NON-MOTOR CLUES</b>", ParagraphStyle("s1h3", fontSize=8, textColor=WHITE,
               fontName="Helvetica-Bold", leading=11, alignment=TA_CENTER))],
    ["\n".join([
        "☐  Bradykinesia",
        "     PLUS at least one of:",
        "☐  Rigidity",
        "☐  Rest tremor (4-6 Hz)",
     ]),
     "\n".join([
        "☐  T  — Tremor at rest (pill-rolling)",
        "☐  R  — Rigidity (cogwheel / lead-pipe)",
        "☐  A  — Akinesia / bradykinesia",
        "☐  P  — Postural instability (pull test +)",
        "☐  Flexed posture",
        "☐  Freezing of gait",
     ]),
     "\n".join([
        "☐  Anosmia / hyposmia",
        "☐  Constipation (pre-motor)",
        "☐  REM sleep behaviour disorder",
        "☐  Depression / anxiety",
        "☐  Orthostatic hypotension",
        "☐  Micrographia / hypophonia",
     ])]
]
t1 = Table(step1_data, colWidths=[W/3]*3)
t1.setStyle(TableStyle([
    ("BACKGROUND", (0,0),(0,0), NAVY),
    ("BACKGROUND", (1,0),(1,0), STEEL),
    ("BACKGROUND", (2,0),(2,0), TEAL),
    ("GRID",       (0,0),(-1,-1), 0.3, MGREY),
    ("TOPPADDING", (0,0),(-1,-1), 4),
    ("BOTTOMPADDING",(0,0),(-1,-1), 4),
    ("LEFTPADDING",(0,0),(-1,-1), 6),
    ("FONTNAME",   (0,1),(-1,1), "Helvetica"),
    ("FONTSIZE",   (0,1),(-1,1), 8),
    ("LEADING",    (0,1),(-1,1), 13),
    ("VALIGN",     (0,0),(-1,-1), "TOP"),
    ("ROWBACKGROUNDS",(0,1),(-1,1),[WHITE]),
]))
story.append(t1)
story.append(sp(8))

# ── STEP 2: Exclude Secondary ─────────────────────────────────────────────────
story.append(section_header("STEP 2 · EXCLUDE SECONDARY (NON-DEGENERATIVE) PARKINSONISM", GREY))
story.append(sp(3))
sec_data = [
    ["DRUG-INDUCED (most common secondary cause)",
     "VASCULAR PARKINSONISM",
     "OTHER SECONDARY CAUSES"],
    ["\n".join([
        "☐  Current antipsychotic use",
        "☐  Metoclopramide / prochlorperazine",
        "☐  Reserpine / tetrabenazine",
        "☐  Valproate",
        "☐  Calcium channel blockers (flunarizine)",
        "",
        "Key: Symmetric onset, normal DaTscan",
        "Rx: Stop offending drug → observe 3 months",
     ]),
     "\n".join([
        "☐  Multiple lacunar infarcts on MRI",
        "☐  Periventricular white matter lesions",
        "☐  Lower body predominant gait disorder",
        "☐  Pyramidal signs",
        "☐  History of hypertension / DM / stroke",
        "☐  Stepwise progression",
        "",
        "Rx: Vascular risk factor modification",
     ]),
     "\n".join([
        "☐  Normal pressure hydrocephalus (triad)",
        "☐  Toxin: MPTP, CO, manganese, cyanide",
        "☐  Neoplasm / abscess (MRI)",
        "☐  Postencephalitic parkinsonism",
        "☐  Wilson's disease (age <50)",
        "☐  Metabolic: hypothyroid, hepatic failure",
        "",
        "→ If any secondary cause found: STOP here",
     ])]
]
ths = ParagraphStyle("ths", fontSize=8, textColor=WHITE, fontName="Helvetica-Bold",
                     leading=11, alignment=TA_CENTER)
sec_table_data = [
    [Paragraph(sec_data[0][0], ths),
     Paragraph(sec_data[0][1], ths),
     Paragraph(sec_data[0][2], ths)],
    [Paragraph(sec_data[1][0], ParagraphStyle("st", fontSize=7.5, textColor=BLACK,
               fontName="Helvetica", leading=12)),
     Paragraph(sec_data[1][1], ParagraphStyle("st2", fontSize=7.5, textColor=BLACK,
               fontName="Helvetica", leading=12)),
     Paragraph(sec_data[1][2], ParagraphStyle("st3", fontSize=7.5, textColor=BLACK,
               fontName="Helvetica", leading=12))],
]
t2 = Table(sec_table_data, colWidths=[W/3]*3)
t2.setStyle(TableStyle([
    ("BACKGROUND",(0,0),(0,0), GREY),
    ("BACKGROUND",(1,0),(1,0), colors.HexColor("#78909C")),
    ("BACKGROUND",(2,0),(2,0), colors.HexColor("#546E7A")),
    ("GRID",(0,0),(-1,-1), 0.3, MGREY),
    ("TOPPADDING",(0,0),(-1,-1), 4),
    ("BOTTOMPADDING",(0,0),(-1,-1), 4),
    ("LEFTPADDING",(0,0),(-1,-1), 6),
    ("VALIGN",(0,0),(-1,-1),"TOP"),
]))
story.append(t2)
story.append(sp(8))

# ── STEP 3: Red Flags ─────────────────────────────────────────────────────────
story.append(section_header("STEP 3 · SCREEN FOR RED FLAGS  (each flags against idiopathic PD)", WARN))
story.append(sp(3))
story.append(red_flag_table())
story.append(sp(8))

# ── STEP 4: Supportive features ───────────────────────────────────────────────
story.append(section_header("STEP 4 · SUPPORTIVE FEATURES FOR IDIOPATHIC PD", GREEN))
story.append(sp(3))
story.append(supportive_table())
story.append(sp(8))

# ── STEP 5: Per-Diagnosis Rapid Assessment ────────────────────────────────────
story.append(section_header("STEP 5 · PER-DIAGNOSIS RAPID ASSESSMENT BLOCKS", NAVY))
story.append(sp(4))

# PD
story.append(KeepTogether([
    dx_block(
        "PARKINSON'S DISEASE  (PD)",
        GREEN,
        must_haves=[
            "Bradykinesia + rigidity and/or rest tremor",
            "Asymmetric onset",
            "Clear pill-rolling 4-6 Hz rest tremor",
            "Anosmia / hyposmia",
            "REM sleep behaviour disorder",
            "Excellent sustained levodopa response",
            "Levodopa-induced dyskinesias",
        ],
        against=[
            "Cerebellar signs",
            "Vertical supranuclear gaze palsy",
            "Early severe autonomic failure",
            "Symmetric onset",
            "Falls in first year",
            "Rapid progression (<5 yrs to chair)",
            "Normal DaTscan",
        ],
        investigations=[
            "DaTscan (asymm. post. putamen ↓)",
            "MIBG scintigraphy (reduced)",
            "Brain MRI (usually normal)",
            "CSF SAA (alpha-syn seed amplif.)",
            "Genetic panel if age <50",
            "Levodopa challenge (UPDRS ≥30%↑)",
        ],
        management=[
            "Levodopa/carbidopa (gold standard)",
            "Dopamine agonist (young/early)",
            "MAO-B inhibitor (early/adjunct)",
            "COMT inhibitor (wearing-off)",
            "Amantadine (dyskinesias)",
            "DBS-STN/GPi (advanced, fluct.)",
            "Physiotherapy + speech therapy",
        ]
    ),
    sp(4)
]))

# PSP
story.append(KeepTogether([
    dx_block(
        "PROGRESSIVE SUPRANUCLEAR PALSY  (PSP)",
        RED,
        must_haves=[
            "Vertical supranuclear gaze palsy",
            "(esp. downward gaze slowing)",
            "Early unexplained falls (yr 1)",
            "Axial > limb rigidity",
            "Neck hyperextension (retrocollis)",
            "Frontal/executive cognitive decline",
            "Dysphagia and dysarthria early",
        ],
        against=[
            "Unilateral asymmetric onset",
            "Good levodopa response",
            "Cerebellar signs",
            "Alien limb / apraxia",
            "Early severe visual hallucinations",
            "Preserved vertical gaze",
        ],
        investigations=[
            "MRI: hummingbird / penguin sign",
            "DaTscan (symmetric reduction)",
            "Neuropsych: frontal battery",
            "Video oculomotor assessment",
            "Tau PET (research setting)",
        ],
        management=[
            "Levodopa trial (often poor response)",
            "Falls prevention programme",
            "Physiotherapy (gait, balance)",
            "PEG tube for dysphagia (early)",
            "Supportive / palliative care",
            "Botox for blepharospasm",
        ]
    ),
    sp(4)
]))

# MSA
story.append(KeepTogether([
    dx_block(
        "MULTIPLE SYSTEM ATROPHY  (MSA)",
        PURPLE,
        must_haves=[
            "Autonomic failure (OH, incontinence)",
            "Parkinsonism (MSA-P) OR",
            "Cerebellar ataxia (MSA-C)",
            "Onset <60 yrs typically",
            "Rapid progression",
            "Inspiratory stridor (nocturnal)",
            "Emotional incontinence",
        ],
        against=[
            "Asymmetric onset",
            "Dementia (prominent early)",
            "Lewy body pathology",
            "Normal autonomic function",
            "Good sustained levodopa response",
        ],
        investigations=[
            "MRI: hot cross bun sign (pons)",
            "Putaminal hypointensity (T2*)",
            "Autonomic battery (tilt, QSART)",
            "Urodynamics (detrusor failure)",
            "DaTscan (symmetric ↓)",
            "Sleep study (RBD + stridor)",
        ],
        management=[
            "Levodopa trial (partial in 30-40%)",
            "Fludrocortisone / midodrine (OH)",
            "CPAP / tracheostomy (stridor)",
            "Urological referral (incontinence)",
            "Physiotherapy (ataxia / falls)",
            "PEG tube for dysphagia",
        ]
    ),
    sp(4)
]))

# CBS
story.append(KeepTogether([
    dx_block(
        "CORTICOBASAL SYNDROME  (CBS)",
        ORANGE,
        must_haves=[
            "Markedly asymmetric parkinsonism",
            "Alien limb phenomenon",
            "Ideomotor limb apraxia",
            "Cortical sensory loss",
            "Focal limb dystonia",
            "Myoclonus (stimulus-sensitive)",
            "Nonfluent aphasia (if frontal)",
        ],
        against=[
            "Symmetric onset",
            "Good levodopa response",
            "Vertical gaze palsy early",
            "Cerebellar signs",
            "Prominent early autonomic failure",
        ],
        investigations=[
            "MRI: asymm. frontoparietal atrophy",
            "FDG-PET: asymm. cortical hypometab.",
            "DaTscan: asymmetric ↓",
            "Neuropsych: apraxia battery",
            "Tau PET (4R tauopathy pattern)",
            "Genetic: consider MAPT",
        ],
        management=[
            "Levodopa trial (usually poor)",
            "Clonazepam for myoclonus",
            "OT for apraxia / limb dysfunction",
            "Speech therapy (aphasia)",
            "Physiotherapy",
            "Supportive / palliative care",
        ]
    ),
    sp(4)
]))

# DLB
story.append(KeepTogether([
    dx_block(
        "DEMENTIA WITH LEWY BODIES  (DLB)",
        STEEL,
        must_haves=[
            "Dementia ≤1 yr before motor onset",
            "Recurrent vivid visual hallucinations",
            "Fluctuating cognition / alertness",
            "REM sleep behaviour disorder",
            "Neuroleptic hypersensitivity (SEVERE)",
            "Parkinsonism (mild, symmetric)",
            "Repeated unexplained falls",
        ],
        against=[
            "Dementia >1 yr after motor onset → PDD",
            "Typical antipsychotic tolerated",
            "Early severe autonomic (→ MSA)",
            "Vertical gaze palsy (→ PSP)",
            "Alien limb / apraxia (→ CBS)",
        ],
        investigations=[
            "MIBG scintigraphy: reduced ✓",
            "DaTscan: bilateral ↓ (sym.)",
            "EEG: posterior slow waves",
            "FDG-PET: occipital hypometab.",
            "CSF SAA (alpha-syn): positive",
            "Neuropsych: visuospatial deficits",
        ],
        management=[
            "AChEIs (rivastigmine / donepezil)",
            "AVOID typical antipsychotics",
            "AVOID risperidone / olanzapine",
            "Quetiapine / clozapine (psychosis)",
            "Melatonin / clonazepam (RBD)",
            "Low-dose levodopa (motor sx)",
        ]
    ),
    sp(4)
]))

# ── STEP 6: Investigations ────────────────────────────────────────────────────
story.append(section_header("STEP 6 · INVESTIGATIONS CHECKLIST", STEEL))
story.append(sp(3))
story.append(investigations_table())
story.append(sp(8))

# ── STEP 7: Medications ────────────────────────────────────────────────────────
story.append(section_header("STEP 7 · MEDICATION CHECKLIST  (with adverse effect profile)", TEAL))
story.append(sp(3))
story.append(meds_table())
story.append(sp(8))

# ── STEP 8: Full comparison table ────────────────────────────────────────────
story.append(section_header("STEP 8 · RAPID COMPARISON TABLE  (PD vs. All Atypical Syndromes)", NAVY))
story.append(sp(3))
story.append(comparison_table())
story.append(sp(8))

# ── STEP 9: Diagnostic certainty ─────────────────────────────────────────────
story.append(section_header("STEP 9 · MDS DIAGNOSTIC CERTAINTY LEVELS  (for PD)", NAVY))
story.append(sp(3))

cert_data = [
    [Paragraph("<b>CLINICALLY ESTABLISHED PD</b>", ParagraphStyle("c1h", fontSize=8.5, textColor=WHITE,
               fontName="Helvetica-Bold", leading=12, alignment=TA_CENTER)),
     Paragraph("<b>CLINICALLY PROBABLE PD</b>", ParagraphStyle("c2h", fontSize=8.5, textColor=WHITE,
               fontName="Helvetica-Bold", leading=12, alignment=TA_CENTER)),
     Paragraph("<b>ABSOLUTE EXCLUSION CRITERIA</b>", ParagraphStyle("c3h", fontSize=8.5, textColor=WHITE,
               fontName="Helvetica-Bold", leading=12, alignment=TA_CENTER))],
    ["\n".join([
        "☐  Parkinsonism (core feature)",
        "☐  No absolute exclusion criteria",
        "☐  ≥2 supportive criteria",
        "☐  No red flags",
        "",
        "→ Specificity >90% for PD pathology",
     ]),
     "\n".join([
        "☐  Parkinsonism (core feature)",
        "☐  No absolute exclusion criteria",
        "☐  ≥1 supportive criteria",
        "☐  Red flags balanced by equal",
        "     number of supportive criteria",
        "→ Lower certainty; monitor over time",
     ]),
     "\n".join([
        "☒  Cerebellar abnormalities",
        "☒  Downward vertical gaze palsy",
        "☒  FTD / PPA in first 5 yrs",
        "☒  Lower limb parkinsonism >3 yrs",
        "☒  Dopaminergic drug causing parkin.",
        "☒  No response to high-dose levodopa",
        "☒  Cortical sensory loss, apraxia",
     ])]
]

cert_table = Table([
    [Paragraph("<b>CLINICALLY ESTABLISHED PD</b>", ParagraphStyle("c1h", fontSize=8.5, textColor=WHITE,
               fontName="Helvetica-Bold", leading=12, alignment=TA_CENTER)),
     Paragraph("<b>CLINICALLY PROBABLE PD</b>", ParagraphStyle("c2h", fontSize=8.5, textColor=WHITE,
               fontName="Helvetica-Bold", leading=12, alignment=TA_CENTER)),
     Paragraph("<b>ABSOLUTE EXCLUSION CRITERIA</b>", ParagraphStyle("c3h", fontSize=8.5, textColor=WHITE,
               fontName="Helvetica-Bold", leading=12, alignment=TA_CENTER))],
    [Paragraph(cert_data[1][0], ParagraphStyle("cv", fontSize=7.5, textColor=BLACK,
               fontName="Helvetica", leading=12)),
     Paragraph(cert_data[1][1], ParagraphStyle("cv2", fontSize=7.5, textColor=BLACK,
               fontName="Helvetica", leading=12)),
     Paragraph(cert_data[1][2], ParagraphStyle("cv3", fontSize=7.5, textColor=WARN,
               fontName="Helvetica", leading=12))],
], colWidths=[W/3]*3)
cert_table.setStyle(TableStyle([
    ("BACKGROUND",(0,0),(0,0), GREEN),
    ("BACKGROUND",(1,0),(1,0), STEEL),
    ("BACKGROUND",(2,0),(2,0), WARN),
    ("GRID",(0,0),(-1,-1), 0.3, MGREY),
    ("TOPPADDING",(0,0),(-1,-1),5),
    ("BOTTOMPADDING",(0,0),(-1,-1),5),
    ("LEFTPADDING",(0,0),(-1,-1),6),
    ("VALIGN",(0,0),(-1,-1),"TOP"),
]))
story.append(cert_table)
story.append(sp(8))

# ── FOOTER ───────────────────────────────────────────────────────────────────
story.append(shaded_box([
    Paragraph(
        "<b>Notes / Clinical observations:</b>",
        ParagraphStyle("noteh", fontSize=8, textColor=NAVY, fontName="Helvetica-Bold", leading=12)
    ),
    Paragraph("_" * 140, ParagraphStyle("line", fontSize=8, textColor=MGREY, leading=14)),
    Paragraph("_" * 140, ParagraphStyle("line", fontSize=8, textColor=MGREY, leading=14)),
    Paragraph("_" * 140, ParagraphStyle("line", fontSize=8, textColor=MGREY, leading=14)),
    sp(4),
    Paragraph(
        "Patient Name: ________________________   DOB: ______________   Clinician: ________________________   Date: ______________",
        ParagraphStyle("pid", fontSize=8, textColor=GREY, fontName="Helvetica", leading=12)
    ),
], bg=colors.HexColor("#F8FBFF"), border=STEEL))
story.append(sp(4))

story.append(Paragraph(
    "Sources: Harrison's Principles of Internal Medicine 22E · Bradley & Daroff's Neurology in Clinical Practice · "
    "Katzung Basic & Clinical Pharmacology 16E · MDS Clinical Diagnostic Criteria for Parkinson's Disease (Berg et al.) · "
    "Adams & Victor's Principles of Neurology 12E · Washington Manual of Medical Therapeutics",
    sNote
))

# ── BUILD ─────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF saved: {OUT}")
print(f"Size: {os.path.getsize(OUT)//1024} KB")
Running Command

cd /tmp/workspace/parkinsonism-workbook && python checklist.py 2>&1

Your checklist is ready:

Parkinsonism DDx Checklist

PDF Document · PDF


Here is what the checklist contains, organized as a 9-step sequential clinical workflow:
Step 1 - Confirm Parkinsonism: Mandatory TRAP criteria (Tremor, Rigidity, Akinesia, Postural instability) plus non-motor clues checklist.
Step 2 - Exclude Secondary Parkinsonism: Three columns covering drug-induced (antipsychotics, metoclopramide), vascular (MRI white matter, lower-body gait), and other causes (NPH, toxins, Wilson's, metabolic).
Step 3 - Red Flags Screen: 18 red flags tabulated with the diagnosis each one points toward - vertical gaze palsy (PSP), stridor (MSA), alien limb (CBS), dementia ≤1 year (DLB), symmetric onset (drug-induced), normal DaTscan (drug-induced), etc.
Step 4 - Supportive Features for PD: 11 items that raise confidence in idiopathic PD (unilateral onset, rest tremor, anosmia, RBD, reduced MIBG, levodopa-induced dyskinesias, etc.).
Step 5 - Per-Diagnosis Rapid Assessment Blocks: Five colour-coded blocks (PD, PSP, MSA, CBS, DLB), each with four columns - Must-Haves, Points Against, Investigations, Management.
Step 6 - Investigations Checklist: 12 tests (DaTscan, MRI, MIBG, levodopa challenge, autonomic battery, genetics, CSF SAA, etc.) with checkbox, purpose, and how to interpret the result.
Step 7 - Medication Checklist: 12 drug classes with indication, adverse effect profile (highlighted in red), and which syndrome each applies to. Includes the critical reminder to avoid typical antipsychotics and risperidone in DLB.
Step 8 - Full Comparison Table: 13 clinical/pathological features compared side-by-side across all 6 diagnosis categories.
Step 9 - MDS Diagnostic Certainty: Clinically Established PD vs. Clinically Probable PD vs. Absolute Exclusion Criteria, with tick-box format.
The last section includes a free-text notes area and a patient/clinician ID line for use as a point-of-care document.

Create clinical practice guideline with infographics

Building a comprehensive Clinical Practice Guideline (CPG) for Parkinsonism as a professional PDF with embedded infographic pages. Starting now.
Generating Image

A clean professional medical infographic titled "Parkinsonism: Step-by-Step Diagnostic Algorithm" showing a vertical flowchart with 5 decision nodes. Start at top: "Parkinsonism Confirmed (Bradykinesia + Rigidity/Tremor)" in dark navy box. Arrow down to diamond decision: "Secondary cause identified? (Drugs, Vascular, Toxins, NPH, Metabolic)" - YES branch goes right to green box "Treat underlying cause". NO branch continues down to diamond: "Red flags present? (Early falls, Vertical gaze palsy, Cerebellar signs, Symmetric onset, Early autonomic failure)" - YES branch to orange box listing "Atypical Parkinsonism workup: MRI, DaTscan, autonomic testing". NO branch continues down to diamond: "Supportive features present? (Asymmetric onset, Rest tremor, Anosmia, RBD, Levodopa response)". YES leads to green box "Clinically Established Parkinson's Disease". Alongside show two smaller boxes: "MDS Criteria: ≥2 supportive + 0 red flags = Established PD" and "DaTscan + MIBG for confirmation". At bottom a row of 5 colored mini-boxes: PD (green), PSP (red), MSA (purple), CBS (orange), DLB (blue). Professional, clean, white background, modern medical style.

Generating Image

A professional medical infographic titled "Pharmacological Management of Parkinson's Disease" showing a tiered treatment pyramid/ladder. At the base (widest, green): "Levodopa/Carbidopa - Gold Standard - All stages". Second tier (blue): "Dopamine Agonists: Pramipexole, Ropinirole, Rotigotine patch - Early disease or adjunct". Third tier (teal): "MAO-B Inhibitors: Rasagiline, Selegiline, Safinamide - Early monotherapy or adjunct for wearing-off". Fourth tier (orange): "COMT Inhibitors: Entacapone, Opicapone - Advanced disease, reduce wearing-off". Fifth tier (purple): "Amantadine - Anti-dyskinetic, NMDA antagonist". Top tier (red): "Surgical: Deep Brain Stimulation STN/GPi - Advanced motor fluctuations". On the right side show a vertical timeline: "Early PD → Moderate PD → Advanced PD" with corresponding drug layers highlighted. Below show a warning box in red: "AVOID in DLB: Typical antipsychotics, Risperidone, Olanzapine". Professional, clinical, color-coded, white background.

Generating Image

A professional medical infographic titled "Non-Motor Features of Parkinson's Disease: Recognition & Management" with a human body silhouette in the center. Around the body, connect labeled organ/system boxes with arrows pointing to the silhouette: BRAIN (top): "Cognitive decline, Dementia (PDD), Depression, Anxiety, Hallucinations, Impulse control disorders" - treat with AChEIs, SSRIs, quetiapine. NOSE: "Anosmia - earliest pre-motor biomarker". EYES: "Visual hallucinations, REM sleep disorder". HEART: "Cardiac sympathetic denervation - MIBG reduced". GUT (abdomen): "Constipation, Dysphagia, Gastroparesis, Nausea on levodopa - Braak stage 1". BLADDER: "Urinary urgency/frequency/incontinence". LEGS/CIRCULATION: "Orthostatic hypotension - Fludrocortisone/Midodrine". SKIN: "Seborrhoea, Excessive sweating". At bottom a timeline bar showing: "Pre-motor phase (years before diagnosis) → Motor onset → Motor + Non-motor → Advanced". Professional, clean, medical illustration style, color-coded by system.

Generating Image

A professional medical comparison infographic titled "Atypical Parkinsonism: At-a-Glance Comparison" showing 4 condition cards side by side. PSP card (red): brain icon with downward gaze arrow, bullet points: Vertical gaze palsy, Early falls, Retrocollis, Tau pathology, Hummingbird MRI sign, Poor levodopa response. MSA card (purple): autonomic system icon, bullet points: Severe autonomic failure, Cerebellar ataxia, Inspiratory stridor, Hot cross bun MRI sign, Alpha-synuclein oligodendrocytes, Poor levodopa. CBS card (orange): asymmetric limb icon, bullet points: Alien limb phenomenon, Ideomotor apraxia, Cortical sensory loss, Markedly asymmetric, Tau pathology, Levodopa-resistant. DLB card (blue): brain with Lewy body icon, bullet points: Dementia before/with motor, Visual hallucinations, Fluctuating cognition, RBD, Neuroleptic DANGER, Reduced MIBG. Below each card a small MRI brain image label showing the characteristic finding. Bottom row: treatment summary for each. Clean, modern, professional medical design, white background, distinct color coding for each condition.

!

Error calling model 'gemini-3-pro-image' (RESOURCE_EXHAUSTED): 429 RESOURCE_EXHAUSTED. {'error': {'code': 429, 'message': 'Resource has been exhausted (e.g. check quota).', 'status': 'RESOURCE_EXHAUSTED'}}

We encountered an error while processing your request. Please try again or reach out to us for help.

Create clinical practice guideline with infographics

Building a full Clinical Practice Guideline PDF with embedded matplotlib infographic pages. This will be a complete, self-contained document.
Running Command

mkdir -p /tmp/workspace/parkinsonism-cpg/assets && echo "ready"

Create clinical practice guideline with infographics

Building a full Clinical Practice Guideline PDF with embedded infographic pages — all in one script.
Running Command

mkdir -p /tmp/workspace/parkinsonism-cpg/assets && python3 - <<'PYEOF' import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import matplotlib.patches as mpatches from matplotlib.patches import FancyBboxPatch, FancyArrowPatch from matplotlib.patches import Polygon as MplPolygon import textwrap, os ASSET = "/tmp/workspace/parkinsonism-cpg/assets" # ── palette ────────────────────────────────────────────────────────────────── NAVY = "#1A3A5C"; GREEN = "#1E8449"; RED = "#922B21" PURPLE = "#6C3483"; ORANGE = "#B7770D"; STEEL = "#2471A3" TEAL = "#117A65"; WARN = "#C0392B"; LGREY = "#F2F3F4" MGREY = "#BDC3C7"; WHITE = "white"; BLACK = "#1A1A1A" GOLD = "#D4AC0D" def fbox(ax, cx, cy, w, h, txt, fc, tc="white", fs=9, bold=False, wrap=True, lsp=1.35): rx, ry = cx-w/2, cy-h/2 p = FancyBboxPatch((rx,ry),w,h, boxstyle="round,pad=0.12", fc=fc, ec="white", lw=1.4, zorder=3) ax.add_patch(p) t = textwrap.fill(txt, width=max(8,int(w*9))) if wrap else txt ax.text(cx, cy, t, ha="center", va="center", fontsize=fs, color=tc, fontweight="bold" if bold else "normal", linespacing=lsp, zorder=4, multialignment="center") def diamond(ax, cx, cy, w, h, txt, fc, tc="white", fs=8.5): pts = [(cx,cy+h/2),(cx+w/2,cy),(cx,cy-h/2),(cx-w/2,cy)] poly = MplPolygon(pts, closed=True, fc=fc, ec="white", lw=1.4, zorder=3) ax.add_patch(poly) t = textwrap.fill(txt, width=max(6,int(w*6.5))) ax.text(cx,cy,t,ha="center",va="center",fontsize=fs, color=tc,fontweight="bold",zorder=4,multialignment="center",linespacing=1.25) def arr(ax,x1,y1,x2,y2,lbl="",lc="#444",lbl_off=(0,0)): ax.annotate("",xy=(x2,y2),xytext=(x1,y1), arrowprops=dict(arrowstyle="->",color=lc,lw=1.8),zorder=2) if lbl: mx,my=(x1+x2)/2+lbl_off[0],(y1+y2)/2+lbl_off[1] ax.text(mx,my,lbl,ha="center",va="center",fontsize=8,color=lc, fontweight="bold", bbox=dict(fc="white",ec="none",alpha=0.9,pad=1.5),zorder=5) # ════════════════════════════════════════════════════════════════════════════ # INFOGRAPHIC 1 — Diagnostic Algorithm # ════════════════════════════════════════════════════════════════════════════ fig,ax = plt.subplots(figsize=(14,20)); ax.set_xlim(0,14); ax.set_ylim(0,20); ax.axis("off") fig.patch.set_facecolor("#F7F9FC") ax.text(7,19.5,"PARKINSONISM: STEP-BY-STEP DIAGNOSTIC ALGORITHM", ha="center",va="center",fontsize=14,fontweight="bold",color=NAVY) ax.text(7,19.1,"Based on MDS Clinical Diagnostic Criteria · Harrison's 22E · Bradley & Daroff's Neurology", ha="center",va="center",fontsize=8.5,color="#555",style="italic") # Node 1 — Entry fbox(ax,7,18.3,10,0.85, "PATIENT PRESENTS WITH SUSPECTED PARKINSONISM\nBradykinesia + Rigidity and/or Rest Tremor", NAVY,fs=10,bold=True) arr(ax,7,17.88,7,17.2) # Node 2 — Secondary diamond(ax,7,16.7,10,0.95, "Identifiable secondary cause?\n(Drugs · Vascular · Toxin · NPH · Metabolic · Infection)", STEEL,fs=8.5) fbox(ax,12,16.7,3.2,1.0, "SECONDARY\nPARKINSONISM\n→ Treat cause", TEAL,fs=8.5) arr(ax,12,16.22,12,15.6) fbox(ax,12,15.2,3.2,0.75, "Stop drug (DIP)\nVascular Rx factors\nNPH → shunt eval.", TEAL,tc="white",fs=7.5) ax.text(9.7,16.82,"YES",ha="center",va="center",fontsize=8,color=TEAL,fontweight="bold", bbox=dict(fc="white",ec="none",alpha=0.9)) arr(ax,7,16.22,7,15.5) ax.text(7.3,15.85,"NO",ha="center",va="center",fontsize=8,color="#333",fontweight="bold", bbox=dict(fc="white",ec="none",alpha=0.9)) # Node 3 — Red Flags diamond(ax,7,15.0,10,0.9, "Red Flags present?\n(Vertical gaze palsy · Early falls · Cerebellar · Symmetric · Severe autonomic)", WARN,fs=8.5) fbox(ax,12,15.0,3.2,1.0, "ATYPICAL\nPARKINSONISM\nWorkup ↓", WARN,fs=8.5) ax.text(9.7,15.1,"YES →",ha="center",va="center",fontsize=8,color=WARN,fontweight="bold", bbox=dict(fc="white",ec="none",alpha=0.9)) arr(ax,7,14.55,7,13.8) ax.text(7.3,14.15,"NO",ha="center",va="center",fontsize=8,color="#333",fontweight="bold", bbox=dict(fc="white",ec="none",alpha=0.9)) # Atypical workup box fbox(ax,12,14.0,3.2,1.8, "MRI Brain\nDaTscan / SPECT\nAutonomic battery\nNeuropsych testing\nLevodopa challenge", "#7B241C",fs=7.5) arr(ax,12,15.5,12,14.9) # Node 4 — Supportive diamond(ax,7,13.3,10,0.9, "≥2 Supportive Features? No Red Flags?\n(Asymm. onset · Rest tremor · Anosmia · RBD · Levodopa response)", GREEN,fs=8.5) arr(ax,7,12.85,7,12.1) ax.text(7.3,12.45,"YES",ha="center",va="center",fontsize=8,color=GREEN,fontweight="bold", bbox=dict(fc="white",ec="none",alpha=0.9)) arr(ax,2,13.3,2,12.3) ax.text(3.85,13.3,"NO / 1 FEATURE →",ha="right",va="center",fontsize=8,color=STEEL,fontweight="bold", bbox=dict(fc="white",ec="none",alpha=0.9)) ax.annotate("",xy=(2,13.3),xytext=(2.1,13.3), arrowprops=dict(arrowstyle="<-",color=STEEL,lw=1.5),zorder=2) fbox(ax,2,11.9,3.5,0.8, "Clinically PROBABLE PD\n(Monitor; repeat levodopa trial)", STEEL,fs=8) # Node 5 — PD fbox(ax,7,11.6,10,0.85, "CLINICALLY ESTABLISHED PARKINSON'S DISEASE", GREEN,fs=10.5,bold=True) # PD details pd_box = ( "DaTscan: asymmetric posterior putamen ↓ | MIBG: cardiac sympathetic denervation\n" "Pathology: Lewy bodies (α-synuclein) in SNc | Genetics if age <50: SNCA · LRRK2 · Parkin · PINK1" ) fbox(ax,7,10.85,12,0.7,pd_box, "#EAF9ED",tc=BLACK,fs=8,wrap=False) # Atypical row dxs = [ ("PSP","Vertical gaze palsy\nRetropulsion falls\nHummingbird MRI",RED), ("MSA","Autonomic failure\nCerebellar ataxia\nHot cross bun MRI",PURPLE), ("CBS","Alien limb\nApraxia · Myoclonus\nAsymm. cortical atrophy",ORANGE), ("DLB","Dementia ≤1 yr\nVisual hallucinations\nNeuroleptic DANGER",STEEL), ] ax.text(7,9.95,"ATYPICAL PARKINSONISM — KEY DISTINGUISHING FEATURES", ha="center",fontsize=9.5,fontweight="bold",color=NAVY) for i,(name,txt,col) in enumerate(dxs): cx = 1.8 + i*3.15 fbox(ax,cx,9.5,2.9,0.65,name,col,fs=9,bold=True) fbox(ax,cx,8.85,2.9,1.05,txt,col,fs=7.5,tc="white",lsp=1.4) # Investigations row inv = [ ("DaTscan","Confirms nigrostriatal\ndegeneration\n(not drug-induced/ET)",STEEL), ("Brain MRI","Hummingbird=PSP\nHot cross bun=MSA\nWM lesions=Vascular",NAVY), ("MIBG","Low = PD/DLB\nPreserved = MSA/PSP",TEAL), ("Levodopa\nChallenge","≥30% UPDRS↑\n= strong PD support",GREEN), ("Autonomic\nBattery","Severe early = MSA\nMild = PD autonomic",ORANGE), ] ax.text(7,8.0,"KEY INVESTIGATIONS", ha="center",fontsize=9.5,fontweight="bold",color=NAVY) for i,(name,txt,col) in enumerate(inv): cx = 1.4 + i*2.65 fbox(ax,cx,7.5,2.4,0.65,name,col,fs=8.5,bold=True) fbox(ax,cx,6.8,2.4,0.95,txt,col,fs=7.2,tc="white",lsp=1.35) # Genetic box ax.text(7,5.95,"GENETIC TESTING — CONSIDER IF AGE <50 OR FAMILY HISTORY", ha="center",fontsize=9,fontweight="bold",color=NAVY) genes = [("LRRK2\n(PARK8)","AD, typical PD\nNorth African/\nAshkenazi",STEEL), ("Parkin\n(PARK2)","AR, up to 50%\nearly-onset PD",GREEN), ("PINK1\n(PARK6)","AR, early onset\nmitochondrial",TEAL), ("SNCA\n(PARK1)","AD, rare\nα-synuclein\nmutations",RED), ("GBA1","Risk factor +\nfaster progression\nLysosomal",PURPLE)] for i,(name,txt,col) in enumerate(genes): cx = 1.4 + i*2.65 fbox(ax,cx,5.45,2.4,0.65,name,col,fs=8.5,bold=True) fbox(ax,cx,4.75,2.4,0.95,txt,col,fs=7.2,tc="white",lsp=1.35) ax.text(7,0.3,"Sources: Harrison's Principles of Internal Medicine 22E · MDS Diagnostic Criteria (Berg et al.) · " "Bradley & Daroff's Neurology", ha="center",fontsize=7,color="#777",style="italic") plt.tight_layout(pad=0.3) plt.savefig(f"{ASSET}/infographic_01_diagnosis.png",dpi=150,bbox_inches="tight", facecolor=fig.get_facecolor()) plt.close() print("Saved infographic_01") PYEOF echo "Exit: $?"

Running Command

python3 - <<'PYEOF' import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import matplotlib.patches as mpatches from matplotlib.patches import FancyBboxPatch from matplotlib.patches import Polygon as MplPolygon import textwrap ASSET = "/tmp/workspace/parkinsonism-cpg/assets" NAVY="#1A3A5C";GREEN="#1E8449";RED="#922B21";PURPLE="#6C3483" ORANGE="#B7770D";STEEL="#2471A3";TEAL="#117A65";WARN="#C0392B" WHITE="white";BLACK="#1A1A1A";LGREY="#F2F3F4";MGREY="#BDC3C7" def fbox(ax,cx,cy,w,h,txt,fc,tc="white",fs=9,bold=False,lsp=1.35,wrap=True,pad=0.12): p=FancyBboxPatch((cx-w/2,cy-h/2),w,h,boxstyle=f"round,pad={pad}", fc=fc,ec="white",lw=1.3,zorder=3) ax.add_patch(p) t=textwrap.fill(txt,width=max(6,int(w*9))) if wrap else txt ax.text(cx,cy,t,ha="center",va="center",fontsize=fs,color=tc, fontweight="bold" if bold else "normal",linespacing=lsp, zorder=4,multialignment="center") def arr(ax,x1,y1,x2,y2,lc="#444"): ax.annotate("",xy=(x2,y2),xytext=(x1,y1), arrowprops=dict(arrowstyle="->",color=lc,lw=2),zorder=2) # ════════════════════════════════════════════════════════════════════════════ # INFOGRAPHIC 2 — Treatment Algorithm # ════════════════════════════════════════════════════════════════════════════ fig,ax=plt.subplots(figsize=(16,22)); ax.set_xlim(0,16); ax.set_ylim(0,22); ax.axis("off") fig.patch.set_facecolor("#F7F9FC") ax.text(8,21.5,"PARKINSON'S DISEASE: PHARMACOLOGICAL MANAGEMENT ALGORITHM", ha="center",fontsize=14,fontweight="bold",color=NAVY) ax.text(8,21.1,"Clinical Practice Guideline · Specialist Level · Based on MDS/AAN Guidelines & Katzung Pharmacology 16E", ha="center",fontsize=8.5,color="#555",style="italic") # Stage labels for y,lbl,col in [(19.5,"EARLY PD\n(Mild symptoms, functional impairment minor)",GREEN), (15.5,"MODERATE PD\n(Motor fluctuations beginning, wearing-off)",STEEL), (10.5,"ADVANCED PD\n(Dyskinesias, motor fluctuations, non-motor burden)",ORANGE), (5.5,"REFRACTORY / SURGICAL\n(Drug-resistant fluctuations & dyskinesias)",RED)]: fbox(ax,2,y,3.5,0.95,lbl,col,fs=8.5,bold=True) # ── EARLY PD ────────────────────────────────────────────────────────────── fbox(ax,9,20.5,10,0.75, "CONFIRM DIAGNOSIS · Educate patient · Multidisciplinary team referral · Exercise programme", NAVY,fs=9,bold=True) arr(ax,8,20.12,8,19.5) # Decision: Age / cognitive from matplotlib.patches import Polygon as P2 def diam(ax,cx,cy,w,h,txt,fc,fs=8.5): pts=[(cx,cy+h/2),(cx+w/2,cy),(cx,cy-h/2),(cx-w/2,cy)] ax.add_patch(P2(pts,closed=True,fc=fc,ec="white",lw=1.4,zorder=3)) ax.text(cx,cy,textwrap.fill(txt,width=int(w*6)),ha="center",va="center", fontsize=fs,color="white",fontweight="bold",zorder=4,multialignment="center",linespacing=1.2) diam(ax,8,19.0,9,0.9,"Age <70 AND no significant cognitive impairment?",STEEL,fs=8.5) ax.text(12.7,19.1,"YES →",ha="center",fontsize=8,color=GREEN,fontweight="bold") ax.text(3.7,18.45,"NO ↓",ha="center",fontsize=8,color=WARN,fontweight="bold") # YES branch — young / cognitively intact fbox(ax,13.5,18.55,4.5,1.65, "DOPAMINE AGONIST\nPramipexole · Ropinirole · Rotigotine\n\nOR MAO-B INHIBITOR\nRasagiline · Selegiline\n(Delay levodopa, reduce dyskinesia risk)", GREEN,fs=8,lsp=1.5) arr(ax,11.4,18.55,13.5-2.25,18.55,lc=GREEN) # NO branch — older / cognitive fbox(ax,8,17.55,9.5,1.5, "LEVODOPA / CARBIDOPA (Sinemet / Madopar) — GOLD STANDARD\n" "Start: 100/25 mg TID · Titrate by 50-100 mg/wk to symptom control\n" "Target: lowest effective dose · Extended release for nocturnal symptoms", GREEN,fs=8.5,bold=True,lsp=1.5) arr(ax,8,18.55,8,18.32) ax.text(8,16.65,"If symptoms not adequately controlled, or if dopamine agonist used → ADD levodopa", ha="center",fontsize=8,color="#444",style="italic") # ── MODERATE PD ──────────────────────────────────────────────────────────── arr(ax,8,16.4,8,15.85) fbox(ax,8,15.4,13.5,0.8, "ASSESS FOR MOTOR FLUCTUATIONS · Wearing-off? · Dyskinesias? · On-off unpredictability?", STEEL,fs=9,bold=True) arr(ax,8,15.0,8,14.4) # 3-column moderate options cols_mod = [ ("WEARING-OFF\n→ Add COMT inhibitor\nEntacapone 200mg with each LD dose\nOR Opicapone 50mg OD\nOR Extended-release LD\nOR MAO-B inhibitor adjunct",STEEL), ("ADD DOPAMINE AGONIST\n(if not already on one)\nPramipexole ER / Ropinirole XL\nOR Rotigotine patch\n→ Smooth dopaminergic\nstimulation; less wearing-off",GREEN), ("ISTRADEFYLLINE\n(Adenosine A2A antagonist)\n20-40 mg OD\n→ Reduces OFF-time\nas adjunct to LD/carbidopa\nCan add 20-45 min ON-time/day",TEAL), ] for i,(txt,col) in enumerate(cols_mod): cx=4+i*4 fbox(ax,cx,13.6,3.7,1.5,txt,col,fs=7.8,lsp=1.4) # ── ADVANCED PD ──────────────────────────────────────────────────────────── arr(ax,8,12.82,8,12.2) fbox(ax,8,11.75,13.5,0.8, "ADVANCED PD: Dyskinesias · Severe off-periods · Non-motor burden · Cognitive decline", ORANGE,fs=9,bold=True) cols_adv = [ ("DYSKINESIAS\n→ Amantadine\n(NMDA antagonist)\n100mg BD/TID\nOR ER amantadine\n(Gocovri) at bedtime\n→ Reduce LD peak dose",ORANGE), ("PSYCHOSIS /\nHALLUCINATIONS\n→ Stop anticholinergics\n→ AChEI (rivastigmine)\n→ Quetiapine (low dose)\n→ Clozapine (monitoring)\n→ Pimavanserin",PURPLE), ("AUTONOMIC\nFAILURE\n→ OH: fludrocortisone\n midodrine\n→ Constipation: bulk\n→ Bladder: oxybutynin\n→ ED: PDE5 inhibitors",TEAL), ("COGNITIVE\nDECLINE\n→ Rivastigmine\n (FDA-approved PDD)\n→ Donepezil\n→ Memantine (severe)\n→ AVOID anticholinergics",STEEL), ] arr(ax,8,11.35,8,10.85) for i,(txt,col) in enumerate(cols_adv): cx=2.5+i*3.7 fbox(ax,cx,9.9,3.3,1.7,txt,col,fs=7.5,lsp=1.4) # ── SURGICAL ─────────────────────────────────────────────────────────────── arr(ax,8,9.0,8,8.35) fbox(ax,8,7.9,13.5,0.8, "SURGICAL INTERVENTION — Consider when motor fluctuations persist despite optimised pharmacotherapy", RED,fs=9,bold=True) surgical = [ ("DEEP BRAIN STIMULATION\n(DBS)\nSTN or GPi target\nBest: Good levodopa\nresponder, <70 yrs,\nno dementia, no psychosis\nImproves ON-time ~4-6h/day",RED), ("LEVODOPA-\nCARBIDOPA\nINTESTINAL GEL\n(LCIG / Duodopa)\nContinuous infusion\nvia PEG-J tube\nReduces OFF time",RED), ("FOCUSED\nULTRASOUND\nTHALAMOTOMY\nBest for unilateral\ntremor-dominant PD\nNon-invasive\nNo implant",RED), ("RADIOSURGICAL\nPALLIDOTOMY\n/ THALAMOTOMY\nGamma knife\nFor patients not\nsuitable for DBS\nor FUS",RED), ] arr(ax,8,7.5,8,6.9) for i,(txt,col) in enumerate(surgical): cx=2.5+i*3.7 fbox(ax,cx,6.0,3.3,1.6,txt,col,fs=7.5,lsp=1.4) # MDT box fbox(ax,8,4.5,14,1.2, "MULTIDISCIPLINARY CARE (all stages)\n" "Physiotherapy (gait, balance, exercise) · Speech & Language Therapy (hypophonia, dysphagia)\n" "Occupational Therapy · Neuropsychology · Palliative care (advanced) · Patient support groups", NAVY,fs=8.5,lsp=1.5) # Non-pharm fbox(ax,8,3.2,14,0.9, "NON-PHARMACOLOGICAL: Aerobic exercise (neuroprotective signal) · Tai chi/yoga (balance) · " "Mediterranean diet · Cognitive training · Sleep hygiene", TEAL,fs=8.5) ax.text(8,0.3,"Sources: Katzung Basic & Clinical Pharmacology 16E · AAN Practice Guidelines · " "MDS Evidence-Based Medicine Review · Harrison's 22E", ha="center",fontsize=7,color="#777",style="italic") plt.tight_layout(pad=0.3) plt.savefig(f"{ASSET}/infographic_02_treatment.png",dpi=150,bbox_inches="tight", facecolor=fig.get_facecolor()) plt.close() print("Saved infographic_02") PYEOF

Running Command

python3 - <<'PYEOF' import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from matplotlib.patches import FancyBboxPatch, Polygon as MplPoly import textwrap ASSET="/tmp/workspace/parkinsonism-cpg/assets" NAVY="#1A3A5C";GREEN="#1E8449";RED="#922B21";PURPLE="#6C3483" ORANGE="#B7770D";STEEL="#2471A3";TEAL="#117A65";WARN="#C0392B" BLACK="#1A1A1A";LGREY="#F2F3F4";WHITE="white" def fbox(ax,cx,cy,w,h,txt,fc,tc="white",fs=8.5,bold=False,lsp=1.35,wrap=True): p=FancyBboxPatch((cx-w/2,cy-h/2),w,h,boxstyle="round,pad=0.12", fc=fc,ec="white",lw=1.3,zorder=3) ax.add_patch(p) t=textwrap.fill(txt,width=max(6,int(w*8.5))) if wrap else txt ax.text(cx,cy,t,ha="center",va="center",fontsize=fs,color=tc, fontweight="bold" if bold else "normal",linespacing=lsp, zorder=4,multialignment="center") # ════════════════════════════════════════════════════════════════════════════ # INFOGRAPHIC 3 — Atypical Parkinsonism Comparison # ════════════════════════════════════════════════════════════════════════════ fig,ax=plt.subplots(figsize=(18,14)); ax.set_xlim(0,18); ax.set_ylim(0,14); ax.axis("off") fig.patch.set_facecolor("#F7F9FC") ax.text(9,13.55,"ATYPICAL PARKINSONISM: COMPREHENSIVE COMPARISON", ha="center",fontsize=15,fontweight="bold",color=NAVY) ax.text(9,13.15,"PSP · MSA · CBS · DLB vs. Parkinson's Disease | Specialist Reference", ha="center",fontsize=9,color="#555",style="italic") COLS=[(2.2,"PD",GREEN),(5.7,"PSP",RED),(9.2,"MSA",PURPLE),(12.7,"CBS",ORANGE),(16.2,"DLB",STEEL)] ROWS=[ (12.3,"CARDINAL FEATURES"), (10.7,"ONSET / TREMOR"), (9.4,"LEVODOPA"), (8.1,"IMAGING"), (6.8,"PATHOLOGY"), (5.6,"AUTONOMIC"), (4.4,"COGNITIVE"), (3.2,"MANAGEMENT"), (2.0,"PROGNOSIS"), ] # Row label column for y,lbl in ROWS: ax.text(0.35,y,lbl,ha="center",va="center",fontsize=8,color=WHITE,fontweight="bold", bbox=dict(fc=NAVY,ec="white",pad=3,boxstyle="round,pad=0.2"), rotation=0,zorder=4) # Column headers for cx,name,col in COLS: fbox(ax,cx,12.85,3.2,0.55,name,col,fs=12,bold=True) DATA={ "PD":[ "Bradykinesia\nRest tremor\nRigidity\nPostural instability", "Asymmetric onset\nPill-rolling 4-6 Hz\nUnilateral start", "Excellent sustained\nresponse ✓✓\nDyskinesias develop", "DaTscan: asymm.\nposterior putamen ↓\nMIBG: reduced ✓", "Lewy bodies\nAlpha-synuclein\nSNc depigmentation", "Mild-moderate\n(late in disease)\nOH, constipation", "Late-onset dementia\n(PDD after >1 yr)\nSubcortical pattern", "Levodopa/carbidopa\nDopamine agonists\nDBS for advanced", "Slow progression\n10-20 years\nNear-normal lifespan", ], "PSP":[ "Axial > limb rigidity\nRetroflexion neck\nEarly falls yr 1\nDysphagia", "Symmetric onset\nRest tremor rare\nAxial dominant", "Poor / absent\n(<30% respond)\nBrief if any", "Hummingbird sign\n(midbrain atrophy)\nDaTscan: symmetric ↓", "Tau (4R)\nNeurofibrillary tangles\nSubthalamic/SN", "Mild\nurinary urgency\n(late)", "Frontal/executive\nApathy, disinhibition\nRapid decline", "No effective Rx\nFalls prevention\nPEG tube early", "Rapid 5-7 years\nDeath: aspiration\npneumonia", ], "MSA":[ "Parkinsonism (MSA-P)\nOR Cerebellar (MSA-C)\nInspiratory stridor\nEarly autonomic", "Symmetric onset\nPostural tremor\nMild rest tremor", "Partial 30-40%\nfades over time\nNo dyskinesias", "Hot cross bun sign\n(pons, T2 MRI)\nPutaminal ↓ signal", "Alpha-synuclein\nGlial cytoplasmic\ninclusions (GCIs)", "Severe & EARLY ✓✓\nOH · Incontinence\nImpotence · Stridor", "Mild cognitive\ndecline (late)\nFrontal pattern", "Levodopa (partial)\nFludrocortisone/\nmidodrine; CPAP", "Rapid 6-10 years\nStridor = poor\nprognosis", ], "CBS":[ "Markedly asymm.\nAlien limb ✓✓\nIdeomotor apraxia\nMyoclonus", "Markedly asymm.\nPostural/action\nStimulus myoclonus", "Poor/absent\nNo significant\nresponse", "Asymm. frontoparietal\ncortical atrophy\nDaTscan: asymm. ↓", "Tau (4R)\nCorticobasal\ninclusions/astrocytes", "Urinary (late)\nMild autonomic", "Apraxia · Aphasia\nExecutive · Spatial\nPrefrontal syndrome", "No effective Rx\nClonazepam (myo.)\nOT/Speech therapy", "Rapid 6-8 years\nDysarthria &\ndysphagia late", ], "DLB":[ "Parkinsonism mild\nSymmetric motor\nFluctuating alertness\nVisual hallucinations ✓✓", "Symmetric, mild\nRest tremor mild\nMotor after dementia", "Partial response\nCan worsen\npsychiatric sx", "DaTscan: bilat. ↓\nMIBG: reduced ✓\nEEG: posterior slow", "Cortical Lewy bodies\nAlpha-synuclein\nOccipital hypometab.", "Moderate\nOH, syncope\nUrinary urgency", "Dementia ≤1 yr ✓✓\nVisuospatial deficits\nFluctuating attention", "AChEIs (primary)\nAVOID typicals ✓✓\nQuetiapine (psychosis)", "Variable\n5-8 years typical\nNeuroleptics → crisis", ], } row_colours={ "CARDINAL FEATURES": LGREY, "ONSET / TREMOR": "#EAF4FB", "LEVODOPA": "#EAFAF1", "IMAGING": "#EAF2FF", "PATHOLOGY": "#F5EEF8", "AUTONOMIC": "#FEF9E7", "COGNITIVE": "#FDF2F8", "MANAGEMENT": "#E8F8F5", "PROGNOSIS": "#FDEDEC", } for (y,lbl),((_,name,col),dlist) in zip(ROWS, [(c,DATA[c[1]]) for c in COLS]): pass # just to confirm structure # Draw all data cells for ri,(y,lbl) in enumerate(ROWS): bg = row_colours.get(lbl,LGREY) for ci,(cx,name,col) in enumerate(COLS): txt = DATA[name][ri] # highlight special cells cell_bg = bg cell_tc = BLACK if "✓✓" in txt: cell_tc = col p=FancyBboxPatch((cx-1.55,y-0.57),3.1,1.14, boxstyle="round,pad=0.06",fc=cell_bg, ec="#D5D8DC",lw=0.5,zorder=2) ax.add_patch(p) ax.text(cx,y,txt.replace("✓✓","★★").replace("✓","★"), ha="center",va="center",fontsize=7.2, color=cell_tc,linespacing=1.3, zorder=4,multialignment="center", fontweight="bold" if "★★" in txt.replace("✓✓","★★") else "normal") # Row alternating left border for ri,(y,lbl) in enumerate(ROWS): col_val = list(row_colours.values())[ri % len(row_colours)] ax.plot([0.7,0.7],[y-0.6,y+0.6],color=NAVY,lw=2,zorder=5) ax.text(9,0.25, "★★ = Highly characteristic / critical feature " "Sources: Harrison's 22E · Bradley & Daroff's Neurology · Washington Manual · Kaplan & Sadock", ha="center",fontsize=7.5,color="#555",style="italic") plt.tight_layout(pad=0.2) plt.savefig(f"{ASSET}/infographic_03_atypical.png",dpi=150,bbox_inches="tight", facecolor=fig.get_facecolor()) plt.close() print("Saved infographic_03") PYEOF

Running Command

python3 - <<'PYEOF' import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt from matplotlib.patches import FancyBboxPatch import textwrap, numpy as np ASSET="/tmp/workspace/parkinsonism-cpg/assets" NAVY="#1A3A5C";GREEN="#1E8449";RED="#922B21";PURPLE="#6C3483" ORANGE="#B7770D";STEEL="#2471A3";TEAL="#117A65";WARN="#C0392B" BLACK="#1A1A1A";LGREY="#F4F6F7";WHITE="white";MGREY="#BDC3C7" GOLD="#D4AC0D" def fbox(ax,cx,cy,w,h,txt,fc,tc="white",fs=8.5,bold=False,lsp=1.35,wrap=True): p=FancyBboxPatch((cx-w/2,cy-h/2),w,h,boxstyle="round,pad=0.1", fc=fc,ec="white",lw=1.3,zorder=3) ax.add_patch(p) t=textwrap.fill(txt,width=max(6,int(w*8))) if wrap else txt ax.text(cx,cy,t,ha="center",va="center",fontsize=fs,color=tc, fontweight="bold" if bold else "normal",linespacing=lsp, zorder=4,multialignment="center") # ════════════════════════════════════════════════════════════════════════════ # INFOGRAPHIC 4 — Non-Motor Features + Drug Profile # ════════════════════════════════════════════════════════════════════════════ fig = plt.figure(figsize=(18,22)) fig.patch.set_facecolor("#F7F9FC") # ── TOP HALF: Non-motor wheel ──────────────────────────────────────────── ax1 = fig.add_axes([0.0,0.52,1.0,0.48]) ax1.set_xlim(0,18); ax1.set_ylim(0,10); ax1.axis("off") ax1.text(9,9.55,"NON-MOTOR FEATURES OF PARKINSON'S DISEASE", ha="center",fontsize=14,fontweight="bold",color=NAVY) ax1.text(9,9.2,"Recognition, Timing & Management | Harrison's 22E · Bradley & Daroff's Neurology", ha="center",fontsize=8.5,color="#555",style="italic") # Timeline bar for i,(stage,col,xr) in enumerate([ ("PRE-MOTOR PHASE\n(Years before diagnosis)",GREEN,(1.0,5.5)), ("EARLY MOTOR\n(Diagnosis to ~3 yrs)",STEEL,(5.7,10.5)), ("MODERATE\n(3-8 years)",ORANGE,(10.7,14.5)), ("ADVANCED\n(>8-10 years)",RED,(14.7,17.5)), ]): x1,x2=xr ax1.fill_betweenx([8.4,8.85],[x1],[x2],color=col,alpha=0.9,zorder=2) ax1.text((x1+x2)/2,8.62,stage,ha="center",va="center",fontsize=7.5, color="white",fontweight="bold",zorder=3,multialignment="center",linespacing=1.25) # Non-motor feature boxes features = [ # (cx, cy, title, details, colour, timing_x) (2.2,7.1,"ANOSMIA\n/ HYPOSMIA", "Earliest pre-motor marker\n90% of PD patients affected\nAlpha-syn in olfactory bulb\nTest: UPSIT / sniff sticks",GREEN,2.5), (5.5,7.1,"REM SLEEP\nBEHAVIOUR DISORDER", "Acts out vivid dreams\n>80% idiopathic RBD → PD\nPredates motor by 10-25 yrs\nRx: Melatonin / clonazepam",GREEN,5.5), (8.8,7.1,"CONSTIPATION\n/ GI DYSMOTILITY", "Braak stage 1-2 (enteric)\nPrecedes motor by years\nEnema / osmotic laxatives\nDopamine in gut plexus",GREEN,8.5), (12.1,7.1,"DEPRESSION\n/ ANXIETY", "40-50% prevalence\nDopamine & serotonin ↓\nSSRIs preferred (avoid TCAs)\nCBT beneficial",STEEL,11.5), (15.4,7.1,"ORTHOSTATIC\nHYPOTENSION", "Cardiac sympathetic loss\nMIBG: reduced uptake\nRx: fludrocortisone,\nmidodrine, compression",ORANGE,14.5), (2.2,5.1,"URINARY\nDYSFUNCTION", "Urgency, frequency, nocturia\nDetrusor overactivity\nRx: oxybutynin (avoid in elderly)\nOnabotulinumtoxin A",STEEL,4.0), (5.5,5.1,"PAIN /\nSENSORY SX", "Central pain, akathisia\n40% report pain as main sx\nMusculoskeletal most common\nDopaminergic Rx may help",STEEL,6.5), (8.8,5.1,"HALLUCINATIONS\n/ PSYCHOSIS", "Usually visual (formed images)\nLevodopa-related (peak dose)\nRisk: age, cognitive decline\nRx: AChEIs → quetiapine",ORANGE,10.5), (12.1,5.1,"DEMENTIA\n(PDD)", "~80% at 20 years\nSubcortical + cortical\nRivastigmine (FDA-approved)\nDistinct from DLB by timing",RED,14.0), (15.4,5.1,"DYSPHAGIA\n/ SIALORRHOEA", "Late feature, major mortality\nAspiration pneumonia risk\nSpeech therapy, modified diet\nBotox for drooling",RED,16.0), ] for cx,cy,title,detail,col,_ in features: fbox(ax1,cx,cy+0.35,3.3,0.6,title,col,fs=8,bold=True) fbox(ax1,cx,cy-0.5,3.3,1.05,detail,col,fs=7.2,tc="white",lsp=1.4) ax1.text(9,3.75,"MONITORING SCHEDULE", ha="center",fontsize=11,fontweight="bold",color=NAVY) mon_items=[ ("EVERY\nVISIT",["Motor exam (UPDRS-III)","Non-motor review","Falls assessment","Medication side-effects"],NAVY), ("EVERY\n3 MONTHS",["Orthostatic BP","Weight / nutrition","Bowel & bladder Hx","Sleep disorders screen"],STEEL), ("EVERY\n6 MONTHS",["Cognitive screen (MoCA)","Depression screen (GDS)","Swallowing assessment","DBS programming (if implanted)"],TEAL), ("ANNUALLY",["Full neuropsych assessment","Bone density (fall risk)","Driving fitness review","Advance care planning"],ORANGE), ("AS NEEDED",["DaTscan (dx uncertainty)","MIBG (PDD vs DLB)","Genetic counselling","Multidisciplinary meeting"],RED), ] for i,(freq,items,col) in enumerate(mon_items): cx=1.8+i*3.5 fbox(ax1,cx,3.1,3.2,0.65,freq,col,fs=9,bold=True) txt="\n".join([f"☐ {it}" for it in items]) fbox(ax1,cx,2.0,3.2,1.4,txt,col,fs=7.2,tc="white",lsp=1.5) ax1.text(9,0.35,"Sources: Harrison's Principles of Internal Medicine 22E · Bradley & Daroff's Neurology · " "Katzung Pharmacology 16E · Adams & Victor 12E", ha="center",fontsize=7,color="#777",style="italic") # ── BOTTOM HALF: Drug profile table ────────────────────────────────────── ax2 = fig.add_axes([0.0,0.0,1.0,0.50]) ax2.set_xlim(0,18); ax2.set_ylim(0,11); ax2.axis("off") ax2.text(9,10.6,"ANTIPARKINSONIAN DRUGS: QUICK REFERENCE PROFILE", ha="center",fontsize=13,fontweight="bold",color=NAVY) # Header row headers=["DRUG CLASS","MECHANISM","DOSE (typical)","KEY ADVERSE EFFECTS","USE WHEN","AVOID WHEN"] col_w=[2.8,2.4,2.5,4.0,3.0,3.2] hx=[0.3+sum(col_w[:i])+col_w[i]/2 for i in range(len(col_w))] hy=10.1 for cx,h,w in zip(hx,headers,col_w): fbox(ax2,cx,hy,w-0.08,0.55,h,NAVY,fs=8.5,bold=True) drugs=[ # class, mechanism, dose, AEs, use_when, avoid_when, colour ("Levodopa /\nCarbidopa", "Dopamine precursor\n+ peripheral DDC inhibitor", "Start 50/12.5 mg TID\n→ titrate to response\n(max ~1000mg LD/day)", "Nausea, dyskinesias,\nwearing-off, hallucinations,\northostatic hypotension", "All PD stages\nGold standard\nElderly / cognitive impairment", "Active psychosis\n(relative)\nCareful with MAOIs", GREEN), ("Dopamine\nAgonists\n(Pramipexole,\nRopinirole,\nRotigotine)", "D2/D3 receptor\ndirect agonist\n(non-ergoline preferred)", "Pramipexole:\n0.5-1.5 mg TID\nRopinirole: 2-8 mg TID\nRotigotine: 2-8 mg/24h", "ICD (gambling,\nhypersexuality, binge eating)\nSomnolence, oedema,\nnausea, hallucinations", "Young patients <70\nEarly PD monotherapy\nAdjunct for fluctuations", "Dementia / psychosis\nSevere cardiac disease\nPregnancy", STEEL), ("MAO-B\nInhibitors\n(Rasagiline,\nSelegiline,\nSafinamide)", "Irreversible MAO-B block\n→ ↓ dopamine breakdown\nin striatum", "Rasagiline: 0.5-1 mg OD\nSelegiline: 5 mg BD\nSafinamide: 50-100 mg OD", "Insomnia, headache\nSelegiline: serotonin\nsyndrome (avoid SSRIs/SNRIs)\nNausea", "Early mild PD mono.\nAdjunct: wearing-off\nPossible neuroprotection", "Selegiline + SSRIs/\nSNRIs / meperidine\nSevere hepatic disease", TEAL), ("COMT\nInhibitors\n(Entacapone,\nOpicapone,\nTolcapone)", "Inhibit peripheral\n(+ central for tolcapone)\ncatechol-O-methyltransf.\n→ prolong LD effect", "Entacapone: 200 mg\nwith each LD dose\nOpicapone: 50 mg OD\nTolcapone: 100 mg TID", "Diarrhoea, dyskinesias,\norange urine (entacapone)\nTolcapone: hepatotoxicity\n(monitor LFTs q2-4 wks)", "Wearing-off\nMotor fluctuations\nWith levodopa only", "Tolcapone: liver disease\nHistory of NMS\nActive liver disease", ORANGE), ("Amantadine\n(IR / ER\nGocovri)", "NMDA receptor\nantagonist; also\n↑ dopamine release\n/ reuptake inhibition", "IR: 100 mg BD/TID\nER (Gocovri): 137-274mg\nat bedtime\n(extended-release)", "Livedo reticularis,\nperipheral oedema,\nhallucinations, confusion\nDo NOT stop abruptly", "Mild early PD\nLevodopa dyskinesias\n(ER formulation)", "Renal impairment\n(reduce dose)\nSeizure history\nAbrupt withdrawal", PURPLE), ("AChEIs\n(Rivastigmine,\nDonepezil)", "Acetylcholinesterase\ninhibitor → ↑ ACh\nin cortex & striatum", "Rivastigmine:\n1.5→6 mg BD oral\n4.6→9.5 mg/24h patch\nDonepezil: 5-10 mg OD", "Nausea, vomiting\nBradycardia (caution\nin cardiac disease)\n↑ tremor (rivastigmine)", "PDD (rivastigmine\nFDA-approved)\nDLB cognitive sx\nFirst-line for hallucinations", "Active peptic ulcer\nConducting system\ncardiac disease", RED), ("Quetiapine /\nClozapine", "Atypical antipsychotics\n(D2 weak block +\n5-HT2A antagonism)\n→ low EPS risk", "Quetiapine: 12.5-100mg\nat bedtime\nClozapine: 6.25-50mg\n(requires WBC monitoring)", "Sedation, falls (Q)\nAgranulocytosis: clozapine\n(WBC every 1-4 wks)\nQT prolongation", "PD / DLB psychosis\nIF AChEIs insufficient\nUse lowest effective dose", "Typical antipsychotics\nRisperidone, olanzapine\nAVOID in DLB (mortality ↑)", WARN), ] row_ys=[i*1.22 for i in range(len(drugs),0,-1)] row_ys=[y+0.2 for y in row_ys] for ri,(cls,mech,dose,aes,use,avoid,col) in enumerate(drugs): y=row_ys[ri] bg="#F9F9F9" if ri%2==0 else "#FFFFFF" cells=[cls,mech,dose,aes,use,avoid] tcs=[WHITE,BLACK,BLACK,WARN,GREEN,RED] fcs=[col,bg,bg,bg,bg,bg] for ci,(txt,tc2,fc2,w) in enumerate(zip(cells,tcs,fcs,col_w)): cx=0.3+sum(col_w[:ci])+col_w[ci]/2 p=FancyBboxPatch((cx-w/2+0.04,y-0.52),w-0.08,1.04, boxstyle="round,pad=0.05",fc=fc2,ec=MGREY if fc2!=col else col, lw=0.6,zorder=2) ax2.add_patch(p) wrapped=textwrap.fill(str(txt),width=max(5,int(w*9))) ax2.text(cx,y,wrapped,ha="center",va="center",fontsize=7, color=tc2 if fc2==col else (WARN if tc2==WARN else (GREEN if tc2==GREEN else (RED if tc2==RED else BLACK))), linespacing=1.3,zorder=3,multialignment="center") plt.savefig(f"{ASSET}/infographic_04_nonmotor_drugs.png",dpi=140,bbox_inches="tight", facecolor=fig.get_facecolor()) plt.close() print("Saved infographic_04") PYEOF

All 4 infographics done. Now building the full CPG PDF:
Running Command

python3 - <<'PYEOF' from reportlab.lib.pagesizes import A4 from reportlab.lib import colors from reportlab.lib.units import mm, cm from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY, TA_RIGHT from reportlab.platypus import ( SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, HRFlowable, KeepTogether, PageBreak, Image ) from reportlab.platypus.flowables import Flowable import os, glob ASSET = "/tmp/workspace/parkinsonism-cpg/assets" OUT = "/tmp/workspace/parkinsonism-cpg/Parkinsonism_Clinical_Practice_Guideline.pdf" # ── Colours ────────────────────────────────────────────────────────────────── NAVY = colors.HexColor("#1A3A5C"); GREEN = colors.HexColor("#1E8449") RED = colors.HexColor("#922B21"); PURPLE = colors.HexColor("#6C3483") ORANGE = colors.HexColor("#B7770D"); STEEL = colors.HexColor("#2471A3") TEAL = colors.HexColor("#117A65"); WARN = colors.HexColor("#C0392B") LGREY = colors.HexColor("#F2F3F4"); MGREY = colors.HexColor("#D5D8DC") WHITE = colors.white; BLACK = colors.HexColor("#1A1A1A") GOLD = colors.HexColor("#D4AC0D") # ── Document ───────────────────────────────────────────────────────────────── doc = SimpleDocTemplate(OUT, pagesize=A4, leftMargin=16*mm, rightMargin=16*mm, topMargin=14*mm, bottomMargin=14*mm, title="Parkinsonism Clinical Practice Guideline", author="Orris Medical Intelligence") W = A4[0] - 32*mm # ── Styles ─────────────────────────────────────────────────────────────────── def S(name,**kw): return ParagraphStyle(name,**kw) sTitle = S("sTitle", fontSize=20,textColor=WHITE,alignment=TA_CENTER, fontName="Helvetica-Bold",leading=24) sSub = S("sSub", fontSize=9, textColor=WHITE,alignment=TA_CENTER, fontName="Helvetica",leading=13) sH1 = S("sH1", fontSize=12,textColor=WHITE,fontName="Helvetica-Bold", leading=15,leftIndent=6) sH2 = S("sH2", fontSize=10,textColor=NAVY, fontName="Helvetica-Bold", leading=13,spaceBefore=6) sH3 = S("sH3", fontSize=9, textColor=STEEL,fontName="Helvetica-Bold", leading=12,spaceBefore=4) sBody = S("sBody", fontSize=8.5,textColor=BLACK,fontName="Helvetica", leading=12.5,leftIndent=0,spaceAfter=3) sJust = S("sJust", fontSize=8.5,textColor=BLACK,fontName="Helvetica", leading=12.5,alignment=TA_JUSTIFY,spaceAfter=3) sBull = S("sBull", fontSize=8.5,textColor=BLACK,fontName="Helvetica", leading=12.5,leftIndent=12,bulletIndent=4,bulletText="•") sWarn = S("sWarn", fontSize=8.5,textColor=WARN, fontName="Helvetica-Bold", leading=12,leftIndent=12,bulletIndent=4,bulletText="⚠") sNote = S("sNote", fontSize=7.5,textColor=colors.HexColor("#666666"), fontName="Helvetica",leading=10,alignment=TA_CENTER,style="italic") sRec = S("sRec", fontSize=8.5,textColor=NAVY, fontName="Helvetica-Bold", leading=12,leftIndent=12,bulletIndent=4) sGrade = S("sGrade", fontSize=7.5,textColor=WHITE,fontName="Helvetica-Bold", leading=10,alignment=TA_CENTER) def sp(h=5): return Spacer(1,h) def hr(c=MGREY): return HRFlowable(width=W,thickness=0.5,color=c,spaceAfter=3) def colheader(text,sub,col=NAVY): t = Table([[Paragraph(text,sTitle)],[Paragraph(sub,sSub)]],colWidths=[W]) t.setStyle(TableStyle([ ("BACKGROUND",(0,0),(-1,-1),col), ("TOPPADDING",(0,0),(-1,-1),8),("BOTTOMPADDING",(0,0),(-1,-1),8), ("LEFTPADDING",(0,0),(-1,-1),10),("RIGHTPADDING",(0,0),(-1,-1),10), ])) return t def secheader(text,col=NAVY): t = Table([[Paragraph(text,sH1)]],colWidths=[W]) t.setStyle(TableStyle([ ("BACKGROUND",(0,0),(-1,-1),col), ("TOPPADDING",(0,0),(-1,-1),5),("BOTTOMPADDING",(0,0),(-1,-1),5), ("LEFTPADDING",(0,0),(-1,-1),10),("RIGHTPADDING",(0,0),(-1,-1),10), ])) return t def rec_box(grade,text,col=GREEN): gs = ParagraphStyle("g",fontSize=7,textColor=WHITE,fontName="Helvetica-Bold", leading=9,alignment=TA_CENTER) rs = ParagraphStyle("r",fontSize=8.5,textColor=BLACK,fontName="Helvetica",leading=12) t = Table([[Paragraph(grade,gs),Paragraph(text,rs)]], colWidths=[12*mm,W-12*mm]) t.setStyle(TableStyle([ ("BACKGROUND",(0,0),(0,-1),col), ("BACKGROUND",(1,0),(1,-1),LGREY), ("BOX",(0,0),(-1,-1),0.5,col), ("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3), ("LEFTPADDING",(0,0),(-1,-1),4),("RIGHTPADDING",(0,0),(-1,-1),4), ("VALIGN",(0,0),(-1,-1),"MIDDLE"), ("GRID",(0,0),(-1,-1),0.3,MGREY), ])) return t def two_col(items1,items2,h1="",h2="",c1=STEEL,c2=STEEL): hs=ParagraphStyle("th",fontSize=8.5,textColor=WHITE,fontName="Helvetica-Bold", leading=11,alignment=TA_CENTER) cw=W/2-1*mm rows=[[Paragraph(h1,hs),Paragraph(h2,hs)]] if h1 or h2 else [] for i in range(max(len(items1),len(items2))): l=Paragraph(f"• {items1[i]}",sBull) if i<len(items1) else Paragraph("",sBody) r=Paragraph(f"• {items2[i]}",sBull) if i<len(items2) else Paragraph("",sBody) rows.append([l,r]) t=Table(rows,colWidths=[cw,cw]) cmds=[("GRID",(0,0),(-1,-1),0.3,MGREY), ("TOPPADDING",(0,0),(-1,-1),2),("BOTTOMPADDING",(0,0),(-1,-1),2), ("LEFTPADDING",(0,0),(-1,-1),5),("RIGHTPADDING",(0,0),(-1,-1),5), ("VALIGN",(0,0),(-1,-1),"TOP"), ("ROWBACKGROUNDS",(0,1 if (h1 or h2) else 0),(-1,-1),[WHITE,LGREY])] if h1 or h2: cmds+=[("BACKGROUND",(0,0),(0,0),c1),("BACKGROUND",(1,0),(1,0),c2)] t.setStyle(TableStyle(cmds)) return t def img(path,W=W,max_h=200*mm): from reportlab.lib.utils import ImageReader from PIL import Image as PILImage im=PILImage.open(path) iw,ih=im.size ratio=ih/iw ow=W oh=min(ow*ratio,max_h) if oh==max_h: ow=oh/ratio return Image(path,width=ow,height=oh) # ════════════════════════════════════════════════════════════════════════════ # BUILD STORY # ════════════════════════════════════════════════════════════════════════════ story=[] # ── COVER ─────────────────────────────────────────────────────────────────── story.append(colheader( "PARKINSONISM", "Clinical Practice Guideline · Diagnosis · Management · Monitoring\n" "Specialist Reference · August 2026 · Orris Medical Intelligence" )) story.append(sp(8)) # Cover metadata table meta=[ ["Target Users","Neurologists, Movement Disorder Specialists, Geriatricians, General Physicians"], ["Topic","Parkinsonism: Differential Diagnosis and Evidence-Based Management"], ["Edition","2026 (based on MDS Criteria, AAN Guidelines, Harrison's 22E)"], ["Grading System","A=Strong evidence (RCTs/meta-analyses) · B=Moderate (cohort/controlled) · C=Expert consensus/practice"], ["Disclaimer","This guideline is an educational reference. Clinical decisions require individual patient assessment."], ] ms=ParagraphStyle("ms",fontSize=8.5,textColor=BLACK,fontName="Helvetica",leading=12) mb=ParagraphStyle("mb",fontSize=8.5,textColor=NAVY,fontName="Helvetica-Bold",leading=12) meta_rows=[[Paragraph(k,mb),Paragraph(v,ms)] for k,v in meta] mt=Table(meta_rows,colWidths=[35*mm,W-35*mm]) mt.setStyle(TableStyle([ ("GRID",(0,0),(-1,-1),0.3,MGREY), ("BACKGROUND",(0,0),(0,-1),LGREY), ("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4), ("LEFTPADDING",(0,0),(-1,-1),6),("RIGHTPADDING",(0,0),(-1,-1),6), ("VALIGN",(0,0),(-1,-1),"TOP"), ])) story.append(mt) story.append(sp(8)) # Table of contents story.append(secheader("TABLE OF CONTENTS",NAVY)) story.append(sp(4)) toc_items=[ ("1.","Introduction & Scope"), ("2.","Definition & Pathophysiology"), ("3.","Classification of Parkinsonism"), ("4.","Clinical Assessment & Diagnostic Criteria [Infographic 1]"), ("5.","Red Flags & Supportive Features"), ("6.","Investigations"), ("7.","Pharmacological Management [Infographic 2]"), ("8.","Non-Pharmacological Management"), ("9.","Non-Motor Features & Their Management [Infographic 4]"), ("10.","Atypical Parkinsonism Syndromes [Infographic 3]"), ("11.","Special Populations (Young-onset, Elderly, Pregnancy)"), ("12.","Monitoring & Follow-up"), ("13.","Patient Information & Shared Decision Making"), ("14.","References & Evidence Base"), ] toc_s=ParagraphStyle("toc",fontSize=9,textColor=BLACK,fontName="Helvetica", leading=14,leftIndent=12) toc_n=ParagraphStyle("tocn",fontSize=9,textColor=NAVY,fontName="Helvetica-Bold", leading=14) for num,item in toc_items: story.append(Table([[Paragraph(num,toc_n),Paragraph(item,toc_s)]], colWidths=[10*mm,W-10*mm])) story.append(PageBreak()) # ── SECTION 1 ─────────────────────────────────────────────────────────────── story.append(secheader("1. INTRODUCTION & SCOPE",NAVY)) story.append(sp(5)) story.append(Paragraph( "Parkinsonism is the second most common neurodegenerative syndrome worldwide, affecting approximately " "1% of individuals over 60 years and 3% over 80 years. This Clinical Practice Guideline (CPG) provides " "evidence-based recommendations for the diagnosis, differential diagnosis, and management of all major " "forms of parkinsonism in adult patients. It is intended for use by neurologists, movement disorder " "specialists, geriatricians, and general physicians.", sJust)) story.append(sp(4)) story.append(Paragraph( "This guideline covers: idiopathic Parkinson's Disease (PD), Atypical Parkinsonism syndromes " "(Progressive Supranuclear Palsy [PSP], Multiple System Atrophy [MSA], Corticobasal Syndrome [CBS], " "Dementia with Lewy Bodies [DLB]), and Secondary Parkinsonism. It does not address paediatric cases, " "Huntington's disease, or Wilson's disease in detail.", sJust)) story.append(sp(6)) story.append(Paragraph("Key objectives of this guideline:", sH3)) for obj in [ "Provide a structured, stepwise diagnostic framework for parkinsonism using MDS Clinical Diagnostic Criteria", "Define red flags that distinguish PD from atypical and secondary parkinsonism", "Offer evidence-graded pharmacological management recommendations for each stage of PD", "Address the full spectrum of non-motor features and their management", "Guide appropriate investigation ordering and interpretation", "Support multidisciplinary care planning and patient-centred decision making", ]: story.append(Paragraph(obj,sBull)) story.append(sp(8)) # ── SECTION 2 ─────────────────────────────────────────────────────────────── story.append(secheader("2. DEFINITION & PATHOPHYSIOLOGY",TEAL)) story.append(sp(5)) story.append(Paragraph("<b>Parkinsonism</b> is a clinical syndrome defined by bradykinesia (mandatory) " "combined with at least one of: muscular rigidity, rest tremor (4-6 Hz), or postural instability. " "The additional features of flexed posture and freezing of gait complete the full TRAP+2 syndrome " "(Tremor, Rigidity, Akinesia, Postural instability, flexed posture, freezing).", sJust)) story.append(sp(4)) story.append(Paragraph("<b>Pathophysiology — Basal Ganglia Circuit:</b>", sH3)) story.append(Paragraph( "Motor symptoms arise from degeneration of dopaminergic neurons in the Substantia Nigra pars compacta (SNc). " "These neurons project via the nigrostriatal pathway to the striatum (putamen > caudate). " "Dopamine normally modulates two competing pathways:", sJust)) story.append(sp(3)) story.append(two_col( ["Direct pathway (D1): Striatum → GPi inhibition → Thalamus disinhibition → Cortex activation → Movement facilitated", "In PD: D1 activity ↓ → GPi less inhibited → Thalamus over-inhibited → Movement suppressed"], ["Indirect pathway (D2): Striatum → GPe → STN → GPi excitation → Thalamus inhibited → Movement suppressed", "In PD: D2 inhibition lost → STN over-active → GPi hyperactive → Net thalamic inhibition → Bradykinesia"], h1="DIRECT PATHWAY",h2="INDIRECT PATHWAY",c1=GREEN,c2=RED )) story.append(sp(5)) story.append(Paragraph( "<b>Alpha-synuclein & Lewy Bodies:</b> The pathological hallmark of PD is the misfolding and aggregation of " "alpha-synuclein protein into Lewy bodies within surviving neurons. This process follows the Braak staging " "model, beginning in the enteric/autonomic nervous system and olfactory bulb (stages 1-2), progressing to " "the substantia nigra (stage 3-4), and ultimately involving the neocortex (stages 5-6). This explains why " "non-motor features (anosmia, constipation, RBD) precede motor symptoms by 10-25 years.", sJust)) story.append(sp(8)) # ── SECTION 3 ─────────────────────────────────────────────────────────────── story.append(secheader("3. CLASSIFICATION OF PARKINSONISM",STEEL)) story.append(sp(5)) class_data=[ ["CATEGORY","SUBTYPES","KEY FEATURES"], ["Parkinson's Disease\n(~75% of parkinsonism)", "Sporadic (90%)\nGenetic: LRRK2, Parkin, PINK1, SNCA, GBA1\nPD + Dementia (PDD)", "Asymmetric onset · Lewy body pathology · Good levodopa response"], ["Atypical Parkinsonism\n(~15-20%)", "PSP (tau) · MSA (alpha-syn GCIs)\nCBS (tau) · DLB (alpha-syn Lewy)", "Poor levodopa response · Rapid progression · Additional neurological features"], ["Secondary Parkinsonism\n(~5-10%)", "Drug-induced · Vascular · NPH\nToxic · Infective · Metabolic · Neoplastic", "Identifiable cause · Potentially reversible · Normal DaTscan (drug-induced)"], ["Other Neurodegenerative", "Wilson's disease · Huntington's\nSCA3 · Prion disease · X-linked dystonia-parkinsonism", "Systemic or multi-system features · Age of onset often younger"], ] cs=ParagraphStyle("cs",fontSize=8,textColor=BLACK,fontName="Helvetica",leading=11) ch=ParagraphStyle("ch",fontSize=8.5,textColor=WHITE,fontName="Helvetica-Bold",leading=11,alignment=TA_CENTER) ct=Table([[Paragraph(c,ch) for c in class_data[0]]]+ [[Paragraph(c,cs) for c in row] for row in class_data[1:]], colWidths=[45*mm,60*mm,W-105*mm]) ct.setStyle(TableStyle([ ("BACKGROUND",(0,0),(-1,0),NAVY), ("BACKGROUND",(0,1),(0,1),GREEN),("BACKGROUND",(0,2),(0,2),PURPLE), ("BACKGROUND",(0,3),(0,3),STEEL),("BACKGROUND",(0,4),(0,4),ORANGE), ("GRID",(0,0),(-1,-1),0.3,MGREY), ("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4), ("LEFTPADDING",(0,0),(-1,-1),5),("RIGHTPADDING",(0,0),(-1,-1),5), ("VALIGN",(0,0),(-1,-1),"TOP"), ("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE,LGREY]), ("FONTNAME",(0,1),(0,-1),"Helvetica-Bold"), ("TEXTCOLOR",(0,1),(0,-1),WHITE), ])) story.append(ct) story.append(sp(8)) story.append(PageBreak()) # ── SECTION 4 + INFOGRAPHIC 1 ─────────────────────────────────────────────── story.append(secheader("4. CLINICAL ASSESSMENT & DIAGNOSTIC CRITERIA",GREEN)) story.append(sp(5)) story.append(Paragraph( "<b>MDS Clinical Diagnostic Criteria for Parkinson's Disease (Berg et al., 2015)</b> — the current " "international standard — requires bradykinesia plus rigidity and/or rest tremor as the mandatory " "motor syndrome (parkinsonism). Diagnosis of PD then relies on three additional categories:", sJust)) story.append(sp(4)) for cat,txt in [ ("Supportive Criteria (each increases confidence):", "Unilateral onset, clear rest tremor, excellent levodopa response, levodopa-induced dyskinesias, " "anosmia, cardiac sympathetic denervation on MIBG, REM sleep behaviour disorder, asymmetric DaTscan"), ("Absolute Exclusion Criteria (any single one rules out PD):", "Cerebellar abnormalities, downward vertical gaze palsy, FTD/PPA in first 5 years, " "lower limb parkinsonism only for >3 years, dopaminergic drug exposure, no levodopa response to ≥1g/day, " "cortical sensory loss or apraxia, normal FP-CIT SPECT"), ("Red Flags (must be counterbalanced by supportive criteria):", "Early severe autonomic failure, early recurrent falls, inspiratory stridor, " "absent non-motor features, severe dysautonomia within first year, symmetric parkinsonism"), ]: story.append(Paragraph(f"<b>{cat}</b> {txt}", sBull)) story.append(sp(2)) story.append(sp(4)) story.append(rec_box("A","Diagnosis of PD should use MDS Criteria. Clinically Established PD requires " "parkinsonism + ≥2 supportive features + no red flags + no absolute exclusion criteria. " "Clinically Probable PD requires ≥1 supportive feature with red flags balanced by equal supportive criteria.",GREEN)) story.append(sp(8)) story.append(Paragraph("<b>Infographic 1: Step-by-Step Diagnostic Algorithm</b>", S("ih",fontSize=9,textColor=NAVY,fontName="Helvetica-Bold", leading=12,alignment=TA_CENTER))) story.append(sp(3)) story.append(img(f"{ASSET}/infographic_01_diagnosis.png",W=W,max_h=240*mm)) story.append(sp(4)) story.append(Paragraph( "Figure 1. Diagnostic algorithm for parkinsonism from first presentation through differential diagnosis " "to confirmed Parkinson's Disease or atypical syndrome. Based on MDS Criteria and Harrison's 22E.", sNote)) story.append(PageBreak()) # ── SECTION 5 ─────────────────────────────────────────────────────────────── story.append(secheader("5. RED FLAGS & SUPPORTIVE FEATURES",WARN)) story.append(sp(5)) rf_data=[ ["RED FLAG","MOST LIKELY DIAGNOSIS"], ["Vertical supranuclear gaze palsy (especially downgaze slowing)","PSP"], ["Recurrent unexplained falls within first year of onset","PSP / MSA"], ["Severe autonomic failure (OH, urinary) within first year","MSA"], ["Cerebellar ataxia / nystagmus","MSA-C"], ["Inspiratory stridor or nocturnal laryngeal spasm","MSA"], ["Alien limb phenomenon / ideomotor apraxia","CBS"], ["Dementia onset ≤1 year of motor features","DLB"], ["Recurrent, well-formed visual hallucinations (early)","DLB"], ["Bilateral symmetric onset from day one","Drug-induced / MSA / PSP"], ["Antipsychotic or metoclopramide exposure","Drug-induced"], ["Normal DaTscan / FP-CIT SPECT","Drug-induced / Essential Tremor"], ["Rapid progression to wheelchair within 5 years","MSA / PSP"], ["Pyramidal signs (Babinski, hyperreflexia)","MSA / CBS"], ["Absence of any non-motor PD features despite years of disease","Atypical"], ["No response to levodopa ≥1000 mg/day for adequate duration","Atypical"], ["Age of onset <40 years","Genetic PD / Wilson's / DRD"], ["Hot cross bun sign on brain MRI","MSA"], ["Hummingbird sign on brain MRI sagittal","PSP"], ] rh=ParagraphStyle("rh",fontSize=8,textColor=WHITE,fontName="Helvetica-Bold",leading=11,alignment=TA_CENTER) rc=ParagraphStyle("rc",fontSize=8,textColor=BLACK,fontName="Helvetica",leading=11) rd=ParagraphStyle("rd",fontSize=8,textColor=WARN,fontName="Helvetica-Bold",leading=11) rfrows=[[Paragraph(rf_data[0][0],rh),Paragraph(rf_data[0][1],rh)]] for flag,dx in rf_data[1:]: rfrows.append([Paragraph(f"⚠ {flag}",rc),Paragraph(dx,rd)]) rft=Table(rfrows,colWidths=[130*mm,W-130*mm]) rft.setStyle(TableStyle([ ("BACKGROUND",(0,0),(-1,0),WARN), ("GRID",(0,0),(-1,-1),0.3,MGREY), ("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3), ("LEFTPADDING",(0,0),(-1,-1),5),("RIGHTPADDING",(0,0),(-1,-1),5), ("VALIGN",(0,0),(-1,-1),"MIDDLE"), ("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE,colors.HexColor("#FEF9F9")]), ])) story.append(rft) story.append(sp(8)) # ── SECTION 6 ─────────────────────────────────────────────────────────────── story.append(secheader("6. INVESTIGATIONS",STEEL)) story.append(sp(5)) story.append(Paragraph( "Investigation selection should be guided by clinical presentation. Not all tests are required in every patient. " "In a patient with classic asymmetric PD presenting after age 60 with excellent levodopa response, " "DaTscan may not be necessary. Investigations should target clinical uncertainty.", sJust)) story.append(sp(5)) inv_data=[ ["INVESTIGATION","CLINICAL USE","RESULT INTERPRETATION","GRADE"], ["DaTscan (FP-CIT SPECT) /\n[18F]FDOPA PET", "Confirm nigrostriatal degeneration; exclude drug-induced parkinsonism and essential tremor", "Reduced: PD, PSP, MSA, CBS (all equally)\nNormal: drug-induced, ET, psychogenic\nPattern: asymm. post. putamen = PD", "A"], ["Brain MRI (3T preferred)", "Exclude structural causes; identify atypical MRI patterns", "Hummingbird/penguin sign = PSP\nHot cross bun = MSA\nAsymm. frontoparietal = CBS\nWM lacunes = vascular", "B"], ["MIBG cardiac scintigraphy", "Differentiate PD/DLB from MSA/PSP/drug-induced", "Reduced H/M ratio = PD or DLB\nPreserved = MSA, PSP, drug-induced", "B"], ["Levodopa challenge\n(carbidopa/levodopa)", "Confirm dopaminergic response; support PD diagnosis", "≥30% UPDRS-III improvement = strong PD support\n<30% = consider atypical", "A"], ["Autonomic battery\n(tilt-table, QSART, urodynamics)", "Quantify autonomic failure; differentiate MSA from PD", "Severe early OH + urinary failure = MSA\nMild-moderate = PD autonomic", "B"], ["Neuropsychological testing", "Characterise cognitive profile; distinguish PDD, DLB, CBS, PSP", "Visuospatial+fluctuation = DLB\nFrontal/executive = PSP\nApraxia+aphasia = CBS\nSubcortical = PD", "B"], ["Ceruloplasmin + 24h urine copper", "Exclude Wilson's disease", "Mandatory if age <50 at onset\nLow ceruloplasmin + high Cu = Wilson's", "A"], ["Thyroid function (TSH, fT4)", "Exclude hypothyroid tremor/bradykinesia", "Hypothyroidism can mimic parkinsonism; reverses with levothyroxine", "C"], ["Genetic panel\n(LRRK2, Parkin, PINK1, SNCA, GBA1)", "Identify monogenic PD; genetic counselling", "Parkin/PINK1: early AR onset\nLRRK2: typical PD, AD\nGBA1: risk + faster progression", "B"], ["CSF alpha-synuclein seed amplification assay (SAA)", "Biomarker for synucleinopathy (emerging)", "High sensitivity/specificity for PD/DLB/MSA\nNegative in PSP/CBS (tauopathies)", "B"], ["Polysomnography", "Confirm REM sleep behaviour disorder", "RBD present in >80% of prodromal PD\nAlso present in MSA, DLB", "B"], ] ih=ParagraphStyle("ih2",fontSize=7.5,textColor=WHITE,fontName="Helvetica-Bold", leading=10,alignment=TA_CENTER) ic=ParagraphStyle("ic",fontSize=7.5,textColor=BLACK,fontName="Helvetica",leading=10) ig=ParagraphStyle("ig",fontSize=8,textColor=WHITE,fontName="Helvetica-Bold", leading=10,alignment=TA_CENTER) invrows=[[Paragraph(c,ih) for c in inv_data[0]]] grade_cols={ "A":colors.HexColor("#1E8449"), "B":colors.HexColor("#2471A3"), "C":colors.HexColor("#B7770D"), } for test,use,interp,grade in inv_data[1:]: gc=grade_cols.get(grade,STEEL) invrows.append([ Paragraph(test,ParagraphStyle("it",fontSize=7.5,textColor=NAVY, fontName="Helvetica-Bold",leading=10)), Paragraph(use,ic), Paragraph(interp,ic), Paragraph(grade,ParagraphStyle("ig2",fontSize=9,textColor=WHITE, fontName="Helvetica-Bold",leading=11, alignment=TA_CENTER)), ]) invt=Table(invrows,colWidths=[38*mm,45*mm,W-97*mm,14*mm]) inv_cmds=[ ("BACKGROUND",(0,0),(-1,0),STEEL), ("GRID",(0,0),(-1,-1),0.3,MGREY), ("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3), ("LEFTPADDING",(0,0),(-1,-1),4),("RIGHTPADDING",(0,0),(-1,-1),4), ("VALIGN",(0,0),(-1,-1),"TOP"), ("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE,LGREY]), ] for ri,row in enumerate(inv_data[1:],1): gc=grade_cols.get(row[3],STEEL) inv_cmds.append(("BACKGROUND",(3,ri),(3,ri),gc)) invt.setStyle(TableStyle(inv_cmds)) story.append(invt) story.append(sp(4)) story.append(Paragraph( "Grade A = RCT/meta-analysis evidence · Grade B = Cohort/controlled study · Grade C = Expert consensus", sNote)) story.append(PageBreak()) # ── SECTION 7 + INFOGRAPHIC 2 ─────────────────────────────────────────────── story.append(secheader("7. PHARMACOLOGICAL MANAGEMENT",GREEN)) story.append(sp(5)) story.append(Paragraph( "Pharmacological therapy in PD is symptomatic — no disease-modifying treatment has been conclusively " "established. The goal is to maintain function and quality of life with minimal adverse effects. " "Treatment should be individualised, considering age, cognitive status, comorbidities, patient preference, " "and stage of disease.", sJust)) story.append(sp(5)) for title,recs,col in [ ("EARLY PD — MILD SYMPTOMS (Hoehn & Yahr 1-2)",[ ("A","Levodopa/carbidopa is the most effective symptomatic treatment and remains the gold standard at all stages. " "Start low and titrate to symptom control. Target the lowest effective dose to minimise dyskinesia risk."), ("A","In patients aged <70 years with no significant cognitive impairment, a dopamine agonist (pramipexole, " "ropinirole, or rotigotine) may be used as initial monotherapy to delay levodopa exposure and reduce " "early dyskinesia risk. Inform patients of impulse control disorder risk (5-17%)."), ("A","MAO-B inhibitors (rasagiline, selegiline, safinamide) provide mild symptomatic benefit and may be " "used as initial monotherapy in very mild disease or as an adjunct. Selegiline: avoid with SSRIs/SNRIs."), ("C","Physiotherapy, exercise (aerobic + resistance), and speech therapy should be initiated at diagnosis " "alongside pharmacotherapy."), ],GREEN), ("MODERATE PD — MOTOR FLUCTUATIONS",[ ("A","Wearing-off: Add a COMT inhibitor (entacapone with each levodopa dose, or opicapone 50mg OD) " "OR add a MAO-B inhibitor OR switch to controlled-release levodopa formulations."), ("A","Alternatively, add a dopamine agonist if not already prescribed, to smooth motor response " "and extend ON-time."), ("B","Istradefylline (adenosine A2A antagonist, 20-40mg OD) reduces OFF-time by ~45 min/day as adjunct " "to levodopa/carbidopa and is well tolerated."), ("B","Divide total daily levodopa into smaller, more frequent doses (e.g. 4-6 times daily) " "to reduce peak-dose dyskinesias while maintaining total daily exposure."), ],STEEL), ("ADVANCED PD — DYSKINESIAS & REFRACTORY FLUCTUATIONS",[ ("A","Amantadine (NMDA antagonist) reduces levodopa-induced dyskinesias. " "Extended-release amantadine (Gocovri 274mg at bedtime) is FDA-approved for dyskinesias."), ("A","Deep Brain Stimulation (DBS) of the subthalamic nucleus (STN) or globus pallidus internus (GPi) " "significantly improves motor fluctuations and dyskinesias in carefully selected patients. " "Best candidates: good levodopa response, age <70, no significant dementia or psychosis."), ("B","Levodopa-carbidopa intestinal gel (LCIG/Duodopa) via PEG-jejunal infusion provides continuous " "dopaminergic stimulation and markedly reduces OFF-time in patients not suitable for DBS."), ("B","Focused ultrasound thalamotomy provides unilateral tremor suppression in tremor-dominant PD " "where DBS is not suitable."), ("C","For PD-related psychosis: first reduce/eliminate anticholinergics and dopamine agonists. " "If necessary add: AChEI (rivastigmine) → quetiapine → clozapine (with WBC monitoring). " "NEVER use haloperidol, risperidone, or olanzapine in PD/DLB."), ],ORANGE), ]: story.append(Paragraph(title, sH2)) story.append(sp(3)) for grade,text in recs: story.append(rec_box(f"Grade\n{grade}",text, grade_cols.get(grade,STEEL))) story.append(sp(3)) story.append(sp(4)) story.append(Paragraph("<b>Infographic 2: Pharmacological Management Algorithm</b>", S("ih3",fontSize=9,textColor=NAVY,fontName="Helvetica-Bold", leading=12,alignment=TA_CENTER))) story.append(sp(3)) story.append(img(f"{ASSET}/infographic_02_treatment.png",W=W,max_h=250*mm)) story.append(sp(3)) story.append(Paragraph( "Figure 2. Parkinson's Disease pharmacological management algorithm from early through advanced disease " "and surgical options. Based on AAN Practice Guidelines, MDS Evidence Review, and Katzung Pharmacology 16E.",sNote)) story.append(PageBreak()) # ── SECTION 8 ─────────────────────────────────────────────────────────────── story.append(secheader("8. NON-PHARMACOLOGICAL MANAGEMENT",TEAL)) story.append(sp(5)) story.append(two_col( ["Physiotherapy: gait training, balance, posture, fall prevention, cueing strategies", "Aerobic exercise (150 min/week moderate intensity): neuroprotective signal in animal models; improves motor scores", "Resistance training: muscle strength, freezing of gait, functional independence", "Tai Chi / yoga: balance and fall reduction (RCT evidence)", "Dance therapy (tango): gait and balance improvement (pilot evidence)", "Occupational therapy: adaptive equipment, home hazard assessment, driving review", ], ["Speech & Language Therapy: Lee Silverman Voice Treatment (LSVT LOUD) for hypophonia", "Swallowing assessment and modified diet for dysphagia (refer early in MSA/PSP)", "Neuropsychology: cognitive rehabilitation, depression/anxiety management, CBT", "Dietitian: Mediterranean diet, nutritional assessment, protein redistribution (with levodopa)", "Palliative care: advance care planning, goals of care, end-of-life symptom management", "Patient support groups: Parkinson's UK, Michael J. Fox Foundation, World Parkinson Coalition", ], h1="PHYSICAL & FUNCTIONAL",h2="COMMUNICATION & COGNITIVE",c1=TEAL,c2=STEEL )) story.append(sp(6)) story.append(rec_box("A","Regular aerobic exercise (≥150 min/week moderate intensity) is recommended for " "all PD patients for motor and non-motor benefit. Physiotherapy and speech therapy " "should be offered at time of diagnosis.", TEAL)) story.append(sp(8)) # ── SECTION 9 + INFOGRAPHIC 4 ─────────────────────────────────────────────── story.append(secheader("9. NON-MOTOR FEATURES & MANAGEMENT",PURPLE)) story.append(sp(5)) story.append(Paragraph( "Non-motor features are present in >90% of PD patients throughout the disease course and have a greater " "impact on quality of life than motor symptoms in many patients. Pre-motor features (anosmia, constipation, " "RBD) may precede motor onset by 5-25 years. Systematic screening at each visit is recommended.", sJust)) story.append(sp(4)) nm_data=[ ["FEATURE","PREVALENCE","SCREENING","MANAGEMENT","GRADE"], ["Constipation","50-80% (pre-motor)","Bowel habit history","Increase fluid/fibre, osmotic laxatives, polyethylene glycol","C"], ["Anosmia","90%","UPSIT / Sniffin' Sticks","No treatment; prognostic biomarker","C"], ["REM sleep behaviour disorder","40-50% at diagnosis","Polysomnography","Melatonin 2-12mg OR clonazepam 0.25-0.5mg","B"], ["Depression","40-50%","GDS-15 / PHQ-9","SSRIs (sertraline, escitalopram); avoid TCAs","A"], ["Anxiety","30-40%","GAD-7","SSRIs; CBT; avoid benzodiazepines","B"], ["Orthostatic hypotension","30-40%","Standing BP (1,3,5 min)","Head-up tilt, compression stockings, fludrocortisone, midodrine","B"], ["Urinary urgency","40-70%","IPSS questionnaire","Bladder training, solifenacin, botulinum toxin","C"], ["Cognitive impairment (MCI→PDD)","80% by 20 yrs","MoCA (monthly)","Rivastigmine (FDA-approved PDD); donepezil","A"], ["Visual hallucinations","20-40%","Ask directly at each visit","Reduce/stop anticholinergics; rivastigmine; quetiapine","B"], ["Drooling / sialorrhoea","70-80% advanced","Clinical assessment","Speech therapy; atropine drops; botulinum toxin","B"], ["Pain","40-60%","NRS; pain type classification","Optimise dopaminergic therapy; pregabalin (nociceptive)","C"], ["Impulse control disorder","5-17% on DAs","QUIP-RS screening","Reduce/stop dopamine agonist; CBT","A"], ] nh=ParagraphStyle("nh",fontSize=7.5,textColor=WHITE,fontName="Helvetica-Bold",leading=10,alignment=TA_CENTER) nc=ParagraphStyle("nc",fontSize=7.5,textColor=BLACK,fontName="Helvetica",leading=10) nmrows=[[Paragraph(c,nh) for c in nm_data[0]]] for row in nm_data[1:]: nmrows.append([Paragraph(c,nc) for c in row]) nmt=Table(nmrows,colWidths=[32*mm,22*mm,30*mm,W-98*mm,14*mm]) nm_cmds=[ ("BACKGROUND",(0,0),(-1,0),PURPLE), ("GRID",(0,0),(-1,-1),0.3,MGREY), ("TOPPADDING",(0,0),(-1,-1),3),("BOTTOMPADDING",(0,0),(-1,-1),3), ("LEFTPADDING",(0,0),(-1,-1),4),("RIGHTPADDING",(0,0),(-1,-1),4), ("VALIGN",(0,0),(-1,-1),"TOP"), ("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE,LGREY]), ] for ri,row in enumerate(nm_data[1:],1): gc=grade_cols.get(row[4],STEEL) nm_cmds.append(("BACKGROUND",(4,ri),(4,ri),gc)) nmt.setStyle(TableStyle(nm_cmds)) story.append(nmt) story.append(sp(5)) story.append(Paragraph("<b>Infographic 4: Non-Motor Features, Timeline & Drug Profile</b>", S("ih4",fontSize=9,textColor=NAVY,fontName="Helvetica-Bold", leading=12,alignment=TA_CENTER))) story.append(sp(3)) story.append(img(f"{ASSET}/infographic_04_nonmotor_drugs.png",W=W,max_h=260*mm)) story.append(sp(3)) story.append(Paragraph( "Figure 4. Non-motor features of Parkinson's Disease mapped to disease timeline, monitoring schedule (top), " "and antiparkinsonian drug quick-reference profile with adverse effects (bottom).", sNote)) story.append(PageBreak()) # ── SECTION 10 + INFOGRAPHIC 3 ────────────────────────────────────────────── story.append(secheader("10. ATYPICAL PARKINSONISM SYNDROMES",RED)) story.append(sp(5)) story.append(Paragraph( "Atypical Parkinsonism syndromes (APS) collectively account for ~15-20% of parkinsonism. They are " "clinically important because they have poor levodopa response, more rapid progression, " "and require different management. Misdiagnosis rates are high: ~25% of PD diagnoses, and up to " "74% of CBS cases may be initially misdiagnosed. Post-mortem studies remain the diagnostic gold standard.", sJust)) story.append(sp(5)) for name,col,features,imaging,path,mgmt in [ ("PROGRESSIVE SUPRANUCLEAR PALSY (PSP)",RED, "Vertical supranuclear gaze palsy (downward >> upward) · Early unexplained falls (retropulsion) · " "Axial rigidity > limb rigidity · Retrocollis · Frontal/executive cognitive decline · " "Eyelid opening apraxia · Dysphagia early", "MRI sagittal: Hummingbird/penguin sign (midbrain atrophy) · Reduced midbrain diameter <14mm · " "DaTscan: symmetric reduction", "4R-Tauopathy · Neurofibrillary tangles in STN, SN, locus coeruleus, frontal cortex", "No effective pharmacotherapy · Falls prevention programme · PEG tube for dysphagia · " "Botulinum toxin for blepharospasm · Supportive/palliative care · Prognosis: 5-7 years"), ("MULTIPLE SYSTEM ATROPHY (MSA)",PURPLE, "MSA-P: Parkinsonism (dominant) · MSA-C: Cerebellar ataxia (dominant) · " "Severe early autonomic failure (OH, urinary incontinence, erectile dysfunction) · " "Inspiratory stridor / nocturnal laryngeal spasm · Emotional incontinence · " "Onset typically age 50-60", "MRI: Hot cross bun sign (pons, T2) · Putaminal hypointensity + slit-like signal (T2*) · " "Cerebellar atrophy (MSA-C) · DaTscan: symmetric bilateral reduction", "Alpha-synuclein in Glial Cytoplasmic Inclusions (GCIs) in oligodendrocytes · " "Olivopontocerebellar atrophy (MSA-C) · Striatonigral degeneration (MSA-P)", "Levodopa trial (partial response 30-40%, fades) · Fludrocortisone + midodrine for OH · " "CPAP or tracheostomy for stridor · Urological referral · PEG tube · " "Physiotherapy for ataxia · Prognosis: 6-10 years"), ("CORTICOBASAL SYNDROME (CBS)",ORANGE, "Markedly asymmetric parkinsonism · Alien limb phenomenon · Ideomotor limb apraxia · " "Cortical sensory loss (astereognosis, graphaesthesia) · Focal limb dystonia · " "Stimulus-sensitive myoclonus · Nonfluent aphasia (if frontal involvement)", "MRI: Asymmetric frontoparietal cortical atrophy (contralateral to affected limb) · " "FDG-PET: Asymmetric frontoparietal hypometabolism · DaTscan: Asymmetric reduction", "4R-Tauopathy · Corticobasal inclusions (astrocytic plaques + NT inclusions) · " "Also: TDP-43 pathology in some CBS presentations", "No effective pharmacotherapy · Clonazepam for myoclonus · " "OT for limb apraxia and function · Speech therapy for aphasia · " "Physiotherapy · Prognosis: 6-8 years · Botulinum toxin for focal dystonia"), ("DEMENTIA WITH LEWY BODIES (DLB)",STEEL, "Dementia onset ≤1 year of motor parkinsonism (vs. PDD where dementia comes >1 year after motor) · " "Recurrent well-formed visual hallucinations · Fluctuating cognition and alertness · " "REM sleep behaviour disorder · SEVERE neuroleptic sensitivity (risk of death) · " "Repeated unexplained falls · Syncope", "DaTscan: Bilateral reduced dopamine transporter · MIBG cardiac scintigraphy: Reduced H/M ratio · " "FDG-PET: Occipital hypometabolism · EEG: Posterior slow waves", "Cortical and subcortical Lewy bodies (alpha-synuclein) · " "Cholinergic deficit more severe than PD or AD · " "Some patients have concurrent AD pathology", "AChEIs (rivastigmine, donepezil) — first-line for cognition AND hallucinations · " "ABSOLUTELY AVOID: haloperidol, olanzapine, risperidone (mortality risk) · " "Quetiapine or clozapine ONLY if AChEIs insufficient for psychosis · " "Low-dose levodopa for motor symptoms · Melatonin/clonazepam for RBD"), ]: story.append(Paragraph(name, sH2)) story.append(sp(3)) feat_style=ParagraphStyle("fss",fontSize=8,textColor=BLACK,fontName="Helvetica",leading=12) ks=ParagraphStyle("ks",fontSize=8,textColor=WHITE,fontName="Helvetica-Bold",leading=11,alignment=TA_CENTER) block=Table([ [Paragraph("CLINICAL FEATURES",ks),Paragraph("IMAGING",ks), Paragraph("PATHOLOGY",ks),Paragraph("MANAGEMENT",ks)], [Paragraph(features,feat_style),Paragraph(imaging,feat_style), Paragraph(path,feat_style),Paragraph(mgmt,feat_style)], ],colWidths=[W/4]*4) block.setStyle(TableStyle([ ("BACKGROUND",(0,0),(-1,0),col), ("GRID",(0,0),(-1,-1),0.3,MGREY), ("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4), ("LEFTPADDING",(0,0),(-1,-1),5),("RIGHTPADDING",(0,0),(-1,-1),5), ("VALIGN",(0,0),(-1,-1),"TOP"), ("ROWBACKGROUNDS",(0,1),(-1,-1),[colors.HexColor("#FDF2F2") if col==RED else colors.HexColor("#F5EEF8") if col==PURPLE else colors.HexColor("#FDFBE4") if col==ORANGE else LGREY]), ])) story.append(block) story.append(sp(6)) story.append(Paragraph("<b>Infographic 3: Atypical Parkinsonism At-a-Glance Comparison</b>", S("ih5",fontSize=9,textColor=NAVY,fontName="Helvetica-Bold", leading=12,alignment=TA_CENTER))) story.append(sp(3)) story.append(img(f"{ASSET}/infographic_03_atypical.png",W=W,max_h=230*mm)) story.append(sp(3)) story.append(Paragraph( "Figure 3. Comprehensive comparison of PD vs. PSP, MSA, CBS and DLB across 9 clinical, " "imaging, pathological and management domains. ★★ = highly characteristic/critical feature.",sNote)) story.append(PageBreak()) # ── SECTION 11 ────────────────────────────────────────────────────────────── story.append(secheader("11. SPECIAL POPULATIONS",GOLD)) story.append(sp(5)) for pop,items in [ ("YOUNG-ONSET PD (Age <50 years)",[ "Mandatory Wilson's disease screen: ceruloplasmin, 24h urine copper, slit-lamp examination", "Genetic testing recommended: Parkin (PARK2) accounts for up to 50% of early-onset AR cases; " "also PINK1, DJ-1, GBA1", "Higher risk of early levodopa-induced motor complications — start dopamine agonist first where possible", "DaTscan useful to confirm diagnosis; FDG-PET may aid differential", "Genetic counselling for patient and family members; consider cascade testing", "Employment, fertility, and insurance implications must be discussed proactively", ]), ("ELDERLY PATIENTS (Age >80 years)",[ "Levodopa/carbidopa is the preferred first-line treatment — dopamine agonists poorly tolerated (falls, somnolence, ICD)", "Avoid anticholinergics (trihexyphenidyl, benztropine): high risk of confusion, urinary retention, falls", "Orthostatic hypotension is common — check lying and standing BP at every visit", "Fall risk assessment and home hazard modification are mandatory at diagnosis", "Cognitive assessment (MoCA) at baseline and every 6-12 months", "Drug-induced parkinsonism must be excluded before commencing dopaminergic therapy", ]), ("PREGNANCY",[ "No antiparkinsonian drug is established as safe in pregnancy — counsel carefully", "If treatment essential: levodopa is the most studied; animal studies show no teratogenicity", "Dopamine agonists: limited data; generally avoided in first trimester", "Multidisciplinary team approach: obstetrician + neurologist + neonatologist", "Genetic counselling: LRRK2 (AD) and Parkin (AR) — implications for offspring", "Postpartum monitoring: disease may worsen after delivery", ]), ("HEPATIC / RENAL IMPAIRMENT",[ "Pramipexole: renal excretion — reduce dose if eGFR <50 ml/min", "Tolcapone: avoid in liver disease (hepatotoxic — monitor LFTs q2-4 wks)", "Amantadine: reduce dose in renal impairment; avoid if eGFR <15", "Levodopa/carbidopa: no dose adjustment for renal/hepatic impairment", "Selegiline: caution in severe hepatic impairment", ]), ]: story.append(Paragraph(pop,sH2)) for item in items: story.append(Paragraph(item,sBull)) story.append(sp(5)) story.append(PageBreak()) # ── SECTION 12 ────────────────────────────────────────────────────────────── story.append(secheader("12. MONITORING & FOLLOW-UP",TEAL)) story.append(sp(5)) mon_data=[ ["INTERVAL","CLINICAL ASSESSMENT","INVESTIGATIONS","MANAGEMENT REVIEW"], ["Every visit\n(3-6 monthly\nearly; 3-monthly\nadvanced)", "UPDRS-III motor score\nFall history + pull test\nNon-motor symptom review (NMSScale)\nOrthostatic BP\nWeight + nutrition\nMedication side-effects", "—","Medication optimisation\nPhysiotherapy referral if new issues\nSpeech therapy if hypophonia/dysphagia"], ["Every 6 months", "MoCA cognitive screening\nDepression screen (GDS-15)\nSwallowing assessment\nSleep disorder assessment (PDSS-2)\nQUIP-RS (if on DA)", "Renal function (amantadine)\nLFTs (tolcapone)\nFull blood count (clozapine)", "Adjust medications for fluctuations\nConsider COMT inhibitor/DA if wearing-off\nRefer neuropsychology if MoCA <24"], ["Annually", "Full neuropsychological assessment\nBone mineral density (DEXA)\nDriving fitness review\nAdvance care planning discussion\nCaregiver burden assessment", "DaTscan (if diagnostic uncertainty remains)\nGenetic counselling update (if relevant)", "Consider DBS assessment if advanced motor complications\nMDT meeting\nPalliative care referral if advanced disease"], ["As clinically\nindicated", "Urodynamics (urinary sx)\nOphthalmology (visual sx)\nCardiology (syncope)", "MIBG if DLB vs PD uncertain\nCSF SAA biomarker\nPolysomnography for RBD\nTilt table for severe OH", "PEG tube assessment (dysphagia)\nLCIG assessment (severe fluctuations)\nFocused ultrasound (tremor)\nHospice referral"], ] mh=ParagraphStyle("mh",fontSize=8,textColor=WHITE,fontName="Helvetica-Bold",leading=10,alignment=TA_CENTER) mc=ParagraphStyle("mc",fontSize=7.5,textColor=BLACK,fontName="Helvetica",leading=11) mrows=[[Paragraph(c,mh) for c in mon_data[0]]] for row in mon_data[1:]: mrows.append([Paragraph(c,mc) for c in row]) mt2=Table(mrows,colWidths=[22*mm,55*mm,45*mm,W-122*mm]) mt2.setStyle(TableStyle([ ("BACKGROUND",(0,0),(-1,0),TEAL), ("GRID",(0,0),(-1,-1),0.3,MGREY), ("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4), ("LEFTPADDING",(0,0),(-1,-1),5),("RIGHTPADDING",(0,0),(-1,-1),5), ("VALIGN",(0,0),(-1,-1),"TOP"), ("ROWBACKGROUNDS",(0,1),(-1,-1),[WHITE,LGREY]), ("BACKGROUND",(0,1),(0,1),colors.HexColor("#0A5C4C")), ("BACKGROUND",(0,2),(0,2),TEAL), ("BACKGROUND",(0,3),(0,3),colors.HexColor("#0D7A64")), ("BACKGROUND",(0,4),(0,4),STEEL), ("TEXTCOLOR",(0,1),(0,-1),WHITE), ("FONTNAME",(0,1),(0,-1),"Helvetica-Bold"), ])) story.append(mt2) story.append(sp(8)) # ── SECTION 13 ────────────────────────────────────────────────────────────── story.append(secheader("13. PATIENT INFORMATION & SHARED DECISION MAKING",NAVY)) story.append(sp(5)) story.append(two_col( ["Inform patients of diagnosis sensitively, with time for questions and follow-up appointment", "Explain the progressive nature of PD but emphasise that many people live well for 10-20+ years", "Discuss treatment options including benefits, risks, and alternatives for each drug class", "Counsel on impulse control disorder risk with dopamine agonists — must be explicit", "Discuss genetic implications if family history is present or onset is early", "Provide written information (Parkinson's UK, EPDA leaflets)", ], ["Driving: notify DVLA (UK) / equivalent authority; reassess annually", "Exercise: emphasise the benefit of regular aerobic exercise — prescribe it", "Diet: Mediterranean diet, avoid protein-heavy meals close to levodopa doses", "Falls prevention: home assessment, avoid rugs, grab rails, alarm device", "Advance care planning: discuss while patient has capacity; include LPA", "Support groups: Parkinson's UK, Michael J Fox Foundation, local carer groups", ], h1="INFORMATION & COUNSELLING",h2="LIFESTYLE & SAFETY",c1=NAVY,c2=STEEL )) story.append(sp(8)) # ── SECTION 14 ────────────────────────────────────────────────────────────── story.append(secheader("14. REFERENCES & EVIDENCE BASE",GREY:=colors.HexColor("#555555"))) story.append(sp(5)) refs=[ "Berg D, et al. MDS Research Criteria for Prodromal Parkinson's Disease. Movement Disorders 2015;30(12):1600-11.", "Postuma RB, et al. MDS Clinical Diagnostic Criteria for Parkinson's Disease. Movement Disorders 2015;30(12):1591-601.", "Harrison's Principles of Internal Medicine, 22nd Edition. McGraw-Hill, 2025. Chapter 446: Parkinson's Disease and Related Disorders.", "Bradley and Daroff's Neurology in Clinical Practice, 8th Edition. Elsevier, 2022. Chapters 24, 95.", "Katzung BG. Basic and Clinical Pharmacology, 16th Edition. McGraw-Hill, 2023. Chapter 28: Pharmacologic Management of Parkinsonism.", "Adams and Victor's Principles of Neurology, 12th Edition. McGraw-Hill, 2023.", "Kaplan & Sadock's Comprehensive Textbook of Psychiatry, 11th Edition.", "Washington Manual of Medical Therapeutics, 36th Edition. Wolters Kluwer, 2020.", "Kalia LV, Lang AE. Parkinson's Disease. Lancet 2015;386(9996):896-912.", "Braak H, et al. Staging of brain pathology related to sporadic Parkinson's disease. Neurobiology of Aging 2003;24(2):197-211.", "Reese R, et al. Invasive therapies for Parkinson's disease: an adapted excerpt from the guidelines of the German Society of Neurology. J Neurology 2025. PMID: 39985674.", "Weaver FM, et al. Bilateral deep brain stimulation vs. best medical therapy for advanced Parkinson's disease: a randomized controlled trial. JAMA 2009;301(1):63-73.", "Rivastigmine for PD dementia (EXPRESS study). Emre M, et al. NEJM 2004;351(24):2509-18.", "McKeith IG, et al. Diagnosis and management of dementia with Lewy bodies: Fourth consensus report of the DLB Consortium. Neurology 2017;89(1):88-100.", "O'Sullivan SS, et al. Clinicopathological findings in PSP. Brain 2008;131(6):1659-73.", ] rs=ParagraphStyle("rs",fontSize=7.5,textColor=BLACK,fontName="Helvetica", leading=11,leftIndent=15,firstLineIndent=-15) for i,ref in enumerate(refs,1): story.append(Paragraph(f"{i}. {ref}",rs)) story.append(sp(2)) story.append(sp(8)) story.append(hr()) story.append(Paragraph( "© 2026 Orris Medical Intelligence. This Clinical Practice Guideline is intended for educational and " "reference purposes only. It does not constitute formal institutional clinical guidelines. " "Clinical decisions should be individualised and made in consultation with the patient. " "Always refer to current national guidelines and drug monographs for prescribing decisions.", sNote)) doc.build(story) print(f"PDF saved: {OUT}") import os; print(f"Size: {os.path.getsize(OUT)//1024} KB, pages ~{os.path.getsize(OUT)//8000}") PYEOF

?

Your Clinical Practice Guideline PDF is ready! Here is the download link:

Parkinsonism Clinical Practice Guideline

PDF Document · PDF


What's inside (~1.9 MB, ~20 pages):
4 Full-Page Infographics (matplotlib-generated):
  • Infographic 1 - Diagnostic Algorithm: stepwise flowchart from presentation → secondary exclusion → red flags → MDS criteria → confirmed PD or atypical syndrome, with genetic panel and investigation rows
  • Infographic 2 - Treatment Algorithm: tiered from early PD → moderate → advanced → surgical options (DBS, LCIG, FUS), with MDT and non-pharmacological sections
  • Infographic 3 - Atypical Parkinsonism Comparison: PD vs PSP vs MSA vs CBS vs DLB across 9 domains (features, tremor, levodopa, imaging, pathology, autonomic, cognition, management, prognosis)
  • Infographic 4 - Non-Motor Features + Drug Profile: disease timeline bar, 10 non-motor feature boxes, monitoring schedule, and full 7-drug class reference table with adverse effects
14 Guideline Sections:
  1. Introduction & Scope
  2. Definition & Pathophysiology (basal ganglia circuits, Braak staging)
  3. Classification table (PD / Atypical / Secondary / Other)
  4. Clinical Assessment & MDS Diagnostic Criteria
  5. Red Flags (18 flags with diagnosis pointer)
  6. Investigations (11 tests, graded A/B/C, with interpretation guide)
  7. Pharmacological Management (graded recommendations by disease stage)
  8. Non-Pharmacological Management (physio, speech therapy, exercise, palliative)
  9. Non-Motor Features table (12 features, prevalence, screening, management)
  10. Atypical Parkinsonism — PSP, MSA, CBS, DLB detailed blocks
  11. Special Populations (young-onset, elderly, pregnancy, organ impairment)
  12. Monitoring & Follow-up schedule
  13. Patient Information & Shared Decision Making
  14. References (15 primary sources)

Can you make a video explaining drugs use in Parkinson

I'm not able to generate videos directly — that's outside what I can create. However, here are the best options I can offer:
What I can do instead:
  1. Animated slide presentation (.pptx) — A narration-ready PowerPoint with visual slides covering each drug class, mechanism diagrams, dose tables, and adverse effects. You could record your voice over it to make a video.
  2. Full illustrated PDF — Like the CPG we just made, but focused entirely on drug pharmacology with mechanism diagrams for each drug class.
  3. Find an existing video — I can search for high-quality YouTube explanations of Parkinson's pharmacology right now.
Here are some well-known educational video sources on this topic:
Searching that will surface channels like:
  • Ninja Nerd (detailed mechanism-based pharmacology)
  • Osmosis (visual medical education)
  • Armando Hasudungan (hand-drawn mechanism diagrams)
  • Sketchy Medical (mnemonic-based pharmacology)

Which would you prefer?
Asking for Preferences

What would be most useful for you?

Searching the Web

best YouTube videos Parkinson disease drugs pharmacology explained levodopa dopamine agonists

Here are the best YouTube videos on Parkinson's disease drugs, ranked by quality and depth:

🥇 Best Overall — Ninja Nerd (1hr 36min, comprehensive)

Ninja Nerd Science — Prof. Zach Murphy covers everything: basal ganglia anatomy, direct/indirect pathways, pathophysiology, then every drug class with mechanisms. Timestamped chapters:
  • 0:00 - Intro | 1:20 - Basal Ganglia anatomy | 4:23 - Direct vs Indirect Pathway
  • 18:23 - PD Pathophysiology | 21:26 - Drug Classes overview
  • 38:51 - Levodopa + Carbidopa (deep dive)
  • 1:00:22 - Dopamine Agonists | 1:06:08 - COMT Inhibitors
  • 1:11:39 - MAO-B Inhibitors | 1:20:12 - Amantadine
  • 1:27:10 - Anticholinergics | 1:31:18 - Practice Problems
265,000+ views · Based on Lippincott Pharmacology

🥈 Best for Nursing / NCLEX — SimpleNursing (concise)

SimpleNursing — Focuses on levodopa, nursing interventions, the dopamine/acetylcholine imbalance concept, and NCLEX-relevant points. Clear, visual, and fast-paced.
320,000+ views · Ideal for quick review

Other top channels to search directly:

ChannelWhat to searchStyle
Osmosis"Parkinson's pharmacology"Animated, visual
Armando Hasudungan"Parkinson's treatment"Hand-drawn mechanisms
Sketchy Medical"Parkinson's drugs"Mnemonic stories
Boards & Beyond"Parkinson's medications"USMLE-focused
DirtyUSMLE"Parkinson's"High-yield bullet style

The Ninja Nerd video is the strongest single resource — it starts from the circuit-level mechanism and builds all the way through every drug class used clinically. Highly recommended as a complete lecture.

Armando hasudungan

Searching the Web

Armando Hasudungan Parkinson's disease treatment drugs YouTube

Found it! Armando has two videos on Parkinson's — watch them in order:

Part 1 — Pathophysiology first (watch this before the drugs video):
This is the Pharmacology of Parkinson's Disease video (399,000+ views, 2.89M subscribers). It covers:
  • Substantia nigra dopaminergic neuron loss
  • Levodopa + Carbidopa — mechanism, why carbidopa is needed (peripheral decarboxylase inhibitor)
  • Dopamine Agonists — mimic dopamine at receptors
  • MAO-B Inhibitors — prevent dopamine breakdown inside the neuron
  • Anticholinergics — balance dopamine/acetylcholine
Armando's signature hand-drawn, colour-coded diagram style makes the mechanisms very visual and easy to follow.

Part 2 — Clinical Presentation & Pathophysiology (background context):
His pathophysiology video (from armandoh.org) covers the clinical features — resting tremor, rigidity, bradykinesia — which gives great context before the pharmacology.

Tip: Armando recommends watching his pathophysiology video first, then the pharmacology one — the drug mechanisms make much more sense once you understand the circuit-level deficit.

Osmosis

Searching the Web

Osmosis YouTube Parkinson's disease drugs pharmacology treatment video

Osmosis has two videos — watch them as a pair:

Video 1 — Anti-Parkinson Medications (drugs focus):
Timestamped chapters:
  • 0:00 - Introduction
  • 0:23 - Pathophysiology recap (basal ganglia, dopamine deficit)
  • 1:49 - Mechanism of action overview
  • 2:29 - Levodopa (detailed)
  • 4:38 - Dopamine receptor agonists (bromocriptine, pramipexole, ropinirole)
  • 5:24 - MAO-B inhibitors (rasagiline — blocks dopamine breakdown)
  • COMT inhibitors (tolcapone, entacapone — prevent levodopa breakdown)
Full Osmosis lesson page with labeled diagrams and quiz: osmosis.org/learn/Anti-parkinson_medications

Video 2 — Parkinson's Disease (full disease overview):
Covers the full clinical picture — pathophysiology, Lewy bodies, symptoms, staging — giving essential context for the drug mechanisms.

Why Osmosis stands out: their signature animated style shows the drug acting at the synapse in real time — you can literally see levodopa crossing the blood-brain barrier, carbidopa blocking peripheral decarboxylation, and MAO-B being inhibited. Great for visual learners. Pair with their free quiz bank on the same page to test yourself after watching.
This is a shared conversation. Sign in to Orris to start your own chat.