Coder Social home page Coder Social logo

cadop / pycgm Goto Github PK

View Code? Open in Web Editor NEW
23.0 4.0 20.0 136.65 MB

python Convention Gait Model

Home Page: http://cadop.github.io/pyCGM

License: MIT License

Python 100.00%
biomechanical-analysis biomechanics gait-analysis kinematics motion-capture python conventional-gait-model

pycgm's Introduction

pyCGM

Python Module for the Conventional Gait Model calculates Kinematics and Center of Mass

The goal of this project is to release an easy to understand conventional gait model that users can implement in their own projects via a single python file. While the project is multiple files, the kinematics code is contained in a single file pyCGM.py. With the update, another kinetics file is also used for the center of mass calculation.

Our aim is to provide researchers and students a tool that can aid in understanding and developing modifications to the conventional gait model through python without much more.

The kinematics are validated against Nexus 1.8, and file types are known from Nexus 1.8. Newer C3D files may not work (but files re-exported from Mokka usually work).

How to use?

For getting started, please check the WIKI on github

Requirements:

  • Python 2.7 or Python 3
  • Numpy
  • Scipy (only if using the pipeline operations)

Requirements for HPC:

  • Python 2.7
  • Numpy
  • MPI Preferably Linux (MPI is not as simple to setup on windows)

Uses a modified version of the c3d.py loader from github. https://pypi.python.org/pypi/c3d/0.2.1

Credits:

Originally developed in the Digital Human Research Center at the Advanced Institutes of Convergence Technology (AICT), Seoul National University http://aict.snu.ac.kr

Project Lead: Mathew Schwartz (umcadop at gmail) For issues, use github or email me directly

Contributors: Neil M. Thomas, Philippe C. Dixon, Seungeun Yeon (연승은),Filipe Alves Caixeta, Robert Van-Wesep

Reference

Read about this code and if you find it useful in your work please cite:

Schwartz, Mathew, and Philippe C. Dixon. "The effect of subject measurement error on joint kinematics in the conventional gait model: Insights from the open-source pyCGM tool using high performance computing methods." PloS one 13.1 (2018): e0189984. https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0189984

Bibtex:

@article{schwartz2018effect, title={The effect of subject measurement error on joint kinematics in the conventional gait model: Insights from the open-source pyCGM tool using high performance computing methods}, author={Schwartz, Mathew and Dixon, Philippe C}, journal={PloS one}, volume={13}, number={1}, pages={e0189984}, year={2018}, publisher={Public Library of Science} }

pycgm's People

Contributors

ameeryhassan avatar cadop avatar dvkm avatar gveras avatar kazoni avatar khgaw avatar mattgonz avatar moppr avatar niravkin avatar thepeytongreen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

pycgm's Issues

Python 2.7 build failing in all workflows

Currently, the Python 2.7 build (build2) in the GitHub workflow is failing automatically for all commits because of a handful on compatibility issues. The earliest of these examples is located in setup.py, where the builtin function open() has a keyword argument "encoding" that only exists for Python 3 and not Python 2. There are a few more issues in addition to this one, such as the python_requires setup option which is also in setup.py, and several doctests which have some sort of version difference between the Python builds.

Marker size is hardcoded

The marker size, while seemingly always 14mm, should be provided as a measurement with a default of 14 instead.

Existing Docstrings are not in proper Numpy format

The following functions from each of these files need to have their docstrings reformatted:

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/pyCGM.py

  • pelvisJointCenter
  • hipJointCenter
  • hipAxisCenter
  • kneeJointCenter
  • ankleJointCenter
  • footJointCenter
  • headJC
  • thoraxJC
  • findwandmarker
  • findshoulderJC
  • shoulderAxisCalc
  • elbowJointCenter
  • wristJointCenter
  • handJointCenter
  • findJointC
  • cross
  • getPelangle
  • getHeadangle
  • getangle_sho
  • getangle_spi
  • getangle
  • norm2d
  • norm3d
  • normDiv
  • matrixmult
  • rotmat
  • JointAngleCalc

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/pycgm_embed.py

  • getfilenames
  • loadData
  • main

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/pycgmKinetics.py

  • f
  • dot
  • length
  • vector
  • unit
  • distance
  • scale
  • add
  • pnt2line
  • findL5_Pelvis
  • findL5_Thorax

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/pyCGM_Helpers.py

  • getfilenames

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/Pipelines.py

  • prep
  • clearMarker
  • filtering

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/pycgmStatic.py

  • rotmat
  • getDist
  • getStatic
  • average
  • IADcalculation
  • staticCalculationHead
  • headoffCalc
  • staticCalculation
  • pelvisJointCenter
  • hipJointCenter
  • hipAxisCenter
  • kneeJointCenter
  • ankleJointCenter
  • footJointCenter
  • headJC
  • uncorrect_footaxis
  • rotaxis_footflat
  • rotaxis_nonfootflat
  • getankleangle
  • findJointC
  • norm2d
  • norm3d
  • normDiv
  • matrixmult
  • cross

normDiv in pyCGM_Single/pyCGM.py

Function normDiv in pyCGM_single/pyCGM.py should be calculation the normalization, vec, and then dividing every x, y, and z by vec. Instead it divides each x, y, z by vec twice. I believe just removing the following line,

def normDiv(v):
, should fix it:
v = [v[0]/vec,v[1]/vec,v[2]/vec]

dataAsDict in pycgmIO.py has an improperly indented return statement.

def dataAsDict(data,npArray=False):
    dataDict = {}
    
    for frame in data:
        for key in frame:
            dataDict.setdefault(key,[])
            dataDict[key].append(frame[key])
    
    if npArray == True:
        for key in dataDict:
            dataDict[key] = np.array(dataDict[key])
        
        return dataDict

The return statement only executes when the boolean flag npArray is True because of its indentation. If npArray is False, the function returns nothing.

Relative imports fail when using doctest in docstrings

After having pip install the pyCGM module, a few of the relative imports do not work with doctests in docstrings.

For a example, a successful import in a doctest:

"""
>>>  from pycgmKinetics import unit
"""
if __name__ == "__main__":
    import doctest
    doctest.testmod()

Will yield the result:

Trying:
from pycgmKinetics import unit
Expecting nothing
Test passed.

While an doctest like this :

"""
>>> from pyCGM import cross
"""

if __name__ == "__main__":
    import doctest
    doctest.testmod()

Yields the error:

Failed example:
from pyCGM import cross
Exception raised:
Traceback (most recent call last):
File "C:\Users\GabrielVeras.windows-build-tools\python27\lib\doctest.py", line 1315, in __run
compileflags, 1) in test.globs
File "<doctest test file[0]>", line 1, in
from pyCGM import cross
File "pyCGM.py", line 30, in
from .pycgmIO import *
ValueError: Attempted relative import in non-package
Test Failed 1 failures.

In general, attempting to import from pyCGM or importing any method from the pyCGM file results in the same error.

pyCGM_Single/pycgmClusters.py imports and uses a non-existent function

The file pycgmClusters.py contains one function, calcFramesClusters which imports a function from clusterCalc.py named groupInClustDict that does not exist.

On line 15, the function is imported:
from .clusterCalc import targetName, getMarkerLocation, targetDict, groupInClustDict ,getStaticTransform

On line 18, the function is used:
clusters = groupInClustDict()

Marker Names are Hardcoded

Currently marker names are hardcoded everywhere. This makes it hard to load a file that has, for example, a string appended subject:LFHD. It would be good to have a function that allows people to overwrite marker names easily. Perhaps this is done while loading the file as a mapping, or is done as a mapping after.

A pycgmStatic.py doctest results in a import math error

When running the command:
pytest --doctest-modules --continue-on-collection-errors --ignore=HPC/ --ignore=Muliprocessing/
in the main directory, I get the error:
UNEXPECTED EXCEPTION: NameError("name 'math' is not defined")
R_alpha = np.around(math.degrees(static_info[0][0]*-1),decimals=5)
NameError: name 'math' is not defined
specifically for a doctest that I created for the function footJointCenter in pycgmStatic.py. In my doctest I used both import math and from math import * and neither resolved this issue, even though import math should have.

Incorrect Syntax in pyCGM_Single/Pipelines.py

Minor incorrect syntax for the function prep in Pipelines.py.

When running the function prep with correct parameters, the following for loop generates an error:

 for key, val in trajs.iteritems():
                temp.update({key:val[i,:]})

The specific error raised:

    temp.update({key:val[i,:]})
TypeError: list indices must be integers or slices, not tuple

It is due to the slice being an incorrect format, instead i think it should just be temp.update({key:val[i:]}).
It is also worth noting that it is for both for loops in the function.

Setup Workflows

Setup the github workflows to test pull requests (although kind of needs doc and unit tests first).

Create a setup file

Make a setup file for pip install. Will also help with doctests dealing with relative imports.

Many functions are missing Docstrings

The following functions from each of these files need to have docstrings written for them in Numpy format:

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/clusterCalc.py

  • normalize
  • printMat
  • getMarkerLocation
  • getStaticTransform
  • targetName
  • target_dict
  • segment_dict

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/Pipelines.py

  • butterFilter
  • filt
  • transform_from_static
  • transform_from_mov
  • segmentFinder
  • rigid_fill

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/pycgmCalc.py

  • calcKinetics
  • calcAngles
  • Calc
  • calcFrames

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/pycgmClusters.py

  • calcFramesClusters

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/pycgmKinetics.py

  • getKinetics

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/pycgmIO.py

  • createMotionDataDict
  • splitMotionDataDict
  • createVskDataDict
  • splitVskDataDict
  • markerKeys
  • loadEZC3D
  • loadC3D
  • loadCSV
  • loadData
  • dataAsArray
  • dataAsDict
  • writeKinetics
  • writeResult
  • smKeys
  • loadVSK
  • splitDataDict
  • combineDataDict
  • make_sure_path_exists

Some pyCGM.py unit tests still mock frame and vsk dictionaries

Many functions in pyCGM_Single/pyCGM.py used to take in:

frame: a dictionary of marker names to positions

 {
    "RTIB": np.array([433.97537231, 211.93408203, 273.3008728]),
    "LTIB": np.array([50.04016495,  235.90718079, 364.32226562]),
    "RANK": np.array([422.77005005, 217.74053955,  92.86152649]),
    "LANK": np.array([58.57380676,  208.54806519,  86.16953278]),
    ...
},

and vsk: a dictionary of subject measurement names to values

{
    "RightAnkleWidth": 70.0,
    "LeftAnkleWidth": 70.0,
    "RightTibialTorsion": 0.0,
    "LeftTibialTorsion": 0.0,
    ...
}

Some tests such as test_calc_axis_ankle still take in frame and vsk, but pull out the values:

rtib = frame["RTIB"] if "RTIB" in frame else None

before passing them directly to their respective functions:
result = pyCGM.calc_axis_ankle(rtib, ltib, rank, lank, r_knee_jc, l_knee_jc, rank_width, lank_width, rtib_torsion, ltib_torsion)

While this is still a proper test, it would be more straightforward to properly parametrize the values instead of continuing to use the dictionaries.

new

Hi,
I come across your dev.
I dont know if your projet is still in progress.
If yes, i can say you i have a full-python code of the Vicon Plugin Gait Model.
Both kinematics and kinetics, were compared and verfified.

feel free to contact me if you were inerested in.

cheers

fabien

No Unit Tests have been implemented

The following functions from each of these files need to unit tests written for them:

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/clusterCalc.py

  • normalize
  • printMat
  • getMarkerLocation
  • getStaticTransform
  • targetName
  • target_dict
  • segment_dict

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/Pipelines.py

  • butterFilter
  • filt
  • prep
  • clearMarker
  • filtering
  • transform_from_static
  • transform_from_mov
  • segmentFinder
  • rigid_fill

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/pyCGM.py

  • pelvisJointCenter
  • hipJointCenter
  • hipAxisCenter
  • kneeJointCenter
  • ankleJointCenter
  • footJointCenter
  • headJC
  • thoraxJC
  • findwandmarker
  • findshoulderJC
  • shoulderAxisCalc
  • elbowJointCenter
  • wristJointCenter
  • handJointCenter
  • findJointC
  • cross
  • getPelangle
  • getHeadangle
  • getangle_sho
  • getangle_spi
  • getangle
  • norm2d
  • norm3d
  • normDiv
  • matrixmult
  • rotmat
  • JointAngleCalc

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/pycgmCalc.py

  • calcKinetics
  • calcAngles
  • Calc
  • calcFrames

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/pycgmClusters.py

  • calcFramesClusters

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/pycgmIO.py

  • createMotionDataDict
  • splitMotionDataDict
  • createVskDataDict
  • splitVskDataDict
  • markerKeys
  • loadEZC3D
  • loadC3D
  • loadCSV
  • loadData
  • dataAsArray
  • dataAsDict
  • writeKinetics
  • writeResult
  • smKeys
  • loadVSK
  • splitDataDict
  • combineDataDict
  • make_sure_path_exists

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/pycgmKinetics.py

  • f
  • dot
  • length
  • vector
  • unit
  • distance
  • scale
  • add
  • pnt2line
  • findL5_Pelvis
  • findL5_Thorax
  • getKinetics

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/pycgmStatic.py

  • rotmat
  • getDist
  • getStatic
  • average
  • IADcalculation
  • staticCalculationHead
  • headoffCalc
  • staticCalculation
  • pelvisJointCenter
  • hipJointCenter
  • hipAxisCenter
  • kneeJointCenter
  • ankleJointCenter
  • footJointCenter
  • headJC
  • uncorrect_footaxis
  • rotaxis_footflat
  • rotaxis_nonfootflat
  • getankleangle
  • findJointC
  • norm2d
  • norm3d
  • normDiv
  • matrixmult
  • cross

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/pycgm_embed.py

  • getfilenames
  • loadData
  • main

https://github.com/cadop/pyCGM/blob/master/pyCGM_Single/pyCGM_Helpers.py

  • getfilenames

Refactored pelvis axis unit test only accurate to 5 decimal places

The original test for pyCGM_Single/pyCGM.py/pelvisJointCenter expects the z component of the pelvis origin to equal 1032.89349365.

[np.array([251.60830688, 391.74131775, 1032.89349365]),

The new test for pelvisJointCenter (now pyCGM_Single/pyCGM.py/calc_axis_pelvis) expects the same value but in scientific notation: 1.03289349e+03

https://github.com/MattGonz/pyCGM/blob/15a9030e9c6e0835ab12f0e2bde0315488ce9b55/pyCGM_Single/tests/test_pycgm_axis.py#L973

It seems that when 1.03289349e+03 is evaluated and asserted almost equal to 1032.89349365 using np.testing.assert_almost_equal to six decimal places, the test fails.

image

Manual assertion: np.testing.assert_almost_equal(1032.89349365, 1032.89349, 6)

AssertionError:
Arrays are not almost equal to 6 decimals
 ACTUAL: 1032.89349365
 DESIRED: 1032.89349

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.