Nihss score

Reading File
Searching the Web

NIHSS score NIH Stroke Scale components interpretation 2024

Finding Sources
Reading File
Finding Sources
Reading File
The table content was captured in the first read. Let me compile the full NIHSS details from the textbook data retrieved.

NIH Stroke Scale (NIHSS)

The NIHSS is a 15-item standardized neurological examination tool used to assess stroke severity, guide treatment decisions (including thrombolysis eligibility), and monitor progress. Total score ranges from 0 to 42.
  • Tintinalli's Emergency Medicine: A Comprehensive Study Guide, Table 167-6

The 15 Items and Scoring

#DomainScore RangeKey Points
1aLevel of Consciousness (LOC)0-30 = Alert; 1 = arousable by minor stimulation; 2 = requires repeated stimulation; 3 = unresponsive/reflex only
1bLOC Questions (age + month)0-20 = both correct; 1 = one correct; 2 = neither correct. Intubated/aphasic patients: 1 if non-aphasic cause
1cLOC Commands (open/close eyes, grip/release)0-20 = both correct; 1 = one correct; 2 = neither
2Best Gaze (horizontal eye movements only)0-20 = normal; 1 = partial gaze palsy; 2 = forced deviation
3Visual Fields0-30 = no loss; 1 = partial hemianopia; 2 = complete hemianopia; 3 = bilateral blindness
4Facial Palsy0-30 = normal; 1 = minor; 2 = partial; 3 = complete (upper + lower face)
5a/5bMotor Arm (left and right, scored separately)0-4 each0 = no drift; 1 = drift but doesn't hit bed; 2 = some effort against gravity; 3 = no effort against gravity; 4 = no movement. Amputees: score 9 (untestable)
6a/6bMotor Leg (left and right, scored separately)0-4 eachSame schema as arm; tested at 30 degrees
7Limb Ataxia0-20 = absent; 1 = one limb; 2 = two limbs
8Sensory0-20 = normal; 1 = mild-moderate loss; 2 = severe/total loss or bilateral loss
9Best Language0-30 = no aphasia; 1 = mild-moderate aphasia; 2 = severe aphasia; 3 = mute/global aphasia
10Dysarthria0-20 = normal; 1 = mild-moderate; 2 = severe/unintelligible. Intubated = 9 (untestable)
11Extinction / Inattention (Neglect)0-20 = no abnormality; 1 = inattention in one modality; 2 = severe hemi-inattention
Note: Items 5 and 6 are scored for each side separately, making the total possible score 42.

Score Interpretation

ScoreSeverity
0No stroke symptoms
1-4Minor stroke
5-15Moderate stroke
16-20Moderate-to-severe stroke
21-42Severe stroke

Clinical Relevance

Thrombolysis (IV tPA):
  • NIHSS is used to assess eligibility. Scores 4-25 are generally considered for IV tPA (AHA/ASA guidelines vary by context).
  • Very low scores (0-3) may indicate minor deficits where risk-benefit analysis is needed.
  • Very high scores (>25) indicate higher hemorrhagic risk.
Endovascular therapy (thrombectomy):
  • Large vessel occlusion (LVO) is suggested by NIHSS >= 6 (sensitive, not specific).
  • Higher NIHSS scores with proximal vessel occlusion on CTA are the typical target population.
Prognosis:
  • Baseline NIHSS strongly predicts functional outcome. Each 1-point increase is associated with ~17% reduction in likelihood of excellent 3-month outcome.
  • NIHSS > 16 predicts high probability of death or severe disability; < 6 predicts good recovery in many patients.

Important Exam Tips

  • Always score the first response - do not coach the patient.
  • Items are scored on what the patient does, not what the examiner believes the patient can do.
  • Untestable items (amputation, prior blindness, intubation) are scored as 9 and not added to the total.
  • The scale must be administered in order; do not go back and change scores.
  • Certified NIHSS training (NIH Stroke Scale Certification) is required in many stroke centers.

Create a quick reference PDF of the NIHSS for clinical use

Reading File
Running Command

ls -la /home/daytona/workspace/ 2>/dev/null || echo "workspace not found"

Running Command

mkdir -p /home/daytona/workspace/nihss-pdf

Writing File

~/nihss-pdf/create_nihss_pdf.py

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

OUTPUT = "/home/daytona/workspace/nihss-pdf/NIHSS_Quick_Reference.pdf"

# ── Colour palette ──────────────────────────────────────────────────────────
DARK_BLUE   = colors.HexColor("#0D3B66")
MED_BLUE    = colors.HexColor("#1A6EA8")
LIGHT_BLUE  = colors.HexColor("#D6EAF8")
TEAL        = colors.HexColor("#1ABC9C")
LIGHT_TEAL  = colors.HexColor("#D5F5E3")
ORANGE      = colors.HexColor("#E67E22")
LIGHT_ORANGE= colors.HexColor("#FAD7A0")
RED         = colors.HexColor("#C0392B")
LIGHT_RED   = colors.HexColor("#FADBD8")
WHITE       = colors.white
LIGHT_GREY  = colors.HexColor("#F4F6F7")
MID_GREY    = colors.HexColor("#BDC3C7")
DARK_GREY   = colors.HexColor("#2C3E50")

doc = SimpleDocTemplate(
    OUTPUT,
    pagesize=A4,
    leftMargin=1.2*cm, rightMargin=1.2*cm,
    topMargin=1.2*cm,  bottomMargin=1.2*cm,
    title="NIHSS Quick Reference",
    author="Clinical Reference",
)

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

styles = getSampleStyleSheet()

def style(name, **kw):
    s = styles[name].clone(name + str(id(kw)))
    for k, v in kw.items():
        setattr(s, k, v)
    return s

# ── Paragraph styles ─────────────────────────────────────────────────────────
header_style = style("Normal", fontSize=20, textColor=WHITE,
                     fontName="Helvetica-Bold", alignment=TA_CENTER, leading=26)
subheader_style = style("Normal", fontSize=10, textColor=LIGHT_BLUE,
                        fontName="Helvetica", alignment=TA_CENTER, leading=14)
section_title = style("Normal", fontSize=9.5, textColor=WHITE,
                      fontName="Helvetica-Bold", alignment=TA_LEFT, leading=13)
body = style("Normal", fontSize=8, textColor=DARK_GREY,
             fontName="Helvetica", leading=11)
body_bold = style("Normal", fontSize=8, textColor=DARK_GREY,
                  fontName="Helvetica-Bold", leading=11)
small = style("Normal", fontSize=7, textColor=DARK_GREY,
              fontName="Helvetica", leading=10)
small_bold = style("Normal", fontSize=7.5, textColor=DARK_GREY,
                   fontName="Helvetica-Bold", leading=11)
score_style = style("Normal", fontSize=9, textColor=WHITE,
                    fontName="Helvetica-Bold", alignment=TA_CENTER, leading=12)
note_style = style("Normal", fontSize=7.5, textColor=DARK_GREY,
                   fontName="Helvetica-Oblique", leading=10)

elements = []

# ═══════════════════════════════════════════════════════════════════════════
# HEADER BANNER
# ═══════════════════════════════════════════════════════════════════════════
header_data = [[
    Paragraph("NIH Stroke Scale (NIHSS)", header_style),
    Paragraph("Quick Reference Card  •  Clinical Use", subheader_style),
]]
header_table = Table(header_data, colWidths=[CONTENT_W * 0.62, CONTENT_W * 0.38])
header_table.setStyle(TableStyle([
    ("BACKGROUND",   (0, 0), (-1, -1), DARK_BLUE),
    ("TOPPADDING",   (0, 0), (-1, -1), 10),
    ("BOTTOMPADDING",(0, 0), (-1, -1), 10),
    ("LEFTPADDING",  (0, 0), (0, -1), 14),
    ("RIGHTPADDING", (1, 0), (1, -1), 14),
    ("VALIGN",       (0, 0), (-1, -1), "MIDDLE"),
    ("ROUNDEDCORNERS", (0,0), (-1,-1), 6),
]))
elements.append(header_table)
elements.append(Spacer(1, 5*mm))

# ═══════════════════════════════════════════════════════════════════════════
# NIHSS ITEMS TABLE
# ═══════════════════════════════════════════════════════════════════════════

def section_header(text, color=MED_BLUE):
    return Table(
        [[Paragraph(text, section_title)]],
        colWidths=[CONTENT_W],
    ), TableStyle([
        ("BACKGROUND",    (0, 0), (-1, -1), color),
        ("TOPPADDING",    (0, 0), (-1, -1), 4),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 4),
        ("LEFTPADDING",   (0, 0), (-1, -1), 8),
    ])

# Build section header
sh_tbl, sh_style = section_header("  NIHSS ITEMS  —  Score each item in order. Use the FIRST response. Do NOT coach the patient.")
sh_tbl.setStyle(sh_style)
elements.append(sh_tbl)
elements.append(Spacer(1, 1*mm))

# ── NIHSS items data ─────────────────────────────────────────────────────────
nihss_items = [
    # (item, domain, scores_text, max, color_band)
    ("1a", "Level of Consciousness (LOC)",
     "0 = Alert, responsive\n1 = Drowsy, arousable by minor stimulation\n2 = Obtunded, requires repeated stimulation\n3 = Unresponsive / reflex only",
     3, LIGHT_BLUE),

    ("1b", "LOC Questions\n(Age + Current month)",
     "0 = Both correct\n1 = One correct  (intubated / non-aphasic cause → score 1)\n2 = Neither correct  (aphasic/stuporous → score 2)",
     2, WHITE),

    ("1c", "LOC Commands\n(Open/close eyes; grip/release)",
     "0 = Both tasks correct\n1 = One task correct\n2 = Neither correct  (only 1st attempt scored)",
     2, LIGHT_BLUE),

    ("2", "Best Gaze\n(Horizontal eye movements only)",
     "0 = Normal\n1 = Partial gaze palsy\n2 = Forced deviation / total gaze palsy",
     2, WHITE),

    ("3", "Visual Fields",
     "0 = No visual loss\n1 = Partial hemianopia\n2 = Complete hemianopia\n3 = Bilateral blindness",
     3, LIGHT_BLUE),

    ("4", "Facial Palsy",
     "0 = Normal, symmetric\n1 = Minor paralysis (flattened NLF, smile asymmetry)\n2 = Partial paralysis (lower face only)\n3 = Complete palsy (upper + lower face)",
     3, WHITE),

    ("5a", "Motor — Right Arm\n(Hold 90° seated / 45° supine × 10 sec)",
     "0 = No drift for 10 sec\n1 = Drift but does not hit bed/support\n2 = Some effort against gravity, cannot sustain\n3 = No effort against gravity (gravity brings limb down)\n4 = No movement\n9 = Untestable (amputation, fusion)",
     4, LIGHT_BLUE),

    ("5b", "Motor — Left Arm\n(Same as 5a)",
     "0 = No drift for 10 sec\n1 = Drift but does not hit bed/support\n2 = Some effort against gravity\n3 = No effort against gravity\n4 = No movement\n9 = Untestable",
     4, WHITE),

    ("6a", "Motor — Right Leg\n(Hold 30° supine × 5 sec)",
     "0 = No drift for 5 sec\n1 = Drift but does not hit bed\n2 = Some effort against gravity\n3 = No effort against gravity\n4 = No movement\n9 = Untestable",
     4, LIGHT_BLUE),

    ("6b", "Motor — Left Leg\n(Same as 6a)",
     "0 = No drift for 5 sec\n1 = Drift but does not hit bed\n2 = Some effort against gravity\n3 = No effort against gravity\n4 = No movement\n9 = Untestable",
     4, WHITE),

    ("7", "Limb Ataxia\n(Finger-nose; heel-shin)",
     "0 = Absent\n1 = Present in one limb\n2 = Present in two limbs\n9 = Untestable (paralysed / amputated)",
     2, LIGHT_BLUE),

    ("8", "Sensory\n(Pinprick face/arm/leg)",
     "0 = Normal, no sensory loss\n1 = Mild-to-moderate loss; patient aware of being touched\n2 = Severe/total loss; patient unaware of touch",
     2, WHITE),

    ("9", "Best Language\n(Name items, read sentences, describe picture)",
     "0 = No aphasia\n1 = Mild-moderate aphasia; some loss of fluency / comprehension\n2 = Severe aphasia; communication by guessing\n3 = Mute / global aphasia / no usable speech",
     3, LIGHT_BLUE),

    ("10", "Dysarthria\n(Read / repeat words)",
     "0 = Normal articulation\n1 = Mild-moderate; slurred but understandable\n2 = Severe; unintelligible or mute/anarthric\n9 = Untestable (intubated)",
     2, WHITE),

    ("11", "Extinction / Inattention\n(Double simultaneous stimulation)",
     "0 = No abnormality\n1 = Inattention or extinction in one sensory modality\n2 = Severe hemi-inattention (>1 modality); does not recognise own hand",
     2, LIGHT_BLUE),
]

# Column header
col_header = [
    Paragraph("<b>Item</b>", small_bold),
    Paragraph("<b>Domain</b>", small_bold),
    Paragraph("<b>Scoring Criteria</b>", small_bold),
    Paragraph("<b>Max</b>", small_bold),
]

# Col widths
COL_W = [1.0*cm, 3.4*cm, 11.5*cm, 1.0*cm]

table_data = [col_header]
row_styles = [
    ("BACKGROUND", (0, 0), (-1, 0), DARK_BLUE),
    ("TEXTCOLOR",  (0, 0), (-1, 0), WHITE),
    ("FONTNAME",   (0, 0), (-1, 0), "Helvetica-Bold"),
    ("FONTSIZE",   (0, 0), (-1, 0), 8),
    ("ALIGN",      (0, 0), (-1, 0), "CENTER"),
    ("TOPPADDING", (0, 0), (-1, 0), 5),
    ("BOTTOMPADDING", (0, 0), (-1, 0), 5),
    ("LINEBELOW",  (0, 0), (-1, 0), 0.5, DARK_BLUE),
]

for i, (item, domain, scores, max_score, bg) in enumerate(nihss_items):
    row_idx = i + 1
    row = [
        Paragraph(f"<b>{item}</b>", style("Normal", fontSize=8.5, textColor=DARK_BLUE,
                                           fontName="Helvetica-Bold", alignment=TA_CENTER, leading=12)),
        Paragraph(domain.replace("\n", "<br/>"), small_bold),
        Paragraph(scores.replace("\n", "<br/>"), small),
        Paragraph(f"<b>{max_score}</b>", style("Normal", fontSize=9, textColor=MED_BLUE,
                                                fontName="Helvetica-Bold", alignment=TA_CENTER, leading=12)),
    ]
    table_data.append(row)
    row_styles += [
        ("BACKGROUND",    (0, row_idx), (-1, row_idx), bg),
        ("TOPPADDING",    (0, row_idx), (-1, row_idx), 3),
        ("BOTTOMPADDING", (0, row_idx), (-1, row_idx), 3),
        ("LEFTPADDING",   (0, row_idx), (-1, row_idx), 5),
        ("RIGHTPADDING",  (0, row_idx), (-1, row_idx), 5),
        ("VALIGN",        (0, row_idx), (-1, row_idx), "TOP"),
        ("LINEBELOW",     (0, row_idx), (-1, row_idx), 0.3, MID_GREY),
    ]

row_styles += [
    ("GRID",      (0, 0), (-1, -1), 0.3, MID_GREY),
    ("ROWBACKGROUNDS", (0, 0), (-1, -1), []),  # override per row above
    ("ALIGN",     (0, 0), (0, -1), "CENTER"),
    ("ALIGN",     (3, 0), (3, -1), "CENTER"),
    ("VALIGN",    (0, 0), (0, -1), "MIDDLE"),
    ("VALIGN",    (3, 0), (3, -1), "MIDDLE"),
    ("FONTNAME",  (0, 1), (0, -1), "Helvetica-Bold"),
]

nihss_table = Table(table_data, colWidths=COL_W, repeatRows=1)
nihss_table.setStyle(TableStyle(row_styles))
elements.append(nihss_table)
elements.append(Spacer(1, 4*mm))

# ═══════════════════════════════════════════════════════════════════════════
# TOTAL SCORE ROW
# ═══════════════════════════════════════════════════════════════════════════
total_data = [[
    Paragraph("<b>TOTAL NIHSS SCORE</b>", style("Normal", fontSize=10, textColor=WHITE,
              fontName="Helvetica-Bold", alignment=TA_LEFT, leading=14)),
    Paragraph("<b>0 – 42</b>", style("Normal", fontSize=12, textColor=WHITE,
              fontName="Helvetica-Bold", alignment=TA_CENTER, leading=16)),
    Paragraph("Items 5a, 5b, 6a, 6b scored separately  •  Items scored 9 (Untestable) are NOT added to total",
              style("Normal", fontSize=7.5, textColor=LIGHT_BLUE,
                    fontName="Helvetica-Oblique", alignment=TA_LEFT, leading=11)),
]]
total_tbl = Table(total_data, colWidths=[5*cm, 2*cm, CONTENT_W - 7*cm])
total_tbl.setStyle(TableStyle([
    ("BACKGROUND",    (0, 0), (-1, -1), DARK_BLUE),
    ("TOPPADDING",    (0, 0), (-1, -1), 8),
    ("BOTTOMPADDING", (0, 0), (-1, -1), 8),
    ("LEFTPADDING",   (0, 0), (-1, -1), 10),
    ("VALIGN",        (0, 0), (-1, -1), "MIDDLE"),
    ("LINEABOVE",     (0, 0), (-1, 0), 2, TEAL),
]))
elements.append(total_tbl)
elements.append(Spacer(1, 5*mm))

# ═══════════════════════════════════════════════════════════════════════════
# SEVERITY BANDS + CLINICAL THRESHOLDS (side by side)
# ═══════════════════════════════════════════════════════════════════════════

# Left: Severity table
sev_header = [
    [Paragraph("<b>Score</b>", small_bold), Paragraph("<b>Severity</b>", small_bold),
     Paragraph("<b>Typical Presentation</b>", small_bold)],
]
sev_data = [
    ("0",     "No deficit",          "Normal examination", WHITE),
    ("1 – 4", "Minor stroke",        "Subtle deficits; high recovery chance", LIGHT_TEAL),
    ("5 – 15","Moderate stroke",     "Hemiparesis ± aphasia; eligible for tPA", LIGHT_ORANGE),
    ("16 – 20","Moderate-severe",    "Significant deficits; higher haem. risk with tPA", LIGHT_RED),
    ("21 – 42","Severe stroke",      "Major deficits; consider endovascular rx", colors.HexColor("#FADBD8")),
]

sev_table_data = sev_header[:]
sev_row_styles = [
    ("BACKGROUND", (0, 0), (-1, 0), DARK_BLUE),
    ("TEXTCOLOR",  (0, 0), (-1, 0), WHITE),
    ("FONTNAME",   (0, 0), (-1, 0), "Helvetica-Bold"),
    ("FONTSIZE",   (0, 0), (-1, 0), 8),
    ("ALIGN",      (0, 0), (-1, 0), "CENTER"),
    ("TOPPADDING", (0, 0), (-1, 0), 4),
    ("BOTTOMPADDING", (0, 0), (-1, 0), 4),
]
for i, (sc, sev, pres, bg) in enumerate(sev_data):
    sev_table_data.append([
        Paragraph(f"<b>{sc}</b>", style("Normal", fontSize=8, textColor=DARK_GREY,
                                         fontName="Helvetica-Bold", alignment=TA_CENTER, leading=11)),
        Paragraph(sev, small_bold),
        Paragraph(pres, small),
    ])
    sev_row_styles += [
        ("BACKGROUND",    (0, i+1), (-1, i+1), bg),
        ("TOPPADDING",    (0, i+1), (-1, i+1), 4),
        ("BOTTOMPADDING", (0, i+1), (-1, i+1), 4),
        ("LEFTPADDING",   (0, i+1), (-1, i+1), 5),
        ("RIGHTPADDING",  (0, i+1), (-1, i+1), 5),
        ("LINEBELOW",     (0, i+1), (-1, i+1), 0.3, MID_GREY),
    ]
sev_row_styles += [
    ("GRID",  (0, 0), (-1, -1), 0.3, MID_GREY),
    ("ALIGN", (0, 0), (0, -1), "CENTER"),
    ("VALIGN",(0, 0), (-1, -1), "MIDDLE"),
]
sev_tbl = Table(sev_table_data, colWidths=[1.6*cm, 3.4*cm, 4.8*cm])
sev_tbl.setStyle(TableStyle(sev_row_styles))

# Right: Clinical thresholds box
thresholds = [
    ("IV tPA Eligibility",    "NIHSS 4 – 25 (typical range)\nScore 0–3: assess risk-benefit carefully\nScore >25: higher haemorrhage risk",  LIGHT_ORANGE),
    ("LVO / Thrombectomy",    "NIHSS ≥ 6 suggests large vessel occlusion\nConfirm with CTA head & neck",               LIGHT_BLUE),
    ("Prognosis",             "Each +1 point ≈ 17% ↓ in excellent outcome\nNIHSS <6 → likely good recovery\nNIHSS >16 → high risk of severe disability/death", LIGHT_TEAL),
]

thr_title = Table([[Paragraph("CLINICAL THRESHOLDS", section_title)]],
                  colWidths=[6.8*cm])
thr_title.setStyle(TableStyle([
    ("BACKGROUND", (0,0), (-1,-1), MED_BLUE),
    ("TOPPADDING", (0,0), (-1,-1), 5),
    ("BOTTOMPADDING", (0,0), (-1,-1), 5),
    ("LEFTPADDING",   (0,0), (-1,-1), 8),
]))

thr_rows = []
for label, content, bg in thresholds:
    thr_rows.append([
        Paragraph(f"<b>{label}</b>", small_bold),
        Paragraph(content.replace("\n", "<br/>"), small),
    ])

thr_body = Table(thr_rows, colWidths=[2.8*cm, 4.0*cm])
thr_body_styles = []
for i, (_, _, bg) in enumerate(thresholds):
    thr_body_styles += [
        ("BACKGROUND",    (0, i), (-1, i), bg),
        ("TOPPADDING",    (0, i), (-1, i), 5),
        ("BOTTOMPADDING", (0, i), (-1, i), 5),
        ("LEFTPADDING",   (0, i), (-1, i), 5),
        ("LINEBELOW",     (0, i), (-1, i), 0.3, MID_GREY),
        ("VALIGN",        (0, i), (-1, i), "TOP"),
    ]
thr_body_styles += [("GRID", (0,0), (-1,-1), 0.3, MID_GREY)]
thr_body.setStyle(TableStyle(thr_body_styles))

# Combine severity and thresholds side by side
right_col = [thr_title, thr_body]
from reportlab.platypus import KeepInFrame

# Use a nested table
bottom_left = [
    [Table([[Paragraph("SCORE SEVERITY", section_title)]],
           colWidths=[9.8*cm])],
    [sev_tbl],
]
bl_outer = Table(bottom_left, colWidths=[9.8*cm])
bl_outer.setStyle(TableStyle([
    ("TOPPADDING",    (0, 0), (-1, -1), 0),
    ("BOTTOMPADDING", (0, 0), (-1, -1), 0),
    ("LEFTPADDING",   (0, 0), (-1, -1), 0),
    ("RIGHTPADDING",  (0, 0), (-1, -1), 0),
]))
# Set section header style on that cell
sev_header_tbl = bl_outer._cellvalues[0][0]
if hasattr(sev_header_tbl, 'setStyle'):
    sev_header_tbl.setStyle(TableStyle([
        ("BACKGROUND", (0, 0), (-1, -1), MED_BLUE),
        ("TOPPADDING", (0, 0), (-1, -1), 5),
        ("BOTTOMPADDING", (0, 0), (-1, -1), 5),
        ("LEFTPADDING",   (0, 0), (-1, -1), 8),
    ]))

bottom_right = [
    [thr_title],
    [thr_body],
]
br_outer = Table(bottom_right, colWidths=[6.8*cm])
br_outer.setStyle(TableStyle([
    ("TOPPADDING",    (0, 0), (-1, -1), 0),
    ("BOTTOMPADDING", (0, 0), (-1, -1), 0),
    ("LEFTPADDING",   (0, 0), (-1, -1), 0),
    ("RIGHTPADDING",  (0, 0), (-1, -1), 0),
]))

two_col = Table(
    [[bl_outer, Spacer(4*mm, 1), br_outer]],
    colWidths=[9.8*cm, 0.4*cm, 6.8*cm]
)
two_col.setStyle(TableStyle([
    ("VALIGN",        (0, 0), (-1, -1), "TOP"),
    ("TOPPADDING",    (0, 0), (-1, -1), 0),
    ("BOTTOMPADDING", (0, 0), (-1, -1), 0),
    ("LEFTPADDING",   (0, 0), (-1, -1), 0),
    ("RIGHTPADDING",  (0, 0), (-1, -1), 0),
]))
elements.append(two_col)
elements.append(Spacer(1, 5*mm))

# ═══════════════════════════════════════════════════════════════════════════
# ADMINISTRATION NOTES
# ═══════════════════════════════════════════════════════════════════════════
notes_header = Table([[Paragraph("ADMINISTRATION NOTES", section_title)]],
                     colWidths=[CONTENT_W])
notes_header.setStyle(TableStyle([
    ("BACKGROUND", (0, 0), (-1, -1), TEAL),
    ("TOPPADDING", (0, 0), (-1, -1), 5),
    ("BOTTOMPADDING", (0, 0), (-1, -1), 5),
    ("LEFTPADDING",   (0, 0), (-1, -1), 8),
]))
elements.append(notes_header)

notes_data = [
    [
        Paragraph("<b>Order matters</b>", small_bold),
        Paragraph("Administer items in sequence (1a → 11). Do not skip ahead or return to change scores.", small),
        Paragraph("<b>First response only</b>", small_bold),
        Paragraph("Score the first attempt. Do not prompt, coach, or provide verbal/non-verbal cues.", small),
    ],
    [
        Paragraph("<b>Score 9 = Untestable</b>", small_bold),
        Paragraph("Use for amputation, fusion, prior blindness, intubation (items 5, 6, 7, 10). Do NOT add to total.", small),
        Paragraph("<b>Bilateral testing</b>", small_bold),
        Paragraph("Items 5a/5b and 6a/6b are scored and recorded separately; both contribute to total.", small),
    ],
    [
        Paragraph("<b>Unconscious patients</b>", small_bold),
        Paragraph("Score 2 for items 1b/1c; score 3 for item 9 (global aphasia) if no response.", small),
        Paragraph("<b>Certification</b>", small_bold),
        Paragraph("NIHSS certification required at most stroke centres. Retrain every 6–12 months.", small),
    ],
]

notes_tbl = Table(notes_data, colWidths=[3.0*cm, 6.0*cm, 3.0*cm, 5.0*cm])
notes_tbl.setStyle(TableStyle([
    ("BACKGROUND",    (0, 0), (1, -1), LIGHT_GREY),
    ("BACKGROUND",    (2, 0), (3, -1), WHITE),
    ("TOPPADDING",    (0, 0), (-1, -1), 5),
    ("BOTTOMPADDING", (0, 0), (-1, -1), 5),
    ("LEFTPADDING",   (0, 0), (-1, -1), 6),
    ("RIGHTPADDING",  (0, 0), (-1, -1), 6),
    ("LINEBELOW",     (0, 0), (-1, -2), 0.3, MID_GREY),
    ("VALIGN",        (0, 0), (-1, -1), "TOP"),
    ("GRID",          (0, 0), (-1, -1), 0.3, MID_GREY),
]))
elements.append(notes_tbl)
elements.append(Spacer(1, 4*mm))

# ═══════════════════════════════════════════════════════════════════════════
# FOOTER
# ═══════════════════════════════════════════════════════════════════════════
footer_data = [[
    Paragraph("Reference: Tintinalli's Emergency Medicine (Table 167-6)  •  AHA/ASA Stroke Guidelines", note_style),
    Paragraph("Total Score = Sum of all items (except untestable items scored 9)  •  Max = 42", note_style),
]]
footer_tbl = Table(footer_data, colWidths=[CONTENT_W * 0.6, CONTENT_W * 0.4])
footer_tbl.setStyle(TableStyle([
    ("BACKGROUND",    (0, 0), (-1, -1), DARK_BLUE),
    ("TEXTCOLOR",     (0, 0), (-1, -1), LIGHT_BLUE),
    ("TOPPADDING",    (0, 0), (-1, -1), 6),
    ("BOTTOMPADDING", (0, 0), (-1, -1), 6),
    ("LEFTPADDING",   (0, 0), (-1, -1), 10),
    ("RIGHTPADDING",  (0, 0), (-1, -1), 10),
    ("VALIGN",        (0, 0), (-1, -1), "MIDDLE"),
]))
elements.append(footer_tbl)

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

cd /home/daytona/workspace/nihss-pdf && python create_nihss_pdf.py 2>&1

Editing File

~/nihss-pdf/create_nihss_pdf.py

Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/nihss-pdf/create_nihss_pdf.py'
Running Command

cd /home/daytona/workspace/nihss-pdf && python create_nihss_pdf.py 2>&1

Running Command

ls -lh /home/daytona/workspace/nihss-pdf/NIHSS_Quick_Reference.pdf

Your NIHSS Quick Reference PDF is ready:

NIHSS Quick Reference

PDF Document · PDF

What's included (single A4 page):
  • Header banner with title and "Clinical Use" label
  • All 15 NIHSS items (1a, 1b, 1c, 2-11) in a colour-coded table - alternating rows for easy reading, with full scoring criteria for each item and max score per domain
  • Score severity bands - 0 (no deficit) through 21-42 (severe), colour-coded from green to red
  • Clinical thresholds panel - IV tPA eligibility ranges, LVO/thrombectomy indicators, and prognosis guidance
  • Administration notes - key rules on ordering, first-response scoring, untestable items (score 9), bilateral scoring for arms and legs, and certification reminders
  • Footer citing Tintinalli's Emergency Medicine and AHA/ASA guidelines
This is a shared conversation. Sign in to Orris to start your own chat.