diff --git a/ActivityAnalyses/gait_analysis.py b/ActivityAnalyses/gait_analysis.py index 6673b862..825a4aca 100644 --- a/ActivityAnalyses/gait_analysis.py +++ b/ActivityAnalyses/gait_analysis.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ --------------------------------------------------------------------------- OpenCap processing: gaitAnalysis.py @@ -21,7 +20,7 @@ import os import sys -sys.path.append('../../') +sys.path.append('../') import numpy as np import pandas as pd @@ -36,51 +35,53 @@ class gait_analysis(kinematics): def __init__(self, sessionDir, trialName, leg='auto', lowpass_cutoff_frequency_for_coordinate_values=-1, - n_gait_cycles=1): + n_gait_cycles=-1): - # inherit init from kinematics class - super().__init__(sessionDir, trialName, - lowpass_cutoff_frequency_for_coordinate_values=lowpass_cutoff_frequency_for_coordinate_values) + # Inherit init from kinematics class. + super().__init__( + sessionDir, + trialName, + lowpass_cutoff_frequency_for_coordinate_values=lowpass_cutoff_frequency_for_coordinate_values) - # Marker data load and filter - trcFilePath = os.path.join(sessionDir,'MarkerData', - '{}.trc'.format(trialName)) + # Marker data load and filter. + trcFilePath = os.path.join(sessionDir, + 'MarkerData', + '{}.trc'.format(trialName)) self.markerDict = trc_2_dict(trcFilePath) if lowpass_cutoff_frequency_for_coordinate_values > 0: self.markerDict['markers'] = { - marker_name: lowPassFilter(self.time, data, lowpass_cutoff_frequency_for_coordinate_values) \ - for marker_name, data in self.markerDict['markers'].items()} + marker_name: lowPassFilter(self.time, data, lowpass_cutoff_frequency_for_coordinate_values) + for marker_name, data in self.markerDict['markers'].items()} - # Coordinate values + # Coordinate values. self.coordinateValues = self.get_coordinate_values() - # Segment gait cycles + # Segment gait cycles. self.gaitEvents = self.segment_walking(n_gait_cycles=n_gait_cycles,leg=leg) self.nGaitCycles = np.shape(self.gaitEvents['ipsilateralIdx'])[0] - # determine treadmill speed (0 if overground) + # Determine treadmill speed (0 if overground). self.treadmillSpeed = self.compute_treadmill_speed() - # initialize variables to be lazy loaded + # Initialize variables to be lazy loaded. self._comValues = None self._R_world_to_gait = None - # # Lazy loaded variables (setting state trajectory in utilsKinematics is slow) - # Compute COM trajectory and gait frame...used in multiple scalar computations + # Compute COM trajectory. def comValues(self): if self._comValues is None: self._comValues = self.get_center_of_mass_values() return self._comValues + # Compute gait frame. def R_world_to_gait(self): if self._R_world_to_gait is None: self._R_world_to_gait = self.compute_gait_frame() return self._R_world_to_gait - # # End Lazy loading def compute_scalars(self,scalarNames): - # verify that scalarNames are methods in gait_analysis + # Verify that scalarNames are methods in gait_analysis. method_names = [func for func in dir(self) if callable(getattr(self, func))] possibleMethods = [entry for entry in method_names if 'compute_' in entry] @@ -92,7 +93,7 @@ def compute_scalars(self,scalarNames): nonexistant_methods = [entry for entry in scalarNames if 'compute_' + entry not in method_names] if len(nonexistant_methods) > 0: - raise Exception(str(['compute_' + a for a in nonexistant_methods]) + ' not in gait_analysis class.') + raise Exception(str(['compute_' + a for a in nonexistant_methods]) + ' does not exist in gait_analysis class.') scalarDict = {} for scalarName in scalarNames: @@ -107,13 +108,15 @@ def compute_stride_length(self): calc_position = self.markerDict['markers'][leg + '_calc_study'] - # find stride length on treadmill - # difference in ipsilateral calcaneus position at heel strike + treadmill speed * time - strideLength = np.linalg.norm(calc_position[self.gaitEvents['ipsilateralIdx'][:,:1]] - \ - calc_position[self.gaitEvents['ipsilateralIdx'][:,2:3]], axis=2) + \ - self.treadmillSpeed * np.diff(self.gaitEvents['ipsilateralTime'][:,(0,2)]) - - # average across all strides + # On treadmill, the stride length is the difference in ipsilateral + # calcaneus position at heel strike + treadmill speed * time. + strideLength = ( + np.linalg.norm( + calc_position[self.gaitEvents['ipsilateralIdx'][:,:1]] - + calc_position[self.gaitEvents['ipsilateralIdx'][:,2:3]], axis=2) + + self.treadmillSpeed * np.diff(self.gaitEvents['ipsilateralTime'][:,(0,2)])) + + # Average across all strides. strideLength = np.mean(strideLength) return strideLength @@ -121,26 +124,28 @@ def compute_stride_length(self): def compute_gait_speed(self): comValuesArray = np.vstack((self.comValues()['x'],self.comValues()['y'],self.comValues()['z'])).T - gait_speed = (np.linalg.norm(comValuesArray[self.gaitEvents['ipsilateralIdx'][:,:1]] - \ - comValuesArray[self.gaitEvents['ipsilateralIdx'][:,2:3]], axis=2)) / \ - np.diff(self.gaitEvents['ipsilateralTime'][:,(0,2)]) + self.treadmillSpeed + gait_speed = ( + np.linalg.norm( + comValuesArray[self.gaitEvents['ipsilateralIdx'][:,:1]] - + comValuesArray[self.gaitEvents['ipsilateralIdx'][:,2:3]], axis=2) / + np.diff(self.gaitEvents['ipsilateralTime'][:,(0,2)]) + self.treadmillSpeed) - # average across all strides + # Average across all strides. gait_speed = np.mean(gait_speed) return gait_speed def compute_cadence(self): - # in steps per second + # In steps per second. cadence = 1/np.diff(self.gaitEvents['ipsilateralTime'][:,(0,2)]) - # average across strides + # Average across all strides. cadence = np.mean(cadence) return cadence - def compute_treadmill_speed(self): + def compute_treadmill_speed(self, overground_speed_threshold=0.3): leg,_ = self.get_leg() @@ -150,7 +155,7 @@ def compute_treadmill_speed(self): startIdx = np.round(self.gaitEvents['ipsilateralIdx'][:,:1]+.1*stanceTimeLength).astype(int) endIdx = np.round(self.gaitEvents['ipsilateralIdx'][:,1:2]-.3*stanceTimeLength).astype(int) - # average instantaneous velocities + # Average instantaneous velocities. dt = np.diff(self.markerDict['time'][:2])[0] for i in range(self.nGaitCycles): footVel = np.linalg.norm(np.mean(np.diff( @@ -158,31 +163,35 @@ def compute_treadmill_speed(self): treadmillSpeed = np.mean(footVel) - # overground - if treadmillSpeed < .3: + # Overground. + if treadmillSpeed < overground_speed_threshold: treadmillSpeed = 0 return treadmillSpeed def compute_step_width(self): - # get ankle joint center positions - leg,contLeg = self.get_leg() - ankle_position_ips = (self.markerDict['markers'][leg + '_ankle_study'] + - self.markerDict['markers'][leg + '_mankle_study'])/2 - ankle_position_cont = (self.markerDict['markers'][contLeg + '_ankle_study'] + - self.markerDict['markers'][contLeg + '_mankle_study'])/2 + leg,contLeg = self.get_leg() - ankleVector = ankle_position_cont[self.gaitEvents['contralateralIdx'][:,1]] - \ - ankle_position_ips[self.gaitEvents['ipsilateralIdx'][:,0]] + # Get ankle joint center positions. + ankle_position_ips = ( + self.markerDict['markers'][leg + '_ankle_study'] + + self.markerDict['markers'][leg + '_mankle_study'])/2 + ankle_position_cont = ( + self.markerDict['markers'][contLeg + '_ankle_study'] + + self.markerDict['markers'][contLeg + '_mankle_study'])/2 + ankleVector = ( + ankle_position_cont[self.gaitEvents['contralateralIdx'][:,1]] - + ankle_position_ips[self.gaitEvents['ipsilateralIdx'][:,0]]) - ankleVector_inGaitFrame = np.array([np.dot(ankleVector[i,:], self.R_world_to_gait()[i,:,:]) \ - for i in range(self.nGaitCycles)]) + ankleVector_inGaitFrame = np.array( + [np.dot(ankleVector[i,:], self.R_world_to_gait()[i,:,:]) + for i in range(self.nGaitCycles)]) - # step width is z distance + # Step width is z distance. stepWidth = np.abs(ankleVector_inGaitFrame[:,2]) - # average across gait cycles + # Average across all strides. stepWidth = np.mean(stepWidth) return stepWidth @@ -191,43 +200,45 @@ def compute_single_support_time(self): singleSupportTime = np.diff(self.gaitEvents['ipsilateralTime'][:,:2]) - # average across strides + # Average across all strides. singleSupportTime = np.mean(singleSupportTime) return singleSupportTime def compute_double_support_time(self): - # ipsilateral single support time - contralateral swing time - doubleSupportTime = np.diff(self.gaitEvents['ipsilateralTime'][:,:2]) - \ - np.diff(self.gaitEvents['contralateralTime'][:,:2]) + # Ipsilateral single support time - contralateral swing time. + doubleSupportTime = ( + np.diff(self.gaitEvents['ipsilateralTime'][:,:2]) - + np.diff(self.gaitEvents['contralateralTime'][:,:2])) - # average across strides + # Average across all strides. doubleSupportTime = np.mean(doubleSupportTime) return doubleSupportTime def compute_gait_frame(self): - # Create frame for each gait cycle with x: pelvis heading, - # z: average vector between ASIS during gait cycle, y: cross. + + # Create frame for each gait cycle with x: pelvis heading, + # z: average vector between ASIS during gait cycle, y: cross. - # Pelvis center trajectory (for overground heading vector) + # Pelvis center trajectory (for overground heading vector). pelvisMarkerNames = ['r.ASIS_study','L.ASIS_study','r.PSIS_study','L.PSIS_study'] pelvisMarkers = [self.markerDict['markers'][mkr] for mkr in pelvisMarkerNames] pelvisCenter = np.mean(np.array(pelvisMarkers),axis=0) - # ankle trajectory (for treadmill heading vector) + # Ankle trajectory (for treadmill heading vector). leg = self.gaitEvents['ipsilateralLeg'] if leg == 'l': leg='L' anklePos = self.markerDict['markers'][leg + '_ankle_study'] - # vector from left ASIS to right ASIS (for mediolateral direction) + # Vector from left ASIS to right ASIS (for mediolateral direction). asisMarkerNames = ['L.ASIS_study','r.ASIS_study'] asisMarkers = [self.markerDict['markers'][mkr] for mkr in asisMarkerNames] asisVector = np.squeeze(np.diff(np.array(asisMarkers),axis=0)) - # heading vector per gait cycle - # if overground, use pelvis center trajectory; treadmill: ankle trajectory + # Heading vector per gait cycle. + # If overground, use pelvis center trajectory; treadmill: ankle trajectory. if self.treadmillSpeed == 0: x = np.diff(pelvisCenter[self.gaitEvents['ipsilateralIdx'][:,(0,2)],:],axis=1)[:,0,:] x = x / np.linalg.norm(x,axis=1,keepdims=True) @@ -238,22 +249,23 @@ def compute_gait_frame(self): anklePos[self.gaitEvents['ipsilateralIdx'][i,1]] x = x / np.linalg.norm(x,axis=1,keepdims=True) - # mean ASIS vector over gait cycle + # Mean ASIS vector over gait cycle. z = np.zeros((self.nGaitCycles,3)) for i in range(self.nGaitCycles): z[i,:] = np.mean(asisVector[self.gaitEvents['ipsilateralIdx'][i,0]: \ self.gaitEvents['ipsilateralIdx'][i,2]],axis=0) z = z / np.linalg.norm(z,axis=1,keepdims=True) - # cross to get y + # Cross to get y. y = np.cross(z,x) - # 3x3xnSteps + # 3x3xnSteps. R_lab_to_gait = np.stack((x.T,y.T,z.T),axis=1).transpose((2, 0, 1)) return R_lab_to_gait def get_leg(self): + if self.gaitEvents['ipsilateralLeg'] == 'r': leg = 'r' contLeg = 'L' @@ -275,44 +287,49 @@ def get_coordinates_normalized_time(self): for i in range(coordValues.shape[1])],axis=1)) coordinateValuesTimeNormalized = {} - # average + # Average. coordVals_mean = np.mean(np.array(coordValuesNorm),axis=0) coordinateValuesTimeNormalized['mean'] = pd.DataFrame(data=coordVals_mean, columns=colNames) - # standard deviation + # Standard deviation. if self.nGaitCycles >2: coordVals_sd = np.std(np.array(coordValuesNorm), axis=0) coordinateValuesTimeNormalized['sd'] = pd.DataFrame(data=coordVals_sd, columns=colNames) else: coordinateValuesTimeNormalized['sd'] = None - #return to dataframe + # Return to dataframe. coordinateValuesTimeNormalized['indiv'] = [pd.DataFrame(data=d, columns=colNames) for d in coordValuesNorm] return coordinateValuesTimeNormalized def segment_walking(self, n_gait_cycles=-1, leg='auto', visualize=False): - # n_gait_cycles = -1 finds all accessible gait cycles. Otherwise, it finds - # that many gait cycles, working backwards from end of trial. - - # subtract sacrum from foot - # visually, it looks like the position-based approach will be more robust - r_calc_rel_x = (self.markerDict['markers']['r_calc_study'] - self.markerDict[ - 'markers']['r.PSIS_study'])[:,0] - r_toe_rel_x = (self.markerDict['markers']['r_toe_study'] - self.markerDict[ - 'markers']['r.PSIS_study'])[:,0] - # repeat for left - l_calc_rel_x = (self.markerDict['markers']['L_calc_study'] - self.markerDict[ - 'markers']['L.PSIS_study'])[:,0] - l_toe_rel_x = (self.markerDict['markers']['L_toe_study'] - self.markerDict[ - 'markers']['L.PSIS_study'])[:,0] - - # Find HS + # n_gait_cycles = -1 finds all accessible gait cycles. Otherwise, it + # finds that many gait cycles, working backwards from end of trial. + + # Subtract sacrum from foot. + # It looks like the position-based approach will be more robust. + r_calc_rel_x = ( + self.markerDict['markers']['r_calc_study'] - + self.markerDict['markers']['r.PSIS_study'])[:,0] + r_toe_rel_x = ( + self.markerDict['markers']['r_toe_study'] - + self.markerDict['markers']['r.PSIS_study'])[:,0] + + # Repeat for left. + l_calc_rel_x = ( + self.markerDict['markers']['L_calc_study'] - + self.markerDict['markers']['L.PSIS_study'])[:,0] + l_toe_rel_x = ( + self.markerDict['markers']['L_toe_study'] - + self.markerDict['markers']['L.PSIS_study'])[:,0] + + # Find HS. rHS, _ = find_peaks(r_calc_rel_x, prominence=0.3) lHS, _ = find_peaks(l_calc_rel_x, prominence=0.3) - # Find TO + # Find TO. rTO, _ = find_peaks(-r_toe_rel_x, prominence=0.3) lTO, _ = find_peaks(-l_toe_rel_x, prominence=0.3) @@ -333,15 +350,15 @@ def segment_walking(self, n_gait_cycles=-1, leg='auto', visualize=False): plt.scatter(self.markerDict['time'][lTO], l_toe_rel_x[lTO], color='blue', label='lTO') plt.legend() - # find the number of gait cycles for the foot of interest + # Find the number of gait cycles for the foot of interest. if leg=='auto': - # find the last HS of either foot + # Find the last HS of either foot. if rHS[-1] > lHS[-1]: leg = 'r' else: leg = 'l' - # find the number of gait cycles for the foot of interest + # Find the number of gait cycles for the foot of interest. if leg == 'r': hsIps = rHS toIps = rTO @@ -354,34 +371,36 @@ def segment_walking(self, n_gait_cycles=-1, leg='auto', visualize=False): toCont = rTO if len(hsIps)-1 < n_gait_cycles: - print('You requested {} gait cycles, but only {} were found. Proceeding with this number.'.format( - n_gait_cycles,len(hsIps)-1)) + print('You requested {} gait cycles, but only {} were found. ' + 'Proceeding with this number.'.format(n_gait_cycles,len(hsIps)-1)) n_gait_cycles = len(hsIps)-1 if n_gait_cycles == -1: n_gait_cycles = len(hsIps)-1 print('Processing {} gait cycles.'.format(n_gait_cycles)) - # Ipsilateral gait events: heel strike, toe-off, heel strike + # Ipsilateral gait events: heel strike, toe-off, heel strike. gaitEvents_ips = np.zeros((n_gait_cycles, 3),dtype=np.int) - # Contralateral gait events: toe-off, heel strike + # Contralateral gait events: toe-off, heel strike. gaitEvents_cont = np.zeros((n_gait_cycles, 2),dtype=np.int) if n_gait_cycles <1: raise Exception('Not enough gait cycles found.') for i in range(n_gait_cycles): - # ipsilateral HS, TO, HS + # Ipsilateral HS, TO, HS. gaitEvents_ips[i,0] = hsIps[-i-2] gaitEvents_ips[i,2] = hsIps[-i-1] - # iterate in reverse through ipsilateral TO, finding the one that is within the range of gaitEvents_ips + # Iterate in reverse through ipsilateral TO, finding the one that + # is within the range of gaitEvents_ips. toIpsFound = False for j in range(len(toIps)): if toIps[-j-1] > gaitEvents_ips[i,0] and toIps[-j-1] < gaitEvents_ips[i,2] and not toIpsFound: gaitEvents_ips[i,1] = toIps[-j-1] toIpsFound = True - # contralateral TO, HS - # iterate in reverse through contralateral HS and TO, finding the one that is within the range of gaitEvents_ips + # Contralateral TO, HS. + # Iterate in reverse through contralateral HS and TO, finding the + # one that is within the range of gaitEvents_ips hsContFound = False toContFound = False for j in range(len(toCont)): @@ -394,13 +413,13 @@ def segment_walking(self, n_gait_cycles=-1, leg='auto', visualize=False): gaitEvents_cont[i,1] = hsCont[-j-1] hsContFound = True - # making contralateral gait events optional + # Making contralateral gait events optional. if not toContFound or not hsContFound: raise Warning('Could not find contralateral gait event within ipsilateral gait event range.') gaitEvents_cont[i,0] = np.nan gaitEvents_cont[i,1] = np.nan - # convert gaitEvents to times using self.markerDict['time'] + # Convert gaitEvents to times using self.markerDict['time']. gaitEventTimes_ips = self.markerDict['time'][gaitEvents_ips] gaitEventTimes_cont = self.markerDict['time'][gaitEvents_cont] @@ -412,7 +431,5 @@ def segment_walking(self, n_gait_cycles=-1, leg='auto', visualize=False): 'eventNamesContralateral':['TO','HS'], 'ipsilateralLeg':leg} - return gaitEvents - - # Lazy loading some things that are computationally expensive + return gaitEvents \ No newline at end of file diff --git a/Examples/example_gait_analysis.py b/Examples/example_gait_analysis.py index 8c26a22d..82d5c544 100644 --- a/Examples/example_gait_analysis.py +++ b/Examples/example_gait_analysis.py @@ -29,58 +29,62 @@ sys.path.append("../ActivityAnalyses") from gait_analysis import gait_analysis -import utils +from utils import get_trial_id, download_trial, plot_subplots_with_shading +# %% Paths. +baseDir = os.path.join(os.getcwd(), '..') +dataFolder = os.path.join(baseDir, 'Data') -# %% User-defined variables +# %% User-defined variables. +# Select example: options are treadmill and overground. +example = 'treadmill' -# overground trial -# session_id = 'b39b10d1-17c7-4976-b06c-a6aaf33fead2' -# trial_name = 'gait_3' +if example == 'treadmill': + session_id = '4d5c3eb1-1a59-4ea1-9178-d3634610561c' # 1.25m/s + trial_name = 'walk_1_25ms' -# treadmill trial 1.25m/s -session_id = '4d5c3eb1-1a59-4ea1-9178-d3634610561c' -trial_name = 'walk_1_25ms' +elif example == 'overground': + session_id = 'b39b10d1-17c7-4976-b06c-a6aaf33fead2' + trial_name = 'gait_3' scalar_names = {'gait_speed','stride_length','step_width','cadence', 'single_support_time','double_support_time'} -# how many gait cycles you'd like to analyze -# -1 for all gait cycles detected in the trial +# Select how many gait cycles you'd like to analyze. Select -1 for all gait +# cycles detected in the trial. n_gait_cycles = -1 -# Lowpass filter frequency for kinematics data +# Select lowpass filter frequency for kinematics data. filter_frequency = 6 -# %% Gait analysis - -# Get trial id from name -trial_id = utils.get_trial_id(session_id,trial_name) - -# Local data dir -> will be deleted with lambda instance -sessionDir = os.path.join(os.path.abspath('../Data'),session_id) - -# download data -trialName = utils.download_trial(trial_id,sessionDir,session_id=session_id) - -# init gait analysis -gait_r = gait_analysis(sessionDir, trialName, leg='r', - lowpass_cutoff_frequency_for_coordinate_values=filter_frequency, - n_gait_cycles=n_gait_cycles) -gait_l = gait_analysis(sessionDir, trialName, leg='l', - lowpass_cutoff_frequency_for_coordinate_values=filter_frequency, - n_gait_cycles=n_gait_cycles) +# %% Gait analysis. +# Get trial id from name. +trial_id = get_trial_id(session_id,trial_name) + +# Set session path. +sessionDir = os.path.join(dataFolder, session_id) + +# Download data. +trialName = download_trial(trial_id,sessionDir,session_id=session_id) + +# Init gait analysis. +gait_r = gait_analysis( + sessionDir, trialName, leg='r', + lowpass_cutoff_frequency_for_coordinate_values=filter_frequency, + n_gait_cycles=n_gait_cycles) +gait_l = gait_analysis( + sessionDir, trialName, leg='l', + lowpass_cutoff_frequency_for_coordinate_values=filter_frequency, + n_gait_cycles=n_gait_cycles) -# compute scalars and get time-normalized kinematic curves +# Compute scalars and get time-normalized kinematic curves. gaitResults = {} gaitResults['scalars_r'] = gait_r.compute_scalars(scalar_names) gaitResults['curves_r'] = gait_r.get_coordinates_normalized_time() gaitResults['scalars_l'] = gait_l.compute_scalars(scalar_names) -gaitResults['curves_l'] = gait_l.get_coordinates_normalized_time() - - -# %% Print scalar results +gaitResults['curves_l'] = gait_l.get_coordinates_normalized_time() +# %% Print scalar results. print('\nRight foot gait metrics:') print('(units: m and s)') print('-----------------') @@ -95,9 +99,8 @@ rounded_value = round(value, 2) print(f"{key}: {rounded_value}") -# %% Plot kinematic curves - +# %% Plot kinematic curves. for leg in ['r','l']: - utils.plot_subplots_with_shading(gaitResults['curves_' + leg]['mean'], - gaitResults['curves_' + leg]['sd'], columns=None, - leg=leg) \ No newline at end of file + plot_subplots_with_shading( + gaitResults['curves_' + leg]['mean'], + gaitResults['curves_' + leg]['sd'], columns=None, leg=leg) diff --git a/Examples/example_walking_opensimAD.py b/Examples/example_walking_opensimAD.py index 6f19cc59..28f3b649 100644 --- a/Examples/example_walking_opensimAD.py +++ b/Examples/example_walking_opensimAD.py @@ -90,23 +90,21 @@ # Insert the time interval you want to simulate. It is recommended to simulate # trials shorter than 2s (more details above). Set to [] to simulate full trial. # We here selected a time window that corresponds to a full gait stride in order -# to use poriodic constraints - -# automatically -# time_window, gaitObject = segment_gait(session_id, trial_name, dataFolder, gait_cycles_from_end=3) - -# manually -time_window = [5.7333333, 6.9333333] - -# Insert the speed of the treadmill in m/s. A positive value indicates that the -# subject is moving forward. You should ignore this parameter or set it to 0 if -# the trial was not measured on a treadmill. - -# automatically -# treadmill_speed = gaitObject.treadmillSpeed - -#manually -treadmill_speed = 1.25 +# to use periodic constraints. You can use the gait segmentation function to +# automatically segment the gait cycle. Also insert the speed of the treadmill +# in m/s. A positive value indicates that the subject is moving forward. +# You should ignore this parameter or set it to 0 if the trial was not measured +# on a treadmill. You can also use the gait segmenter to automatically extract +# the treadmill speed. +segmentation_method = 'manual' +if segmentation_method == 'automatic': + time_window, gaitObject = segment_gait( + session_id, trial_name, dataFolder, gait_cycles_from_end=3) + treadmill_speed = gaitObject.treadmillSpeed + +else: + time_window = [5.7333333, 6.9333333] + treadmill_speed = 1.25 # %% Sub-example 1: walking simulation with torque-driven model. # Insert a string to "name" you case. diff --git a/utils.py b/utils.py index 175d4cc0..bc5fd4e1 100644 --- a/utils.py +++ b/utils.py @@ -137,16 +137,16 @@ def get_model_and_metadata(session_id, session_path): return modelName -def get_model_from_metadata(sessionFolder,appendText='_scaled'): +def get_model_name_from_metadata(sessionFolder,appendText='_scaled'): metadataPath = os.path.join(sessionFolder,'sessionMetadata.yaml') if os.path.exists(metadataPath): metadata = import_metadata(os.path.join(sessionFolder,'sessionMetadata.yaml')) - modelFile = metadata['openSimModel'] + appendText + '.osim' + modelName = metadata['openSimModel'] + appendText + '.osim' else: raise Exception('Session metadata not found, could not identify OpenSim model.') - return modelFile + return modelName def get_motion_data(trial_id, session_path): @@ -257,7 +257,7 @@ def download_kinematics(session_id, folder=None, trialNames=None): return loadedTrialNames, modelName -# %% download pertinent trial data +# Download pertinent trial data. def download_trial(trial_id, folder, session_id=None): trial = get_trial_json(trial_id) @@ -273,7 +273,9 @@ def download_trial(trial_id, folder, session_id=None): get_motion_data(trial_id,folder) return trial['name'] -# %% get trialID from name + + +# Get trial ID from name. def get_trial_id(session_id,trial_name): session = get_session_json(session_id) diff --git a/utilsKinematics.py b/utilsKinematics.py index d591d1c8..4fa06e55 100644 --- a/utilsKinematics.py +++ b/utilsKinematics.py @@ -43,8 +43,9 @@ def __init__(self, sessionDir, trialName, modelPath = os.path.join(sessionDir, 'OpenSimData', 'Model', '{}.osim'.format(modelName)) if not os.path.exists(modelPath): - modelFromMetadata = utils.get_model_from_metadata(sessionDir) - modelPath = modelPath.replace(modelName + '.osim',modelFromMetadata) + modelNameFromMetadata = utils.get_model_name_from_metadata(sessionDir) + modelPath = modelPath.replace(modelName + '.osim', + modelNameFromMetadata) self.model = opensim.Model(modelPath) self.model.initSystem() @@ -60,8 +61,8 @@ def __init__(self, sessionDir, trialName, tableProcessor.append(opensim.TabOpUseAbsoluteStateNames()) self.time = np.asarray(self.table.getIndependentColumn()) - # initialize the state trajectory. We will set it in other functions - # if it is needed + # Initialize the state trajectory. We will set it in other functions + # if it is needed. self._stateTrajectory = None # Filter coordinate values. @@ -126,7 +127,7 @@ def __init__(self, sessionDir, trialName, self.coordinates = [self.coordinateSet.get(i).getName() for i in range(self.nCoordinates)] - # Find rotational and translational coords + # Find rotational and translational coordinates. self.idxColumnTrLabels = [ self.columnLabels.index(i) for i in self.coordinates if \ self.coordinateSet.get(i).getMotionType() == 2] @@ -147,11 +148,12 @@ def __init__(self, sessionDir, trialName, 'arm_flex_l', 'arm_add_l', 'arm_rot_l', 'elbow_flex_l', 'pro_sup_l'] - # Only set the state trajectory when needed b/c it is slow + # Only set the state trajectory when needed because it is slow. def stateTrajectory(self): if self._stateTrajectory is None: - self._stateTrajectory = opensim.StatesTrajectory.createFromStatesTable( - self.model, self.table) + self._stateTrajectory = ( + opensim.StatesTrajectory.createFromStatesTable( + self.model, self.table)) return self._stateTrajectory def get_coordinate_values(self, in_degrees=True, diff --git a/utilsProcessing.py b/utilsProcessing.py index b4d82946..bbddc44e 100644 --- a/utilsProcessing.py +++ b/utilsProcessing.py @@ -18,10 +18,11 @@ limitations under the License. ''' +import os +pathFile = os.path.dirname(os.path.realpath(__file__)) import sys -sys.path.append('AnalysisFunctions/') +sys.path.append(os.path.join(pathFile, 'ActivityAnalyses')) -import os import logging import opensim import numpy as np