autogaita 1.0.5__tar.gz → 1.0.6__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 (90) hide show
  1. {autogaita-1.0.5 → autogaita-1.0.6}/PKG-INFO +1 -1
  2. autogaita-1.0.6/autogaita/batchrun_scripts/group_universal3Drun.py +139 -0
  3. autogaita-1.0.5/autogaita/batchrun_scripts/group_universal3Drun.py → autogaita-1.0.6/autogaita/batchrun_scripts/group_universal3Drun_backup.py +2 -0
  4. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/batchrun_scripts/universal3D_multirun.py +6 -1
  5. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/batchrun_scripts/universal3D_singlerun.py +7 -2
  6. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/common2D/common2D_3_analysis.py +12 -9
  7. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/dlc/dlc_1_preparation.py +1 -1
  8. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/group/group_1_preparation.py +1 -1
  9. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/group/group_3_PCA.py +2 -0
  10. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/gui/dlc_gui.py +5 -3
  11. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/gui/group_gui.py +15 -10
  12. autogaita-1.0.6/autogaita/gui/group_gui_config.json +121 -0
  13. autogaita-1.0.6/autogaita/gui/gui_utils.py +51 -0
  14. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/gui/sleap_gui.py +4 -2
  15. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/gui/universal3D_gui.py +141 -46
  16. autogaita-1.0.6/autogaita/gui/universal3D_gui_config.json +66 -0
  17. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/gui/window_2D_advanced_config.py +13 -11
  18. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/universal3D/universal3D_1_preparation.py +79 -14
  19. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/universal3D/universal3D_3_analysis.py +114 -32
  20. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita.egg-info/PKG-INFO +1 -1
  21. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita.egg-info/SOURCES.txt +1 -0
  22. {autogaita-1.0.5 → autogaita-1.0.6}/setup.py +1 -1
  23. {autogaita-1.0.5 → autogaita-1.0.6}/tests/test_common2D_unit_3_main_analysis.py +14 -9
  24. {autogaita-1.0.5 → autogaita-1.0.6}/tests/test_group_unit.py +57 -1
  25. autogaita-1.0.5/autogaita/gui/group_gui_config.json +0 -42
  26. autogaita-1.0.5/autogaita/gui/gui_utils.py +0 -92
  27. autogaita-1.0.5/autogaita/gui/universal3D_gui_config.json +0 -54
  28. {autogaita-1.0.5 → autogaita-1.0.6}/LICENSE +0 -0
  29. {autogaita-1.0.5 → autogaita-1.0.6}/README.md +0 -0
  30. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/__init__.py +0 -0
  31. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/__main__.py +0 -0
  32. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/batchrun_scripts/__init__.py +0 -0
  33. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/batchrun_scripts/dlc_multirun.py +0 -0
  34. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/batchrun_scripts/dlc_singlerun.py +0 -0
  35. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/batchrun_scripts/group_dlcrun.py +0 -0
  36. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/batchrun_scripts/group_dlcrun_forpaper.py +0 -0
  37. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/batchrun_scripts/sleap_singlerun.py +0 -0
  38. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/common2D/__init__.py +0 -0
  39. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/common2D/common2D_4_plots.py +0 -0
  40. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/common2D/common2D_constants.py +0 -0
  41. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/common2D/common2D_utils.py +0 -0
  42. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/dlc/__init__.py +0 -0
  43. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/dlc/dlc_2_sc_extraction.py +0 -0
  44. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/dlc/dlc_main.py +0 -0
  45. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/dlc/dlc_utils.py +0 -0
  46. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/group/__init__.py +0 -0
  47. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/group/group_2_data_processing.py +0 -0
  48. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/group/group_4_stats.py +0 -0
  49. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/group/group_5_plots.py +0 -0
  50. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/group/group_constants.py +0 -0
  51. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/group/group_main.py +0 -0
  52. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/group/group_utils.py +0 -0
  53. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/gui/__init__.py +0 -0
  54. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/gui/dlc_gui_config.json +0 -0
  55. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/gui/first_level_gui_utils.py +0 -0
  56. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/gui/gaita_widgets.py +0 -0
  57. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/gui/gui_constants.py +0 -0
  58. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/gui/main_gui.py +0 -0
  59. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/gui/sleap_gui_config.json +0 -0
  60. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/gui/window_2D_columninfo.py +0 -0
  61. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/gui/window_2D_run_and_done.py +0 -0
  62. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/resources/__init__.py +0 -0
  63. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/resources/constants.py +0 -0
  64. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/resources/icon.icns +0 -0
  65. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/resources/icon.ico +0 -0
  66. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/resources/logo.png +0 -0
  67. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/resources/pic_to_demo_for_repo.png +0 -0
  68. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/resources/utils.py +0 -0
  69. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/sleap/__init__.py +0 -0
  70. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/sleap/sleap_1_preparation.py +0 -0
  71. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/sleap/sleap_2_sc_extraction.py +0 -0
  72. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/sleap/sleap_main.py +0 -0
  73. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/universal3D/__init__.py +0 -0
  74. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/universal3D/universal3D_2_sc_extraction.py +0 -0
  75. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/universal3D/universal3D_4_plots.py +0 -0
  76. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/universal3D/universal3D_constants.py +0 -0
  77. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/universal3D/universal3D_datafile_preparation.py +0 -0
  78. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/universal3D/universal3D_main.py +0 -0
  79. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita/universal3D/universal3D_utils.py +0 -0
  80. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita.egg-info/dependency_links.txt +0 -0
  81. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita.egg-info/requires.txt +0 -0
  82. {autogaita-1.0.5 → autogaita-1.0.6}/autogaita.egg-info/top_level.txt +0 -0
  83. {autogaita-1.0.5 → autogaita-1.0.6}/setup.cfg +0 -0
  84. {autogaita-1.0.5 → autogaita-1.0.6}/tests/__init__.py +0 -0
  85. {autogaita-1.0.5 → autogaita-1.0.6}/tests/test_dlc_approval.py +0 -0
  86. {autogaita-1.0.5 → autogaita-1.0.6}/tests/test_dlc_unit_1_preparation.py +0 -0
  87. {autogaita-1.0.5 → autogaita-1.0.6}/tests/test_dlc_unit_2_sc_extraction.py +0 -0
  88. {autogaita-1.0.5 → autogaita-1.0.6}/tests/test_group_approval.py +0 -0
  89. {autogaita-1.0.5 → autogaita-1.0.6}/tests/test_universal3D_approval.py +0 -0
  90. {autogaita-1.0.5 → autogaita-1.0.6}/tests/test_universal3D_unit.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: autogaita
3
- Version: 1.0.5
3
+ Version: 1.0.6
4
4
  Summary: Automatic Gait Analysis in Python. A toolbox to streamline and standardise the analysis of kinematics across species after ML-based body posture tracking. Despite being optimised for gait analyses, AutoGaitA has the potential to be used for any kind of kinematic analysis.
5
5
  Home-page: https://github.com/mahan-hosseini/AutoGaitA/
6
6
  Author: Mahan Hosseini
@@ -0,0 +1,139 @@
1
+ import autogaita
2
+
3
+
4
+ def group_universal3Drun():
5
+ """
6
+ Batchrun script to run AutoGaitA Group for Results obtained with AutoGaitA Universal 3D.
7
+ folderinfo & cfg dictionaries must be configured as explained in our documentation. See the "AutoGaitA without the GUI" section of our documentation for references to in-depth explanations to all dictionary keys (note that each key of dicts corresponds to some object in the AutoGaitA Group GUI)
8
+ """
9
+ # loop over legs - currently no option to do both legs in a single run
10
+ cfg = {}
11
+ # folderinfo
12
+ # => Note that length of folderinfo's group_names & group_dirs lists determines # how many groups are compared.
13
+ # => Also note that indices must correspond (i.e., idx # 1's name will be # used for dataset stored in group_dir's idx 1)
14
+ folderinfo = {}
15
+ folderinfo["group_names"] = [
16
+ "crawling",
17
+ "sideways",
18
+ "walking",
19
+ "jogging",
20
+ "jumping_jack",
21
+ "vertical_jumping",
22
+ ]
23
+ folderinfo["group_dirs"] = [
24
+ "/Users/mahan/sciebo/Research/AutoGaitA/Showcase 3/MOVI/First Analysis/gaita prepared/crawling/Results/",
25
+ "/Users/mahan/sciebo/Research/AutoGaitA/Showcase 3/MOVI/First Analysis/gaita prepared/sideways/Results/",
26
+ "/Users/mahan/sciebo/Research/AutoGaitA/Showcase 3/MOVI/First Analysis/gaita prepared/walking/Results/",
27
+ "/Users/mahan/sciebo/Research/AutoGaitA/Showcase 3/MOVI/First Analysis/gaita prepared/jogging/Results/",
28
+ "/Users/mahan/sciebo/Research/AutoGaitA/Showcase 3/MOVI/First Analysis/gaita prepared/jumping_jack/Results/",
29
+ "/Users/mahan/sciebo/Research/AutoGaitA/Showcase 3/MOVI/First Analysis/gaita prepared/vertical_jumping/Results/",
30
+ ]
31
+ folderinfo["results_dir"] = (
32
+ "/Users/mahan/sciebo/Research/AutoGaitA/Showcase 3/MOVI/First Analysis/gaita prepared/group/"
33
+ )
34
+ folderinfo["load_dir"] = ""
35
+ # cfg
36
+ cfg["do_permtest"] = True
37
+ cfg["do_anova"] = True
38
+ cfg["permutation_number"] = 10000
39
+ cfg["PCA_n_components"] = 10
40
+ cfg["PCA_custom_scatter_PCs"] = ""
41
+ cfg["PCA_save_3D_video"] = True
42
+ cfg["PCA_bins"] = ""
43
+ cfg["stats_threshold"] = 0.05
44
+ cfg["plot_SE"] = False
45
+ cfg["color_palette"] = "Set2"
46
+ cfg["legend_outside"] = True
47
+ cfg["dont_show_plots"] = True
48
+ cfg["anova_design"] = "Mixed ANOVA"
49
+ cfg["which_leg"] = "right"
50
+ cfg["PCA_variables"] = [
51
+ "Head Y",
52
+ "Head Z",
53
+ "Hip Y",
54
+ "Hip Z",
55
+ "Pelvis Y",
56
+ "Pelvis Z",
57
+ "Thorax Y",
58
+ "Thorax Z",
59
+ "Ankle, left Y",
60
+ "Ankle, left Z",
61
+ "Elbow, left Y",
62
+ "Elbow, left Z",
63
+ "Hip, left Y",
64
+ "Hip, left Z",
65
+ "Hand, left Y",
66
+ "Hand, left Z",
67
+ "Knee, left Y",
68
+ "Knee, left Z",
69
+ "Shoulder, left Y",
70
+ "Shoulder, left Z",
71
+ "Wrist, left Y",
72
+ "Wrist, left Z",
73
+ "Foot, left Y",
74
+ "Foot, left Z",
75
+ "Ankle, right Y",
76
+ "Ankle, right Z",
77
+ "Elbow, right Y",
78
+ "Elbow, right Z",
79
+ "Hip, right Y",
80
+ "Hip, right Z",
81
+ "Hand, right Y",
82
+ "Hand, right Z",
83
+ "Knee, right Y",
84
+ "Knee, right Z",
85
+ "Shoulder, right Y",
86
+ "Shoulder, right Z",
87
+ "Wrist, right Y",
88
+ "Wrist, right Z",
89
+ "Foot, right Y",
90
+ "Foot, right Z",
91
+ "Ankle, left Angle",
92
+ "Knee, left Angle",
93
+ "Elbow, left Angle",
94
+ "Foot, left Velocity",
95
+ "Foot, left Acceleration",
96
+ "Ankle, left Velocity",
97
+ "Ankle, left Acceleration",
98
+ "Knee, left Velocity",
99
+ "Knee, left Acceleration",
100
+ "Hip Velocity",
101
+ "Hip Acceleration",
102
+ "Pelvis Velocity",
103
+ "Pelvis Acceleration",
104
+ "Shoulder, left Velocity",
105
+ "Shoulder, left Acceleration",
106
+ "Head Velocity",
107
+ "Head Acceleration",
108
+ "Ankle, left Angle Velocity",
109
+ "Ankle, left Angle Acceleration",
110
+ "Knee, left Angle Velocity",
111
+ "Knee, left Angle Acceleration",
112
+ "Elbow, left Angle Velocity",
113
+ "Elbow, left Angle Acceleration",
114
+ "Ankle, right Angle",
115
+ "Knee, right Angle",
116
+ "Elbow, right Angle",
117
+ "Foot, right Velocity",
118
+ "Foot, right Acceleration",
119
+ "Ankle, right Velocity",
120
+ "Ankle, right Acceleration",
121
+ "Knee, right Velocity",
122
+ "Knee, right Acceleration",
123
+ "Shoulder, right Velocity",
124
+ "Shoulder, right Acceleration",
125
+ "Ankle, right Angle Velocity",
126
+ "Ankle, right Angle Acceleration",
127
+ "Knee, right Angle Velocity",
128
+ "Knee, right Angle Acceleration",
129
+ "Elbow, right Angle Velocity",
130
+ "Elbow, right Angle Acceleration",
131
+ ]
132
+ cfg["stats_variables"] = []
133
+ # run
134
+ autogaita.group(folderinfo, cfg)
135
+
136
+
137
+ # %% what happens if we just hit run
138
+ if __name__ == "__main__":
139
+ group_universal3Drun()
@@ -29,6 +29,8 @@ def group_universal3Drun():
29
29
  cfg["do_anova"] = True
30
30
  cfg["permutation_number"] = 10
31
31
  cfg["PCA_n_components"] = 3
32
+ cfg["PCA_custom_scatter_PCs"] = ""
33
+ cfg["PCA_bins"] = ""
32
34
  cfg["PCA_save_3D_video"] = False
33
35
  cfg["stats_threshold"] = 0.05
34
36
  cfg["plot_SE"] = False
@@ -24,11 +24,16 @@ def universal3D_multirun():
24
24
  cfg["angular_acceleration"] = True
25
25
  cfg["bin_num"] = 25
26
26
  cfg["plot_SE"] = True
27
- cfg["normalise_height_at_SC_level"] = True
27
+ cfg["standardise_z_at_SC_level"] = True
28
+ cfg["standardise_z_to_a_joint"] = True
29
+ cfg["z_standardisation_joint"] = ["Foot, left"]
28
30
  cfg["plot_joint_number"] = 7
29
31
  cfg["color_palette"] = "viridis"
30
32
  cfg["legend_outside"] = True
33
+ cfg["flip_gait_direction"] = False
31
34
  cfg["analyse_average_y"] = True
35
+ cfg["standardise_y_coordinates"] = True
36
+ cfg["y_standardisation_joint"] = ["Foot"]
32
37
  cfg["joints"] = ["Midfoot", "Ankle", "Knee", "Hip", "Pelvis", "Shoulder", "Neck"]
33
38
  cfg["angles"] = {
34
39
  "name": ["Ankle", "Knee"],
@@ -23,11 +23,16 @@ def universal3D_singlerun():
23
23
  cfg["angular_acceleration"] = True
24
24
  cfg["bin_num"] = 25
25
25
  cfg["plot_SE"] = True
26
- cfg["normalise_height_at_SC_level"] = True
26
+ cfg["standardise_z_at_SC_level"] = True
27
+ cfg["standardise_z_to_a_joint"] = True
28
+ cfg["z_standardisation_joint"] = ["Midfoot"]
27
29
  cfg["plot_joint_number"] = 5
28
30
  cfg["color_palette"] = "Set2"
29
31
  cfg["legend_outside"] = True
30
- cfg["analyse_average_y"] = False
32
+ cfg["flip_gait_direction"] = False
33
+ cfg["analyse_average_y"] = True
34
+ cfg["standardise_y_coordinates"] = True
35
+ cfg["y_standardisation_joint"] = ["Midfoot"]
31
36
  cfg["joints"] = [
32
37
  # "R1-ThCx",
33
38
  "Midfoot",
@@ -63,6 +63,9 @@ def analyse_and_export_stepcycles(data, all_cycles, info, cfg):
63
63
  # 2 or more steps - build dataframe
64
64
  elif len(all_cycles) > 1:
65
65
  # first- step is added manually
66
+ # NOTE
67
+ # ----
68
+ # normalised_steps_data is created using x_standardised_steps_data or first_step
66
69
  first_step = data_copy.loc[all_cycles[0][0] : all_cycles[0][1]]
67
70
  if standardise_x_coordinates:
68
71
  all_steps_data, x_standardised_steps_data = (
@@ -181,20 +184,20 @@ def standardise_x_y_and_add_features_to_one_step(step, cfg):
181
184
  step_copy[y_cols] -= this_y_min
182
185
  # if no x-standardisation, just add features & return non-(x-)normalised step
183
186
  if cfg["standardise_x_coordinates"] is False:
184
- non_norm_step = add_features(step_copy, cfg)
185
- return non_norm_step
187
+ non_stand_step = add_features(step_copy, cfg)
188
+ return non_stand_step
186
189
  # else standardise x (horizontal dimension) at step-cycle level too
187
190
  else:
188
- non_norm_step = add_features(step_copy, cfg)
189
- x_norm_step = step_copy.copy()
190
- x_cols = [col for col in x_norm_step.columns if col.endswith("x")]
191
+ non_stand_step = add_features(step_copy, cfg)
192
+ x_stand_step = step_copy.copy()
193
+ x_cols = [col for col in x_stand_step.columns if col.endswith("x")]
191
194
  # note the [0] here is important because it's still a list of len=1!!
192
- min_x_standardisation_joint = x_norm_step[
195
+ min_x_standardisation_joint = x_stand_step[
193
196
  cfg["x_standardisation_joint"][0] + "x"
194
197
  ].min()
195
- x_norm_step[x_cols] -= min_x_standardisation_joint
196
- x_norm_step = add_features(x_norm_step, cfg)
197
- return non_norm_step, x_norm_step
198
+ x_stand_step[x_cols] -= min_x_standardisation_joint
199
+ x_stand_step = add_features(x_stand_step, cfg)
200
+ return non_stand_step, x_stand_step
198
201
 
199
202
 
200
203
  def add_features(step, cfg):
@@ -169,7 +169,7 @@ def some_prep(info, folderinfo, cfg):
169
169
  beam_hind_jointadd = cfg["beam_hind_jointadd"]
170
170
  beam_fore_jointadd = cfg["beam_fore_jointadd"]
171
171
  direction_joint = cfg["direction_joint"]
172
- # important to unpack to vars hand not to cfg since cfg is overwritten in multiruns!
172
+ # important to unpack to vars and not to cfg since cfg is overwritten in multiruns!
173
173
  x_standardisation_joint = cfg["x_standardisation_joint"][0]
174
174
  y_standardisation_joint = cfg["y_standardisation_joint"][0]
175
175
  # store config json file @ group path
@@ -54,7 +54,7 @@ def some_prep(folderinfo, cfg):
54
54
  # => use this and just return the cfg
55
55
  # => make sure to write folderinfo["contrast"] manually above as is and then return
56
56
  # that folderinfo plus the cfg you load from the file
57
- if folderinfo["load_dir"]:
57
+ if len(folderinfo["load_dir"]) > 0:
58
58
  with open(
59
59
  os.path.join(folderinfo["load_dir"], CONFIG_JSON_FILENAME), "r"
60
60
  ) as config_json_file:
@@ -218,6 +218,8 @@ def run_PCA(PCA_df, features, cfg):
218
218
  # excel files)
219
219
  x = pd.DataFrame(x, columns=features)
220
220
  # NOTE that this next line changes the PCA_model variable!
221
+ # pdb.set_trace()
222
+ x.fillna(0, inplace=True)
221
223
  PCs = PCA_model.fit_transform(x)
222
224
  # NOTE! we use number_of_PCs from here onwards (in info/plots/etc) to differentiate
223
225
  # between n_components which can be smaller than 1!
@@ -198,11 +198,13 @@ def run_dlc_gui():
198
198
  WIDGET_CFG,
199
199
  )
200
200
  convert_checkbox.configure(
201
- command=lambda: gui_utils.change_ratio_entry_state(cfg, ratio_entry),
201
+ command=lambda: gui_utils.change_widget_state_based_on_checkbox(
202
+ cfg, "convert_to_mm", ratio_entry
203
+ ),
202
204
  )
203
205
  convert_checkbox.grid(row=2, column=0, columnspan=2, sticky="w")
204
206
 
205
- # ratio label
207
+ # ratio label
206
208
  ratio_entry = ctk.CTkEntry(
207
209
  root,
208
210
  textvariable=cfg["pixel_to_mm_ratio"],
@@ -215,7 +217,7 @@ def run_dlc_gui():
215
217
  )
216
218
  ratio_right_label.grid(row=2, column=2, sticky="w")
217
219
  # to initialise the widget correctly, run this function once
218
- gui_utils.change_ratio_entry_state(cfg, ratio_entry)
220
+ gui_utils.change_widget_state_based_on_checkbox(cfg, "convert_to_mm", ratio_entry)
219
221
 
220
222
  # subtract beam
221
223
  subtract_beam_checkbox = gaita_widgets.checkbox(
@@ -349,7 +349,7 @@ def build_mainwindow(root, group_number, root_dimensions):
349
349
  )
350
350
  ANOVA_checkbox.configure(
351
351
  command=lambda: change_ANOVA_buttons_state(ANOVA_buttons),
352
- )
352
+ ) # dont use gui_utils here because its a bit special
353
353
  ANOVA_checkbox.grid(row=last_group_row + 7, column=0, columnspan=3, pady=10)
354
354
  # ANOVA design
355
355
  ANOVA_string_and_var_value = [
@@ -406,7 +406,8 @@ def build_mainwindow(root, group_number, root_dimensions):
406
406
  group_names,
407
407
  group_dirs,
408
408
  results_dir,
409
- load_dir,
409
+ load_dir, # tk var
410
+ cfg["which_leg"], # tk var
410
411
  root,
411
412
  ),
412
413
  ),
@@ -595,7 +596,7 @@ def advanced_cfgwindow(mainwindow):
595
596
 
596
597
 
597
598
  def definefeatures_window(
598
- mainwindow, group_names, group_dirs, results_dir, load_dir, root
599
+ mainwindow, group_names, group_dirs, results_dir, load_dir, which_leg, root
599
600
  ):
600
601
  """Build define features window"""
601
602
 
@@ -618,7 +619,7 @@ def definefeatures_window(
618
619
  # averaging, or throw errors if we don't manage to do so
619
620
  # -- (note we extract from average xls since that automatically informs about
620
621
  # export_average_x/y vars!)
621
- if load_dir:
622
+ if len(load_dir.get()) > 0:
622
623
  group_one_string = group_names[0].get()
623
624
  load_dir_string = load_dir.get()
624
625
  df = pd.read_excel(
@@ -659,7 +660,11 @@ def definefeatures_window(
659
660
  if av_sheet_path: # won't be true if no AVXLS found
660
661
  full_path = os.path.join(some_IDs_dir, av_sheet_path)
661
662
  if av_sheet_path.endswith(".xlsx"):
662
- df = pd.read_excel(full_path)
663
+ try:
664
+ # universal 3D (that has which_leg sheets) always exports xlsx
665
+ df = pd.read_excel(full_path, sheet_name=which_leg.get())
666
+ except:
667
+ df = pd.read_excel(full_path)
663
668
  break
664
669
  elif av_sheet_path.endswith(".csv"):
665
670
  df = pd.read_csv(full_path)
@@ -912,7 +917,7 @@ def check_folderinfo_and_cfg(folderinfo, cfg):
912
917
  for key in inner_dict.keys():
913
918
  # check string vars: group dirs & names and results dir
914
919
  if key in STRING_VARS:
915
- if key == "group_dirs" and not folderinfo["load_dir"]:
920
+ if key == "group_dirs" and len(folderinfo["load_dir"]) > 0:
916
921
  for g_idx, group_dir in enumerate(inner_dict[key]):
917
922
  if not os.path.exists(group_dir):
918
923
  this_msg = (
@@ -967,8 +972,8 @@ def extract_this_runs_folderinfo_and_cfg(folderinfo, cfg):
967
972
  # using string concatenation). If not just add a forward slash. In the beginning
968
973
  # of autogaita.group, we will convert os.sep to forward slashes if they should be
969
974
  # backward slashes (windows works with both)
970
- # => Note this was changed and works with os.path.join() now...
971
- # => NU: have another look @ this matter in GUI functions
975
+ # => The part that does this in autogaita.group was updated and uses os.path.join
976
+ # => Thought about changing strings to Paths here but will leave it for now it works
972
977
  for key in folderinfo.keys():
973
978
  if key == "group_names":
974
979
  this_runs_folderinfo[key] = folderinfo[key]
@@ -981,8 +986,8 @@ def extract_this_runs_folderinfo_and_cfg(folderinfo, cfg):
981
986
  else:
982
987
  this_runs_folderinfo[key][i] = folderinfo[key][i]
983
988
  # results_dir and load_dir (check load_dir only if not empty)
984
- elif key == "results_dir" or (key == "load_dir" and folderinfo[key]):
985
- if not folderinfo[key].endswith(os.sep):
989
+ elif key in ["results_dir", "load_dir"]:
990
+ if len(folderinfo[key]) > 0 and not folderinfo[key].endswith(os.sep):
986
991
  this_runs_folderinfo[key] = folderinfo[key] + "/"
987
992
  else:
988
993
  this_runs_folderinfo[key] = folderinfo[key]
@@ -0,0 +1,121 @@
1
+ [
2
+ {
3
+ "group_names": [
4
+ "crawling",
5
+ "sideways",
6
+ "walking",
7
+ "jogging",
8
+ "jumping_jack",
9
+ "vertical_jumping"
10
+ ],
11
+ "group_dirs": [
12
+ "/Users/mahan/sciebo/Research/AutoGaitA/Showcase 3/MOVI/First Analysis/gaita prepared/crawling/Results/",
13
+ "/Users/mahan/sciebo/Research/AutoGaitA/Showcase 3/MOVI/First Analysis/gaita prepared/sideways/Results/",
14
+ "/Users/mahan/sciebo/Research/AutoGaitA/Showcase 3/MOVI/First Analysis/gaita prepared/walking/Results/",
15
+ "/Users/mahan/sciebo/Research/AutoGaitA/Showcase 3/MOVI/First Analysis/gaita prepared/jogging/Results/",
16
+ "/Users/mahan/sciebo/Research/AutoGaitA/Showcase 3/MOVI/First Analysis/gaita prepared/jumping_jack/Results/",
17
+ "/Users/mahan/sciebo/Research/AutoGaitA/Showcase 3/MOVI/First Analysis/gaita prepared/vertical_jumping/Results/"
18
+ ],
19
+ "results_dir": "/Users/mahan/sciebo/Research/AutoGaitA/Showcase 3/MOVI/First Analysis/gaita prepared/gaita_tests/",
20
+ "load_dir": ""
21
+ },
22
+ {
23
+ "do_permtest": true,
24
+ "do_anova": true,
25
+ "anova_design": "RM ANOVA",
26
+ "permutation_number": "10000",
27
+ "stats_threshold": "0.05",
28
+ "which_leg": "left",
29
+ "PCA_n_components": "10",
30
+ "PCA_custom_scatter_PCs": "",
31
+ "PCA_save_3D_video": true,
32
+ "PCA_bins": "",
33
+ "plot_SE": false,
34
+ "color_palette": "Set2",
35
+ "dont_show_plots": false,
36
+ "legend_outside": true,
37
+ "stats_variables": [],
38
+ "PCA_variables": [
39
+ "Head Y",
40
+ "Head Z",
41
+ "Hip Y",
42
+ "Hip Z",
43
+ "Pelvis Y",
44
+ "Pelvis Z",
45
+ "Thorax Y",
46
+ "Thorax Z",
47
+ "Ankle, left Y",
48
+ "Ankle, left Z",
49
+ "Elbow, left Y",
50
+ "Elbow, left Z",
51
+ "Hip, left Y",
52
+ "Hip, left Z",
53
+ "Hand, left Y",
54
+ "Hand, left Z",
55
+ "Knee, left Y",
56
+ "Knee, left Z",
57
+ "Shoulder, left Y",
58
+ "Shoulder, left Z",
59
+ "Wrist, left Y",
60
+ "Wrist, left Z",
61
+ "Foot, left Y",
62
+ "Foot, left Z",
63
+ "Ankle, right Y",
64
+ "Ankle, right Z",
65
+ "Elbow, right Y",
66
+ "Elbow, right Z",
67
+ "Hip, right Y",
68
+ "Hip, right Z",
69
+ "Hand, right Y",
70
+ "Hand, right Z",
71
+ "Knee, right Y",
72
+ "Knee, right Z",
73
+ "Shoulder, right Y",
74
+ "Shoulder, right Z",
75
+ "Wrist, right Y",
76
+ "Wrist, right Z",
77
+ "Foot, right Y",
78
+ "Foot, right Z",
79
+ "Ankle, left Angle",
80
+ "Knee, left Angle",
81
+ "Elbow, left Angle",
82
+ "Foot, left Velocity",
83
+ "Foot, left Acceleration",
84
+ "Ankle, left Velocity",
85
+ "Ankle, left Acceleration",
86
+ "Knee, left Velocity",
87
+ "Knee, left Acceleration",
88
+ "Hip Velocity",
89
+ "Hip Acceleration",
90
+ "Pelvis Velocity",
91
+ "Pelvis Acceleration",
92
+ "Shoulder, left Velocity",
93
+ "Shoulder, left Acceleration",
94
+ "Head Velocity",
95
+ "Head Acceleration",
96
+ "Ankle, left Angle Velocity",
97
+ "Ankle, left Angle Acceleration",
98
+ "Knee, left Angle Velocity",
99
+ "Knee, left Angle Acceleration",
100
+ "Elbow, left Angle Velocity",
101
+ "Elbow, left Angle Acceleration",
102
+ "Ankle, right Angle",
103
+ "Knee, right Angle",
104
+ "Elbow, right Angle",
105
+ "Foot, right Velocity",
106
+ "Foot, right Acceleration",
107
+ "Ankle, right Velocity",
108
+ "Ankle, right Acceleration",
109
+ "Knee, right Velocity",
110
+ "Knee, right Acceleration",
111
+ "Shoulder, right Velocity",
112
+ "Shoulder, right Acceleration",
113
+ "Ankle, right Angle Velocity",
114
+ "Ankle, right Angle Acceleration",
115
+ "Knee, right Angle Velocity",
116
+ "Knee, right Angle Acceleration",
117
+ "Elbow, right Angle Velocity",
118
+ "Elbow, right Angle Acceleration"
119
+ ]
120
+ }
121
+ ]
@@ -0,0 +1,51 @@
1
+ import platform
2
+ from importlib import resources
3
+
4
+
5
+ # ............................... general gui stuff ..................................
6
+ def configure_the_icon(root):
7
+ """Configure the icon - in macos it changes the dock icon, in windows it changes
8
+ all windows titlebar icons (taskbar cannot be changed without converting to exe)
9
+ """
10
+ if platform.system().startswith("Darwin"):
11
+ try:
12
+ from Cocoa import NSApplication, NSImage
13
+ except ImportError:
14
+ print("Unable to import pyobjc modules")
15
+ else:
16
+ with resources.path("autogaita.resources", "icon.icns") as icon_path:
17
+ ns_application = NSApplication.sharedApplication()
18
+ logo_ns_image = NSImage.alloc().initWithContentsOfFile_(str(icon_path))
19
+ ns_application.setApplicationIconImage_(logo_ns_image)
20
+ elif platform.system().startswith("win"):
21
+ with resources.path("autogaita.resources", "icon.ico") as icon_path:
22
+ root.iconbitmap(str(icon_path))
23
+
24
+
25
+ def fix_window_after_its_creation(window):
26
+ """Perform some quality of life things after creating a window (root or Toplevel)"""
27
+ window.attributes("-topmost", True)
28
+ window.focus_set()
29
+ window.after(100, lambda: window.attributes("-topmost", False)) # 100 ms
30
+
31
+
32
+ def maximise_widgets(window):
33
+ """Maximises all widgets to look good in fullscreen"""
34
+ # fix the grid to fill the window
35
+ num_rows = window.grid_size()[1] # maximise rows
36
+ for r in range(num_rows):
37
+ window.grid_rowconfigure(r, weight=1)
38
+ num_cols = window.grid_size()[0] # maximise cols
39
+ for c in range(num_cols):
40
+ window.grid_columnconfigure(c, weight=1)
41
+
42
+
43
+ # .............................. change widget states ................................
44
+
45
+
46
+ def change_widget_state_based_on_checkbox(cfg, key_of_checkbox, entry_to_change):
47
+ """Change the state of an entry widget based on whether a checkbox is checked."""
48
+ if cfg[key_of_checkbox].get() is True:
49
+ entry_to_change.configure(state="normal")
50
+ elif cfg[key_of_checkbox].get() is False:
51
+ entry_to_change.configure(state="disabled")
@@ -192,7 +192,9 @@ def run_sleap_gui():
192
192
  WIDGET_CFG,
193
193
  )
194
194
  convert_checkbox.configure(
195
- command=lambda: gui_utils.change_ratio_entry_state(cfg, ratio_entry),
195
+ command=lambda: gui_utils.change_widget_state_based_on_checkbox(
196
+ cfg, "convert_to_mm", ratio_entry
197
+ ),
196
198
  )
197
199
  convert_checkbox.grid(row=2, column=0, columnspan=2, sticky="w")
198
200
 
@@ -209,7 +211,7 @@ def run_sleap_gui():
209
211
  )
210
212
  ratio_right_label.grid(row=2, column=2, sticky="w")
211
213
  # to initialise the widget correctly, run this function once
212
- gui_utils.change_ratio_entry_state(cfg, ratio_entry)
214
+ gui_utils.change_widget_state_based_on_checkbox(cfg, "convert_to_mm", ratio_entry)
213
215
 
214
216
  # NU - I'll implement beam subtraction and gait direction flipping after having
215
217
  # data for testing