pyc3dtools


Namepyc3dtools JSON
Version 0.3.2 PyPI version JSON
download
home_pagehttps://github.com/etoshey/pyc3dtools
SummaryC3Dtools API package - Read c3d files
upload_time2023-11-23 12:48:22
maintainer
docs_urlNone
authorSoroosh.b.k (C3Dtools.com)
requires_python
licenseMIT
keywords python c3d motion capture biomechanics
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # pyc3dtools 
This is python package that you can use it to read your c3d file. Actually, this is an [C3Dtools.com](https://c3dtools.com) API. 

```diff
- I called it MAHSA
```
The [C3Dtools.com](https://c3dtools.com) is a free web-based biomechanical toolbox.
On [C3Dtools.com](https://c3dtools.com) you can :

        - Lower Body Inverse Kinematic - Plug-in Gait Model NEW
        - Convert C3D file to ASCII and create .TRC and .MOT that is compatible with the Opensim
        - Convert Xsens IMU sensors data to .sto to use in Opensim(Opensens)
        - Detect Gait events based on kinematic data
        - Calculate spatiotemporal gait parameters based on kinematic data
        - Apply Butterworth low-pass and high-pass digital filtering
        - Free C3D files repository
        - Trim C3D file   


# Install
```
pip install pyc3dtools
```




# Usage
First of all, create an account ([Register](https://c3dtools.com/register)) and then log in to your account, you can find the API token on the home page

and then import pyc3dtools package
```python
import pyc3dtools
```
Finally pass the API token and your file path to the readC3D function as inputs,
```python
c3d =  pyc3dtools.readC3D(TOKEN,'TYPE-2.C3D')
```

# Get data
### 1.Header section
```python
Number_of_Markers = c3d['Header']['Number_of_Points']
First_Frame = c3d['Header']['first_frame']
Last_Frame = c3d['Header']['last_frame']
Video_Sampling_Rate = c3d['Header']['Video_Frame_Rate']
Number_of_Analog_Channels = c3d['Header']['Analog_number_channel']
Analog_Sample_Rate = c3d['Header']['Analog_Frame_Rate']
Analog_sample_per_video_frame = c3d['Header']['Analog_sample_per_Frame']
```
#### 2.Marker & Analog Labels
```python
Markers_Label = c3d['Markers Label']
Analog_Label = c3d['Analog Label']
```

#### 3. Markers

```python
### c3d['Markers'][frame][marker][:3]

p1 = c3d['Markers'][0][0][:3] # Get the position of the first marker (x,y,z) in the first frame 
p2 = c3d['Markers'][100][0][:3] # Get the position of the first marker (x,y,z) in the 100th frame
p3 = c3d['Markers'][100][1][:3] # Get the position of the second marker (x,y,z) in the 100th frame
```
#### 5. Units and Coordinate System

```python
Units = c3d['Units']
coordinate_System = c3d['Coordinate system'] #[X_SCREEN, Y_SCREEN]
```

#### 6. ForcePlate Type 2,3,4,5

```python
### c3d['ForcePlate'][Plate Number]['FZ'][Frame][Analog Frame per Video Frame]

Number_Of_Forceplates = len(result['ForcePlate'])
Force = c3d['ForcePlate'][0]['FX'][100] ,c3d['ForcePlate'][0]['FY'][100],c3d['ForcePlate'][0]['FZ'][100] 
Force = c3d['ForcePlate'][0]['FX'][100][10] ,c3d['ForcePlate'][0]['FY'][100][10],c3d['ForcePlate'][0]['FZ'][100][10] 
Corners c3d['ForcePlate'][0]['corners']
Origin = c3d['ForcePlate'][0]['Origin']

### c3d['ForcePlate'][Plate Number]['COP'][Frame][X|Y|Z][Frame][Analog Frame per Video Frame]
Xcop_frame_50_1 = c3d['ForcePlate'][0]['COP'][50][0][1]
Ycop_frame_50_1 = c3d['ForcePlate'][0]['COP'][50][1][1]
Zcop_frame_50_1 = c3d['ForcePlate'][0]['COP'][50][2][1]
```

# Sample
```python

import sys
import pyc3dtools
import matplotlib.pyplot as plt
import numpy as np

TOKEN = "YOUR TOKEN"

result =  pyc3dtools.readC3D(TOKEN,'TYPE-2.C3D')

if result['Status']=='Failed':
  print(f"Failed to Read File... | {result['error']}") 
  sys.exit(0)

print('---------------------------- C3Dtools.Com ----------------------------')
print(f"Header::Number of Markers = {result['Header']['Number_of_Points']}")
print(f"Header::First Frame = {result['Header']['first_frame']}")
print(f"Header::Last Frame = {result['Header']['last_frame']}")
print(f"Header::Video Sampling Rate = {result['Header']['Video_Frame_Rate']}")
print(f"Header::Analog Channels = {result['Header']['Analog_number_channel']}")
print(f"Header:: Analog Sample Rate = {result['Header']['Analog_Frame_Rate']}")
print(f"Header:: Analog sample per video frame = {result['Header']['Analog_sample_per_Frame']}")


print('----------------------------------------------------------------------')
print(f"GP::Markers Label = {result['Markers Label']}")
print(f"GP::Analog Label = {result['Analog Label']}")
print('----------------------------------------------------------------------')
print(f"Markers:: Frame->0 , {result['Markers Label'][0]}  = {result['Markers'][0][0][:3]}")
print(f"Markers:: Frame->100 , {result['Markers Label'][0]}  = {result['Markers'][100][0][:3]}")
print(f"Markers:: Frame->150 , {result['Markers Label'][1]}  = {result['Markers'][150][1][:3]}")
print(f"Markers:: Units = {result['Units']}")
print(f"coordinate System [X_SCREEN, Y_SCREEN] = {result['Coordinate system']}")
print('----------------------------------------------------------------------')
print(f"Number Of Forceplates = {len(result['ForcePlate'])}")
#print(f"First plate:: FX, FY, FZ :: Frame->100 = ({result['ForcePlate'][0]['FX'][100] ,result['ForcePlate'][0]['FY'][100],result['ForcePlate'][0]['FZ'][100] })") # Analog sample per video frame is equal 20 
print(f"First plate:: FX, FY, FZ :: Frame->100 :: Analog Sample 10 = {result['ForcePlate'][0]['FX'][100][10] ,result['ForcePlate'][0]['FY'][100][10],result['ForcePlate'][0]['FZ'][100][10] }") # Analog sample per video frame is equal 20 
print(f"First plate:: Corners = {result['ForcePlate'][0]['corners']}")
print(f"First plate:: Origin = {result['ForcePlate'][0]['Origin']}")
print(f"First plate:: COP :: X,Y,Z :: Frame->50 :: Analog Sample 1 = {result['ForcePlate'][0]['COP'][50][0][1],result['ForcePlate'][0]['COP'][50][1][1],result['ForcePlate'][0]['COP'][50][2][1]}") # Analog sample per video frame is equal 20 



#plot data
Marker1 = result['Markers'][:,1,:3]

FZ = np.array(result['ForcePlate'][0]['FZ'])
FZ = FZ.flatten()


COP = result['ForcePlate'][0]['COP'][:,:,:]
COP_X = COP[:,0,:]
COP_Y = COP[:,1,:]
COP_X = COP_X.flatten()
COP_Y = COP_Y.flatten()


Vec_GRF = result['ForcePlate'][0]['GRF_VECTOR'][:,:,:]
Vec_GRF_X = Vec_GRF[:,0,:]
Vec_GRF_Y = Vec_GRF[:,1,:]
Vec_GRF_Z = Vec_GRF[:,2,:]
Vec_GRF_X = Vec_GRF_X.flatten()
Vec_GRF_Y = Vec_GRF_Y.flatten()
Vec_GRF_Z = Vec_GRF_Z.flatten()


fig = plt.figure()
axs = fig.subplots(2, 2)
axs[0, 0].plot(Marker1[:,0], color='r', label='X')
axs[0, 0].plot(Marker1[:,1], color='g', label='Y')
axs[0, 0].plot(Marker1[:,2], color='b', label='Z')
axs[0, 0].set_title('Marker Position')
axs[0, 1].plot(FZ, 'tab:orange')
axs[0, 1].set_title('GRF Z')
axs[1, 0].plot(COP_X, color='g', label='copX')
axs[1, 0].plot(COP_Y, color='b', label='copY')
axs[1, 0].set_title('COP')
axs[1, 1].plot(Vec_GRF_X, color='g', label='GRFX')
axs[1, 1].plot(Vec_GRF_Y, color='b', label='GRFY')
axs[1, 1].plot(Vec_GRF_Z, color='r', label='GRFZ')
axs[1, 1].set_title('GRF vector')




NumFrames = result['Header']['last_frame'] - result['Header']['first_frame']

Forceplates = result['ForcePlate']
cop_data = []
grf_vector = []
corners = []
for fp in Forceplates:  
  #COP 
  cop_data.append(fp['COP'])
  #GRF
  grf_vector.append(fp['GRF_VECTOR'])
  #Corners
  for c in range(4):    
    corners.extend(fp['corners'])



# COP & GRF
main_cop_data =[]
main_grf_data =[]

for i in range(NumFrames):   
  for fp in range(len(Forceplates)):
    main_cop_data.append([cop_data[fp][i,0,0] , cop_data[fp][i,1,0]])
    main_grf_data.append([grf_vector[fp][i,0,0] , grf_vector[fp][i,1,0], grf_vector[fp][i,2,0]])  



# Get Analog data
Analog_Label = result['Analog Label']
Analog_Data = result['Analog']

ch0 = Analog_Data[:,:,0]
ch1 = Analog_Data[:,:,1]
ch2 = Analog_Data[:,:,2]




plt.show()

print('OK')

```


# Export .mot and .trc
If you need to convert your c3d file to compatible files for OpenSim software you can use *getTRCMot* function. This function returns all c3d file data and also write .mot and .trc file in a directory

```python
import pyc3dtools
TOKEN = "YOUR_TOKEN"
#result =  pyc3dtools.getTRCMot(TOKEN,'Input C3D File','Destination directory')
result =  pyc3dtools.getTRCMot(TOKEN,'TYPE-2.C3D','./exportData')
```

## Export .mot and .trc Sample code
```python
import pyc3dtools
TOKEN = "YOUR_TOKEN"
result =  pyc3dtools.getTRCMot(TOKEN,'TYPE-2.C3D','./exportData')
if result['Status'] == 'Success':
    print('Done.')
```


# Inverse Kinematic : Plug-in Gait
By this API can compute the joint's kinematics. Just pass a static trial, a dynamic trial and anthropometry data of your subject.

```python
import pyc3dtools
import matplotlib.pyplot as plt
import numpy as np

TOKEN = "YOUR TOKEN"

Anthropometry = [('Left_Leg_Length',800), # mm
                  ('Right_Leg_Length',800),
                  ('Knee_Width',100),
                  ('Ankle_Width',90),
                  ('Marker_Radius',14)]


Markers_label = [('LASI','LASI'), # (Fixed label , your label in c3d file)
                 ('RASI','RASI'), # (Fixed label , your label in c3d file)
                 ('LPSI','LPSI'), # (Fixed label , your label in c3d file)
                 ('RPSI','RPSI'), # (Fixed label , your label in c3d file)
                 #('SACR','SACR'), # (Fixed label , your label in c3d file) - Optional
                 ('LTHI','LTHI'), # (Fixed label , your label in c3d file)
                 ('RTHI','RTHI'), # (Fixed label , your label in c3d file)
                 ('LKNE','LKNE'), # (Fixed label , your label in c3d file)
                 ('RKNE','RKNE'), # (Fixed label , your label in c3d file)
                 ('LTIB','LTIB'), # (Fixed label , your label in c3d file)
                 ('RTIB','RTIB'), # (Fixed label , your label in c3d file)
                 ('LANK','LANK'), # (Fixed label , your label in c3d file)
                 ('RANK','RANK'), # (Fixed label , your label in c3d file)
                 ('LHEE','LHEE'), # (Fixed label , your label in c3d file)
                 ('RHEE','RHEE'), # (Fixed label , your label in c3d file)
                 ('LTOE','LTOE'), # (Fixed label , your label in c3d file)
                 ('RTOE','RTOE')] # (Fixed label , your label in c3d file)


#pyc3dtools.IKPiG(TOKEN, Static Trial,Dynamic Trial, Markers_label,Anthropometry,[start Frame, end Frame] *Optional)
result =  pyc3dtools.IKPiG(TOKEN,'Cal 01.C3D','Walking 01.C3D',Markers_label,Anthropometry)



if result['Status'] == 'Success':
    print('Done.')
    t = np.arange(0,len(result['IK_Result'][0]['angle']))  

    fig, axs = plt.subplots(3, 2)
    # HIP Joint
    LHIP = next((obj for obj in result['IK_Result'] if obj['name'] == 'LHIP'),  None)
    RHIP = next((obj for obj in result['IK_Result'] if obj['name'] == 'RHIP'),  None)
    LHIP_angle_x = [item[0] for item in LHIP['angle']]
    LHIP_angle_y = [item[1] for item in LHIP['angle']]
    LHIP_angle_z = [item[2] for item in LHIP['angle']]
    axs[0,0].plot(t,LHIP_angle_x,t,LHIP_angle_y,t,LHIP_angle_z)
    axs[0,0].legend(['Flex/Ext','Abd/Add','Ex/Int Rotation'])
    axs[0,0].set_ylabel('Left HIP')

    RHIP_angle_x = [item[0] for item in RHIP['angle']]
    RHIP_angle_y = [item[1] for item in RHIP['angle']]
    RHIP_angle_z = [item[2] for item in RHIP['angle']]     
    axs[0,1].plot(t,RHIP_angle_x,t,RHIP_angle_y,t,RHIP_angle_z)
    axs[0,1].legend(['Flex/Ext','Abd/Add','Ex/Int Rotation'])
    axs[0,1].set_ylabel('Right HIP')

    # KNEE Joint
    LKNEE = next((obj for obj in result['IK_Result'] if obj['name'] == 'LKNEE'),  None)
    RKNEE = next((obj for obj in result['IK_Result'] if obj['name'] == 'RKNEE'),  None)
    LKNEE_angle_x = [item[0] for item in LKNEE['angle']]
    LKNEE_angle_y = [item[1] for item in LKNEE['angle']]
    LKNEE_angle_z = [item[2] for item in LKNEE['angle']]
    axs[1,0].plot(t,LKNEE_angle_x,t,LKNEE_angle_y,t,LKNEE_angle_z)
    axs[1,0].legend(['Flex/Ext','Abd/Add','Ex/Int Rotation'])
    axs[1,0].set_ylabel('Left Knee')

    RKNEE_angle_x = [item[0] for item in RKNEE['angle']]
    RKNEE_angle_y = [item[1] for item in RKNEE['angle']]
    RKNEE_angle_z = [item[2] for item in RKNEE['angle']] 
    axs[1,1].plot(t,RKNEE_angle_x,t,RKNEE_angle_y,t,RKNEE_angle_z)
    axs[1,1].legend(['Flex/Ext','Abd/Add','Ex/Int Rotation'])
    axs[1,1].set_ylabel('Right Knee')


    # ANKLe Joint
    LANK = next((obj for obj in result['IK_Result'] if obj['name'] == 'LANK'),  None)
    RANK = next((obj for obj in result['IK_Result'] if obj['name'] == 'RANK'),  None)
    LANK_angle_x = [item[0] for item in LANK['angle']]
    LANK_angle_y = [item[1] for item in LANK['angle']]
    LANK_angle_z = [item[2] for item in LANK['angle']]
    axs[2,0].plot(t,LANK_angle_x,t,LANK_angle_y,t,LANK_angle_z)
    axs[2,0].legend(['Flex/Ext','Abd/Add','Ex/Int Rotation'])
    axs[2,0].set_ylabel('Left Ankle')

    RANK_angle_x = [item[0] for item in RANK['angle']]
    RANK_angle_y = [item[1] for item in RANK['angle']]
    RANK_angle_z = [item[2] for item in RANK['angle']] 
    axs[2,1].plot(t,RANK_angle_x,t,RANK_angle_y,t,RANK_angle_z)
    axs[2,1].legend(['Flex/Ext','Abd/Add','Ex/Int Rotation'])
    axs[2,1].set_ylabel('right Ankle')
   

    plt.show()    

```
## Inverse Kinematic Sample Output
![C3Dtools](https://github.com/etoshey/pyc3dtools/blob/da4f2fd2220088b04a6435c8667d12b5370fd10d/Test/IK%20result.png)



```diff
+ Women Life Freedom
```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/etoshey/pyc3dtools",
    "name": "pyc3dtools",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "python,c3d,motion capture,biomechanics",
    "author": "Soroosh.b.k (C3Dtools.com)",
    "author_email": "<soroosh.b.k@gmail.com>",
    "download_url": "",
    "platform": null,
    "description": "# pyc3dtools \r\nThis is python package that you can use it to read your c3d file. Actually, this is an [C3Dtools.com](https://c3dtools.com) API. \r\n\r\n```diff\r\n- I called it MAHSA\r\n```\r\nThe [C3Dtools.com](https://c3dtools.com) is a free web-based biomechanical toolbox.\r\nOn [C3Dtools.com](https://c3dtools.com) you can :\r\n\r\n        - Lower Body Inverse Kinematic - Plug-in Gait Model NEW\r\n        - Convert C3D file to ASCII and create .TRC and .MOT that is compatible with the Opensim\r\n        - Convert Xsens IMU sensors data to .sto to use in Opensim(Opensens)\r\n        - Detect Gait events based on kinematic data\r\n        - Calculate spatiotemporal gait parameters based on kinematic data\r\n        - Apply Butterworth low-pass and high-pass digital filtering\r\n        - Free C3D files repository\r\n        - Trim C3D file   \r\n\r\n\r\n# Install\r\n```\r\npip install pyc3dtools\r\n```\r\n\r\n\r\n\r\n\r\n# Usage\r\nFirst of all, create an account ([Register](https://c3dtools.com/register)) and then log in to your account, you can find the API token on the home page\r\n\r\nand then import pyc3dtools package\r\n```python\r\nimport pyc3dtools\r\n```\r\nFinally pass the API token and your file path to the readC3D function as inputs,\r\n```python\r\nc3d =  pyc3dtools.readC3D(TOKEN,'TYPE-2.C3D')\r\n```\r\n\r\n# Get data\r\n### 1.Header section\r\n```python\r\nNumber_of_Markers = c3d['Header']['Number_of_Points']\r\nFirst_Frame = c3d['Header']['first_frame']\r\nLast_Frame = c3d['Header']['last_frame']\r\nVideo_Sampling_Rate = c3d['Header']['Video_Frame_Rate']\r\nNumber_of_Analog_Channels = c3d['Header']['Analog_number_channel']\r\nAnalog_Sample_Rate = c3d['Header']['Analog_Frame_Rate']\r\nAnalog_sample_per_video_frame = c3d['Header']['Analog_sample_per_Frame']\r\n```\r\n#### 2.Marker & Analog Labels\r\n```python\r\nMarkers_Label = c3d['Markers Label']\r\nAnalog_Label = c3d['Analog Label']\r\n```\r\n\r\n#### 3. Markers\r\n\r\n```python\r\n### c3d['Markers'][frame][marker][:3]\r\n\r\np1 = c3d['Markers'][0][0][:3] # Get the position of the first marker (x,y,z) in the first frame \r\np2 = c3d['Markers'][100][0][:3] # Get the position of the first marker (x,y,z) in the 100th frame\r\np3 = c3d['Markers'][100][1][:3] # Get the position of the second marker (x,y,z) in the 100th frame\r\n```\r\n#### 5. Units and Coordinate System\r\n\r\n```python\r\nUnits = c3d['Units']\r\ncoordinate_System = c3d['Coordinate system'] #[X_SCREEN, Y_SCREEN]\r\n```\r\n\r\n#### 6. ForcePlate Type 2,3,4,5\r\n\r\n```python\r\n### c3d['ForcePlate'][Plate Number]['FZ'][Frame][Analog Frame per Video Frame]\r\n\r\nNumber_Of_Forceplates = len(result['ForcePlate'])\r\nForce = c3d['ForcePlate'][0]['FX'][100] ,c3d['ForcePlate'][0]['FY'][100],c3d['ForcePlate'][0]['FZ'][100] \r\nForce = c3d['ForcePlate'][0]['FX'][100][10] ,c3d['ForcePlate'][0]['FY'][100][10],c3d['ForcePlate'][0]['FZ'][100][10] \r\nCorners c3d['ForcePlate'][0]['corners']\r\nOrigin = c3d['ForcePlate'][0]['Origin']\r\n\r\n### c3d['ForcePlate'][Plate Number]['COP'][Frame][X|Y|Z][Frame][Analog Frame per Video Frame]\r\nXcop_frame_50_1 = c3d['ForcePlate'][0]['COP'][50][0][1]\r\nYcop_frame_50_1 = c3d['ForcePlate'][0]['COP'][50][1][1]\r\nZcop_frame_50_1 = c3d['ForcePlate'][0]['COP'][50][2][1]\r\n```\r\n\r\n# Sample\r\n```python\r\n\r\nimport sys\r\nimport pyc3dtools\r\nimport matplotlib.pyplot as plt\r\nimport numpy as np\r\n\r\nTOKEN = \"YOUR TOKEN\"\r\n\r\nresult =  pyc3dtools.readC3D(TOKEN,'TYPE-2.C3D')\r\n\r\nif result['Status']=='Failed':\r\n  print(f\"Failed to Read File... | {result['error']}\") \r\n  sys.exit(0)\r\n\r\nprint('---------------------------- C3Dtools.Com ----------------------------')\r\nprint(f\"Header::Number of Markers = {result['Header']['Number_of_Points']}\")\r\nprint(f\"Header::First Frame = {result['Header']['first_frame']}\")\r\nprint(f\"Header::Last Frame = {result['Header']['last_frame']}\")\r\nprint(f\"Header::Video Sampling Rate = {result['Header']['Video_Frame_Rate']}\")\r\nprint(f\"Header::Analog Channels = {result['Header']['Analog_number_channel']}\")\r\nprint(f\"Header:: Analog Sample Rate = {result['Header']['Analog_Frame_Rate']}\")\r\nprint(f\"Header:: Analog sample per video frame = {result['Header']['Analog_sample_per_Frame']}\")\r\n\r\n\r\nprint('----------------------------------------------------------------------')\r\nprint(f\"GP::Markers Label = {result['Markers Label']}\")\r\nprint(f\"GP::Analog Label = {result['Analog Label']}\")\r\nprint('----------------------------------------------------------------------')\r\nprint(f\"Markers:: Frame->0 , {result['Markers Label'][0]}  = {result['Markers'][0][0][:3]}\")\r\nprint(f\"Markers:: Frame->100 , {result['Markers Label'][0]}  = {result['Markers'][100][0][:3]}\")\r\nprint(f\"Markers:: Frame->150 , {result['Markers Label'][1]}  = {result['Markers'][150][1][:3]}\")\r\nprint(f\"Markers:: Units = {result['Units']}\")\r\nprint(f\"coordinate System [X_SCREEN, Y_SCREEN] = {result['Coordinate system']}\")\r\nprint('----------------------------------------------------------------------')\r\nprint(f\"Number Of Forceplates = {len(result['ForcePlate'])}\")\r\n#print(f\"First plate:: FX, FY, FZ :: Frame->100 = ({result['ForcePlate'][0]['FX'][100] ,result['ForcePlate'][0]['FY'][100],result['ForcePlate'][0]['FZ'][100] })\") # Analog sample per video frame is equal 20 \r\nprint(f\"First plate:: FX, FY, FZ :: Frame->100 :: Analog Sample 10 = {result['ForcePlate'][0]['FX'][100][10] ,result['ForcePlate'][0]['FY'][100][10],result['ForcePlate'][0]['FZ'][100][10] }\") # Analog sample per video frame is equal 20 \r\nprint(f\"First plate:: Corners = {result['ForcePlate'][0]['corners']}\")\r\nprint(f\"First plate:: Origin = {result['ForcePlate'][0]['Origin']}\")\r\nprint(f\"First plate:: COP :: X,Y,Z :: Frame->50 :: Analog Sample 1 = {result['ForcePlate'][0]['COP'][50][0][1],result['ForcePlate'][0]['COP'][50][1][1],result['ForcePlate'][0]['COP'][50][2][1]}\") # Analog sample per video frame is equal 20 \r\n\r\n\r\n\r\n#plot data\r\nMarker1 = result['Markers'][:,1,:3]\r\n\r\nFZ = np.array(result['ForcePlate'][0]['FZ'])\r\nFZ = FZ.flatten()\r\n\r\n\r\nCOP = result['ForcePlate'][0]['COP'][:,:,:]\r\nCOP_X = COP[:,0,:]\r\nCOP_Y = COP[:,1,:]\r\nCOP_X = COP_X.flatten()\r\nCOP_Y = COP_Y.flatten()\r\n\r\n\r\nVec_GRF = result['ForcePlate'][0]['GRF_VECTOR'][:,:,:]\r\nVec_GRF_X = Vec_GRF[:,0,:]\r\nVec_GRF_Y = Vec_GRF[:,1,:]\r\nVec_GRF_Z = Vec_GRF[:,2,:]\r\nVec_GRF_X = Vec_GRF_X.flatten()\r\nVec_GRF_Y = Vec_GRF_Y.flatten()\r\nVec_GRF_Z = Vec_GRF_Z.flatten()\r\n\r\n\r\nfig = plt.figure()\r\naxs = fig.subplots(2, 2)\r\naxs[0, 0].plot(Marker1[:,0], color='r', label='X')\r\naxs[0, 0].plot(Marker1[:,1], color='g', label='Y')\r\naxs[0, 0].plot(Marker1[:,2], color='b', label='Z')\r\naxs[0, 0].set_title('Marker Position')\r\naxs[0, 1].plot(FZ, 'tab:orange')\r\naxs[0, 1].set_title('GRF Z')\r\naxs[1, 0].plot(COP_X, color='g', label='copX')\r\naxs[1, 0].plot(COP_Y, color='b', label='copY')\r\naxs[1, 0].set_title('COP')\r\naxs[1, 1].plot(Vec_GRF_X, color='g', label='GRFX')\r\naxs[1, 1].plot(Vec_GRF_Y, color='b', label='GRFY')\r\naxs[1, 1].plot(Vec_GRF_Z, color='r', label='GRFZ')\r\naxs[1, 1].set_title('GRF vector')\r\n\r\n\r\n\r\n\r\nNumFrames = result['Header']['last_frame'] - result['Header']['first_frame']\r\n\r\nForceplates = result['ForcePlate']\r\ncop_data = []\r\ngrf_vector = []\r\ncorners = []\r\nfor fp in Forceplates:  \r\n  #COP \r\n  cop_data.append(fp['COP'])\r\n  #GRF\r\n  grf_vector.append(fp['GRF_VECTOR'])\r\n  #Corners\r\n  for c in range(4):    \r\n    corners.extend(fp['corners'])\r\n\r\n\r\n\r\n# COP & GRF\r\nmain_cop_data =[]\r\nmain_grf_data =[]\r\n\r\nfor i in range(NumFrames):   \r\n  for fp in range(len(Forceplates)):\r\n    main_cop_data.append([cop_data[fp][i,0,0] , cop_data[fp][i,1,0]])\r\n    main_grf_data.append([grf_vector[fp][i,0,0] , grf_vector[fp][i,1,0], grf_vector[fp][i,2,0]])  \r\n\r\n\r\n\r\n# Get Analog data\r\nAnalog_Label = result['Analog Label']\r\nAnalog_Data = result['Analog']\r\n\r\nch0 = Analog_Data[:,:,0]\r\nch1 = Analog_Data[:,:,1]\r\nch2 = Analog_Data[:,:,2]\r\n\r\n\r\n\r\n\r\nplt.show()\r\n\r\nprint('OK')\r\n\r\n```\r\n\r\n\r\n# Export .mot and .trc\r\nIf you need to convert your c3d file to compatible files for OpenSim software you can use *getTRCMot* function. This function returns all c3d file data and also write .mot and .trc file in a directory\r\n\r\n```python\r\nimport pyc3dtools\r\nTOKEN = \"YOUR_TOKEN\"\r\n#result =  pyc3dtools.getTRCMot(TOKEN,'Input C3D File','Destination directory')\r\nresult =  pyc3dtools.getTRCMot(TOKEN,'TYPE-2.C3D','./exportData')\r\n```\r\n\r\n## Export .mot and .trc Sample code\r\n```python\r\nimport pyc3dtools\r\nTOKEN = \"YOUR_TOKEN\"\r\nresult =  pyc3dtools.getTRCMot(TOKEN,'TYPE-2.C3D','./exportData')\r\nif result['Status'] == 'Success':\r\n    print('Done.')\r\n```\r\n\r\n\r\n# Inverse Kinematic : Plug-in Gait\r\nBy this API can compute the joint's kinematics. Just pass a static trial, a dynamic trial and anthropometry data of your subject.\r\n\r\n```python\r\nimport pyc3dtools\r\nimport matplotlib.pyplot as plt\r\nimport numpy as np\r\n\r\nTOKEN = \"YOUR TOKEN\"\r\n\r\nAnthropometry = [('Left_Leg_Length',800), # mm\r\n                  ('Right_Leg_Length',800),\r\n                  ('Knee_Width',100),\r\n                  ('Ankle_Width',90),\r\n                  ('Marker_Radius',14)]\r\n\r\n\r\nMarkers_label = [('LASI','LASI'), # (Fixed label , your label in c3d file)\r\n                 ('RASI','RASI'), # (Fixed label , your label in c3d file)\r\n                 ('LPSI','LPSI'), # (Fixed label , your label in c3d file)\r\n                 ('RPSI','RPSI'), # (Fixed label , your label in c3d file)\r\n                 #('SACR','SACR'), # (Fixed label , your label in c3d file) - Optional\r\n                 ('LTHI','LTHI'), # (Fixed label , your label in c3d file)\r\n                 ('RTHI','RTHI'), # (Fixed label , your label in c3d file)\r\n                 ('LKNE','LKNE'), # (Fixed label , your label in c3d file)\r\n                 ('RKNE','RKNE'), # (Fixed label , your label in c3d file)\r\n                 ('LTIB','LTIB'), # (Fixed label , your label in c3d file)\r\n                 ('RTIB','RTIB'), # (Fixed label , your label in c3d file)\r\n                 ('LANK','LANK'), # (Fixed label , your label in c3d file)\r\n                 ('RANK','RANK'), # (Fixed label , your label in c3d file)\r\n                 ('LHEE','LHEE'), # (Fixed label , your label in c3d file)\r\n                 ('RHEE','RHEE'), # (Fixed label , your label in c3d file)\r\n                 ('LTOE','LTOE'), # (Fixed label , your label in c3d file)\r\n                 ('RTOE','RTOE')] # (Fixed label , your label in c3d file)\r\n\r\n\r\n#pyc3dtools.IKPiG(TOKEN, Static Trial,Dynamic Trial, Markers_label,Anthropometry,[start Frame, end Frame] *Optional)\r\nresult =  pyc3dtools.IKPiG(TOKEN,'Cal 01.C3D','Walking 01.C3D',Markers_label,Anthropometry)\r\n\r\n\r\n\r\nif result['Status'] == 'Success':\r\n    print('Done.')\r\n    t = np.arange(0,len(result['IK_Result'][0]['angle']))  \r\n\r\n    fig, axs = plt.subplots(3, 2)\r\n    # HIP Joint\r\n    LHIP = next((obj for obj in result['IK_Result'] if obj['name'] == 'LHIP'),  None)\r\n    RHIP = next((obj for obj in result['IK_Result'] if obj['name'] == 'RHIP'),  None)\r\n    LHIP_angle_x = [item[0] for item in LHIP['angle']]\r\n    LHIP_angle_y = [item[1] for item in LHIP['angle']]\r\n    LHIP_angle_z = [item[2] for item in LHIP['angle']]\r\n    axs[0,0].plot(t,LHIP_angle_x,t,LHIP_angle_y,t,LHIP_angle_z)\r\n    axs[0,0].legend(['Flex/Ext','Abd/Add','Ex/Int Rotation'])\r\n    axs[0,0].set_ylabel('Left HIP')\r\n\r\n    RHIP_angle_x = [item[0] for item in RHIP['angle']]\r\n    RHIP_angle_y = [item[1] for item in RHIP['angle']]\r\n    RHIP_angle_z = [item[2] for item in RHIP['angle']]     \r\n    axs[0,1].plot(t,RHIP_angle_x,t,RHIP_angle_y,t,RHIP_angle_z)\r\n    axs[0,1].legend(['Flex/Ext','Abd/Add','Ex/Int Rotation'])\r\n    axs[0,1].set_ylabel('Right HIP')\r\n\r\n    # KNEE Joint\r\n    LKNEE = next((obj for obj in result['IK_Result'] if obj['name'] == 'LKNEE'),  None)\r\n    RKNEE = next((obj for obj in result['IK_Result'] if obj['name'] == 'RKNEE'),  None)\r\n    LKNEE_angle_x = [item[0] for item in LKNEE['angle']]\r\n    LKNEE_angle_y = [item[1] for item in LKNEE['angle']]\r\n    LKNEE_angle_z = [item[2] for item in LKNEE['angle']]\r\n    axs[1,0].plot(t,LKNEE_angle_x,t,LKNEE_angle_y,t,LKNEE_angle_z)\r\n    axs[1,0].legend(['Flex/Ext','Abd/Add','Ex/Int Rotation'])\r\n    axs[1,0].set_ylabel('Left Knee')\r\n\r\n    RKNEE_angle_x = [item[0] for item in RKNEE['angle']]\r\n    RKNEE_angle_y = [item[1] for item in RKNEE['angle']]\r\n    RKNEE_angle_z = [item[2] for item in RKNEE['angle']] \r\n    axs[1,1].plot(t,RKNEE_angle_x,t,RKNEE_angle_y,t,RKNEE_angle_z)\r\n    axs[1,1].legend(['Flex/Ext','Abd/Add','Ex/Int Rotation'])\r\n    axs[1,1].set_ylabel('Right Knee')\r\n\r\n\r\n    # ANKLe Joint\r\n    LANK = next((obj for obj in result['IK_Result'] if obj['name'] == 'LANK'),  None)\r\n    RANK = next((obj for obj in result['IK_Result'] if obj['name'] == 'RANK'),  None)\r\n    LANK_angle_x = [item[0] for item in LANK['angle']]\r\n    LANK_angle_y = [item[1] for item in LANK['angle']]\r\n    LANK_angle_z = [item[2] for item in LANK['angle']]\r\n    axs[2,0].plot(t,LANK_angle_x,t,LANK_angle_y,t,LANK_angle_z)\r\n    axs[2,0].legend(['Flex/Ext','Abd/Add','Ex/Int Rotation'])\r\n    axs[2,0].set_ylabel('Left Ankle')\r\n\r\n    RANK_angle_x = [item[0] for item in RANK['angle']]\r\n    RANK_angle_y = [item[1] for item in RANK['angle']]\r\n    RANK_angle_z = [item[2] for item in RANK['angle']] \r\n    axs[2,1].plot(t,RANK_angle_x,t,RANK_angle_y,t,RANK_angle_z)\r\n    axs[2,1].legend(['Flex/Ext','Abd/Add','Ex/Int Rotation'])\r\n    axs[2,1].set_ylabel('right Ankle')\r\n   \r\n\r\n    plt.show()    \r\n\r\n```\r\n## Inverse Kinematic Sample Output\r\n![C3Dtools](https://github.com/etoshey/pyc3dtools/blob/da4f2fd2220088b04a6435c8667d12b5370fd10d/Test/IK%20result.png)\r\n\r\n\r\n\r\n```diff\r\n+ Women Life Freedom\r\n```\r\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "C3Dtools API package - Read c3d files",
    "version": "0.3.2",
    "project_urls": {
        "Homepage": "https://github.com/etoshey/pyc3dtools"
    },
    "split_keywords": [
        "python",
        "c3d",
        "motion capture",
        "biomechanics"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "a5c442d475d07a5d22c775ced455a8456b94bd581564284226b8767d7a38dfa6",
                "md5": "95330defd5a4c35c0794bf3a7a0b0a13",
                "sha256": "5ca8624296bb4d755c180ab8638c3c877d4d7c6706fd9beb6a1e5c76b7dd60e4"
            },
            "downloads": -1,
            "filename": "pyc3dtools-0.3.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "95330defd5a4c35c0794bf3a7a0b0a13",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 7775,
            "upload_time": "2023-11-23T12:48:22",
            "upload_time_iso_8601": "2023-11-23T12:48:22.830486Z",
            "url": "https://files.pythonhosted.org/packages/a5/c4/42d475d07a5d22c775ced455a8456b94bd581564284226b8767d7a38dfa6/pyc3dtools-0.3.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-11-23 12:48:22",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "etoshey",
    "github_project": "pyc3dtools",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "pyc3dtools"
}
        
Elapsed time: 0.42135s