~/hmf-pdf/generate_hmf_pdf.py
"""
Higher Mental Functions (HMF) - Colourful PDF Generator
MD General Medicine Final Practical Examination Guide
Uses ReportLab for rich formatting, colours, and layout.
"""
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, PageBreak, KeepTogether
)
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus.flowables import Flowable
import os
OUTPUT = "/tmp/workspace/hmf-pdf/Higher_Mental_Functions_MD_Guide.pdf"
# ── Colour Palette ──────────────────────────────────────────────────────────
DEEP_NAVY = colors.HexColor("#0D1B3E")
ROYAL_BLUE = colors.HexColor("#1A4A9C")
SKY_BLUE = colors.HexColor("#3A7BD5")
TEAL = colors.HexColor("#0F7B6C")
EMERALD = colors.HexColor("#1D7A4A")
CRIMSON = colors.HexColor("#C0392B")
ORANGE = colors.HexColor("#E67E22")
GOLD = colors.HexColor("#D4A017")
PURPLE = colors.HexColor("#6C3483")
DARK_PURPLE = colors.HexColor("#4A235A")
LIGHT_BLUE = colors.HexColor("#D6EAF8")
LIGHT_TEAL = colors.HexColor("#D1F2EB")
LIGHT_GREEN = colors.HexColor("#D5F5E3")
LIGHT_ORANGE = colors.HexColor("#FDEBD0")
LIGHT_PURPLE = colors.HexColor("#E8DAEF")
LIGHT_YELLOW = colors.HexColor("#FEF9E7")
LIGHT_PINK = colors.HexColor("#FDEDEC")
LIGHT_GREY = colors.HexColor("#F2F3F4")
WHITE = colors.white
BLACK = colors.black
DARK_GREY = colors.HexColor("#2C3E50")
MID_GREY = colors.HexColor("#7F8C8D")
# ── Page dimensions ──────────────────────────────────────────────────────────
PAGE_W, PAGE_H = A4 # 595 x 842 pts
# ── Document ─────────────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=1.8*cm, rightMargin=1.8*cm,
topMargin=2.5*cm, bottomMargin=2.0*cm,
title="Higher Mental Functions – MD General Medicine Guide",
author="Orris AI"
)
# ── Styles ────────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()
def S(name, **kw):
return ParagraphStyle(name, **kw)
TITLE_STYLE = S("DocTitle",
fontName="Helvetica-Bold", fontSize=26, leading=32,
textColor=WHITE, alignment=TA_CENTER, spaceAfter=4)
SUBTITLE_STYLE = S("DocSubtitle",
fontName="Helvetica", fontSize=12, leading=16,
textColor=colors.HexColor("#BDC3C7"), alignment=TA_CENTER, spaceAfter=2)
PART_STYLE = S("PartHeading",
fontName="Helvetica-Bold", fontSize=17, leading=22,
textColor=WHITE, spaceAfter=6, spaceBefore=8)
H2_STYLE = S("H2",
fontName="Helvetica-Bold", fontSize=13, leading=17,
textColor=WHITE, spaceAfter=4, spaceBefore=8)
H3_STYLE = S("H3",
fontName="Helvetica-Bold", fontSize=11, leading=15,
textColor=DEEP_NAVY, spaceAfter=3, spaceBefore=6)
H4_STYLE = S("H4",
fontName="Helvetica-Bold", fontSize=10, leading=14,
textColor=ROYAL_BLUE, spaceAfter=2, spaceBefore=4)
BODY_STYLE = S("Body",
fontName="Helvetica", fontSize=9.5, leading=14,
textColor=DARK_GREY, spaceAfter=5, alignment=TA_JUSTIFY)
BODY_BOLD = S("BodyBold",
fontName="Helvetica-Bold", fontSize=9.5, leading=14,
textColor=DARK_GREY, spaceAfter=4)
BULLET_STYLE = S("Bullet",
fontName="Helvetica", fontSize=9.5, leading=13,
textColor=DARK_GREY, leftIndent=14, firstLineIndent=-10,
spaceAfter=3)
PEARL_STYLE = S("Pearl",
fontName="Helvetica-BoldOblique", fontSize=9.5, leading=14,
textColor=DARK_PURPLE, spaceAfter=4, leftIndent=8, rightIndent=8)
NOTE_STYLE = S("Note",
fontName="Helvetica-Oblique", fontSize=9, leading=13,
textColor=TEAL, spaceAfter=4, leftIndent=8)
CODE_STYLE = S("Code",
fontName="Courier", fontSize=8.5, leading=12,
textColor=DARK_GREY, spaceAfter=4, leftIndent=10)
SMALL_STYLE = S("Small",
fontName="Helvetica", fontSize=8, leading=11,
textColor=MID_GREY, spaceAfter=2)
REF_STYLE = S("Ref",
fontName="Helvetica-Oblique", fontSize=8, leading=11,
textColor=MID_GREY, spaceAfter=2, alignment=TA_CENTER)
# ── Helper Flowables ──────────────────────────────────────────────────────────
class ColourBanner(Flowable):
"""A full-width solid colour banner (used for part headings)."""
def __init__(self, text, bg_color, text_style, height=28, radius=6):
super().__init__()
self.text = text
self.bg_color = bg_color
self.text_style = text_style
self.banner_height = height
self.radius = radius
def wrap(self, availWidth, availHeight):
self.avail_w = availWidth
return (availWidth, self.banner_height + 4)
def draw(self):
c = self.canv
w = self.avail_w
h = self.banner_height
r = self.radius
c.setFillColor(self.bg_color)
c.roundRect(0, 0, w, h, r, stroke=0, fill=1)
c.setFillColor(WHITE)
c.setFont(self.text_style.fontName, self.text_style.fontSize)
c.drawCentredString(w / 2, h / 2 - self.text_style.fontSize / 3, self.text)
class SideBar(Flowable):
"""A coloured left-side vertical bar with text (for callouts)."""
def __init__(self, text, bar_color, bg_color, width, style):
super().__init__()
self._text = text
self.bar_color = bar_color
self.bg_color = bg_color
self._width = width
self._style = style
def wrap(self, availWidth, availHeight):
from reportlab.platypus import Paragraph
self.avail_w = availWidth
p = Paragraph(self._text, self._style)
_, h = p.wrap(availWidth - 20, availHeight)
self._h = h + 12
return (availWidth, self._h)
def draw(self):
c = self.canv
w = self.avail_w
h = self._h
c.setFillColor(self.bg_color)
c.roundRect(0, 0, w, h, 4, stroke=0, fill=1)
c.setFillColor(self.bar_color)
c.rect(0, 0, 5, h, stroke=0, fill=1)
from reportlab.platypus import Paragraph
p = Paragraph(self._text, self._style)
p.wrapOn(c, w - 20, h)
p.drawOn(c, 14, 6)
def spacer(h=6):
return Spacer(1, h)
def hr(color=SKY_BLUE, thickness=1):
return HRFlowable(width="100%", thickness=thickness, color=color, spaceAfter=4, spaceBefore=4)
def part_banner(text, color=ROYAL_BLUE):
return ColourBanner(text, color, PART_STYLE, height=32, radius=6)
def h2_banner(text, color=SKY_BLUE):
return ColourBanner(text, color, H2_STYLE, height=24, radius=4)
def h3(text):
return Paragraph(text, H3_STYLE)
def h4(text):
return Paragraph(text, H4_STYLE)
def body(text):
return Paragraph(text, BODY_STYLE)
def bold(text):
return Paragraph(text, BODY_BOLD)
def bullet(text, symbol="•"):
return Paragraph(f"{symbol} {text}", BULLET_STYLE)
def pearl(text):
return Paragraph(f"⭐ {text}", PEARL_STYLE)
def note(text):
return Paragraph(f"📌 {text}", NOTE_STYLE)
def ref(text):
return Paragraph(text, REF_STYLE)
# ── Table helpers ─────────────────────────────────────────────────────────────
def make_table(data, col_widths=None, header_bg=ROYAL_BLUE, alt_bg=LIGHT_BLUE,
header_text_color=WHITE):
"""Build a formatted table with coloured header and alternating rows."""
t = Table(data, colWidths=col_widths, repeatRows=1)
n_rows = len(data)
n_cols = len(data[0])
style_cmds = [
# Header
("BACKGROUND", (0, 0), (-1, 0), header_bg),
("TEXTCOLOR", (0, 0), (-1, 0), header_text_color),
("FONTNAME", (0, 0), (-1, 0), "Helvetica-Bold"),
("FONTSIZE", (0, 0), (-1, 0), 9),
("ALIGN", (0, 0), (-1, 0), "CENTER"),
("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
("GRID", (0, 0), (-1, -1), 0.4, colors.HexColor("#BDC3C7")),
("FONTNAME", (0, 1), (-1, -1), "Helvetica"),
("FONTSIZE", (0, 1), (-1, -1), 8.5),
("LEFTPADDING", (0, 0), (-1, -1), 5),
("RIGHTPADDING", (0, 0), (-1, -1), 5),
("TOPPADDING", (0, 0), (-1, -1), 4),
("BOTTOMPADDING",(0, 0), (-1, -1), 4),
("ROWBACKGROUNDS", (0, 1), (-1, -1), [WHITE, alt_bg]),
]
t.setStyle(TableStyle(style_cmds))
return t
def cell(text, bold_=False, color=DARK_GREY, size=8.5):
fn = "Helvetica-Bold" if bold_ else "Helvetica"
return Paragraph(f'<font name="{fn}" size="{size}" color="{color.hexval() if hasattr(color,"hexval") else "#2C3E50"}">{text}</font>', BODY_STYLE)
# ── Cover Page ────────────────────────────────────────────────────────────────
def cover_page(story):
# Gradient banner effect with nested rectangles
story.append(spacer(10))
story.append(ColourBanner(
"HIGHER MENTAL FUNCTIONS (HMF)",
DEEP_NAVY, PART_STYLE, height=60, radius=10
))
story.append(spacer(4))
story.append(ColourBanner(
"Complete Bedside Guide for MD General Medicine Final Practical Examinations",
ROYAL_BLUE, PART_STYLE, height=36, radius=6
))
story.append(spacer(8))
story.append(Paragraph(
"Based on: Harrison's 22e · Bradley & Daroff · Adams & Victor · Localization in Clinical Neurology · "
"Neuroanatomy through Clinical Cases · DeJong's · Bickerstaff's · Macleod's · Oxford Handbook",
REF_STYLE
))
story.append(spacer(6))
story.append(hr(GOLD, 2))
story.append(spacer(4))
toc_data = [
[cell("PART", bold_=True, color=WHITE), cell("TOPIC", bold_=True, color=WHITE), cell("COLOUR", bold_=True, color=WHITE)],
["1", "Importance of HMF Examination", "Navy Blue"],
["2", "Neuroanatomical Basis", "Royal Blue"],
["3", "Physiology of HMF", "Teal"],
["4", "Bedside Examination (Step-by-Step)", "Emerald Green"],
["5", "Mechanisms – Why Abnormalities Occur", "Purple"],
["6", "Interpretation – Localization & DDx", "Crimson"],
]
toc = make_table(toc_data, col_widths=[1.5*cm, 12*cm, 3.5*cm],
header_bg=DEEP_NAVY, alt_bg=LIGHT_BLUE)
story.append(toc)
story.append(spacer(10))
story.append(hr(GOLD, 2))
story.append(spacer(4))
story.append(Paragraph(
"\"The mental status examination is underway as soon as the physician begins observing and speaking with the patient.\" "
"— Harrison's Principles of Internal Medicine, 22nd Edition",
PEARL_STYLE
))
story.append(PageBreak())
# ── PART 1 ────────────────────────────────────────────────────────────────────
def part1(story):
story.append(part_banner("PART 1: IMPORTANCE OF HMF EXAMINATION", DEEP_NAVY))
story.append(spacer(6))
story.append(h2_banner("1.1 Clinical Significance", ROYAL_BLUE))
story.append(spacer(4))
story.append(body(
"Higher Mental Functions (HMF) represent the sum of all cognitive abilities that distinguish human beings — "
"consciousness, orientation, memory, language, praxis, gnosis, executive function, and visuospatial abilities. "
"Examining HMF is not a formality; it is the cornerstone of neurological diagnosis."
))
story.append(body(
"The difference between <b>delirium, dementia, aphasia, and psychiatric illness</b> — conditions with completely "
"different etiologies, treatments, and prognoses — can only be established at the bedside through careful HMF testing."
))
story.append(spacer(4))
story.append(h2_banner("1.2 Indications for Detailed HMF Assessment", SKY_BLUE))
story.append(spacer(4))
indications = [
"History raises concern for cognitive or behavioral change",
"Patient is brought in with altered or reduced consciousness",
"Family/caregiver reports personality change, forgetfulness, or behavioral disturbance",
"Patient cannot give a coherent history",
"Observation-based signs during interview: word-finding difficulty, repetition, poor grooming, disinhibition",
"Any focal neurological deficit found — always check accompanying HMF",
"Known systemic illness affecting the brain: hepatic encephalopathy, uraemia, hyponatraemia, thiamine deficiency, HIV, SLE",
"Elderly patient with falls, incontinence, or gait change (NPH triad)",
"Post-stroke, post-TBI, post-encephalitis assessment",
"Suspected dementia, delirium, or frontal lobe syndrome",
]
for i in indications:
story.append(bullet(i))
story.append(spacer(4))
story.append(h2_banner("1.3 When HMF is Absolutely Essential", TEAL))
story.append(spacer(4))
data = [
[cell("Clinical Scenario", bold_=True, color=WHITE), cell("Why It Cannot Be Skipped", bold_=True, color=WHITE)],
["Stroke workup", "Aphasia localizes the lesion; neglect indicates non-dominant hemisphere"],
["Head injury", "GCS alone is insufficient; HMF documents trajectory"],
["Encephalitis (HSV, autoimmune)", "Memory loss and behavioral change are dominant features"],
["Delirium vs dementia", "The clinical distinction is made entirely on HMF"],
["Frontal lobe lesion", "Motor exam may be normal; only HMF reveals the lesion"],
["Pre-operative assessment", "Baseline cognitive function needed for post-op comparison"],
]
story.append(make_table(data, col_widths=[6*cm, 11*cm], header_bg=TEAL, alt_bg=LIGHT_TEAL))
story.append(spacer(6))
story.append(h2_banner("1.4 Common Neurological Diseases Affecting HMF", EMERALD))
story.append(spacer(4))
data2 = [
[cell("Disease", bold_=True, color=WHITE), cell("Primary HMF Domains Affected", bold_=True, color=WHITE)],
["Alzheimer's Disease", "Episodic memory first, then language (anomia), then praxis, visuospatial"],
["Vascular Dementia", "Executive function, psychomotor slowing, patchy deficits"],
["Frontotemporal Dementia", "Executive function, personality, language (naming, speech)"],
["Lewy Body Dementia", "Visuospatial, executive, fluctuating attention, hallucinations"],
["Acute Stroke (MCA dominant)", "Aphasia (Broca or Wernicke), memory"],
["Acute Stroke (MCA non-dominant)", "Neglect, anosognosia, visuospatial"],
["Herpes Encephalitis", "Anterograde amnesia, behavioral change, temporal lobe"],
["Wernicke's Encephalopathy", "Confusion, ophthalmoplegia, ataxia → Korsakoff's amnesia"],
["Normal Pressure Hydrocephalus", "Dementia + gait apraxia + urinary incontinence"],
["HIV Encephalopathy", "Executive function, psychomotor slowing"],
["Delirium (any cause)", "Attention, working memory, fluctuating consciousness — global"],
]
story.append(make_table(data2, col_widths=[6.5*cm, 10.5*cm], header_bg=EMERALD, alt_bg=LIGHT_GREEN))
story.append(spacer(6))
story.append(h2_banner("1.5 What Examiners Expect in MD Practicals", CRIMSON))
story.append(spacer(4))
story.append(body(
"Examiners test two things simultaneously: your <b>technique</b> (correct commands, scoring) "
"and your <b>reasoning</b> (what does an abnormal finding localize to?). They will:"
))
for pt in [
"Ask you to demonstrate one component (e.g., 'test memory for me')",
"Follow up: 'What does the finding mean? Where is the lesion?'",
"Ask: 'What conditions can cause this?'",
"Ask: 'How does Broca's aphasia differ from Wernicke's aphasia?'",
]:
story.append(bullet(pt, "➤"))
story.append(pearl(
"You must be fluent in all six parts: anatomy, physiology, technique, scoring, interpretation, and differential diagnosis."
))
story.append(PageBreak())
# ── PART 2 ────────────────────────────────────────────────────────────────────
def part2(story):
story.append(part_banner("PART 2: NEUROANATOMICAL BASIS", ROYAL_BLUE))
story.append(spacer(6))
story.append(h2_banner("2.1 Cerebral Cortex Overview", ROYAL_BLUE))
story.append(spacer(4))
story.append(body(
"The cerebral cortex contains 6 layers of neurons (neocortex) organized into functional areas described by Brodmann's numbered map."
))
data = [
[cell("Category", bold_=True, color=WHITE), cell("Areas", bold_=True, color=WHITE), cell("Function", bold_=True, color=WHITE)],
["Primary cortices", "1,2,3 / 4 / 17 / 41", "Direct sensory input / motor output"],
["Unimodal association", "5,7 / 18,19 / 22", "Process one sensory modality each"],
["Heteromodal association", "PFC / IPL / ant. temporal", "Integrate across modalities — substrate of HMF"],
]
story.append(make_table(data, col_widths=[5*cm, 4.5*cm, 7.5*cm], header_bg=ROYAL_BLUE, alt_bg=LIGHT_BLUE))
story.append(spacer(6))
story.append(h2_banner("2.2 Frontal Lobe", SKY_BLUE))
story.append(spacer(4))
data = [
[cell("Subregion", bold_=True, color=WHITE), cell("Brodmann Areas", bold_=True, color=WHITE), cell("Function", bold_=True, color=WHITE)],
["Primary motor cortex", "Area 4", "Voluntary movement (contralateral)"],
["Premotor cortex", "Area 6", "Motor planning, preparation"],
["Supplementary motor area", "Area 6 (medial)", "Bilateral motor coordination, initiation"],
["Frontal eye fields", "Area 8", "Voluntary conjugate eye movement"],
["Broca's area (dominant)", "Areas 44, 45", "Speech production, language output"],
["DLPFC", "Areas 9, 46", "Working memory, planning, flexibility, abstract thinking"],
["Orbitofrontal cortex", "Areas 10, 11, 47", "Impulse control, reward, emotional regulation"],
["Anterior cingulate cortex", "Areas 24, 32", "Motivation, error detection, emotional processing"],
]
story.append(make_table(data, col_widths=[5.5*cm, 3.5*cm, 8*cm], header_bg=SKY_BLUE, alt_bg=LIGHT_BLUE))
story.append(spacer(4))
story.append(note(
"Frontal lobe lesions may produce ZERO motor signs. A patient with a large prefrontal tumour "
"can have normal power, tone, reflexes — yet be profoundly disinhibited, perseverative, and have "
"lost all executive function. HMF examination is the ONLY way to detect this."
))
story.append(spacer(6))
story.append(h2_banner("2.3 Parietal Lobe", TEAL))
story.append(spacer(4))
data = [
[cell("Subregion", bold_=True, color=WHITE), cell("Areas", bold_=True, color=WHITE), cell("Function", bold_=True, color=WHITE)],
["Primary somatosensory cortex", "1, 2, 3", "Tactile, pain, temp, proprioception (contralateral)"],
["Superior parietal lobule", "5, 7", "Somatosensory association, spatial orientation"],
["Supramarginal gyrus (dominant)", "40", "Phonological processing, ideomotor praxis"],
["Angular gyrus (dominant)", "39", "Reading, writing, calculation — Gerstmann syndrome"],
]
story.append(make_table(data, col_widths=[5.5*cm, 2.5*cm, 9*cm], header_bg=TEAL, alt_bg=LIGHT_TEAL))
story.append(spacer(6))
story.append(h2_banner("2.4 Temporal Lobe", PURPLE))
story.append(spacer(4))
data = [
[cell("Subregion", bold_=True, color=WHITE), cell("Areas", bold_=True, color=WHITE), cell("Function", bold_=True, color=WHITE)],
["Primary auditory cortex", "41, 42", "Hearing"],
["Wernicke's area (dominant)", "22 + 37,39,40", "Language comprehension"],
["Inferior temporal gyrus", "20", "Object recognition, visual memory"],
["Fusiform gyrus", "37", "Face recognition — prosopagnosia if damaged"],
["Hippocampus (mesial)", "—", "Explicit memory encoding (declarative)"],
["Amygdala (mesial)", "—", "Emotional memory, fear conditioning, social behavior"],
["Parahippocampal gyrus", "28, 35", "Spatial memory, scene recognition"],
]
story.append(make_table(data, col_widths=[5.5*cm, 2.5*cm, 9*cm], header_bg=PURPLE, alt_bg=LIGHT_PURPLE))
story.append(spacer(6))
story.append(h2_banner("2.5 Dominant vs Non-Dominant Hemisphere", CRIMSON))
story.append(spacer(4))
story.append(body(
"<b>Left hemisphere is dominant for language</b> in >95% of right-handed individuals and 60–70% of left-handers "
"(Neuroanatomy through Clinical Cases 3e). This is one of the most tested topics in MD practicals."
))
story.append(spacer(4))
data = [
[cell("Function", bold_=True, color=WHITE), cell("Dominant (usually Left)", bold_=True, color=WHITE), cell("Non-Dominant (usually Right)", bold_=True, color=WHITE)],
["Language", "Broca, Wernicke, reading, writing", "Prosody (emotional tone)"],
["Praxis", "Ideomotor apraxia if parietal", "Constructional, dressing apraxia"],
["Calculation", "Angular gyrus (Gerstmann)", "—"],
["Memory", "Verbal memory", "Non-verbal (visuospatial) memory"],
["Attention", "—", "Global attention, hemispatial vigilance"],
["Spatial awareness", "—", "Right hemisphere dominates global spatial map"],
["Anosognosia", "—", "Right lesion → denial of left hemiplegia"],
]
story.append(make_table(data, col_widths=[5*cm, 6*cm, 6*cm], header_bg=CRIMSON, alt_bg=LIGHT_PINK))
story.append(spacer(4))
story.append(pearl(
"VIVA KEY: Why does anosognosia occur with RIGHT hemisphere lesions? Because the right hemisphere maintains "
"global attention and spatial awareness of the ENTIRE body and extrapersonal space. Left hemisphere lesions "
"produce aphasia which makes deficits immediately obvious; right hemisphere lesions produce neglect which is subtle."
))
story.append(spacer(6))
story.append(h2_banner("2.6 Limbic System, Thalamus & ARAS", ORANGE))
story.append(spacer(4))
data = [
[cell("Structure", bold_=True, color=WHITE), cell("Role in HMF", bold_=True, color=WHITE)],
["Hippocampus", "Encodes new declarative (explicit) memories; anterograde amnesia if damaged bilaterally"],
["Amygdala", "Emotional salience, fear memory, social cognition"],
["Fornix → Mamillary bodies", "Papez circuit relay; damaged in Wernicke-Korsakoff"],
["Dorsomedial thalamic nucleus", "Projects to PFC; bilateral damage → profound anterograde amnesia"],
["Intralaminar thalamic nuclei", "Receive ARAS input → broadcast to cortex → arousal/consciousness"],
["Anterior cingulate", "Motivation, attention, error detection"],
["ARAS (brainstem → thalamus → cortex)", "Neurophysiological substrate of arousal — norepinephrine, serotonin, ACh, histamine"],
]
story.append(make_table(data, col_widths=[6*cm, 11*cm], header_bg=ORANGE, alt_bg=LIGHT_ORANGE))
story.append(PageBreak())
# ── PART 3 ────────────────────────────────────────────────────────────────────
def part3(story):
story.append(part_banner("PART 3: PHYSIOLOGY OF HMF", TEAL))
story.append(spacer(6))
physiology_sections = [
("3.1 Consciousness", TEAL,
[
("Components", "Arousal (wakefulness) maintained by ARAS → thalamus → cortex; "
"Awareness (content) maintained by cerebral cortex itself."),
("Substrate", "ARAS projects from upper brainstem (locus coeruleus, raphe, pedunculopontine nucleus) "
"via thalamic intralaminar nuclei to diffusely activate the cortex."),
("For normal consciousness", "BOTH intact ARAS AND intact cortex are required. "
"Explains why GCS tests eye opening (ARAS), verbal response (cortex), and motor response (corticospinal tract)."),
]),
("3.2 Attention", SKY_BLUE,
[
("Mediated by", "Right prefrontal + right parietal cortex (global sustained attention); "
"anterior cingulate (error detection); noradrenergic ARAS projections from locus coeruleus."),
("Gating function", "Attention is the GATE for all other HMF — you cannot properly test memory, "
"language, or executive function in an inattentive patient. Always test attention FIRST."),
("Right hemisphere dominance", "Right hemisphere directs attention to BOTH sides of space. "
"Left hemisphere only directs to right hemispace. Therefore right parietal damage → left neglect."),
]),
("3.3 Memory Organisation", PURPLE,
[
("Declarative (Explicit)", "Conscious recall: Episodic (personal events — hippocampus + frontal) and "
"Semantic (general facts — temporal neocortex)."),
("Non-declarative (Implicit)", "Procedural skills (striatum, cerebellum); priming (neocortex); "
"emotional conditioning (amygdala)."),
("Papez Circuit", "Hippocampus → fornix → mamillary bodies → mamillo-thalamic tract → "
"anterior thalamus → cingulate gyrus → entorhinal cortex → hippocampus."),
("Time frames at bedside", "Immediate (working memory, PFC) → Recent 5–15 min (hippocampal encoding) → "
"Remote (neocortical long-term stores)."),
]),
("3.4 Language", ROYAL_BLUE,
[
("Core circuit", "Auditory input → primary auditory cortex (41/42) → Wernicke's area (22) for comprehension "
"→ arcuate fasciculus → Broca's area (44/45) for production → primary motor cortex (face area) for articulation."),
("Classification axes", "FLUENCY (anterior lesion = non-fluent; posterior lesion = fluent) + "
"COMPREHENSION (intact or impaired) + REPETITION (intact or impaired)."),
("Key rule", "In perisylvian aphasias (Broca, Wernicke, Conduction), repetition is ALWAYS impaired. "
"Outside the perisylvian zone (watershed areas), repetition is SPARED."),
]),
("3.5 Executive Functions", DARK_PURPLE,
[
("Mediated by", "Dorsolateral prefrontal cortex (DLPFC, areas 9/46) and fronto-striato-thalamo-cortical loops."),
("Components", "Working memory; planning & sequencing; cognitive flexibility (set-shifting); "
"inhibitory control; abstract reasoning."),
("Bedside tests", "Serial 7s, verbal fluency, Luria 3-step, go/no-go, similarities, proverb interpretation, "
"frontal release signs."),
]),
("3.6 Praxis", EMERALD,
[
("Definition", "Ability to perform learned, purposeful, skilled movements NOT explained by primary motor, "
"sensory, or coordination deficits."),
("Pathway", "Conceptual system (temporal-parietal junction, area 40) → "
"transcallosal → left SMA and premotor cortex → execution."),
("Ideomotor vs Ideational", "Ideomotor: movement concept intact, translation to motor program broken "
"(parietal or callosal). Ideational: concept itself disrupted (diffuse dominant temporal-parietal)."),
]),
("3.7 Gnosis & Agnosia", CRIMSON,
[
("Definition (Adams & Victor)", "Conceptual inability to recognize objects, persons, or sensory stimuli "
"in the ABSENCE of a primary sensory deficit."),
("Types", "Visual agnosia (occipital-temporal); prosopagnosia (bilateral fusiform); "
"astereognosis (contralateral parietal); auditory agnosia (bilateral temporal); "
"anosognosia (right parietal)."),
("Body schema", "Right hemisphere maintains body schema — spatial representation of body and "
"extrapersonal space. Damage → anosognosia, hemispatial neglect, amorphosynthesis."),
]),
]
for title, color, points in physiology_sections:
story.append(h2_banner(title, color))
story.append(spacer(4))
data = [[cell("Aspect", bold_=True, color=WHITE), cell("Detail", bold_=True, color=WHITE)]]
for aspect, detail in points:
data.append([aspect, detail])
bg = {TEAL: LIGHT_TEAL, SKY_BLUE: LIGHT_BLUE, PURPLE: LIGHT_PURPLE,
ROYAL_BLUE: LIGHT_BLUE, DARK_PURPLE: LIGHT_PURPLE, EMERALD: LIGHT_GREEN,
CRIMSON: LIGHT_PINK}.get(color, LIGHT_GREY)
story.append(make_table(data, col_widths=[4.5*cm, 12.5*cm], header_bg=color, alt_bg=bg))
story.append(spacer(6))
story.append(PageBreak())
# ── PART 4 ────────────────────────────────────────────────────────────────────
def part4(story):
story.append(part_banner("PART 4: BEDSIDE EXAMINATION — STEP BY STEP", EMERALD))
story.append(spacer(4))
story.append(note(
"PREPARATION: Introduce yourself. Ensure adequate lighting. Minimise distractions. "
"Sit at patient's eye level. Note mother tongue, education level, premorbid baseline. "
"Have ready: pen, paper, common objects (coin, pen, key, comb), watch."
))
story.append(spacer(6))
# ── 4.1 Level of Consciousness ──
story.append(h2_banner("4.1 Level of Consciousness", EMERALD))
story.append(spacer(4))
story.append(body("<b>Observe before you speak.</b> Are they awake? Drowsy? Maintaining gaze?"))
steps = [
("Step 1", "If patient appears awake, note alertness and appropriateness of responses."),
("Step 2", "If not fully alert: Call name clearly — 'Mr. Sharma! Can you open your eyes?' "
"Note if eyes open spontaneously, to voice, or only to pain."),
("Step 3", "If no response to voice: Apply trapezius squeeze or supraorbital ridge pressure. "
"Distinguish directed responses (cortical) from reflex/spinal responses (triple flexion)."),
]
for step, desc in steps:
story.append(bullet(f"<b>{step}:</b> {desc}", "▶"))
story.append(spacer(4))
story.append(bold("Glasgow Coma Scale (GCS)"))
gcs_data = [
[cell("Domain", bold_=True, color=WHITE), cell("Score", bold_=True, color=WHITE), cell("Response", bold_=True, color=WHITE)],
["Eye Opening", "4 / 3 / 2 / 1", "Spontaneous / To voice / To pain / None"],
["Verbal", "5 / 4 / 3 / 2 / 1", "Oriented / Confused / Inappropriate words / Sounds / None"],
["Motor", "6 / 5 / 4 / 3 / 2 / 1", "Obeys / Localizes / Withdrawal / Flex (decorticate) / Ext (decerebrate) / None"],
]
story.append(make_table(gcs_data, col_widths=[4*cm, 3.5*cm, 9.5*cm], header_bg=EMERALD, alt_bg=LIGHT_GREEN))
story.append(spacer(4))
desc_data = [
[cell("Term", bold_=True, color=WHITE), cell("Definition", bold_=True, color=WHITE)],
["Alert", "Fully awake, responds appropriately"],
["Drowsy / Lethargic", "Sleepy but arousable to voice; returns to sleep quickly"],
["Obtunded", "Arousable to vigorous stimulation; slow, confused responses"],
["Stupor", "Arousable only to pain; minimal purposeful responses"],
["Coma", "Unarousable; no purposeful response to any stimulus"],
]
story.append(make_table(desc_data, col_widths=[5*cm, 12*cm], header_bg=DARK_GREY, alt_bg=LIGHT_GREY))
story.append(spacer(4))
story.append(pearl("VIVA: Never just say 'the patient is confused.' Always report GCS (E_V_M_), "
"what stimulus was required, and what response was obtained."))
story.append(spacer(6))
# ── 4.2 Orientation ──
story.append(h2_banner("4.2 Orientation (Time → Place → Person)", TEAL))
story.append(spacer(4))
story.append(body("Test in this order: Time fails FIRST in disease, so it is the most sensitive indicator."))
orient_data = [
[cell("Domain", bold_=True, color=WHITE), cell("Questions to Ask", bold_=True, color=WHITE)],
["Person", "'What is your full name?' / 'How old are you?'"],
["Place", "'Where are you right now?' / 'Which hospital/city/state?'"],
["Time", "'What is today's date?' / 'Day of the week?' / 'Season?' / 'Approximate time of day?'"],
]
story.append(make_table(orient_data, col_widths=[3.5*cm, 13.5*cm], header_bg=TEAL, alt_bg=LIGHT_TEAL))
story.append(spacer(4))
story.append(note(
"Bradley's: Patients off 3 days on date, 2 days on day of week, or 4 hours on time may be "
"significantly disoriented to time."
))
story.append(spacer(6))
# ── 4.3 Attention ──
story.append(h2_banner("4.3 Attention and Concentration", SKY_BLUE))
story.append(spacer(4))
story.append(pearl("Always test attention BEFORE memory — an inattentive patient will fail memory tests falsely."))
story.append(spacer(4))
attn_data = [
[cell("Test", bold_=True, color=WHITE), cell("Method", bold_=True, color=WHITE), cell("Normal", bold_=True, color=WHITE)],
["Digit Span Forward",
"'I will say numbers. Repeat in the same order.' Start 3 digits → 7+. 1 digit/sec.",
"7 ± 2 digits"],
["Digit Span Backward",
"'Now say them in REVERSE order.' (e.g., 2-4 → say 4-2)",
"5 ± 2 digits"],
["Serial 7s",
"'Start at 100, subtract 7 each time.' (93, 86, 79, 72, 65) — 5 subtractions.",
"≤1 error"],
["WORLD backwards",
"'Spell WORLD backwards.' (D-L-R-O-W)",
"Correct"],
["A-Vigilance",
"Read letters 1/sec — patient taps every time they hear 'A'.",
"No omissions or commission errors"],
]
story.append(make_table(attn_data, col_widths=[4*cm, 9.5*cm, 3.5*cm], header_bg=SKY_BLUE, alt_bg=LIGHT_BLUE))
story.append(spacer(6))
# ── 4.4 Memory ──
story.append(h2_banner("4.4 Memory Examination", PURPLE))
story.append(spacer(4))
mem_data = [
[cell("Time Frame", bold_=True, color=WHITE), cell("Test", bold_=True, color=WHITE), cell("Normal", bold_=True, color=WHITE), cell("Lesion if Impaired", bold_=True, color=WHITE)],
["Immediate\n(Working Memory)",
"Say 3 words (Apple–Table–Penny). Ask immediate repetition.",
"Repeats all 3",
"Prefrontal cortex (PFC)"],
["Recent Memory\n(5–15 min)",
"Recall same 3 words at 5 min (continue other tests during interval). If fails free recall → try semantic cue → then recognition.",
"3/3 at 5 min",
"Hippocampus (mesial temporal)"],
["Remote Memory\n(Long-term)",
"DOB, personal history, historical events (PM of India, COVID), children's names. Verify with informant.",
"Coherent chronological history",
"Neocortical networks; if impaired early → semantic dementia"],
]
story.append(make_table(mem_data, col_widths=[3*cm, 7*cm, 3*cm, 4*cm], header_bg=PURPLE, alt_bg=LIGHT_PURPLE))
story.append(spacer(4))
story.append(note(
"If patient fails free recall → provide semantic cue ('One was a fruit') → then recognition ('Was it apple, mango, or banana?'). "
"Encoding failure = fails all 3 options. Retrieval failure = benefits from cue or recognition."
))
story.append(spacer(6))
# ── 4.5 Language ──
story.append(h2_banner("4.5 Language Examination", ROYAL_BLUE))
story.append(spacer(4))
lang_steps = [
("Spontaneous Speech", "Observe during history. Is speech <b>fluent</b> (≥6 words/phrase, effortless) or "
"<b>non-fluent</b> (effortful, telegraphic, agrammatic)? Are there paraphasias (phonemic, semantic, neologisms)?"),
("Naming", "Show pen → 'What is this?' Then: 'And this part?' (cap/clip/nib). "
"Anomia occurs in ALL aphasias. Benefits from phonemic cue = Broca; No benefit = Wernicke/semantic."),
("Comprehension", "'Is your name [X]?' (yes/no) → 'Point to ceiling... floor... window' (single-step) → "
"'Take paper in right hand, fold in half, put on floor' (3-step command)."),
("Repetition", "'Please repeat: No ifs, ands, or buts.' "
"IMPAIRED in perisylvian aphasias; INTACT in transcortical aphasias."),
("Reading", "Show written card: CLOSE YOUR EYES. 'Read this and do what it says.'"),
("Writing", "Give pen and paper: 'Write a complete sentence about anything.'"),
]
for step, detail in lang_steps:
story.append(bullet(f"<b>{step}:</b> {detail}", "➤"))
story.append(spacer(6))
story.append(bold("Aphasia Classification — The Most Important Table in HMF"))
aphasia_data = [
[cell("Type", bold_=True, color=WHITE), cell("Fluency", bold_=True, color=WHITE),
cell("Comprehension", bold_=True, color=WHITE), cell("Repetition", bold_=True, color=WHITE),
cell("Lesion", bold_=True, color=WHITE)],
["Broca", "NON-fluent", "Intact*", "IMPAIRED", "Dominant inf. frontal gyrus (44/45)"],
["Wernicke", "FLUENT", "IMPAIRED", "IMPAIRED", "Dominant post. sup. temporal (22)"],
["Conduction", "Fluent", "Intact", "SEVERELY impaired", "Arcuate fasciculus / SM gyrus (40)"],
["Global", "NON-fluent", "IMPAIRED", "IMPAIRED", "Large dominant MCA territory"],
["Transcortical Motor", "NON-fluent", "Intact", "INTACT ✓", "SMA, ant. cingulate (above Broca)"],
["Transcortical Sensory", "Fluent", "IMPAIRED", "INTACT ✓", "Posterior watershed, TPJ"],
["Anomic", "Fluent", "Intact", "Intact", "Angular gyrus (39) or any cortical"],
]
story.append(make_table(aphasia_data, col_widths=[3.5*cm, 2.5*cm, 3*cm, 3*cm, 5*cm], header_bg=ROYAL_BLUE, alt_bg=LIGHT_BLUE))
story.append(spacer(4))
story.append(pearl(
"MEMORY HOOK: Perisylvian zone (Broca → arcuate fasciculus → Wernicke) → repetition ALWAYS impaired. "
"Outside perisylvian zone (watershed areas) → repetition SPARED. This is the single most reliable rule."
))
story.append(spacer(4))
story.append(bold("Speech vs Language — Critical Distinction"))
sv_data = [
[cell("Feature", bold_=True, color=WHITE), cell("Speech Disorder (Dysarthria)", bold_=True, color=WHITE), cell("Language Disorder (Aphasia)", bold_=True, color=WHITE)],
["What is affected?", "Motor execution of articulation", "The language system itself"],
["Content", "Normal content, garbled execution", "Abnormal content (paraphasia, agrammatism)"],
["Writing", "NORMAL", "ALSO abnormal"],
["Comprehension", "Normal", "May be impaired"],
["Lesion", "LMN/UMN/cerebellar/extrapyramidal", "Dominant hemisphere cortex"],
]
story.append(make_table(sv_data, col_widths=[4*cm, 6*cm, 7*cm], header_bg=DARK_GREY, alt_bg=LIGHT_GREY))
story.append(spacer(6))
# ── 4.6 Calculation, Abstract Thinking, Judgment/Insight ──
story.append(h2_banner("4.6 Calculation · Abstract Thinking · Judgment · Insight", ORANGE))
story.append(spacer(4))
cog_data = [
[cell("Component", bold_=True, color=WHITE), cell("Bedside Test", bold_=True, color=WHITE), cell("Abnormal = Lesion", bold_=True, color=WHITE)],
["Calculation",
"'7+8=?' / '15-6=?' / '9×7=?' / Serial 7s.",
"Acalculia in isolation = angular gyrus (39) — Gerstmann"],
["Abstract Thinking (Similarities)",
"'How are apple and orange alike?' (Abstract: both are fruits; Concrete: both round)",
"Concrete responses = frontal lobe dysfunction"],
["Proverb Interpretation",
"'What does a rolling stone gathers no moss mean?'",
"Literal/concrete interpretation = frontal lobe"],
["Judgment",
"'What would you do if you found a sealed stamped envelope on the street?' (Normal: post it)",
"Poor judgment = frontal lobe, dementia, psychiatric"],
["Insight",
"'What do you think is wrong with you?' / 'Do you think you have a memory problem?'",
"No insight (anosognosia) = right parietal (organic) or psychiatric"],
]
story.append(make_table(cog_data, col_widths=[4*cm, 7*cm, 6*cm], header_bg=ORANGE, alt_bg=LIGHT_ORANGE))
story.append(spacer(6))
# ── 4.7 Visuospatial ──
story.append(h2_banner("4.7 Visuospatial Ability", TEAL))
story.append(spacer(4))
vs_data = [
[cell("Test", bold_=True, color=WHITE), cell("Method", bold_=True, color=WHITE), cell("What is Tested", bold_=True, color=WHITE)],
["Clock Drawing Test",
"'Draw a clock showing 10 past 11.' Assess: circle, number placement, hand placement.",
"Visuoconstructional + planning + numeric knowledge"],
["Pentagon Copying (MMSE)",
"Show intersecting pentagons. 'Copy this drawing exactly.'",
"Visuoconstructional ability — parietal"],
["Line Bisection",
"Draw 20 cm line. 'Mark the centre.' Normal = within 1 cm.",
"Hemispatial neglect (right parietal → bisects right of center)"],
["Figure Drawing from Memory",
"'Draw a house / flower / bicycle from memory.'",
"Visuospatial + constructional"],
]
story.append(make_table(vs_data, col_widths=[3.5*cm, 8*cm, 5.5*cm], header_bg=TEAL, alt_bg=LIGHT_TEAL))
story.append(spacer(6))
# ── 4.8 Praxis ──
story.append(h2_banner("4.8 Praxis Examination", EMERALD))
story.append(spacer(4))
praxis_data = [
[cell("Type", bold_=True, color=WHITE), cell("Test Commands", bold_=True, color=WHITE), cell("Grading", bold_=True, color=WHITE)],
["Ideomotor Apraxia",
"1. On command: 'Show me how you would wave goodbye / comb hair / use a toothbrush / hammer a nail.'\n"
"2. Imitation: 'Do exactly what I do.' (demonstrate)\n"
"3. With actual object: hand the object and say 'Please use this.'",
"Normal: correct on verbal command\nMild: needs imitation\nModerate: needs object\nSevere: fails with object"],
["Constructional Apraxia",
"Copy geometric figures, clock drawing, intersecting pentagons.",
"Errors = parietal (bilateral, worse non-dominant)"],
["Oral Apraxia",
"'Stick out tongue / blow out candle / cough / whistle.'",
"Impaired in Broca's aphasia, opercular syndrome"],
["Gait Apraxia",
"Ask patient to walk. Observe initiation, stride length, foot clearance.",
"Magnetic gait + normal limb exam = frontal gait apraxia (NPH)"],
]
story.append(make_table(praxis_data, col_widths=[3.5*cm, 9*cm, 4.5*cm], header_bg=EMERALD, alt_bg=LIGHT_GREEN))
story.append(spacer(6))
# ── 4.9 Agnosia & Neglect ──
story.append(h2_banner("4.9 Agnosia and Hemispatial Neglect", CRIMSON))
story.append(spacer(4))
agn_data = [
[cell("Test", bold_=True, color=WHITE), cell("Method", bold_=True, color=WHITE), cell("Significance", bold_=True, color=WHITE)],
["Visual Object Agnosia",
"'Without touching it, what is this?' If fails: 'Show me what you'd do with it.'",
"Visual agnosia = occipital-temporal; not a naming problem"],
["Prosopagnosia",
"Show photo of famous person. 'Do you recognise this person?'",
"Bilateral fusiform / inf. temporal lesion"],
["Astereognosis",
"Eyes closed, common object in hand. 'What is this?' Fails touch, passes vision.",
"Contralateral parietal cortex"],
["Anosognosia",
"'Can you raise your left arm?' / 'Is there anything wrong with your left arm?'",
"Right parietal lesion"],
["Line Bisection",
"20 cm line — 'Mark the centre.' Bisects to right of centre.",
"Left hemispatial neglect — right parietal"],
["Letter Cancellation",
"Cancel all letter A / stars on a page. Misses left-sided targets.",
"Left hemispatial neglect — right parietal"],
["Extinction",
"Single stimulation each side — normal. Bilateral simultaneous — reports only right side.",
"Right parietal — subtle neglect"],
]
story.append(make_table(agn_data, col_widths=[3.5*cm, 8*cm, 5.5*cm], header_bg=CRIMSON, alt_bg=LIGHT_PINK))
story.append(spacer(6))
# ── 4.10 Frontal Tests ──
story.append(h2_banner("4.10 Frontal Lobe Tests", DARK_PURPLE))
story.append(spacer(4))
frontal_data = [
[cell("Test", bold_=True, color=WHITE), cell("Method", bold_=True, color=WHITE), cell("Abnormal Response", bold_=True, color=WHITE)],
["Luria 3-Step Sequence",
"Demonstrate: Palm → Side → Fist (3×). 'Now you do it.'",
"Perseverates on one position; loses sequence; mirrors examiner"],
["Verbal Fluency — Phonemic",
"'Name words beginning with F. 1 minute. No proper nouns.'",
"<12 words/min = frontal initiation deficit"],
["Verbal Fluency — Semantic",
"'Name animals. 1 minute.'",
"<12 animals/min = temporal semantic memory or frontal"],
["Grasp Reflex",
"Stroke palm from thenar toward fingers.",
"Involuntary gripping = frontal disinhibition"],
["Snout Reflex",
"Tap lips with finger.",
"Lip puckering/pouting = frontal release sign"],
["Glabellar Tap",
"Repeatedly tap glabella.",
"Fails to habituate after 2–3 taps = frontal / Parkinson's"],
["Palmomental Reflex",
"Scratch thenar eminence briskly.",
"Ipsilateral chin dimpling (non-specific alone)"],
]
story.append(make_table(frontal_data, col_widths=[3.5*cm, 7.5*cm, 6*cm], header_bg=DARK_PURPLE, alt_bg=LIGHT_PURPLE))
story.append(spacer(6))
# ── 4.11 MMSE ──
story.append(h2_banner("4.11 Mini-Mental State Examination (MMSE) — Full 30-Point Scale", ROYAL_BLUE))
story.append(spacer(4))
mmse_data = [
[cell("Component", bold_=True, color=WHITE), cell("Task", bold_=True, color=WHITE), cell("Points", bold_=True, color=WHITE)],
["Orientation — Time", "Year / Season / Date / Day / Month", "5"],
["Orientation — Place", "Country / State / City / Hospital / Floor", "5"],
["Registration", "Name 3 objects, patient repeats immediately", "3"],
["Attention / Calculation", "Serial 7s (5 subtractions) OR spell WORLD backwards", "5"],
["Recall", "Recall the 3 registered objects at ~5 minutes", "3"],
["Naming", "Name a pencil and a watch", "2"],
["Repetition", "'No ifs, ands, or buts'", "1"],
["3-Step Command", "'Take paper in right hand, fold in half, put on floor'", "3"],
["Reading", "Read and obey 'CLOSE YOUR EYES'", "1"],
["Writing", "Write a complete spontaneous sentence", "1"],
["Construction", "Copy two intersecting pentagons", "1"],
["TOTAL", "", "30"],
]
story.append(make_table(mmse_data, col_widths=[5*cm, 10*cm, 2*cm], header_bg=ROYAL_BLUE, alt_bg=LIGHT_BLUE))
story.append(spacer(4))
score_data = [
[cell("Score", bold_=True, color=WHITE), cell("Interpretation", bold_=True, color=WHITE)],
["27–30", "Normal"],
["24–26", "Borderline / Mild impairment"],
["20–23", "Mild dementia"],
["10–19", "Moderate dementia"],
["<10", "Severe dementia"],
]
story.append(make_table(score_data, col_widths=[3*cm, 14*cm], header_bg=DARK_GREY, alt_bg=LIGHT_GREY))
story.append(spacer(4))
story.append(pearl(
"LIMITATIONS: MMSE misses executive dysfunction and early cognitive impairment. "
"A patient with early Alzheimer's or frontal dementia may score 28/30 yet have profound functional impairment. "
"MoCA (≥26/30 normal) is more sensitive for MCI — tests executive function, has clock drawing, better ceiling."
))
story.append(PageBreak())
# ── Presentation Template ──
story.append(h2_banner("4.12 Bedside Presentation Template for MD Examination", GOLD))
story.append(spacer(4))
template_text = (
"\"I examined the higher mental functions of this patient. The patient was [alert/drowsy/obtunded], "
"GCS [E_V_M_]. Orientation was [intact/impaired — specify domains]. Attention was [intact/impaired — "
"digit span forward ___/backward ___, serial 7s: ___ errors]. Immediate memory was [intact/impaired]. "
"Recent memory was [intact/impaired — recalled ___/3 words at 5 minutes with/without cueing]. "
"Remote memory was [intact/impaired].\n\n"
"Language: speech was [fluent/non-fluent] with [present/absent] paraphasias. Comprehension was "
"[intact/impaired] on [single-step/three-step commands]. Repetition was [intact/impaired]. "
"Naming was [intact/impaired]. Reading and writing were [intact/impaired].\n\n"
"Executive functions: serial 7s [___ errors], verbal fluency [F-words: ___], abstraction "
"[concrete/abstract]. Judgment and insight were [intact/impaired].\n\n"
"Visuospatial function: clock drawing [intact/impaired — describe errors]. Figure copying [intact/impaired]. "
"Praxis: [intact/impaired — ideomotor/constructional]. Neglect: [absent/present — describe test results]. "
"Frontal release signs: [absent/present — specify].\n\n"
"In summary, the pattern is consistent with [localization] most likely due to [diagnosis], because [reason].\""
)
story.append(SideBar(template_text, GOLD, LIGHT_YELLOW,
doc.width, NOTE_STYLE))
story.append(PageBreak())
# ── PART 5 ────────────────────────────────────────────────────────────────────
def part5(story):
story.append(part_banner("PART 5: MECHANISMS — WHY ABNORMALITIES OCCUR", PURPLE))
story.append(spacer(6))
mechanisms = [
("Broca's Aphasia", ROYAL_BLUE, [
("Anatomy", "Left inferior frontal gyrus (areas 44/45) + surrounding perisylvian cortex "
"(postcentral + supramarginal gyrus 40 + underlying white matter)."),
("Why non-fluent", "Broca's area is the motor sequencing centre for speech. Damage disrupts the ability "
"to generate fluent, grammatically organized motor speech programs. Output is effortful, telegraphic "
"(content words preserved, function words absent = agrammatism)."),
("Why repetition impaired", "Arcuate fasciculus enters the Broca complex; damage disrupts the "
"phonological motor loop needed for accurate repetition."),
("Why comprehension relatively spared", "Wernicke's area is intact. Single words and simple sentences "
"can still be decoded."),
("Why patient is depressed/frustrated", "Full insight (comprehension intact) but cannot express themselves."),
]),
("Wernicke's Aphasia", TEAL, [
("Anatomy", "Left posterior superior temporal gyrus (area 22) + adjacent areas 37, 39, 40."),
("Why fluent", "Broca's area and connections to primary motor cortex are intact. Speech production circuits unaffected."),
("Why paraphasic", "Without feedback from the intact phonological mapping system (damaged), patient cannot "
"monitor phonological accuracy of output. Substitutions occur unchecked."),
("Why repetition impaired", "Comprehension of heard phrase is necessary for accurate repetition. Without "
"decoding what was said, repetition is impossible."),
("Why patient unaware/agitated", "Comprehension impairment means patient cannot monitor correctness of own "
"speech. Can produce paranoid agitation."),
]),
("Conduction Aphasia", SKY_BLUE, [
("Anatomy", "Arcuate fasciculus (white matter connecting Wernicke's posteriorly to Broca's anteriorly). "
"Supramarginal gyrus (area 40) is the cortical component."),
("Specific disruption", "Disconnection of posterior phonological representation from anterior motor speech system."),
("Why repetition disproportionately impaired", "Repetition requires exact phonological transmission through "
"arcuate fasciculus. Phonemic paraphasias occur on repetition; patient hears errors and struggles to "
"self-correct (conduit d'approche: repeated attempts with progressive approximation)."),
]),
("Hippocampal Amnesia", PURPLE, [
("Mechanism", "New memories cannot be encoded (consolidated into long-term stores). Working memory (PFC) "
"is spared. Remote memory (neocortical networks) relatively spared."),
("Patient lives in an eternal present", "Papez circuit is disrupted. Hippocampus cannot pass "
"information to mamillary bodies → anterior thalamus → cingulate → neocortex."),
]),
("Korsakoff Amnesia + Confabulation", ORANGE, [
("Anatomy", "Bilateral mamillary body damage (+ dorsomedial thalamic nucleus) disrupts Papez circuit relay. "
"Fornix output cannot reach thalamo-cingulate system for consolidation."),
("Why confabulation", "Prefrontal orbitofrontal monitoring systems are also damaged (thiamine-dependent). "
"Without frontal monitoring, false memories are produced without awareness. Patient generates plausible "
"but incorrect accounts without the ability to suppress or evaluate them."),
]),
("Hemispatial Neglect", CRIMSON, [
("Right hemisphere dominance", "Right parietal directs attention to BOTH sides of space. Left parietal "
"only directs to right hemispace. Therefore: left parietal lesion → right parietal compensates → minimal neglect. "
"Right parietal lesion → no compensation → severe sustained left neglect."),
("Anosognosia mechanism (Adams & Victor)", "Right hemisphere maintains body schema — spatial representation "
"of body and extrapersonal space. Damage means the monitoring system itself is offline. Patient does not "
"refuse to acknowledge the problem; the neural machinery for awareness of that body part is destroyed."),
]),
("Frontal Lobe Syndrome", DARK_PURPLE, [
("DLPFC lesion", "Loss of working memory, planning, cognitive flexibility. Cannot hold information in mind "
"while manipulating it. Perseverates — cannot shift set. Concrete thinking — cannot abstract."),
("Orbitofrontal lesion", "Loss of impulse control, reward evaluation, emotional regulation. "
"Disinhibition, inappropriate social behavior, Witzelsucht (pathological jocularity)."),
("Anterior cingulate lesion", "Apathy, abulia, loss of motivation, akinetic mutism in severe cases. "
"No motor deficit — patient CAN move, but has no drive to initiate."),
]),
]
for title, color, points in mechanisms:
story.append(h2_banner(title, color))
story.append(spacer(4))
data = [[cell("Aspect", bold_=True, color=WHITE), cell("Mechanism", bold_=True, color=WHITE)]]
for aspect, detail in points:
data.append([aspect, detail])
bg = {ROYAL_BLUE: LIGHT_BLUE, TEAL: LIGHT_TEAL, SKY_BLUE: LIGHT_BLUE,
PURPLE: LIGHT_PURPLE, ORANGE: LIGHT_ORANGE, CRIMSON: LIGHT_PINK,
DARK_PURPLE: LIGHT_PURPLE}.get(color, LIGHT_GREY)
story.append(make_table(data, col_widths=[4.5*cm, 12.5*cm], header_bg=color, alt_bg=bg))
story.append(spacer(6))
story.append(PageBreak())
# ── PART 6 ────────────────────────────────────────────────────────────────────
def part6(story):
story.append(part_banner("PART 6: INTERPRETATION — LOCALIZATION & DIFFERENTIAL DIAGNOSIS", CRIMSON))
story.append(spacer(6))
story.append(h2_banner("6.1 Aphasia Localization Summary", ROYAL_BLUE))
story.append(spacer(4))
aph_loc = [
[cell("Aphasia", bold_=True, color=WHITE), cell("Lesion Site", bold_=True, color=WHITE),
cell("Associated Signs", bold_=True, color=WHITE), cell("Common Causes", bold_=True, color=WHITE)],
["Broca", "Dominant inferior frontal (44/45) + surrounding cortex",
"Right hemiparesis (face/arm), right lower facial droop",
"MCA superior division stroke, glioma, abscess"],
["Wernicke", "Dominant post. sup. temporal (22)",
"Often NO hemiparesis; right superior visual field defect",
"MCA inferior division stroke, HSV encephalitis, glioma"],
["Conduction", "Arcuate fasciculus / supramarginal gyrus (40)",
"Mild arm/hand weakness possible",
"MCA branch, Rolandic/parietal infarct"],
["Global", "Large dominant MCA territory (frontal+temporal+parietal)",
"Dense right hemiplegia, hemianopia, hemisensory loss",
"Complete MCA occlusion, ICA occlusion"],
["Transcortical Motor", "SMA, anterior cingulate, above Broca's",
"Reduced spontaneous speech, right leg weakness",
"ACA territory stroke, parasagittal meningioma"],
["Transcortical Sensory", "Posterior watershed, angular/TPJ",
"May have right visual field defect",
"ICA stenosis watershed infarct"],
["Anomic", "Angular gyrus (39) or diffuse",
"May be isolated",
"Early AD, any focal lesion, metabolic encephalopathy"],
]
story.append(make_table(aph_loc, col_widths=[3*cm, 5*cm, 4.5*cm, 4.5*cm], header_bg=ROYAL_BLUE, alt_bg=LIGHT_BLUE))
story.append(spacer(4))
story.append(pearl(
"RED FLAG: Wernicke's aphasia without hemiparesis is frequently misdiagnosed as acute psychosis. "
"Any acute fluent aphasia without known etiology requires HSV PCR in CSF."
))
story.append(spacer(6))
story.append(h2_banner("6.2 Memory Disorders — Localization", PURPLE))
story.append(spacer(4))
mem_loc = [
[cell("Pattern", bold_=True, color=WHITE), cell("Localization", bold_=True, color=WHITE), cell("DDx", bold_=True, color=WHITE)],
["Anterograde amnesia — no confabulation",
"Bilateral hippocampi",
"HSV encephalitis, bilateral PCA infarcts, early AD"],
["Anterograde amnesia + confabulation",
"Mamillary bodies + DM thalamus",
"Wernicke-Korsakoff, bilateral thalamic infarcts, ruptured AComA aneurysm"],
["Transient global amnesia",
"Hippocampus (reversible ischemia/venous)",
"TGA: no seizure, no focal deficit, resolves <24h"],
["Semantic memory loss (words, faces, concepts)",
"Anterior temporal neocortex (asymmetric)",
"Semantic variant FTD (semantic dementia)"],
["Working memory impaired, episodic spared",
"Prefrontal cortex, DLPFC",
"Frontal lobe lesion, delirium, ADHD"],
]
story.append(make_table(mem_loc, col_widths=[5.5*cm, 5*cm, 6.5*cm], header_bg=PURPLE, alt_bg=LIGHT_PURPLE))
story.append(spacer(6))
story.append(h2_banner("6.3 Apraxia — Localization", EMERALD))
story.append(spacer(4))
apr_loc = [
[cell("Type", bold_=True, color=WHITE), cell("Localization", bold_=True, color=WHITE), cell("Bedside Finding", bold_=True, color=WHITE)],
["Ideomotor apraxia", "Left inferior parietal (area 40), left SMA, corpus callosum",
"Fails pantomime on command; improves with imitation or object"],
["Ideational apraxia", "Dominant temporal-parietal, diffuse",
"Cannot complete multi-step sequential tasks even with objects"],
["Constructional apraxia", "Parietal (bilateral, worse non-dominant)",
"Fails figure copying, clock drawing"],
["Dressing apraxia", "Right parietal",
"Cannot orient clothing correctly to body in space"],
["Gait apraxia", "Bilateral frontal (SMA, premotor)",
"Magnetic gait; normal motor exam in upper limbs"],
]
story.append(make_table(apr_loc, col_widths=[4*cm, 6*cm, 7*cm], header_bg=EMERALD, alt_bg=LIGHT_GREEN))
story.append(spacer(6))
story.append(h2_banner("6.4 Dementia Syndromes — Pattern Recognition", ORANGE))
story.append(spacer(4))
dem_data = [
[cell("Type", bold_=True, color=WHITE), cell("First HMF Affected", bold_=True, color=WHITE),
cell("Pattern of Spread", bold_=True, color=WHITE), cell("Key Distinguishing Feature", bold_=True, color=WHITE)],
["Alzheimer's Disease",
"Episodic memory (recent > remote)",
"Memory → anomia → praxis → visuospatial → executive",
"Temporal gradient; benefits from scaffolded cues initially"],
["Frontotemporal Dementia (bvFTD)",
"Personality, executive, social judgment",
"Frontal → temporal lobes",
"Dramatic personality change; disinhibition / apathy; early frontal release signs"],
["Semantic Dementia (svFTD)",
"Semantic memory — loss of word meanings, face recognition",
"Progressive asymmetric temporal",
"Cannot name or understand words despite fluent spontaneous speech"],
["Vascular Dementia",
"Patchy — executive, psychomotor slowing",
"Step-wise progression",
"Vascular risk factors; focal signs; neuroimaging shows infarcts/WMH"],
["Lewy Body Dementia",
"Visuospatial, attention, executive",
"Fluctuating; visual hallucinations; parkinsonism",
"REM sleep behaviour disorder; sensitivity to antipsychotics"],
["Korsakoff Syndrome",
"Anterograde amnesia + confabulation",
"Does NOT progress like degenerative dementia",
"History of alcoholism; thiamine deficiency; mamillary body atrophy on MRI"],
["Normal Pressure Hydrocephalus",
"Attention, executive function",
"Plus gait apraxia + urinary urgency/incontinence",
"Hakim's triad; responds to CSF diversion; large ventricles on imaging"],
]
story.append(make_table(dem_data, col_widths=[3.5*cm, 4*cm, 4.5*cm, 5*cm], header_bg=ORANGE, alt_bg=LIGHT_ORANGE))
story.append(spacer(6))
story.append(h2_banner("6.5 Frontal Lobe Syndrome — Localisation & DDx", DARK_PURPLE))
story.append(spacer(4))
fr_data = [
[cell("Circuit", bold_=True, color=WHITE), cell("Clinical Features", bold_=True, color=WHITE), cell("DDx", bold_=True, color=WHITE)],
["DLPFC (areas 9/46)",
"Poor planning, perseveration, concrete thinking, impaired working memory, loss of cognitive flexibility",
"Glioma, trauma, FTD, large AComA rupture"],
["Orbitofrontal (10/11/47)",
"Disinhibition, impulsivity, inappropriate social behavior, Witzelsucht, poor decision-making",
"Meningioma (olfactory groove/sphenoid wing), FTD, OFC contusion"],
["Anterior cingulate (24/32)",
"Apathy, abulia, loss of initiation, akinetic mutism (severe)",
"ACA infarct, hydrocephalus, bilateral mesial frontal glioma"],
]
story.append(make_table(fr_data, col_widths=[4.5*cm, 7.5*cm, 5*cm], header_bg=DARK_PURPLE, alt_bg=LIGHT_PURPLE))
story.append(spacer(4))
story.append(pearl(
"RED FLAG: New personality change in adults >50 years always requires brain imaging to exclude frontal neoplasm."
))
story.append(spacer(6))
story.append(h2_banner("6.6 Gerstmann Syndrome", TEAL))
story.append(spacer(4))
gest_data = [
[cell("Component", bold_=True, color=WHITE), cell("Test", bold_=True, color=WHITE)],
["Finger agnosia", "Eyes closed — touch a finger — 'Which finger did I touch?'"],
["Acalculia", "Simple and serial arithmetic — 'What is 9 × 7?'"],
["Agraphia", "'Write a complete sentence.' (pure agraphia — no other aphasia)"],
["Right-left disorientation", "'Show me your right hand.' / 'Touch your left ear with your right hand.'"],
]
story.append(make_table(gest_data, col_widths=[5*cm, 12*cm], header_bg=TEAL, alt_bg=LIGHT_TEAL))
story.append(spacer(4))
story.append(body(
"<b>Lesion:</b> Left (dominant) parietal lobe, angular gyrus (Brodmann area 39) — at the junction of temporal, parietal, and occipital lobes. "
"All four features must be present for the syndrome. <b>Causes:</b> Posterior MCA branch stroke, glioma, degenerative dementia."
))
story.append(spacer(6))
story.append(h2_banner("6.7 Common Viva Questions & Model Answers", CRIMSON))
story.append(spacer(4))
viva = [
("What is the difference between delirium and dementia?",
"Delirium: acute, fluctuating, impaired ATTENTION as cardinal feature, clouded consciousness, reversible. "
"Dementia: chronic, progressive, attention relatively spared initially, clear consciousness until late, irreversible. "
"A patient with dementia is at much higher risk of superimposed delirium when acutely unwell."),
("Why test attention before memory?",
"Attention is the gating mechanism for memory encoding. An inattentive patient will fail three-word recall not "
"because of hippocampal lesion but because they never properly registered the words. Testing attention first "
"allows correct interpretation of memory test results."),
("Most sensitive bedside test for early Alzheimer's?",
"Three-word delayed recall (free recall at 5 min, no cueing) is the most sensitive single bedside test for "
"hippocampal dysfunction. Semantic fluency (animal naming) is the second most sensitive. Standard MMSE can miss early AD."),
("Patient has fluent aphasia with paraphasias — where is the lesion?",
"Posterior to the Rolandic fissure in the dominant hemisphere. If comprehension is also impaired → Wernicke's area "
"(post. sup. temporal, area 22). If comprehension is intact but repetition is severely impaired → "
"arcuate fasciculus / supramarginal gyrus (area 40) = conduction aphasia."),
("Patient cannot draw a clock correctly — where is the lesion?",
"Clock errors can reflect: Parietal (spatial disorganization — numbers placed incorrectly in space, crowded to one side); "
"Frontal (planning errors — perseveration, clock starts well then deteriorates); or Global dementia (multiple errors). "
"Ask: Was circle correct? Numbers spatial? Hands correct? Right parietal = spatial errors; Frontal = planning errors."),
("What is Gerstmann syndrome and where is the lesion?",
"Tetrad: finger agnosia + acalculia + agraphia + right-left disorientation. "
"Lesion: left angular gyrus (Brodmann area 39), at the TPO junction. "
"The angular gyrus is the convergence zone for reading, writing, calculation, and finger identification."),
("Why does anosognosia occur with right hemisphere lesions?",
"The right hemisphere dominates global spatial and body monitoring. It directs attention to both sides. "
"Left parietal lesions produce aphasia (obvious deficit); right parietal lesions disrupt the spatial monitoring "
"system itself — the patient lacks the neural machinery to perceive the deficit. Not psychological denial."),
("What is the perisylvian rule for aphasia classification?",
"In the perisylvian zone (Broca → arcuate fasciculus → Wernicke), repetition is ALWAYS impaired. "
"Outside the perisylvian zone (transcortical aphasias — watershed areas), repetition is SPARED. "
"This is the most reliable single rule for aphasia classification at the bedside."),
]
for q, a in viva:
story.append(KeepTogether([
Paragraph(f"Q: {q}", ParagraphStyle("Q", fontName="Helvetica-Bold", fontSize=9.5,
textColor=CRIMSON, spaceAfter=2, leading=13)),
SideBar(f"A: {a}", EMERALD, LIGHT_GREEN, doc.width,
ParagraphStyle("A", fontName="Helvetica", fontSize=9, textColor=DARK_GREY,
leading=13, leftIndent=4)),
Spacer(1, 6),
]))
story.append(spacer(6))
story.append(hr(GOLD, 2))
story.append(spacer(4))
story.append(Paragraph(
"References: Harrison's Principles of Internal Medicine 22e · Bradley & Daroff's Neurology in Clinical Practice · "
"Adams & Victor's Principles of Neurology 12e · Localization in Clinical Neurology 8e · "
"Neuroanatomy through Clinical Cases 3e · Kaplan & Sadock's Synopsis of Psychiatry",
REF_STYLE
))
# ── Build Story ───────────────────────────────────────────────────────────────
def build():
story = []
cover_page(story)
part1(story)
part2(story)
part3(story)
part4(story)
part5(story)
part6(story)
def on_page(canvas, doc_):
canvas.saveState()
canvas.setFont("Helvetica", 8)
canvas.setFillColor(MID_GREY)
canvas.drawCentredString(PAGE_W / 2, 1.2*cm,
f"Higher Mental Functions — MD General Medicine Examination Guide | Page {doc_.page}")
canvas.setStrokeColor(ROYAL_BLUE)
canvas.setLineWidth(0.5)
canvas.line(1.8*cm, 1.5*cm, PAGE_W - 1.8*cm, 1.5*cm)
canvas.restoreState()
doc.build(story, onFirstPage=on_page, onLaterPages=on_page)
print(f"PDF written: {OUTPUT}")
if __name__ == "__main__":
build()