Skip to content

Commit 218949f

Browse files
revisions based on reviews from merge request (J.W.)
1 parent c366fd8 commit 218949f

File tree

10 files changed

+50
-141
lines changed

10 files changed

+50
-141
lines changed

docs/dataclass.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
In the following the KielMAT dataclass is described.
2-
The dataclass is used to store motion data in a standardized way. We provide some small set of import functions, each of which returns a `pandas.DataFrame` or a dict.
3-
User should easily be able to write their own import functions, to get the their data into the provided dataclass (this step might take some thinking).
4-
After the data is in the dataclass, running functions on the data from our toolbox should be really straight forward.
1+
In the following, the KielMAT dataclass is described. The dataclass is used to store motion data in a standardized way. We provide a small set of import functions, each of which returns a `pandas.DataFrame` or a dict. Users should easily be able to write their own import functions to get their data into the provided dataclass (this step might take some thinking). After the data is in the dataclass, running functions on the data from our toolbox should be really straightforward.
52

6-
## KielMAT data class
73
```mermaid
84
classDiagram
95
class KielMATRecording {

docs/index.md

Lines changed: 16 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -17,123 +17,27 @@ The toolbox is aimed at motion researchers who want to use Python-based open-sou
1717

1818
The table below provides an overview of key modules, their functionalities, input data, validation datasets, and outputs.
1919

20-
<div style="width: 100%; text-align: left; margin-top: 20px; background-color: transparent; padding: 0; border: none;">
21-
22-
<table style="width: 100%; border-collapse: collapse; font-size: 0.9em; background-color: transparent; border: none;">
23-
24-
<thead style="background-color: #f2f2f2;">
25-
<tr>
26-
<th style="padding: 10px; border-bottom: 1px solid #ddd;">Module</th>
27-
<th style="padding: 10px; border-bottom: 1px solid #ddd;">Description</th>
28-
<th style="padding: 10px; border-bottom: 1px solid #ddd;">Input Data</th>
29-
<th style="padding: 10px; border-bottom: 1px solid #ddd;">Validation Dataset</th>
30-
<th style="padding: 10px; border-bottom: 1px solid #ddd;">Event Type</th>
31-
<th style="padding: 10px; border-bottom: 1px solid #ddd;">Output Parameters</th>
32-
</tr>
33-
</thead>
34-
35-
<tbody>
36-
<tr>
37-
<td style="padding: 8px;"><a href="https://neurogeriatricskiel.github.io/KielMAT/modules/gsd/">Gait Sequence Detection</a></td>
38-
<td style="padding: 8px;">Detects gait sequences</td>
39-
<td style="padding: 8px;">3D accelerations from lower back IMU</td>
40-
<td style="padding: 8px;"><a href="https://neurogeriatricskiel.github.io/KielMAT/datasets/mobilised/">Mobilise-D</a> and <a href="https://neurogeriatricskiel.github.io/KielMAT/datasets/keepcontrol/">KeepControl</a></td>
41-
<td style="padding: 8px;">gait sequence</td>
42-
<td style="padding: 8px;">-</td>
43-
</tr>
44-
45-
<tr>
46-
<td style="padding: 8px;"><a href="https://neurogeriatricskiel.github.io/KielMAT/modules/icd/">Initial Contact Detection</a></td>
47-
<td style="padding: 8px;">Detects initial and final contacts within each gait cycle</td>
48-
<td style="padding: 8px;">3D accelerations from lower back IMU</td>
49-
<td style="padding: 8px;"><a href="https://neurogeriatricskiel.github.io/KielMAT/datasets/mobilised/">Mobilise-D</a> and <a href="https://neurogeriatricskiel.github.io/KielMAT/datasets/keepcontrol/">KeepControl</a></td>
50-
<td style="padding: 8px;">initial contact, final contact</td>
51-
<td style="padding: 8px;">Temporal parameters (e.g., step time, stride time)</td>
52-
</tr>
53-
54-
<tr>
55-
<td style="padding: 8px;"><a href="https://neurogeriatricskiel.github.io/KielMAT/modules/pam/">Physical Activity Monitoring</a></td>
56-
<td style="padding: 8px;">Monitors physical activity levels</td>
57-
<td style="padding: 8px;">3D accelerations from wrist IMU</td>
58-
<td style="padding: 8px;"><a href="https://www.fairpark2.eu/">Fair Park Ⅱ</a></td>
59-
<td style="padding: 8px;">-</td>
60-
<td style="padding: 8px;">Mean and duration of activity level</td>
61-
</tr>
62-
63-
<tr>
64-
<td style="padding: 8px;"><a href="https://neurogeriatricskiel.github.io/KielMAT/modules/ptd/">Postural Transition Detection</a></td>
65-
<td style="padding: 8px;">Detects sit-to-stand and stand-to-sit transitions</td>
66-
<td style="padding: 8px;">3D acceleration and gyroscope data from lower back IMU</td>
67-
<td style="padding: 8px;"><a href="https://neurogeriatricskiel.github.io/KielMAT/datasets/keepcontrol/">KeepControl</a> and <a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC4460963/">SENSE-PARK</a></td>
68-
<td style="padding: 8px;">sit-to-stand, stand-to-sit</td>
69-
<td style="padding: 8px;">Spatio-temporal parameters (e.g., postural transition angle)</td>
70-
</tr>
71-
72-
<tr>
73-
<td style="padding: 8px;"><a href="https://neurogeriatricskiel.github.io/KielMAT/modules/td/">Turn Detection</a></td>
74-
<td style="padding: 8px;">Detects turn movements</td>
75-
<td style="padding: 8px;">3D acceleration and gyroscope data from lower back IMU</td>
76-
<td style="padding: 8px;"><a href="https://neurogeriatricskiel.github.io/KielMAT/datasets/keepcontrol/">KeepControl</a> and <a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC4460963/">SENSE-PARK</a></td>
77-
<td style="padding: 8px;">turn</td>
78-
<td style="padding: 8px;">Spatio-temporal parameters (e.g., turn angle)</td>
79-
</tr>
80-
81-
</tbody>
82-
</table>
83-
</div>
20+
| Module | Description | Input Data | Validation Dataset | Event Type | Output Parameters |
21+
|--------|-------------|------------|--------------------|------------|-------------------|
22+
| [Gait Sequence Detection](https://neurogeriatricskiel.github.io/KielMAT/modules/gsd/) | Detects gait sequences | 3D accelerations from lower back IMU | [Mobilise-D](https://neurogeriatricskiel.github.io/KielMAT/datasets/mobilised/) and [KeepControl](https://neurogeriatricskiel.github.io/KielMAT/datasets/keepcontrol/) | gait sequence | - |
23+
| [Initial Contact Detection](https://neurogeriatricskiel.github.io/KielMAT/modules/icd/) | Detects initial and final contacts within each gait cycle | 3D accelerations from lower back IMU | [Mobilise-D](https://neurogeriatricskiel.github.io/KielMAT/datasets/mobilised/) and [KeepControl](https://neurogeriatricskiel.github.io/KielMAT/datasets/keepcontrol/) | initial contact, final contact | Temporal parameters (e.g., step time, stride time) |
24+
| [Physical Activity Monitoring](https://neurogeriatricskiel.github.io/KielMAT/modules/pam/) | Monitors physical activity levels | 3D accelerations from wrist IMU | [Fair Park Ⅱ](https://www.fairpark2.eu/) | - | Mean and duration of activity level |
25+
| [Postural Transition Detection](https://neurogeriatricskiel.github.io/KielMAT/modules/ptd/) | Detects sit-to-stand and stand-to-sit transitions | 3D acceleration and gyroscope data from lower back IMU | [KeepControl](https://neurogeriatricskiel.github.io/KielMAT/datasets/keepcontrol/) and [SENSE-PARK](https://pmc.ncbi.nlm.nih.gov/articles/PMC4460963/) | sit-to-stand, stand-to-sit | Spatio-temporal parameters (e.g., postural transition angle) |
26+
| [Turn Detection](https://neurogeriatricskiel.github.io/KielMAT/modules/td/) | Detects turn movements | 3D acceleration and gyroscope data from lower back IMU | [KeepControl](https://neurogeriatricskiel.github.io/KielMAT/datasets/keepcontrol/) and [SENSE-PARK](https://pmc.ncbi.nlm.nih.gov/articles/PMC4460963/) | turn | Spatio-temporal parameters (e.g., turn angle) |
8427

8528

8629
## Units
8730

8831
The table below provides an overview of commonly used value types and their corresponding units. Before starting work with modules in the toolbox, ensure that all data is in standard SI units as specified. This ensures compatibility with the algorithms, which are designed to expect inputs in these units.
8932

90-
<div style="width: 50%; text-align: left; margin-top: 20px; overflow: hidden; padding: 0; background-color: transparent;">
91-
92-
<table style="width: 100%; border-collapse: collapse; font-size: 0.9em; border: none; background-color: transparent;">
93-
94-
<thead style="background-color: #f2f2f2;">
95-
<tr>
96-
<th style="padding: 10px; border-bottom: 1px solid #ddd;">Value</th>
97-
<th style="padding: 10px; border-bottom: 1px solid #ddd;">Unit</th>
98-
</tr>
99-
</thead>
100-
101-
<tbody>
102-
<tr>
103-
<td style="padding: 8px;">Acceleration</td>
104-
<td style="padding: 8px;">m/s²</td>
105-
</tr>
106-
107-
<tr>
108-
<td style="padding: 8px;">Angular Velocity</td>
109-
<td style="padding: 8px;">deg/s</td>
110-
</tr>
111-
112-
<tr>
113-
<td style="padding: 8px;">Velocity</td>
114-
<td style="padding: 8px;">m/s</td>
115-
</tr>
116-
117-
<tr>
118-
<td style="padding: 8px;">Distance</td>
119-
<td style="padding: 8px;">m</td>
120-
</tr>
121-
122-
<tr>
123-
<td style="padding: 8px;">Time</td>
124-
<td style="padding: 8px;">s</td>
125-
</tr>
126-
127-
<tr>
128-
<td style="padding: 8px;">Sampling Rate</td>
129-
<td style="padding: 8px;">Hz</td>
130-
</tr>
131-
132-
</tbody>
133-
</table>
134-
</div>
135-
136-
33+
| Value | Unit | Channel Type |
34+
|-------------------|--------|---------------|
35+
| Acceleration | m/s² | ACCEL |
36+
| Angular Velocity | deg/s | GYRO |
37+
| Velocity | m/s | VEL |
38+
| Distance | m | POS |
39+
| Time | s | |
40+
| Sampling Rate | Hz | |
13741

13842
## Installation
13943
The toolbox has been released on [pypi](https://pypi.org/project/kielmat/) and can be installed via pip:
@@ -149,7 +53,7 @@ The idea is that various motion data can be loaded into our dedicated dataclass
14953

15054
Motion data is recorded with many different systems and modalities, each with their own proprietary data format. KielMAT deals with this by organizing both data and metadata in a [BIDS-like format](https://bids-specification.readthedocs.io/en/stable/modality-specific-files/motion.html). The BIDS format suggests that [motion recording data](https://bids-specification.readthedocs.io/en/stable/modality-specific-files/motion.html#motion-recording-data) from a single tracking system is organized in a single `*_tracksys-<label>_motion.tsv` file.
15155

152-
> [!NOTE]
56+
> !!! note
15357
> A tracking system is defined as a group of motion channels that share hardware properties (the recording device) and software properties (the recording duration and number of samples).
15458
15559
In KielMAT, data from a single tracking system is therefore loaded into a single `pandas.DataFrame`. The column headers of this `pandas.DataFrame` refer to the channels, and the corresponding [channels information](https://bids-specification.readthedocs.io/en/stable/modality-specific-files/motion.html#channels-description-_channelstsv) is likewise available as a `pandas.DataFrame`.

kielmat/datasets/keepcontrol.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from kielmat.utils.kielmat_dataclass import REQUIRED_COLUMNS
88
import logging
99
import warnings
10+
from tqdm import tqdm
1011

1112
# Dict of valid tracked points for the Keep Control dataset for each tracking system
1213
VALID_TRACKED_POINTS = {
@@ -84,6 +85,7 @@
8485

8586

8687
def fetch_dataset(
88+
progressbar: bool = True,
8789
dataset_path: str | Path = Path(__file__).parent / "_keepcontrol",
8890
) -> None:
8991
"""Fetch the Keep Control dataset from the OpenNeuro repository.
@@ -104,6 +106,10 @@ def fetch_dataset(
104106
dataset="ds005258", # this is the example Keep Control dataset on OpenNeuro, maintained by Julius Welzel
105107
target_dir=dataset_path,
106108
)
109+
110+
else:
111+
if progressbar:
112+
print("Dataset already downloaded, skipping download.")
107113
return
108114

109115

kielmat/modules/ptd/_pham.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def __init__(
8888
cutoff_freq_hz (float, optional): Cutoff frequency for low-pass Butterworth filer. Default is 5.0.
8989
thr_accel_var (float): Threshold value for identifying periods where the acceleartion variance is low. Default is 0.5.
9090
thr_gyro_var (float): Threshold value for identifying periods where the gyro variance is low. Default is 2e-4.
91-
min_turn_angle_deg (float): Minimum angle which is considered as postural transition in degrees. Default is 15.0.
91+
min_postural_transition_angle_deg (float): Minimum angle which is considered as postural transition in degrees. Default is 15.0.
9292
"""
9393
self.cutoff_freq_hz = cutoff_freq_hz
9494
self.thr_accel_var = thr_accel_var
@@ -104,7 +104,7 @@ def detect(
104104
tracking_system: Optional[str] = None,
105105
tracked_point: Optional[str] = None,
106106
plot_results: bool = False,
107-
) -> "PhamPosturalTransitionDetection":
107+
) -> pd.DataFrame:
108108
"""
109109
Detects postural transitions based on the input accelerometer and gyro data.
110110
@@ -460,7 +460,7 @@ def detect(
460460
# Return an instance of the class
461461
return self
462462

463-
def spatio_temporal_parameters(self) -> None:
463+
def spatio_temporal_parameters(self) -> pd.DataFrame:
464464
"""
465465
Extracts spatio-temporal parameters of the detected postural transitions.
466466

kielmat/modules/td/_pham.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def detect(
105105
tracking_system: Optional[str] = None,
106106
tracked_point: Optional[str] = None,
107107
plot_results: bool = False,
108-
) -> "PhamTurnDetection":
108+
) -> pd.DataFrame:
109109
"""
110110
Detects truns based on the input accelerometer and gyro data.
111111
@@ -450,7 +450,7 @@ def detect(
450450
# Return an instance of the class
451451
return self
452452

453-
def spatio_temporal_parameters(self) -> None:
453+
def spatio_temporal_parameters(self) -> pd.DataFrame:
454454
"""
455455
Extracts spatio-temporal parameters of the detected turns.
456456

kielmat/utils/importers.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from pathlib import Path
88

99

10-
def import_axivity(file_path: str, tracked_point: str):
10+
def import_axivity(file_path: str, tracked_point: str) -> tuple[pd.DataFrame, pd.DataFrame]:
1111
"""
1212
Imports Axivity data from the specified file path and
1313
return the data and channel formatted to be used in a KielMATRecording object.
@@ -52,7 +52,7 @@ def import_axivity(file_path: str, tracked_point: str):
5252
col_names = [f"{tracked_point}_{s}_{x}" for s in ["ACCEL"] for x in ["x", "y", "z"]]
5353

5454
# Create the channel dictionary following the BIDS naming conventions
55-
channels = {
55+
channels_dict = {
5656
"name": col_names,
5757
"component": ["x", "y", "z"] * (n_channels // 3),
5858
"type": ["ACCEL"] * (n_channels),
@@ -61,6 +61,9 @@ def import_axivity(file_path: str, tracked_point: str):
6161
"sampling_frequency": [info["ResampleRate"]] * n_channels,
6262
}
6363

64+
# Convert channels dictionary to a DataFrame
65+
channels = pd.DataFrame(channels_dict)
66+
6467
return data, channels
6568

6669

@@ -74,16 +77,16 @@ def import_mobilityLab(
7477
7578
Args:
7679
file_name (str or Path): The absolute or relative path to the data file.
77-
tracked_point (str or list of str]):
80+
tracked_points (str or list of str]):
7881
Defines for which tracked points data are to be returned.
7982
8083
Returns:
8184
dict, dict: The loaded data and channels as dictionaries.
8285
8386
Examples:
8487
>>> file_path = "/path/to/sensor_data.h5"
85-
>>> tracked_point = "Lumbar"
86-
>>> recording = import_mobilityLab(file_path, tracked_point)
88+
>>> tracked_points = "Lumbar"
89+
>>> recording = import_mobilityLab(file_path, tracked_points)
8790
"""
8891
# Convert file_name to a Path object if it is a string
8992
if isinstance(file_name, str):

kielmat/utils/kielmat_dataclass.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def __post_init__(self):
7777
# Validate channels when an instance is created
7878
self.validate_channels()
7979

80-
def validate_channels(self):
80+
def validate_channels(self) -> str:
8181
"""
8282
Validates the channel dataframes for each system.
8383

kielmat/utils/preprocessing.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,15 @@ def resample_interpolate(
7575
return resampled_signal
7676

7777

78-
def lowpass_filter(signal, method="savgol", order=None, **kwargs):
78+
def lowpass_filter(signal, method="savgol", order=None, **kwargs:dict):
7979
"""
8080
Apply a low-pass filter to the input signal.
8181
8282
Args:
8383
signal (numpy.ndarray): The input signal to be filtered.
8484
method (str): The filter method to use ("savgol", "butter", or "fir").
8585
order (int): The order of the filter (applicable for "butter" method).
86-
param (**kwargs): Additional keyword arguments specific to the Savitzky-Golay filter method or other methods.
86+
**kwargs: Additional keyword arguments specific to the Savitzky-Golay filter method or other methods.
8787
8888
Returns:
8989
filt_signal (numpy.ndarray): The filtered signal.
@@ -165,18 +165,17 @@ def lowpass_filter(signal, method="savgol", order=None, **kwargs):
165165
raise ValueError("Invalid filter method specified")
166166

167167

168-
def highpass_filter(signal, sampling_frequency=40, method="iir", **kwargs):
168+
def highpass_filter(signal, sampling_frequency=40, method="iir"):
169169
"""
170170
Apply a high-pass filter to the input signal using the specified method.
171171
172172
Args:
173173
signal (np.ndarray): The input signal to be filtered.
174174
sampling_frequency (float): The sampling frequency of the input signal.
175175
method (str): The filtering method to be used.
176-
**kwargs: Additional keyword arguments specific to the filtering method.
177176
178177
Returns:
179-
np.ndarray: The filtered signal.
178+
filtered_signal (np.ndarray): The filtered signal.
180179
181180
"""
182181
# Error handling for invalid input data
@@ -441,7 +440,7 @@ def find_consecutive_groups(input_signal):
441440
the start index of the group and the second column containing the end index of the group.
442441
443442
Parameters:
444-
input_array (ndarray): The input array.
443+
input_signal (ndarray): The input array.
445444
446445
Returns:
447446
ind (ndarray): A 2D array where each row represents a group of consecutive non-zero values.
@@ -1085,13 +1084,13 @@ def wavelet_decomposition(data, level, wavetype):
10851084

10861085

10871086
# Function for computing moving variance
1088-
def moving_var(data, window):
1087+
def moving_var(data, window) -> np.ndarray:
10891088
"""
10901089
Compute the centered moving variance.
10911090
10921091
Args:
1093-
Data (int) : Data to take the moving variance on window
1094-
Window size (int) : Window size for the moving variance.
1092+
data (int) : Data to take the moving variance on window
1093+
window size (int) : Window size for the moving variance.
10951094
10961095
Returns:
10971096
m_var (numpy.ndarray) : Moving variance

kielmat/utils/quaternion.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -292,10 +292,8 @@ def rotm2quat(R: np.ndarray, method: int | str = "auto") -> np.ndarray:
292292
293293
Args:
294294
R (np.ndarray): A rotation matrix with shape (3, 3).
295-
scalar_first (bool, optional): If True, sets the first element as the scalar part.
296-
If False, sets the last element as the scalar part is the last element. Default is True.
297-
channels_last (bool, optional): If True, assumes the channels are the last dimension.
298-
If False, assumes the channels are the first dimension. Default is True.
295+
method (int | str, optional): The method to use for conversion.
296+
Can be "auto" (default), "copysign", or a number (0, 1, 2, or 3).
299297
300298
Returns:
301299
np.ndarray: The quaternion corresponding to the rotation matrix.

mkdocs.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ nav:
4747
- Events in dataclass: examples/basic_02_events.md
4848
- Gait Sequence Detection: examples/modules_01_gsd.md
4949
- Initial Contact Detection: examples/modules_02_icd.md
50+
- Physical Activity Monitoring: examples/modules_03_pam.md
51+
- Postural Transition Detection: examples/modules_04_ptd.md
52+
- Turn Detection: examples/modules_05_td.md
5053
- Dataclass: dataclass.md
5154
- Modules:
5255
- modules/index.md

0 commit comments

Comments
 (0)