biomechzoo 0.5.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. __init__.py +33 -0
  2. biomechzoo/__init__.py +0 -0
  3. biomechzoo/__main__.py +6 -0
  4. biomechzoo/biomech_ops/__init__.py +0 -0
  5. biomechzoo/biomech_ops/continuous_relative_phase_data.py +31 -0
  6. biomechzoo/biomech_ops/continuous_relative_phase_line.py +36 -0
  7. biomechzoo/biomech_ops/filter_data.py +58 -0
  8. biomechzoo/biomech_ops/filter_line.py +85 -0
  9. biomechzoo/biomech_ops/movement_onset.py +53 -0
  10. biomechzoo/biomech_ops/normalize_data.py +36 -0
  11. biomechzoo/biomech_ops/normalize_line.py +51 -0
  12. biomechzoo/biomech_ops/phase_angle_data.py +39 -0
  13. biomechzoo/biomech_ops/phase_angle_line.py +48 -0
  14. biomechzoo/biomechzoo.py +447 -0
  15. biomechzoo/conversion/__init__.py +0 -0
  16. biomechzoo/conversion/c3d2zoo_data.py +95 -0
  17. biomechzoo/conversion/mvnx2zoo_data.py +113 -0
  18. biomechzoo/conversion/opencap2zoo_data.py +23 -0
  19. biomechzoo/conversion/table2zoo_data.py +114 -0
  20. biomechzoo/imu/__init__.py +0 -0
  21. biomechzoo/imu/kinematics.py +0 -0
  22. biomechzoo/imu/tilt_algorithm.py +112 -0
  23. biomechzoo/linear_algebra_ops/__init__.py +0 -0
  24. biomechzoo/linear_algebra_ops/compute_magnitude_data.py +43 -0
  25. biomechzoo/mvn/__init__.py +0 -0
  26. biomechzoo/mvn/load_mvnx.py +514 -0
  27. biomechzoo/mvn/main_mvnx.py +75 -0
  28. biomechzoo/mvn/mvn.py +232 -0
  29. biomechzoo/mvn/mvnx_file_accessor.py +464 -0
  30. biomechzoo/processing/__init__.py +0 -0
  31. biomechzoo/processing/addchannel_data.py +71 -0
  32. biomechzoo/processing/addevent_data.py +116 -0
  33. biomechzoo/processing/explodechannel_data.py +69 -0
  34. biomechzoo/processing/partition_data.py +46 -0
  35. biomechzoo/processing/removechannel_data.py +46 -0
  36. biomechzoo/processing/removeevent_data.py +57 -0
  37. biomechzoo/processing/renamechannel_data.py +79 -0
  38. biomechzoo/processing/renameevent_data.py +62 -0
  39. biomechzoo/processing/split_trial_data.py +40 -0
  40. biomechzoo/statistics/eventval.py +118 -0
  41. biomechzoo/utils/__init__.py +0 -0
  42. biomechzoo/utils/batchdisp.py +21 -0
  43. biomechzoo/utils/compute_sampling_rate_from_time.py +25 -0
  44. biomechzoo/utils/engine.py +88 -0
  45. biomechzoo/utils/findfield.py +11 -0
  46. biomechzoo/utils/get_split_events.py +33 -0
  47. biomechzoo/utils/peak_sign.py +24 -0
  48. biomechzoo/utils/set_zoosystem.py +66 -0
  49. biomechzoo/utils/version.py +5 -0
  50. biomechzoo/utils/zload.py +57 -0
  51. biomechzoo/utils/zplot.py +61 -0
  52. biomechzoo/utils/zsave.py +54 -0
  53. biomechzoo-0.5.9.dist-info/METADATA +46 -0
  54. biomechzoo-0.5.9.dist-info/RECORD +58 -0
  55. biomechzoo-0.5.9.dist-info/WHEEL +5 -0
  56. biomechzoo-0.5.9.dist-info/entry_points.txt +2 -0
  57. biomechzoo-0.5.9.dist-info/licenses/LICENSE +21 -0
  58. biomechzoo-0.5.9.dist-info/top_level.txt +2 -0
biomechzoo/mvn/mvn.py ADDED
@@ -0,0 +1,232 @@
1
+ FRAMES_ALL = -1
2
+
3
+ AXIS_ALL = -1
4
+ AXIS_X = 0
5
+ AXIS_Y = 1
6
+ AXIS_Z = 2
7
+ AXIS_W = 3 # The retrieval method will shift indices for w,x,y,z to 0,1,2,3
8
+
9
+ ANGLE_ALL = -1
10
+
11
+ ANGLE_ABDUCTION_ADDUCTION = 0
12
+ ANGLE_RADIAL_ULNAR_DEVIATION = 0
13
+ ANGLE_LATERAL_BENDING = 0
14
+
15
+ ANGLE_INTERNAL_EXTERNAL_ROTATION = 1
16
+ ANGLE_PRONATION_SUPINATION = 1
17
+ ANGLE_AXIAL_ROTATION = 1
18
+
19
+ ANGLE_FLEXION_EXTENSION = 2
20
+ ANGLE_DORSIFLEXION_PLANTARFLEXION = 2
21
+
22
+ SEGMENT_PELVIS = 0
23
+ SEGMENT_L5 = 1
24
+ SEGMENT_L3 = 2
25
+ SEGMENT_T12 = 3
26
+ SEGMENT_T8 = 4
27
+ SEGMENT_NECK = 5
28
+ SEGMENT_HEAD = 6
29
+ SEGMENT_RIGHT_SHOULDER = 7
30
+ SEGMENT_RIGHT_UPPER_ARM = 8
31
+ SEGMENT_RIGHT_FOREARM = 9
32
+ SEGMENT_RIGHT_HAND = 10
33
+ SEGMENT_LEFT_SHOULDER = 11
34
+ SEGMENT_LEFT_UPPER_ARM = 12
35
+ SEGMENT_LEFT_FOREARM = 13
36
+ SEGMENT_LEFT_HAND = 14
37
+ SEGMENT_RIGHT_UPPER_LEG = 15
38
+ SEGMENT_RIGHT_LOWER_LEG = 16
39
+ SEGMENT_RIGHT_FOOT = 17
40
+ SEGMENT_RIGHT_TOE = 18
41
+ SEGMENT_LEFT_UPPER_LEG = 19
42
+ SEGMENT_LEFT_LOWER_LEG = 20
43
+ SEGMENT_LEFT_FOOT = 21
44
+ SEGMENT_LEFT_TOE = 22
45
+
46
+ SEGMENT_CENTER_OF_MASS = 1000
47
+
48
+ SEGMENTS = {SEGMENT_PELVIS: 'Pelvis',
49
+ SEGMENT_L5: 'L5',
50
+ SEGMENT_L3: 'L3',
51
+ SEGMENT_T12: 'T12',
52
+ SEGMENT_T8: 'T8',
53
+ SEGMENT_NECK: 'Neck',
54
+ SEGMENT_HEAD: 'Head',
55
+ SEGMENT_RIGHT_SHOULDER: 'RightShoulder',
56
+ SEGMENT_RIGHT_UPPER_ARM: 'RightUpperArm',
57
+ SEGMENT_RIGHT_FOREARM: 'RightForeArm',
58
+ SEGMENT_RIGHT_HAND: 'RightHand',
59
+ SEGMENT_LEFT_SHOULDER: 'LeftShoulder',
60
+ SEGMENT_LEFT_UPPER_ARM: 'LeftUpperArm',
61
+ SEGMENT_LEFT_FOREARM: 'LeftForeArm',
62
+ SEGMENT_LEFT_HAND: 'LeftHand',
63
+ SEGMENT_RIGHT_UPPER_LEG: 'RightUpperLeg',
64
+ SEGMENT_RIGHT_LOWER_LEG: 'RightLowerLeg',
65
+ SEGMENT_RIGHT_FOOT: 'RightFoot',
66
+ SEGMENT_RIGHT_TOE: 'RightToe',
67
+ SEGMENT_LEFT_UPPER_LEG: 'LeftUpperLeg',
68
+ SEGMENT_LEFT_LOWER_LEG: 'LeftLowerLeg',
69
+ SEGMENT_LEFT_FOOT: 'LeftFoot',
70
+ SEGMENT_LEFT_TOE: 'LeftToe',
71
+ SEGMENT_CENTER_OF_MASS: 'CoM'}
72
+
73
+
74
+ # regular joints
75
+
76
+ JOINT_L5_S1 = 0
77
+ JOINT_L4_L3 = 1
78
+ JOINT_L1_T12 = 2
79
+ JOINT_T9_T8 = 3
80
+ JOINT_T1_C7 = 4
81
+ JOINT_C1_HEAD = 5
82
+ JOINT_RIGHT_T4_SHOULDER = 6
83
+ JOINT_RIGHT_SHOULDER = 7
84
+ JOINT_RIGHT_ELBOW = 8
85
+ JOINT_RIGHT_WRIST = 9
86
+ JOINT_LEFT_T4_SHOULDER = 10
87
+ JOINT_LEFT_SHOULDER = 11
88
+ JOINT_LEFT_ELBOW = 12
89
+ JOINT_LEFT_WRIST = 13
90
+ JOINT_RIGHT_HIP = 14
91
+ JOINT_RIGHT_KNEE = 15
92
+ JOINT_RIGHT_ANKLE = 16
93
+ JOINT_RIGHT_BALL_FOOT = 17
94
+ JOINT_LEFT_HIP = 18
95
+ JOINT_LEFT_KNEE = 19
96
+ JOINT_LEFT_ANKLE = 20
97
+ JOINT_LEFT_BALL_FOOT = 21
98
+
99
+ JOINTS = {JOINT_L5_S1: 'jL5S1',
100
+ JOINT_L4_L3: 'jL4L3',
101
+ JOINT_L1_T12: 'jL1T12',
102
+ JOINT_T9_T8: 'jT9T8',
103
+ JOINT_T1_C7: 'jT1C7',
104
+ JOINT_C1_HEAD: 'jC1Head',
105
+ JOINT_RIGHT_T4_SHOULDER: 'jRightT4Shoulder',
106
+ JOINT_RIGHT_SHOULDER: 'jRightShoulder',
107
+ JOINT_RIGHT_ELBOW: 'jRightElbow',
108
+ JOINT_RIGHT_WRIST: 'jRightWrist',
109
+ JOINT_LEFT_T4_SHOULDER: 'jLeftT4Shoulder',
110
+ JOINT_LEFT_SHOULDER: 'jLeftShoulder',
111
+ JOINT_LEFT_ELBOW: 'jLeftElbow',
112
+ JOINT_LEFT_WRIST: 'jLeftWrist',
113
+ JOINT_RIGHT_HIP: 'jRightHip',
114
+ JOINT_RIGHT_KNEE: 'jRightKnee',
115
+ JOINT_RIGHT_ANKLE: 'jRightAnkle',
116
+ JOINT_RIGHT_BALL_FOOT: 'jRightBallFoot',
117
+ JOINT_LEFT_HIP: 'jLeftHip',
118
+ JOINT_LEFT_KNEE: 'jLeftKnee',
119
+ JOINT_LEFT_ANKLE: 'jLeftAnkle',
120
+ JOINT_LEFT_BALL_FOOT: 'jLeftBallFoot'}
121
+
122
+ PARAMETER_JOINTS = {JOINT_L5_S1: 'j_l5_s1',
123
+ JOINT_L4_L3: 'j_l4_l3',
124
+ JOINT_L1_T12: 'j_l1_t12',
125
+ JOINT_T9_T8: 'j_t9_t8',
126
+ JOINT_T1_C7: 'j_t1_c7',
127
+ JOINT_C1_HEAD: 'j_c1_head',
128
+ JOINT_RIGHT_T4_SHOULDER: 'j_right_t4_shoulder',
129
+ JOINT_RIGHT_SHOULDER: 'j_right_shoulder',
130
+ JOINT_RIGHT_ELBOW: 'j_right_elbow',
131
+ JOINT_RIGHT_WRIST: 'j_right_wrist',
132
+ JOINT_LEFT_T4_SHOULDER: 'j_left_t4_shoulder',
133
+ JOINT_LEFT_SHOULDER: 'j_left_shoulder',
134
+ JOINT_LEFT_ELBOW: 'j_left_elbow',
135
+ JOINT_LEFT_WRIST: 'j_left_wrist',
136
+ JOINT_RIGHT_HIP: 'j_right_hip',
137
+ JOINT_RIGHT_KNEE: 'j_right_knee',
138
+ JOINT_RIGHT_ANKLE: 'j_right_ankle',
139
+ JOINT_RIGHT_BALL_FOOT: 'j_right_ball_foot',
140
+ JOINT_LEFT_HIP: 'j_left_hip',
141
+ JOINT_LEFT_KNEE: 'j_left_knee',
142
+ JOINT_LEFT_ANKLE: 'j_left_ankle',
143
+ JOINT_LEFT_BALL_FOOT: 'j_left_ball_foot'}
144
+
145
+
146
+ # ergonomic joints
147
+
148
+ ERGO_JOINT_T8_HEAD = 0
149
+ ERGO_JOINT_T8_LEFT_UPPER_ARM = 1
150
+ ERGO_JOINT_T8_RIGHT_UPPER_ARM = 2
151
+ ERGO_JOINT_PELVIS_T8 = 3
152
+ ERGO_JOINT_VERTICAL_PELVIS = 4
153
+ ERGO_JOINT_VERTICAL_T8 = 5
154
+
155
+ ERGO_JOINT_INDICES = {ERGO_JOINT_T8_HEAD,
156
+ ERGO_JOINT_T8_LEFT_UPPER_ARM,
157
+ ERGO_JOINT_T8_RIGHT_UPPER_ARM,
158
+ ERGO_JOINT_PELVIS_T8,
159
+ ERGO_JOINT_VERTICAL_PELVIS,
160
+ ERGO_JOINT_VERTICAL_T8}
161
+
162
+ ERGO_JOINTS = {ERGO_JOINT_T8_HEAD: 'T8_Head',
163
+ ERGO_JOINT_T8_LEFT_UPPER_ARM: 'T8_LeftUpperArm',
164
+ ERGO_JOINT_T8_RIGHT_UPPER_ARM: 'T8_RightUpperArm',
165
+ ERGO_JOINT_PELVIS_T8: 'Pelvis_T8',
166
+ ERGO_JOINT_VERTICAL_PELVIS: 'Vertical_Pelvis',
167
+ ERGO_JOINT_VERTICAL_T8: 'Vertical_T8'}
168
+
169
+ ERGO_PARAMETER_JOINTS = {ERGO_JOINT_T8_HEAD: 't8_head',
170
+ ERGO_JOINT_T8_LEFT_UPPER_ARM: 't8_left_upper_arm',
171
+ ERGO_JOINT_T8_RIGHT_UPPER_ARM: 't8_right_upper_arm',
172
+ ERGO_JOINT_PELVIS_T8: 'pelvis_t8',
173
+ ERGO_JOINT_VERTICAL_PELVIS: 'vertical_p1elvis',
174
+ ERGO_JOINT_VERTICAL_T8: 'vertical_t8'}
175
+
176
+
177
+ # foot contacts
178
+
179
+ FOOT_CONTACT_LEFT_HEEL = 1
180
+ FOOT_CONTACT_LEFT_TOE = 2
181
+ FOOT_CONTACT_RIGHT_HEEL = 4
182
+ FOOT_CONTACT_RIGHT_TOE = 8
183
+
184
+ # some points
185
+
186
+ POINT_JOINT_ANKLE = 0
187
+ POINT_JOINT_BALL_FOOT = 1
188
+ POINT_HEEL_FOOT = 2
189
+ POINT_FIRST_METATARSAL = 3
190
+ POINT_FIFTH_METATARSAL = 4
191
+ POINT_PIVOT_FOOT = 5
192
+ POINT_HEEL_CENTER = 6
193
+ POINT_TOP_OF_FOOT = 7
194
+
195
+ POINTS_LEFT_FOOT = {
196
+ POINT_JOINT_ANKLE: 'jLeftAnkle',
197
+ POINT_JOINT_BALL_FOOT: 'jLeftBallFoot',
198
+ POINT_HEEL_FOOT: 'pLeftHeelFoot',
199
+ POINT_FIRST_METATARSAL: 'pLeftFirstMetatarsal',
200
+ POINT_FIFTH_METATARSAL: 'pLeftFifthMetatarsal',
201
+ POINT_PIVOT_FOOT: 'pLeftPivotFoot',
202
+ POINT_HEEL_CENTER: 'pLeftHeelCenter',
203
+ POINT_TOP_OF_FOOT: 'pLeftTopOfFoot',
204
+ }
205
+
206
+ POINTS_RIGHT_FOOT = {
207
+ POINT_JOINT_ANKLE: 'jRightAnkle',
208
+ POINT_JOINT_BALL_FOOT: 'jRightBallFoot',
209
+ POINT_HEEL_FOOT: 'pRightHeelFoot',
210
+ POINT_FIRST_METATARSAL: 'pRightFirstMetatarsal',
211
+ POINT_FIFTH_METATARSAL: 'pRightFifthMetatarsal',
212
+ POINT_PIVOT_FOOT: 'pRightPivotFoot',
213
+ POINT_HEEL_CENTER: 'pRightHeelCenter',
214
+ POINT_TOP_OF_FOOT: 'pRightTopOfFoot',
215
+ }
216
+
217
+ # Toe
218
+ # POINT_JOINT_BALL_FOOT = 0 # overlaps with foot segment
219
+ POINT_TOE = 1
220
+ POINT_JOINT_TOE = 2
221
+
222
+ POINTS_LEFT_TOE = {
223
+ # POINT_JOINT_BALL_FOOT: 'jLeftBallFoot',
224
+ POINT_TOE: 'pLeftToe',
225
+ POINT_JOINT_TOE: 'jLeftToe',
226
+ }
227
+
228
+ POINTS_RIGHT_TOE = {
229
+ # POINT_JOINT_BALL_FOOT: 'jRightBallFoot',
230
+ POINT_TOE: 'pRightToe',
231
+ POINT_JOINT_TOE: 'jRightToe',
232
+ }
@@ -0,0 +1,464 @@
1
+ from biomechzoo.mvn import mvn
2
+ import warnings
3
+
4
+
5
+ class MvnxFileAccessor:
6
+
7
+ @property
8
+ def original_file_name(self):
9
+ return self.file_data['meta_data']['original_filename']
10
+
11
+ @property
12
+ def actor_name(self):
13
+ return self.file_data['meta_data']['name']
14
+
15
+ @property
16
+ def actor_color(self):
17
+ return self.file_data['meta_data']['color']
18
+
19
+ @property
20
+ def profile(self):
21
+ return self.file_data['meta_data']['scenario']
22
+
23
+ @property
24
+ def configuration(self):
25
+ return self.file_data['meta_data']['configuration']
26
+
27
+ @property
28
+ def comments(self):
29
+ return self.file_data['meta_data']['comments']
30
+
31
+ @property
32
+ def quality(self):
33
+ return self.file_data['meta_data']['quality']
34
+
35
+ @property
36
+ def frame_count(self):
37
+ return self._last_frame - self._first_frame
38
+
39
+ @property
40
+ def segment_count(self):
41
+ return self.file_data['frames']['segment_count']
42
+
43
+ @property
44
+ def joint_count(self):
45
+ return self.file_data['frames']['joint_count']
46
+
47
+ @property
48
+ def finger_joint_count(self):
49
+ return self.file_data['frames']['finger_joint_count']
50
+
51
+ @property
52
+ def ergo_joint_count(self):
53
+ ergo_joint_count = len(self.file_data['ergo_joints']) if self.file_data['ergo_joints'] is not None else None
54
+ return ergo_joint_count # 'ergoJointCount' non-existing in mvnx
55
+
56
+ @property
57
+ def sensor_count(self):
58
+ return self.file_data['frames']['sensor_count']
59
+
60
+ @property
61
+ def frame_rate(self) -> int:
62
+ if 'sample_rate' in self.file_data['meta_data']:
63
+ return int(self.file_data['meta_data']['sample_rate'])
64
+ else:
65
+ warnings.warn('Using default sample rate of 240')
66
+ return 240
67
+
68
+ @property
69
+ def recording_date(self) -> str:
70
+ return self.file_data['meta_data']['rec_date']
71
+
72
+ @property
73
+ def version(self):
74
+ return self.file_data['meta_data']['version']
75
+
76
+ def __init__(self):
77
+ self.file_data = {}
78
+ self._all_frames_slice = None
79
+ self._first_frame = 0
80
+ self._last_frame = 0
81
+ self._index_to_segment = {}
82
+
83
+ def create_index_to_segment_dict(self):
84
+ segment_index = 0
85
+ for _, segment in self.file_data['segments']['elements'].items():
86
+ if 'label' in segment:
87
+ self._index_to_segment[segment_index] = segment['label']
88
+ segment_index += 1
89
+
90
+ def set_frame_window(self, first_frame, last_frame):
91
+ self._first_frame = first_frame
92
+ self._last_frame = last_frame
93
+ self._all_frames_slice = slice(self._first_frame, self._last_frame)
94
+
95
+ def reset_frame_window(self):
96
+ self._first_frame = 0
97
+ self._last_frame = len(self.file_data['frames']['segment_data'])
98
+ self._all_frames_slice = slice(self._first_frame, self._last_frame)
99
+
100
+ def window_profile(self):
101
+ """
102
+ This method determines the filter profile (aka scenario) for the currently selected window on the
103
+ data.
104
+ :return: The profile name (singleLevel, multiLevel, ...) or 'mixed' if different profiles
105
+ ere applied to the window.
106
+ """
107
+ if 'profiles' not in self.file_data['meta_data']:
108
+ return self.profile
109
+ else:
110
+ profiles = set()
111
+ for profile_spec in self.file_data['meta_data']['profiles']:
112
+ if profile_spec[1] > self._first_frame and profile_spec[0] <= self._last_frame:
113
+ profiles.add(profile_spec[2])
114
+
115
+ if len(profiles) == 1:
116
+ return profiles.pop()
117
+ else:
118
+ return 'mixed'
119
+
120
+ def frame_to_mapped_slice(self, frame) -> (slice, bool):
121
+ # convert the frame parameter to a slice that is mapped to the current view on the file
122
+ single_frame = False
123
+ if not isinstance(frame, slice):
124
+ if frame == mvn.FRAMES_ALL:
125
+ # all frames slice already is mapped to the current view
126
+ self.reset_frame_window()
127
+ frame = self._all_frames_slice # use the prepared 'all frames' slice
128
+ else:
129
+ # for a single frame, map the frame to the current view on all data by adding the virtual first frame
130
+ frame = slice(self._first_frame + frame, self._first_frame + frame + 1) # create a single frame slice
131
+ single_frame = True
132
+ else:
133
+ # shift the slice to the current virtual 'view'
134
+ start = frame.start + self._first_frame
135
+ if frame.stop:
136
+ stop = frame.stop + self._first_frame
137
+ else: # a slice with end given as None implies end at last frame
138
+ stop = self._last_frame
139
+ step = frame.step
140
+ frame = slice(start, stop, step)
141
+
142
+ return frame, single_frame
143
+
144
+ def segment_name_from_index(self, segment_index):
145
+ return self._index_to_segment[segment_index]
146
+
147
+ def point_name_from_indices(self, segment_index, point_index):
148
+ segment_name = self.segment_name_from_index(segment_index)
149
+ segment = self.file_data['segments']['elements'][segment_name]
150
+ return segment['info']['point_label_from_index'][point_index]
151
+
152
+ """ Pose methods """
153
+
154
+ def identity_pose_is_valid(self):
155
+ return ('identity' in self.file_data) and \
156
+ (self.identity_pose()['segments_counts'] > 0)
157
+
158
+ def identity_pose_segment_pos(self, segment):
159
+ return self.identity_pose()['segments'][segment]['pos_g']
160
+
161
+ def identity_pose_segment_ori(self, segment):
162
+ return self.identity_pose()['segments'][segment]['q_gb']
163
+
164
+ def t_pose_is_valid(self):
165
+ return ('tpose' in self.file_data) and \
166
+ (self.t_pose()['segments_counts'] > 0)
167
+
168
+ def t_pose_segment_pos(self, segment):
169
+ return self.t_pose()['segments'][segment]['pos_g']
170
+
171
+ def t_pose_segment_ori(self, segment):
172
+ return self.t_pose()['segments'][segment]['q_gb']
173
+
174
+ def identity_pose(self):
175
+ return self.file_data['identity']
176
+
177
+ def t_pose(self):
178
+ return self.file_data['tpose']
179
+
180
+ """ Segment methods """
181
+
182
+ def get_segment_pos(self, segment, frame=mvn.FRAMES_ALL, axis=mvn.AXIS_ALL):
183
+ """
184
+ Get the position information for a segment
185
+
186
+ :param segment: The index of the segment to return the data for (Mvn.SEGMENT_.... )
187
+ :param frame: Can be the index of the frame to return, a slice to return a range of frames
188
+ or Mvn.FRAMES_ALL (default) to return all frames
189
+ :param axis: The frame number to return the data for (Mvn.AXIS_... ALL for all axes)
190
+ :return: A single value, list, or list of lists with position values
191
+ """
192
+
193
+ return self.get_segment_data('pos', segment, frame, axis)
194
+
195
+ def get_segment_ori(self, segment, frame=mvn.FRAMES_ALL, axis=mvn.AXIS_ALL):
196
+ """
197
+ Get the orientation information for a segment
198
+
199
+ :param segment: The index of the segment to return the data for (Mvn.SEGMENT_.... )
200
+ :param frame: Can be the index of the frame to return, a slice to return a range of frames
201
+ or Mvn.FRAMES_ALL (default) to return all frames
202
+ :param axis: The frame number to return the data for (Mvn.AXIS_... ALL for all axes)
203
+ :return: A single value, list, or list of lists with orientation values
204
+ """
205
+
206
+ # For orientation data, if all axes requested, return all. If specific axis requested, shift index so that w,
207
+ # x,y,z becomes 0,1,2,3
208
+ axis = (axis + 1) % 4 if axis != mvn.AXIS_ALL else axis
209
+ return self.get_segment_data('ori', segment, frame, axis)
210
+
211
+ def get_segment_point_pos(self, segment, point):
212
+ segment_name = mvn.SEGMENTS[segment]
213
+ segment_info = self.file_data['segments'][segment_name]
214
+ points = segment_info['info']['point_label_from_index']
215
+ point_name = points[point]
216
+ return segment_info['points_mvn'][point_name]
217
+
218
+ def get_point_pos(self, segment, point):
219
+ segment_name = mvn.SEGMENTS[segment]
220
+
221
+ if segment_name == 'LeftFoot':
222
+ point_name = mvn.POINTS_LEFT_FOOT[point]
223
+ elif segment_name == 'RightFoot':
224
+ point_name = mvn.POINTS_RIGHT_FOOT[point]
225
+ elif segment_name == 'LeftToe':
226
+ point_name = mvn.POINTS_LEFT_TOE[point]
227
+ elif segment_name == 'RightToe':
228
+ point_name = mvn.POINTS_RIGHT_TOE[point]
229
+
230
+ return self.file_data['segments'][segment_name]['points_mvn'][point_name]
231
+
232
+ def get_segment_vel(self, segment, frame=mvn.FRAMES_ALL, axis=mvn.AXIS_ALL):
233
+ """
234
+ Get the local velocity information for a segment
235
+
236
+ :param segment: The index of the segment to return the data for (Mvn.SEGMENT_.... )
237
+ :param frame: Can be the index of the frame to return, a slice to return a range of frames
238
+ or Mvn.FRAMES_ALL (default) to return all frames
239
+ :param axis: The frame number to return the data for (Mvn.AXIS_... ALL for all axes)
240
+ :return: A single value, list, or list of lists with velocity values
241
+ """
242
+
243
+ return self.get_segment_data('vel', segment, frame, axis)
244
+
245
+ def get_segment_acc(self, segment, frame=mvn.FRAMES_ALL, axis=mvn.AXIS_ALL):
246
+ """
247
+ Get the acceleration information for a segment
248
+
249
+ :param segment: The index of the segment to return the data for (Mvn.SEGMENT_.... )
250
+ :param frame: Can be the index of the frame to return, a slice to return a range of frames
251
+ or Mvn.FRAMES_ALL (default) to return all frames
252
+ :param axis: The frame number to return the data for (Mvn.AXIS_... ALL for all axes)
253
+ :return: A single value, list, or list of lists with acceleration values
254
+ """
255
+
256
+ return self.get_segment_data('acc', segment, frame, axis)
257
+
258
+ def get_segment_angular_vel(self, segment, frame=mvn.FRAMES_ALL, axis=mvn.AXIS_ALL):
259
+ """
260
+ Get the acceleration information for a segment
261
+
262
+ :param segment: The index of the segment to return the data for (Mvn.SEGMENT_.... )
263
+ :param frame: Can be the index of the frame to return, a slice to return a range of frames
264
+ or Mvn.FRAMES_ALL (default) to return all frames
265
+ :param axis: The frame number to return the data for (Mvn.AXIS_... ALL for all axes)
266
+ :return: A single value, list, or list of lists with angular velocity values
267
+ """
268
+
269
+ return self.get_segment_data('ang_vel', segment, frame, axis)
270
+
271
+ def get_segment_angular_acc(self, segment, frame=mvn.FRAMES_ALL, axis=mvn.AXIS_ALL):
272
+ """
273
+ Get the acceleration information for a segment
274
+
275
+ :param segment: The index of the segment to return the data for (Mvn.SEGMENT_.... )
276
+ :param frame: Can be the index of the frame to return, a slice to return a range of frames
277
+ or Mvn.FRAMES_ALL (default) to return all frames
278
+ :param axis: The frame number to return the data for (Mvn.AXIS_... ALL for all axes)
279
+ :return: A single value, list, or list of lists with acceleration values
280
+ """
281
+
282
+ return self.get_segment_data('ang_acc', segment, frame, axis)
283
+
284
+ def get_segment_data(self, data_field, segment, frame=mvn.FRAMES_ALL, axis=mvn.AXIS_ALL):
285
+ return self.get_data('segment_data', data_field, segment, frame, axis)
286
+
287
+ """ Joint methods """
288
+
289
+ def get_joint_angle(self, joint, frame=mvn.FRAMES_ALL, angle=mvn.ANGLE_ALL):
290
+ joint_name = mvn.JOINTS[joint]
291
+ data_set = 'joint_data'
292
+
293
+ frame, is_single_frame = self.frame_to_mapped_slice(frame)
294
+
295
+ if angle == mvn.ANGLE_ALL:
296
+ return_values = [value[joint_name] for value in self.file_data['frames'][data_set][frame]]
297
+ else:
298
+ return_values = [value[joint_name][angle] for value in self.file_data['frames'][data_set][frame]]
299
+
300
+ return return_values[0] if is_single_frame else return_values
301
+
302
+ def get_joint_angle_xzy(self, joint, frame=mvn.FRAMES_ALL, angle=mvn.ANGLE_ALL):
303
+ joint_name = mvn.JOINTS[joint]
304
+ data_set = 'joint_data_xzy'
305
+
306
+ frame, is_single_frame = self.frame_to_mapped_slice(frame)
307
+
308
+ if angle == mvn.ANGLE_ALL:
309
+ return_values = [value[joint_name] for value in self.file_data['frames'][data_set][frame]]
310
+ else:
311
+ return_values = [value[joint_name][angle] for value in self.file_data['frames'][data_set][frame]]
312
+
313
+ return return_values[0] if is_single_frame else return_values
314
+
315
+ def get_ergo_joint_angle(self, joint, frame=mvn.FRAMES_ALL, angle=mvn.ANGLE_ALL):
316
+ joint_name = mvn.ERGO_JOINTS[joint]
317
+ data_set = 'ergo_joint_data'
318
+
319
+ frame, is_single_frame = self.frame_to_mapped_slice(frame)
320
+
321
+ if angle == mvn.ANGLE_ALL:
322
+ return_values = [value[joint_name] for value in self.file_data['frames'][data_set][frame]]
323
+ else:
324
+ return_values = [value[joint_name][angle] for value in self.file_data['frames'][data_set][frame]]
325
+
326
+ return return_values[0] if is_single_frame else return_values
327
+
328
+ """ Center of Mass methods """
329
+
330
+ def get_center_of_mass_pos(self, frame=mvn.FRAMES_ALL, axis=mvn.AXIS_ALL):
331
+ """
332
+ Get the position information for center of mass
333
+
334
+ :param frame: Can be the index of the frame to return, a slice to return a range of frames
335
+ or Mvn.FRAMES_ALL (default) to return all frames
336
+ :param axis: The axis to return the data for (Mvn.AXIS_... ALL for all axes)
337
+ :return: A single value, list, or list of lists with position values
338
+ """
339
+
340
+ return self.get_segment_data('pos', mvn.SEGMENT_CENTER_OF_MASS, frame, axis)
341
+
342
+ def get_center_of_mass_vel(self, frame=mvn.FRAMES_ALL, axis=mvn.AXIS_ALL):
343
+ """
344
+ Get the velocity information for center of mass
345
+
346
+ :param frame: Can be the index of the frame to return, a slice to return a range of frames
347
+ or Mvn.FRAMES_ALL (default) to return all frames
348
+ :param axis: The axis to return the data for (Mvn.AXIS_... ALL for all axes)
349
+ :return: A single value, list, or list of lists with position values
350
+ """
351
+
352
+ return self.get_segment_data('vel', mvn.SEGMENT_CENTER_OF_MASS, frame, axis)
353
+
354
+ def get_center_of_mass_acc(self, frame=mvn.FRAMES_ALL, axis=mvn.AXIS_ALL):
355
+ """
356
+ Get the acceleration information for center of mass
357
+
358
+ :param frame: Can be the index of the frame to return, a slice to return a range of frames
359
+ or Mvn.FRAMES_ALL (default) to return all frames
360
+ :param axis: The axis to return the data for (Mvn.AXIS_... ALL for all axes)
361
+ :return: A single value, list, or list of lists with position values
362
+ """
363
+
364
+ return self.get_segment_data('acc', mvn.SEGMENT_CENTER_OF_MASS, frame, axis)
365
+
366
+ """ Sensor methods """
367
+
368
+ def get_sensor_ori(self, segment, frame=mvn.FRAMES_ALL, axis=mvn.AXIS_ALL):
369
+ """
370
+ Get the orientation information for a sensor
371
+
372
+ :param segment: The index of the segment to return the sensor data for (Mvn.SEGMENT_.... )
373
+ :param frame: Can be the index of the frame to return, a slice to return a range of frames
374
+ or Mvn.FRAMES_ALL (default) to return all frames
375
+ :param axis: The frame number to return the data for (Mvn.AXIS_... ALL for all axes)
376
+ :return: A single value, list, or list of lists with orientation values
377
+ """
378
+
379
+ # if all axes requested, return all. If specific axis requested, shift index so that w,x,y,z becomes 0,1,2,3
380
+ axis = (axis + 1) % 4 if axis != mvn.AXIS_ALL else axis
381
+ return self.get_sensor_data('ori', segment, frame, axis)
382
+
383
+ def get_sensor_free_acc(self, segment, frame=mvn.FRAMES_ALL, axis=mvn.AXIS_ALL):
384
+ """
385
+ Get the free acceleration information for a sensor
386
+
387
+ :param segment: The index of the segment to return the sensor data for (Mvn.SEGMENT_.... )
388
+ :param frame: Can be the index of the frame to return, a slice to return a range of frames
389
+ or Mvn.FRAMES_ALL (default) to return all frames
390
+ :param axis: The frame number to return the data for (Mvn.AXIS_... ALL for all axes)
391
+ :return: A single value, list, or list of lists with acceleration values
392
+ """
393
+
394
+ return self.get_sensor_data('acc', segment, frame, axis)
395
+
396
+ def get_sensor_data(self, data_field, sensor_segment, frame=mvn.FRAMES_ALL, axis=mvn.AXIS_ALL):
397
+ return self.get_data('sensor_data', data_field, sensor_segment, frame, axis)
398
+
399
+ """ Contact methods """
400
+
401
+ def get_foot_contacts(self, frame):
402
+ """
403
+ Get the contacts for a frame
404
+ :param frame: The frame, or a range of frames to retrieve the contacts for.
405
+ :return: The contacts
406
+ """
407
+ frame, is_single_frame = self.frame_to_mapped_slice(frame)
408
+ return_values = self.file_data['frames']['contacts_data'][frame] #edited Phil Dixon
409
+ return return_values[0] if is_single_frame else return_values
410
+
411
+
412
+ def has_foot_contact(self, frame, foot_contact_flags=0):
413
+ """
414
+ Find out if the frame has a contact, optionally for a specific segment/point combo
415
+
416
+ :param frame: The frame (or range) to retrieve the contacts for.
417
+ :param foot_contact_flags: The specific contact to check for:
418
+ mvn.FOOT_CONTACT_LEFT_HEEL,
419
+ mvn.FOOT_CONTACT_LEFT_TOE,
420
+ mvn.FOOT_CONTACT_RIGHT_HEEL or
421
+ mvn.FOOT_CONTACT_RIGHT_TOE
422
+
423
+ It is possible to combine contacts by summing the values, eg:
424
+ mvn.FOOT_CONTACT_LEFT_HEEL + mvn.FOOT_CONTACT_LEFT_TOE
425
+ This will return a contact if either of the flags has a contact
426
+
427
+ Passing 0 (or nothing) will return True if there is any contact
428
+
429
+ :return: Per frame True if a contact was found, False otherwise.
430
+ """
431
+ frame_contacts = self.get_foot_contacts(frame) # frame will be shifted in the called method
432
+
433
+ if isinstance(frame_contacts, int):
434
+ if foot_contact_flags == 0:
435
+ return frame_contacts > 0
436
+ else:
437
+ return True if (frame_contacts & foot_contact_flags) > 0 else False
438
+ else:
439
+ has_contacts = []
440
+ for contacts in frame_contacts:
441
+ if foot_contact_flags == 0:
442
+ has_contacts.append(frame_contacts > 0)
443
+ else:
444
+ has_contacts.append(True if (contacts & foot_contact_flags) > 0 else False)
445
+ return has_contacts
446
+
447
+ """ Generic methods """
448
+
449
+ def get_data(self, data_set, data_field, segment, frame=mvn.FRAMES_ALL, axis=mvn.AXIS_ALL):
450
+ if segment == -1:
451
+ segment_name = 'com'
452
+ else:
453
+ segment_name = mvn.SEGMENTS[segment]
454
+
455
+ frame, is_single_frame = self.frame_to_mapped_slice(frame)
456
+ if data_set == 'joint_data':
457
+ return_values = [value[data_field] for value in self.file_data['frames'][data_set][frame]]
458
+ elif axis == mvn.AXIS_ALL:
459
+ return_values = [value[segment_name][data_field] for value in self.file_data['frames'][data_set][frame]]
460
+ else:
461
+ return_values = [value[segment_name][data_field][axis] for value in
462
+ self.file_data['frames'][data_set][frame]]
463
+
464
+ return return_values[0] if is_single_frame else return_values
File without changes