What should a swallowing therapist should carry in there bag for a session
swallowing therapist dysphagia SLP bag supplies equipment bedside assessment
https://www.sprypt.com/fot/bedside-swallowing-evaluation
| Setting | Extra Considerations |
|---|---|
| Acute hospital | Know suction/crash trolley location; shorter sessions; NPO status common |
| Skilled nursing facility | Mealtime observation tools (MEOF-II); carer training materials |
| Paediatrics | NUK brushes, chewy tubes in smaller sizes, different food textures, parent handouts |
| Home visits | Self-contained kit; portable suction if high-risk patient; phone for tele-consult |
Create a checklist PDF I can print for session prep
mkdir -p /home/daytona/workspace/swallowing-therapist && ls /home/daytona/workspace/
~/swallowing-therapist/generate_checklist.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, HRFlowable
)
from reportlab.lib.enums import TA_LEFT, TA_CENTER
OUTPUT = "/home/daytona/workspace/swallowing-therapist/Swallowing_Therapist_Session_Checklist.pdf"
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=15*mm,
rightMargin=15*mm,
topMargin=15*mm,
bottomMargin=15*mm,
)
# ── Colour palette ──────────────────────────────────────────────────────────
TEAL = colors.HexColor("#1A7A8A")
TEAL_LIGHT= colors.HexColor("#D6EEF1")
DARK = colors.HexColor("#1C2B35")
MID_GREY = colors.HexColor("#6B7C85")
ROW_ALT = colors.HexColor("#F0F8FA")
WHITE = colors.white
# ── Styles ───────────────────────────────────────────────────────────────────
styles = getSampleStyleSheet()
title_style = ParagraphStyle(
"Title",
fontName="Helvetica-Bold",
fontSize=18,
textColor=WHITE,
alignment=TA_CENTER,
leading=22,
)
subtitle_style = ParagraphStyle(
"Subtitle",
fontName="Helvetica",
fontSize=9,
textColor=WHITE,
alignment=TA_CENTER,
leading=12,
)
section_style = ParagraphStyle(
"Section",
fontName="Helvetica-Bold",
fontSize=10,
textColor=WHITE,
alignment=TA_LEFT,
leading=13,
leftIndent=4,
)
item_style = ParagraphStyle(
"Item",
fontName="Helvetica",
fontSize=9,
textColor=DARK,
alignment=TA_LEFT,
leading=13,
leftIndent=2,
)
note_style = ParagraphStyle(
"Note",
fontName="Helvetica-Oblique",
fontSize=7.5,
textColor=MID_GREY,
alignment=TA_LEFT,
leading=10,
leftIndent=2,
)
footer_style = ParagraphStyle(
"Footer",
fontName="Helvetica",
fontSize=7,
textColor=MID_GREY,
alignment=TA_CENTER,
)
# ── Helper: checkbox + item row ───────────────────────────────────────────────
def item_row(text, note=None, shade=False):
bg = ROW_ALT if shade else WHITE
item_para = Paragraph(text, item_style)
note_para = Paragraph(note, note_style) if note else Paragraph("", note_style)
# checkbox cell is a small square drawn via a nested table
checkbox = Table(
[[""]],
colWidths=[5*mm],
rowHeights=[5*mm],
)
checkbox.setStyle(TableStyle([
("BOX", (0,0),(0,0), 1, colors.HexColor("#9BB8BE")),
("BACKGROUND", (0,0),(0,0), WHITE),
("VALIGN", (0,0),(0,0), "MIDDLE"),
]))
row = Table(
[[checkbox, item_para], ["", note_para]],
colWidths=[8*mm, None],
rowHeights=[None, None],
)
row.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), bg),
("VALIGN", (0,0),(-1,-1), "TOP"),
("LEFTPADDING",(0,0),(-1,-1), 2),
("RIGHTPADDING",(0,0),(-1,-1), 4),
("TOPPADDING", (0,0),(-1,-1), 2),
("BOTTOMPADDING",(0,0),(-1,-1), 2),
]))
return row
# ── Helper: section header ────────────────────────────────────────────────────
def section_header(title, icon=""):
label = Paragraph(f"{icon} {title}", section_style)
t = Table([[label]], colWidths=[None])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), TEAL),
("TOPPADDING", (0,0),(-1,-1), 4),
("BOTTOMPADDING", (0,0),(-1,-1), 4),
("LEFTPADDING", (0,0),(-1,-1), 6),
("RIGHTPADDING", (0,0),(-1,-1), 6),
("ROUNDEDCORNERS",(0,0),(-1,-1), [3,3,3,3]),
]))
return t
# ── Content ───────────────────────────────────────────────────────────────────
story = []
# ── Title banner ──────────────────────────────────────────────────────────────
banner_data = [[
Paragraph("Swallowing Therapist", title_style),
Paragraph("Session Preparation Checklist", title_style),
]]
# Actually build a stacked title
title_table = Table(
[[Paragraph("SWALLOWING THERAPIST", title_style)],
[Paragraph("Session Preparation Checklist", subtitle_style)],
[Paragraph("Clinical Dysphagia Service | Print & tick before each session", subtitle_style)]],
colWidths=[None],
)
title_table.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), TEAL),
("TOPPADDING", (0,0),(-1,-1), 8),
("BOTTOMPADDING", (0,0),(-1,-1), 8),
("LEFTPADDING", (0,0),(-1,-1), 10),
("RIGHTPADDING", (0,0),(-1,-1), 10),
]))
story.append(title_table)
story.append(Spacer(1, 4*mm))
# ── Session info strip ────────────────────────────────────────────────────────
info_row = Table(
[[
Paragraph("<b>Date:</b> ___________________", item_style),
Paragraph("<b>Patient/Client:</b> _______________________", item_style),
Paragraph("<b>Setting:</b> __________________", item_style),
Paragraph("<b>Clinician:</b> ________________", item_style),
]],
colWidths=["25%","35%","20%","20%"],
)
info_row.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), TEAL_LIGHT),
("BOX", (0,0),(-1,-1), 0.5, TEAL),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 6),
("RIGHTPADDING", (0,0),(-1,-1), 6),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
]))
story.append(info_row)
story.append(Spacer(1, 4*mm))
# ═══════════════════════════════════════════════════════════════════════════
# Two-column layout
# ═══════════════════════════════════════════════════════════════════════════
LEFT_W = 88*mm
RIGHT_W = 88*mm
GAP = 4*mm
def build_section(header_text, items):
"""Returns a list of flowables for one checklist section."""
block = []
block.append(section_header(header_text))
for i, (text, note) in enumerate(items):
block.append(item_row(text, note, shade=(i % 2 == 1)))
block.append(Spacer(1, 3*mm))
return block
def flowables_to_table_col(flowables, width):
"""Wraps a list of flowables into a single-cell Table for use in a column."""
from reportlab.platypus import KeepTogether
cell_table = Table([[f] for f in flowables], colWidths=[width])
cell_table.setStyle(TableStyle([
("LEFTPADDING", (0,0),(-1,-1), 0),
("RIGHTPADDING", (0,0),(-1,-1), 0),
("TOPPADDING", (0,0),(-1,-1), 0),
("BOTTOMPADDING",(0,0),(-1,-1), 0),
]))
return cell_table
# ── LEFT COLUMN ───────────────────────────────────────────────────────────────
left_items = []
left_items += build_section("ASSESSMENT & SCREENING TOOLS", [
("Pulse oximeter", "Monitor O2 sat during trials; drop ≥2% may indicate aspiration"),
("Stethoscope (flat diaphragm)", "Cervical auscultation — place on thyroid cartilage"),
("Penlight / small torch", "Oral cavity & cranial nerve inspection"),
("Tongue depressors", "Oral motor exam; resistance exercises"),
("Gauze squares", "Tongue protrusion test; bolus control"),
("Gloves (nitrile/non-latex)", "Essential for all oral examination"),
("Face mask & apron", "Standard PPE; aerosol precautions"),
("Graduated cup / 30 mL syringe", "Controlled water swallow test (30 mL or 100 mL WST)"),
("Stopwatch / timer", "WST: measures speed, capacity & volume"),
])
left_items += build_section("VALIDATED OUTCOME MEASURES", [
("EAT-10 form", "Patient-reported dysphagia severity screening"),
("GUSS (Gugging Swallowing Screen)", "Validated bedside screening tool"),
("MASA form", "Mann Assessment of Swallowing Ability"),
("FOIS reference card", "Functional Oral Intake Scale — level of oral intake"),
("PSS-HN reference card", "Performance Status Scale for Head & Neck Cancer"),
("MEOF-II / McGill observation sheet", "Mealtime observation; dementia/LD patients"),
("Penetration-Aspiration Scale (PAS) card", "Quick reference for instrumental findings"),
("SOAP / progress note forms", "Or tablet/clipboard for charting"),
])
left_items += build_section("DOCUMENTATION & ADMIN", [
("Referral forms (MBSS / FEES)", "For escalation when silent aspiration suspected"),
("Pens & markers", None),
("Tablet / device for electronic records", None),
("Hand sanitizer", None),
("Paper towels & wet wipes", None),
])
# ── RIGHT COLUMN ──────────────────────────────────────────────────────────────
right_items = []
right_items += build_section("FOOD & LIQUID TRIAL SUPPLIES", [
("Thickening agent (xanthan gum-based)", "e.g. Resource ThickenUp Clear — IDDSI Levels 1-4"),
("Small cups (30 mL & standard)", None),
("Teaspoons & tablespoons", None),
("Standard & cut straws", "Cut straw = controlled sip volume"),
("60 mL syringes", "Bolus delivery for reduced lip closure"),
("Puree pouches / soft food samples", "e.g. crackers, soft biscuit, smooth puree"),
("Sealed water bottle (plain)", None),
])
right_items += build_section("ORAL MOTOR & THERAPY TOOLS", [
("NUK brush / oral stimulation kit", "Sensory & thermal-tactile stimulation"),
("Chewy tubes (varied resistance)", "Jaw strengthening exercises"),
("Vibrating oral stimulator (Z-Vibe)", "Thermal-tactile application; oral alerting"),
("Bite blocks", "Jaw stability training"),
("Padded tongue depressors", "Resistance exercises; isometric tongue press"),
("Small hand mirror", "Patient biofeedback on lip/mouth movement"),
])
right_items += build_section("SAFETY EQUIPMENT", [
("Suction catheter (portable)", "Or confirm location of unit suction on arrival"),
("Emesis basin / sick bowl", None),
("Spare gloves, masks, apron (x2 sets)", None),
])
right_items += build_section("PATIENT EDUCATION MATERIALS", [
("Safe swallowing posture handouts", "Chin tuck, head rotation/tilt, supraglottic swallow"),
("IDDSI texture/liquid level guide", "For patient & carer reference"),
("Compensatory strategy handout", "Effortful swallow, Mendelsohn, double swallow"),
("Carer feeding guidance sheet", "Bite size, pacing, positioning instructions"),
("Swallowing anatomy diagram", "Visual aid for patient education"),
])
# Assemble two-column table
left_col = flowables_to_table_col(left_items, LEFT_W)
right_col = flowables_to_table_col(right_items, RIGHT_W)
two_col = Table(
[[left_col, Spacer(GAP, 1), right_col]],
colWidths=[LEFT_W, GAP, RIGHT_W],
)
two_col.setStyle(TableStyle([
("VALIGN", (0,0),(-1,-1), "TOP"),
("LEFTPADDING", (0,0),(-1,-1), 0),
("RIGHTPADDING", (0,0),(-1,-1), 0),
("TOPPADDING", (0,0),(-1,-1), 0),
("BOTTOMPADDING", (0,0),(-1,-1), 0),
]))
story.append(two_col)
# ── Clinical reminder box ──────────────────────────────────────────────────────
story.append(Spacer(1, 3*mm))
reminder_style = ParagraphStyle(
"Reminder",
fontName="Helvetica",
fontSize=8,
textColor=DARK,
leading=11,
leftIndent=4,
)
reminder_bold = ParagraphStyle(
"ReminderBold",
fontName="Helvetica-Bold",
fontSize=8,
textColor=TEAL,
leading=11,
leftIndent=4,
)
reminder_content = Table(
[[
Paragraph("CLINICAL NOTE", reminder_bold),
Paragraph(
"A bedside CSE is a screening tool only. Silent aspiration cannot be confirmed without instrumental assessment (MBSS or FEES). "
"Escalate if: O2 sat drops ≥2%, wet/gurgly voice post-swallow, coughing on multiple consistencies, or if any 2 of "
"the following are present — abnormal voluntary cough, absent gag, dysarthria, dysphonia, post-swallow cough/throat clear/voice change.",
reminder_style,
),
]],
colWidths=[32*mm, None],
)
reminder_content.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), TEAL_LIGHT),
("BOX", (0,0),(-1,-1), 1, TEAL),
("VALIGN", (0,0),(-1,-1), "TOP"),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 6),
("RIGHTPADDING", (0,0),(-1,-1), 6),
]))
story.append(reminder_content)
# ── Footer ─────────────────────────────────────────────────────────────────────
story.append(Spacer(1, 3*mm))
story.append(HRFlowable(width="100%", thickness=0.5, color=TEAL))
story.append(Spacer(1, 1.5*mm))
story.append(Paragraph(
"Swallowing Therapist Session Preparation Checklist | Based on clinical dysphagia practice and Scott-Brown's Otorhinolaryngology (2018) | Review annually",
footer_style,
))
# ── Build ──────────────────────────────────────────────────────────────────────
doc.build(story)
print(f"PDF saved to: {OUTPUT}")
cd /home/daytona/workspace/swallowing-therapist && python generate_checklist.py
~/swallowing-therapist/generate_checklist.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm
from reportlab.lib.styles import ParagraphStyle
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_LEFT, TA_CENTER
OUTPUT = "/home/daytona/workspace/swallowing-therapist/Swallowing_Therapist_Session_Checklist.pdf"
W, H = A4 # 595.28 x 841.89 pts
LM = RM = 14*mm
TM = BM = 14*mm
CONTENT_W = W - LM - RM
doc = SimpleDocTemplate(
OUTPUT, pagesize=A4,
leftMargin=LM, rightMargin=RM,
topMargin=TM, bottomMargin=BM,
)
# ── Colours ───────────────────────────────────────────────────────────────────
TEAL = colors.HexColor("#1A7A8A")
TEAL_LIGHT = colors.HexColor("#D8EFF2")
DARK = colors.HexColor("#1C2B35")
MID_GREY = colors.HexColor("#6B7C85")
ROW_ALT = colors.HexColor("#F2FAFB")
WHITE = colors.white
# ── Styles ────────────────────────────────────────────────────────────────────
s_title = ParagraphStyle("title", fontName="Helvetica-Bold",
fontSize=17, textColor=WHITE, alignment=TA_CENTER, leading=21)
s_sub = ParagraphStyle("sub", fontName="Helvetica",
fontSize=8.5, textColor=WHITE, alignment=TA_CENTER, leading=12)
s_section = ParagraphStyle("sec", fontName="Helvetica-Bold",
fontSize=9.5, textColor=WHITE, leading=13, leftIndent=3)
s_item = ParagraphStyle("item", fontName="Helvetica",
fontSize=8.5, textColor=DARK, leading=12, leftIndent=2)
s_note = ParagraphStyle("note", fontName="Helvetica-Oblique",
fontSize=7.5, textColor=MID_GREY, leading=10, leftIndent=2)
s_footer = ParagraphStyle("footer", fontName="Helvetica",
fontSize=7, textColor=MID_GREY, alignment=TA_CENTER)
s_reminder_hd = ParagraphStyle("remhd", fontName="Helvetica-Bold",
fontSize=8, textColor=TEAL, leading=11)
s_reminder = ParagraphStyle("rem", fontName="Helvetica",
fontSize=8, textColor=DARK, leading=11)
COL_CHECK = 7*mm
COL_ITEM = CONTENT_W * 0.45 - COL_CHECK
COL_NOTE = CONTENT_W * 0.55
# ── Helpers ───────────────────────────────────────────────────────────────────
def checkbox():
t = Table([[""]], colWidths=[4.5*mm], rowHeights=[4.5*mm])
t.setStyle(TableStyle([
("BOX", (0,0),(0,0), 0.8, colors.HexColor("#7AACB5")),
("BACKGROUND", (0,0),(0,0), WHITE),
]))
return t
def item_row(text, note="", shade=False):
bg = ROW_ALT if shade else WHITE
cells = [
[checkbox(), Paragraph(text, s_item),
Paragraph(note or "", s_note)]
]
t = Table(cells, colWidths=[COL_CHECK, COL_ITEM, COL_NOTE])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), bg),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("TOPPADDING", (0,0),(-1,-1), 2.5),
("BOTTOMPADDING", (0,0),(-1,-1), 2.5),
("LEFTPADDING", (0,0),(-1,-1), 2),
("RIGHTPADDING", (0,0),(-1,-1), 3),
]))
return t
def section_hdr(title):
p = Paragraph(title, s_section)
t = Table([[p]], colWidths=[CONTENT_W])
t.setStyle(TableStyle([
("BACKGROUND", (0,0),(0,0), TEAL),
("TOPPADDING", (0,0),(0,0), 4),
("BOTTOMPADDING", (0,0),(0,0), 4),
("LEFTPADDING", (0,0),(0,0), 6),
("RIGHTPADDING", (0,0),(0,0), 6),
]))
return t
def build_section(title, rows):
"""Returns a KeepTogether block (section header + all rows)."""
items = [section_hdr(title)]
for i, (text, note) in enumerate(rows):
items.append(item_row(text, note, shade=(i % 2 == 1)))
items.append(Spacer(1, 2*mm))
return KeepTogether(items)
# ── Story ─────────────────────────────────────────────────────────────────────
story = []
# Title banner
banner = Table(
[[Paragraph("SWALLOWING THERAPIST", s_title)],
[Paragraph("Session Preparation Checklist", s_sub)],
[Paragraph("Clinical Dysphagia Service \u2022 Print & tick before each session", s_sub)]],
colWidths=[CONTENT_W],
)
banner.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), TEAL),
("TOPPADDING", (0,0),(-1,-1), 7),
("BOTTOMPADDING", (0,0),(-1,-1), 7),
("LEFTPADDING", (0,0),(-1,-1), 8),
("RIGHTPADDING", (0,0),(-1,-1), 8),
]))
story.append(banner)
story.append(Spacer(1, 3*mm))
# Session info strip
s_info = ParagraphStyle("info", fontName="Helvetica", fontSize=8.5,
textColor=DARK, leading=12)
info = Table(
[[Paragraph("<b>Date:</b> ______________________", s_info),
Paragraph("<b>Patient / Client:</b> ________________________________", s_info),
Paragraph("<b>Setting:</b> ___________________", s_info),
Paragraph("<b>Clinician:</b> _________________", s_info)]],
colWidths=[CONTENT_W*0.18, CONTENT_W*0.37, CONTENT_W*0.22, CONTENT_W*0.23],
)
info.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), TEAL_LIGHT),
("BOX", (0,0),(-1,-1), 0.5, TEAL),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 6),
("RIGHTPADDING", (0,0),(-1,-1), 4),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
]))
story.append(info)
story.append(Spacer(1, 3*mm))
# Column header row
hdr_style = ParagraphStyle("hdr", fontName="Helvetica-Bold",
fontSize=8, textColor=TEAL, leading=11)
col_hdr = Table(
[["", Paragraph("ITEM", hdr_style), Paragraph("NOTES / CLINICAL REMINDERS", hdr_style)]],
colWidths=[COL_CHECK, COL_ITEM, COL_NOTE],
)
col_hdr.setStyle(TableStyle([
("BOTTOMPADDING", (0,0),(-1,-1), 2),
("LEFTPADDING", (0,0),(-1,-1), 2),
]))
story.append(col_hdr)
story.append(HRFlowable(width="100%", thickness=0.75, color=TEAL))
story.append(Spacer(1, 1.5*mm))
# ── Section 1: Assessment & Screening ────────────────────────────────────────
story.append(build_section("1. ASSESSMENT & SCREENING TOOLS", [
("Pulse oximeter",
"Monitor SpO2 throughout; drop \u22652% during a trial may indicate aspiration"),
("Stethoscope (flat diaphragm)",
"Cervical auscultation \u2014 flat diaphragm on thyroid cartilage; note subglottic air release & epiglottic movement"),
("Penlight / small torch",
"Oral cavity, dentition & cranial nerve inspection"),
("Tongue depressors (x10)",
"Oral motor / cranial nerve exam; resistance exercises"),
("Gauze squares",
"Tongue protrusion testing; bolus handling assessment"),
("Gloves \u2014 nitrile/non-latex (2 pairs)",
"Required for all oral examination"),
("Face mask & apron",
"Standard PPE; aerosol precautions where indicated"),
("Graduated cup (30 mL & standard) + 60 mL syringe",
"Controlled water swallow test \u2014 30 mL WST predicts pneumonia risk; 100 mL WST measures speed/capacity"),
("Stopwatch / timer",
"WST: record swallowing speed, swallow count & volume per swallow"),
]))
# ── Section 2: Validated Outcome Measures ─────────────────────────────────────
story.append(build_section("2. VALIDATED OUTCOME MEASURES & DOCUMENTATION", [
("EAT-10 form",
"Patient-reported 10-item dysphagia severity screen; score \u22653 = abnormal"),
("GUSS \u2014 Gugging Swallowing Screen",
"Validated bedside screen; semi-solid first, then liquid"),
("MASA form",
"Mann Assessment of Swallowing Ability \u2014 detailed clinical rating"),
("FOIS reference card",
"Functional Oral Intake Scale (Levels 1\u20137) \u2014 quantifies oral intake status"),
("PSS-HN reference card",
"Performance Status Scale for Head & Neck Cancer"),
("MEOF-II / McGill observation sheet",
"Mealtime observation tool for dementia / learning disability patients"),
("Penetration-Aspiration Scale (PAS) card",
"Quick reference for documenting instrumental findings"),
("SOAP note / progress forms (or tablet)",
"Document findings, recommendations & follow-up plan"),
("Referral forms for MBSS / FEES",
"Escalate when silent aspiration suspected or CSE inconclusive"),
]))
# ── Section 3: Food & Liquid Trials ───────────────────────────────────────────
story.append(build_section("3. FOOD & LIQUID TRIAL SUPPLIES", [
("Thickening agent \u2014 xanthan gum-based",
"e.g. Resource ThickenUp Clear. Prepare IDDSI Levels 1 (slightly thick) through 4 (extremely thick)"),
("Small cups (30 mL & standard size)",
None),
("Teaspoons & tablespoons",
"Spoon trials before cup sip where aspiration risk is high"),
("Standard straws & cut straws",
"Cut straw limits sip volume for controlled trials"),
("60 mL syringes (x2)",
"Controlled bolus delivery in patients with reduced lip closure"),
("Puree pouches / soft food samples",
"e.g. crackers, soft biscuit, smooth puree \u2014 cover IDDSI texture Levels 3\u20136"),
("Sealed still water bottle",
None),
]))
# ── Section 4: Oral Motor & Therapy ───────────────────────────────────────────
story.append(build_section("4. ORAL MOTOR & THERAPY TOOLS", [
("NUK brush / oral stimulation kit",
"Sensory and thermal-tactile stimulation"),
("Chewy tubes (varied resistance \u2014 2\u20133 grades)",
"Jaw strengthening; resistance progression"),
("Vibrating oral stimulator (e.g. Z-Vibe)",
"Thermal-tactile application; oral alerting before swallow trials"),
("Bite blocks",
"Jaw stability training and graded jaw opening exercises"),
("Small hand mirror",
"Patient biofeedback on lip seal, facial symmetry & laryngeal movement"),
("Padded tongue depressors",
"Isometric tongue press exercises (Iowa Oral Performance Instrument protocol)"),
]))
# ── Section 5: Safety ─────────────────────────────────────────────────────────
story.append(build_section("5. SAFETY EQUIPMENT", [
("Suction catheter (portable) OR confirm unit suction location on arrival",
"Know emergency escalation pathway before beginning trials"),
("Emesis basin / sick bowl",
None),
("Spare gloves, masks & aprons (x2 sets)",
None),
("Hand sanitizer",
None),
("Paper towels & wet wipes",
None),
]))
# ── Section 6: Patient Education ──────────────────────────────────────────────
story.append(build_section("6. PATIENT EDUCATION & CARER MATERIALS", [
("Safe swallowing posture handouts",
"Chin tuck, head rotation/tilt, upright 90\u00b0 positioning, supraglottic swallow technique"),
("IDDSI food & liquid level visual guide",
"Patient and carer reference card for home diet modification"),
("Compensatory strategy handout",
"Effortful swallow, Mendelsohn manoeuvre, double swallow, Masako"),
("Carer / feeder guidance sheet",
"Bite size, pacing, positioning, warning signs to report"),
("Swallowing anatomy diagram",
"Visual aid explaining oral/pharyngeal/oesophageal stages to patient & family"),
]))
# ── Clinical reminder box ─────────────────────────────────────────────────────
story.append(Spacer(1, 2*mm))
reminder = Table(
[[Paragraph("CLINICAL REMINDER", s_reminder_hd),
Paragraph(
"The bedside CSE is a screening tool \u2014 silent aspiration cannot be confirmed without instrumental assessment (MBSS or FEES). "
"Escalate if: SpO2 drops \u22652%, wet/gurgly voice post-swallow, coughing on multiple consistencies, or any 2 of "
"the following: abnormal voluntary cough \u2022 absent gag \u2022 dysarthria \u2022 dysphonia \u2022 post-swallow cough/throat-clear/voice change "
"(sensitivity 92%, specificity 67% for aspiration \u2014 Scott-Brown\u2019s Otorhinolaryngology, 2018).",
s_reminder,
)]],
colWidths=[30*mm, CONTENT_W - 30*mm],
)
reminder.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), TEAL_LIGHT),
("BOX", (0,0),(-1,-1), 0.8, TEAL),
("VALIGN", (0,0),(-1,-1), "TOP"),
("TOPPADDING", (0,0),(-1,-1), 5),
("BOTTOMPADDING", (0,0),(-1,-1), 5),
("LEFTPADDING", (0,0),(-1,-1), 6),
("RIGHTPADDING", (0,0),(-1,-1), 6),
]))
story.append(reminder)
# ── Footer ────────────────────────────────────────────────────────────────────
story.append(Spacer(1, 2.5*mm))
story.append(HRFlowable(width="100%", thickness=0.5, color=TEAL))
story.append(Spacer(1, 1.5*mm))
story.append(Paragraph(
"Swallowing Therapist Session Preparation Checklist \u2022 "
"Based on clinical dysphagia practice & Scott-Brown\u2019s Otorhinolaryngology Head & Neck Surgery (2018) \u2022 Review annually",
s_footer,
))
doc.build(story)
print(f"PDF saved: {OUTPUT}")
~/swallowing-therapist/generate_checklist.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/swallowing-therapist/generate_checklist.py'
cat > /home/daytona/workspace/swallowing-therapist/generate_checklist.py << 'PYEOF' from reportlab.lib.pagesizes import A4 from reportlab.lib import colors from reportlab.lib.units import mm from reportlab.lib.styles import ParagraphStyle from reportlab.platypus import ( SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, HRFlowable, KeepTogether ) from reportlab.lib.enums import TA_LEFT, TA_CENTER OUTPUT = "/home/daytona/workspace/swallowing-therapist/Swallowing_Therapist_Session_Checklist.pdf" W, H = A4 LM = RM = 14*mm TM = BM = 14*mm CONTENT_W = W - LM - RM doc = SimpleDocTemplate( OUTPUT, pagesize=A4, leftMargin=LM, rightMargin=RM, topMargin=TM, bottomMargin=BM, ) TEAL = colors.HexColor("#1A7A8A") TEAL_LIGHT = colors.HexColor("#D8EFF2") DARK = colors.HexColor("#1C2B35") MID_GREY = colors.HexColor("#6B7C85") ROW_ALT = colors.HexColor("#F2FAFB") WHITE = colors.white s_title = ParagraphStyle("title", fontName="Helvetica-Bold", fontSize=17, textColor=WHITE, alignment=TA_CENTER, leading=21) s_sub = ParagraphStyle("sub", fontName="Helvetica", fontSize=8.5, textColor=WHITE, alignment=TA_CENTER, leading=12) s_section = ParagraphStyle("sec", fontName="Helvetica-Bold", fontSize=9.5, textColor=WHITE, leading=13, leftIndent=3) s_item = ParagraphStyle("item", fontName="Helvetica", fontSize=8.5, textColor=DARK, leading=12, leftIndent=2) s_note = ParagraphStyle("note", fontName="Helvetica-Oblique", fontSize=7.5, textColor=MID_GREY, leading=10, leftIndent=2) s_footer = ParagraphStyle("footer", fontName="Helvetica", fontSize=7, textColor=MID_GREY, alignment=TA_CENTER) s_reminder_hd = ParagraphStyle("remhd", fontName="Helvetica-Bold", fontSize=8, textColor=TEAL, leading=11) s_reminder = ParagraphStyle("rem", fontName="Helvetica", fontSize=8, textColor=DARK, leading=11) COL_CHECK = 7*mm COL_ITEM = CONTENT_W * 0.44 - COL_CHECK COL_NOTE = CONTENT_W * 0.56 def checkbox(): t = Table([[""]], colWidths=[4.5*mm], rowHeights=[4.5*mm]) t.setStyle(TableStyle([ ("BOX", (0,0),(0,0), 0.8, colors.HexColor("#7AACB5")), ("BACKGROUND", (0,0),(0,0), WHITE), ])) return t def item_row(text, note="", shade=False): bg = ROW_ALT if shade else WHITE cells = [[checkbox(), Paragraph(text, s_item), Paragraph(note or "", s_note)]] t = Table(cells, colWidths=[COL_CHECK, COL_ITEM, COL_NOTE]) t.setStyle(TableStyle([ ("BACKGROUND", (0,0),(-1,-1), bg), ("VALIGN", (0,0),(-1,-1), "MIDDLE"), ("TOPPADDING", (0,0),(-1,-1), 2.5), ("BOTTOMPADDING", (0,0),(-1,-1), 2.5), ("LEFTPADDING", (0,0),(-1,-1), 2), ("RIGHTPADDING", (0,0),(-1,-1), 3), ])) return t def section_hdr(title): p = Paragraph(title, s_section) t = Table([[p]], colWidths=[CONTENT_W]) t.setStyle(TableStyle([ ("BACKGROUND", (0,0),(0,0), TEAL), ("TOPPADDING", (0,0),(0,0), 4), ("BOTTOMPADDING", (0,0),(0,0), 4), ("LEFTPADDING", (0,0),(0,0), 6), ("RIGHTPADDING", (0,0),(0,0), 6), ])) return t def build_section(title, rows): items = [section_hdr(title)] for i, (text, note) in enumerate(rows): items.append(item_row(text, note, shade=(i % 2 == 1))) items.append(Spacer(1, 2*mm)) return KeepTogether(items) story = [] # Title banner banner = Table( [[Paragraph("SWALLOWING THERAPIST", s_title)], [Paragraph("Session Preparation Checklist", s_sub)], [Paragraph("Clinical Dysphagia Service \u2022 Print & tick before each session", s_sub)]], colWidths=[CONTENT_W], ) banner.setStyle(TableStyle([ ("BACKGROUND", (0,0),(-1,-1), TEAL), ("TOPPADDING", (0,0),(-1,-1), 7), ("BOTTOMPADDING", (0,0),(-1,-1), 7), ("LEFTPADDING", (0,0),(-1,-1), 8), ("RIGHTPADDING", (0,0),(-1,-1), 8), ])) story.append(banner) story.append(Spacer(1, 3*mm)) # Session info strip s_info = ParagraphStyle("info", fontName="Helvetica", fontSize=8.5, textColor=DARK, leading=12) info = Table( [[Paragraph("<b>Date:</b> ______________________", s_info), Paragraph("<b>Patient / Client:</b> ________________________________", s_info), Paragraph("<b>Setting:</b> ___________________", s_info), Paragraph("<b>Clinician:</b> _________________", s_info)]], colWidths=[CONTENT_W*0.18, CONTENT_W*0.37, CONTENT_W*0.22, CONTENT_W*0.23], ) info.setStyle(TableStyle([ ("BACKGROUND", (0,0),(-1,-1), TEAL_LIGHT), ("BOX", (0,0),(-1,-1), 0.5, TEAL), ("TOPPADDING", (0,0),(-1,-1), 5), ("BOTTOMPADDING", (0,0),(-1,-1), 5), ("LEFTPADDING", (0,0),(-1,-1), 6), ("RIGHTPADDING", (0,0),(-1,-1), 4), ("VALIGN", (0,0),(-1,-1), "MIDDLE"), ])) story.append(info) story.append(Spacer(1, 3*mm)) hdr_style = ParagraphStyle("hdr", fontName="Helvetica-Bold", fontSize=8, textColor=TEAL, leading=11) col_hdr = Table( [["", Paragraph("ITEM", hdr_style), Paragraph("NOTES / CLINICAL REMINDERS", hdr_style)]], colWidths=[COL_CHECK, COL_ITEM, COL_NOTE], ) col_hdr.setStyle(TableStyle([ ("BOTTOMPADDING", (0,0),(-1,-1), 2), ("LEFTPADDING", (0,0),(-1,-1), 2), ])) story.append(col_hdr) story.append(HRFlowable(width="100%", thickness=0.75, color=TEAL)) story.append(Spacer(1, 1.5*mm)) story.append(build_section("1. ASSESSMENT & SCREENING TOOLS", [ ("Pulse oximeter", "Monitor SpO2 throughout; drop \u22652% during a trial may indicate aspiration"), ("Stethoscope (flat diaphragm)", "Cervical auscultation \u2014 place on thyroid cartilage; note subglottic air release & epiglottic movement"), ("Penlight / small torch", "Oral cavity, dentition & cranial nerve inspection"), ("Tongue depressors (x10)", "Oral motor / cranial nerve exam; resistance exercises"), ("Gauze squares", "Tongue protrusion testing; bolus handling assessment"), ("Gloves \u2014 nitrile/non-latex (2 pairs+)", "Required for all oral examination"), ("Face mask & apron", "Standard PPE; use for aerosol-risk patients"), ("Graduated cup (30 mL & standard) + 60 mL syringe", "Controlled water swallow test \u2014 30 mL WST linked to pneumonia prediction; 100 mL WST measures speed & capacity"), ("Stopwatch / timer", "WST: record total time, swallow count & volume per swallow"), ])) story.append(build_section("2. VALIDATED OUTCOME MEASURES & DOCUMENTATION", [ ("EAT-10 form", "Patient-reported 10-item screen; score \u22653 = abnormal, warrants further assessment"), ("GUSS \u2014 Gugging Swallowing Screen", "Validated bedside screen; semi-solid tested first, then liquid"), ("MASA form", "Mann Assessment of Swallowing Ability \u2014 detailed 24-item clinical rating"), ("FOIS reference card", "Functional Oral Intake Scale Levels 1\u20137 \u2014 quantifies level of oral intake"), ("PSS-HN reference card", "Performance Status Scale for Head & Neck Cancer"), ("MEOF-II / McGill observation sheet", "Validated mealtime observation tool; use for dementia / learning disability patients"), ("Penetration-Aspiration Scale (PAS) card", "Quick reference for documenting instrumental findings (Scores 1\u20138)"), ("SOAP note / progress forms or tablet", "Document findings, diet recommendations & follow-up plan"), ("MBSS / FEES referral forms", "Escalate when silent aspiration suspected or CSE is inconclusive"), ])) story.append(build_section("3. FOOD & LIQUID TRIAL SUPPLIES", [ ("Thickening agent \u2014 xanthan gum-based", "e.g. Resource ThickenUp Clear. Prepare IDDSI Levels 1 (slightly thick) to 4 (extremely thick)"), ("Small cups (30 mL & standard size)", None), ("Teaspoons & tablespoons", "Begin with spoon trials before cup sip where aspiration risk is high"), ("Standard straws & cut straws", "Cut straw limits sip volume for more controlled trials"), ("60 mL syringes (x2)", "Controlled bolus delivery in patients with reduced lip closure"), ("Puree pouches / soft food samples", "e.g. crackers, soft biscuit, smooth puree \u2014 cover IDDSI texture Levels 3\u20136"), ("Sealed still water bottle", None), ])) story.append(build_section("4. ORAL MOTOR & THERAPY TOOLS", [ ("NUK brush / oral stimulation kit", "Sensory and thermal-tactile stimulation of the anterior faucial pillars"), ("Chewy tubes (2\u20133 resistance grades)", "Jaw strengthening; grade resistance progressively"), ("Vibrating oral stimulator (e.g. Z-Vibe)", "Thermal-tactile application; oral alerting prior to swallow trials"), ("Bite blocks", "Jaw stability training; graded jaw opening exercises"), ("Small hand mirror", "Patient biofeedback on lip seal, facial symmetry & laryngeal excursion"), ("Padded tongue depressors", "Isometric tongue press exercises (Iowa Oral Performance Instrument protocol)"), ])) story.append(build_section("5. SAFETY EQUIPMENT", [ ("Suction catheter (portable) OR confirm unit suction location", "Know emergency escalation pathway before beginning any swallowing trials"), ("Emesis basin / sick bowl", None), ("Spare gloves, masks & aprons (x2 sets)", None), ("Hand sanitizer", None), ("Paper towels & wet wipes", None), ])) story.append(build_section("6. PATIENT EDUCATION & CARER MATERIALS", [ ("Safe swallowing posture handouts", "Chin tuck, head rotation/tilt, upright 90\u00b0 positioning; supraglottic swallow technique"), ("IDDSI food & liquid level visual guide", "Patient and carer reference card for home diet modification"), ("Compensatory strategy handout", "Effortful swallow, Mendelsohn manoeuvre, double swallow, Masako manoeuvre"), ("Carer / feeder guidance sheet", "Bite size, pacing, positioning, warning signs to report (coughing, wet voice, fever)"), ("Swallowing anatomy diagram", "Explains oral/pharyngeal/oesophageal stages to patient & family"), ])) # Clinical reminder box story.append(Spacer(1, 2*mm)) reminder = Table( [[Paragraph("CLINICAL REMINDER", s_reminder_hd), Paragraph( "The bedside CSE is a screening tool \u2014 silent aspiration cannot be confirmed without MBSS or FEES. " "Escalate if: SpO2 drops \u22652%, wet/gurgly voice post-swallow, coughing on multiple consistencies, or any 2 of: " "abnormal voluntary cough \u2022 absent gag \u2022 dysarthria \u2022 dysphonia \u2022 post-swallow cough / throat-clear / voice change " "(sensitivity 92%, specificity 67% for aspiration \u2014 Scott-Brown\u2019s Otorhinolaryngology, 2018).", s_reminder, )]], colWidths=[30*mm, CONTENT_W - 30*mm], ) reminder.setStyle(TableStyle([ ("BACKGROUND", (0,0),(-1,-1), TEAL_LIGHT), ("BOX", (0,0),(-1,-1), 0.8, TEAL), ("VALIGN", (0,0),(-1,-1), "TOP"), ("TOPPADDING", (0,0),(-1,-1), 5), ("BOTTOMPADDING", (0,0),(-1,-1), 5), ("LEFTPADDING", (0,0),(-1,-1), 6), ("RIGHTPADDING", (0,0),(-1,-1), 6), ])) story.append(reminder) story.append(Spacer(1, 2.5*mm)) story.append(HRFlowable(width="100%", thickness=0.5, color=TEAL)) story.append(Spacer(1, 1.5*mm)) story.append(Paragraph( "Swallowing Therapist Session Preparation Checklist \u2022 " "Based on clinical dysphagia practice & Scott-Brown\u2019s Otorhinolaryngology Head & Neck Surgery (2018) \u2022 Review annually", s_footer, )) doc.build(story) print(f"PDF saved: {OUTPUT}") PYEOF echo "File written."
cd /home/daytona/workspace/swallowing-therapist && python generate_checklist.py
Swallowing Therapist Session Checklist
PDF Document · PDF