In this notebook, I’m using library dplyr, ggplot2 and function plot() to demonstrate the plotting of pinch force along time when a healthy human subject was turning a force-embedded key.
The selected task is one of the functional tasks extracted from Wolf Motor Function Test-Item 15 to assess stroke survivor’s pinch force control/scaling ability.
This task requires participant to 1) first grip the key 2) perform “turn and return” and 3) release the key as fast as possible. Participant has to repeat it for 6 times.
The ability of turning key can reflect fine motor skill (human hand dexterity).
The data is collected from a healthy subject, obtained from a publicly available source (data source). In this section, we aim to understand trend of turning a key in a normal way (normative data).
The force sensor data is collected at 200Hz frequency, and post-processed with low pass Butterworth filter at 6Hz for noise cleaning (i.e. high frequency noises > 6hz are filtered out). After which, data are systematically segmented according to a customized algorithm.
Now, lets read the file from one human subject doing key turning.
# read file
comdf <- read.table(file=paste0("./processed_files/", filename),
header=TRUE, fill = TRUE)
#extract subject name
subject <- stringi::stri_sub(filename, 1, 5)
subject <- "SNXXX " #censor subject name
#extract handedness
hand <- stringi::stri_sub(filename, 6, 7)
hand <- "Right Hand"
Here, the column P.V. (peak and valley location) and phases (turn key, return key & release key) are converted from character to factor(i.e. categorical attribute), to facilitate ease of data manipulation.
# Transform Data
library(dplyr)
comdf <- comdf %>%
select(c("Time", "theta_lowpass",
"phase", "wrist.deg_lowpass",
"Key_Pinch_kg_lowpass",
"firstder.Pinch_kg_lowpass",
"secder.Pinch_kg_lowpass", "P.V", "maxstaticpinch")) %>%
mutate_at(vars(P.V, phase), list(factor))
# checking
glimpse(comdf)
## Rows: 7,441
## Columns: 9
## $ Time <dbl> 0.905, 0.910, 0.915, 0.920, 0.925, 0.930, 0.~
## $ theta_lowpass <dbl> 0.03548162, 0.04071614, 0.04591240, 0.050908~
## $ phase <fct> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,~
## $ wrist.deg_lowpass <dbl> 4.710036, 5.195445, 5.633970, 6.013274, 6.32~
## $ Key_Pinch_kg_lowpass <dbl> 0.1414459, 0.1600956, 0.1781672, 0.1952391, ~
## $ firstder.Pinch_kg_lowpass <dbl> 0.000000000, 3.694167969, 3.536273440, 3.305~
## $ secder.Pinch_kg_lowpass <dbl> 0.00000000, -21.61862451, -38.88305342, -51.~
## $ P.V <fct> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,~
## $ maxstaticpinch <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,~
P.V. and phases are now converted to factor
Below with the explanation of each variables: - Time: Measuring time (in seconds) - theta_lowpass: Angle of key while turning (in degree) - phase: - wrist.deg_lowpass: - Key_Pinch_kg_lowpass: Force - firstder.Pinch_kg_lowpass: - secder.Pinch_kg_lowpass - P.V: - maxstaticpinch:
Let’s now look at the plots. Plot_1 shows the filtered pinch force while turning a key (embedded with force sensor) repeated 6 times.
The vertical dotted lines used to segment the signal are based on turning angle (not shown in the graph).
We get to see the trend that higher amount of force occurred at the time of returning key (light seagreen color).
## [1] "SNXXX Right Hand Plot_1: Key Turning Pinch Force v.s Time"
In Plot_2, pinch force profile per each of 6 trials is extracted against normalized time. It gives us an idea how a pinch force is varying within each phase cycle per single participant.
The shape is generally consistent.
## [1] "SNXXX Right Hand Plot_2: Pinch Force v.s. Time"
Pinch force rate reflect the pinch force increase within unit time, namely “scaling”.
The shape of each trial is consistent and the fastest scaling rate is found at 15kg/s in positive (adding force) and negative (releasing force).
## [1] "SNXXX Right Hand Plot_3: Pinch Force Rate v.s. Time"
The pinch force is plotted against key turning angle. When key is turned forward (zero to 180 degree), the force increases non-linearly. It interestingly reflects how human hand gently control the force in a non-linear way which can be very different to traditional robot hand (linear open and close).
## [1] "SNXXX Right Hand Pinch Force v.s. Key_angle"
Here is a chunk of data wrangling code and I’m attempting to apply Fisher-EM algorithm to cluster high dimensional data (in this case, 288 layer of time series) into two clusters mean.
The plot visualises trend of normative pinch variation for key turning and returning only (excluding the release phase). The trajectory is a dual peak shape.
#plotting all trials
filename <- "_trialdata_pinch.tsv"
trialdata_pinch <- read.table(file=paste0("./processed_files/",
filename), header=TRUE, fill = TRUE)
filename <- "newtrialdata_mean_pinch.tsv"
newtrialdata_mean_pinch <- read.table(file=paste0("./processed_files/", filename),
header=TRUE, fill = TRUE)
long_transpose_pinch <- reshape2::melt(trialdata_pinch, id.vars = "X")
colnames(long_transpose_pinch) <- c("time", "subject", "value")
View(long_transpose_pinch)
# Fisher EM clustering
newtrialdata_mean_pinch <- newtrialdata_mean_pinch[,2:102]
res = FisherEM::fem(newtrialdata_mean_pinch,K=2,model='AB',method='reg')
#plot(res)
fem_mean <- t(res$mean) #get from following fem
long_fem_mean <- reshape2::melt(fem_mean)
colnames(long_fem_mean) <- c("time", "cluster", "value")
#---------------
# 288 profiles ensembles
#---------------
library(ggplot2)
library("ggthemes")
ggbase <- ggplot(long_transpose_pinch, # Draw ggplot2 time series plot
aes(x = time,
y = value,
col = subject)) +
geom_line() +
theme(legend.position = "none")
gg1 <- ggbase+ labs(x = "Normalised Time(%)", y = "Pinch Force (kg)") +
ggtitle("Absolute Pinch Force vs Normarlised Time") +
theme_hc() + theme(legend.position = "none") +
geom_point(data=long_fem_mean, aes(x = time, y = value),
pch = 13, size = 3.0, colour ="black", alpha = 1)
gg1
[Update Jan 2023] Good news! The presented work eventually leads to publication in a Biomechanics conference. I’m grateful for this opportunity to promote the potential of sensor data in tracking hand dexterity recovery in rehabilitation field. Below with a sneak preview.
Sneak Preview
In this notebook, we get to see how normative key turning pinch profile is like. The next step is to compare it with stroke survivor pinch profile and to discover useful metric able to distinguish the healthy and post-stroke condition.
To identify useful metric, we can preliminary employ Two Sample t-test (parametric test for normal distribution) or Wilcoxon-Mann-Whitney test (non-parametric without underlying distribution) to prove our hypothesis. Taking t-test as example:
We can use t.test() or wilcox.test() in R to run hypothesis test. (note: wilcox has different hypothesis statement)
If the p-value is <0.05, we have sufficient evidence to reject null H0 and conclude mean time is significantly different between two groups. That gives an insight that such sensor measurement can be used to measure human hand dexterity performance. It will encourage sensor-based approach to monitor patient’s hand rehabilitation journey.