Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation Improvement #110

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions docs/dataclass.md
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mermaid dataclass diagram has not changed

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handled here: 0185add

Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
In the following the KielMAT dataclass is described.
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.
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).
After the data is in the dataclass, running functions on the data from our toolbox should be really straight forward.
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.

## KielMAT data class
```mermaid
classDiagram
class KielMATRecording {
Expand Down
128 changes: 16 additions & 112 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,123 +17,27 @@ The toolbox is aimed at motion researchers who want to use Python-based open-sou

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

<div style="width: 100%; text-align: left; margin-top: 20px; background-color: transparent; padding: 0; border: none;">

<table style="width: 100%; border-collapse: collapse; font-size: 0.9em; background-color: transparent; border: none;">

<thead style="background-color: #f2f2f2;">
<tr>
<th style="padding: 10px; border-bottom: 1px solid #ddd;">Module</th>
<th style="padding: 10px; border-bottom: 1px solid #ddd;">Description</th>
<th style="padding: 10px; border-bottom: 1px solid #ddd;">Input Data</th>
<th style="padding: 10px; border-bottom: 1px solid #ddd;">Validation Dataset</th>
<th style="padding: 10px; border-bottom: 1px solid #ddd;">Event Type</th>
<th style="padding: 10px; border-bottom: 1px solid #ddd;">Output Parameters</th>
</tr>
</thead>

<tbody>
<tr>
<td style="padding: 8px;"><a href="https://neurogeriatricskiel.github.io/KielMAT/modules/gsd/">Gait Sequence Detection</a></td>
<td style="padding: 8px;">Detects gait sequences</td>
<td style="padding: 8px;">3D accelerations from lower back IMU</td>
<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>
<td style="padding: 8px;">gait sequence</td>
<td style="padding: 8px;">-</td>
</tr>

<tr>
<td style="padding: 8px;"><a href="https://neurogeriatricskiel.github.io/KielMAT/modules/icd/">Initial Contact Detection</a></td>
<td style="padding: 8px;">Detects initial and final contacts within each gait cycle</td>
<td style="padding: 8px;">3D accelerations from lower back IMU</td>
<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>
<td style="padding: 8px;">initial contact, final contact</td>
<td style="padding: 8px;">Temporal parameters (e.g., step time, stride time)</td>
</tr>

<tr>
<td style="padding: 8px;"><a href="https://neurogeriatricskiel.github.io/KielMAT/modules/pam/">Physical Activity Monitoring</a></td>
<td style="padding: 8px;">Monitors physical activity levels</td>
<td style="padding: 8px;">3D accelerations from wrist IMU</td>
<td style="padding: 8px;"><a href="https://www.fairpark2.eu/">Fair Park Ⅱ</a></td>
<td style="padding: 8px;">-</td>
<td style="padding: 8px;">Mean and duration of activity level</td>
</tr>

<tr>
<td style="padding: 8px;"><a href="https://neurogeriatricskiel.github.io/KielMAT/modules/ptd/">Postural Transition Detection</a></td>
<td style="padding: 8px;">Detects sit-to-stand and stand-to-sit transitions</td>
<td style="padding: 8px;">3D acceleration and gyroscope data from lower back IMU</td>
<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>
<td style="padding: 8px;">sit-to-stand, stand-to-sit</td>
<td style="padding: 8px;">Spatio-temporal parameters (e.g., postural transition angle)</td>
</tr>

<tr>
<td style="padding: 8px;"><a href="https://neurogeriatricskiel.github.io/KielMAT/modules/td/">Turn Detection</a></td>
<td style="padding: 8px;">Detects turn movements</td>
<td style="padding: 8px;">3D acceleration and gyroscope data from lower back IMU</td>
<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>
<td style="padding: 8px;">turn</td>
<td style="padding: 8px;">Spatio-temporal parameters (e.g., turn angle)</td>
</tr>

</tbody>
</table>
</div>
| Module | Description | Input Data | Validation Dataset | Event Type | Output Parameters |
|--------|-------------|------------|--------------------|------------|-------------------|
| [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 | - |
| [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) |
| [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 |
| [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) |
| [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) |


## Units

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.

<div style="width: 50%; text-align: left; margin-top: 20px; overflow: hidden; padding: 0; background-color: transparent;">

<table style="width: 100%; border-collapse: collapse; font-size: 0.9em; border: none; background-color: transparent;">

<thead style="background-color: #f2f2f2;">
<tr>
<th style="padding: 10px; border-bottom: 1px solid #ddd;">Value</th>
<th style="padding: 10px; border-bottom: 1px solid #ddd;">Unit</th>
</tr>
</thead>

<tbody>
<tr>
<td style="padding: 8px;">Acceleration</td>
<td style="padding: 8px;">m/s²</td>
</tr>

<tr>
<td style="padding: 8px;">Angular Velocity</td>
<td style="padding: 8px;">deg/s</td>
</tr>

<tr>
<td style="padding: 8px;">Velocity</td>
<td style="padding: 8px;">m/s</td>
</tr>

<tr>
<td style="padding: 8px;">Distance</td>
<td style="padding: 8px;">m</td>
</tr>

<tr>
<td style="padding: 8px;">Time</td>
<td style="padding: 8px;">s</td>
</tr>

<tr>
<td style="padding: 8px;">Sampling Rate</td>
<td style="padding: 8px;">Hz</td>
</tr>

</tbody>
</table>
</div>


| Value | Unit | Channel Type |
|-------------------|--------|---------------|
| Acceleration | m/s² | ACCEL |
| Angular Velocity | deg/s | GYRO |
| Velocity | m/s | VEL |
| Distance | m | POS |
| Time | s | |
| Sampling Rate | Hz | |

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

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.

> [!NOTE]
> !!! note
> 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).

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`.
Expand Down
6 changes: 6 additions & 0 deletions kielmat/datasets/keepcontrol.py
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not add it to the code but remove the progress bar from the documentation

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is handled here: 73bad3e

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from kielmat.utils.kielmat_dataclass import REQUIRED_COLUMNS
import logging
import warnings
from tqdm import tqdm

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


def fetch_dataset(
progressbar: bool = True,
dataset_path: str | Path = Path(__file__).parent / "_keepcontrol",
) -> None:
"""Fetch the Keep Control dataset from the OpenNeuro repository.
Expand All @@ -104,6 +106,10 @@ def fetch_dataset(
dataset="ds005258", # this is the example Keep Control dataset on OpenNeuro, maintained by Julius Welzel
target_dir=dataset_path,
)

else:
if progressbar:
print("Dataset already downloaded, skipping download.")
return


Expand Down
6 changes: 3 additions & 3 deletions kielmat/modules/ptd/_pham.py
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does still not render properly:
image

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handled in 5514104

Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def __init__(
cutoff_freq_hz (float, optional): Cutoff frequency for low-pass Butterworth filer. Default is 5.0.
thr_accel_var (float): Threshold value for identifying periods where the acceleartion variance is low. Default is 0.5.
thr_gyro_var (float): Threshold value for identifying periods where the gyro variance is low. Default is 2e-4.
min_turn_angle_deg (float): Minimum angle which is considered as postural transition in degrees. Default is 15.0.
min_postural_transition_angle_deg (float): Minimum angle which is considered as postural transition in degrees. Default is 15.0.
"""
self.cutoff_freq_hz = cutoff_freq_hz
self.thr_accel_var = thr_accel_var
Expand All @@ -104,7 +104,7 @@ def detect(
tracking_system: Optional[str] = None,
tracked_point: Optional[str] = None,
plot_results: bool = False,
) -> "PhamPosturalTransitionDetection":
) -> pd.DataFrame:
"""
Detects postural transitions based on the input accelerometer and gyro data.

Expand Down Expand Up @@ -460,7 +460,7 @@ def detect(
# Return an instance of the class
return self

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

Expand Down
4 changes: 2 additions & 2 deletions kielmat/modules/td/_pham.py
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still not rendered properly:
image

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handled in 5514104

Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def detect(
tracking_system: Optional[str] = None,
tracked_point: Optional[str] = None,
plot_results: bool = False,
) -> "PhamTurnDetection":
) -> pd.DataFrame:
"""
Detects truns based on the input accelerometer and gyro data.

Expand Down Expand Up @@ -450,7 +450,7 @@ def detect(
# Return an instance of the class
return self

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

Expand Down
13 changes: 8 additions & 5 deletions kielmat/utils/importers.py
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have to change the docstring of this function

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handled here e6a4ab1

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from pathlib import Path


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

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

# Convert channels dictionary to a DataFrame
channels = pd.DataFrame(channels_dict)

return data, channels


Expand All @@ -74,16 +77,16 @@ def import_mobilityLab(

Args:
file_name (str or Path): The absolute or relative path to the data file.
tracked_point (str or list of str]):
tracked_points (str or list of str]):
Defines for which tracked points data are to be returned.

Returns:
dict, dict: The loaded data and channels as dictionaries.

Examples:
>>> file_path = "/path/to/sensor_data.h5"
>>> tracked_point = "Lumbar"
>>> recording = import_mobilityLab(file_path, tracked_point)
>>> tracked_points = "Lumbar"
>>> recording = import_mobilityLab(file_path, tracked_points)
"""
# Convert file_name to a Path object if it is a string
if isinstance(file_name, str):
Expand Down
2 changes: 1 addition & 1 deletion kielmat/utils/kielmat_dataclass.py
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not correct:
image

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handled here: 7026ba2

Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def __post_init__(self):
# Validate channels when an instance is created
self.validate_channels()

def validate_channels(self):
def validate_channels(self) -> str:
"""
Validates the channel dataframes for each system.

Expand Down
17 changes: 8 additions & 9 deletions kielmat/utils/preprocessing.py
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do **kwargs need to be specified as a dictionary? See here

Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,15 @@ def resample_interpolate(
return resampled_signal


def lowpass_filter(signal, method="savgol", order=None, **kwargs):
def lowpass_filter(signal, method="savgol", order=None, **kwargs:dict):
"""
Apply a low-pass filter to the input signal.

Args:
signal (numpy.ndarray): The input signal to be filtered.
method (str): The filter method to use ("savgol", "butter", or "fir").
order (int): The order of the filter (applicable for "butter" method).
param (**kwargs): Additional keyword arguments specific to the Savitzky-Golay filter method or other methods.
**kwargs: Additional keyword arguments specific to the Savitzky-Golay filter method or other methods.

Returns:
filt_signal (numpy.ndarray): The filtered signal.
Expand Down Expand Up @@ -165,18 +165,17 @@ def lowpass_filter(signal, method="savgol", order=None, **kwargs):
raise ValueError("Invalid filter method specified")


def highpass_filter(signal, sampling_frequency=40, method="iir", **kwargs):
def highpass_filter(signal, sampling_frequency=40, method="iir"):
"""
Apply a high-pass filter to the input signal using the specified method.

Args:
signal (np.ndarray): The input signal to be filtered.
sampling_frequency (float): The sampling frequency of the input signal.
method (str): The filtering method to be used.
**kwargs: Additional keyword arguments specific to the filtering method.

Returns:
np.ndarray: The filtered signal.
filtered_signal (np.ndarray): The filtered signal.

"""
# Error handling for invalid input data
Expand Down Expand Up @@ -441,7 +440,7 @@ def find_consecutive_groups(input_signal):
the start index of the group and the second column containing the end index of the group.

Parameters:
input_array (ndarray): The input array.
input_signal (ndarray): The input array.

Returns:
ind (ndarray): A 2D array where each row represents a group of consecutive non-zero values.
Expand Down Expand Up @@ -1085,13 +1084,13 @@ def wavelet_decomposition(data, level, wavetype):


# Function for computing moving variance
def moving_var(data, window):
def moving_var(data, window) -> np.ndarray:
"""
Compute the centered moving variance.

Args:
Data (int) : Data to take the moving variance on window
Window size (int) : Window size for the moving variance.
data (int) : Data to take the moving variance on window
window size (int) : Window size for the moving variance.

Returns:
m_var (numpy.ndarray) : Moving variance
Expand Down
6 changes: 2 additions & 4 deletions kielmat/utils/quaternion.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,10 +292,8 @@ def rotm2quat(R: np.ndarray, method: int | str = "auto") -> np.ndarray:

Args:
R (np.ndarray): A rotation matrix with shape (3, 3).
scalar_first (bool, optional): If True, sets the first element as the scalar part.
If False, sets the last element as the scalar part is the last element. Default is True.
channels_last (bool, optional): If True, assumes the channels are the last dimension.
If False, assumes the channels are the first dimension. Default is True.
method (int | str, optional): The method to use for conversion.
Can be "auto" (default), "copysign", or a number (0, 1, 2, or 3).

Returns:
np.ndarray: The quaternion corresponding to the rotation matrix.
Expand Down
3 changes: 3 additions & 0 deletions mkdocs.yml
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should not be example with the same number. Maybe we can name them 1-8

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handled here: 3a21b36

Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ nav:
- Events in dataclass: examples/basic_02_events.md
- Gait Sequence Detection: examples/modules_01_gsd.md
- Initial Contact Detection: examples/modules_02_icd.md
- Physical Activity Monitoring: examples/modules_03_pam.md
- Postural Transition Detection: examples/modules_04_ptd.md
- Turn Detection: examples/modules_05_td.md
- Dataclass: dataclass.md
- Modules:
- modules/index.md
Expand Down
Loading