FlexTail Sensor Evaluation Series
Quantifying Lumbar and Axial Exposure From Continuous Spine Data
A reproducible explanation of the lumbar-twist exposure model used in the FlexTail HAR study, including feature construction, global normalisation, and interpretation limits.
Published
Research question and data scope
The first analysis asks a deliberately constrained question: given continuous lumbar and axial-rotation signals, how can activities be compared without reducing a recording to one arbitrary threshold crossing? The source dataset is a controlled human activity recognition (HAR) study in which 10 participants performed seven familiar household activities for approximately one minute each: cutting, eating, loading a dishwasher, walking, unloading a dishwasher, vacuuming, and wiping. The sensor records continuous spine kinematics during each task.
The analysis has two units of observation. A sample is one sensor frame. A participant-activity recording is the collection of frames for one person performing one task. The latter is the unit used in the risk scatter and activity-summary plots, so a person with more frames cannot dominate the participant-level comparison merely because their recording is longer.
This is an exposure-description model, not a clinical prediction model. A high value means that the measured posture features were high relative to the reference distribution used by this analysis. It does not establish injury probability, diagnose disease, or replace an occupational risk assessment. The distinction matters especially with a small, controlled sample: the model is useful for transparent comparison and hypothesis generation, not for estimating population prevalence.
The underlying HAR study is described in Walkling, Masch, Sander, and Deserno, Sensors 25(12), 3806 (2025), doi:10.3390/s25123806. The worked examples below reproduce the analysis logic in a form that can be inspected independently.
From a frame to interpretable features
For a recording with $N$ frames, let $b_i$ be the lumbar angle in degrees at frame $i$, and let $r_i$ be the axial twist in degrees. The code converts the radian-valued lumbarAngle and twist channels returned by flexlib before feature extraction. Four features are calculated for each anatomical plane.
The mean represents the central tendency:
$$ \mu_b = \frac{1}{N}\sum_{i=1}^{N} b_i, \qquad \mu_r = \frac{1}{N}\sum_{i=1}^{N} |r_i|. $$
The 90th percentile makes the upper tail visible without letting one extreme frame define the entire recording:
$$ P90_b = Q_{0.90}(b_1, \ldots, b_N), \qquad P90_r = Q_{0.90}(|r_1|, \ldots, |r_N|). $$
Time-above-threshold features quantify the fraction of a task spent in a predefined posture band:
$$ T20_b = 100\frac{1}{N}\sum_{i=1}^{N}\mathbb{1}(b_i > 20^\circ), \qquad T10_r = 100\frac{1}{N}\sum_{i=1}^{N}\mathbb{1}(|r_i| > 10^\circ). $$
Finally, root-mean-square jerk is used as a movement-dynamics proxy. With an assumed sample interval $\Delta t$, the discrete approximation is:
$$ J_b = \sqrt{\frac{1}{N}\sum_{i=1}^{N}\left(\frac{b_{i+1}-2b_i+b_{i-1}}{\Delta t^2}\right)^2}, \qquad J_r = \sqrt{\frac{1}{N}\sum_{i=1}^{N}\left(\frac{r_{i+1}-2r_i+r_{i-1}}{\Delta t^2}\right)^2}. $$
The calculation below is a direct excerpt of the HAR risk pipeline. It uses dt = 1 / 15, so the jerk feature assumes an effective 15 Hz sample interval. That assumption should be replaced with timestamps or the acquisition rate whenever a differently sampled recording is analysed. Otherwise, the jerk magnitude changes with sampling rate rather than only with movement dynamics.
dt = 1 / 15
b = np.degrees(df["lumbarAngle"].values)
tw = np.degrees(df["twist"].values)
lumbar_jerk = np.sqrt(np.mean(np.gradient(np.gradient(b, dt), dt) ** 2))
twist_jerk = np.sqrt(np.mean(np.gradient(np.gradient(tw, dt), dt) ** 2))
row = {
"lumbar_mean": b.mean(),
"lumbar_p90": np.percentile(b, 90),
"lumbar_t20": 100 * np.mean(b > 20),
"lumbar_jerk": lumbar_jerk,
"twist_mean": np.abs(tw).mean(),
"twist_p90": np.percentile(np.abs(tw), 90),
"twist_t10": 100 * np.mean(np.abs(tw) > 10),
"twist_jerk": twist_jerk,
}
Using both a location statistic and a tail statistic avoids a common ambiguity. A recording can have a modest mean lumbar angle but a high $P90_b$ because it contains repeated deep bends. Conversely, a high mean with a modest jerk can describe a prolonged static stoop. These are mechanically different patterns even if a single mean score happened to be equal.
Global normalisation and the composite score
The model uses a single reference scaler fitted across all risk activities rather than fitting a new scale for every activity. For feature $x_j$, the standardised value is:
$$ z_j = \frac{x_j - \mu^{(g)}_j}{\sigma^{(g)}_j}, $$
where $\mu^{(g)}_j$ and $\sigma^{(g)}_j$ are the global mean and standard deviation across the assembled HAR comparison dataset. The four lumbar z-scores are averaged to obtain $\bar z_L$; the four twist z-scores give $\bar z_T$. Each is then mapped from the fixed interval $[-2, 2]$ to $[0, 1]$, with clipping outside that range:
$$ R_L = \operatorname{clip}\left(\frac{\bar z_L + 2}{4}, 0, 1\right), \qquad R_T = \operatorname{clip}\left(\frac{\bar z_T + 2}{4}, 0, 1\right). $$
The composite is the unweighted mean:
$$ R = \frac{R_L + R_T}{2}. $$
This is implemented as follows.
SCORE_Z_LO = -2.0
SCORE_Z_HI = 2.0
z = (df_r[METRIC_COLS_LT] - g_mean) / g_std
def sub_score(columns):
mean_z = z[columns].mean(axis=1)
return ((mean_z - SCORE_Z_LO) / (SCORE_Z_HI - SCORE_Z_LO)).clip(0.0, 1.0)
lumbar_risk = sub_score(LUMBAR_COLS)
twist_risk = sub_score(TWIST_COLS)
composite_risk = (lumbar_risk + twist_risk) / 2
The fixed scale creates comparability within the playbook: $R=0.50$ represents the global mean on this scale, $R=0.75$ corresponds to an average feature profile near $+1$ SD, and $R=1$ is the clipped high end near $+2$ SD. These are analytical tier boundaries, not physiological safety boundaries. In particular, a score of $0.75$ does not mean 75% risk, and a score under $0.50$ does not mean no load.
Why lumbar and twist are retained separately
An average composite can conceal the pathway that created it. A participant at $(R_L, R_T) = (0.80, 0.20)$ and a participant at $(0.50, 0.50)$ have the same composite score of $0.50$, yet the first profile is dominated by sagittal exposure and the second is balanced across the two planes. The two-dimensional scatter is therefore not a decorative companion to the bar chart; it preserves information that the average removes.
The four quadrants, separated at $0.50$, are useful descriptors:
- Low lumbar, low twist: activity or participant profile is below the reference mean in both feature groups.
- High lumbar, low twist: flexion exposure dominates the profile.
- Low lumbar, high twist: axial asymmetry dominates the profile.
- High lumbar, high twist: both feature families are elevated relative to the reference.
The point size and colour in the playbook encode the composite tier. They should not be interpreted as uncertainty intervals. For a scientific comparison, add participant-level confidence intervals or fit a hierarchical model that respects the repeated recordings within a participant.
Reproducing the participant-level table
The minimal workflow is to parse each RSF recording with flexlib, convert it to a DataFrame, calculate features per participant and activity, then fit the reference distribution once across the chosen analysis set. The following pattern makes the scope explicit and keeps raw recordings separate from derived tables.
from pathlib import Path
import numpy as np
import pandas as pd
from flexlib import create_dataframe
# The HAR study uses an annotated RSF reader for its recording format.
from models.read_annotated_rsf import RSFReader
def features_for_recording(path: Path) -> dict[str, float]:
recording = RSFReader.parse(str(path))
df = create_dataframe(recording.measurements)
lumbar = np.degrees(df["lumbarAngle"].to_numpy())
twist = np.degrees(df["twist"].to_numpy())
return {
"lumbar_mean": lumbar.mean(),
"lumbar_p90": np.percentile(lumbar, 90),
"lumbar_t20": 100 * (lumbar > 20).mean(),
"twist_mean": np.abs(twist).mean(),
"twist_p90": np.percentile(np.abs(twist), 90),
"twist_t10": 100 * (np.abs(twist) > 10).mean(),
}
Before comparing new data with the published plots, keep the reference scaler fixed and record its provenance: participant set, activities included, feature definitions, units, software version, and treatment of missing samples. Refitting $\mu^{(g)}$ and $\sigma^{(g)}$ to a new cohort answers a valid within-cohort question, but scores are no longer numerically comparable to the original plots.
What the model can and cannot support
The controlled recordings clearly separate upright table tasks from tasks that involve reaching, stooping, and object handling. That pattern is descriptive evidence that the signal and feature set respond to task demands. It is not evidence that any one household activity causes a particular clinical outcome.
Several limitations should accompany any reuse:
- The HAR sample is small and recordings are brief. It does not estimate a workshift dose-response relationship.
- The scalar feature average assigns equal importance to mean, upper-tail exposure, time above threshold, and jerk. This is a design choice, not an empirically fitted injury model.
- The 20 degree lumbar and 10 degree twist time-fraction thresholds are operational cut-points in this pipeline. Their use should be justified or varied in a sensitivity analysis for a new task.
- The score is relative to its reference distribution. A different cohort can shift scores even if the raw angle distribution is unchanged.
- Sensor placement, garment fit, task pace, and individual movement strategy all contribute to between-participant variation.
For a study protocol, report the raw features alongside $R_L$, $R_T$, and $R$. Raw values retain their physical units and let other researchers test alternative normalisation, weighting, and threshold choices.
Sources and further reading
- Walkling J, Masch A, Sander L, Deserno TM. Wearable Spine Tracker vs. Video-Based Pose Estimation for Human Activity Recognition. Sensors. 2025;25(12):3806. doi:10.3390/s25123806
- Hoogendoorn WE, et al. Flexion and Rotation of the Trunk and Lifting at Work are Risk Factors for Low Back Pain. Spine. 2000;25(23):3087-3092. doi:10.1097/00007632-200012010-00018