c3d-parser 0.3.4__tar.gz → 0.4.0__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.
Files changed (45) hide show
  1. {c3d_parser-0.3.4/src/c3d_parser.egg-info → c3d_parser-0.4.0}/PKG-INFO +4 -2
  2. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/requirements.txt +3 -1
  3. c3d_parser-0.4.0/src/c3d_parser/__init__.py +2 -0
  4. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/core/c3d_parser.py +17 -0
  5. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/core/osim.py +9 -0
  6. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/view/main_window.py +29 -0
  7. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/view/ui/ui_main_window.py +6 -0
  8. {c3d_parser-0.3.4 → c3d_parser-0.4.0/src/c3d_parser.egg-info}/PKG-INFO +4 -2
  9. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser.egg-info/requires.txt +3 -1
  10. c3d_parser-0.3.4/src/c3d_parser/__init__.py +0 -2
  11. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/LICENSE +0 -0
  12. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/README.md +0 -0
  13. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/pyproject.toml +0 -0
  14. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/setup.cfg +0 -0
  15. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/application.py +0 -0
  16. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/core/c3d_patch.py +0 -0
  17. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/core/osim_resources/external_loads_template.xml +0 -0
  18. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/core/osim_resources/ik_task_set.xml +0 -0
  19. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/core/utils.py +0 -0
  20. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/settings/general.py +0 -0
  21. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/settings/logging.py +0 -0
  22. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/settings/marker_maps/AUC.json +0 -0
  23. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/settings/marker_maps/FMC.json +0 -0
  24. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/settings/marker_maps/MH.json +0 -0
  25. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/settings/marker_maps/QCMAS.json +0 -0
  26. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/settings/marker_maps/RBWH.json +0 -0
  27. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/settings/marker_maps/RCH.json +0 -0
  28. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/settings/marker_maps/Sydney.json +0 -0
  29. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/splash_rc.py +0 -0
  30. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/splashscreen.py +0 -0
  31. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/view/dialogs/about_dialog.py +0 -0
  32. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/view/dialogs/marker_set_dialog.py +0 -0
  33. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/view/dialogs/marker_set_import_dialog.py +0 -0
  34. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/view/dialogs/options_dialog.py +0 -0
  35. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/view/ui/resources_rc.py +0 -0
  36. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/view/ui/ui_marker_set_dialog.py +0 -0
  37. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/view/ui/ui_marker_set_import_dialog.py +0 -0
  38. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/view/ui/ui_options_dialog.py +0 -0
  39. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/view/utils.py +0 -0
  40. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser/view/widgets.py +0 -0
  41. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser.egg-info/SOURCES.txt +0 -0
  42. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser.egg-info/dependency_links.txt +0 -0
  43. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser.egg-info/entry_points.txt +0 -0
  44. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/src/c3d_parser.egg-info/top_level.txt +0 -0
  45. {c3d_parser-0.3.4 → c3d_parser-0.4.0}/tests/test_parser.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: c3d-parser
3
- Version: 0.3.4
3
+ Version: 0.4.0
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,10 +12,12 @@ 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
15
- Requires-Dist: opensim-model-creator>=0.1.19
15
+ Requires-Dist: opensim-model-creator>=0.2.0
16
16
  Requires-Dist: PySide6
17
17
  Requires-Dist: matplotlib
18
18
  Requires-Dist: mplcursors
19
+ Requires-Dist: pyvistaqt
20
+ Requires-Dist: ll-visualiser
19
21
  Dynamic: license-file
20
22
 
21
23
  # C3D-parser
@@ -3,7 +3,9 @@ numpy==1.26.4
3
3
  pandas
4
4
  c3d==0.5.2
5
5
  trc-data-reader
6
- opensim-model-creator>=0.1.19
6
+ opensim-model-creator>=0.2.0
7
7
  PySide6
8
8
  matplotlib
9
9
  mplcursors
10
+ pyvistaqt
11
+ ll-visualiser
@@ -0,0 +1,2 @@
1
+
2
+ __version__ = "0.4.0"
@@ -329,6 +329,8 @@ def harmonise_markers(frame_data, lab, required_markers):
329
329
  if None in frame_data.columns:
330
330
  frame_data.drop(columns=frame_data.columns[frame_data.columns.isna()], inplace=True)
331
331
 
332
+ # TODO: This error window does not indicate which trial has the issue.
333
+ # Update this.
332
334
  # Ensure required markers are present.
333
335
  available = set(frame_data.columns)
334
336
  for item in required_markers:
@@ -382,8 +384,10 @@ def trim_frames(frame_data):
382
384
  if not drop_frames.empty:
383
385
  frame_data.drop(drop_frames, inplace=True)
384
386
 
387
+ # TODO: If we convert this to a dictionary we can keep the markers that are missing and check if they are required.
385
388
  remaining_frames = [frame for frame in incomplete_frames.keys() if trim_start <= frame <= trim_end]
386
389
  if remaining_frames:
390
+ # TODO: We should raise a ParserError (skip this trial) if the missing markers are required...?
387
391
  logger.warn(f"Frames {remaining_frames} are incomplete.")
388
392
 
389
393
  return trim_start, trim_end
@@ -597,6 +601,14 @@ def extract_data(file_path, start_frame, end_frame):
597
601
  return analog_data, reader.analog_rate, trimmed_events, plate_count, corners
598
602
 
599
603
 
604
+ # TODO: Georgio asked if we could maybe provide a way to approximate some of these values (from markers),
605
+ # if they haven't measured them.
606
+ # ...
607
+ # Thor suggests taking this value from the model.
608
+ # ...
609
+ # Discuss this with Elyse to see if she's Ok with this/
610
+ # If she can get the other labs to agree/
611
+ # See how each lab measures this.
600
612
  def extract_static_data(file_path):
601
613
  with open(file_path, 'rb') as handle:
602
614
  reader = c3d.Reader(handle)
@@ -1410,6 +1422,11 @@ def add_medial_knee_markers(frame_data, left_knee_width, right_knee_width, marke
1410
1422
  def create_osim_model(static_trc, dynamic_trc, static_marker_data, marker_diameter, static_data,
1411
1423
  output_directory, optimise_knee_axis, progress_tracker):
1412
1424
 
1425
+ # TODO: Lazy import this here.
1426
+ # Reduce startup time.
1427
+ # We might be able to "warm up" this import in the background before we get here as well.
1428
+ # from opensim_model_creator.Create_Model import create_model
1429
+
1413
1430
  static_marker_data = static_marker_data.drop("Time").to_dict()
1414
1431
  rotation_matrix = np.array([[1, 0, 0], [0, 0, 1], [0, -1, 0]])
1415
1432
  static_marker_data = {k: np.dot(rotation_matrix, v) for k, v in static_marker_data.items()}
@@ -18,6 +18,11 @@ def perform_ik(osim_file, trc_file, output_file):
18
18
  ik_tool.setModel(model)
19
19
  ik_tool.setMarkerDataFileName(trc_file)
20
20
  ik_tool.set_IKTaskSet(osim.IKTaskSet(IK_TASK_SET))
21
+
22
+ # TODO: Fix Teresa's OpenSim issue.
23
+ # ik_tool.setResultsDir(r"C:\Users\MyUser\AppData\Local\MyApp\results")
24
+ # ik_tool.setResultsDir(output_directory)
25
+
21
26
  ik_tool.setOutputMotionFileName(output_file)
22
27
  ik_tool.set_report_errors(False)
23
28
  ik_tool.run()
@@ -34,9 +39,13 @@ def perform_id(osim_file, ik_file, grf_file, output_file):
34
39
  id_tool = osim.InverseDynamicsTool()
35
40
  id_tool.setModel(model)
36
41
  id_tool.setCoordinatesFileName(ik_file)
42
+
43
+ # TODO: Temporarily disable.
37
44
  id_tool.setExternalLoadsFileName(external_loads_file)
45
+
38
46
  id_tool.setResultsDir(output_directory)
39
47
  id_tool.setOutputGenForceFileName(output_file_name)
48
+ # TODO: We shouldn't need this since the data (IK results) are already filtered.
40
49
  id_tool.setLowpassCutoffFrequency(6)
41
50
  id_tool.setStartTime(time_values[0])
42
51
  id_tool.setEndTime(time_values[-1])
@@ -12,6 +12,8 @@ from PySide6.QtWidgets import (QApplication, QMainWindow, QMenu, QFileDialog, QL
12
12
  QWidget, QVBoxLayout, QHBoxLayout)
13
13
  from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg
14
14
  from matplotlib.figure import Figure
15
+ from pyvistaqt import QtInteractor
16
+ from ll_visualiser.visualiser import visualise_model
15
17
 
16
18
  from c3d_parser.core.c3d_parser import (parse_session, extract_static_data, extract_marker_names, is_dynamic,
17
19
  CancelException, write_normalised_kinematics, write_normalised_kinetics, write_spatiotemporal_data)
@@ -53,6 +55,13 @@ class ProgressTracker(QObject):
53
55
  progress = Signal(str, str)
54
56
 
55
57
 
58
+ # TODO: Add the deidentified name to the column in the file details.
59
+ # Instead of just "Dynamic", "Dynamic_1" or whatever.
60
+ # ...
61
+ # Nah just create local mapping file directly in input directory.
62
+
63
+
64
+ # TODO: CGM2 event detector on GitHub...?
56
65
  class MainWindow(QMainWindow):
57
66
 
58
67
  def __init__(self):
@@ -86,6 +95,7 @@ class MainWindow(QMainWindow):
86
95
  self._load_settings()
87
96
  self._setup_progress_bar()
88
97
  self._validate_directory()
98
+ self._setup_visualiser()
89
99
 
90
100
  self._grf_curves = GaitCurves(self._grf_canvas)
91
101
  self._kinematic_curves = GaitCurves(self._kinematic_canvas)
@@ -96,6 +106,14 @@ class MainWindow(QMainWindow):
96
106
  self._progress_value = 0
97
107
  self._ui.progressBar.setVisible(False)
98
108
 
109
+ def _setup_visualiser(self):
110
+ self._plotter = QtInteractor(self._ui.tabVisualiser)
111
+ self._plotter.set_background('#2b2b2b')
112
+ self._ui.tabVisualiser.layout().addWidget(self._plotter.interactor)
113
+
114
+ def _clear_visualiser(self):
115
+ self._plotter.clear_actors()
116
+
99
117
  def _clear_progress_bar(self):
100
118
  self._progress_text = ""
101
119
  self._ui.labelProgress.setText("")
@@ -303,6 +321,7 @@ class MainWindow(QMainWindow):
303
321
  self._reset_kinematic_plots()
304
322
  self._reset_kinetic_plots()
305
323
  self._clear_spatiotemporal_data()
324
+ self._clear_visualiser()
306
325
 
307
326
  def _validate_directory(self):
308
327
  input_directory = self._ui.lineEditInputDirectory.text()
@@ -514,6 +533,7 @@ class MainWindow(QMainWindow):
514
533
  self._visualise_kinematic_data(self._kinematic_data)
515
534
  self._visualise_kinetic_data(self._kinetic_data)
516
535
  self._visualise_spatiotemporal_data()
536
+ self._visualise_model()
517
537
 
518
538
  self._show_selected_trials()
519
539
  self._progress_tracker.progress.emit("Process completed successfully", "green")
@@ -543,6 +563,15 @@ class MainWindow(QMainWindow):
543
563
  self._progress_value = min(self._progress_value + 20, 100)
544
564
  self._ui.progressBar.setValue(self._progress_value)
545
565
 
566
+ def _visualise_model(self):
567
+ model_directory = os.path.join(self._output_directory, "Models", "Meshes")
568
+ left_original_landmark_file = os.path.join(model_directory, 'original_lms_left.txt')
569
+ right_original_landmark_file = os.path.join(model_directory, 'original_lms_right.txt')
570
+ left_predicted_landmark_file = os.path.join(model_directory, 'predicted_lms_left.txt')
571
+ right_predicted_landmark_file = os.path.join(model_directory, 'predicted_lms_right.txt')
572
+ visualise_model(self._plotter, model_directory, left_original_landmark_file, right_original_landmark_file,
573
+ left_predicted_landmark_file, right_predicted_landmark_file)
574
+
546
575
  @handle_runtime_error
547
576
  def _harmonise_data(self):
548
577
  selected = self._get_selected_trials()
@@ -522,6 +522,11 @@ class Ui_MainWindow(object):
522
522
  self.verticalLayout_8.addWidget(self.scrollArea)
523
523
 
524
524
  self.tabWidget.addTab(self.tabSpatiotemporal, "")
525
+ self.tabVisualiser = QWidget()
526
+ self.tabVisualiser.setObjectName(u"tabVisualiser")
527
+ self.verticalLayout_13 = QVBoxLayout(self.tabVisualiser)
528
+ self.verticalLayout_13.setObjectName(u"verticalLayout_13")
529
+ self.tabWidget.addTab(self.tabVisualiser, "")
525
530
 
526
531
  self.verticalLayout_3.addWidget(self.tabWidget)
527
532
 
@@ -638,6 +643,7 @@ class Ui_MainWindow(object):
638
643
  self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabKinetic), QCoreApplication.translate("MainWindow", u"Kinetic", None))
639
644
  self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabGRF), QCoreApplication.translate("MainWindow", u"GRF", None))
640
645
  self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabSpatiotemporal), QCoreApplication.translate("MainWindow", u"Spatio-temporal", None))
646
+ self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabVisualiser), QCoreApplication.translate("MainWindow", u"Visualiser", None))
641
647
  self.labelProgress.setText("")
642
648
  self.menuFile.setTitle(QCoreApplication.translate("MainWindow", u"File", None))
643
649
  self.menuView.setTitle(QCoreApplication.translate("MainWindow", u"View", None))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: c3d-parser
3
- Version: 0.3.4
3
+ Version: 0.4.0
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,10 +12,12 @@ 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
15
- Requires-Dist: opensim-model-creator>=0.1.19
15
+ Requires-Dist: opensim-model-creator>=0.2.0
16
16
  Requires-Dist: PySide6
17
17
  Requires-Dist: matplotlib
18
18
  Requires-Dist: mplcursors
19
+ Requires-Dist: pyvistaqt
20
+ Requires-Dist: ll-visualiser
19
21
  Dynamic: license-file
20
22
 
21
23
  # C3D-parser
@@ -3,7 +3,9 @@ numpy==1.26.4
3
3
  pandas
4
4
  c3d==0.5.2
5
5
  trc-data-reader
6
- opensim-model-creator>=0.1.19
6
+ opensim-model-creator>=0.2.0
7
7
  PySide6
8
8
  matplotlib
9
9
  mplcursors
10
+ pyvistaqt
11
+ ll-visualiser
@@ -1,2 +0,0 @@
1
-
2
- __version__ = "0.3.4"
File without changes
File without changes
File without changes
File without changes