autogaita 1.1.0__tar.gz → 1.1.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.
- {autogaita-1.1.0 → autogaita-1.1.1}/PKG-INFO +1 -1
- {autogaita-1.1.0 → autogaita-1.1.1}/README.md +1 -1
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/batchrun_scripts/dlc_multirun.py +1 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/batchrun_scripts/dlc_singlerun.py +4 -1
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/batchrun_scripts/sleap_singlerun.py +1 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/batchrun_scripts/universal3D_multirun.py +1 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/batchrun_scripts/universal3D_singlerun.py +1 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/common2D/common2D_1_preparation.py +26 -7
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/common2D/common2D_2_sc_extraction.py +8 -4
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/common2D/common2D_utils.py +44 -2
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/dlc/dlc_main.py +1 -1
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/gui/common2D_advanced_config_gui.py +25 -12
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/gui/common2D_gui_constants.py +1 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/gui/dlc_gui_config.json +1 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/gui/gui_utils.py +6 -6
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/gui/sleap_gui_config.json +1 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/gui/universal3D_gui.py +24 -11
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/gui/universal3D_gui_config.json +1 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/resources/utils.py +154 -1
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/sleap/sleap_main.py +1 -1
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/universal3D/universal3D_1_preparation.py +17 -4
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita.egg-info/PKG-INFO +1 -1
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita.egg-info/SOURCES.txt +2 -1
- {autogaita-1.1.0 → autogaita-1.1.1}/setup.py +1 -1
- {autogaita-1.1.0 → autogaita-1.1.1}/tests/test_common2D_unit_1_preparation.py +1 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/tests/test_common2D_unit_2_sc_extraction.py +38 -9
- {autogaita-1.1.0 → autogaita-1.1.1}/tests/test_common2D_unit_3_analysis.py +4 -1
- {autogaita-1.1.0 → autogaita-1.1.1}/tests/test_dlc_approval.py +1 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/tests/test_dlc_unit_1_preparation.py +1 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/tests/test_universal3D_approval.py +1 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/tests/test_universal3D_unit_3_analysis.py +1 -0
- autogaita-1.1.1/tests/test_utils.py +297 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/LICENSE +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/__init__.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/__main__.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/batchrun_scripts/__init__.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/batchrun_scripts/group_dlcrun.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/batchrun_scripts/group_dlcrun_forpaper.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/batchrun_scripts/group_universal3Drun.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/common2D/__init__.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/common2D/common2D_3_analysis.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/common2D/common2D_4_plots.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/common2D/common2D_constants.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/dlc/__init__.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/group/__init__.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/group/group_1_preparation.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/group/group_2_data_processing.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/group/group_3_PCA.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/group/group_4_stats.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/group/group_5_plots.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/group/group_constants.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/group/group_main.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/group/group_utils.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/gui/__init__.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/gui/common2D_columninfo_gui.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/gui/common2D_gui_utils.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/gui/common2D_main_gui.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/gui/common2D_run_and_done_gui.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/gui/dlc_gui.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/gui/first_level_gui_utils.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/gui/gaita_widgets.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/gui/group_gui.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/gui/group_gui_config.json +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/gui/gui_constants.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/gui/main_gui.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/gui/sleap_gui.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/resources/__init__.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/resources/constants.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/resources/icon.icns +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/resources/icon.ico +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/resources/logo.png +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/resources/pic_to_demo_for_repo.png +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/sleap/__init__.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/universal3D/__init__.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/universal3D/universal3D_2_sc_extraction.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/universal3D/universal3D_3_analysis.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/universal3D/universal3D_4_plots.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/universal3D/universal3D_constants.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/universal3D/universal3D_datafile_preparation.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/universal3D/universal3D_main.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita/universal3D/universal3D_utils.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita.egg-info/dependency_links.txt +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita.egg-info/requires.txt +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/autogaita.egg-info/top_level.txt +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/setup.cfg +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/tests/__init__.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/tests/test_group_approval.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/tests/test_group_unit.py +0 -0
- {autogaita-1.1.0 → autogaita-1.1.1}/tests/test_universal3D_unit_1_preparation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: autogaita
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.1
|
|
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
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
# Automated Gait Analysis in Python 🐸
|
|
13
13
|
|
|
14
|
-
- AutoGaitA simplifies, accelerates, and standardises gait analyses after body posture tracking in 2D with [DeepLabCut](https://github.com/DeepLabCut/DeepLabCut) and [SLEAP](https://github.com/talmolab/sleap) or marker-based (such as [Simi Motion](http://www.simi.com/en/products/movement-analysis/simi-motion-2d3d.html?type=rss%2F))
|
|
14
|
+
- AutoGaitA simplifies, accelerates, and standardises gait analyses (as well as the analysis of other rhythmic behaviours) after body posture tracking in 2D with [DeepLabCut](https://github.com/DeepLabCut/DeepLabCut) and [SLEAP](https://github.com/talmolab/sleap) or marker-based as well as marker-less (such as [Simi Motion](http://www.simi.com/en/products/movement-analysis/simi-motion-2d3d.html?type=rss%2F)) methods for obtaining 3D coordinates.
|
|
15
15
|
- AutoGaitA's first-level tools provide a wide range of automated kinematic analyses for each input video and AutoGaitA Group allows the comparison of up to six groups.
|
|
16
16
|
- AutoGaitA enables comparisons to be made across experimental conditions, species, disease states or genotypes.
|
|
17
17
|
- Despite being developed with gait data, AutoGaitA can be utilised for the analysis of any motor behaviour.
|
|
@@ -43,6 +43,7 @@ def dlc_multirun():
|
|
|
43
43
|
cfg["analyse_average_x"] = True
|
|
44
44
|
cfg["standardise_x_coordinates"] = True
|
|
45
45
|
cfg["x_standardisation_joint"] = ["Hind paw tao"]
|
|
46
|
+
cfg["coordinate_standardisation_xls"] = ""
|
|
46
47
|
cfg["results_dir"] = ""
|
|
47
48
|
cfg["hind_joints"] = ["Hind paw tao", "Ankle", "Knee", "Hip", "Iliac Crest"]
|
|
48
49
|
cfg["fore_joints"] = [
|
|
@@ -23,7 +23,7 @@ def dlc_singlerun():
|
|
|
23
23
|
cfg = {}
|
|
24
24
|
cfg["sampling_rate"] = 100 # base cfg
|
|
25
25
|
cfg["subtract_beam"] = True
|
|
26
|
-
cfg["dont_show_plots"] =
|
|
26
|
+
cfg["dont_show_plots"] = True
|
|
27
27
|
cfg["convert_to_mm"] = True
|
|
28
28
|
cfg["pixel_to_mm_ratio"] = 3.76
|
|
29
29
|
cfg["x_sc_broken_threshold"] = 200 # optional cfg
|
|
@@ -44,6 +44,9 @@ def dlc_singlerun():
|
|
|
44
44
|
cfg["analyse_average_x"] = True
|
|
45
45
|
cfg["standardise_x_coordinates"] = True
|
|
46
46
|
cfg["x_standardisation_joint"] = ["Hind paw tao"]
|
|
47
|
+
cfg["coordinate_standardisation_xls"] = (
|
|
48
|
+
"/Users/mahan/sciebo/PythonCode/gaita_repo/autogaita/resources/Coordinate Standardisation Table Template.xlsx"
|
|
49
|
+
)
|
|
47
50
|
cfg["hind_joints"] = ["Hind paw tao", "Ankle", "Knee", "Hip", "Iliac Crest"]
|
|
48
51
|
cfg["fore_joints"] = [
|
|
49
52
|
"Front paw tao ",
|
|
@@ -49,6 +49,7 @@ def sleap_singlerun():
|
|
|
49
49
|
cfg["analyse_average_x"] = False
|
|
50
50
|
cfg["standardise_x_coordinates"] = False
|
|
51
51
|
cfg["x_standardisation_joint"] = ["Midfoot"]
|
|
52
|
+
cfg["coordinate_standardisation_xls"] = ""
|
|
52
53
|
cfg["hind_joints"] = ["Midfoot", "Ankle", "Knee", "Hip"]
|
|
53
54
|
cfg["fore_joints"] = []
|
|
54
55
|
cfg["beam_col_left"] = [] # list of len == 1
|
|
@@ -34,6 +34,7 @@ def universal3D_multirun():
|
|
|
34
34
|
cfg["analyse_average_y"] = True
|
|
35
35
|
cfg["standardise_y_coordinates"] = True
|
|
36
36
|
cfg["y_standardisation_joint"] = ["Foot"]
|
|
37
|
+
cfg["coordinate_standardisation_xls"] = ""
|
|
37
38
|
cfg["joints"] = ["Midfoot", "Ankle", "Knee", "Hip", "Pelvis", "Shoulder", "Neck"]
|
|
38
39
|
cfg["angles"] = {
|
|
39
40
|
"name": ["Ankle", "Knee"],
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# %% imports
|
|
2
|
-
from autogaita.resources.utils import
|
|
2
|
+
from autogaita.resources.utils import (
|
|
3
|
+
write_issues_to_textfile,
|
|
4
|
+
standardise_primary_joint_coordinates,
|
|
5
|
+
)
|
|
3
6
|
from autogaita.common2D.common2D_constants import FILE_ID_STRING_ADDITIONS
|
|
4
7
|
import os
|
|
5
8
|
import shutil
|
|
@@ -48,6 +51,7 @@ def some_prep(tracking_software, info, folderinfo, cfg):
|
|
|
48
51
|
analyse_average_x = cfg["analyse_average_x"]
|
|
49
52
|
standardise_x_coordinates = cfg["standardise_x_coordinates"]
|
|
50
53
|
standardise_y_to_a_joint = cfg["standardise_y_to_a_joint"]
|
|
54
|
+
coordinate_standardisation_xls = cfg["coordinate_standardisation_xls"]
|
|
51
55
|
|
|
52
56
|
# ............................. move data ........................................
|
|
53
57
|
# => slightly different for DLC or SLEAP (see local functions below)
|
|
@@ -198,6 +202,7 @@ def some_prep(tracking_software, info, folderinfo, cfg):
|
|
|
198
202
|
"x_standardisation_joint": x_standardisation_joint,
|
|
199
203
|
"standardise_y_to_a_joint": standardise_y_to_a_joint,
|
|
200
204
|
"y_standardisation_joint": y_standardisation_joint,
|
|
205
|
+
"coordinate_standardisation_xls": coordinate_standardisation_xls,
|
|
201
206
|
"hind_joints": hind_joints,
|
|
202
207
|
"fore_joints": fore_joints,
|
|
203
208
|
"angles": angles,
|
|
@@ -236,7 +241,7 @@ def some_prep(tracking_software, info, folderinfo, cfg):
|
|
|
236
241
|
)
|
|
237
242
|
print(cols_are_weird_message)
|
|
238
243
|
write_issues_to_textfile(cols_are_weird_message, info)
|
|
239
|
-
# if wanted: fix that deeplabcut
|
|
244
|
+
# if wanted: fix that deeplabcut & SLEAP inverse y
|
|
240
245
|
if invert_y_axis:
|
|
241
246
|
for col in data.columns:
|
|
242
247
|
if col.endswith(" y"):
|
|
@@ -250,11 +255,6 @@ def some_prep(tracking_software, info, folderinfo, cfg):
|
|
|
250
255
|
else:
|
|
251
256
|
y_min = data[y_cols].min().min()
|
|
252
257
|
data[y_cols] -= y_min
|
|
253
|
-
# convert pixels to millimeters
|
|
254
|
-
if convert_to_mm:
|
|
255
|
-
for column in data.columns:
|
|
256
|
-
if not column.endswith("likelihood"):
|
|
257
|
-
data[column] = data[column] / pixel_to_mm_ratio
|
|
258
258
|
# quick warning if cfg is set to not flip gait direction but to standardise x
|
|
259
259
|
if not flip_gait_direction and standardise_x_coordinates:
|
|
260
260
|
message = (
|
|
@@ -295,6 +295,25 @@ def some_prep(tracking_software, info, folderinfo, cfg):
|
|
|
295
295
|
# reorder the columns we added
|
|
296
296
|
cols = [TIME_COL, "Flipped"]
|
|
297
297
|
data = data[cols + [c for c in data.columns if c not in cols]]
|
|
298
|
+
# ------------------------------------------------------------------------
|
|
299
|
+
# IMPORTANT
|
|
300
|
+
# Next two things must be the last that are done in this function, since
|
|
301
|
+
# joint-standardisation must be done after beam-subtraction & non-beam-height-stand
|
|
302
|
+
# and pixel-standardisation must be done after joint-standardisation!
|
|
303
|
+
# ------------------------------------------------------------------------
|
|
304
|
+
# 1) standardise all primary joint (!) coordinates
|
|
305
|
+
# => all dimensions are divided by a fixed user-provided value
|
|
306
|
+
# => note this function has proper errors raised if things should be wrongly
|
|
307
|
+
# configured by user!
|
|
308
|
+
if len(coordinate_standardisation_xls) > 0:
|
|
309
|
+
data, cfg = standardise_primary_joint_coordinates(
|
|
310
|
+
data, tracking_software, info, cfg
|
|
311
|
+
)
|
|
312
|
+
# 2) convert pixels to millimeters
|
|
313
|
+
if convert_to_mm:
|
|
314
|
+
for column in data.columns:
|
|
315
|
+
if column.endswith((" x", " y")): # if tuple: endswith any of these
|
|
316
|
+
data[column] = data[column] / pixel_to_mm_ratio
|
|
298
317
|
return data
|
|
299
318
|
|
|
300
319
|
|
|
@@ -4,7 +4,8 @@ from autogaita.common2D.common2D_utils import (
|
|
|
4
4
|
check_cycle_out_of_bounds,
|
|
5
5
|
check_cycle_duplicates,
|
|
6
6
|
check_cycle_order,
|
|
7
|
-
|
|
7
|
+
check_tracking_xy_thresholds,
|
|
8
|
+
check_tracking_SLEAP_nans,
|
|
8
9
|
handle_issues,
|
|
9
10
|
)
|
|
10
11
|
import os
|
|
@@ -23,7 +24,7 @@ from autogaita.common2D.common2D_constants import (
|
|
|
23
24
|
# %% workflow step #2 - SC extraction (reading user-provided SC Table)
|
|
24
25
|
|
|
25
26
|
|
|
26
|
-
def extract_stepcycles(data, info, folderinfo, cfg):
|
|
27
|
+
def extract_stepcycles(tracking_software, data, info, folderinfo, cfg):
|
|
27
28
|
"""Read XLS file with SC annotations, find correct row & return all_cycles"""
|
|
28
29
|
|
|
29
30
|
# ............................... preparation ....................................
|
|
@@ -212,6 +213,9 @@ def extract_stepcycles(data, info, folderinfo, cfg):
|
|
|
212
213
|
all_cycles = check_cycle_duplicates(all_cycles)
|
|
213
214
|
# check if user input progressively later latencies
|
|
214
215
|
all_cycles = check_cycle_order(all_cycles, info)
|
|
215
|
-
# check if tracking broke for any SCs -
|
|
216
|
-
all_cycles =
|
|
216
|
+
# check if tracking broke for any SCs using user-provided x and y thresholds
|
|
217
|
+
all_cycles = check_tracking_xy_thresholds(data, info, all_cycles, cfg)
|
|
218
|
+
# for SLEAP - check if there were any NaNs in any joints/angle-joints in SCs
|
|
219
|
+
if tracking_software == "SLEAP":
|
|
220
|
+
all_cycles = check_tracking_SLEAP_nans(data, info, all_cycles, cfg)
|
|
217
221
|
return all_cycles
|
|
@@ -210,7 +210,7 @@ def check_cycle_order(all_cycles, info):
|
|
|
210
210
|
return clean_cycles
|
|
211
211
|
|
|
212
212
|
|
|
213
|
-
def
|
|
213
|
+
def check_tracking_xy_thresholds(data, info, all_cycles, cfg):
|
|
214
214
|
"""Check if any x/y column of any joint has broken datapoints"""
|
|
215
215
|
# unpack
|
|
216
216
|
convert_to_mm = cfg["convert_to_mm"]
|
|
@@ -241,7 +241,49 @@ def check_tracking(data, info, all_cycles, cfg):
|
|
|
241
241
|
exclude_this_cycle = True
|
|
242
242
|
if exclude_this_cycle == True:
|
|
243
243
|
this_message = (
|
|
244
|
-
"\n...excluding SC #"
|
|
244
|
+
"\n...excluding SC #"
|
|
245
|
+
+ str(c + 1)
|
|
246
|
+
+ " - Tracking failed (coordinate-jump larger than x/y threshold)!"
|
|
247
|
+
)
|
|
248
|
+
print(this_message)
|
|
249
|
+
write_issues_to_textfile(this_message, info)
|
|
250
|
+
else:
|
|
251
|
+
if clean_cycles == None:
|
|
252
|
+
clean_cycles = [cycle] # also makes a 2xscs list of lists
|
|
253
|
+
else:
|
|
254
|
+
clean_cycles.append(cycle)
|
|
255
|
+
return clean_cycles
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def check_tracking_SLEAP_nans(data, info, all_cycles, cfg):
|
|
259
|
+
"""In SLEAP if tracking fails it generates NaNs - make sure we don't have those in any SC in any joint or angle-joint"""
|
|
260
|
+
# unpack
|
|
261
|
+
hind_joints = cfg["hind_joints"]
|
|
262
|
+
angles = cfg["angles"]
|
|
263
|
+
# all joints to test for NaNs
|
|
264
|
+
all_joints = hind_joints
|
|
265
|
+
for key in angles.keys():
|
|
266
|
+
all_joints += angles[key]
|
|
267
|
+
# columns to check
|
|
268
|
+
columns = []
|
|
269
|
+
for joint in all_joints:
|
|
270
|
+
columns.append(joint + "x")
|
|
271
|
+
columns.append(joint + "y")
|
|
272
|
+
# check for NaNs
|
|
273
|
+
clean_cycles = None
|
|
274
|
+
for c, cycle in enumerate(all_cycles):
|
|
275
|
+
exclude_this_cycle = False # reset
|
|
276
|
+
for col in columns:
|
|
277
|
+
this_data = data.loc[cycle[0] : cycle[1], col]
|
|
278
|
+
if any(this_data.isna()):
|
|
279
|
+
exclude_this_cycle = True
|
|
280
|
+
NaN_joint = col
|
|
281
|
+
break
|
|
282
|
+
if exclude_this_cycle == True:
|
|
283
|
+
this_message = (
|
|
284
|
+
"\n...excluding SC #"
|
|
285
|
+
+ str(c + 1)
|
|
286
|
+
+ f" - Tracking failed (NaN found at {NaN_joint})!"
|
|
245
287
|
)
|
|
246
288
|
print(this_message)
|
|
247
289
|
write_issues_to_textfile(this_message, info)
|
|
@@ -47,7 +47,7 @@ def dlc(info, folderinfo, cfg):
|
|
|
47
47
|
return
|
|
48
48
|
|
|
49
49
|
# ......................... step-cycle extraction ................................
|
|
50
|
-
all_cycles = extract_stepcycles(data, info, folderinfo, cfg)
|
|
50
|
+
all_cycles = extract_stepcycles(tracking_software, data, info, folderinfo, cfg)
|
|
51
51
|
if all_cycles is None:
|
|
52
52
|
handle_issues("scs_invalid", info)
|
|
53
53
|
if cfg["dont_show_plots"] is False: # otherwise stuck at loading
|
|
@@ -203,6 +203,19 @@ def build_cfg_window(root, cfg, widget_cfg, root_dimensions):
|
|
|
203
203
|
)
|
|
204
204
|
invert_y_axis_box.grid(row=12, column=0, columnspan=2)
|
|
205
205
|
|
|
206
|
+
# Standardise all (primary) joint coordinates by a fixed decimal value
|
|
207
|
+
coordinate_standardisation_xls_label, coordinate_standardisation_xls_entry = (
|
|
208
|
+
gaita_widgets.label_and_entry_pair(
|
|
209
|
+
cfg_window,
|
|
210
|
+
"Excel file for primary-joint coordinate standardisation:",
|
|
211
|
+
cfg["coordinate_standardisation_xls"],
|
|
212
|
+
widget_cfg,
|
|
213
|
+
adv_cfg_textsize=True,
|
|
214
|
+
)
|
|
215
|
+
)
|
|
216
|
+
coordinate_standardisation_xls_label.grid(row=13, column=0, columnspan=2)
|
|
217
|
+
coordinate_standardisation_xls_entry.grid(row=14, column=0, columnspan=2)
|
|
218
|
+
|
|
206
219
|
# ............................. advanced output .................................
|
|
207
220
|
# advanced analysis header
|
|
208
221
|
adv_cfg_output_header_label = gaita_widgets.header_label(
|
|
@@ -211,7 +224,7 @@ def build_cfg_window(root, cfg, widget_cfg, root_dimensions):
|
|
|
211
224
|
widget_cfg,
|
|
212
225
|
)
|
|
213
226
|
adv_cfg_output_header_label.grid(
|
|
214
|
-
row=
|
|
227
|
+
row=15, column=0, rowspan=2, columnspan=2, sticky="nsew"
|
|
215
228
|
)
|
|
216
229
|
|
|
217
230
|
# number of hindlimb (primary) joints to plot
|
|
@@ -222,8 +235,8 @@ def build_cfg_window(root, cfg, widget_cfg, root_dimensions):
|
|
|
222
235
|
widget_cfg,
|
|
223
236
|
adv_cfg_textsize=True,
|
|
224
237
|
)
|
|
225
|
-
plot_joint_num__label.grid(row=
|
|
226
|
-
plot_joint_num_entry.grid(row=
|
|
238
|
+
plot_joint_num__label.grid(row=17, column=0, columnspan=2)
|
|
239
|
+
plot_joint_num_entry.grid(row=18, column=0, columnspan=2)
|
|
227
240
|
|
|
228
241
|
# save to xls
|
|
229
242
|
save_to_xls_box = gaita_widgets.checkbox(
|
|
@@ -233,7 +246,7 @@ def build_cfg_window(root, cfg, widget_cfg, root_dimensions):
|
|
|
233
246
|
widget_cfg,
|
|
234
247
|
adv_cfg_textsize=True,
|
|
235
248
|
)
|
|
236
|
-
save_to_xls_box.grid(row=
|
|
249
|
+
save_to_xls_box.grid(row=19, column=0, columnspan=2)
|
|
237
250
|
|
|
238
251
|
# plot SE
|
|
239
252
|
plot_SE_box = gaita_widgets.checkbox(
|
|
@@ -243,7 +256,7 @@ def build_cfg_window(root, cfg, widget_cfg, root_dimensions):
|
|
|
243
256
|
widget_cfg,
|
|
244
257
|
adv_cfg_textsize=True,
|
|
245
258
|
)
|
|
246
|
-
plot_SE_box.grid(row=
|
|
259
|
+
plot_SE_box.grid(row=20, column=0, columnspan=2)
|
|
247
260
|
|
|
248
261
|
# color palette
|
|
249
262
|
color_palette_string = "Choose figures' color palette"
|
|
@@ -252,7 +265,7 @@ def build_cfg_window(root, cfg, widget_cfg, root_dimensions):
|
|
|
252
265
|
text=color_palette_string,
|
|
253
266
|
font=(TEXT_FONT_NAME, ADV_CFG_TEXT_FONT_SIZE),
|
|
254
267
|
)
|
|
255
|
-
color_palette_label.grid(row=
|
|
268
|
+
color_palette_label.grid(row=21, column=0, columnspan=2)
|
|
256
269
|
color_palette_entry = ctk.CTkOptionMenu(
|
|
257
270
|
cfg_window,
|
|
258
271
|
values=COLOR_PALETTES_LIST,
|
|
@@ -262,7 +275,7 @@ def build_cfg_window(root, cfg, widget_cfg, root_dimensions):
|
|
|
262
275
|
button_hover_color=HOVER_COLOR,
|
|
263
276
|
font=(TEXT_FONT_NAME, ADV_CFG_TEXT_FONT_SIZE),
|
|
264
277
|
)
|
|
265
|
-
color_palette_entry.grid(row=
|
|
278
|
+
color_palette_entry.grid(row=22, column=0, columnspan=2)
|
|
266
279
|
|
|
267
280
|
# legend outside
|
|
268
281
|
legend_outside_checkbox = gaita_widgets.checkbox(
|
|
@@ -272,18 +285,18 @@ def build_cfg_window(root, cfg, widget_cfg, root_dimensions):
|
|
|
272
285
|
widget_cfg,
|
|
273
286
|
adv_cfg_textsize=True,
|
|
274
287
|
)
|
|
275
|
-
legend_outside_checkbox.grid(row=
|
|
288
|
+
legend_outside_checkbox.grid(row=23, column=0, columnspan=2)
|
|
276
289
|
|
|
277
290
|
# results dir
|
|
278
291
|
results_dir_label, results_dir_entry = gaita_widgets.label_and_entry_pair(
|
|
279
292
|
cfg_window,
|
|
280
|
-
"Save Results subfolders to directory below instead of to data's",
|
|
293
|
+
"Save Results subfolders to directory below instead of to data's:",
|
|
281
294
|
cfg["results_dir"],
|
|
282
295
|
widget_cfg,
|
|
283
296
|
adv_cfg_textsize=True,
|
|
284
297
|
)
|
|
285
|
-
results_dir_label.grid(row=
|
|
286
|
-
results_dir_entry.grid(row=
|
|
298
|
+
results_dir_label.grid(row=24, column=0, columnspan=2)
|
|
299
|
+
results_dir_entry.grid(row=25, column=0, columnspan=2)
|
|
287
300
|
|
|
288
301
|
# done button
|
|
289
302
|
adv_cfg_done_button = ctk.CTkButton(
|
|
@@ -295,7 +308,7 @@ def build_cfg_window(root, cfg, widget_cfg, root_dimensions):
|
|
|
295
308
|
command=lambda: cfg_window.destroy(),
|
|
296
309
|
)
|
|
297
310
|
adv_cfg_done_button.grid(
|
|
298
|
-
row=
|
|
311
|
+
row=26, column=0, columnspan=2, rowspan=2, sticky="nsew", padx=10, pady=(10, 5)
|
|
299
312
|
)
|
|
300
313
|
# maximise widgets
|
|
301
314
|
cfg_window.columnconfigure(list(range(2)), weight=1, uniform="Silent_Creme")
|
|
@@ -43,9 +43,9 @@ def maximise_widgets(window):
|
|
|
43
43
|
# .............................. change widget states ................................
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
def change_widget_state_based_on_checkbox(cfg,
|
|
47
|
-
"""Change the state of
|
|
48
|
-
if cfg[
|
|
49
|
-
|
|
50
|
-
elif cfg[
|
|
51
|
-
|
|
46
|
+
def change_widget_state_based_on_checkbox(cfg, key_to_check, widget_to_change):
|
|
47
|
+
"""Change the state of a widget based on state of another widget."""
|
|
48
|
+
if cfg[key_to_check].get() is True:
|
|
49
|
+
widget_to_change.configure(state="normal")
|
|
50
|
+
elif cfg[key_to_check].get() is False:
|
|
51
|
+
widget_to_change.configure(state="disabled")
|
|
@@ -71,6 +71,7 @@ TK_STR_VARS = [
|
|
|
71
71
|
"sctable_filename",
|
|
72
72
|
"postname_string",
|
|
73
73
|
"color_palette",
|
|
74
|
+
"coordinate_standardisation_xls",
|
|
74
75
|
"fileprep_root_dir", # for datafile prep window only
|
|
75
76
|
"fileprep_filetype",
|
|
76
77
|
"fileprep_postname_string",
|
|
@@ -696,6 +697,18 @@ def build_cfg_window(root, cfg):
|
|
|
696
697
|
gui_utils.change_widget_state_based_on_checkbox(
|
|
697
698
|
cfg, "standardise_y_coordinates", y_standardisation_joint_entry
|
|
698
699
|
)
|
|
700
|
+
# standardise all (primary) joint coordinates by a fixed decimal value
|
|
701
|
+
coordinate_standardisation_xls_label, coordinate_standardisation_xls_entry = (
|
|
702
|
+
gaita_widgets.label_and_entry_pair(
|
|
703
|
+
cfg_window,
|
|
704
|
+
"Excel file for primary-joint coordinate standardisation:",
|
|
705
|
+
cfg["coordinate_standardisation_xls"],
|
|
706
|
+
WIDGET_CFG,
|
|
707
|
+
adv_cfg_textsize=True,
|
|
708
|
+
)
|
|
709
|
+
)
|
|
710
|
+
coordinate_standardisation_xls_label.grid(row=12, column=0, columnspan=2)
|
|
711
|
+
coordinate_standardisation_xls_entry.grid(row=13, column=0, columnspan=2)
|
|
699
712
|
|
|
700
713
|
# ............................. advanced output .................................
|
|
701
714
|
# advanced output header
|
|
@@ -703,7 +716,7 @@ def build_cfg_window(root, cfg):
|
|
|
703
716
|
cfg_window, "Output", WIDGET_CFG
|
|
704
717
|
)
|
|
705
718
|
adv_cfg_output_header_label.grid(
|
|
706
|
-
row=
|
|
719
|
+
row=14, column=0, rowspan=2, columnspan=2, sticky="nsew"
|
|
707
720
|
)
|
|
708
721
|
# number of joints to plot
|
|
709
722
|
plot_joint_num_label, plot_joint_num_entry = gaita_widgets.label_and_entry_pair(
|
|
@@ -713,8 +726,8 @@ def build_cfg_window(root, cfg):
|
|
|
713
726
|
WIDGET_CFG,
|
|
714
727
|
adv_cfg_textsize=True,
|
|
715
728
|
)
|
|
716
|
-
plot_joint_num_label.grid(row=
|
|
717
|
-
plot_joint_num_entry.grid(row=
|
|
729
|
+
plot_joint_num_label.grid(row=16, column=0, sticky="e")
|
|
730
|
+
plot_joint_num_entry.grid(row=16, column=1, sticky="w")
|
|
718
731
|
# plot plots to python
|
|
719
732
|
showplots_checkbox = gaita_widgets.checkbox(
|
|
720
733
|
cfg_window,
|
|
@@ -723,7 +736,7 @@ def build_cfg_window(root, cfg):
|
|
|
723
736
|
WIDGET_CFG,
|
|
724
737
|
adv_cfg_textsize=True,
|
|
725
738
|
)
|
|
726
|
-
showplots_checkbox.grid(row=
|
|
739
|
+
showplots_checkbox.grid(row=17, column=0, columnspan=2)
|
|
727
740
|
# plot SE
|
|
728
741
|
plot_SE_box = gaita_widgets.checkbox(
|
|
729
742
|
cfg_window,
|
|
@@ -732,7 +745,7 @@ def build_cfg_window(root, cfg):
|
|
|
732
745
|
WIDGET_CFG,
|
|
733
746
|
adv_cfg_textsize=True,
|
|
734
747
|
)
|
|
735
|
-
plot_SE_box.grid(row=
|
|
748
|
+
plot_SE_box.grid(row=18, column=0, columnspan=2)
|
|
736
749
|
# color palette
|
|
737
750
|
color_palette_string = "Choose figures' color palette"
|
|
738
751
|
color_palette_label = ctk.CTkLabel(
|
|
@@ -740,7 +753,7 @@ def build_cfg_window(root, cfg):
|
|
|
740
753
|
text=color_palette_string,
|
|
741
754
|
font=(TEXT_FONT_NAME, ADV_CFG_TEXT_FONT_SIZE),
|
|
742
755
|
)
|
|
743
|
-
color_palette_label.grid(row=
|
|
756
|
+
color_palette_label.grid(row=19, column=0, columnspan=2)
|
|
744
757
|
color_palette_entry = ctk.CTkOptionMenu(
|
|
745
758
|
cfg_window,
|
|
746
759
|
values=COLOR_PALETTES_LIST,
|
|
@@ -750,7 +763,7 @@ def build_cfg_window(root, cfg):
|
|
|
750
763
|
button_hover_color=HOVER_COLOR,
|
|
751
764
|
font=(TEXT_FONT_NAME, ADV_CFG_TEXT_FONT_SIZE),
|
|
752
765
|
)
|
|
753
|
-
color_palette_entry.grid(row=
|
|
766
|
+
color_palette_entry.grid(row=20, column=0, columnspan=2)
|
|
754
767
|
# legend outside
|
|
755
768
|
legend_outside_checkbox = gaita_widgets.checkbox(
|
|
756
769
|
cfg_window,
|
|
@@ -759,7 +772,7 @@ def build_cfg_window(root, cfg):
|
|
|
759
772
|
WIDGET_CFG,
|
|
760
773
|
adv_cfg_textsize=True,
|
|
761
774
|
)
|
|
762
|
-
legend_outside_checkbox.grid(row=
|
|
775
|
+
legend_outside_checkbox.grid(row=21, column=0, columnspan=2)
|
|
763
776
|
|
|
764
777
|
# results dir
|
|
765
778
|
results_dir_label, results_dir_entry = gaita_widgets.label_and_entry_pair(
|
|
@@ -769,8 +782,8 @@ def build_cfg_window(root, cfg):
|
|
|
769
782
|
WIDGET_CFG,
|
|
770
783
|
adv_cfg_textsize=True,
|
|
771
784
|
)
|
|
772
|
-
results_dir_label.grid(row=
|
|
773
|
-
results_dir_entry.grid(row=
|
|
785
|
+
results_dir_label.grid(row=22, column=0, columnspan=2)
|
|
786
|
+
results_dir_entry.grid(row=23, column=0, columnspan=2)
|
|
774
787
|
|
|
775
788
|
# done button
|
|
776
789
|
adv_cfg_done_button = ctk.CTkButton(
|
|
@@ -782,7 +795,7 @@ def build_cfg_window(root, cfg):
|
|
|
782
795
|
command=lambda: cfg_window.destroy(),
|
|
783
796
|
)
|
|
784
797
|
adv_cfg_done_button.grid(
|
|
785
|
-
row=
|
|
798
|
+
row=24, column=0, rowspan=2, columnspan=2, sticky="nsew", padx=10, pady=(10, 5)
|
|
786
799
|
)
|
|
787
800
|
# maximise widgets
|
|
788
801
|
cfg_window.columnconfigure(list(range(2)), weight=1, uniform="Silent_Creme")
|