Ton thinks I'm outputting incorrect ankle moments. His 2D inverse dynamics code seems to work on his test data, so I may be passing something in incorrectly.
Update: We've determined that subject 9 has incorrect measurements resulting in the weird ankle moments. Not sure why.../
import sys
import os
import operator
import numpy as np
import pandas
import matplotlib.pyplot as plt
from IPython.core.pylabtools import figsize
import gaitanalysis
from gaitanalysis.motek import markers_for_2D_inverse_dynamics
from gaitanalysis.gait import WalkingData
from gaitanalysis.controlid import SimpleControlSolver
sys.path.append('..')
from src import utils
from src.grf_landmark_settings import settings
%matplotlib inline
Load the path to the directory with the experimental data.
trials_dir = utils.trial_data_dir()
Trials data directory is set to /home/moorepants/Data/human-gait/gait-control-identification
df = utils.generate_meta_data_table(trials_dir)
df.sort('id').head()
datetime | id | nominal-speed | notes | subject-id | |
---|---|---|---|---|---|
72 | 2013-12-03 05:06:00 | 1 | NaN | This is a trial that Obinna collected for his ... | 1 |
20 | 2013-10-22 | 3 | 1.2 | This is an unloaded trial (no subject) of the ... | 0 |
35 | 2013-10-22 | 4 | 1.2 | This is an unloaded trial (no subject) of the ... | 0 |
44 | 2013-10-22 | 5 | 1.2 | This is an unloaded trial (no subject) of the ... | 0 |
27 | 2013-10-22 | 6 | 1.2 | This is the first attempt at the 10 minute pro... | 1 |
trial_number = '026'
params = settings[trial_number]
First, extract the data from the first normal walking period in the trial.
walking_event_data_frame, meta_data, walking_event_data_path = \
utils.write_event_data_frame_to_disk(trial_number, event='First Normal Walking')
Trials data directory is set to /home/moorepants/Data/human-gait/gait-control-identification Temporary data directory is set to ../data Loading pre-cleaned data: ../data/cleaned-data-026-first-normal-walking.h5 0.10 s
walking_data, walking_data_path = \
utils.write_inverse_dynamics_to_disk(walking_event_data_frame,
meta_data,
walking_event_data_path)
Loading pre-computed inverse dynamics from ../data/walking-data-026-first-normal-walking.h5. 0.06 s
steps, walking_data = utils.section_signals_into_steps(walking_data, walking_data_path,
filter_frequency=params[0],
threshold=params[1],
num_samples_lower_bound=params[2],
num_samples_upper_bound=params[3],
num_samples=None)
Loading pre-computed steps from ../data/walking-data-026-first-normal-walking.h5. 0.046039
Load in Ton's test data.
path = os.path.join(os.path.split(gaitanalysis.__file__)[0], 'octave', '2d_inverse_dynamics', 'test', 'rawdata.txt')
df = pandas.read_csv(path, delimiter='\t', na_values='NaN ')
meta_data['subject']['id']
9
Cortex Coordinate System [3D]
The walking_data
is transformed into the ISB standard which matches Ton's 2D inverse dynamics code:
2D Inverse Dynamics Coordinate System [2D]
Force plate 2 FP2
is the right force plate.
So in the test data, there is FP1 which is the left force plate, but all the markers are right side markers.
These are the column labels from the Cortex/D-Flow data that need to be used in the 2D inverse dynamics code, in the correct order.
orig_labels = markers_for_2D_inverse_dynamics('full')
orig_labels
(['LSHO.PosX', 'LSHO.PosY', 'LGTRO.PosX', 'LGTRO.PosY', 'LLEK.PosX', 'LLEK.PosY', 'LLM.PosX', 'LLM.PosY', 'LHEE.PosX', 'LHEE.PosY', 'LMT5.PosX', 'LMT5.PosY'], ['RSHO.PosX', 'RSHO.PosY', 'RGTRO.PosX', 'RGTRO.PosY', 'RLEK.PosX', 'RLEK.PosY', 'RLM.PosX', 'RLM.PosY', 'RHEE.PosX', 'RHEE.PosY', 'RMT5.PosX', 'RMT5.PosY'], ['FP1.ForX', 'FP1.ForY', 'FP1.MomZ'], ['FP2.ForX', 'FP2.ForY', 'FP2.MomZ'])
Thes plots compare the shape, sign, and magnitudes of the raw data for this test subject to the raw data in the 2D inverse dynamics test code.
start, end = 265, 600
def compare(df1, cols1, df2, cols2):
fig, axes = plt.subplots(len(cols1), 1)
for ax, threed, twod in zip(axes, cols1, cols2):
ax.plot(df1[threed][start:end], label=threed + ' [3D]')
ax.plot(df2[twod], label=twod + ' [2D]')
ax.legend()
figsize(14, 8)
df.columns
Index([u'% TimeStamp', u'RSHO.PosX', u'RSHO.PosY', u'RGTRO.PosX', u'RGTRO.PosY', u'RLEK.PosX', u'RLEK.PosY', u'RLM.PosX', u'RLM.PosY', u'RHEE.PosX', u'RHEE.PosY', u'RMT5.PosX', u'RMT5.PosY', u'FP2.ForX', u'FP2.ForY', u'FP2.MomZ'], dtype=object)
compare(walking_data.raw_data, ['FP2.ForX', 'FP2.ForY', 'FP2.MomZ'],
df, ['FP2.ForX', 'FP2.ForY', 'FP2.MomZ'])
markers = ['RSHO', 'RGTRO', 'RLEK', 'RLM', 'RHEE', 'RMT5']
for marker in markers:
threed = [marker + '.PosX', marker + '.PosY']
twod = [marker + '.PosX', marker + '.PosY']
compare(walking_data.raw_data, threed, df, twod)
Everything seems to be fine. The differnce in the moment curves simply reflect the relative difference in the subjects fore/aft position on the treadmill.
df['FP2.CopX'] = df['FP2.MomZ'] / df['FP2.ForY']
plt.plot(walking_data.raw_data['FP2.CopX'][start:end], 'b-', label='FP2.CopX [3D]')
plt.plot(walking_data.raw_data['RLM.PosX'][start:end], 'b.', label='RLM.PosX [3D]')
plt.plot(df['FP2.CopX'], 'r-', label='FP2.CopX [2D]')
plt.plot(df['RLM.PosX'], 'r.', label='RLM.PosX [2D]')
plt.ylim((-1, 1))
plt.legend()
<matplotlib.legend.Legend at 0x7fd4b5981250>
plt.plot(walking_data.raw_data['Right.Ankle.PlantarFlexion.Moment'][start:end])
[<matplotlib.lines.Line2D at 0x7fd4b58bd0d0>]
!git rev-parse HEAD
7ba68f0160c23a61204291ca107ad570ac6f6e5a
!git --git-dir=/home/moorepants/src/GaitAnalysisToolKit/.git --work-tree=/home/moorepants/src/GaitAnalysisToolKit rev-parse HEAD
a3732352747bc03ca839df9ff02ddcbd889e636d
%install_ext http://raw.github.com/jrjohansson/version_information/master/version_information.py
Installed version_information.py. To use it, type: %load_ext version_information
%load_ext version_information
%version_information gaitanalysis, numpy, scipy, pandas, matplotlib, tables, oct2py
Software | Version |
---|---|
Python | 2.7.8 64bit [GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] |
IPython | 2.3.0 |
OS | Linux 3.13.0 37 generic x86_64 with debian jessie sid |
gaitanalysis | 0.1.0dev |
numpy | 1.8.2 |
scipy | 0.14.0 |
pandas | 0.12.0 |
matplotlib | 1.4.0 |
tables | 3.1.1 |
oct2py | 2.4.0 |
Fri Oct 17 13:06:13 2014 EDT |
!pip freeze
DynamicistToolKit==0.3.5 -e git+git@github.com:csu-hmc/GaitAnalysisToolKit.git@a3732352747bc03ca839df9ff02ddcbd889e636d#egg=GaitAnalysisToolKit-origin/HEAD Jinja2==2.7.2 MarkupSafe==0.18 PyYAML==3.11 backports.ssl-match-hostname==3.4.0.2 ipython==2.3.0 matplotlib==1.4.0 numexpr==2.3.1 numpy==1.8.2 oct2py==2.4.0 pandas==0.12.0 patsy==0.2.1 pyparsing==2.0.1 python-dateutil==1.5 pytz==2014.7 pyzmq==14.3.0 scipy==0.14.0 six==1.8.0 statsmodels==0.5.0 sympy==0.7.5 tables==3.1.1 tornado==3.2.1 uncertainties==2.4.6.1 wsgiref==0.1.2