Kinematic Center of Mass: tutorial

If the center_of_mass package is not installed, run the following lines:

import sys
sys.path.insert(0, '../src')
[2]:
import center_of_mass

The example data file is loaded.

[3]:
import pickle
input_file     = '..\\examples\\example_data.pkl'
pickle_file    = open(input_file,'rb')
data           = pickle.load(pickle_file)
pickle_file.close()
sex            = data['sex']                # 'female' or 'male'
Labels         = data['Labels']             # list of marker labels
Position       = data['Position']           # dictionary with, for each marker, the position in meters (numpy.ndarray of shape (3,duration*Position_frequency)

We collect the kinematic data into a Kinematics object, which generates additional attributes: Joint_centers, SegmentCoordinateSystem, SegmentLength and SegmentOrigin.

[4]:
kinematics    = center_of_mass.Kinematics(Position, Labels, sex)

Function for visualising segments

[5]:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
%matplotlib widget
instant = 500 # timepoint at which the data will be visualised

def visualise(kinematics, segments = [], xlim = [1,2.8], ylim = [-0.9,0.9], zlim = [0,1.8], instant = instant):
    fig = plt.figure()
    ax  = fig.add_subplot(111, projection="3d")
    for marker in kinematics.Labels:
        position = kinematics.Position[marker][:,instant]
        ax.scatter(position[0],position[1],position[2], color = 'k', s=0.5)
    for segment in segments:
        origin   = kinematics.SegmentOrigin[segment][:,instant]
        if segment == 'Head':
            endpoint = origin + kinematics.SegmentLength[segment]*kinematics.SegmentCoordinateSystem[segment][1][:,instant]
        elif segment.endswith('Foot'):
            endpoint = origin + kinematics.SegmentLength[segment]*kinematics.SegmentCoordinateSystem[segment][0][:,instant]
        else:
            endpoint = origin - kinematics.SegmentLength[segment]*kinematics.SegmentCoordinateSystem[segment][1][:,instant]
        ax.scatter(origin[0],origin[1],origin[2], label = segment)
        ax.plot([origin[0],endpoint[0]],[origin[1],endpoint[1]],[origin[2],endpoint[2]])
    ax.legend()
    ax.set_xlim(xlim)
    ax.set_ylim(ylim)
    ax.set_zlim(zlim)
    return ax

The length, coordinate system and origin of each segment can be calculated using the methods of the Kinematics class.

[6]:
kinematics.calculate_Pelvis(kinematics.Labels)
visualise(kinematics, segments = ['Pelvis'])
plt.show()
[7]:
kinematics.calculate_Trunk(kinematics.Labels)
visualise(kinematics, segments = ['Torso'])
plt.show()
[9]:
kinematics.calculate_Head(kinematics.Labels)
visualise(kinematics, segments = ['Head'])
plt.show()
[11]:
kinematics.calculate_UpperLimbs(kinematics.Labels)
visualise(kinematics, segments = ['L_UpperArm','L_Forearm','L_Hand','R_UpperArm','R_Forearm','R_Hand'])
plt.show()
[13]:
kinematics.calculate_LowerLimbs(kinematics.Labels)
visualise(kinematics, segments = ['L_Thigh','L_Shank','L_Foot','R_Thigh','R_Shank','R_Foot'])
plt.show()

The simplified method can be used to calculate the trunk segments by providing a reduced list of labels.

[8]:
kinematics.calculate_Trunk(Labels = ['C7'])
visualise(kinematics, segments = ['Torso'])
plt.show()

The simplified method can be used to calculate the head segment by providing an empty label list.

[10]:
kinematics.calculate_Head([])
visualise(kinematics, segments = ['Head'])
plt.show()

The simplified method can be used to calculate the arm segments by providing a reduced list of marker labels.

[12]:
kinematics.calculate_UpperLimbs(Labels = ['LELL','LWRU','RELL','RWRU'])
visualise(kinematics, segments = ['L_UpperArm','L_Forearm','L_Hand','R_UpperArm','R_Forearm','R_Hand'])
plt.show()

The simplified method can be used to calculate the leg segments by providing a reduced list of marker labels.

[14]:
kinematics.calculate_LowerLimbs(Labels = ['LFLE','LLMAL','RFLE','RLMAL'])
visualise(kinematics, segments = ['L_Thigh','L_Shank','L_Foot','R_Thigh','R_Shank','R_Foot'])
plt.show()

The whole body center of mass can be calculated using the previously calculated segment data.

[15]:
CoM = kinematics.calculate_CoM()
ax = visualise(kinematics, segments = list(kinematics.SegmentCoordinateSystem.keys()))
com = CoM[:,500]
ax.scatter(com[0],com[1],com[2], color = 'k', s=40, label = 'CoM')
ax.legend()
plt.show()

The calculate_CoM function calculates any segments which have not already been calculated. It can therefore be called before any segments have been calculated.

[16]:
kinematics    = center_of_mass.Kinematics(Position, Labels, sex)
Kinematic_com = kinematics.calculate_CoM()
ax = visualise(kinematics, segments = list(kinematics.SegmentCoordinateSystem.keys()))
com = Kinematic_com[:,500]
ax.scatter(com[0],com[1],com[2], color = 'k', s=40, label = 'CoM')
ax.legend()
plt.show()
[ ]: