| Title: | ICF-Native Single-Case Clinical-Reasoning Tools for Rehabilitation |
|---|---|
| Description: | Re-centres physiological measurement around the way rehabilitation reasons about the individual: International Classification of Functioning (ICF) semantics, individualised goal-referenced outcomes (Goal Attainment Scaling), single-case change detection that fuses quantitative signals with qualitative ICF qualifiers, a hypothesis-to-evidence reasoning scaffold that keeps the clinician in the loop, and an auto-drafted, ICF-structured progress note. Adapters ingest real signals from the ecosystem (markerless gait from 'PhysioMoCap', muscle fatigue from 'PhysioEMG'); the ICF layer resolves against 'PhysioAnnotationHub'; single-case statistics come from 'PhysioAppKit'. The worked instance is stroke hemiplegic gait; the framework is condition-agnostic. A research tool with synthetic examples, not a medical device: outputs are clinician-in-the-loop measurement, documentation and reasoning support, never diagnosis. |
| Authors: | Yusuke Matsui [aut, cre] |
| Maintainer: | Yusuke Matsui <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.5.2 |
| Built: | 2026-10-03 14:04:02 UTC |
| Source: | https://github.com/x-biosignal/PhysioRehab |
Records one modality's view of the domain, tagged as 'capacity' (a standardised/clinic measure – an ordinal scale total, a Rasch person measure, a performance test) or 'performance' (a free-living / real-world measure). The value is mapped to the ICF 0-4 qualifier either directly ('qualifier') or from 'cutpoints' (direction-aware), so heterogeneous measures become comparable. 'value' and 'date' may be vectors to add a whole longitudinal stream at once.
add_icf_measure( construct, source, value, qualifier_type = c("capacity", "performance"), modality = c("scale", "rasch", "performance_test", "sensor", "self_report"), date = NA, unit = NA_character_, direction = c("higher_better", "higher_worse"), qualifier = NULL, cutpoints = NULL )add_icf_measure( construct, source, value, qualifier_type = c("capacity", "performance"), modality = c("scale", "rasch", "performance_test", "sensor", "self_report"), date = NA, unit = NA_character_, direction = c("higher_better", "higher_worse"), qualifier = NULL, cutpoints = NULL )
construct |
an 'icf_construct'. |
source |
short measure id, e.g. '"barthel"', '"steps_per_day"'. |
value |
numeric measure value(s). |
qualifier_type |
'"capacity"' or '"performance"'. |
modality |
'"scale"', '"rasch"', '"performance_test"', '"sensor"' or '"self_report"'. |
date |
measurement date(s) (Date or coercible); recycled to 'value'. |
unit |
optional measure unit. |
direction |
'"higher_better"' (default) or '"higher_worse"'. |
qualifier |
optional explicit ICF qualifier(s) 0-4 (overrides 'cutpoints'). |
cutpoints |
optional length-4 ascending cut-points mapping 'value' to the 0-4 qualifier. |
the updated 'icf_construct'.
[capacity_performance_gap()], [icf_construct_trajectory()]
cc <- new_icf_construct("d450") # A clinic scale (capacity) and a free-living sensor metric (performance), # each mapped to the ICF 0-4 qualifier via ascending cut-points. 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)) cccc <- new_icf_construct("d450") # A clinic scale (capacity) and a free-living sensor metric (performance), # each mapped to the ICF 0-4 qualifier via ascending cut-points. 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)) cc
Convenience adapter: pulls one aggregate metric from a 'PhysioWearable::summarizeFreeLiving()' result and records it as the 'performance' qualifier of the construct. Works structurally, so PhysioWearable need not be attached.
add_performance_from_freeliving( construct, fl, metric, cutpoints, date = NA, source = metric )add_performance_from_freeliving( construct, fl, metric, cutpoints, date = NA, source = metric )
construct |
an 'icf_construct'. |
fl |
a 'freeliving_summary' (or any list with an 'aggregate' element). |
metric |
aggregate field name, e.g. '"mvpa_min"' or '"steps"'. |
cutpoints |
length-4 ascending cut-points mapping the metric to the 0-4 qualifier (higher metric = better performance). |
date |
measurement date. |
source |
measure id recorded (defaults to 'metric'). |
the updated 'icf_construct'.
[add_icf_measure()]
cc <- new_icf_construct("d450") # Any list with an `aggregate` element works; here one free-living metric. fl <- list(aggregate = list(steps = 2400)) cc <- add_performance_from_freeliving(cc, fl, metric = "steps", cutpoints = c(1000, 3000, 6000, 9000)) cccc <- new_icf_construct("d450") # Any list with an `aggregate` element works; here one free-living metric. fl <- list(aggregate = list(steps = 2400)) cc <- add_performance_from_freeliving(cc, fl, metric = "steps", cutpoints = c(1000, 3000, 6000, 9000)) cc
Record one therapy session
add_session( ep, date, phase, gait_speed = NA, cadence = NA, symmetry = NA, measures = list(), icf = list(), gas = list(), observation = "" )add_session( ep, date, phase, gait_speed = NA, cadence = NA, symmetry = NA, measures = list(), icf = list(), gas = list(), observation = "" )
ep |
a 'rehab_episode'. |
date |
session date (Date or string). |
phase |
"baseline" or "intervention". |
gait_speed |
comfortable gait speed (m/s), the primary measure. |
cadence, symmetry
|
secondary quantitative measures (optional). |
measures |
named list of additional quantitative measures (arbitrary columns), e.g. 'list(knee_rom = 47.2)' for signal-derived measures. |
icf |
named list of ICF qualifiers, e.g. 'list(b770 = 3, d450 = 3)'. |
gas |
named list of GAS ratings keyed by goal id, e.g. 'list(G1 = -1)'. |
observation |
clinician's free-text qualitative note. |
the updated 'rehab_episode'.
ep <- new_rehab_episode("PT-01", "stroke, left hemiplegia") ep <- add_session(ep, "2026-04-06", "baseline", gait_speed = 0.41, icf = list(d450 = 3), gas = list(G1 = -1)) epep <- new_rehab_episode("PT-01", "stroke, left hemiplegia") ep <- add_session(ep, "2026-04-06", "baseline", gait_speed = 0.41, icf = list(d450 = 3), gas = list(G1 = -1)) ep
Append a rehab session whose measures come from a real EMG recording
add_session_from_emg(ep, date, phase, emg_pe, observation = "")add_session_from_emg(ep, date, phase, emg_pe, observation = "")
ep |
a 'rehab_episode'. |
date |
session date (Date or string). |
phase |
"baseline" or "intervention". |
emg_pe |
a PhysioExperiment of raw EMG. |
observation |
optional clinician note (auto-filled if empty). |
the updated 'rehab_episode', with real 'mdf_slope' / 'emg_rms'.
## Not run: ep <- new_rehab_episode("PT-01", "stroke, left hemiplegia") emg_pe <- PhysioEMG::make_emg_fatigue() ep <- add_session_from_emg(ep, "2026-04-06", "baseline", emg_pe) ## End(Not run)## Not run: ep <- new_rehab_episode("PT-01", "stroke, left hemiplegia") emg_pe <- PhysioEMG::make_emg_fatigue() ep <- add_session_from_emg(ep, "2026-04-06", "baseline", emg_pe) ## End(Not run)
Append a rehab session whose measures come from a real OpenPose recording
add_session_from_mocap( ep, date, phase, openpose_dir, side = "R", observation = "" )add_session_from_mocap( ep, date, phase, openpose_dir, side = "R", observation = "" )
ep |
a 'rehab_episode'. |
date, phase
|
session date and phase. |
openpose_dir |
directory of OpenPose JSON frames for this visit. |
side |
"R"/"L". |
observation |
optional clinician note (auto-filled if empty). |
the updated 'rehab_episode', with real 'knee_rom' / 'knee_smoothness'.
## Not run: ep <- new_rehab_episode("PT-01", "stroke, left hemiplegia") ep <- add_session_from_mocap(ep, "2026-04-06", "baseline", openpose_dir = "path/to/openpose_frames") ## End(Not run)## Not run: ep <- new_rehab_episode("PT-01", "stroke, left hemiplegia") ep <- add_session_from_mocap(ep, "2026-04-06", "baseline", openpose_dir = "path/to/openpose_frames") ## End(Not run)
What the ecosystem can measure for each ADL: the ICF Activities & Participation code, the measurement modality ('scale', 'performance_test', 'kinematics', 'emg', 'dexterity', 'sensor_freeliving', 'sensor_har'), the ICF qualifier it informs ('capacity' for standardised/clinic measures, 'performance' for real-world ones), and the function that provides it.
adl_coverage(code = NULL, qualifier = NULL)adl_coverage(code = NULL, qualifier = NULL)
code |
Optional ICF code(s) to filter to. |
qualifier |
Optional '"capacity"'/'"performance"' filter. |
a data.frame with 'code', 'title', 'modality', 'qualifier', 'method', 'package' and 'status' ('"validated"' = proven on real data or an established/verified measure; '"supported"' = pipeline + ICF mapping ready but not yet validated on a task-specific dataset).
[adl_coverage_summary()], [construct_coverage()]
adl_coverage("d640")adl_coverage("d640")
Summarises, for each ADL code in the registry, how many modalities measure it and whether it is covered on the capacity and the performance qualifier – and hence whether it is genuinely multi-modal.
adl_coverage_summary()adl_coverage_summary()
a data.frame 'code', 'title', 'n_modalities', 'has_capacity', 'has_performance', 'validated_performance' (at least one performance method proven on real data, not merely pipeline-ready) and 'multimodal' (both qualifiers), with an attribute 'overall' giving ecosystem-level percentages including 'pct_validated_performance'.
[adl_coverage()]
adl_coverage_summary()adl_coverage_summary()
The signature rehabilitation discrepancy: how much a person's real-world doing (performance) falls short of what they can do in a standardised setting (capacity), both on the ICF 0-4 qualifier. A positive gap means performance is worse than capacity – the person does less than they are able, pointing to environmental or behavioural barriers rather than impairment.
capacity_performance_gap(construct, when = c("latest", "mean"))capacity_performance_gap(construct, when = c("latest", "mean"))
construct |
an 'icf_construct' carrying both a capacity and a performance qualifier. |
when |
'"latest"' (default, most recent of each) or '"mean"'. |
a list: 'code', 'title', 'capacity', 'performance', 'gap' (performance - capacity) and a text 'interpretation'.
[add_icf_measure()]
cc <- new_icf_construct("d450") cc <- add_icf_measure(cc, "barthel_walk", 10, "capacity", "scale", cutpoints = c(2, 5, 8, 12)) cc <- add_icf_measure(cc, "steps_per_day", 1800, "performance", "sensor", cutpoints = c(1000, 3000, 6000, 9000)) capacity_performance_gap(cc)cc <- new_icf_construct("d450") cc <- add_icf_measure(cc, "barthel_walk", 10, "capacity", "scale", cutpoints = c(2, 5, 8, 12)) cc <- add_icf_measure(cc, "steps_per_day", 1800, "performance", "sensor", cutpoints = c(1000, 3000, 6000, 9000)) capacity_performance_gap(cc)
For the domain of one [new_icf_construct], reports which measurement modalities the ecosystem offers (from [adl_coverage()]) and which qualifiers the construct has actually populated, flagging the gaps – the modalities that are available but not yet used for this individual.
construct_coverage(construct)construct_coverage(construct)
construct |
an 'icf_construct'. |
a list: 'code', 'title', 'has_capacity'/'has_performance' (in the construct), 'available' (registry rows for the code) and 'missing_qualifiers' (registry qualifiers with an available method but no observation yet).
[adl_coverage()], [capacity_performance_gap()]
cc <- new_icf_construct("d450") cc <- add_icf_measure(cc, "barthel_walk", 10, "capacity", "scale", cutpoints = c(2, 5, 8, 12)) construct_coverage(cc)$missing_qualifierscc <- new_icf_construct("d450") cc <- add_icf_measure(cc, "barthel_walk", 10, "capacity", "scale", cutpoints = c(2, 5, 8, 12)) construct_coverage(cc)$missing_qualifiers
Draft an ICF-structured progress note from an analysed episode
draft_progress_note( ep, sced, reasoning = NULL, mcid = sced$mcid, constructs = NULL, fall_risk = NULL )draft_progress_note( ep, sced, reasoning = NULL, mcid = sced$mcid, constructs = NULL, fall_risk = NULL )
ep |
a 'rehab_episode'. |
sced |
result of [sced_analyze]. |
reasoning |
optional result of [evaluate_hypothesis]. |
mcid |
MCID used (for the record). |
constructs |
optional list of [new_icf_construct] objects; when supplied, a cross-modal capacity-vs-performance section is added. |
fall_risk |
optional result of [fall_risk_from_episode()]; when supplied, an integrated fall-risk section is added. |
a single Markdown string (also the object printed in the demo).
ep <- simulate_stroke_gait_case() sced <- sced_analyze(ep) note <- draft_progress_note(ep, sced) cat(substr(note, 1, 160))ep <- simulate_stroke_gait_case() sced <- sced_analyze(ep) note <- draft_progress_note(ep, sced) cat(substr(note, 1, 160))
Real muscle-fatigue / amplitude measures from an EMG recording (via PhysioEMG)
emg_fatigue_measures(emg_pe, feature = c("mdf", "mnf"))emg_fatigue_measures(emg_pe, feature = c("mdf", "mnf"))
emg_pe |
a PhysioExperiment holding raw EMG (e.g. from PhysioIO, or the realistic 'PhysioEMG::make_emg_fatigue()' model). |
feature |
"mdf" (median) or "mnf" (mean) frequency. |
list: mdf_slope_hz_per_min, mdf_norm_slope_pct, fit_r2, rms.
## Not run: # Requires PhysioEMG; emg_pe is a PhysioExperiment holding raw EMG. emg_pe <- PhysioEMG::make_emg_fatigue() emg_fatigue_measures(emg_pe) ## End(Not run)## Not run: # Requires PhysioEMG; emg_pe is a PhysioExperiment holding raw EMG. emg_pe <- PhysioEMG::make_emg_fatigue() emg_fatigue_measures(emg_pe) ## End(Not run)
Evaluate a hypothesis against the episode's evidence
evaluate_hypothesis(ep, hyp, sced)evaluate_hypothesis(ep, hyp, sced)
ep |
a 'rehab_episode'. |
hyp |
a 'rehab_hypothesis'. |
sced |
the result of [sced_analyze] on the primary measure. |
list(verdict, overall, items) where each item is one checked expectation with its supported/refuted status and the evidence used.
ep <- simulate_stroke_gait_case() hyp <- rehab_hypothesis("task-oriented training improves gait", expect_icf = c(d450 = 1)) sced <- sced_analyze(ep) evaluate_hypothesis(ep, hyp, sced)$overallep <- simulate_stroke_gait_case() hyp <- rehab_hypothesis("task-oriented training improves gait", expect_icf = c(d450 = 1)) sced <- sced_analyze(ep) evaluate_hypothesis(ep, hyp, sced)$overall
Builds [fall_risk_index()] domain inputs from a ‘rehab_episode'’s latest (or a chosen) session, mapping the standard domain names out of the session's quantitative 'measures' columns (as stored by [add_session()]). Returns 'NULL' if the session holds none of the fall-risk domains, so it composes cleanly into [draft_progress_note()] / [rehab_workflow()].
fall_risk_from_episode( ep, session = NULL, reference = NULL, weights = NULL, cutpoints = NULL, strata_labels = NULL, domain_map = c(sway = "sway", gait_variability = "gait_variability", tug = "tug", strength = "strength", reaction_time = "reaction_time", vision = "vision", proprioception = "proprioception") )fall_risk_from_episode( ep, session = NULL, reference = NULL, weights = NULL, cutpoints = NULL, strata_labels = NULL, domain_map = c(sway = "sway", gait_variability = "gait_variability", tug = "tug", strength = "strength", reaction_time = "reaction_time", vision = "vision", proprioception = "proprioception") )
ep |
A 'rehab_episode' (see [new_rehab_episode()]). |
session |
Session number to use (default: the latest session). |
reference, weights, cutpoints, strata_labels
|
Passed to [fall_risk_index()]. |
domain_map |
Named character vector mapping fall-risk domains to session column names (default: identity for 'sway', 'gait_variability', 'tug', 'strength', 'reaction_time', 'vision', 'proprioception'). |
A 'fall_risk_index', or 'NULL' if no domain columns are present.
[fall_risk_index()], [draft_progress_note()]
# Synthetic domain summaries recorded on one session (not clinical advice). ep <- new_rehab_episode("PT-01", "stroke, left hemiplegia") ep <- add_session(ep, "2026-04-06", "baseline", measures = list(sway = 12, tug = 18, strength = 38)) fall_risk_from_episode(ep)# Synthetic domain summaries recorded on one session (not clinical advice). ep <- new_rehab_episode("PT-01", "stroke, left hemiplegia") ep <- add_session(ep, "2026-04-06", "baseline", measures = list(sway = 12, tug = 18, strength = 38)) fall_risk_from_episode(ep)
Combines per-domain fall-risk summaries into a single index. Each argument is a scalar summary from the corresponding validated measure (e.g. 'sway' from [PhysioMoCap::swayMetrics()] path length, 'gait_variability' from a [PhysioMoCap::summarizeGaitParameters()] CV, 'tug' from [PhysioClinical::scoreTUG()], 'strength' from [PhysioClinical::scoreMRCSum()]). Omit a domain by leaving it 'NA'.
fall_risk_index( sway = NA_real_, gait_variability = NA_real_, tug = NA_real_, strength = NA_real_, reaction_time = NA_real_, vision = NA_real_, proprioception = NA_real_, reference = NULL, weights = NULL, direction = NULL, cutpoints = NULL, strata_labels = NULL, method = c("zscore_composite", "ppa"), ppa_coef = NULL )fall_risk_index( sway = NA_real_, gait_variability = NA_real_, tug = NA_real_, strength = NA_real_, reaction_time = NA_real_, vision = NA_real_, proprioception = NA_real_, reference = NULL, weights = NULL, direction = NULL, cutpoints = NULL, strata_labels = NULL, method = c("zscore_composite", "ppa"), ppa_coef = NULL )
sway, gait_variability, tug, strength, reaction_time, vision, proprioception
|
Per-domain scalar summaries (any may be 'NA' to omit). |
reference |
A 'data.frame' of the same-named domain columns measured in a healthy reference sample; required for the '"zscore_composite"' method (each domain is z-standardised against it, sign-aligned so higher = more risk). Without it the composite is 'NA'. |
weights |
Optional named per-domain weights for the composite (default equal). |
direction |
Optional named '+1'/'-1' overrides of the default domain orientation ('+1' = higher is riskier). |
cutpoints |
Optional ascending composite cut-points defining risk strata; supply only from validated fall-outcome data. Default 'NULL' = uncalibrated (no stratum). |
strata_labels |
Optional labels for the 'length(cutpoints) + 1' strata. |
method |
'"zscore_composite"' (default) or '"ppa"' (needs 'ppa_coef'). |
ppa_coef |
For 'method = "ppa"', a named numeric vector of the published PPA discriminant weights per domain (plus optional 'intercept'); not bundled. |
An S3 'fall_risk_index': 'domains', sign-aligned 'z', 'composite', 'percentile' (normal, when calibrated by a reference), 'stratum', 'method' and 'calibrated'.
Lord SR, Menz HB, Tiedemann A (2003). A physiological profile approach to falls risk assessment and prevention. *Phys Ther* 83:237-252.
[PhysioClinical::scoreTUG()], [PhysioClinical::scoreBerg()]
ref <- data.frame(sway = c(5, 6, 4, 5, 6), gait_variability = c(3, 4, 3, 5, 4), tug = c(8, 9, 7, 10, 8), strength = c(55, 52, 58, 50, 56)) fall_risk_index(sway = 12, gait_variability = 10, tug = 18, strength = 38, reference = ref)ref <- data.frame(sway = c(5, 6, 4, 5, 6), gait_variability = c(3, 4, 3, 5, 4), tug = c(8, 9, 7, 10, 8), strength = c(55, 52, 58, 50, 56)) fall_risk_index(sway = 12, gait_variability = 10, tug = 18, strength = 38, reference = ref)
ICF catalogue (stroke gait core-set subset)
icf_catalog()icf_catalog()
A data.frame of ICF codes: 'code', 'component', 'title_en', 'title_ja'.
icf_catalog()icf_catalog()
ICF qualifier change across an episode (improvement = qualifier decreases)
icf_change(ep, code)icf_change(ep, code)
ep |
a 'rehab_episode'. |
code |
ICF code, e.g. "d450". |
list(code, from, to, improved) where 'improved' > 0 means the qualifier fell (clinical improvement). NULL if the code was never recorded.
ep <- simulate_stroke_gait_case() icf_change(ep, "d450")ep <- simulate_stroke_gait_case() icf_change(ep, "d450")
Time-ordered trajectory of one qualifier stream (feeds single-case analysis)
icf_construct_trajectory( construct, qualifier_type = c("capacity", "performance") )icf_construct_trajectory( construct, qualifier_type = c("capacity", "performance") )
construct |
an 'icf_construct'. |
qualifier_type |
'"capacity"' or '"performance"'. |
a data.frame('date', 'value', 'qualifier') ordered by date, ready to pass to [PhysioAppKit::nonoverlap_analyze()] or the rehab SCED tools.
[capacity_performance_gap()]
cc <- new_icf_construct("d450") cc <- add_icf_measure(cc, "steps_per_day", value = c(1500, 2200, 3100), qualifier_type = "performance", modality = "sensor", date = as.Date("2026-04-06") + c(0, 7, 14), cutpoints = c(1000, 3000, 6000, 9000)) icf_construct_trajectory(cc, "performance")cc <- new_icf_construct("d450") cc <- add_icf_measure(cc, "steps_per_day", value = c(1500, 2200, 3100), qualifier_type = "performance", modality = "sensor", date = as.Date("2026-04-06") + c(0, 7, 14), cutpoints = c(1000, 3000, 6000, 9000)) icf_construct_trajectory(cc, "performance")
Uses PhysioAnnotationHub's ICF-linking rules (Cieza 2005) so a measure such as '"gait_speed"' resolves to '"d450"' from the maintained ontology, not a hard-coded table. Signal-derived measures that are not yet in the ontology (e.g. '"knee_rom"') return 'character(0)'; the fix is to register the mapping in PhysioAnnotationHub, not to hard-code it here.
icf_for_measure(measure)icf_for_measure(measure)
measure |
a measure / instrument id, e.g. "gait_speed". |
character vector of ICF codes (possibly empty).
# Resolves a measure to ICF code(s); "gait_speed" maps to walking (d450). icf_for_measure("gait_speed")# Resolves a measure to ICF code(s); "gait_speed" maps to walking (d450). icf_for_measure("gait_speed")
ICF body-function / activity qualifiers: 0 no problem .. 4 complete problem. Lower is better; improvement means the qualifier decreases.
icf_qualifier_label(q)icf_qualifier_label(q)
q |
integer qualifier 0..4 (vectorised). |
character labels.
icf_qualifier_label(0:4)icf_qualifier_label(0:4)
Launch the PhysioRehab GUI in a browser
launch_rehab_app(...)launch_rehab_app(...)
... |
passed to [shiny::runApp]. |
## Not run: launch_rehab_app() ## End(Not run)## Not run: launch_rehab_app() ## End(Not run)
Reads the COCO-18 OpenPose JSON frames, builds a PhysioExperiment, runs [PhysioMoCap::poseFix], and derives real knee-kinematic measures for one side.
mocap_gait_measures(openpose_dir, side = c("R", "L"), fps = 30)mocap_gait_measures(openpose_dir, side = c("R", "L"), fps = 30)
openpose_dir |
directory of 'openpose_data<N>.json' frames (COCO-18 flat). |
side |
"R" or "L". |
fps |
frame rate (Hz). |
a list of real measures: knee_rom (deg), knee_smoothness_fixed and _raw (mean |2nd diff| of the knee angle, after / before poseFix), frames, flagged_fraction, leg_swaps.
## Not run: # Requires PhysioMoCap and a directory of COCO-18 OpenPose JSON frames. m <- mocap_gait_measures("path/to/openpose_frames", side = "R") m$knee_rom ## End(Not run)## Not run: # Requires PhysioMoCap and a directory of COCO-18 OpenPose JSON frames. m <- mocap_gait_measures("path/to/openpose_frames", side = "R") m$knee_rom ## End(Not run)
Create a cross-modal ICF construct for one Activity/Participation domain
new_icf_construct(code, title = NULL)new_icf_construct(code, title = NULL)
code |
an ICF code, e.g. '"d450"' (walking) or '"d550"' (eating). |
title |
optional human title; resolved from the ontology (PhysioAnnotationHub, else the local catalogue) when omitted. |
an empty object of class 'icf_construct'.
[add_icf_measure()], [capacity_performance_gap()]
new_icf_construct("d450")new_icf_construct("d450")
Create an empty rehabilitation episode (single-case)
new_rehab_episode(patient_id, condition, design = "AB", goals = list())new_rehab_episode(patient_id, condition, design = "AB", goals = list())
patient_id |
de-identified patient id. |
condition |
free-text condition, e.g. "stroke, left hemiplegia". |
design |
single-case design label, e.g. "AB". |
goals |
list of [rehab_goal] objects. |
an object of class 'rehab_episode'.
new_rehab_episode("PT-01", "stroke, left hemiplegia", design = "AB")new_rehab_episode("PT-01", "stroke, left hemiplegia", design = "AB")
Plot a single-case trajectory with phase line, 2-SD band and MCID target
plot_trajectory( ep, measure = "gait_speed", mcid = 0.16, file = NULL, ylab = NULL )plot_trajectory( ep, measure = "gait_speed", mcid = 0.16, file = NULL, ylab = NULL )
ep |
a 'rehab_episode'. |
measure |
primary measure column. |
mcid |
MCID (drawn as the target line above baseline mean). |
file |
optional PNG path; if NULL, draws to the current device. |
ylab |
y-axis label. |
(invisibly) the file path, or NULL.
ep <- simulate_stroke_gait_case() # Draw to the current graphics device; pass `file` to save a PNG instead. plot_trajectory(ep, mcid = 0.16)ep <- simulate_stroke_gait_case() # Draw to the current graphics device; pass `file` to save a PNG instead. plot_trajectory(ep, mcid = 0.16)
Build the PhysioRehab clinician prototype GUI
rehab_app()rehab_app()
a Shiny app object (pass to [shiny::runApp] or print to launch).
## Not run: # Requires shiny and bslib. app <- rehab_app() shiny::runApp(app) ## End(Not run)## Not run: # Requires shiny and bslib. app <- rehab_app() shiny::runApp(app) ## End(Not run)
Define a rehabilitation goal (ICF-linked, GAS-scaled)
rehab_goal(id, statement, icf_codes, baseline, target, unit, gas = NULL)rehab_goal(id, statement, icf_codes, baseline, target, unit, gas = NULL)
id |
short identifier, e.g. "G1". |
statement |
free-text clinical goal (the patient's own words are ideal). |
icf_codes |
character vector of ICF codes this goal maps to. |
baseline, target
|
numeric baseline and target on the primary measure. |
unit |
measurement unit, e.g. "m/s". |
gas |
optional named character vector describing GAS levels "-2","-1","0","+1","+2". |
an object of class 'rehab_goal'.
# Synthetic, goal-referenced target on a personal measure (not clinical advice). rehab_goal("G1", "Walk 10 m indoors unaided", icf_codes = c("d450", "d4500"), baseline = 0.40, target = 0.70, unit = "m/s")# Synthetic, goal-referenced target on a personal measure (not clinical advice). rehab_goal("G1", "Walk 10 m indoors unaided", icf_codes = c("d450", "d4500"), baseline = 0.40, target = 0.70, unit = "m/s")
State a clinical hypothesis about expected change
rehab_hypothesis(statement, expect_speed_mcid = TRUE, expect_icf = c(d450 = 1))rehab_hypothesis(statement, expect_speed_mcid = TRUE, expect_icf = c(d450 = 1))
statement |
free-text clinical hypothesis. |
expect_speed_mcid |
logical: expect the primary measure to exceed MCID. |
expect_icf |
named integer vector of ICF codes -> minimum expected qualifier improvement, e.g. 'c(d450 = 1, b735 = 1)'. |
an object of class 'rehab_hypothesis'.
rehab_hypothesis("task-oriented training improves gait", expect_speed_mcid = TRUE, expect_icf = c(d450 = 1))rehab_hypothesis("task-oriented training improves gait", expect_speed_mcid = TRUE, expect_icf = c(d450 = 1))
Run the full single-case rehab workflow (guided, one call)
rehab_workflow( ep, hypothesis = NULL, measure = "gait_speed", mcid = 0.16, direction = "increase", out_dir = tempdir(), fall_risk_reference = NULL )rehab_workflow( ep, hypothesis = NULL, measure = "gait_speed", mcid = 0.16, direction = "increase", out_dir = tempdir(), fall_risk_reference = NULL )
ep |
a 'rehab_episode'. |
hypothesis |
optional 'rehab_hypothesis'. |
measure |
primary measure column. |
mcid |
MCID for the primary measure. |
direction |
improvement direction. |
out_dir |
directory for the trajectory PNG and progress-note Markdown. |
fall_risk_reference |
optional healthy-reference 'data.frame' passed to [fall_risk_from_episode()] to calibrate the integrated fall-risk composite. |
(invisibly) list(sced, reasoning, report, plot_file, report_file).
ep <- simulate_stroke_gait_case() # Writes the trajectory PNG and progress note into out_dir (here tempdir()). res <- rehab_workflow(ep, out_dir = tempdir()) cat(substr(res$report, 1, 140))ep <- simulate_stroke_gait_case() # Writes the trajectory PNG and progress note into out_dir (here tempdir()). res <- rehab_workflow(ep, out_dir = tempdir()) cat(substr(res$report, 1, 140))
Analyse an episode's primary measure with SCED + MCID (via PhysioAppKit)
sced_analyze( ep, measure = "gait_speed", mcid = 0.16, direction = c("increase", "decrease") )sced_analyze( ep, measure = "gait_speed", mcid = 0.16, direction = c("increase", "decrease") )
ep |
a 'rehab_episode'. |
measure |
column name of the primary quantitative measure. |
mcid |
minimal clinically important difference on that measure. |
direction |
improvement direction. |
a list with NAP, Tau, baseline mean, latest, MCID verdict, 2-SD band.
ep <- simulate_stroke_gait_case() res <- sced_analyze(ep, measure = "gait_speed", mcid = 0.16) res[c("nap", "delta", "exceeds_mcid")]ep <- simulate_stroke_gait_case() res <- sced_analyze(ep, measure = "gait_speed", mcid = 0.16) res[c("nap", "delta", "exceeds_mcid")]
Simulate a stroke hemiplegic-gait single-case episode
simulate_stroke_gait_case(seed = 42)simulate_stroke_gait_case(seed = 42)
seed |
RNG seed for reproducibility. |
a populated 'rehab_episode'.
ep <- simulate_stroke_gait_case() epep <- simulate_stroke_gait_case() ep