autogaita 0.0.6__tar.gz → 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. autogaita-0.1.0/PKG-INFO +23 -0
  2. {autogaita-0.0.6 → autogaita-0.1.0}/README.md +7 -2
  3. {autogaita-0.0.6 → autogaita-0.1.0}/autogaita/autogaita.py +0 -1
  4. {autogaita-0.0.6 → autogaita-0.1.0}/autogaita/autogaita_dlc.py +63 -66
  5. {autogaita-0.0.6 → autogaita-0.1.0}/autogaita/autogaita_dlc_gui.py +213 -92
  6. {autogaita-0.0.6 → autogaita-0.1.0}/autogaita/autogaita_group.py +39 -61
  7. {autogaita-0.0.6 → autogaita-0.1.0}/autogaita/autogaita_group_gui.py +202 -52
  8. {autogaita-0.0.6 → autogaita-0.1.0}/autogaita/autogaita_simi.py +52 -34
  9. {autogaita-0.0.6 → autogaita-0.1.0}/autogaita/autogaita_simi_gui.py +218 -61
  10. autogaita-0.1.0/autogaita/batchrun_scripts/autogaita_dlc_multirun.py +123 -0
  11. autogaita-0.1.0/autogaita/batchrun_scripts/autogaita_dlc_singlerun.py +75 -0
  12. {autogaita-0.0.6 → autogaita-0.1.0}/autogaita/batchrun_scripts/autogaita_group_dlcrun.py +21 -18
  13. {autogaita-0.0.6 → autogaita-0.1.0}/autogaita/batchrun_scripts/autogaita_group_simirun.py +32 -30
  14. autogaita-0.1.0/autogaita/batchrun_scripts/autogaita_simi_multirun.py +95 -0
  15. autogaita-0.1.0/autogaita/batchrun_scripts/autogaita_simi_singlerun.py +49 -0
  16. autogaita-0.1.0/autogaita.egg-info/PKG-INFO +23 -0
  17. {autogaita-0.0.6 → autogaita-0.1.0}/autogaita.egg-info/SOURCES.txt +6 -1
  18. {autogaita-0.0.6 → autogaita-0.1.0}/autogaita.egg-info/requires.txt +1 -0
  19. {autogaita-0.0.6 → autogaita-0.1.0}/setup.py +2 -2
  20. autogaita-0.1.0/tests/test_dlc_approval.py +137 -0
  21. autogaita-0.1.0/tests/test_dlc_unit2_sc_extraction.py +250 -0
  22. autogaita-0.1.0/tests/test_dlc_unit3_main_analysis.py +219 -0
  23. autogaita-0.1.0/tests/test_group_approval.py +122 -0
  24. autogaita-0.1.0/tests/test_simi_approval.py +99 -0
  25. autogaita-0.0.6/PKG-INFO +0 -10
  26. autogaita-0.0.6/autogaita/batchrun_scripts/autogaita_dlc_multirun.py +0 -172
  27. autogaita-0.0.6/autogaita/batchrun_scripts/autogaita_dlc_singlerun.py +0 -119
  28. autogaita-0.0.6/autogaita/batchrun_scripts/autogaita_simi_multirun.py +0 -111
  29. autogaita-0.0.6/autogaita/batchrun_scripts/autogaita_simi_singlerun.py +0 -75
  30. autogaita-0.0.6/autogaita.egg-info/PKG-INFO +0 -10
  31. {autogaita-0.0.6 → autogaita-0.1.0}/LICENSE +0 -0
  32. {autogaita-0.0.6 → autogaita-0.1.0}/autogaita/__init__.py +0 -0
  33. {autogaita-0.0.6 → autogaita-0.1.0}/autogaita/__main__.py +0 -0
  34. {autogaita-0.0.6 → autogaita-0.1.0}/autogaita/autogaita_icon.icns +0 -0
  35. {autogaita-0.0.6 → autogaita-0.1.0}/autogaita/autogaita_icon.ico +0 -0
  36. {autogaita-0.0.6 → autogaita-0.1.0}/autogaita/autogaita_logo.png +0 -0
  37. {autogaita-0.0.6 → autogaita-0.1.0}/autogaita/autogaita_utils.py +0 -0
  38. {autogaita-0.0.6 → autogaita-0.1.0}/autogaita/batchrun_scripts/__init__.py +0 -0
  39. {autogaita-0.0.6 → autogaita-0.1.0}/autogaita.egg-info/dependency_links.txt +0 -0
  40. {autogaita-0.0.6 → autogaita-0.1.0}/autogaita.egg-info/top_level.txt +0 -0
  41. {autogaita-0.0.6 → autogaita-0.1.0}/setup.cfg +0 -0
@@ -0,0 +1,23 @@
1
+ Metadata-Version: 2.1
2
+ Name: autogaita
3
+ Version: 0.1.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
+ License-File: LICENSE
10
+ Requires-Dist: customtkinter>=5.2
11
+ Requires-Dist: pandas>=2.0
12
+ Requires-Dist: numpy>=1.24
13
+ Requires-Dist: matplotlib>=3.7
14
+ Requires-Dist: scikit-learn>=1.2
15
+ Requires-Dist: pingouin>=0.5
16
+ Requires-Dist: scipy>=1.11
17
+ Requires-Dist: ffmpeg-python>=0.2
18
+ Requires-Dist: openpyxl>=3.1
19
+ Requires-Dist: pillow>=10.3
20
+ Requires-Dist: pyobjc
21
+ Provides-Extra: dev
22
+ Requires-Dist: pytest; extra == "dev"
23
+ Requires-Dist: hypothesis; extra == "dev"
@@ -1,8 +1,11 @@
1
1
  ![AutoGaitA](https://github.com/mahan-hosseini/AutoGaitA/blob/main/res/autogaita_logo.png?raw=true)
2
- [![PyPI version](https://badge.fury.io/py/autogaita.svg)](https://badge.fury.io/py/autogaita)
2
+ ![Repository Active](https://www.repostatus.org/badges/latest/active.svg)
3
3
  [![Test AutoGaitA](https://github.com/mahan-hosseini/AutoGaitA/actions/workflows/auto_test_gaita.yml/badge.svg)](https://github.com/mahan-hosseini/AutoGaitA/actions/workflows/auto_test_gaita.yml)
4
4
  ![Python](https://img.shields.io/badge/python-v3.10+-blue.svg)
5
- ![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)
5
+ [![PyPI - Version](https://img.shields.io/pypi/v/autogaita)](https://pypi.org/project/autogaita/)
6
+ ![license: GPL v3](https://img.shields.io/badge/license-GPLv3-blue.svg)
7
+ [![paper: biorxiv](https://img.shields.io/badge/paper-biorxiv-blue)](https://doi.org/10.1101/2024.04.14.589409)
8
+
6
9
  ![Black](https://img.shields.io/badge/code%20style-black-000000.svg)
7
10
  # Automated Gait Analysis in Python 🐸
8
11
 
@@ -34,6 +37,8 @@ It is strongly recommended that a separate virtual environment for AutoGaitA is
34
37
 
35
38
  **[The AutoGaitA YouTube Channel](https://youtube.com/playlist?list=PLCn5T7K_H8K56NIcEsfDK664OP7cN_Bad&si=mV5p2--nYvbofkPh) provides tutorials for file preparation and instructions on how to use AutoGaitA**
36
39
 
40
+ *Please note that tutorial videos might not always reflect the most up-to-date version of our toolbox, especially in the beginning when things are regularly changing. We will make sure to record new videos whenever there are major changes, though.*
41
+
37
42
  ### Example Data
38
43
  We provide an example dataset in the **example data** folder of this repository, with a set of mice walking over differently wide beams and both the beam as well as body coordinates being tracked with DLC. Note that this dataset was used in our tutorial videos introducing *AutoGaitA_DLC*, *AutoGaitA_Group* and in our video explaining file preparation for *AutoGaitA_DLC*. We further provide a **group** folder there that can be used alongside the *AutoGaitA_Group* tutorial to confirm that users generate the same set of results following our instructions.
39
44
 
@@ -6,7 +6,6 @@ from PIL import Image, ImageTk
6
6
  from importlib import resources
7
7
  import platform
8
8
 
9
-
10
9
  # %% global constants
11
10
  TXT_COLOR = "#ffffff" # white
12
11
  FONT_SIZE = 20
@@ -60,7 +60,7 @@ def dlc(info, folderinfo, cfg):
60
60
 
61
61
  # ......................... step-cycle extraction ................................
62
62
  all_cycles = extract_stepcycles(data, info, folderinfo, cfg)
63
- if all_cycles == None:
63
+ if not all_cycles:
64
64
  handle_issues("scs_invalid", info)
65
65
  return
66
66
 
@@ -71,7 +71,7 @@ def dlc(info, folderinfo, cfg):
71
71
  plot_results(info, results, folderinfo, cfg)
72
72
 
73
73
  # ............................ print finish ......................................
74
- print_finish(cfg)
74
+ print_finish(info, cfg)
75
75
 
76
76
 
77
77
  # %% local functions 1 - preparation
@@ -225,6 +225,7 @@ def some_prep(info, folderinfo, cfg):
225
225
  beam_hind_jointadd = cfg["beam_hind_jointadd"]
226
226
  beam_fore_jointadd = cfg["beam_fore_jointadd"]
227
227
  direction_joint = cfg["direction_joint"]
228
+ export_average_x = cfg["export_average_x"]
228
229
  # store config json file @ group path
229
230
  # !!! NU - do this @ mouse path!
230
231
  group_path = results_dir.split(name)[0]
@@ -233,6 +234,7 @@ def some_prep(info, folderinfo, cfg):
233
234
  "sampling_rate": sampling_rate,
234
235
  "convert_to_mm": convert_to_mm,
235
236
  "normalise_height_at_SC_level": normalise_height_at_SC_level,
237
+ "export_average_x": export_average_x,
236
238
  "hind_joints": hind_joints,
237
239
  "fore_joints": fore_joints,
238
240
  "angles": angles,
@@ -727,8 +729,7 @@ def extract_stepcycles(data, info, folderinfo, cfg):
727
729
  next_mouse_idx = mouse_row # search idx of first row of next mouse
728
730
 
729
731
  # .............................. main xls read ...................................
730
- # if while is False, we arrived at the next mouse/end & dont update
731
- # next_mouse_idx
732
+ # if while is False, we arrived at the next mouse/end & dont update next_mouse_idx
732
733
  # 3 conditions (continue if true):
733
734
  # 1) First row of this mouse
734
735
  # 2) None means a different run of this mouse or an empty row
@@ -950,7 +951,7 @@ def handle_issues(condition, info):
950
951
  elif condition == "no_scs":
951
952
  this_message = (
952
953
  "\n***********\n! WARNING !\n***********\n"
953
- + "Skipped since no SCs in latency XLS!"
954
+ + "Skipped since no SCs in Annotation Table!"
954
955
  )
955
956
  print(this_message)
956
957
  write_issues_to_textfile(this_message, info)
@@ -958,7 +959,7 @@ def handle_issues(condition, info):
958
959
  elif condition == "no_mouse":
959
960
  this_message = (
960
961
  "\n***********\n! WARNING !\n***********\n"
961
- + "Skipped since ID not in latency XLS!"
962
+ + "Skipped since ID not in Annotation Table!"
962
963
  )
963
964
  print(this_message)
964
965
  write_issues_to_textfile(this_message, info)
@@ -967,7 +968,7 @@ def handle_issues(condition, info):
967
968
  this_message = (
968
969
  "\n******************\n! CRITICAL ERROR !"
969
970
  + "\n******************\n"
970
- + "Latency XLS Column names are wrong!\n"
971
+ + "Annotation Table's Column Names are wrong!\n"
971
972
  + "Check Instructions!"
972
973
  )
973
974
  print(this_message)
@@ -977,7 +978,7 @@ def handle_issues(condition, info):
977
978
  this_message = (
978
979
  "\n***********\n! WARNING !\n***********\n"
979
980
  + "Skipped since ID found more than once in "
980
- + "latency XLS!"
981
+ + "Annotation Table!"
981
982
  )
982
983
  print(this_message)
983
984
  write_issues_to_textfile(this_message, info)
@@ -1007,6 +1008,7 @@ def analyse_and_export_stepcycles(data, all_cycles, info, folderinfo, cfg):
1007
1008
  name = info["name"]
1008
1009
  results_dir = info["results_dir"]
1009
1010
  save_to_xls = cfg["save_to_xls"]
1011
+ export_average_x = cfg["export_average_x"]
1010
1012
  bin_num = cfg["bin_num"]
1011
1013
  # do everything on a copy of the data df
1012
1014
  data_copy = data.copy()
@@ -1052,7 +1054,7 @@ def analyse_and_export_stepcycles(data, all_cycles, info, folderinfo, cfg):
1052
1054
  )
1053
1055
  # compute average & std data
1054
1056
  average_data, std_data = compute_average_and_std_data(
1055
- name, normalised_steps_data, bin_num, results_dir
1057
+ name, normalised_steps_data, bin_num, export_average_x
1056
1058
  )
1057
1059
  # save to results dict
1058
1060
  results = {}
@@ -1062,15 +1064,23 @@ def analyse_and_export_stepcycles(data, all_cycles, info, folderinfo, cfg):
1062
1064
  results["all_cycles"] = all_cycles
1063
1065
  # save to files
1064
1066
  save_results_sheet(
1065
- all_steps_data, save_to_xls, results_dir + name + ORIGINAL_XLS_FILENAME
1067
+ all_steps_data,
1068
+ save_to_xls,
1069
+ os.path.join(results_dir, name + ORIGINAL_XLS_FILENAME),
1066
1070
  )
1067
1071
  save_results_sheet(
1068
- normalised_steps_data, save_to_xls, results_dir + name + NORMALISED_XLS_FILENAME
1072
+ normalised_steps_data,
1073
+ save_to_xls,
1074
+ os.path.join(results_dir, name + NORMALISED_XLS_FILENAME),
1069
1075
  )
1070
1076
  save_results_sheet(
1071
- average_data, save_to_xls, results_dir + name + AVERAGE_XLS_FILENAME
1077
+ average_data,
1078
+ save_to_xls,
1079
+ os.path.join(results_dir, name + AVERAGE_XLS_FILENAME),
1080
+ )
1081
+ save_results_sheet(
1082
+ std_data, save_to_xls, os.path.join(results_dir, name + STD_XLS_FILENAME)
1072
1083
  )
1073
- save_results_sheet(std_data, save_to_xls, results_dir + name + STD_XLS_FILENAME)
1074
1084
  return results
1075
1085
 
1076
1086
 
@@ -1253,7 +1263,9 @@ def define_bins(triallength, bin_num):
1253
1263
  # ......................................................................................
1254
1264
 
1255
1265
 
1256
- def compute_average_and_std_data(name, normalised_steps_data, bin_num, results_dir):
1266
+ def compute_average_and_std_data(
1267
+ name, normalised_steps_data, bin_num, export_average_x
1268
+ ):
1257
1269
  """Export XLS tables that store all averages & std of y-coords & angles"""
1258
1270
  # initialise col of % of SC over time for plotting first
1259
1271
  percentages = [int(((s + 1) / bin_num) * 100) for s in range(bin_num)]
@@ -1265,12 +1277,20 @@ def compute_average_and_std_data(name, normalised_steps_data, bin_num, results_d
1265
1277
  )
1266
1278
  sc_num = len(np.where(normalised_steps_data.index == 0)[0])
1267
1279
  for c, col in enumerate(normalised_steps_data.columns):
1268
- if (
1269
- (not col.endswith("x"))
1270
- & (not col.endswith("likelihood"))
1271
- & (col != TIME_COL)
1272
- & (col != "Flipped")
1273
- ):
1280
+ if export_average_x:
1281
+ condition = (
1282
+ (not col.endswith("likelihood"))
1283
+ & (col != TIME_COL)
1284
+ & (col != "Flipped")
1285
+ )
1286
+ else:
1287
+ condition = (
1288
+ (not col.endswith("x"))
1289
+ & (not col.endswith("likelihood"))
1290
+ & (col != TIME_COL)
1291
+ & (col != "Flipped")
1292
+ )
1293
+ if condition:
1274
1294
  this_data = np.zeros([bin_num, sc_num])
1275
1295
  for s in range(sc_num):
1276
1296
  # with this_end it's bin_num & not bin_num -1 because iloc
@@ -1298,22 +1318,6 @@ def save_results_sheet(dataframe, save_to_xls, fullfilepath):
1298
1318
  # ......................................................................................
1299
1319
 
1300
1320
 
1301
- def delete_previous_xlsfiles(name, results_dir):
1302
- """
1303
- Check and delete previously stored excel files (important since appending sheets)
1304
- """
1305
- all_filenames = [
1306
- ORIGINAL_XLS_FILENAME,
1307
- NORMALISED_XLS_FILENAME,
1308
- AVERAGE_XLS_FILENAME,
1309
- STD_XLS_FILENAME,
1310
- ]
1311
- for filename in all_filenames:
1312
- fullfilepath = results_dir + name + filename + ".xlsx"
1313
- if os.path.exists(fullfilepath):
1314
- os.remove(fullfilepath)
1315
-
1316
-
1317
1321
  def add_step_separators(dataframe, nanvector, numvector):
1318
1322
  """Add nan & num vector separators between step cycles to dataframes"""
1319
1323
  dataframe = pd.concat([dataframe, nanvector], axis=0) # nan
@@ -1487,10 +1491,7 @@ def plot_joint_y_by_x(all_steps_data, sc_idxs, info, cfg):
1487
1491
  figure_file_string = " - Foot y by x coordinates"
1488
1492
  else:
1489
1493
  figure_file_string = " - " + joint + "y by x coordinates"
1490
- f[j].savefig(
1491
- results_dir + name + figure_file_string + ".png", bbox_inches="tight"
1492
- )
1493
- save_as_svg(f[j], results_dir, name, figure_file_string)
1494
+ save_figures(f[j], results_dir, name, figure_file_string)
1494
1495
  if dont_show_plots:
1495
1496
  plt.close(f[j])
1496
1497
 
@@ -1524,11 +1525,8 @@ def plot_angles_by_time(all_steps_data, sc_idxs, info, cfg):
1524
1525
  this_x = all_steps_data.iloc[sc_idxs[s], x_col_idx]
1525
1526
  this_y = all_steps_data.iloc[sc_idxs[s], y_col_idx]
1526
1527
  ax[a].plot(this_x, this_y)
1527
- figure_file_string = " - " + angle + " Angle by Time"
1528
- f[a].savefig(
1529
- results_dir + name + figure_file_string + ".png", bbox_inches="tight"
1530
- )
1531
- save_as_svg(f[a], results_dir, name, figure_file_string)
1528
+ figure_file_string = " - " + angle + "Angle by Time"
1529
+ save_figures(f[a], results_dir, name, figure_file_string)
1532
1530
  if dont_show_plots:
1533
1531
  plt.close(f[a])
1534
1532
 
@@ -1590,8 +1588,7 @@ def plot_hindlimb_stickdiagram(all_steps_data, sc_idxs, info, cfg):
1590
1588
  tickconvert_mm_to_cm(ax, "both")
1591
1589
  ax.legend(fontsize=SC_LAT_LEGEND_FONTSIZE)
1592
1590
  figure_file_string = " - Hindlimb Stick Diagram"
1593
- f.savefig(results_dir + name + figure_file_string + ".png", bbox_inches="tight")
1594
- save_as_svg(f, results_dir, name, figure_file_string)
1591
+ save_figures(f, results_dir, name, figure_file_string)
1595
1592
  if dont_show_plots:
1596
1593
  plt.close(f)
1597
1594
 
@@ -1652,8 +1649,7 @@ def plot_forelimb_stickdiagram(all_steps_data, sc_idxs, info, cfg):
1652
1649
  tickconvert_mm_to_cm(ax, "both")
1653
1650
  ax.legend(fontsize=SC_LAT_LEGEND_FONTSIZE)
1654
1651
  figure_file_string = " - Forelimb Stick Diagram"
1655
- f.savefig(results_dir + name + figure_file_string + ".png", bbox_inches="tight")
1656
- save_as_svg(f, results_dir, name, figure_file_string)
1652
+ save_figures(f, results_dir, name, figure_file_string)
1657
1653
  if dont_show_plots:
1658
1654
  plt.close(f)
1659
1655
 
@@ -1693,8 +1689,7 @@ def plot_joint_y_by_average_SC(average_data, std_data, info, cfg):
1693
1689
  if convert_to_mm:
1694
1690
  tickconvert_mm_to_cm(ax, "y")
1695
1691
  figure_file_string = " - Joint y-coord.s over average step cycle"
1696
- f.savefig(results_dir + name + figure_file_string + ".png", bbox_inches="tight")
1697
- save_as_svg(f, results_dir, name, figure_file_string)
1692
+ save_figures(f, results_dir, name, figure_file_string)
1698
1693
  if dont_show_plots:
1699
1694
  plt.close(f)
1700
1695
 
@@ -1731,8 +1726,7 @@ def plot_angles_by_average_SC(average_data, std_data, info, cfg):
1731
1726
  ax.fill_between(x, this_y - this_std, this_y + this_std, alpha=0.2)
1732
1727
  ax.legend()
1733
1728
  figure_file_string = " - Joint angles over average step cycle"
1734
- f.savefig(results_dir + name + figure_file_string + ".png", bbox_inches="tight")
1735
- save_as_svg(f, results_dir, name, figure_file_string)
1729
+ save_figures(f, results_dir, name, figure_file_string)
1736
1730
  if dont_show_plots:
1737
1731
  plt.close(f)
1738
1732
 
@@ -1778,8 +1772,7 @@ def plot_x_velocities_by_average_SC(average_data, std_data, info, cfg):
1778
1772
  "Velocity (x in cm / " + str(int((1 / sampling_rate) * 1000)) + "ms)"
1779
1773
  )
1780
1774
  figure_file_string = " - Joint velocities over average step cycle"
1781
- f.savefig(results_dir + name + figure_file_string + ".png", bbox_inches="tight")
1782
- save_as_svg(f, results_dir, name, figure_file_string)
1775
+ save_figures(f, results_dir, name, figure_file_string)
1783
1776
  if dont_show_plots:
1784
1777
  plt.close(f)
1785
1778
 
@@ -1817,8 +1810,7 @@ def plot_angular_velocities_by_average_SC(average_data, std_data, info, cfg):
1817
1810
  ax.fill_between(x, this_y - this_std, this_y + this_std, alpha=0.2)
1818
1811
  ax.legend()
1819
1812
  figure_file_string = " - Angular velocities over average step cycle"
1820
- f.savefig(results_dir + name + figure_file_string + ".png", bbox_inches="tight")
1821
- save_as_svg(f, results_dir, name, figure_file_string)
1813
+ save_figures(f, results_dir, name, figure_file_string)
1822
1814
  if dont_show_plots:
1823
1815
  plt.close(f)
1824
1816
 
@@ -1864,8 +1856,7 @@ def plot_x_acceleration_by_average_SC(average_data, std_data, info, cfg):
1864
1856
  "Acceleration (x in cm / " + str(int((1 / sampling_rate) * 1000)) + "ms)"
1865
1857
  )
1866
1858
  figure_file_string = " - Joint acceleration over average step cycle"
1867
- f.savefig(results_dir + name + figure_file_string + ".png", bbox_inches="tight")
1868
- save_as_svg(f, results_dir, name, figure_file_string)
1859
+ save_figures(f, results_dir, name, figure_file_string)
1869
1860
  if dont_show_plots:
1870
1861
  plt.close(f)
1871
1862
 
@@ -1907,19 +1898,24 @@ def plot_angular_acceleration_by_average_SC(average_data, std_data, info, cfg):
1907
1898
  ax.fill_between(x, this_y - this_std, this_y + this_std, alpha=0.2)
1908
1899
  ax.legend()
1909
1900
  figure_file_string = " - Angular acceleration over average step cycle"
1910
- f.savefig(results_dir + name + figure_file_string + ".png", bbox_inches="tight")
1911
- save_as_svg(f, results_dir, name, figure_file_string)
1901
+ save_figures(f, results_dir, name, figure_file_string)
1912
1902
  if dont_show_plots:
1913
1903
  plt.close(f)
1914
1904
 
1915
1905
 
1916
- def save_as_svg(figure, results_dir, name, figure_file_string):
1917
- """Save figures as svgs to separate subfolder"""
1906
+ def save_figures(figure, results_dir, name, figure_file_string):
1907
+ """Save figures as pngs to results_dir and as svgs to separate subfolders"""
1908
+ # pngs to results_dir
1909
+ figure.savefig(
1910
+ os.path.join(results_dir, name + figure_file_string + ".png"),
1911
+ bbox_inches="tight",
1912
+ )
1913
+ # svgs to subfolders
1918
1914
  svg_dir = os.path.join(results_dir, "SVG Figures")
1919
1915
  if not os.path.exists(svg_dir):
1920
1916
  os.makedirs(svg_dir)
1921
1917
  figure.savefig(
1922
- svg_dir + "/" + name + figure_file_string + ".svg", bbox_inches="tight"
1918
+ os.path.join(svg_dir, name + figure_file_string + ".svg"), bbox_inches="tight"
1923
1919
  )
1924
1920
 
1925
1921
 
@@ -1944,7 +1940,7 @@ def tickconvert_mm_to_cm(axis, whichlabel):
1944
1940
  # %% local functions 5 - print finish
1945
1941
 
1946
1942
 
1947
- def print_finish(cfg):
1943
+ def print_finish(info, cfg):
1948
1944
  """Print that we finished this program"""
1949
1945
  # unpack
1950
1946
  dont_show_plots = cfg["dont_show_plots"]
@@ -1953,7 +1949,8 @@ def print_finish(cfg):
1953
1949
  plt.pause(1) # so we ensure that plots are plotted to python before print
1954
1950
 
1955
1951
  print("\n***************************************************")
1956
- print("* GAITA FINISHED - RESULTS SAVED IN /Results DIR! *")
1952
+ print("* GAITA FINISHED - RESULTS WERE SAVED HERE: *")
1953
+ print("* " + info["results_dir"] + " *")
1957
1954
  print("***************************************************")
1958
1955
 
1959
1956