autogaita 0.1.0__tar.gz → 0.2.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.
- autogaita-0.2.0/PKG-INFO +10 -0
- {autogaita-0.1.0 → autogaita-0.2.0}/README.md +18 -3
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita/autogaita_dlc.py +196 -90
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita/autogaita_dlc_gui.py +70 -12
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita/autogaita_group.py +116 -19
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita/autogaita_group_gui.py +67 -4
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita/autogaita_simi.py +120 -57
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita/autogaita_simi_gui.py +69 -12
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita/batchrun_scripts/autogaita_dlc_multirun.py +7 -5
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita/batchrun_scripts/autogaita_dlc_singlerun.py +9 -7
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita/batchrun_scripts/autogaita_group_dlcrun.py +2 -0
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita/batchrun_scripts/autogaita_group_simirun.py +2 -0
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita/batchrun_scripts/autogaita_simi_multirun.py +2 -0
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita/batchrun_scripts/autogaita_simi_singlerun.py +2 -0
- autogaita-0.2.0/autogaita/dlc_gui_config.json +82 -0
- autogaita-0.2.0/autogaita/group_gui_config.json +36 -0
- autogaita-0.2.0/autogaita/simi_gui_config.json +48 -0
- autogaita-0.2.0/autogaita.egg-info/PKG-INFO +10 -0
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita.egg-info/SOURCES.txt +4 -6
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita.egg-info/requires.txt +1 -0
- {autogaita-0.1.0 → autogaita-0.2.0}/setup.py +3 -2
- autogaita-0.1.0/PKG-INFO +0 -23
- autogaita-0.1.0/autogaita.egg-info/PKG-INFO +0 -23
- autogaita-0.1.0/tests/test_dlc_approval.py +0 -137
- autogaita-0.1.0/tests/test_dlc_unit2_sc_extraction.py +0 -250
- autogaita-0.1.0/tests/test_dlc_unit3_main_analysis.py +0 -219
- autogaita-0.1.0/tests/test_group_approval.py +0 -122
- autogaita-0.1.0/tests/test_simi_approval.py +0 -99
- {autogaita-0.1.0 → autogaita-0.2.0}/LICENSE +0 -0
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita/__init__.py +0 -0
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita/__main__.py +0 -0
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita/autogaita.py +0 -0
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita/autogaita_icon.icns +0 -0
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita/autogaita_icon.ico +0 -0
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita/autogaita_logo.png +0 -0
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita/autogaita_utils.py +0 -0
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita/batchrun_scripts/__init__.py +0 -0
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita.egg-info/dependency_links.txt +0 -0
- {autogaita-0.1.0 → autogaita-0.2.0}/autogaita.egg-info/top_level.txt +0 -0
- {autogaita-0.1.0 → autogaita-0.2.0}/setup.cfg +0 -0
autogaita-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: autogaita
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Automatic Gait Analysis in Python
|
|
5
|
+
Home-page: https://github.com/mahan-hosseini/AutoGaitA/
|
|
6
|
+
Author: Mahan Hosseini
|
|
7
|
+
License: GPLv3
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Provides-Extra: dev
|
|
10
|
+
License-File: LICENSE
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
## Getting Started
|
|
18
18
|
|
|
19
|
-
***Note!** Our documentation provides step-by-step walkthroughs of how to install autogaita for **[Windows](https://docs.google.com/document/d/1Y4wrrsjs0ybLDKPzE2LAatqPDq9jtwjIuk4M0jRZ3wE/edit#heading=h.28j6wu2vamre)** and **[Mac](https://docs.google.com/document/d/1Y4wrrsjs0ybLDKPzE2LAatqPDq9jtwjIuk4M0jRZ3wE/edit)***
|
|
19
|
+
***Note!** [Our documentation](https://docs.google.com/document/d/1Y4wrrsjs0ybLDKPzE2LAatqPDq9jtwjIuk4M0jRZ3wE/edit?usp=sharing) provides step-by-step walkthroughs of how to install autogaita for **[Windows](https://docs.google.com/document/d/1Y4wrrsjs0ybLDKPzE2LAatqPDq9jtwjIuk4M0jRZ3wE/edit#heading=h.28j6wu2vamre)** and **[Mac](https://docs.google.com/document/d/1Y4wrrsjs0ybLDKPzE2LAatqPDq9jtwjIuk4M0jRZ3wE/edit)***
|
|
20
20
|
|
|
21
21
|
It is strongly recommended that a separate virtual environment for AutoGaitA is created (note that the approach below creates the virtual environment to your current directory):
|
|
22
22
|
|
|
@@ -31,6 +31,8 @@ It is strongly recommended that a separate virtual environment for AutoGaitA is
|
|
|
31
31
|
|
|
32
32
|
- Access the main user interface via `python -m autogaita`.
|
|
33
33
|
|
|
34
|
+
- To update to the latest release (see the *Releases* panel on the right for the current version) activate your virtual environment & enter `pip install autogaita -U`.
|
|
35
|
+
|
|
34
36
|
## Tutorials and Examples
|
|
35
37
|
|
|
36
38
|
### Video Walkthrough Tutorials
|
|
@@ -45,7 +47,7 @@ We provide an example dataset in the **example data** folder of this repository,
|
|
|
45
47
|
### Annotation Table Examples and Templates
|
|
46
48
|
Annotation Table example and template files for *AutoGaitA_DLC* and *AutoGaitA_Simi* can be found in the [**annotation tables**](https://github.com/mahan-hosseini/AutoGaitA/tree/main/annotation%20tables) folder of this repository.
|
|
47
49
|
|
|
48
|
-
Users are advised to read the ***important note*** of that folder, use the template to enter their data's timestamp information and to then compare the resulting table with our example to check formatting.
|
|
50
|
+
Users are advised to read the ***important note*** of that folder, use the template to enter their data's timestamp information and to then compare the resulting table with our example to check formatting. Users working with ImageJ/FIJI are encouraged to check out the [AnnotationTable-Plugin](https://github.com/luca-flemming/AnnotationTable-Plugin) developed by our contributor Luca Flemming.
|
|
49
51
|
|
|
50
52
|
## Documentation
|
|
51
53
|
|
|
@@ -62,6 +64,9 @@ By default, *AutoGaitA DLC* and *AutoGaitA Simi* implement standard values for m
|
|
|
62
64
|
- [Documentation - AutoGaitA DLC](https://docs.google.com/document/d/1Y4wrrsjs0ybLDKPzE2LAatqPDq9jtwjIuk4M0jRZ3wE/edit#heading=h.20bg7b7ymt0b)
|
|
63
65
|
- [Documentation - AutoGaitA Simi](https://docs.google.com/document/d/1Y4wrrsjs0ybLDKPzE2LAatqPDq9jtwjIuk4M0jRZ3wE/edit#heading=h.uz61bpmua7qz)
|
|
64
66
|
|
|
67
|
+
## Analysing other behaviours - AutoCyclA 🚴
|
|
68
|
+
Even though AutoGaitA's main focus is to automate and standardise gait analyses, our toolbox can be used to automate the analyses of any rhythmic behaviour of interest. For a proof-of-principle demonstration and an introduction of the general workflow of such analyses, see **[AutoCyclA - Automated Cycling Analysis with AutoGaitA.](https://github.com/mahan-hosseini/AutoGaitA/tree/main/autocycla)**
|
|
69
|
+
|
|
65
70
|
## Reference
|
|
66
71
|
If you use this code or data please [cite our preprint](https://www.biorxiv.org/content/10.1101/2024.04.14.589409v1).
|
|
67
72
|
|
|
@@ -71,4 +76,14 @@ AutoGaitA is licensed under [GPL v3.0](https://github.com/mahan-hosseini/AutoGai
|
|
|
71
76
|
The AutoGaitA software is provided without warranty of any kind, express or implied, including, but not limited to, the implied warranty of fitness for a particular purpose.
|
|
72
77
|
|
|
73
78
|
## Authors
|
|
74
|
-
Mahan Hosseini
|
|
79
|
+
[Mahan Hosseini](https://github.com/mahan-hosseini)
|
|
80
|
+
|
|
81
|
+
## Contributors
|
|
82
|
+
[Luca Flemming](https://github.com/luca-flemming) - Undergraduate Student
|
|
83
|
+
|
|
84
|
+
[Nicholas del Grosso](https://github.com/nickdelgrosso) - RSE Advisor
|
|
85
|
+
|
|
86
|
+
## Contributing
|
|
87
|
+
If you would like to contribute to the AutoGaitA toolbox, feel free to open a pull request or contact us at autogaita@fz-juelich.de!
|
|
88
|
+
|
|
89
|
+
We are looking forward to your input and ideas 😊
|
|
@@ -9,6 +9,7 @@ import numpy as np
|
|
|
9
9
|
import math
|
|
10
10
|
import matplotlib
|
|
11
11
|
import matplotlib.pyplot as plt
|
|
12
|
+
import seaborn as sns
|
|
12
13
|
|
|
13
14
|
# %% constants
|
|
14
15
|
plt.rcParams["figure.dpi"] = 300 # increase resolution of figures
|
|
@@ -38,6 +39,7 @@ AVERAGE_XLS_FILENAME = " - Average Stepcycle"
|
|
|
38
39
|
STD_XLS_FILENAME = " - Standard Devs. Stepcycle"
|
|
39
40
|
SC_LAT_LEGEND_FONTSIZE = 7
|
|
40
41
|
|
|
42
|
+
|
|
41
43
|
# %% main program
|
|
42
44
|
|
|
43
45
|
|
|
@@ -92,6 +94,7 @@ def some_prep(info, folderinfo, cfg):
|
|
|
92
94
|
normalise_height_at_SC_level = cfg["normalise_height_at_SC_level"]
|
|
93
95
|
invert_y_axis = cfg["invert_y_axis"]
|
|
94
96
|
flip_gait_direction = cfg["flip_gait_direction"]
|
|
97
|
+
export_average_x = cfg["export_average_x"]
|
|
95
98
|
|
|
96
99
|
# ............................. move data ........................................
|
|
97
100
|
# => see if we can delete a previous runs results folder if existant. if not, it's a
|
|
@@ -127,8 +130,8 @@ def some_prep(info, folderinfo, cfg):
|
|
|
127
130
|
"\n******************\n! CRITICAL ERROR !\n******************\n"
|
|
128
131
|
+ "Unable to identify ANY RELEVANT FILES for "
|
|
129
132
|
+ name
|
|
130
|
-
+ "!\nThis is likely due to issues with
|
|
131
|
-
+ "capitalisation!"
|
|
133
|
+
+ "!\nThis is likely due to issues with unique file name identifiers.. "
|
|
134
|
+
+ "check capitalisation!"
|
|
132
135
|
)
|
|
133
136
|
write_issues_to_textfile(no_files_error, info)
|
|
134
137
|
print(no_files_error)
|
|
@@ -138,6 +141,15 @@ def some_prep(info, folderinfo, cfg):
|
|
|
138
141
|
datadf = pd.DataFrame(data=None) # prep stuff for error handling
|
|
139
142
|
datadf_duplicate_error = ""
|
|
140
143
|
if subtract_beam:
|
|
144
|
+
if data_string == beam_string:
|
|
145
|
+
beam_and_data_string_error_message = (
|
|
146
|
+
"\n******************\n! CRITICAL ERROR !\n******************\n"
|
|
147
|
+
+ "Your data & baseline (beam) identifiers ([G] in our "
|
|
148
|
+
+ "file naming convention) are identical. "
|
|
149
|
+
+ "\nNote that they must be different! \nTry again"
|
|
150
|
+
)
|
|
151
|
+
write_issues_to_textfile(beam_and_data_string_error_message, info)
|
|
152
|
+
return
|
|
141
153
|
beamdf = pd.DataFrame(data=None)
|
|
142
154
|
beamdf_duplicate_error = ""
|
|
143
155
|
for filename in os.listdir(results_dir): # import
|
|
@@ -216,7 +228,7 @@ def some_prep(info, folderinfo, cfg):
|
|
|
216
228
|
# IMPORTANT
|
|
217
229
|
# ---------
|
|
218
230
|
# MAIN TESTS OF USER-INPUT VALIDITY OCCUR HERE!
|
|
219
|
-
cfg =
|
|
231
|
+
cfg = check_and_expand_cfg(data, cfg, info)
|
|
220
232
|
if cfg is None: # hind joints were empty
|
|
221
233
|
return
|
|
222
234
|
hind_joints = cfg["hind_joints"]
|
|
@@ -225,7 +237,6 @@ def some_prep(info, folderinfo, cfg):
|
|
|
225
237
|
beam_hind_jointadd = cfg["beam_hind_jointadd"]
|
|
226
238
|
beam_fore_jointadd = cfg["beam_fore_jointadd"]
|
|
227
239
|
direction_joint = cfg["direction_joint"]
|
|
228
|
-
export_average_x = cfg["export_average_x"]
|
|
229
240
|
# store config json file @ group path
|
|
230
241
|
# !!! NU - do this @ mouse path!
|
|
231
242
|
group_path = results_dir.split(name)[0]
|
|
@@ -243,6 +254,29 @@ def some_prep(info, folderinfo, cfg):
|
|
|
243
254
|
# note - using "w" will overwrite/truncate file, thus no need to remove it if exists
|
|
244
255
|
with open(config_json_path, "w") as config_json_file:
|
|
245
256
|
json.dump(config_vars_to_json, config_json_file, indent=4)
|
|
257
|
+
# a little test to see if columns make sense, i.e., same number of x/y/likelihood
|
|
258
|
+
x_col_count = len([c for c in data.columns if c.endswith(" x")])
|
|
259
|
+
y_col_count = len([c for c in data.columns if c.endswith(" y")])
|
|
260
|
+
likelihood_col_count = len([c for c in data.columns if c.endswith(" likelihood")])
|
|
261
|
+
if x_col_count == y_col_count == likelihood_col_count:
|
|
262
|
+
pass
|
|
263
|
+
else:
|
|
264
|
+
cols_are_weird_message = (
|
|
265
|
+
"\n***********\n! WARNING !\n***********\n"
|
|
266
|
+
+ "We detected an unequal number of columns ending with x, y or "
|
|
267
|
+
+ "likelihood!\nCounts were:\n"
|
|
268
|
+
+ "x: "
|
|
269
|
+
+ str(x_col_count)
|
|
270
|
+
+ ", y: "
|
|
271
|
+
+ str(y_col_count)
|
|
272
|
+
+ ", likelihood: "
|
|
273
|
+
+ str(likelihood_col_count)
|
|
274
|
+
+ "!\n\n"
|
|
275
|
+
+ "We continue with the analysis but we strongly suggest you have another "
|
|
276
|
+
+ "look at your dataset, this should not happen.\n"
|
|
277
|
+
)
|
|
278
|
+
print(cols_are_weird_message)
|
|
279
|
+
write_issues_to_textfile(cols_are_weird_message, info)
|
|
246
280
|
# if wanted: fix that deeplabcut inverses y
|
|
247
281
|
if invert_y_axis:
|
|
248
282
|
for col in data.columns:
|
|
@@ -346,7 +380,7 @@ def move_data_to_folders(info, folderinfo):
|
|
|
346
380
|
write_issues_to_textfile(this_message, info)
|
|
347
381
|
|
|
348
382
|
|
|
349
|
-
def
|
|
383
|
+
def check_and_expand_cfg(data, cfg, info):
|
|
350
384
|
"""Test some important cfg variables and add new ones based on them
|
|
351
385
|
|
|
352
386
|
Procedure
|
|
@@ -402,7 +436,7 @@ def test_and_expand_cfg(data, cfg, info):
|
|
|
402
436
|
return
|
|
403
437
|
cfg["direction_joint"] = hind_joints[0]
|
|
404
438
|
|
|
405
|
-
# if subtracting beam, check that
|
|
439
|
+
# if subtracting beam, check identifier-strings & that beam colnames were valid.
|
|
406
440
|
if cfg["subtract_beam"]:
|
|
407
441
|
beam_col_error_message = (
|
|
408
442
|
"\n******************\n! CRITICAL ERROR !\n******************\n"
|
|
@@ -585,12 +619,10 @@ def flip_mouse_body(data, info):
|
|
|
585
619
|
write_issues_to_textfile(message, info)
|
|
586
620
|
|
|
587
621
|
# 1) Flip all rows in x columns only and subtract max from all vals
|
|
588
|
-
flipped_data =
|
|
589
|
-
for col in
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
else:
|
|
593
|
-
flipped_data.loc[:, col] = data.loc[:, col]
|
|
622
|
+
flipped_data = data.copy()
|
|
623
|
+
x_cols = [col for col in flipped_data.columns if col.endswith(" x")]
|
|
624
|
+
for col in x_cols:
|
|
625
|
+
flipped_data[col] = max(flipped_data[col]) - flipped_data[col]
|
|
594
626
|
return flipped_data
|
|
595
627
|
|
|
596
628
|
|
|
@@ -1330,6 +1362,24 @@ def add_step_separators(dataframe, nanvector, numvector):
|
|
|
1330
1362
|
|
|
1331
1363
|
|
|
1332
1364
|
# .............................. master function .............................
|
|
1365
|
+
|
|
1366
|
+
# A note on updated colour cyclers after pull request that was merged 20.06.2024
|
|
1367
|
+
# => Using color palettes instead of colour maps as I had previously means that
|
|
1368
|
+
# we cycle through neighbouring colours
|
|
1369
|
+
# => I initially implemented an "equally distant" approach.
|
|
1370
|
+
# => So for viridis and n=2 (e.g. if 2 groups) it would be purple and yellow
|
|
1371
|
+
# (as far away as possible)
|
|
1372
|
+
# => Now it is dark blue and green
|
|
1373
|
+
# => Updated approach is aesthetically more pleasing IMO.
|
|
1374
|
+
# => However it does have the risk of not being able to tell the colours in
|
|
1375
|
+
# some cases - e.g. if some accelerations are very overlapping.
|
|
1376
|
+
# => But - because users can in theses cases just choose a colour palette that
|
|
1377
|
+
# in itself has categorical colours (Set1, Dark2, etc.) I still keep the new
|
|
1378
|
+
# behaviour
|
|
1379
|
+
# => Nonetheless, in case you want to use the "old behaviour" at some point it
|
|
1380
|
+
# would be coded as commented out in plot_joint_y_by_x
|
|
1381
|
+
|
|
1382
|
+
|
|
1333
1383
|
def plot_results(info, results, folderinfo, cfg):
|
|
1334
1384
|
"""Plot results - y coords by x coords & average angles over SC %"""
|
|
1335
1385
|
# unpack
|
|
@@ -1439,6 +1489,8 @@ def plot_joint_y_by_x(all_steps_data, sc_idxs, info, cfg):
|
|
|
1439
1489
|
convert_to_mm = cfg["convert_to_mm"]
|
|
1440
1490
|
plot_joints = cfg["plot_joints"]
|
|
1441
1491
|
sampling_rate = cfg["sampling_rate"]
|
|
1492
|
+
legend_outside = cfg["legend_outside"]
|
|
1493
|
+
color_palette = cfg["color_palette"]
|
|
1442
1494
|
|
|
1443
1495
|
# some prep
|
|
1444
1496
|
sc_num = len(sc_idxs)
|
|
@@ -1448,49 +1500,37 @@ def plot_joint_y_by_x(all_steps_data, sc_idxs, info, cfg):
|
|
|
1448
1500
|
# plot
|
|
1449
1501
|
for j, joint in enumerate(plot_joints): # joint loop (figures)
|
|
1450
1502
|
f[j], ax[j] = plt.subplots(1, 1)
|
|
1451
|
-
|
|
1452
|
-
|
|
1503
|
+
# What "Old" colormap approach would look like with seaborn
|
|
1504
|
+
# this_map = sns.color_palette(cfg["color_palette"], as_cmap=True)
|
|
1505
|
+
# ax[j].set_prop_cycle(plt.cycler("color", this_map(np.linspace(0, 1, sc_num))))
|
|
1506
|
+
ax[j].set_prop_cycle( # New color palette approach
|
|
1507
|
+
plt.cycler("color", sns.color_palette(color_palette, sc_num))
|
|
1453
1508
|
)
|
|
1454
|
-
|
|
1455
|
-
ax[j].set_title(name + " - Foot")
|
|
1456
|
-
else:
|
|
1457
|
-
ax[j].set_title(name + " - " + joint)
|
|
1509
|
+
ax[j].set_title(name + " - " + joint)
|
|
1458
1510
|
x_col_idx = all_steps_data.columns.get_loc(joint + "x")
|
|
1459
1511
|
y_col_idx = all_steps_data.columns.get_loc(joint + "y")
|
|
1460
1512
|
time_col_idx = all_steps_data.columns.get_loc(TIME_COL)
|
|
1461
1513
|
for s in range(sc_num):
|
|
1462
1514
|
this_x = all_steps_data.iloc[sc_idxs[s], x_col_idx]
|
|
1463
1515
|
this_y = all_steps_data.iloc[sc_idxs[s], y_col_idx]
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
else:
|
|
1467
|
-
float_precision = 4
|
|
1468
|
-
this_label = (
|
|
1469
|
-
str(
|
|
1470
|
-
round(
|
|
1471
|
-
all_steps_data.iloc[sc_idxs[s][0], time_col_idx],
|
|
1472
|
-
float_precision,
|
|
1473
|
-
)
|
|
1474
|
-
)
|
|
1475
|
-
+ "-"
|
|
1476
|
-
+ str(
|
|
1477
|
-
round(
|
|
1478
|
-
all_steps_data.iloc[sc_idxs[s][-1], time_col_idx],
|
|
1479
|
-
float_precision,
|
|
1480
|
-
)
|
|
1481
|
-
)
|
|
1482
|
-
+ "s"
|
|
1516
|
+
this_label = generate_sc_latency_label(
|
|
1517
|
+
all_steps_data, sc_idxs[s], sampling_rate, time_col_idx
|
|
1483
1518
|
)
|
|
1484
1519
|
ax[j].plot(this_x, this_y, label=this_label)
|
|
1485
1520
|
ax[j].set_xlabel("x (pixel)") # will be overwritten if we convert
|
|
1486
1521
|
ax[j].set_ylabel("y (pixel)")
|
|
1487
|
-
|
|
1522
|
+
# legend adjustments
|
|
1523
|
+
if legend_outside is True:
|
|
1524
|
+
ax[j].legend(
|
|
1525
|
+
fontsize=SC_LAT_LEGEND_FONTSIZE,
|
|
1526
|
+
loc="center left",
|
|
1527
|
+
bbox_to_anchor=(1, 0.5),
|
|
1528
|
+
)
|
|
1529
|
+
elif legend_outside is False:
|
|
1530
|
+
ax[j].legend(fontsize=SC_LAT_LEGEND_FONTSIZE)
|
|
1488
1531
|
if convert_to_mm:
|
|
1489
1532
|
tickconvert_mm_to_cm(ax[j], "both")
|
|
1490
|
-
|
|
1491
|
-
figure_file_string = " - Foot y by x coordinates"
|
|
1492
|
-
else:
|
|
1493
|
-
figure_file_string = " - " + joint + "y by x coordinates"
|
|
1533
|
+
figure_file_string = " - " + joint + "y by x coordinates"
|
|
1494
1534
|
save_figures(f[j], results_dir, name, figure_file_string)
|
|
1495
1535
|
if dont_show_plots:
|
|
1496
1536
|
plt.close(f[j])
|
|
@@ -1504,6 +1544,9 @@ def plot_angles_by_time(all_steps_data, sc_idxs, info, cfg):
|
|
|
1504
1544
|
results_dir = info["results_dir"]
|
|
1505
1545
|
dont_show_plots = cfg["dont_show_plots"]
|
|
1506
1546
|
angles = cfg["angles"]
|
|
1547
|
+
sampling_rate = cfg["sampling_rate"]
|
|
1548
|
+
legend_outside = cfg["legend_outside"]
|
|
1549
|
+
color_palette = cfg["color_palette"]
|
|
1507
1550
|
|
|
1508
1551
|
# some prep
|
|
1509
1552
|
sc_num = len(sc_idxs)
|
|
@@ -1514,17 +1557,30 @@ def plot_angles_by_time(all_steps_data, sc_idxs, info, cfg):
|
|
|
1514
1557
|
for a, angle in enumerate(angles["name"]): # angle loop (figures)
|
|
1515
1558
|
f[a], ax[a] = plt.subplots(1, 1)
|
|
1516
1559
|
ax[a].set_prop_cycle(
|
|
1517
|
-
plt.cycler("color",
|
|
1560
|
+
plt.cycler("color", sns.color_palette(color_palette, sc_num))
|
|
1518
1561
|
)
|
|
1519
1562
|
ax[a].set_title(name + " - " + angle)
|
|
1520
1563
|
ax[a].set_ylabel("Angle")
|
|
1521
1564
|
ax[a].set_xlabel("Time (s)")
|
|
1522
1565
|
x_col_idx = all_steps_data.columns.get_loc(TIME_COL)
|
|
1523
1566
|
y_col_idx = all_steps_data.columns.get_loc(angle + "Angle")
|
|
1567
|
+
time_col_idx = all_steps_data.columns.get_loc(TIME_COL)
|
|
1524
1568
|
for s in range(sc_num):
|
|
1525
1569
|
this_x = all_steps_data.iloc[sc_idxs[s], x_col_idx]
|
|
1526
1570
|
this_y = all_steps_data.iloc[sc_idxs[s], y_col_idx]
|
|
1527
|
-
|
|
1571
|
+
this_label = generate_sc_latency_label(
|
|
1572
|
+
all_steps_data, sc_idxs[s], sampling_rate, time_col_idx
|
|
1573
|
+
)
|
|
1574
|
+
ax[a].plot(this_x, this_y, label=this_label)
|
|
1575
|
+
# legend adjustments
|
|
1576
|
+
if legend_outside is True:
|
|
1577
|
+
ax[a].legend(
|
|
1578
|
+
fontsize=SC_LAT_LEGEND_FONTSIZE,
|
|
1579
|
+
loc="center left",
|
|
1580
|
+
bbox_to_anchor=(1, 0.5),
|
|
1581
|
+
)
|
|
1582
|
+
elif legend_outside is False:
|
|
1583
|
+
ax[a].legend(fontsize=SC_LAT_LEGEND_FONTSIZE)
|
|
1528
1584
|
figure_file_string = " - " + angle + "Angle by Time"
|
|
1529
1585
|
save_figures(f[a], results_dir, name, figure_file_string)
|
|
1530
1586
|
if dont_show_plots:
|
|
@@ -1541,11 +1597,13 @@ def plot_hindlimb_stickdiagram(all_steps_data, sc_idxs, info, cfg):
|
|
|
1541
1597
|
convert_to_mm = cfg["convert_to_mm"]
|
|
1542
1598
|
plot_joints = cfg["plot_joints"]
|
|
1543
1599
|
sampling_rate = cfg["sampling_rate"]
|
|
1600
|
+
legend_outside = cfg["legend_outside"]
|
|
1601
|
+
color_palette = cfg["color_palette"]
|
|
1544
1602
|
|
|
1545
1603
|
# some prep
|
|
1546
1604
|
sc_num = len(sc_idxs)
|
|
1547
1605
|
f, ax = plt.subplots(1, 1)
|
|
1548
|
-
color_cycle = plt.cycler("color",
|
|
1606
|
+
color_cycle = plt.cycler("color", sns.color_palette(color_palette, sc_num))
|
|
1549
1607
|
ax.set_prop_cycle(color_cycle)
|
|
1550
1608
|
time_col_idx = all_steps_data.columns.get_loc(TIME_COL)
|
|
1551
1609
|
|
|
@@ -1553,21 +1611,8 @@ def plot_hindlimb_stickdiagram(all_steps_data, sc_idxs, info, cfg):
|
|
|
1553
1611
|
# => for timepoints from SC1 to SCend - plot(joint1x, joint1y)
|
|
1554
1612
|
for s, this_color_dict in zip(range(sc_num), color_cycle): # SC loop (colors)
|
|
1555
1613
|
this_color = this_color_dict["color"][:3]
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
else:
|
|
1559
|
-
float_precision = 4
|
|
1560
|
-
this_label = (
|
|
1561
|
-
str(
|
|
1562
|
-
round(all_steps_data.iloc[sc_idxs[s][0], time_col_idx], float_precision)
|
|
1563
|
-
)
|
|
1564
|
-
+ "-"
|
|
1565
|
-
+ str(
|
|
1566
|
-
round(
|
|
1567
|
-
all_steps_data.iloc[sc_idxs[s][-1], time_col_idx], float_precision
|
|
1568
|
-
)
|
|
1569
|
-
)
|
|
1570
|
-
+ "s"
|
|
1614
|
+
this_label = generate_sc_latency_label(
|
|
1615
|
+
all_steps_data, sc_idxs[s], sampling_rate, time_col_idx
|
|
1571
1616
|
)
|
|
1572
1617
|
for i in sc_idxs[s]: # loop over timepoints of current SC
|
|
1573
1618
|
this_xs = list() # for each timepoint, define joints' xy coord new
|
|
@@ -1586,7 +1631,13 @@ def plot_hindlimb_stickdiagram(all_steps_data, sc_idxs, info, cfg):
|
|
|
1586
1631
|
ax.set_ylabel("y (pixel)")
|
|
1587
1632
|
if convert_to_mm:
|
|
1588
1633
|
tickconvert_mm_to_cm(ax, "both")
|
|
1589
|
-
|
|
1634
|
+
# legend adjustments
|
|
1635
|
+
if legend_outside is True:
|
|
1636
|
+
ax.legend(
|
|
1637
|
+
fontsize=SC_LAT_LEGEND_FONTSIZE, loc="center left", bbox_to_anchor=(1, 0.5)
|
|
1638
|
+
)
|
|
1639
|
+
elif legend_outside is False:
|
|
1640
|
+
ax.legend(fontsize=SC_LAT_LEGEND_FONTSIZE)
|
|
1590
1641
|
figure_file_string = " - Hindlimb Stick Diagram"
|
|
1591
1642
|
save_figures(f, results_dir, name, figure_file_string)
|
|
1592
1643
|
if dont_show_plots:
|
|
@@ -1603,32 +1654,21 @@ def plot_forelimb_stickdiagram(all_steps_data, sc_idxs, info, cfg):
|
|
|
1603
1654
|
convert_to_mm = cfg["convert_to_mm"]
|
|
1604
1655
|
fore_joints = cfg["fore_joints"]
|
|
1605
1656
|
sampling_rate = cfg["sampling_rate"]
|
|
1657
|
+
legend_outside = cfg["legend_outside"]
|
|
1658
|
+
color_palette = cfg["color_palette"]
|
|
1606
1659
|
|
|
1607
1660
|
# some prep
|
|
1608
1661
|
sc_num = len(sc_idxs)
|
|
1609
1662
|
f, ax = plt.subplots(1, 1)
|
|
1610
|
-
color_cycle = plt.cycler("color",
|
|
1663
|
+
color_cycle = plt.cycler("color", sns.color_palette(color_palette, sc_num))
|
|
1611
1664
|
ax.set_prop_cycle(color_cycle)
|
|
1612
1665
|
time_col_idx = all_steps_data.columns.get_loc(TIME_COL)
|
|
1613
1666
|
|
|
1614
1667
|
# plot
|
|
1615
1668
|
for s, this_color in zip(range(sc_num), color_cycle): # SC loop (colors)
|
|
1616
1669
|
this_color = this_color["color"][:3]
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
else:
|
|
1620
|
-
float_precision = 4
|
|
1621
|
-
this_label = (
|
|
1622
|
-
str(
|
|
1623
|
-
round(all_steps_data.iloc[sc_idxs[s][0], time_col_idx], float_precision)
|
|
1624
|
-
)
|
|
1625
|
-
+ "-"
|
|
1626
|
-
+ str(
|
|
1627
|
-
round(
|
|
1628
|
-
all_steps_data.iloc[sc_idxs[s][-1], time_col_idx], float_precision
|
|
1629
|
-
)
|
|
1630
|
-
)
|
|
1631
|
-
+ "s"
|
|
1670
|
+
this_label = generate_sc_latency_label(
|
|
1671
|
+
all_steps_data, sc_idxs[s], sampling_rate, time_col_idx
|
|
1632
1672
|
)
|
|
1633
1673
|
for i in sc_idxs[s]:
|
|
1634
1674
|
this_xs = list()
|
|
@@ -1647,7 +1687,13 @@ def plot_forelimb_stickdiagram(all_steps_data, sc_idxs, info, cfg):
|
|
|
1647
1687
|
ax.set_ylabel("y (pixel)")
|
|
1648
1688
|
if convert_to_mm:
|
|
1649
1689
|
tickconvert_mm_to_cm(ax, "both")
|
|
1650
|
-
|
|
1690
|
+
# legend adjustments
|
|
1691
|
+
if legend_outside is True:
|
|
1692
|
+
ax.legend(
|
|
1693
|
+
fontsize=SC_LAT_LEGEND_FONTSIZE, loc="center left", bbox_to_anchor=(1, 0.5)
|
|
1694
|
+
)
|
|
1695
|
+
elif legend_outside is False:
|
|
1696
|
+
ax.legend(fontsize=SC_LAT_LEGEND_FONTSIZE)
|
|
1651
1697
|
figure_file_string = " - Forelimb Stick Diagram"
|
|
1652
1698
|
save_figures(f, results_dir, name, figure_file_string)
|
|
1653
1699
|
if dont_show_plots:
|
|
@@ -1666,11 +1712,13 @@ def plot_joint_y_by_average_SC(average_data, std_data, info, cfg):
|
|
|
1666
1712
|
plot_SE = cfg["plot_SE"]
|
|
1667
1713
|
sc_num = cfg["sc_num"]
|
|
1668
1714
|
hind_joints = cfg["hind_joints"]
|
|
1715
|
+
legend_outside = cfg["legend_outside"]
|
|
1716
|
+
color_palette = cfg["color_palette"]
|
|
1669
1717
|
|
|
1670
1718
|
# plot
|
|
1671
1719
|
f, ax = plt.subplots(1, 1)
|
|
1672
1720
|
ax.set_prop_cycle(
|
|
1673
|
-
plt.cycler("color",
|
|
1721
|
+
plt.cycler("color", sns.color_palette(color_palette, len(hind_joints)))
|
|
1674
1722
|
)
|
|
1675
1723
|
x = np.linspace(0, 100, bin_num)
|
|
1676
1724
|
for joint in hind_joints: # joint loop (lines)
|
|
@@ -1682,7 +1730,11 @@ def plot_joint_y_by_average_SC(average_data, std_data, info, cfg):
|
|
|
1682
1730
|
this_std = std_data.iloc[:, y_col_idx]
|
|
1683
1731
|
ax.plot(x, this_y, label=joint)
|
|
1684
1732
|
ax.fill_between(x, this_y - this_std, this_y + this_std, alpha=0.2)
|
|
1685
|
-
|
|
1733
|
+
# legend adjustments
|
|
1734
|
+
if legend_outside is True:
|
|
1735
|
+
ax.legend(loc="center left", bbox_to_anchor=(1, 0.5))
|
|
1736
|
+
elif legend_outside is False:
|
|
1737
|
+
ax.legend()
|
|
1686
1738
|
ax.set_title(name + " - Joint Y over average step cycle")
|
|
1687
1739
|
ax.set_xlabel("Percentage")
|
|
1688
1740
|
ax.set_ylabel("y (pixel)")
|
|
@@ -1705,11 +1757,13 @@ def plot_angles_by_average_SC(average_data, std_data, info, cfg):
|
|
|
1705
1757
|
plot_SE = cfg["plot_SE"]
|
|
1706
1758
|
sc_num = cfg["sc_num"]
|
|
1707
1759
|
angles = cfg["angles"]
|
|
1760
|
+
legend_outside = cfg["legend_outside"]
|
|
1761
|
+
color_palette = cfg["color_palette"]
|
|
1708
1762
|
|
|
1709
1763
|
# plot
|
|
1710
1764
|
f, ax = plt.subplots(1, 1)
|
|
1711
1765
|
ax.set_prop_cycle(
|
|
1712
|
-
plt.cycler("color",
|
|
1766
|
+
plt.cycler("color", sns.color_palette(color_palette, len(angles["name"])))
|
|
1713
1767
|
)
|
|
1714
1768
|
x = np.linspace(0, 100, bin_num)
|
|
1715
1769
|
ax.set_title(name + " - Joint angles over average step cycle")
|
|
@@ -1724,7 +1778,11 @@ def plot_angles_by_average_SC(average_data, std_data, info, cfg):
|
|
|
1724
1778
|
this_std = std_data.iloc[:, y_col_idx]
|
|
1725
1779
|
ax.plot(x, this_y, label=angle)
|
|
1726
1780
|
ax.fill_between(x, this_y - this_std, this_y + this_std, alpha=0.2)
|
|
1727
|
-
|
|
1781
|
+
# legend adjustments
|
|
1782
|
+
if legend_outside is True:
|
|
1783
|
+
ax.legend(loc="center left", bbox_to_anchor=(1, 0.5))
|
|
1784
|
+
elif legend_outside is False:
|
|
1785
|
+
ax.legend()
|
|
1728
1786
|
figure_file_string = " - Joint angles over average step cycle"
|
|
1729
1787
|
save_figures(f, results_dir, name, figure_file_string)
|
|
1730
1788
|
if dont_show_plots:
|
|
@@ -1744,11 +1802,13 @@ def plot_x_velocities_by_average_SC(average_data, std_data, info, cfg):
|
|
|
1744
1802
|
plot_SE = cfg["plot_SE"]
|
|
1745
1803
|
sc_num = cfg["sc_num"]
|
|
1746
1804
|
hind_joints = cfg["hind_joints"]
|
|
1805
|
+
legend_outside = cfg["legend_outside"]
|
|
1806
|
+
color_palette = cfg["color_palette"]
|
|
1747
1807
|
|
|
1748
1808
|
# plot
|
|
1749
1809
|
f, ax = plt.subplots(1, 1)
|
|
1750
1810
|
ax.set_prop_cycle(
|
|
1751
|
-
plt.cycler("color",
|
|
1811
|
+
plt.cycler("color", sns.color_palette(color_palette, len(hind_joints)))
|
|
1752
1812
|
)
|
|
1753
1813
|
x = np.linspace(0, 100, bin_num)
|
|
1754
1814
|
ax.set_title(name + " - Joint velocities over average step cycle")
|
|
@@ -1761,7 +1821,11 @@ def plot_x_velocities_by_average_SC(average_data, std_data, info, cfg):
|
|
|
1761
1821
|
this_std = std_data.iloc[:, y_col_idx]
|
|
1762
1822
|
ax.plot(x, this_y, label=joint)
|
|
1763
1823
|
ax.fill_between(x, this_y - this_std, this_y + this_std, alpha=0.2)
|
|
1764
|
-
|
|
1824
|
+
# legend adjustments
|
|
1825
|
+
if legend_outside is True:
|
|
1826
|
+
ax.legend(loc="center left", bbox_to_anchor=(1, 0.5))
|
|
1827
|
+
elif legend_outside is False:
|
|
1828
|
+
ax.legend()
|
|
1765
1829
|
ax.set_xlabel("Percentage")
|
|
1766
1830
|
ax.set_ylabel(
|
|
1767
1831
|
"Velocity (x in pixel / " + str(int((1 / sampling_rate) * 1000)) + "ms)"
|
|
@@ -1789,11 +1853,13 @@ def plot_angular_velocities_by_average_SC(average_data, std_data, info, cfg):
|
|
|
1789
1853
|
plot_SE = cfg["plot_SE"]
|
|
1790
1854
|
sc_num = cfg["sc_num"]
|
|
1791
1855
|
angles = cfg["angles"]
|
|
1856
|
+
legend_outside = cfg["legend_outside"]
|
|
1857
|
+
color_palette = cfg["color_palette"]
|
|
1792
1858
|
|
|
1793
1859
|
# plot
|
|
1794
1860
|
f, ax = plt.subplots(1, 1)
|
|
1795
1861
|
ax.set_prop_cycle(
|
|
1796
|
-
plt.cycler("color",
|
|
1862
|
+
plt.cycler("color", sns.color_palette(color_palette, len(angles["name"])))
|
|
1797
1863
|
)
|
|
1798
1864
|
x = np.linspace(0, 100, bin_num)
|
|
1799
1865
|
ax.set_title(name + " - Angular velocities over average step cycle")
|
|
@@ -1808,7 +1874,11 @@ def plot_angular_velocities_by_average_SC(average_data, std_data, info, cfg):
|
|
|
1808
1874
|
this_std = std_data.iloc[:, y_col_idx]
|
|
1809
1875
|
ax.plot(x, this_y, label=angle)
|
|
1810
1876
|
ax.fill_between(x, this_y - this_std, this_y + this_std, alpha=0.2)
|
|
1811
|
-
|
|
1877
|
+
# legend adjustments
|
|
1878
|
+
if legend_outside is True:
|
|
1879
|
+
ax.legend(loc="center left", bbox_to_anchor=(1, 0.5))
|
|
1880
|
+
elif legend_outside is False:
|
|
1881
|
+
ax.legend()
|
|
1812
1882
|
figure_file_string = " - Angular velocities over average step cycle"
|
|
1813
1883
|
save_figures(f, results_dir, name, figure_file_string)
|
|
1814
1884
|
if dont_show_plots:
|
|
@@ -1828,11 +1898,13 @@ def plot_x_acceleration_by_average_SC(average_data, std_data, info, cfg):
|
|
|
1828
1898
|
plot_SE = cfg["plot_SE"]
|
|
1829
1899
|
sc_num = cfg["sc_num"]
|
|
1830
1900
|
hind_joints = cfg["hind_joints"]
|
|
1901
|
+
legend_outside = cfg["legend_outside"]
|
|
1902
|
+
color_palette = cfg["color_palette"]
|
|
1831
1903
|
|
|
1832
1904
|
# plot
|
|
1833
1905
|
f, ax = plt.subplots(1, 1)
|
|
1834
1906
|
ax.set_prop_cycle(
|
|
1835
|
-
plt.cycler("color",
|
|
1907
|
+
plt.cycler("color", sns.color_palette(color_palette, len(hind_joints)))
|
|
1836
1908
|
)
|
|
1837
1909
|
x = np.linspace(0, 100, bin_num)
|
|
1838
1910
|
ax.set_title(name + " - Joint accelerations over average step cycle")
|
|
@@ -1845,7 +1917,11 @@ def plot_x_acceleration_by_average_SC(average_data, std_data, info, cfg):
|
|
|
1845
1917
|
this_std = std_data.iloc[:, y_col_idx]
|
|
1846
1918
|
ax.plot(x, this_y, label=joint)
|
|
1847
1919
|
ax.fill_between(x, this_y - this_std, this_y + this_std, alpha=0.2)
|
|
1848
|
-
|
|
1920
|
+
# legend adjustments
|
|
1921
|
+
if legend_outside is True:
|
|
1922
|
+
ax.legend(loc="center left", bbox_to_anchor=(1, 0.5))
|
|
1923
|
+
elif legend_outside is False:
|
|
1924
|
+
ax.legend()
|
|
1849
1925
|
ax.set_xlabel("Percentage")
|
|
1850
1926
|
ax.set_ylabel(
|
|
1851
1927
|
"Acceleration (x in pixel / " + str(int((1 / sampling_rate) * 1000)) + "ms)"
|
|
@@ -1875,11 +1951,13 @@ def plot_angular_acceleration_by_average_SC(average_data, std_data, info, cfg):
|
|
|
1875
1951
|
plot_SE = cfg["plot_SE"]
|
|
1876
1952
|
sc_num = cfg["sc_num"]
|
|
1877
1953
|
angles = cfg["angles"]
|
|
1954
|
+
legend_outside = cfg["legend_outside"]
|
|
1955
|
+
color_palette = cfg["color_palette"]
|
|
1878
1956
|
|
|
1879
1957
|
# plot
|
|
1880
1958
|
f, ax = plt.subplots(1, 1)
|
|
1881
1959
|
ax.set_prop_cycle(
|
|
1882
|
-
plt.cycler("color",
|
|
1960
|
+
plt.cycler("color", sns.color_palette(color_palette, len(angles["name"])))
|
|
1883
1961
|
)
|
|
1884
1962
|
x = np.linspace(0, 100, bin_num)
|
|
1885
1963
|
ax.set_title(name + " - Angular accelerations over average step cycle")
|
|
@@ -1896,7 +1974,11 @@ def plot_angular_acceleration_by_average_SC(average_data, std_data, info, cfg):
|
|
|
1896
1974
|
this_std = std_data.iloc[:, y_col_idx]
|
|
1897
1975
|
ax.plot(x, this_y, label=angle)
|
|
1898
1976
|
ax.fill_between(x, this_y - this_std, this_y + this_std, alpha=0.2)
|
|
1899
|
-
|
|
1977
|
+
# legend adjustments
|
|
1978
|
+
if legend_outside is True:
|
|
1979
|
+
ax.legend(loc="center left", bbox_to_anchor=(1, 0.5))
|
|
1980
|
+
elif legend_outside is False:
|
|
1981
|
+
ax.legend()
|
|
1900
1982
|
figure_file_string = " - Angular acceleration over average step cycle"
|
|
1901
1983
|
save_figures(f, results_dir, name, figure_file_string)
|
|
1902
1984
|
if dont_show_plots:
|
|
@@ -1937,6 +2019,30 @@ def tickconvert_mm_to_cm(axis, whichlabel):
|
|
|
1937
2019
|
axis.set_ylabel("y (cm)")
|
|
1938
2020
|
|
|
1939
2021
|
|
|
2022
|
+
def generate_sc_latency_label(all_steps_data, this_sc_idx, sampling_rate, time_col_idx):
|
|
2023
|
+
if sampling_rate <= 100:
|
|
2024
|
+
float_precision = 2 # how many decimals we round to
|
|
2025
|
+
else:
|
|
2026
|
+
float_precision = 4
|
|
2027
|
+
this_label = (
|
|
2028
|
+
str(
|
|
2029
|
+
round(
|
|
2030
|
+
all_steps_data.iloc[this_sc_idx[0], time_col_idx],
|
|
2031
|
+
float_precision,
|
|
2032
|
+
)
|
|
2033
|
+
)
|
|
2034
|
+
+ "-"
|
|
2035
|
+
+ str(
|
|
2036
|
+
round(
|
|
2037
|
+
all_steps_data.iloc[this_sc_idx[-1], time_col_idx],
|
|
2038
|
+
float_precision,
|
|
2039
|
+
)
|
|
2040
|
+
)
|
|
2041
|
+
+ "s"
|
|
2042
|
+
)
|
|
2043
|
+
return this_label
|
|
2044
|
+
|
|
2045
|
+
|
|
1940
2046
|
# %% local functions 5 - print finish
|
|
1941
2047
|
|
|
1942
2048
|
|