biomechzoo 0.4.1__tar.gz → 0.4.5__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.
Potentially problematic release.
This version of biomechzoo might be problematic. Click here for more details.
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/PKG-INFO +15 -2
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/README.md +13 -1
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/pyproject.toml +5 -4
- biomechzoo-0.4.5/src/__init__.py +33 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/biomechzoo.py +104 -62
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/conversion/csv2zoo_data.py +40 -20
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/processing/explodechannel_data.py +3 -2
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/processing/partition_data.py +7 -5
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/utils/engine.py +6 -1
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/utils/zsave.py +7 -3
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo.egg-info/PKG-INFO +15 -2
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo.egg-info/SOURCES.txt +1 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo.egg-info/requires.txt +1 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo.egg-info/top_level.txt +1 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/LICENSE +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/setup.cfg +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/__init__.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/__main__.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/biomech_ops/__init__.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/biomech_ops/continuous_relative_phase_data.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/biomech_ops/continuous_relative_phase_line.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/biomech_ops/filter_data.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/biomech_ops/filter_line.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/biomech_ops/normalize_data.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/biomech_ops/normalize_line.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/biomech_ops/phase_angle_data.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/biomech_ops/phase_angle_line.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/conversion/__init__.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/conversion/c3d2zoo_data.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/conversion/mvnx2zoo_data.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/conversion/opencap2zoo_data.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/mvn/__init__.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/mvn/load_mvnx.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/mvn/main_mvnx.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/mvn/mvn.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/mvn/mvnx_file_accessor.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/processing/__init__.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/processing/add_channel_data.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/processing/addchannel_data.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/processing/addevent_data.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/processing/removechannel_data.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/processing/renamechannel_data.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/processing/renameevent_data.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/processing/split_trial_by_gait_cycle.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/utils/__init__.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/utils/batchdisp.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/utils/compute_sampling_rate_from_time.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/utils/findfield.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/utils/get_split_events.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/utils/split_trial.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/utils/zload.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/utils/zplot.py +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo.egg-info/dependency_links.txt +0 -0
- {biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo.egg-info/entry_points.txt +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: biomechzoo
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.5
|
|
4
4
|
Summary: Python implementation of the biomechZoo toolbox
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/mcgillmotionlab/biomechzoo
|
|
7
|
-
Requires-Python:
|
|
7
|
+
Requires-Python: <3.12,>=3.11
|
|
8
8
|
Description-Content-Type: text/markdown
|
|
9
9
|
License-File: LICENSE
|
|
10
10
|
Requires-Dist: ezc3d>=1.5.19
|
|
@@ -12,6 +12,7 @@ Requires-Dist: matplotlib>=3.10.6
|
|
|
12
12
|
Requires-Dist: numpy==2.2.6
|
|
13
13
|
Requires-Dist: pandas>=2.3.2
|
|
14
14
|
Requires-Dist: scipy>=1.16.2
|
|
15
|
+
Requires-Dist: pyarrow>=19.0.0
|
|
15
16
|
Dynamic: license-file
|
|
16
17
|
|
|
17
18
|
# BiomechZoo for Python
|
|
@@ -30,3 +31,15 @@ This is a development version of the biomechzoo toolbox for python.
|
|
|
30
31
|
- We use Numpy 2.2.6 for compatibility with https://pypi.org/project/numba/
|
|
31
32
|
|
|
32
33
|
See also http://www.github.com/mcgillmotionlab/biomechzoo or http://www.biomechzoo.com for more information
|
|
34
|
+
|
|
35
|
+
## Developer notes
|
|
36
|
+
|
|
37
|
+
### Installing a dev environment
|
|
38
|
+
conda create -n biomechzoo-dev python=3.11
|
|
39
|
+
conda activate biomechzoo-dev
|
|
40
|
+
pip install -e ".[dev]"
|
|
41
|
+
|
|
42
|
+
### import issues
|
|
43
|
+
if using PyCharm:
|
|
44
|
+
- Right-click on src/.
|
|
45
|
+
- Select Mark Directory as → Sources Root.
|
|
@@ -13,4 +13,16 @@ This is a development version of the biomechzoo toolbox for python.
|
|
|
13
13
|
- We use Python 3.11 for compatibility with https://github.com/stanfordnmbl/opencap-processing
|
|
14
14
|
- We use Numpy 2.2.6 for compatibility with https://pypi.org/project/numba/
|
|
15
15
|
|
|
16
|
-
See also http://www.github.com/mcgillmotionlab/biomechzoo or http://www.biomechzoo.com for more information
|
|
16
|
+
See also http://www.github.com/mcgillmotionlab/biomechzoo or http://www.biomechzoo.com for more information
|
|
17
|
+
|
|
18
|
+
## Developer notes
|
|
19
|
+
|
|
20
|
+
### Installing a dev environment
|
|
21
|
+
conda create -n biomechzoo-dev python=3.11
|
|
22
|
+
conda activate biomechzoo-dev
|
|
23
|
+
pip install -e ".[dev]"
|
|
24
|
+
|
|
25
|
+
### import issues
|
|
26
|
+
if using PyCharm:
|
|
27
|
+
- Right-click on src/.
|
|
28
|
+
- Select Mark Directory as → Sources Root.
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "biomechzoo"
|
|
3
|
-
version = "0.4.
|
|
3
|
+
version = "0.4.5"
|
|
4
4
|
description = "Python implementation of the biomechZoo toolbox"
|
|
5
5
|
readme = "README.md"
|
|
6
|
-
requires-python = ">=3.11"
|
|
6
|
+
requires-python = ">=3.11,<3.12" # max version for opencap-process tools is 3.11
|
|
7
7
|
license = "MIT"
|
|
8
8
|
license-files = ["LICEN[CS]E*"]
|
|
9
9
|
dependencies = [
|
|
10
|
-
"ezc3d>=1.5.19",
|
|
10
|
+
"ezc3d>=1.5.19", # for reading c3d files
|
|
11
11
|
"matplotlib>=3.10.6",
|
|
12
|
-
"numpy==2.2.6",
|
|
12
|
+
"numpy==2.2.6", # max version for opencap-process tools
|
|
13
13
|
"pandas>=2.3.2",
|
|
14
14
|
"scipy>=1.16.2",
|
|
15
|
+
"pyarrow>=19.0.0", # for parquet support
|
|
15
16
|
]
|
|
16
17
|
|
|
17
18
|
[project.urls]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""
|
|
2
|
+
BiomechZoo: A Python toolbox for processing and analyzing human movement data.
|
|
3
|
+
|
|
4
|
+
This package provides functions for converting, processing, analyzing,
|
|
5
|
+
and visualizing biomechanical data (e.g., motion capture, EMG, kinetics).
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
from biomechzoo import BiomechZoo
|
|
9
|
+
from biomechzoo.conversion import c3d2zoo
|
|
10
|
+
|
|
11
|
+
zoo = BiomechZoo()
|
|
12
|
+
zoo.conversion.c3d2zoo('path/to/data')
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
# Import main class or entry point
|
|
16
|
+
from .biomechzo import BiomechZoo
|
|
17
|
+
|
|
18
|
+
# Import commonly used submodules
|
|
19
|
+
from . import conversion
|
|
20
|
+
from . import processing
|
|
21
|
+
from . import plotting
|
|
22
|
+
from . import utils
|
|
23
|
+
|
|
24
|
+
# Define what gets exposed with "from biomechzoo import *"
|
|
25
|
+
__all__ = [
|
|
26
|
+
"BiomechZoo",
|
|
27
|
+
"conversion",
|
|
28
|
+
"processing",
|
|
29
|
+
"plotting",
|
|
30
|
+
"utils",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
__version__ = "0.4.4"
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import inspect
|
|
3
|
+
import time
|
|
2
4
|
from biomechzoo.utils.engine import engine # assumes this returns .zoo files in folder
|
|
3
5
|
from biomechzoo.utils.zload import zload
|
|
4
6
|
from biomechzoo.utils.zsave import zsave
|
|
@@ -18,17 +20,28 @@ from biomechzoo.biomech_ops.normalize_data import normalize_data
|
|
|
18
20
|
from biomechzoo.biomech_ops.phase_angle_data import phase_angle_data
|
|
19
21
|
from biomechzoo.biomech_ops.continuous_relative_phase_data import continuous_relative_phase_data
|
|
20
22
|
|
|
21
|
-
|
|
22
23
|
class BiomechZoo:
|
|
23
|
-
def __init__(self, in_folder, inplace=False, verbose=0):
|
|
24
|
+
def __init__(self, in_folder, inplace=False, subfolders=None, name_contains=None, verbose=0):
|
|
24
25
|
self.verbose = verbose
|
|
25
26
|
self.in_folder = in_folder
|
|
26
27
|
self.verbose = verbose
|
|
27
|
-
self.inplace = inplace
|
|
28
|
+
self.inplace = inplace # choice to save processed files to new folder
|
|
29
|
+
self.subfolders = subfolders # only run processes on list in subfolder
|
|
30
|
+
self.name_contains = name_contains # only run processes on files with name_contains in file name
|
|
28
31
|
|
|
29
32
|
batchdisp('BiomechZoo initialized', level=1, verbose=verbose)
|
|
30
33
|
batchdisp('verbosity set to: {}'.format(verbose), level=1, verbose=verbose)
|
|
31
|
-
batchdisp('processing folder set to: {}'.format(self.in_folder), level=1, verbose=verbose)
|
|
34
|
+
batchdisp('root processing folder set to: {}'.format(self.in_folder), level=1, verbose=verbose)
|
|
35
|
+
if name_contains is not None:
|
|
36
|
+
batchdisp('only include files containing name_contains string: {}'.format(self.name_contains), level=1, verbose=verbose)
|
|
37
|
+
if subfolders is not None:
|
|
38
|
+
if type(subfolders) is list:
|
|
39
|
+
batchdisp('only process files in subfolder(s):', level=1, verbose=verbose)
|
|
40
|
+
for subfolder in self.subfolders:
|
|
41
|
+
batchdisp('{}'.format(os.path.join(self.in_folder, subfolder)), level=1, verbose=verbose)
|
|
42
|
+
else:
|
|
43
|
+
batchdisp('only process files in subfolder(s): {}'.format(os.path.join(self.in_folder, self.subfolders)), level=1, verbose=verbose)
|
|
44
|
+
|
|
32
45
|
if inplace:
|
|
33
46
|
batchdisp('Processing mode: overwrite (inplace=True) (each step will be applied to same folder)', level=1, verbose=verbose)
|
|
34
47
|
else:
|
|
@@ -50,57 +63,75 @@ class BiomechZoo:
|
|
|
50
63
|
|
|
51
64
|
def mvnx2zoo(self, out_folder=None, inplace=False):
|
|
52
65
|
""" Converts all .mvnx files in the folder to .zoo format """
|
|
66
|
+
start_time = time.time()
|
|
53
67
|
verbose = self.verbose
|
|
54
68
|
in_folder = self.in_folder
|
|
55
69
|
if inplace is None:
|
|
56
70
|
inplace = self.inplace
|
|
57
|
-
|
|
58
|
-
fl = engine(in_folder, extension='.mvnx')
|
|
71
|
+
fl = engine(in_folder, extension='.mvnx', name_contains=self.name_contains, subfolders=self.subfolders)
|
|
59
72
|
for f in fl:
|
|
60
73
|
batchdisp('converting mvnx to zoo for {}'.format(f), level=2, verbose=verbose)
|
|
61
74
|
data = mvnx2zoo_data(f)
|
|
62
75
|
f_zoo = f.replace('.mvnx', '.zoo')
|
|
63
76
|
zsave(f_zoo, data, inplace=inplace, out_folder=out_folder, root_folder=in_folder)
|
|
64
|
-
|
|
65
|
-
|
|
77
|
+
method_name = inspect.currentframe().f_code.co_name
|
|
78
|
+
batchdisp('{} conversion complete for {} files'.format(method_name, len(fl)), level=1, verbose=verbose)
|
|
66
79
|
# Update self.folder after processing
|
|
67
80
|
self._update_folder(out_folder, inplace, in_folder)
|
|
68
81
|
|
|
69
82
|
def c3d2zoo(self, out_folder=None, inplace=None):
|
|
70
83
|
""" Converts all .c3d files in the folder to .zoo format """
|
|
84
|
+
start_time = time.time()
|
|
71
85
|
from ezc3d import c3d
|
|
72
86
|
verbose = self.verbose
|
|
73
87
|
in_folder = self.in_folder
|
|
74
88
|
if inplace is None:
|
|
75
89
|
inplace = self.inplace
|
|
76
|
-
|
|
77
|
-
fl = engine(in_folder, extension='.c3d')
|
|
90
|
+
fl = engine(in_folder, extension='.c3d', name_contains=self.name_contains, subfolders=self.subfolders)
|
|
78
91
|
for f in fl:
|
|
79
92
|
batchdisp('converting c3d to zoo for {}'.format(f), level=2, verbose=verbose)
|
|
80
93
|
c3d_obj = c3d(f)
|
|
81
94
|
data = c3d2zoo_data(c3d_obj)
|
|
82
95
|
f_zoo = f.replace('.c3d', '.zoo')
|
|
83
96
|
zsave(f_zoo, data, inplace=inplace, out_folder=out_folder, root_folder=in_folder)
|
|
84
|
-
|
|
85
|
-
|
|
97
|
+
method_name = inspect.currentframe().f_code.co_name
|
|
98
|
+
batchdisp('{} process complete for {} file(s) in {:.2f} secs'.format(method_name, len(fl), time.time() - start_time), level=1, verbose=verbose)
|
|
86
99
|
# Update self.folder after processing
|
|
87
100
|
self._update_folder(out_folder, inplace, in_folder)
|
|
88
101
|
|
|
89
|
-
def csv2zoo(self, out_folder=None, inplace=None):
|
|
102
|
+
def csv2zoo(self, out_folder=None, inplace=None, skip_rows=0):
|
|
90
103
|
""" Converts generic .csv file in the folder to .zoo format """
|
|
104
|
+
start_time = time.time()
|
|
91
105
|
verbose = self.verbose
|
|
92
106
|
in_folder = self.in_folder
|
|
93
107
|
if inplace is None:
|
|
94
108
|
inplace = self.inplace
|
|
95
|
-
|
|
96
|
-
fl = engine(in_folder, extension='.csv')
|
|
109
|
+
fl = engine(in_folder, extension='.csv', name_contains=self.name_contains, subfolders=self.subfolders)
|
|
97
110
|
for f in fl:
|
|
98
111
|
batchdisp('converting csv to zoo for {}'.format(f), level=2, verbose=verbose)
|
|
99
|
-
data = csv2zoo_data(f)
|
|
112
|
+
data = csv2zoo_data(f, type='csv', skip_rows=skip_rows)
|
|
100
113
|
f_zoo = f.replace('.csv', '.zoo')
|
|
101
114
|
zsave(f_zoo, data, inplace=inplace, out_folder=out_folder, root_folder=in_folder)
|
|
102
|
-
|
|
115
|
+
method_name = inspect.currentframe().f_code.co_name
|
|
116
|
+
batchdisp('{} process complete for {} file(s) in {:.2f} secs'.format(method_name, len(fl), time.time() - start_time), level=1, verbose=verbose)
|
|
117
|
+
# Update self.folder after processing
|
|
118
|
+
self._update_folder(out_folder, inplace, in_folder)
|
|
103
119
|
|
|
120
|
+
def parquet2zoo(self, out_folder=None, inplace=None):
|
|
121
|
+
""" Converts generic .csv file in the folder to .zoo format """
|
|
122
|
+
start_time = time.time()
|
|
123
|
+
verbose = self.verbose
|
|
124
|
+
in_folder = self.in_folder
|
|
125
|
+
if inplace is None:
|
|
126
|
+
inplace = self.inplace
|
|
127
|
+
fl = engine(in_folder, extension='.parquet', name_contains=self.name_contains, subfolders=self.subfolders)
|
|
128
|
+
for f in fl:
|
|
129
|
+
batchdisp('converting parquet to zoo for {}'.format(f), level=2, verbose=verbose)
|
|
130
|
+
data = csv2zoo_data(f, type='parquet')
|
|
131
|
+
f_zoo = f.replace('.parquet', '.zoo')
|
|
132
|
+
zsave(f_zoo, data, inplace=inplace, out_folder=out_folder, root_folder=in_folder)
|
|
133
|
+
method_name = inspect.currentframe().f_code.co_name
|
|
134
|
+
batchdisp('{} process complete for {} file(s) in {:.2f} secs'.format(method_name, len(fl), time.time() - start_time), level=1, verbose=verbose)
|
|
104
135
|
# Update self.folder after processing
|
|
105
136
|
self._update_folder(out_folder, inplace, in_folder)
|
|
106
137
|
|
|
@@ -110,67 +141,70 @@ class BiomechZoo:
|
|
|
110
141
|
|
|
111
142
|
def phase_angle(self, ch, out_folder=None, inplace=None):
|
|
112
143
|
""" computes phase angles"""
|
|
144
|
+
start_time = time.time()
|
|
113
145
|
verbose = self.verbose
|
|
114
146
|
in_folder = self.in_folder
|
|
115
147
|
if inplace is None:
|
|
116
148
|
inplace = self.inplace
|
|
117
|
-
|
|
118
|
-
fl = engine(in_folder)
|
|
149
|
+
fl = engine(in_folder, extension='.zoo', name_contains=self.name_contains, subfolders=self.subfolders)
|
|
119
150
|
for f in fl:
|
|
120
151
|
if verbose:
|
|
121
152
|
batchdisp('computing phase angles for {}'.format(f), level=2, verbose=verbose)
|
|
122
153
|
data = zload(f)
|
|
123
154
|
data = phase_angle_data(data, ch)
|
|
124
|
-
zsave(f, data, inplace=inplace,
|
|
125
|
-
|
|
155
|
+
zsave(f, data, inplace=inplace, out_folder=out_folder, root_folder=in_folder)
|
|
156
|
+
method_name = inspect.currentframe().f_code.co_name
|
|
157
|
+
batchdisp('{} process complete for {} file(s) in {:.2f} secs'.format(method_name, len(fl), time.time() - start_time), level=1, verbose=verbose)
|
|
126
158
|
|
|
127
159
|
# Update self.folder after processing
|
|
128
160
|
self._update_folder(out_folder, inplace, in_folder)
|
|
129
161
|
|
|
130
162
|
def continuous_relative_phase(self, ch_prox, ch_dist, out_folder=None, inplace=None):
|
|
131
163
|
""" computes CRP angles"""
|
|
164
|
+
start_time = time.time()
|
|
132
165
|
verbose = self.verbose
|
|
133
166
|
in_folder = self.in_folder
|
|
134
167
|
if inplace is None:
|
|
135
168
|
inplace = self.inplace
|
|
136
|
-
|
|
137
|
-
fl = engine(in_folder)
|
|
169
|
+
fl = engine(in_folder, extension='.zoo', name_contains=self.name_contains, subfolders=self.subfolders)
|
|
138
170
|
for f in fl:
|
|
139
171
|
if verbose:
|
|
140
172
|
batchdisp('computing CRP angles between channel {} (prox) and {} (dist) for {}'.format(ch_prox, ch_dist, f), level=2, verbose=verbose)
|
|
141
173
|
data = zload(f)
|
|
142
174
|
data = continuous_relative_phase_data(data, ch_dist, ch_prox)
|
|
143
|
-
zsave(f, data, inplace=inplace,
|
|
144
|
-
|
|
175
|
+
zsave(f, data, inplace=inplace, out_folder=out_folder, root_folder=in_folder)
|
|
176
|
+
method_name = inspect.currentframe().f_code.co_name
|
|
177
|
+
batchdisp('{} process complete for {} file(s) in {:.2f} secs'.format(method_name, len(fl), time.time() - start_time), level=1, verbose=verbose)
|
|
145
178
|
|
|
146
179
|
# Update self.folder after processing
|
|
147
180
|
self._update_folder(out_folder, inplace, in_folder)
|
|
148
181
|
|
|
149
182
|
def split_trial_by_gait_cycle(self, first_event_name, out_folder=None, inplace=None):
|
|
150
183
|
""" split by gait cycle according to event_name"""
|
|
184
|
+
start_time = time.time()
|
|
151
185
|
verbose = self.verbose
|
|
152
186
|
in_folder = self.in_folder
|
|
153
187
|
if inplace is None:
|
|
154
188
|
inplace = self.inplace
|
|
155
|
-
|
|
156
|
-
fl = engine(in_folder)
|
|
189
|
+
fl = engine(in_folder, extension='.zoo', name_contains=self.name_contains, subfolders=self.subfolders)
|
|
157
190
|
for f in fl:
|
|
158
191
|
f_name = os.path.splitext(os.path.basename(f))[0]
|
|
159
|
-
batchdisp('splitting by gait cycle for {} by {}'.format(f, first_event_name), level=2, verbose=verbose)
|
|
160
192
|
data = zload(f)
|
|
161
193
|
split_events = get_split_events(data, first_event_name)
|
|
162
194
|
if split_events is None:
|
|
163
195
|
print('no event {} found, saving original file'.format(first_event_name))
|
|
164
|
-
zsave(f, data, inplace=inplace,
|
|
196
|
+
zsave(f, data, inplace=inplace, out_folder=out_folder, root_folder=in_folder)
|
|
165
197
|
else:
|
|
166
198
|
for i, _ in enumerate(split_events[0:-1]):
|
|
167
199
|
fl_new = f.replace(f_name, f_name + '_' + str(i + 1))
|
|
168
200
|
start = split_events[i]
|
|
169
201
|
end = split_events[i + 1]
|
|
202
|
+
batchdisp('splitting by gait cycle from {} to {} for {}'.format(start, end, f), level=2,
|
|
203
|
+
verbose=verbose)
|
|
170
204
|
data_new = split_trial(data, start, end)
|
|
171
|
-
zsave(fl_new, data_new, inplace=inplace,
|
|
172
|
-
|
|
173
|
-
batchdisp('
|
|
205
|
+
zsave(fl_new, data_new, inplace=inplace, out_folder=out_folder, root_folder=in_folder)
|
|
206
|
+
method_name = inspect.currentframe().f_code.co_name
|
|
207
|
+
batchdisp('{} process complete for {} file(s) in {:.2f} secs'.format(method_name, len(fl), time.time() - start_time), level=1, verbose=verbose)
|
|
174
208
|
|
|
175
209
|
# Update self.folder after processing
|
|
176
210
|
self._update_folder(out_folder, inplace, in_folder)
|
|
@@ -195,130 +229,137 @@ class BiomechZoo:
|
|
|
195
229
|
# self._update_folder(out_folder, inplace, in_folder)
|
|
196
230
|
def renameevent(self, evt, nevt, out_folder=None, inplace=None):
|
|
197
231
|
""" renames event evt to nevt in all zoo files """
|
|
232
|
+
start_time = time.time()
|
|
198
233
|
verbose = self.verbose
|
|
199
234
|
in_folder = self.in_folder
|
|
200
235
|
if inplace is None:
|
|
201
236
|
inplace = self.inplace
|
|
202
|
-
|
|
203
|
-
fl = engine(in_folder)
|
|
237
|
+
fl = engine(in_folder, extension='.zoo', name_contains=self.name_contains, subfolders=self.subfolders)
|
|
204
238
|
for f in fl:
|
|
205
239
|
batchdisp('renaming events from {} to {} for {}'.format(evt, nevt ,f), level=2, verbose=verbose)
|
|
206
240
|
data = zload(f)
|
|
207
241
|
data = renameevent_data(data, evt, nevt)
|
|
208
|
-
zsave(f, data, inplace=inplace,
|
|
209
|
-
|
|
242
|
+
zsave(f, data, inplace=inplace, out_folder=out_folder, root_folder=in_folder)
|
|
243
|
+
method_name = inspect.currentframe().f_code.co_name
|
|
244
|
+
batchdisp('{} process complete for {} file(s) in {:.2f} secs'.format(method_name, len(fl), time.time() - start_time), level=1, verbose=verbose)
|
|
210
245
|
|
|
211
246
|
# Update self.folder after processing
|
|
212
247
|
self._update_folder(out_folder, inplace, in_folder)
|
|
213
248
|
|
|
214
249
|
def renamechannnel(self, ch, ch_new, out_folder=None, inplace=None):
|
|
215
250
|
""" renames channels from ch to ch_new in all zoo files """
|
|
251
|
+
start_time = time.time()
|
|
216
252
|
verbose = self.verbose
|
|
217
253
|
in_folder = self.in_folder
|
|
218
254
|
if inplace is None:
|
|
219
255
|
inplace = self.inplace
|
|
220
|
-
|
|
221
|
-
fl = engine(in_folder)
|
|
256
|
+
fl = engine(in_folder, extension='.zoo', name_contains=self.name_contains, subfolders=self.subfolders)
|
|
222
257
|
for f in fl:
|
|
223
258
|
batchdisp('renaming channels from {} to {} for {}'.format(ch, ch_new ,f), level=2, verbose=verbose)
|
|
224
259
|
data = zload(f)
|
|
225
260
|
data = renamechannel_data(data, ch, ch_new)
|
|
226
|
-
zsave(f, data, inplace=inplace,
|
|
227
|
-
|
|
261
|
+
zsave(f, data, inplace=inplace, out_folder=out_folder, root_folder=in_folder)
|
|
262
|
+
method_name = inspect.currentframe().f_code.co_name
|
|
263
|
+
batchdisp('{} process complete for {} file(s) in {:.2f} secs'.format(method_name, len(fl), time.time() - start_time), level=1, verbose=verbose)
|
|
228
264
|
|
|
229
265
|
# Update self.folder after processing
|
|
230
266
|
self._update_folder(out_folder, inplace, in_folder)
|
|
231
267
|
|
|
232
268
|
def removechannel(self, ch, mode='remove', out_folder=None, inplace=None):
|
|
233
269
|
""" removes channels from zoo files """
|
|
270
|
+
start_time = time.time()
|
|
234
271
|
verbose = self.verbose
|
|
235
272
|
in_folder = self.in_folder
|
|
236
273
|
if inplace is None:
|
|
237
274
|
inplace = self.inplace
|
|
238
|
-
|
|
239
|
-
fl = engine(in_folder)
|
|
275
|
+
fl = engine(in_folder, extension='.zoo', name_contains=self.name_contains, subfolders=self.subfolders)
|
|
240
276
|
for f in fl:
|
|
241
277
|
batchdisp('removing channels for {}'.format(f), level=2, verbose=verbose)
|
|
242
278
|
data = zload(f)
|
|
243
279
|
data = removechannel_data(data, ch, mode)
|
|
244
|
-
zsave(f, data, inplace=inplace,
|
|
245
|
-
|
|
280
|
+
zsave(f, data, inplace=inplace, out_folder=out_folder, root_folder=in_folder)
|
|
281
|
+
method_name = inspect.currentframe().f_code.co_name
|
|
282
|
+
batchdisp('{} process complete for {} file(s) in {:.2f} secs'.format(method_name, len(fl), time.time() - start_time), level=1, verbose=verbose)
|
|
246
283
|
|
|
247
284
|
# Update self.folder after processing
|
|
248
285
|
self._update_folder(out_folder, inplace, in_folder)
|
|
249
286
|
|
|
250
287
|
def explodechannel(self, out_folder=None, inplace=None):
|
|
251
288
|
""" explodes all channels in a zoo file """
|
|
289
|
+
start_time = time.time()
|
|
252
290
|
verbose = self.verbose
|
|
253
291
|
in_folder = self.in_folder
|
|
254
292
|
if inplace is None:
|
|
255
293
|
inplace = self.inplace
|
|
256
|
-
|
|
257
|
-
fl = engine(in_folder)
|
|
294
|
+
fl = engine(in_folder, extension='.zoo', name_contains=self.name_contains, subfolders=self.subfolders)
|
|
258
295
|
for f in fl:
|
|
259
296
|
if verbose:
|
|
260
297
|
batchdisp('removing channels for {}'.format(f), level=2, verbose=verbose)
|
|
261
298
|
data = zload(f)
|
|
262
299
|
data = explodechannel_data(data)
|
|
263
|
-
zsave(f, data, inplace=inplace,
|
|
264
|
-
|
|
300
|
+
zsave(f, data, inplace=inplace, out_folder=out_folder, root_folder=in_folder)
|
|
301
|
+
method_name = inspect.currentframe().f_code.co_name
|
|
302
|
+
batchdisp('{} process complete for {} file(s) in {:.2f} secs'.format(method_name, len(fl), time.time() - start_time), level=1, verbose=verbose)
|
|
265
303
|
|
|
266
304
|
# Update self.folder after processing
|
|
267
305
|
self._update_folder(out_folder, inplace, in_folder)
|
|
268
306
|
|
|
269
307
|
def normalize(self, nlen=101, out_folder=None, inplace=None):
|
|
270
308
|
""" time normalizes all channels to length nlen """
|
|
309
|
+
start_time = time.time()
|
|
271
310
|
verbose = self.verbose
|
|
272
311
|
in_folder = self.in_folder
|
|
273
312
|
if inplace is None:
|
|
274
313
|
inplace = self.inplace
|
|
275
|
-
|
|
276
|
-
fl = engine(in_folder)
|
|
314
|
+
fl = engine(in_folder, extension='.zoo', name_contains=self.name_contains, subfolders=self.subfolders)
|
|
277
315
|
for f in fl:
|
|
278
316
|
if verbose:
|
|
279
317
|
batchdisp('normalizing channels to length {} for {}'.format(nlen, f), level=2, verbose=verbose)
|
|
280
318
|
data = zload(f)
|
|
281
319
|
data = normalize_data(data, nlen)
|
|
282
|
-
zsave(f, data, inplace=inplace,
|
|
283
|
-
|
|
320
|
+
zsave(f, data, inplace=inplace, out_folder=out_folder, root_folder=in_folder)
|
|
321
|
+
method_name = inspect.currentframe().f_code.co_name
|
|
322
|
+
batchdisp('{} process complete for {} file(s) in {:.2f} secs'.format(method_name, len(fl), time.time() - start_time), level=1, verbose=verbose)
|
|
284
323
|
|
|
285
324
|
# Update self.folder after processing
|
|
286
325
|
self._update_folder(out_folder, inplace, in_folder)
|
|
287
326
|
|
|
288
327
|
def addevent(self, ch, evt_type, evt_name, out_folder=None, inplace=None):
|
|
289
328
|
""" adds events of type evt_type with name evt_name to channel ch """
|
|
329
|
+
start_time = time.time()
|
|
290
330
|
verbose = self.verbose
|
|
291
331
|
in_folder = self.in_folder
|
|
292
332
|
if inplace is None:
|
|
293
333
|
inplace = self.inplace
|
|
294
|
-
|
|
295
|
-
fl = engine(in_folder)
|
|
334
|
+
fl = engine(in_folder, extension='.zoo', name_contains=self.name_contains, subfolders=self.subfolders)
|
|
296
335
|
for f in fl:
|
|
297
336
|
if verbose:
|
|
298
337
|
batchdisp('adding event {} to channel {} for {}'.format(evt_type, ch, f), level=2, verbose=verbose)
|
|
299
338
|
data = zload(f)
|
|
300
339
|
data = addevent_data(data, ch, evt_type, evt_name)
|
|
301
|
-
zsave(f, data, inplace=inplace,
|
|
302
|
-
|
|
340
|
+
zsave(f, data, inplace=inplace, out_folder=out_folder, root_folder=in_folder)
|
|
341
|
+
method_name = inspect.currentframe().f_code.co_name
|
|
342
|
+
batchdisp('{} process complete for {} file(s) in {:.2f} secs'.format(method_name, len(fl), time.time() - start_time), level=1, verbose=verbose)
|
|
303
343
|
|
|
304
344
|
# Update self.folder after processing
|
|
305
345
|
self._update_folder(out_folder, inplace, in_folder)
|
|
306
346
|
|
|
307
347
|
def partition(self, evt_start, evt_end, out_folder=None, inplace=None):
|
|
308
348
|
""" partitions data between events evt_start and evt_end """
|
|
349
|
+
start_time = time.time()
|
|
309
350
|
verbose = self.verbose
|
|
310
351
|
in_folder = self.in_folder
|
|
311
352
|
if inplace is None:
|
|
312
353
|
inplace = self.inplace
|
|
313
|
-
|
|
314
|
-
fl = engine(in_folder)
|
|
354
|
+
fl = engine(in_folder, extension='.zoo', name_contains=self.name_contains, subfolders=self.subfolders)
|
|
315
355
|
for f in fl:
|
|
316
356
|
if verbose:
|
|
317
357
|
batchdisp('partitioning data between events {} and {} for {}'.format(evt_start, evt_end, f), level=2, verbose=verbose)
|
|
318
358
|
data = zload(f)
|
|
319
359
|
data = partition_data(data, evt_start, evt_end)
|
|
320
|
-
zsave(f, data, inplace=inplace,
|
|
321
|
-
|
|
360
|
+
zsave(f, data, inplace=inplace, out_folder=out_folder, root_folder=in_folder)
|
|
361
|
+
method_name = inspect.currentframe().f_code.co_name
|
|
362
|
+
batchdisp('{} process complete for {} file(s) in {:.2f} secs'.format(method_name, len(fl), time.time() - start_time), level=1, verbose=verbose)
|
|
322
363
|
# Update self.folder after processing
|
|
323
364
|
self._update_folder(out_folder, inplace, in_folder)
|
|
324
365
|
|
|
@@ -340,8 +381,9 @@ class BiomechZoo:
|
|
|
340
381
|
# batchdisp('filtering data in channels {} for {}'.format(ch, f), level=2, verbose=verbose)
|
|
341
382
|
# data = zload(f)
|
|
342
383
|
# data = filter_data(data, ch, filt)
|
|
343
|
-
# zsave(f, data, inplace=inplace, root_folder=in_folder, out_folder=out_folder)
|
|
344
|
-
#
|
|
384
|
+
# zsave(f, data, inplace=inplace, root_folder=in_folder, out_folder=out_folder, verbose=verbose)
|
|
385
|
+
# method_name = inspect.currentframe().f_code.co_name
|
|
386
|
+
# batchdisp('{} computation complete for {} file(s)'.format(method_name, len(fl)), level=1, verbose=verbose)
|
|
345
387
|
#
|
|
346
388
|
# # Update self.folder after processing
|
|
347
389
|
# self._update_folder(out_folder, inplace, in_folder)
|
|
@@ -5,25 +5,32 @@ import re
|
|
|
5
5
|
from biomechzoo.utils.compute_sampling_rate_from_time import compute_sampling_rate_from_time
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
def csv2zoo_data(csv_path,
|
|
8
|
+
def csv2zoo_data(csv_path, type='csv',skip_rows=0, freq=None):
|
|
9
|
+
# todo: check calculation for sampling rate
|
|
9
10
|
|
|
10
11
|
# Read header lines until 'endheader'
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
12
|
+
metadata = {}
|
|
13
|
+
if type == 'csv' and skip_rows > 0:
|
|
14
|
+
header_lines = []
|
|
15
|
+
with open(csv_path, 'r') as f:
|
|
16
|
+
for line in f:
|
|
17
|
+
header_lines.append(line.strip())
|
|
18
|
+
if line.strip().lower() == 'endheader':
|
|
19
|
+
break
|
|
20
|
+
# Parse metadata
|
|
21
|
+
metadata = _parse_metadata(header_lines)
|
|
22
|
+
|
|
23
|
+
if type == 'csv':
|
|
24
|
+
df = pd.read_csv(csv_path, skiprows=skip_rows)
|
|
25
|
+
elif type =='parquet':
|
|
26
|
+
df = pd.read_parquet(csv_path)
|
|
27
|
+
else:
|
|
28
|
+
raise ValueError('type must be csv or parquet')
|
|
29
|
+
|
|
30
|
+
# Use all columns
|
|
31
|
+
data = df.iloc[:, 0:]
|
|
32
|
+
|
|
33
|
+
# assemble zoo data
|
|
27
34
|
zoo_data = {}
|
|
28
35
|
for ch in data.columns:
|
|
29
36
|
zoo_data[ch] = {
|
|
@@ -31,13 +38,26 @@ def csv2zoo_data(csv_path, header_len=10):
|
|
|
31
38
|
'event': []
|
|
32
39
|
}
|
|
33
40
|
|
|
34
|
-
#
|
|
35
|
-
|
|
41
|
+
# try to find frequency in metadata
|
|
42
|
+
if freq is None:
|
|
43
|
+
if 'freq' in metadata:
|
|
44
|
+
freq = metadata['freq']
|
|
45
|
+
elif 'sampling_rate' in metadata:
|
|
46
|
+
freq = metadata['sampling_rate']
|
|
47
|
+
else:
|
|
48
|
+
freq = None # or raise an error
|
|
49
|
+
|
|
50
|
+
# now try to calculate freq from a time column
|
|
51
|
+
if freq is None:
|
|
52
|
+
time_col = [col for col in df.columns if 'time' in col.lower()]
|
|
53
|
+
if time_col is not None:
|
|
54
|
+
time_data = df[time_col].to_numpy()[:,0]
|
|
55
|
+
freq = compute_sampling_rate_from_time(time_data)
|
|
36
56
|
|
|
37
57
|
# add metadata
|
|
38
58
|
# todo update zoosystem to match biomechzoo requirements
|
|
39
59
|
zoo_data['zoosystem'] = metadata
|
|
40
|
-
zoo_data['zoosystem']['Freq'] =
|
|
60
|
+
zoo_data['zoosystem']['Freq'] = freq
|
|
41
61
|
|
|
42
62
|
return zoo_data
|
|
43
63
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
|
|
1
3
|
def explodechannel_data(data, channels=None):
|
|
2
4
|
""" Explodes 3D channels (n x 3 arrays) into separate X, Y, Z channels.
|
|
3
5
|
|
|
@@ -10,8 +12,7 @@ def explodechannel_data(data, channels=None):
|
|
|
10
12
|
data_new (dict): Modified zoo dictionary with exploded channels.
|
|
11
13
|
"""
|
|
12
14
|
|
|
13
|
-
data_new =
|
|
14
|
-
|
|
15
|
+
data_new = copy.deepcopy(data)
|
|
15
16
|
# Find default channels if none provided
|
|
16
17
|
if channels is None:
|
|
17
18
|
channels = []
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
from biomechzoo.utils.findfield import findfield
|
|
2
2
|
import warnings
|
|
3
|
+
import copy
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
def partition_data(data, evt_start, evt_end):
|
|
6
7
|
""" partition data for all channels between events evt_start and evt_end"""
|
|
7
8
|
|
|
8
9
|
# extract event values
|
|
9
|
-
e1, _ = findfield(data,evt_start)
|
|
10
|
-
e2, _ = findfield(data,evt_end)
|
|
10
|
+
e1, _ = findfield(data, evt_start)
|
|
11
|
+
e2, _ = findfield(data, evt_end)
|
|
11
12
|
|
|
12
|
-
data_new =
|
|
13
|
+
data_new = copy.deepcopy(data)
|
|
13
14
|
for ch_name, ch_data in data_new.items():
|
|
14
15
|
if ch_name != 'zoosystem':
|
|
15
16
|
try:
|
|
16
|
-
data_new[ch_name]['line'] = ch_data[e1[0]:e2[0],
|
|
17
|
+
data_new[ch_name]['line'] = ch_data[e1[0]:e2[0],]
|
|
17
18
|
except (IndexError, ValueError) as e:
|
|
18
19
|
# IndexError: if e1[0]:e2[0] goes beyond the available indices
|
|
19
20
|
# ValueError: less likely, but may arise with shape mismatches
|
|
@@ -29,6 +30,7 @@ def partition_data(data, evt_start, evt_end):
|
|
|
29
30
|
continue # do not change outlier markers
|
|
30
31
|
else:
|
|
31
32
|
new_frame = original_frame - e1[0] + 1
|
|
33
|
+
print(new_frame)
|
|
32
34
|
data_new[ch_name]['event'][event_name][0] = new_frame
|
|
33
35
|
|
|
34
36
|
return data_new
|
|
@@ -48,4 +50,4 @@ def _partition_event(event_dict, evt_start, evt_end, arr_len):
|
|
|
48
50
|
#
|
|
49
51
|
#
|
|
50
52
|
#
|
|
51
|
-
# return event_dict_new
|
|
53
|
+
# return event_dict_new
|
|
@@ -19,7 +19,7 @@ def engine(root_folder, extension='.zoo', subfolders=None, name_contains=None, v
|
|
|
19
19
|
Arguments:
|
|
20
20
|
root_folder (str): The root directory path where the search begins.
|
|
21
21
|
extension (str): File extension to search for (e.g., '.zoo', '.c3d'). Default .zoo
|
|
22
|
-
subfolders (list
|
|
22
|
+
subfolders (list or str, optional): List of folder names to restrict the search to.
|
|
23
23
|
Only files inside these folders (or their subfolders) are included.
|
|
24
24
|
If None, search all subfolders.
|
|
25
25
|
name_contains (str, optional): Substring that must be present in the filename
|
|
@@ -28,6 +28,11 @@ def engine(root_folder, extension='.zoo', subfolders=None, name_contains=None, v
|
|
|
28
28
|
Returns:
|
|
29
29
|
list of str: List of full file paths matching the criteria.
|
|
30
30
|
"""
|
|
31
|
+
# check format of subfolder (string or list)
|
|
32
|
+
if subfolders is not None:
|
|
33
|
+
if type(subfolders) is str:
|
|
34
|
+
subfolders = [subfolders]
|
|
35
|
+
|
|
31
36
|
matched_files = []
|
|
32
37
|
|
|
33
38
|
subfolders_set = set(subfolders) if subfolders else None
|
|
@@ -2,8 +2,10 @@ from scipy.io import savemat
|
|
|
2
2
|
import inspect
|
|
3
3
|
import os
|
|
4
4
|
|
|
5
|
+
from biomechzoo.utils.batchdisp import batchdisp
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
|
|
8
|
+
def zsave(fl, data, inplace=True, out_folder=None, root_folder=None, verbose=False):
|
|
7
9
|
"""
|
|
8
10
|
Save zoo data to .zoo file (MAT format)
|
|
9
11
|
|
|
@@ -28,9 +30,9 @@ def zsave(fl, data, inplace=True, out_folder=None, root_folder=None):
|
|
|
28
30
|
|
|
29
31
|
# Determine save path
|
|
30
32
|
if inplace:
|
|
31
|
-
|
|
33
|
+
fl_new = fl
|
|
34
|
+
out_dir = os.path.dirname(fl)
|
|
32
35
|
else:
|
|
33
|
-
filename = os.path.basename(fl)
|
|
34
36
|
if out_folder is None:
|
|
35
37
|
out_folder = 'processed'
|
|
36
38
|
|
|
@@ -47,4 +49,6 @@ def zsave(fl, data, inplace=True, out_folder=None, root_folder=None):
|
|
|
47
49
|
|
|
48
50
|
# Save the .zoo file
|
|
49
51
|
savemat(fl_new, data)
|
|
52
|
+
batchdisp('all files saved to ' + out_dir, level=1, verbose=verbose)
|
|
53
|
+
|
|
50
54
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: biomechzoo
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.5
|
|
4
4
|
Summary: Python implementation of the biomechZoo toolbox
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/mcgillmotionlab/biomechzoo
|
|
7
|
-
Requires-Python:
|
|
7
|
+
Requires-Python: <3.12,>=3.11
|
|
8
8
|
Description-Content-Type: text/markdown
|
|
9
9
|
License-File: LICENSE
|
|
10
10
|
Requires-Dist: ezc3d>=1.5.19
|
|
@@ -12,6 +12,7 @@ Requires-Dist: matplotlib>=3.10.6
|
|
|
12
12
|
Requires-Dist: numpy==2.2.6
|
|
13
13
|
Requires-Dist: pandas>=2.3.2
|
|
14
14
|
Requires-Dist: scipy>=1.16.2
|
|
15
|
+
Requires-Dist: pyarrow>=19.0.0
|
|
15
16
|
Dynamic: license-file
|
|
16
17
|
|
|
17
18
|
# BiomechZoo for Python
|
|
@@ -30,3 +31,15 @@ This is a development version of the biomechzoo toolbox for python.
|
|
|
30
31
|
- We use Numpy 2.2.6 for compatibility with https://pypi.org/project/numba/
|
|
31
32
|
|
|
32
33
|
See also http://www.github.com/mcgillmotionlab/biomechzoo or http://www.biomechzoo.com for more information
|
|
34
|
+
|
|
35
|
+
## Developer notes
|
|
36
|
+
|
|
37
|
+
### Installing a dev environment
|
|
38
|
+
conda create -n biomechzoo-dev python=3.11
|
|
39
|
+
conda activate biomechzoo-dev
|
|
40
|
+
pip install -e ".[dev]"
|
|
41
|
+
|
|
42
|
+
### import issues
|
|
43
|
+
if using PyCharm:
|
|
44
|
+
- Right-click on src/.
|
|
45
|
+
- Select Mark Directory as → Sources Root.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/biomech_ops/continuous_relative_phase_data.py
RENAMED
|
File without changes
|
{biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/biomech_ops/continuous_relative_phase_line.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/processing/split_trial_by_gait_cycle.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{biomechzoo-0.4.1 → biomechzoo-0.4.5}/src/biomechzoo/utils/compute_sampling_rate_from_time.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|