Skip to content

Commit 10e367f

Browse files
authored
Updates code to work with latest dependencies. (#140)
* Use Octave interp1 instead of deprecated interp1q. * oct2py >= 4.0 requires an nout kwarg for multiple outputs. * Accommodate Octave 3 and 4. * Round the indice count so that the numpy array is not indexed by a float. * Arrays seemingly copied, moved to simpler verbose code to avoid copies. * Setup Travis CI to use Conda and old/new testing. - Travis CI script uses miniconda for installs. - Two matrix entries to test against oldest support and newest. - Build the docs on Travis.
1 parent 96efe72 commit 10e367f

File tree

8 files changed

+119
-31
lines changed

8 files changed

+119
-31
lines changed

.travis.yml

+40-14
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,43 @@
1-
language: python
2-
python:
3-
- "2.7"
4-
virtualenv:
5-
system_site_packages: true
1+
language: generic
2+
os:
3+
- linux
4+
env:
5+
matrix:
6+
- DEP_VERSIONS="oldest"
7+
- DEP_VERSIONS="latest"
68
before_install:
7-
- pip uninstall -y numpy
8-
- sudo apt-add-repository -y ppa:octave/stable
9+
- if [[ $DEP_VERSIONS == "oldest" ]]; then
10+
sudo apt-get install -y -qq python-pip python-setuptools python-numpy python-scipy python-matplotlib python-tables python-nose python-coverage python-pandas python-sphinx python-mock python-numpydoc python-yaml;
11+
sudo pip install --no-deps oct2py==2.4.2 DynamicistToolKit==0.4.0;
12+
elif [[ $DEP_VERSIONS == "latest" ]]; then
13+
MINICONDA_URL="https://repo.continuum.io/miniconda";
14+
MINICONDA_FILE="Miniconda3-latest-Linux-x86_64.sh";
15+
curl -L -O "${MINICONDA_URL}/${MINICONDA_FILE}";
16+
bash $MINICONDA_FILE -b;
17+
source ~/miniconda3/bin/activate root;
18+
conda config --set always_yes yes;
19+
conda update -q conda;
20+
conda env create -f env-dev-latest.yml;
21+
source activate gaitanalysis-dev-latest;
22+
sudo apt-add-repository -y ppa:octave/stable;
23+
fi
924
- sudo apt-get update
10-
- sudo apt-get install -y -qq python-setuptools python-numpy python-scipy python-matplotlib python-tables python-nose python-coverage octave
11-
- pip install pandas==0.12.0 pyyaml oct2py==1.2.0 DynamicistToolKit==0.4.0
12-
- pip freeze
13-
- octave --version
25+
- sudo apt-get install -y -qq octave
1426
install:
15-
- python setup.py install
16-
script: nosetests -v --with-coverage --cover-package=gaitanalysis
17-
after_success: coveralls
27+
- if [[ $DEP_VERSIONS == "oldest" ]]; then
28+
sudo pip install --no-deps -e .;
29+
elif [[ $DEP_VERSIONS == "latest" ]]; then
30+
python setup.py install;
31+
fi
32+
before_script:
33+
- octave --version
34+
- if [[ $DEP_VERSIONS == "oldest" ]]; then
35+
pip freeze;
36+
elif [[ $DEP_VERSIONS == "latest" ]]; then
37+
conda info;
38+
conda list;
39+
fi
40+
script:
41+
- nosetests -v --with-coverage --cover-package=gaitanalysis
42+
- cd docs
43+
- make html

RELEASE.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
2. Bump the version in gaitanalysis/version.py, for example 0.1.0dev to 0.1.0.
33
3. Commit changes.
44
4. git tag -a vX.X.X -m "Version X.X.X"
5-
5. python setup.py regsiter sdist upload
5+
5. python setup.py register sdist upload
66
6. Make sure the latest version is available on readthedocs.org
77
7. Bump the version in the git repo to one with "dev" appended.

env-dev-latest.yml

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: gaitanalysis-dev-latest
2+
channels:
3+
- conda-forge
4+
dependencies:
5+
- python =2.7.*
6+
- numpy
7+
- scipy
8+
- matplotlib
9+
- pytables
10+
- pandas
11+
- pyyaml
12+
- dynamicisttoolkit
13+
- oct2py
14+
- nose
15+
- sphinx
16+
- coverage
17+
- mock
18+
- numpydoc

env-dev-oldest.yml

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: gaitanalysis-dev-oldest
2+
channels:
3+
- defaults
4+
- moorepants
5+
dependencies:
6+
- python =2.7.*
7+
- numpy =1.9.1
8+
- scipy =0.14.0
9+
- matplotlib =1.4.2
10+
- pytables =3.1.1
11+
- pandas =0.15.1
12+
- pyyaml =3.11
13+
- nose
14+
- sphinx
15+
- coverage
16+
- mock
17+
- numpydoc
18+
- pip:
19+
- dynamicisttoolkit==0.3.5
20+
- oct2py==2.4.2

gaitanalysis/gait.py

+11-4
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
import os
66

77
# external libraries
8+
from pkg_resources import parse_version
89
import numpy as np
910
from scipy.integrate import simps
1011
import matplotlib.pyplot as plt
1112
import pandas
1213
from dtk import process
14+
import oct2py
1315
from oct2py import octave
1416

1517
# local
@@ -65,7 +67,7 @@ def find_constant_speed(time, speed, plot=False, filter_cutoff=1.0):
6567

6668
additional_samples = sample_rate * 0.65
6769

68-
new_indice = indice - additional_samples
70+
new_indice = indice - int(round(additional_samples))
6971

7072
if plot is True:
7173
fig, ax = plt.subplots(2, 1)
@@ -237,9 +239,14 @@ def inverse_dynamics_2d(self, left_leg_markers, right_leg_markers,
237239
# oct2py doesn't allow multiple outputs to be stored in a tuple
238240
# like python, so you have to output each variable
239241
# independently
240-
angles, velocities, moments, forces = \
241-
octave.leg2d(time, marker_array, normalized_force_array,
242-
options)
242+
if parse_version(oct2py.__version__) >= parse_version('4.0'):
243+
angles, velocities, moments, forces = \
244+
octave.leg2d(time, marker_array, normalized_force_array,
245+
options, nout=4)
246+
else:
247+
angles, velocities, moments, forces = \
248+
octave.leg2d(time, marker_array, normalized_force_array,
249+
options)
243250

244251
dynamics = angles, velocities, moments, forces
245252

gaitanalysis/motek.py

+15-7
Original file line numberDiff line numberDiff line change
@@ -1209,17 +1209,25 @@ def orient_accelerometer(orientation, x_prime, y_prime, z_prime):
12091209
y_inertial = np.zeros(np.shape(y_prime))
12101210
z_inertial = np.zeros(np.shape(z_prime))
12111211

1212-
for row, world in enumerate([x_inertial, y_inertial, z_inertial]):
1213-
for col, local in enumerate([x_prime, y_prime, z_prime]):
1214-
world += orientation[row,col] * local
1212+
for col, local in enumerate([x_prime, y_prime, z_prime]):
1213+
x_inertial += orientation[0, col] * local
1214+
1215+
for col, local in enumerate([x_prime, y_prime, z_prime]):
1216+
y_inertial += orientation[1, col] * local
1217+
1218+
for col, local in enumerate([x_prime, y_prime, z_prime]):
1219+
z_inertial += orientation[2, col] * local
12151220

12161221
return x_inertial, y_inertial, z_inertial
12171222

12181223
for sensor, rot_matrix in self.meta['trial']['sensor-orientation'].iteritems():
1219-
data_frame[sensor + '_AccX'], data_frame[sensor + '_AccY'], \
1220-
data_frame[sensor + '_AccZ'] = orient_accelerometer(
1221-
np.array(rot_matrix), data_frame[sensor + '_AccX'],
1222-
data_frame[sensor + '_AccY'], data_frame[sensor + '_AccZ'])
1224+
ax, ay, az = orient_accelerometer(np.array(rot_matrix),
1225+
data_frame[sensor + '_AccX'],
1226+
data_frame[sensor + '_AccY'],
1227+
data_frame[sensor + '_AccZ'])
1228+
data_frame[sensor + '_AccX'] = ax
1229+
data_frame[sensor + '_AccY'] = ay
1230+
data_frame[sensor + '_AccZ'] = az
12231231

12241232
return data_frame
12251233

gaitanalysis/octave/2d_inverse_dynamics/leg2d.m

+12-3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
% - missing marker data is interpolated *after* low pass filtering
3838
% - x and y coordinates of the same marker must be either both valid or both NaN (missing)
3939

40+
oct_ver = strsplit(OCTAVE_VERSION, '.');
41+
4042
% some constants
4143
Nmarkers = 6;
4244
Ncoords = 2*Nmarkers;
@@ -91,9 +93,16 @@
9193
maxmissing = max(diff(validsamples))-1; % determine largest gap
9294
fprintf('Marker %d: %d samples are missing, longest gap is %d samples.\n', i, missing, maxmissing);
9395
[xf, xd, xdd] = myfiltfilt(validtimes, d(validsamples,:), options.freq);
94-
mocap_f(:,columns) = interp1q(validtimes, xf, times); % resample filtered signal to original time stamps
95-
mocap_d(:,columns) = interp1q(validtimes, xd, times); % resample first derivative to original time stamps
96-
mocap_dd(:,columns) = interp1q(validtimes, xdd, times); % resample second derivative to original time stamps
96+
% Octave removed interp1q in version 4.2.
97+
if ((str2num(oct_ver{1}) >= 4) && (str2num(oct_ver{2}) >= 2))
98+
mocap_f(:,columns) = interp1(validtimes, xf, times); % resample filtered signal to original time stamps
99+
mocap_d(:,columns) = interp1(validtimes, xd, times); % resample first derivative to original time stamps
100+
mocap_dd(:,columns) = interp1(validtimes, xdd, times); % resample second derivative to original time stamps
101+
else
102+
mocap_f(:,columns) = interp1q(validtimes, xf, times); % resample filtered signal to original time stamps
103+
mocap_d(:,columns) = interp1q(validtimes, xd, times); % resample first derivative to original time stamps
104+
mocap_dd(:,columns) = interp1q(validtimes, xdd, times); % resample second derivative to original time stamps
105+
end
97106
end
98107

99108
% do the low-pass filtering on the force plate data

gaitanalysis/tests/test_gait.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,8 @@ def test_grf_landmarks(self, plot=False):
180180
min_idx = len(self.data_frame) / 3
181181
max_idx = 2*len(self.data_frame) / 3
182182

183-
min_time = self.data_frame.index.astype(float)[min_idx]
184-
max_time = self.data_frame.index.astype(float)[max_idx]
183+
min_time = self.data_frame.index.values.astype(float)[min_idx]
184+
max_time = self.data_frame.index.values.astype(float)[max_idx]
185185

186186
right_strikes, left_strikes, right_offs, left_offs = \
187187
gait_data.grf_landmarks('Right Vertical GRF',

0 commit comments

Comments
 (0)