!pip freeze
Cython==0.19.1 -e git+git@github.com:moorepants/DynamicistToolKit.git@46718b5cea54b13fe774b7c2b69612ec1f4df429#egg=DynamicistToolKit-dev Jinja2==2.7.1 MarkupSafe==0.18 argparse==1.2.1 coverage==3.6 ipython==1.0.0 matplotlib==1.3.0 nose==1.3.0 numpy==1.7.1 pandas==0.12.0 pyparsing==2.0.1 python-dateutil==2.1 pytz==2013b pyzmq==13.1.0 scipy==0.12.0 six==1.3.0 sympy==0.7.3 tornado==3.1 wsgiref==0.1.2
%pylab inline
Populating the interactive namespace from numpy and matplotlib
Here is some data that was collected for a paper which is about to be published. Proofs and supplementary documentation are attached.
This is from a 77 kg male, 30 seconds of walking preceded by 1 second of standing. The treadmill speed increases gradually in the beginning, at t=6.0 it is at its final constant speed to best to ignore anything that happens before that time.
The dof file contains the generalized coordinates, dofvel the generalized velocities. The jointmoment file the corresponding generalized forces. First line has the names of the generalized coordinates. The grf file has the ground reaction forces, which you would use to determine where you are in the gait cycle (from heelstrike to heelstrike).
CAREN_Trial04.txt is the raw data (mocap and force plate). You could actually load that file in D-Flow to produce the variables that are on the other files, if you wanted to.
ls ../data
CAREN_Trial04_dof.txt CAREN_Trial04_grf.txt CAREN_Trial04.txt obinna-walking.txt CAREN_Trial04_dofvel.txt CAREN_Trial04_jointmoment.txt example_vertical_grf.csv
import pandas
coordinates = pandas.read_csv('../data/CAREN_Trial04_dof.txt', delimiter='\t', index_col="TimeStamp")
speeds = pandas.read_csv('../data/CAREN_Trial04_dofvel.txt', delimiter='\t', index_col="TimeStamp")
generalized_forces = pandas.read_csv('../data/CAREN_Trial04_jointmoment.txt', delimiter='\t', index_col="TimeStamp")
ground_reaction_forces = pandas.read_csv('../data/CAREN_Trial04_grf.txt', delimiter='\t', index_col="TimeStamp")
raw_data = pandas.read_csv('../data/CAREN_Trial04.txt', delimiter='\t', index_col="TimeStamp")
for df in [coordinates, speeds, generalized_forces, ground_reaction_forces, raw_data]:
print(df)
print('=' * 50)
<class 'pandas.core.frame.DataFrame'> Index: 3100 entries, 0.0 to 30.99 Data columns (total 47 columns): FrameNumber 3100 non-null values PelvisX 3100 non-null values PelvisY 3100 non-null values PelvisZ 3100 non-null values PelvisYaw 3100 non-null values PelvisForwardPitch 3100 non-null values PelvisRightRoll 3100 non-null values TrunkFlexion 3100 non-null values TrunkRightBend 3100 non-null values TrunkLeftTwist 3100 non-null values HeadFlexion 3100 non-null values HeadRightBend 3100 non-null values HeadLeftTwist 3100 non-null values RShoulderUp 3100 non-null values LShoulderUp 3100 non-null values RShoulderForward 3100 non-null values LShoulderForward 3100 non-null values RShoulderInward 3100 non-null values LShoulderInward 3100 non-null values RShoulderFlexion 3100 non-null values LShoulderFlexion 3100 non-null values RShoulderAbduction 3100 non-null values LShoulderAbduction 3100 non-null values RShoulderInternalRotation 3100 non-null values LShoulderInternalRotation 3100 non-null values RElbowFlexion 3100 non-null values LElbowFlexion 3100 non-null values RForeArmPronation 3100 non-null values LForeArmPronation 3100 non-null values RWristFlexion 3100 non-null values LWristFlexion 3100 non-null values RHandAbduction 3100 non-null values LHandAbduction 3100 non-null values RHipFlexion 3100 non-null values LHipFlexion 3100 non-null values RHipAbduction 3100 non-null values LHipAbduction 3100 non-null values RHipInternalRotation 3100 non-null values LHipInternalRotation 3100 non-null values RKneeFlexion 3100 non-null values LKneeFlexion 3100 non-null values RAnklePlantarFlexion 3100 non-null values LAnklePlantarFlexion 3100 non-null values RFootPronation 3100 non-null values LFootPronation 3100 non-null values RToeFlexion 3100 non-null values LToeFlexion 3100 non-null values dtypes: float64(46), int64(1) ================================================== <class 'pandas.core.frame.DataFrame'> Index: 3100 entries, 0.0 to 30.99 Data columns (total 47 columns): FrameNumber 3100 non-null values PelvisX 3100 non-null values PelvisY 3100 non-null values PelvisZ 3100 non-null values PelvisYaw 3100 non-null values PelvisForwardPitch 3100 non-null values PelvisRightRoll 3100 non-null values TrunkFlexion 3100 non-null values TrunkRightBend 3100 non-null values TrunkLeftTwist 3100 non-null values HeadFlexion 3100 non-null values HeadRightBend 3100 non-null values HeadLeftTwist 3100 non-null values RShoulderUp 3100 non-null values LShoulderUp 3100 non-null values RShoulderForward 3100 non-null values LShoulderForward 3100 non-null values RShoulderInward 3100 non-null values LShoulderInward 3100 non-null values RShoulderFlexion 3100 non-null values LShoulderFlexion 3100 non-null values RShoulderAbduction 3100 non-null values LShoulderAbduction 3100 non-null values RShoulderInternalRotation 3100 non-null values LShoulderInternalRotation 3100 non-null values RElbowFlexion 3100 non-null values LElbowFlexion 3100 non-null values RForeArmPronation 3100 non-null values LForeArmPronation 3100 non-null values RWristFlexion 3100 non-null values LWristFlexion 3100 non-null values RHandAbduction 3100 non-null values LHandAbduction 3100 non-null values RHipFlexion 3100 non-null values LHipFlexion 3100 non-null values RHipAbduction 3100 non-null values LHipAbduction 3100 non-null values RHipInternalRotation 3100 non-null values LHipInternalRotation 3100 non-null values RKneeFlexion 3100 non-null values LKneeFlexion 3100 non-null values RAnklePlantarFlexion 3100 non-null values LAnklePlantarFlexion 3100 non-null values RFootPronation 3100 non-null values LFootPronation 3100 non-null values RToeFlexion 3100 non-null values LToeFlexion 3100 non-null values dtypes: float64(46), int64(1) ================================================== <class 'pandas.core.frame.DataFrame'> Index: 3100 entries, 0.0 to 30.99 Data columns (total 47 columns): FrameNumber 3100 non-null values PelvisX 3100 non-null values PelvisY 3100 non-null values PelvisZ 3100 non-null values PelvisYaw 3100 non-null values PelvisForwardPitch 3100 non-null values PelvisRightRoll 3100 non-null values TrunkFlexion 3100 non-null values TrunkRightBend 3100 non-null values TrunkLeftTwist 3100 non-null values HeadFlexion 3100 non-null values HeadRightBend 3100 non-null values HeadLeftTwist 3100 non-null values RShoulderUp 3100 non-null values LShoulderUp 3100 non-null values RShoulderForward 3100 non-null values LShoulderForward 3100 non-null values RShoulderInward 3100 non-null values LShoulderInward 3100 non-null values RShoulderFlexion 3100 non-null values LShoulderFlexion 3100 non-null values RShoulderAbduction 3100 non-null values LShoulderAbduction 3100 non-null values RShoulderInternalRotation 3100 non-null values LShoulderInternalRotation 3100 non-null values RElbowFlexion 3100 non-null values LElbowFlexion 3100 non-null values RForeArmPronation 3100 non-null values LForeArmPronation 3100 non-null values RWristFlexion 3100 non-null values LWristFlexion 3100 non-null values RHandAbduction 3100 non-null values LHandAbduction 3100 non-null values RHipFlexion 3100 non-null values LHipFlexion 3100 non-null values RHipAbduction 3100 non-null values LHipAbduction 3100 non-null values RHipInternalRotation 3100 non-null values LHipInternalRotation 3100 non-null values RKneeFlexion 3100 non-null values LKneeFlexion 3100 non-null values RAnklePlantarFlexion 3100 non-null values LAnklePlantarFlexion 3100 non-null values RFootPronation 3100 non-null values LFootPronation 3100 non-null values RToeFlexion 3100 non-null values LToeFlexion 3100 non-null values dtypes: float64(46), int64(1) ================================================== <class 'pandas.core.frame.DataFrame'> Index: 3100 entries, 0.0 to 30.99 Data columns (total 13 columns): FrameNumber 3100 non-null values RFx 3100 non-null values RFy 3100 non-null values RFz 3100 non-null values RCOPx 3100 non-null values RCOPz 3100 non-null values RMy' 3100 non-null values LFx 3100 non-null values LFy 3100 non-null values LFz 3100 non-null values LCOPx 3100 non-null values LCOPz 3100 non-null values LMy' 3100 non-null values dtypes: float64(12), int64(1) ================================================== <class 'pandas.core.frame.DataFrame'> Index: 3100 entries, 0.0 to 30.99 Columns: 186 entries, FrameNumber to FP2.MomZ dtypes: float64(185), int64(1) ==================================================
coordinates['RKneeFlexion'].plot(figsize=(12.0, 8.0))
<matplotlib.axes.AxesSubplot at 0x41a6bd0>
raw_data['TreadmillSpeed'].plot(figsize=(12.0, 8.0))
<matplotlib.axes.AxesSubplot at 0x45fb410>
ground_reaction_forces['LFx'][500:1000].plot(figsize=(12.0, 8.0))
<matplotlib.axes.AxesSubplot at 0x45fb710>
The vertical ground reaction force is in the $Y$ direction, positive is up. So if you press down on the force plate you get a positive vertical ground reaction force.
ground_reaction_forces['LFy'][500:1000].plot(figsize=(12.0, 8.0))
<matplotlib.axes.AxesSubplot at 0x4ba2dd0>
ground_reaction_forces['LFz'][500:1000].plot(figsize=(12.0, 8.0))
<matplotlib.axes.AxesSubplot at 0x3047ad0>
coordinates['RKneeFlexion'].plot(figsize=(12.0, 8.0))
<matplotlib.axes.AxesSubplot at 0x30479d0>
raw_data['TreadmillSpeed'].to_csv('treadmill-speed.csv')
!head treadmill-speed.csv
0.0,0.0 0.01,0.0 0.02,0.0 0.03,0.0 0.04,0.0 0.05,0.0 0.06,0.0 0.07,0.0 0.08,0.0 0.09,0.0
import numpy as np
speed_array = np.loadtxt('treadmill-speed.csv', delimiter=',')
speed_array[:, 0]
array([ 0.00000000e+00, 1.00000000e-02, 2.00000000e-02, ..., 3.09700000e+01, 3.09800000e+01, 3.09900000e+01])
from dtk import walk
reload(walk)
<module 'dtk.walk' from '/home/moorepants/src/DynamicistTK/dtk/walk.pyc'>
walk.gait_landmarks_from_grf(ground_reaction_forces.index.values.astype(float),
ground_reaction_forces['RFy'], ground_reaction_forces['LFy'], do_plot=True, min_time=15.0, threshold=5.0)
(array([ 15.36, 16.52, 17.68, 18.83, 19.97, 21.12, 22.28, 23.42, 24.59, 25.72, 26.87, 28.01, 29.17, 30.33]), array([ 15.6 , 16.75, 20.2 , 25.95, 28.25, 29.39, 30.59]), array([ 15.01, 16.16, 17.33, 18.47, 19.62, 20.78, 21.93, 23.06, 24.22, 25.37, 26.51, 27.66, 28.8 , 29.96]), array([ 15.57, 16.74, 20.19, 25.94, 28.23, 29.36, 30.53]))
obinna = pandas.read_csv('../data/obinna-walking.txt', delimiter='\t', index_col="TimeStamp", na_values='0.000000')
obinna.head()
<class 'pandas.core.frame.DataFrame'> Index: 5 entries, 534.133513 to 534.173667 Columns: 617 entries, FrameNumber to HBM.COM.Z dtypes: float64(616), int64(1)
[col for col in obinna.columns if col.endswith('.Ang') or col.endswith('ForY') or col.endswith('.Mom')]
['FP1.ForY', 'FP2.ForY', 'PelvisX.Ang', 'PelvisX.Mom', 'PelvisY.Ang', 'PelvisY.Mom', 'PelvisZ.Ang', 'PelvisZ.Mom', 'PelvisYaw.Ang', 'PelvisYaw.Mom', 'PelvisForwardPitch.Ang', 'PelvisForwardPitch.Mom', 'PelvisRightRoll.Ang', 'PelvisRightRoll.Mom', 'TrunkFlexion.Ang', 'TrunkFlexion.Mom', 'TrunkRightBend.Ang', 'TrunkRightBend.Mom', 'TrunkLeftTwist.Ang', 'TrunkLeftTwist.Mom', 'HeadFlexion.Ang', 'HeadFlexion.Mom', 'HeadRightBend.Ang', 'HeadRightBend.Mom', 'HeadLeftTwist.Ang', 'HeadLeftTwist.Mom', 'RShoulderUp.Ang', 'RShoulderUp.Mom', 'LShoulderUp.Ang', 'LShoulderUp.Mom', 'RShoulderForward.Ang', 'RShoulderForward.Mom', 'LShoulderForward.Ang', 'LShoulderForward.Mom', 'RShoulderInward.Ang', 'RShoulderInward.Mom', 'LShoulderInward.Ang', 'LShoulderInward.Mom', 'RShoulderFlexion.Ang', 'RShoulderFlexion.Mom', 'LShoulderFlexion.Ang', 'LShoulderFlexion.Mom', 'RShoulderAbduction.Ang', 'RShoulderAbduction.Mom', 'LShoulderAbduction.Ang', 'LShoulderAbduction.Mom', 'RShoulderInternalRotation.Ang', 'RShoulderInternalRotation.Mom', 'LShoulderInternalRotation.Ang', 'LShoulderInternalRotation.Mom', 'RElbowFlexion.Ang', 'RElbowFlexion.Mom', 'LElbowFlexion.Ang', 'LElbowFlexion.Mom', 'RForeArmPronation.Ang', 'RForeArmPronation.Mom', 'LForeArmPronation.Ang', 'LForeArmPronation.Mom', 'RWristFlexion.Ang', 'RWristFlexion.Mom', 'LWristFlexion.Ang', 'LWristFlexion.Mom', 'RHandAbduction.Ang', 'RHandAbduction.Mom', 'LHandAbduction.Ang', 'LHandAbduction.Mom', 'RHipFlexion.Ang', 'RHipFlexion.Mom', 'LHipFlexion.Ang', 'LHipFlexion.Mom', 'RHipAbduction.Ang', 'RHipAbduction.Mom', 'LHipAbduction.Ang', 'LHipAbduction.Mom', 'RHipInternalRotation.Ang', 'RHipInternalRotation.Mom', 'LHipInternalRotation.Ang', 'LHipInternalRotation.Mom', 'RKneeFlexion.Ang', 'RKneeFlexion.Mom', 'LKneeFlexion.Ang', 'LKneeFlexion.Mom', 'RAnklePlantarFlexion.Ang', 'RAnklePlantarFlexion.Mom', 'LAnklePlantarFlexion.Ang', 'LAnklePlantarFlexion.Mom', 'RFootPronation.Ang', 'RFootPronation.Mom', 'LFootPronation.Ang', 'LFootPronation.Mom', 'RToeFlexion.Ang', 'RToeFlexion.Mom', 'LToeFlexion.Ang', 'LToeFlexion.Mom']
obinna['FP2.ForY'].plot(figsize=(20,10))
<matplotlib.axes.AxesSubplot at 0x516f990>
start = 1100
stop = 3000
right_strikes, left_strikes, right_toe_off, left_toe_off = \
walk.gait_landmarks_from_grf(obinna.index.values.astype(float)[start:stop],
obinna['FP1.ForY'][start:stop],
obinna['FP2.ForY'][start:stop],
do_plot=True, min_time=15.0, threshold=28.0)
obinna['FP2.ForY'].to_csv('../data/example_vertical_grf.csv')
first_foot_down = obinna[right_strikes[0]:right_toe_off[1]]
second_foot_down = obinna[right_strikes[1]:right_toe_off[2]]
first_foot_down['FP1.ForY'].shape
(79,)
second_foot_down['FP1.ForY'].shape
(77,)
from dtk import process
# this is giving different answers depending on the guess value
process.find_timeshift(first_foot_down['FP1.ForY'][:-2].values,
second_foot_down['FP1.ForY'].values,
100,
guess=0.01,
plot=True)
The minimun of the error landscape is 0.01. Optimization terminated successfully. Current function value: 1.077503 Iterations: 10 Function evaluations: 21
array([ 0.002625])
figure(figsize=(10, 8))
right_steps = {}
for i, heel in enumerate(right_strikes[:-1]):
right_steps[i] = obinna[heel:right_toe_off[i + 1]]
print(len(right_steps[i]))
time = process.time_vector(len(right_steps[i]), 100)
right_steps[i].index = time
plot(time, right_steps[i]['FP1.ForY'],)
#right_steps = pandas.Panel(right_steps)
79 77 78 77 75 79 79 78 78 79 79 80 78 79 79
right_steps = pandas.Panel(right_steps)
mean_right_steps = right_steps.mean(axis='items')
mean_right_steps['FP1.ForY'].plot()
<matplotlib.axes.AxesSubplot at 0x6384d90>
right_steps = right_steps.fillna(method='pad')
from dtk import walk
sensors = ['RKneeFlexion.Ang', 'RAnklePlantarFlexion.Ang']
controls = ['RKneeFlexion.Mom', 'RHipFlexion.Mom', 'RAnklePlantarFlexion.Mom']
solver = walk.SimpleControlSolver(right_steps, sensors, controls)
gains, sensors = solver.solve()
gains.shape
(80, 3, 2)
figure(figsize=(10, 8))
plot(gains.reshape(gains.shape[0], gains.shape[1] * gains.shape[2]), '.-')
[<matplotlib.lines.Line2D at 0x5fd9950>, <matplotlib.lines.Line2D at 0x5fd9c10>, <matplotlib.lines.Line2D at 0x5fd9e10>, <matplotlib.lines.Line2D at 0x5fd9f90>, <matplotlib.lines.Line2D at 0x63b2150>, <matplotlib.lines.Line2D at 0x63b22d0>]
solver.sensors = ['RKneeFlexion.Ang']
solver.lengths()
gains, sensors = solver.solve()
figure(figsize=(10, 8))
plot(gains.reshape(gains.shape[0], gains.shape[1] * gains.shape[2]), '.-')
[<matplotlib.lines.Line2D at 0x5eb5b50>, <matplotlib.lines.Line2D at 0x5eb5dd0>, <matplotlib.lines.Line2D at 0x5eb5fd0>]