# 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"
}