c3d-parser 1.6.0__tar.gz → 1.6.1__tar.gz
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.
- {c3d_parser-1.6.0/src/c3d_parser.egg-info → c3d_parser-1.6.1}/PKG-INFO +2 -2
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/requirements.txt +1 -1
- c3d_parser-1.6.1/src/c3d_parser/__init__.py +2 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/core/c3d_parser.py +27 -3
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/view/main_window.py +15 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1/src/c3d_parser.egg-info}/PKG-INFO +2 -2
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser.egg-info/requires.txt +1 -1
- c3d_parser-1.6.0/src/c3d_parser/__init__.py +0 -2
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/LICENSE +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/README.md +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/pyproject.toml +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/setup.cfg +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/application.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/core/c3d_patch.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/core/osim.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/core/osim_resources/external_loads_template.xml +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/core/osim_resources/ik_task_set.xml +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/core/utils.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/settings/general.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/settings/logging.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/settings/marker_maps/AUC.json +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/settings/marker_maps/FMC.json +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/settings/marker_maps/MH.json +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/settings/marker_maps/QCMAS.json +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/settings/marker_maps/RBWH.json +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/settings/marker_maps/RCH.json +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/settings/marker_maps/Sydney.json +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/splash_rc.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/splashscreen.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/view/dialogs/about_dialog.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/view/dialogs/delete_marker_set_dialog.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/view/dialogs/marker_set_dialog.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/view/dialogs/marker_set_import_dialog.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/view/dialogs/options_dialog.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/view/ui/resources_rc.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/view/ui/ui_delete_marker_set_dialog.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/view/ui/ui_main_window.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/view/ui/ui_marker_set_dialog.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/view/ui/ui_marker_set_import_dialog.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/view/ui/ui_options_dialog.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/view/utils.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/view/widgets.py +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser.egg-info/SOURCES.txt +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser.egg-info/dependency_links.txt +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser.egg-info/entry_points.txt +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser.egg-info/top_level.txt +0 -0
- {c3d_parser-1.6.0 → c3d_parser-1.6.1}/tests/test_parser.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: c3d-parser
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.1
|
|
4
4
|
Summary: C3D parser for gait data harmonisation.
|
|
5
5
|
Author-email: Timothy Salemink <tim.nicolas@outlook.com>, Sally Jack <sallyjaack@gmail.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -12,7 +12,7 @@ Requires-Dist: numpy==1.26.4
|
|
|
12
12
|
Requires-Dist: pandas
|
|
13
13
|
Requires-Dist: c3d==0.5.2
|
|
14
14
|
Requires-Dist: trc-data-reader>=0.4.1
|
|
15
|
-
Requires-Dist: opensim-model-creator==0.10.
|
|
15
|
+
Requires-Dist: opensim-model-creator==0.10.1
|
|
16
16
|
Requires-Dist: PySide6
|
|
17
17
|
Requires-Dist: matplotlib
|
|
18
18
|
Requires-Dist: mplcursors
|
|
@@ -92,7 +92,8 @@ def parse_session(static_trial, dynamic_trials, input_directory, output_director
|
|
|
92
92
|
output_directory, left_foot_flat, right_foot_flat, toe_marker_proximal,
|
|
93
93
|
optimise_knee_axis, progress_tracker)
|
|
94
94
|
|
|
95
|
-
write_c3d_parser_history(input_directory, output_directory, static_trial, deidentified_file_names, static_data
|
|
95
|
+
write_c3d_parser_history(input_directory, output_directory, lab, static_trial, deidentified_file_names, static_data,
|
|
96
|
+
left_foot_flat, right_foot_flat, toe_marker_proximal)
|
|
96
97
|
|
|
97
98
|
if not trc_file_paths:
|
|
98
99
|
raise CancelException("No dynamic trials found.")
|
|
@@ -251,15 +252,18 @@ def parse_dynamic_trial(c3d_file, lab, output_directory, trial_index, marker_dat
|
|
|
251
252
|
return analog_data, events, s_t_data, trc_file_path, grf_file_path
|
|
252
253
|
|
|
253
254
|
|
|
254
|
-
def write_c3d_parser_history(input_directory, output_directory, static_trial, deidentified_file_names, static_data
|
|
255
|
+
def write_c3d_parser_history(input_directory, output_directory, lab, static_trial, deidentified_file_names, static_data,
|
|
256
|
+
left_foot_flat, right_foot_flat, toe_marker_proximal):
|
|
255
257
|
log_path = os.path.join(input_directory, "c3d_parser_history.log")
|
|
256
258
|
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M")
|
|
257
259
|
|
|
258
260
|
try:
|
|
259
261
|
with open(log_path, "w", encoding="utf-8") as f:
|
|
260
262
|
f.write("C3D-Parser History\n")
|
|
261
|
-
f.write(f"Last Run: {timestamp}\n
|
|
263
|
+
f.write(f"Last Run: {timestamp}\n")
|
|
264
|
+
f.write(f"C3D-Parser Version: {VERSION}\n\n")
|
|
262
265
|
|
|
266
|
+
f.write(f"Lab: {lab}\n")
|
|
263
267
|
f.write(f"Static trial: {static_trial}\n\n")
|
|
264
268
|
|
|
265
269
|
if deidentified_file_names:
|
|
@@ -286,6 +290,12 @@ def write_c3d_parser_history(input_directory, output_directory, static_trial, de
|
|
|
286
290
|
unit = f" {units[key]}" if key in units else ""
|
|
287
291
|
f.write(f"{label}: {value}{unit}\n")
|
|
288
292
|
|
|
293
|
+
f.write("\n")
|
|
294
|
+
f.write("Foot Settings:\n")
|
|
295
|
+
f.write(f"Toe Marker: {'Proximal' if toe_marker_proximal else '2nd/3rd Met'}\n")
|
|
296
|
+
f.write(f"Left Foot Flat: {left_foot_flat}\n")
|
|
297
|
+
f.write(f"Right Foot Flat: {right_foot_flat}\n")
|
|
298
|
+
|
|
289
299
|
metrics, measurements = define_metrics_and_measurements(output_directory)
|
|
290
300
|
if metrics:
|
|
291
301
|
f.write("\n")
|
|
@@ -540,8 +550,10 @@ def trim_frames(frame_data):
|
|
|
540
550
|
if not drop_frames.empty:
|
|
541
551
|
frame_data.drop(drop_frames, inplace=True)
|
|
542
552
|
|
|
553
|
+
# TODO: If we convert this to a dictionary we can keep the markers that are missing and check if they are required.
|
|
543
554
|
remaining_frames = [frame for frame in incomplete_frames.keys() if trim_start <= frame <= trim_end]
|
|
544
555
|
if remaining_frames:
|
|
556
|
+
# TODO: We should raise a ParserError (skip this trial) if the missing markers are required...?
|
|
545
557
|
logger.warn(f"Frames {remaining_frames} are incomplete.")
|
|
546
558
|
|
|
547
559
|
return trim_start, trim_end
|
|
@@ -1105,6 +1117,8 @@ def scale_grf_data(analog_data):
|
|
|
1105
1117
|
analog_data[columns] = analog_data[columns] / 1000
|
|
1106
1118
|
|
|
1107
1119
|
|
|
1120
|
+
# TODO: This incorrectly classifies Adelaide's static trials as dynamic.
|
|
1121
|
+
# Use `calculate_distance_covered` instead?
|
|
1108
1122
|
def is_dynamic(file_path):
|
|
1109
1123
|
with open(file_path, 'rb') as handle:
|
|
1110
1124
|
try:
|
|
@@ -1280,6 +1294,11 @@ def normalise_kinetics(kinetic_data, events):
|
|
|
1280
1294
|
normalised_data[foot][file_name] = {}
|
|
1281
1295
|
data_segment = data.iloc[start:frame, 1:]
|
|
1282
1296
|
|
|
1297
|
+
# TODO: If the model +tve and -tve are wrong, then we can't just flip these.
|
|
1298
|
+
# Because the non-GRF parts of the moments would also be flipped.
|
|
1299
|
+
# Just visually check the results against some clinical kinetics.
|
|
1300
|
+
# ...
|
|
1301
|
+
# Looks pretty good so far.
|
|
1283
1302
|
# Perform sign transformations.
|
|
1284
1303
|
data_segment[f"hip_flexion_{side}_moment"] = -data_segment[f"hip_flexion_{side}_moment"]
|
|
1285
1304
|
data_segment[f"hip_adduction_{side}_moment"] = -data_segment[f"hip_adduction_{side}_moment"]
|
|
@@ -1372,6 +1391,9 @@ def write_normalised_data(data, column_names, selected_trials, excluded_cycles,
|
|
|
1372
1391
|
file.write('\n')
|
|
1373
1392
|
|
|
1374
1393
|
|
|
1394
|
+
# TODO: Rework this function to be less sequential.
|
|
1395
|
+
# It should be able to calculate metrics for walking and running gait.
|
|
1396
|
+
# Put this at the start of the sequential bit.
|
|
1375
1397
|
def calculate_spatiotemporal_data(frame_data, events, static_data):
|
|
1376
1398
|
stride_lengths = {"Left": {}, "Right": {}}
|
|
1377
1399
|
step_lengths = {"Left": {}, "Right": {}}
|
|
@@ -1394,6 +1416,8 @@ def calculate_spatiotemporal_data(frame_data, events, static_data):
|
|
|
1394
1416
|
for event_time, (event_type, event_plate) in stride_events.items():
|
|
1395
1417
|
time_ordered_events[event_time][foot] = [event_type, stride_number]
|
|
1396
1418
|
|
|
1419
|
+
# TODO: We should be able to use this to calculate ALL measurements non-sequentially.
|
|
1420
|
+
# TODO: Double check that we don't have situations where the events are not ordered in increasing stride number.
|
|
1397
1421
|
# Add terminal foot-strike to events for each cycle.
|
|
1398
1422
|
full_cycle_events = copy.deepcopy(events)
|
|
1399
1423
|
for foot, foot_events in full_cycle_events.items():
|
|
@@ -57,6 +57,7 @@ class ProgressTracker(QObject):
|
|
|
57
57
|
progress = Signal(str, str)
|
|
58
58
|
|
|
59
59
|
|
|
60
|
+
# TODO: CGM2 event detector on GitHub...?
|
|
60
61
|
class MainWindow(QMainWindow):
|
|
61
62
|
|
|
62
63
|
def __init__(self):
|
|
@@ -256,6 +257,12 @@ class MainWindow(QMainWindow):
|
|
|
256
257
|
table.deleteLater()
|
|
257
258
|
self._spatiotemporal_tables = []
|
|
258
259
|
|
|
260
|
+
# TODO: The legend is not correctly displayed if the ST tab is open while processing...
|
|
261
|
+
# Repositioning and updating the legend do nothing.
|
|
262
|
+
|
|
263
|
+
# TODO: The border is still having issues.
|
|
264
|
+
# Seems to be related to the area being scrollable.
|
|
265
|
+
# Only happens on some PCs/monitors...
|
|
259
266
|
def _visualise_spatiotemporal_data(self):
|
|
260
267
|
|
|
261
268
|
# Temporarily disable spatio-temporal visualisation for running gait.
|
|
@@ -891,6 +898,8 @@ class MainWindow(QMainWindow):
|
|
|
891
898
|
if (file_name, f"{foot}_{cycle_number}") not in excluded_cycles:
|
|
892
899
|
counts[foot] += 1
|
|
893
900
|
|
|
901
|
+
# TODO: This is being displayed before processing has finished.
|
|
902
|
+
# Which should not be happening.
|
|
894
903
|
self._ui.labelCount.setText(f"Cycles: L {counts['Left']} / R {counts['Right']}")
|
|
895
904
|
|
|
896
905
|
tab = self._ui.tabWidget.currentWidget()
|
|
@@ -918,6 +927,7 @@ class MainWindow(QMainWindow):
|
|
|
918
927
|
self._update_s_t_colours()
|
|
919
928
|
self._update_legend()
|
|
920
929
|
|
|
930
|
+
# TODO: For some reason the legend doesn't get created at all if we are visualising the ST tab while processing...
|
|
921
931
|
def _update_legend(self):
|
|
922
932
|
if self._boxes:
|
|
923
933
|
for side, boxes in self._boxes.items():
|
|
@@ -1010,6 +1020,8 @@ class MainWindow(QMainWindow):
|
|
|
1010
1020
|
settings.beginGroup('MainWindow')
|
|
1011
1021
|
settings.setValue('size', self.size())
|
|
1012
1022
|
settings.setValue('pos', self.pos())
|
|
1023
|
+
# TODO: The taskbar icon fails if the application opens in full-screen...
|
|
1024
|
+
# DON'T open in full screen...?
|
|
1013
1025
|
settings.setValue('is_maximized', self.isMaximized())
|
|
1014
1026
|
settings.setValue('lab', self._ui.comboBoxLab.currentText())
|
|
1015
1027
|
settings.setValue('marker_diameter', self._ui.doubleSpinBoxMarkerDiameter.value())
|
|
@@ -1214,6 +1226,9 @@ class GaitCurves(defaultdict):
|
|
|
1214
1226
|
line.set_color(colour)
|
|
1215
1227
|
line.set_zorder(z_order)
|
|
1216
1228
|
|
|
1229
|
+
# TODO: Replace all these with `draw_idle`?
|
|
1230
|
+
# Just the ones that handle many curves...?
|
|
1231
|
+
# Probably all...?
|
|
1217
1232
|
self._canvas.draw()
|
|
1218
1233
|
|
|
1219
1234
|
def show_curve_menu(self, event):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: c3d-parser
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.1
|
|
4
4
|
Summary: C3D parser for gait data harmonisation.
|
|
5
5
|
Author-email: Timothy Salemink <tim.nicolas@outlook.com>, Sally Jack <sallyjaack@gmail.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -12,7 +12,7 @@ Requires-Dist: numpy==1.26.4
|
|
|
12
12
|
Requires-Dist: pandas
|
|
13
13
|
Requires-Dist: c3d==0.5.2
|
|
14
14
|
Requires-Dist: trc-data-reader>=0.4.1
|
|
15
|
-
Requires-Dist: opensim-model-creator==0.10.
|
|
15
|
+
Requires-Dist: opensim-model-creator==0.10.1
|
|
16
16
|
Requires-Dist: PySide6
|
|
17
17
|
Requires-Dist: matplotlib
|
|
18
18
|
Requires-Dist: mplcursors
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/core/osim_resources/external_loads_template.xml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/view/dialogs/delete_marker_set_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
{c3d_parser-1.6.0 → c3d_parser-1.6.1}/src/c3d_parser/view/dialogs/marker_set_import_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|