worklab 2.1.1__tar.gz → 2.3.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {worklab-2.1.1 → worklab-2.3.6}/PKG-INFO +4 -2
- {worklab-2.1.1 → worklab-2.3.6}/pyproject.toml +5 -3
- {worklab-2.1.1 → worklab-2.3.6}/worklab/ana.py +235 -88
- {worklab-2.1.1 → worklab-2.3.6}/worklab/com.py +15 -12
- worklab-2.3.6/worklab/imu.py +811 -0
- {worklab-2.1.1 → worklab-2.3.6}/worklab/kin.py +4 -0
- {worklab-2.1.1 → worklab-2.3.6}/worklab/plots.py +110 -6
- {worklab-2.1.1 → worklab-2.3.6}/worklab.egg-info/PKG-INFO +4 -2
- {worklab-2.1.1 → worklab-2.3.6}/worklab.egg-info/requires.txt +3 -1
- worklab-2.1.1/worklab/imu.py +0 -376
- {worklab-2.1.1 → worklab-2.3.6}/LICENSE +0 -0
- {worklab-2.1.1 → worklab-2.3.6}/README.md +0 -0
- {worklab-2.1.1 → worklab-2.3.6}/setup.cfg +0 -0
- {worklab-2.1.1 → worklab-2.3.6}/tests/test_utils.py +0 -0
- {worklab-2.1.1 → worklab-2.3.6}/worklab/__init__.py +0 -0
- {worklab-2.1.1 → worklab-2.3.6}/worklab/move.py +0 -0
- {worklab-2.1.1 → worklab-2.3.6}/worklab/physio.py +0 -0
- {worklab-2.1.1 → worklab-2.3.6}/worklab/utils.py +0 -0
- {worklab-2.1.1 → worklab-2.3.6}/worklab.egg-info/SOURCES.txt +0 -0
- {worklab-2.1.1 → worklab-2.3.6}/worklab.egg-info/dependency_links.txt +0 -0
- {worklab-2.1.1 → worklab-2.3.6}/worklab.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: worklab
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.6
|
|
4
4
|
Summary: Basic scripts for worklab devices
|
|
5
5
|
Author-email: Sophie de Klerk <r.de.klerk@pl.hanze.nl>, Thomas Rietveld <t.rietveld@lboro.ac.uk>, Rowie Janssen <r.j.f.janssen@umcg.nl>, Jelmer Braaksma <j.braaksma01@umcg.nl>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -695,11 +695,13 @@ Requires-Dist: matplotlib
|
|
|
695
695
|
Requires-Dist: xlrd
|
|
696
696
|
Requires-Dist: scikit-learn
|
|
697
697
|
Requires-Dist: seaborn
|
|
698
|
+
Requires-Dist: imufusion
|
|
699
|
+
Requires-Dist: openpyxl
|
|
698
700
|
Provides-Extra: dev
|
|
699
701
|
Requires-Dist: pytest; extra == "dev"
|
|
700
702
|
Requires-Dist: Flake8-pyproject; extra == "dev"
|
|
701
703
|
Requires-Dist: black; extra == "dev"
|
|
702
|
-
Requires-Dist: jupyter-book; extra == "dev"
|
|
704
|
+
Requires-Dist: jupyter-book==0.15.1; extra == "dev"
|
|
703
705
|
Requires-Dist: build; extra == "dev"
|
|
704
706
|
Dynamic: license-file
|
|
705
707
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "worklab"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.3.6"
|
|
4
4
|
description = "Basic scripts for worklab devices"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.7"
|
|
@@ -25,7 +25,9 @@ dependencies = [
|
|
|
25
25
|
"matplotlib",
|
|
26
26
|
"xlrd",
|
|
27
27
|
"scikit-learn",
|
|
28
|
-
"seaborn"
|
|
28
|
+
"seaborn",
|
|
29
|
+
"imufusion",
|
|
30
|
+
"openpyxl",
|
|
29
31
|
]
|
|
30
32
|
|
|
31
33
|
[project.optional-dependencies]
|
|
@@ -33,7 +35,7 @@ dev = [
|
|
|
33
35
|
"pytest",
|
|
34
36
|
"Flake8-pyproject",
|
|
35
37
|
"black",
|
|
36
|
-
"jupyter-book",
|
|
38
|
+
"jupyter-book==0.15.1",
|
|
37
39
|
"build"
|
|
38
40
|
]
|
|
39
41
|
|
|
@@ -5,11 +5,15 @@ import math
|
|
|
5
5
|
import pandas as pd
|
|
6
6
|
import matplotlib.pyplot as plt
|
|
7
7
|
import numpy as np
|
|
8
|
-
import
|
|
8
|
+
import os
|
|
9
|
+
from glob import glob
|
|
10
|
+
import warnings
|
|
9
11
|
import seaborn as sns
|
|
10
12
|
|
|
11
|
-
from .plots import plot_power_speed_dist
|
|
13
|
+
from .plots import plot_power_speed_dist, force_velocity_curve, plot_pushes_ergo
|
|
12
14
|
from .physio import calc_weighted_average
|
|
15
|
+
from .com import load_esseda, load_wheelchair
|
|
16
|
+
from .kin import filter_ergo, process_ergo, push_by_push_ergo
|
|
13
17
|
|
|
14
18
|
|
|
15
19
|
def mean_data(data):
|
|
@@ -54,7 +58,7 @@ def cut_data(data, start, end, distance=True):
|
|
|
54
58
|
Returns
|
|
55
59
|
-------
|
|
56
60
|
data : dict
|
|
57
|
-
data
|
|
61
|
+
data cut to time of interest
|
|
58
62
|
|
|
59
63
|
"""
|
|
60
64
|
for side in data:
|
|
@@ -223,7 +227,7 @@ def wingate(data, title=None, box=False, ylim=5):
|
|
|
223
227
|
Parameters
|
|
224
228
|
----------
|
|
225
229
|
data : dict
|
|
226
|
-
processed and
|
|
230
|
+
processed and cut ergometer data dictionary with dataframes
|
|
227
231
|
title : str
|
|
228
232
|
title of figure
|
|
229
233
|
box : bool
|
|
@@ -401,7 +405,7 @@ def maximal1min(data, dur, title=None):
|
|
|
401
405
|
Parameters
|
|
402
406
|
----------
|
|
403
407
|
data : dict
|
|
404
|
-
processed and
|
|
408
|
+
processed and cut ergometer data dictionary with dataframes
|
|
405
409
|
dur : int
|
|
406
410
|
duration of max test in seconds
|
|
407
411
|
title : str, optional
|
|
@@ -494,9 +498,9 @@ def ana_sprint(data, data_pbp, half=5, title=None):
|
|
|
494
498
|
Parameters
|
|
495
499
|
----------
|
|
496
500
|
data : dict
|
|
497
|
-
processed and
|
|
501
|
+
processed and cut ergometer data dictionary with dataframes
|
|
498
502
|
data_pbp : dict
|
|
499
|
-
processed and
|
|
503
|
+
processed and cut push_by_push ergometer data dictionary with dataframes
|
|
500
504
|
half : float, optional
|
|
501
505
|
half-time of the sprint, default is 5 s
|
|
502
506
|
title : str, optional
|
|
@@ -557,11 +561,11 @@ def ana_submax(data_ergo, data_pbp, data_spiro):
|
|
|
557
561
|
Parameters
|
|
558
562
|
----------
|
|
559
563
|
data_ergo : pd.DataFrame
|
|
560
|
-
processed and
|
|
564
|
+
processed and cut ergometer data
|
|
561
565
|
data_pbp : pd.DataFrame
|
|
562
|
-
processed and
|
|
566
|
+
processed and cut ergometer data
|
|
563
567
|
data_spiro : pd.DataFrame
|
|
564
|
-
processed and
|
|
568
|
+
processed and cut spirometer data
|
|
565
569
|
|
|
566
570
|
Returns
|
|
567
571
|
-------
|
|
@@ -597,91 +601,234 @@ def ana_submax(data_ergo, data_pbp, data_spiro):
|
|
|
597
601
|
return outcomes
|
|
598
602
|
|
|
599
603
|
|
|
600
|
-
def
|
|
604
|
+
def force_vel_profiling(filename, athlete='PP01', classification='LP',
|
|
605
|
+
sport='WR', duration=10, var='mean', push_cutoff=1,
|
|
606
|
+
minpeak=None, unit='ms', n_sprints=7,
|
|
607
|
+
res_names=None, x_lim=6, y_lim=None):
|
|
601
608
|
"""
|
|
602
|
-
|
|
609
|
+
Force velocity profiling (individualised) on the LODE wheelchair ergometer.
|
|
610
|
+
|
|
603
611
|
|
|
604
612
|
Parameters
|
|
605
613
|
----------
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
614
|
+
filename : str
|
|
615
|
+
main path name which contain all athlete data, with all sprints
|
|
616
|
+
as separate Excel files within each athlete folder (e.g., 0, 1, 2, 3, 4, 5, 6)
|
|
617
|
+
athlete : str, default 'PP01'
|
|
618
|
+
The alphanumeric identifier or acronym assigned to the participant
|
|
619
|
+
(e.g., 'AS', 'PP01'). Determines the target data folder name.
|
|
620
|
+
classification : str, default 'LP'
|
|
621
|
+
The sport-specific physical impairment classification tier.
|
|
622
|
+
Accepts 'HP' (High Point) or 'LP' (Low Point)
|
|
623
|
+
sport : str, default 'WR'
|
|
624
|
+
The sport, e.g., WR = Wheelchair Rugby
|
|
625
|
+
duration : int, default 10
|
|
626
|
+
The length of sprints in seconds
|
|
610
627
|
var : str
|
|
611
|
-
'
|
|
612
|
-
|
|
628
|
+
'mean' force and velocity, 'peak' force and velocity, or 'impulse' and velocity
|
|
629
|
+
push_cutoff: int
|
|
630
|
+
numbers of pushes to cut off at the start, default is 1
|
|
631
|
+
minpeak : int
|
|
632
|
+
Minimum peak detection on the torque signal
|
|
633
|
+
default is None, which will automatically detect peaks based on mean
|
|
634
|
+
unit : str
|
|
635
|
+
unit of measured 'speed' column; ms, kmh or mph, default is ms
|
|
636
|
+
n_sprints : int
|
|
637
|
+
Total number of sprints, default is 7
|
|
638
|
+
res_names :
|
|
639
|
+
list of sprint names, default ['Low', 'Standard', '25%', '50%', '75%', '100%', '125%']
|
|
640
|
+
x_lim : int
|
|
641
|
+
x limit axis, default is 6
|
|
642
|
+
y_lim : int
|
|
643
|
+
y limit axis, default is 800
|
|
613
644
|
Returns
|
|
614
645
|
-------
|
|
615
|
-
|
|
616
|
-
force-velocity
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
646
|
+
var_fvc : pd.DataFrame()
|
|
647
|
+
Containing the force-velocity outcomes (R2, optimal vel/power, coordinates)
|
|
648
|
+
outcomes_mean_all: pd.DataFrame()
|
|
649
|
+
Mean outcome variables of the sprints (mean, right, left)
|
|
650
|
+
data_pbp_all: pd.DataFrame()
|
|
651
|
+
Push-by-push outcomes for all sprints (mean, right, left)
|
|
620
652
|
"""
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
653
|
+
warnings.filterwarnings("ignore", category=UserWarning, module="openpyxl")
|
|
654
|
+
|
|
655
|
+
outcomes_mean_all, outcomes_right_all, outcomes_left_all = (pd.DataFrame() for _ in range(3))
|
|
656
|
+
|
|
657
|
+
upper_lim = 1400 if classification == 'HP' else 800
|
|
658
|
+
upper_lim = y_lim if y_lim is not None else upper_lim
|
|
659
|
+
low_lim = 6
|
|
660
|
+
low_lim = x_lim if x_lim is not None else low_lim
|
|
661
|
+
if res_names is None:
|
|
662
|
+
res_names = ['Low', 'Standard', '25%', '50%', '75%', '100%', '125%']
|
|
663
|
+
# Reading files and creating resistance names
|
|
664
|
+
if os.path.basename(filename) != athlete:
|
|
665
|
+
filenames = filename + '\\' + athlete + "\\*.xlsx*"
|
|
624
666
|
else:
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
pomax_opt = parabola['POmax'].max()
|
|
648
|
-
vmax_opt = parabola['vmax'][pomax_pos]
|
|
649
|
-
|
|
650
|
-
variables = pd.DataFrame([])
|
|
651
|
-
variables['R2'] = [r_sq]
|
|
652
|
-
variables['opt_vel'] = vmax_opt
|
|
653
|
-
variables['opt_pow'] = pomax_opt
|
|
654
|
-
variables['y_cor'] = model.intercept_
|
|
655
|
-
variables['x_cor'] = x1[-1]
|
|
656
|
-
variables['coef'] = model.coef_
|
|
657
|
-
variables = round(variables, 2)
|
|
658
|
-
|
|
659
|
-
sns.set_style('darkgrid')
|
|
660
|
-
col_pal = sns.color_palette("dark:#5A9_r")
|
|
667
|
+
filenames = filename + '\\*.xlsx*'
|
|
668
|
+
save_loc = filename + "\\Outcomes"
|
|
669
|
+
fig_loc = save_loc + '\\' + athlete
|
|
670
|
+
|
|
671
|
+
if not os.path.exists(save_loc):
|
|
672
|
+
os.makedirs(save_loc)
|
|
673
|
+
if not os.path.exists(fig_loc):
|
|
674
|
+
os.makedirs(fig_loc)
|
|
675
|
+
|
|
676
|
+
folder = sorted(glob(filenames))
|
|
677
|
+
if not folder:
|
|
678
|
+
# Prints a single, clean text line and stops the function immediately
|
|
679
|
+
print(f"Could not find any sprint data files for athlete '{athlete}' at location: {filename}\\{athlete}\\")
|
|
680
|
+
return None
|
|
681
|
+
|
|
682
|
+
if len(res_names) != n_sprints:
|
|
683
|
+
print(
|
|
684
|
+
f"The number of sprints defined in n_sprints '{n_sprints}' and the list of resistance "
|
|
685
|
+
f"names defined in res_names '{res_names}' do not match")
|
|
686
|
+
return None
|
|
687
|
+
data_pbp_all, data_pbp_right, data_pbp_left = pd.DataFrame([]), pd.DataFrame([]), pd.DataFrame([])
|
|
688
|
+
col_pal = sns.color_palette("dark:#5A9_r", 7)
|
|
661
689
|
sns.set_palette(col_pal)
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
690
|
+
sns.set_style('darkgrid')
|
|
691
|
+
var_names = ['dist', 'max_speed', 'mean_power', 'mean_force', 'mean_speed', 'max_power_push', 'max_force_push',
|
|
692
|
+
'max_speed_push', 'mean_power_push', 'mean_force_push', 'mean_speed_push',
|
|
693
|
+
'work_push', 'ptime', 'negwork_push', 'slope', 'smoothness', 'push_freq', 'tot_work', 'mu']
|
|
694
|
+
for sprint, res_name in zip(folder, res_names):
|
|
695
|
+
wheelchair = load_wheelchair(sprint)
|
|
696
|
+
data = load_esseda(sprint)
|
|
697
|
+
data = filter_ergo(data)
|
|
698
|
+
data = process_ergo(data, wheelsize=wheelchair['wheelsize'], rimsize=wheelchair['rimsize'], unit=unit)
|
|
699
|
+
data = mean_data(data)
|
|
700
|
+
res_data = pd.read_excel(sprint, sheet_name=4)
|
|
701
|
+
res_data = res_data[res_data['Time'] > 10]
|
|
702
|
+
mu = np.mean((res_data['Resistance left'] + res_data['Resistance right']) / 2)
|
|
703
|
+
m = int(len(data['mean']["speed"]) - (0.5 * 100))
|
|
704
|
+
start = None
|
|
705
|
+
for st in range(1, m):
|
|
706
|
+
if data['mean']["speed"][st] > 0.1:
|
|
707
|
+
if data['mean']["speed"][int(st + (1.0 * 100))] > 0.5:
|
|
708
|
+
start = st
|
|
709
|
+
break
|
|
710
|
+
if start is None:
|
|
711
|
+
print('Can not determine start point!')
|
|
712
|
+
return None
|
|
713
|
+
data = cut_data(data, start / 100, start / 100 + duration)
|
|
714
|
+
if minpeak is None:
|
|
715
|
+
minpeak = (((np.mean(data['left']['torque']) + np.mean(data['right']['torque'])) / 2)
|
|
716
|
+
+ 4)
|
|
717
|
+
data_pbp = push_by_push_ergo(data, variable='torque', cutoff=1.0,
|
|
718
|
+
minpeak=minpeak)
|
|
719
|
+
|
|
720
|
+
res_label = res_name
|
|
721
|
+
|
|
722
|
+
title_suffix = "resistance"
|
|
723
|
+
sprint_title = f"Sprint at {res_label} {title_suffix}"
|
|
724
|
+
|
|
725
|
+
fig, outcomes = ana_sprint(data, data_pbp, half=5)
|
|
726
|
+
fig[0].suptitle(sprint_title)
|
|
727
|
+
fig[1][1].set_ylabel("Velocity [m/s]")
|
|
728
|
+
fig[1][0].set_ylim(0, upper_lim) # Uses upper_lim automatically (800 or 1400)
|
|
729
|
+
fig[1][1].set_ylim(0, 5)
|
|
730
|
+
fig[0].savefig(f"{fig_loc}\\Sprint_{res_label}.png", dpi=600)
|
|
731
|
+
plt.close(fig[0])
|
|
732
|
+
|
|
733
|
+
plot_pushes_ergo(data, data_pbp, var="torque", start=True, stop=True, peak=True)
|
|
734
|
+
plt.savefig(f"{fig_loc}\\Sprint_{res_label}_pbp.png", dpi=600)
|
|
735
|
+
plt.close('all')
|
|
736
|
+
|
|
737
|
+
max_cols = ['dist', 'speed']
|
|
738
|
+
mean_cols = ['power', 'uforce', 'speed']
|
|
739
|
+
pbp_cols = ['maxpower', 'maxuforce', 'maxspeed', 'meanpower', 'meanuforce',
|
|
740
|
+
'meanspeed', 'work', 'ptime', 'negwork', 'slope', 'smoothness']
|
|
741
|
+
for mode in ['mean', 'right', 'left']:
|
|
742
|
+
data_pbp[mode]['Resistance'] = res_label
|
|
743
|
+
processed_outcomes = {}
|
|
744
|
+
|
|
745
|
+
for side in ['mean', 'right', 'left']:
|
|
746
|
+
data_pbp[side] = data_pbp[side].round(2)
|
|
747
|
+
|
|
748
|
+
stats = [
|
|
749
|
+
data[side][max_cols].max(),
|
|
750
|
+
data[side][mean_cols].mean(),
|
|
751
|
+
data_pbp[side][pbp_cols].mean()
|
|
752
|
+
]
|
|
753
|
+
outcome_series = pd.concat(stats)
|
|
754
|
+
outcome_series['push_freq'] = len(data_pbp[side]) / duration
|
|
755
|
+
outcome_series['tot_work'] = np.trapezoid(data[side]['work'])
|
|
756
|
+
outcome_series['mu'] = mu
|
|
757
|
+
|
|
758
|
+
processed_outcomes[side] = outcome_series
|
|
759
|
+
|
|
760
|
+
outcomes_mean = processed_outcomes['mean']
|
|
761
|
+
outcomes_right = processed_outcomes['right']
|
|
762
|
+
outcomes_left = processed_outcomes['left']
|
|
763
|
+
|
|
764
|
+
if outcomes_right_all.empty:
|
|
765
|
+
outcomes_right_all = outcomes_right
|
|
766
|
+
outcomes_left_all = outcomes_left
|
|
767
|
+
outcomes_mean_all = outcomes_mean
|
|
768
|
+
else:
|
|
769
|
+
outcomes_right_all = pd.concat([outcomes_right_all, outcomes_right], axis=1)
|
|
770
|
+
outcomes_left_all = pd.concat([outcomes_left_all, outcomes_left], axis=1)
|
|
771
|
+
outcomes_mean_all = pd.concat([outcomes_mean_all, outcomes_mean], axis=1)
|
|
772
|
+
|
|
773
|
+
if data_pbp_all.empty:
|
|
774
|
+
data_pbp_all = data_pbp['mean']
|
|
775
|
+
data_pbp_right = data_pbp['right']
|
|
776
|
+
data_pbp_left = data_pbp['left']
|
|
777
|
+
else:
|
|
778
|
+
data_pbp_all = pd.concat([data_pbp_all, data_pbp['mean']])
|
|
779
|
+
data_pbp_right = pd.concat([data_pbp_right, data_pbp['right']])
|
|
780
|
+
data_pbp_left = pd.concat([data_pbp_left, data_pbp['left']])
|
|
781
|
+
|
|
782
|
+
with pd.ExcelWriter(fig_loc + r'\pbp_outcomes.xlsx') as writer:
|
|
783
|
+
data_pbp_all.to_excel(writer, sheet_name='mean')
|
|
784
|
+
data_pbp_right.to_excel(writer, sheet_name='right')
|
|
785
|
+
data_pbp_left.to_excel(writer, sheet_name='left')
|
|
786
|
+
|
|
787
|
+
dfs = {'mean': outcomes_mean_all, 'right': outcomes_right_all, 'left': outcomes_left_all}
|
|
788
|
+
|
|
789
|
+
for side, df in dfs.items():
|
|
790
|
+
df_new = df.T.reset_index(drop=True)
|
|
791
|
+
df_new.columns = var_names
|
|
792
|
+
df_new['athlete'], df_new['side'], df_new['sport'] = athlete, side, sport
|
|
793
|
+
dfs[side] = df_new
|
|
794
|
+
|
|
795
|
+
outcomes_mean_all, outcomes_right_all, outcomes_left_all = dfs.values()
|
|
796
|
+
|
|
797
|
+
with pd.ExcelWriter(fig_loc + r'\pbp_outcomes_mean.xlsx') as writer:
|
|
798
|
+
outcomes_mean_all.to_excel(writer, sheet_name='mean')
|
|
799
|
+
outcomes_right_all.to_excel(writer, sheet_name='right')
|
|
800
|
+
outcomes_left_all.to_excel(writer, sheet_name='left')
|
|
801
|
+
|
|
802
|
+
# Create force_velocity curves for mean/right/left
|
|
803
|
+
fig_fvc_right, var_fvc_right = force_velocity_curve(data_pbp_right, y_lim=upper_lim,
|
|
804
|
+
push_cutoff=push_cutoff,
|
|
805
|
+
n_sprints=n_sprints,
|
|
806
|
+
var=var, x_lim=low_lim)
|
|
807
|
+
var_fvc_right.index = [athlete]
|
|
808
|
+
var_fvc_right['side'] = 'right'
|
|
809
|
+
plt.savefig(fig_loc + r'\Force_velocity_curve_right.png', dpi=600)
|
|
810
|
+
plt.close('all')
|
|
811
|
+
|
|
812
|
+
fig_fvc_left, var_fvc_left = force_velocity_curve(data_pbp_left, y_lim=upper_lim,
|
|
813
|
+
push_cutoff=push_cutoff,
|
|
814
|
+
n_sprints=n_sprints,
|
|
815
|
+
var=var, x_lim=low_lim)
|
|
816
|
+
var_fvc_left.index = [athlete]
|
|
817
|
+
var_fvc_left['side'] = 'left'
|
|
818
|
+
plt.savefig(fig_loc + r'\Force_velocity_curve_left.png', dpi=600)
|
|
819
|
+
plt.close('all')
|
|
820
|
+
|
|
821
|
+
fig_fvc, var_fvc = force_velocity_curve(data_pbp_all, y_lim=upper_lim,
|
|
822
|
+
push_cutoff=push_cutoff,
|
|
823
|
+
n_sprints=n_sprints,
|
|
824
|
+
var=var, x_lim=low_lim)
|
|
825
|
+
var_fvc.index = [athlete]
|
|
826
|
+
var_fvc['side'] = 'mean'
|
|
827
|
+
plt.savefig(fig_loc + r'\Force_velocity_curve.png', dpi=600)
|
|
828
|
+
|
|
829
|
+
with pd.ExcelWriter(fig_loc + r'\force_vel_outcomes.xlsx') as writer:
|
|
830
|
+
var_fvc.to_excel(writer, sheet_name='mean')
|
|
831
|
+
var_fvc_right.to_excel(writer, sheet_name='right')
|
|
832
|
+
var_fvc_left.to_excel(writer, sheet_name='left')
|
|
833
|
+
|
|
834
|
+
return var_fvc, outcomes_mean_all, data_pbp_all
|
|
@@ -282,7 +282,7 @@ def load_opti(filename, rotate=True):
|
|
|
282
282
|
| angle | unwrapped wheel angle| rad |
|
|
283
283
|
+------------+----------------------+-----------+
|
|
284
284
|
|
|
285
|
-
|
|
285
|
+
note:: Optipush uses a local coordinate system, option to rotate Fx and Fy available in >1.6
|
|
286
286
|
|
|
287
287
|
Parameters
|
|
288
288
|
----------
|
|
@@ -341,7 +341,7 @@ def load_sw(filename, sfreq=200):
|
|
|
341
341
|
| angle | unwrapped wheel angle | rad |
|
|
342
342
|
+------------+-----------------------+-----------+
|
|
343
343
|
|
|
344
|
-
|
|
344
|
+
note:: SMARTwheel uses a global coordinate system
|
|
345
345
|
|
|
346
346
|
Parameters
|
|
347
347
|
----------
|
|
@@ -899,7 +899,7 @@ def load_movesense(root_dir, right=None, frame=None, left=None):
|
|
|
899
899
|
|
|
900
900
|
def load_ximu3(root_dir, filenames=None, inplace=False):
|
|
901
901
|
"""
|
|
902
|
-
Imports X-IMU3 session in nested dictionary with all devices with all sensors.
|
|
902
|
+
Imports X-IMU3 session in nested dictionary with all devices with all sensors.
|
|
903
903
|
|
|
904
904
|
Parameters
|
|
905
905
|
----------
|
|
@@ -924,6 +924,8 @@ def load_ximu3(root_dir, filenames=None, inplace=False):
|
|
|
924
924
|
raise Exception("No contents in directory")
|
|
925
925
|
directories = glob(f"{root_dir}/*/") # folders of all devices
|
|
926
926
|
sessiondata = dict()
|
|
927
|
+
timestamp_min = []
|
|
928
|
+
timestamp_max = []
|
|
927
929
|
if not filenames:
|
|
928
930
|
filenames = ["Inertial"]
|
|
929
931
|
|
|
@@ -936,7 +938,6 @@ def load_ximu3(root_dir, filenames=None, inplace=False):
|
|
|
936
938
|
device_name = "trunk" if "trunk" in device_name.lower() else device_name
|
|
937
939
|
|
|
938
940
|
sessiondata[device_name] = dict()
|
|
939
|
-
|
|
940
941
|
for sensor_file in sensor_files: # loop through all csv files
|
|
941
942
|
sensor_name = path.split(sensor_file)[-1].split(".csv")[0] # sensor without path or extension
|
|
942
943
|
|
|
@@ -971,19 +972,21 @@ def load_ximu3(root_dir, filenames=None, inplace=False):
|
|
|
971
972
|
else:
|
|
972
973
|
print('No trunk sensor imported')
|
|
973
974
|
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
975
|
+
for sensor in sessiondata:
|
|
976
|
+
timestamp_min.append(sessiondata[sensor]['timestamp'].min().item())
|
|
977
|
+
timestamp_max.append(sessiondata[sensor]['timestamp'].max().item())
|
|
978
|
+
start_time = max(timestamp_min)
|
|
979
|
+
stop_time = min(timestamp_max)
|
|
978
980
|
|
|
979
981
|
for sensor in sessiondata:
|
|
980
982
|
sessiondata[sensor] = sessiondata[sensor][sessiondata[sensor]['timestamp'] >= start_time]
|
|
981
983
|
sessiondata[sensor] = sessiondata[sensor][sessiondata[sensor]['timestamp'] <= stop_time]
|
|
982
984
|
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
985
|
+
for sensor in sessiondata:
|
|
986
|
+
timestamp_min.append(sessiondata[sensor]['timestamp'].min().item())
|
|
987
|
+
timestamp_max.append(sessiondata[sensor]['timestamp'].max().item())
|
|
988
|
+
start_time = max(timestamp_min)
|
|
989
|
+
stop_time = min(timestamp_max)
|
|
987
990
|
|
|
988
991
|
for sensor in sessiondata:
|
|
989
992
|
sessiondata[sensor] = sessiondata[sensor][sessiondata[sensor]['timestamp'] >= start_time]
|