Single-case rehabilitation reasoning with PhysioRehab

PhysioRehab re-centres physiological measurement around the way rehabilitation reasons about the individual: it anchors measures and goals to the WHO International Classification of Functioning (ICF), detects change with single-case methods, keeps the clinician in the loop, and auto-drafts an ICF-structured progress note.

This vignette walks the whole path on a synthetic case. The numbers below are illustrative and are not clinical advice: PhysioRehab is a research tool for measurement, documentation and clinician-in-the-loop reasoning support, not a medical device, and final judgement always rests with the clinician.

library(PhysioRehab)

1. A synthetic single case

simulate_stroke_gait_case() builds one patient’s episode: an AB single-case design with three baseline sessions and nine intervention sessions, recording comfortable gait speed alongside ICF qualifiers and a Goal Attainment Scaling (GAS) rating.

ep <- simulate_stroke_gait_case()
ep
#> <rehab_episode> patient=PT-0007 | 脳卒中・左片麻痺(慢性期) | design=AB
#>   sessions: 12 (3 baseline / 9 intervention)
#>   goals: 1

An episode is a container of repeated measures; you can also build one by hand with new_rehab_episode() and add_session(), attaching a personal goal with rehab_goal().

2. Detect change defensibly

Rehabilitation compares a person to their own baseline, so change is detected with distribution-free single-case statistics plus a minimal clinically important difference (MCID). sced_analyze() returns the non-overlap of all pairs (NAP), Tau, the baseline-vs-latest change, and whether it clears the MCID.

sced <- sced_analyze(ep, measure = "gait_speed", mcid = 0.16)
sced[c("baseline_mean", "latest", "delta", "nap", "exceeds_mcid")]
#> $baseline_mean
#> [1] 0.4133333
#> 
#> $latest
#> [1] 0.66
#> 
#> $delta
#> [1] 0.2466667
#> 
#> $nap
#> [1] 1
#> 
#> $exceeds_mcid
#> [1] TRUE

The ICF qualifiers (0 = no problem … 4 = complete problem; lower is better) are tracked per code. Improvement means the qualifier falls:

icf_change(ep, "d450")   # walking
#> $code
#> [1] "d450"
#> 
#> $from
#> [1] 3
#> 
#> $to
#> [1] 2
#> 
#> $improved
#> [1] 1
icf_change(ep, "b735")   # muscle tone / spasticity
#> $code
#> [1] "b735"
#> 
#> $from
#> [1] 3
#> 
#> $to
#> [1] 3
#> 
#> $improved
#> [1] 0

3. Keep the clinician in the loop

The clinician states an expectation; evaluate_hypothesis() reports, item by item, whether the evidence supports it – and honestly flags what it does not.

hyp <- rehab_hypothesis(
  "task-oriented training improves gait",
  expect_speed_mcid = TRUE,
  expect_icf = c(d450 = 1, b735 = 1)
)
reasoning <- evaluate_hypothesis(ep, hyp, sced)
reasoning$overall
#> [1] "部分的に支持 (partial)"
for (it in reasoning$items) {
  mark <- if (is.na(it$supported)) "-" else if (it$supported) "OK" else "NO"
  cat(sprintf("[%s] %s\n", mark, it$claim))
}
#> [OK] gait_speed がMCID(0.16)を超えて改善
#> [OK] ICF d450 が1段階以上改善
#> [NO] ICF b735 が1段階以上改善

4. Visualise the trajectory

plot_trajectory(ep, mcid = 0.16, ylab = "comfortable gait speed (m/s)")

5. Draft the progress note

The adoption hook is workflow: the tool drafts the ICF-structured progress note the therapist already has to write, so the measurement and analysis ride along.

note <- draft_progress_note(ep, sced, reasoning)
cat(substr(note, 1, 400))
#> # リハビリテーション経過記録(自動下書き)
#> 
#> - **患者**: PT-0007 **病態**: 脳卒中・左片麻痺(慢性期) **単一事例計画**: AB
#> - **評価期間**: 2026-04-06 〜 2026-05-06(全12回:基準3/介入9)
#> 
#> ## 活動(ICF d:生活レベルの主要アウトカム)
#> - **快適歩行速度**:基準平均 0.41 → 最新 0.66 m/s(Δ0.25)。**MCIDを超える臨床的に意味のある改善**。
#> - 単一事例効果量 **NAP=1.00(大きい効果)**、Tau=1.00。2SD帯超えの介入点 4/9。
#>   (MCID=0.16 m/s を判定基準に使用)
#> - d450 歩行:重度 → 中等度(qualifier 3→2)
#> - d4500 短距離歩行:重度 → 中等度(qualifier 3→2)
#> 
#> ## 心身機能(ICF b:機能障害レ

rehab_workflow() runs all of the above in one call (single-case analysis, hypothesis evaluation, trajectory plot and drafted note), writing the artefacts into out_dir:

res <- rehab_workflow(ep, hyp, out_dir = tempdir())
names(res)
#> [1] "sced"        "reasoning"   "report"      "fall_risk"   "plot_file"  
#> [6] "report_file"

6. Capacity vs performance (cross-modal ICF constructs)

Rehabilitation lives in the gap between what a person can do in the clinic (capacity) and what they actually do at home (performance). An icf_construct unifies heterogeneous measures on one ICF code by mapping each to the 0–4 qualifier via ascending cut-points.

cc <- new_icf_construct("d450")
cc <- add_icf_measure(cc, "barthel_walk", value = 10,
                      qualifier_type = "capacity", modality = "scale",
                      cutpoints = c(2, 5, 8, 12))
cc <- add_icf_measure(cc, "steps_per_day", value = 1800,
                      qualifier_type = "performance", modality = "sensor",
                      cutpoints = c(1000, 3000, 6000, 9000))
capacity_performance_gap(cc)
#> $code
#> [1] "d450"
#> 
#> $title
#> [1] "d450 Walking"
#> 
#> $capacity
#> [1] 1
#> 
#> $performance
#> [1] 3
#> 
#> $gap
#> [1] 2
#> 
#> $interpretation
#> [1] "実行が能力を下回る(できるのにしていない=環境・行動要因の可能性)"

7. What the ecosystem can measure

adl_coverage_summary() reports, for each activity of daily living, how many modalities can measure it and whether both the capacity and performance qualifiers are covered.

head(adl_coverage_summary())
#>   code                 title n_modalities has_capacity has_performance
#> 1 d450               Walking            5         TRUE            TRUE
#> 2 d445      Hand and arm use            4         TRUE            TRUE
#> 3 d550                Eating            4         TRUE            TRUE
#> 4 d520 Caring for body parts            3         TRUE            TRUE
#> 5 d540              Dressing            3         TRUE            TRUE
#> 6 d560              Drinking            3         TRUE            TRUE
#>   validated_performance multimodal
#> 1                  TRUE       TRUE
#> 2                  TRUE       TRUE
#> 3                 FALSE       TRUE
#> 4                  TRUE       TRUE
#> 5                 FALSE       TRUE
#> 6                  TRUE       TRUE

Where to go next

  • Single-case statistics come from PhysioAppKit (the engine behind sced_analyze()).
  • The ICF ontology is served by PhysioAnnotationHub (icf_for_measure()).
  • Real signals feed the episode through PhysioMoCap (add_session_from_mocap()) and PhysioEMG (add_session_from_emg()).
  • ?PhysioRehab lists every entry point grouped by task.