KielMAT

KielMAT: Kiel Motion Analysis Toolbox - An Open-Source Python Toolbox for Analyzing Neurological Motion Data from Various Recording Modalities - Published in JOSS (2024)

https://github.com/neurogeriatricskiel/KielMAT

Science Score: 49.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
    Found 2 DOI reference(s) in README
  • Academic publication links
    Links to: ncbi.nlm.nih.gov
  • Committers with academic emails
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (13.1%) to scientific vocabulary

Keywords from Contributors

mesh
Last synced: 7 months ago · JSON representation

Repository

Python based toolbox for processing motion data

Basic Info
Statistics
  • Stars: 9
  • Watchers: 2
  • Forks: 3
  • Open Issues: 9
  • Releases: 3
Created about 3 years ago · Last pushed 12 months ago
Metadata Files
Readme Changelog Contributing License

README.md

codecov build docs Code style: black GitHub issues GitHub contributors lint-and-test PyPI - Python Version

Welcome to the KielMotionAnalysisToolbox (KielMAT). We are a Python based toolbox for processing motion data.

The toolbox is aimed at motion researchers who want to use Python-based open-source software to process their data. We have implemented validated algorithms in modules to process motion data, as shown in the table below:

Overview of Modules

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

Module Description Input Data Validation Dataset Event Type Output Parameters
Gait Sequence Detection Detects gait sequences 3D accelerations from lower back IMU Mobilise-D and KeepControl gait sequence -
Initial Contact Detection Detects initial and final contacts within each gait cycle 3D accelerations from lower back IMU Mobilise-D and KeepControl initial contact, final contact Temporal parameters (e.g., step time, stride time)
Physical Activity Monitoring Monitors physical activity levels 3D accelerations from wrist IMU Fair Park Ⅱ - Mean and duration of activity level
Postural Transition Detection Detects sit-to-stand and stand-to-sit transitions 3D acceleration and gyroscope data from lower back IMU KeepControl and SENSE-PARK sit-to-stand, stand-to-sit Spatio-temporal parameters (e.g., postural transition angle)
Turn Detection Detects turn movements 3D acceleration and gyroscope data from lower back IMU KeepControl and SENSE-PARK 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.

Value Unit
Acceleration m/s²
Angular Velocity deg/s
Velocity m/s
Distance m
Time s
Sampling Rate Hz

Installation

The toolbox has been released on pypi and can be installed via pip: bash pip install kielmat It requires Python 3.10 or higher.

Data classes

The idea is that various motion data can be loaded into our dedicated dataclass which rely on principles from the Motion-BIDS standard.

Data classes: conceptual framework

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. The BIDS format suggests that motion recording data from a single tracking system is organized in a single *_tracksys-<label>_motion.tsv file.

[!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 is likewise available as a pandas.DataFrame.

Similarly, if any events are available for the given recording, these are loaded into a single pandas.DataFrame for each tracking system as well. The events derived from the toolbox can be exported to a BIDS like '*_events.tsv' file.

Data classes: in practice

These concepts are translated into a KielMAT dataclass for each recording: KielMATRecording: ```mermaid classDiagram class KielMATRecording { data: dict[str, pd.DataFrame] channels: dict[str, pd.DataFrame] info: None | dict[str, Any] = None events: None | dict[str, pd.DataFrame] = None eventsinfo: None | dict[str, Any] = None addevents(trackingsystem, newevents) addinfo(key, value) exportevents(filepath, trackingsystem=None, filename=None, bidscompatible_fname=False) }

`` A recording consists of the motion data from one or more tracking systems, where each tracking system may consist motion data from one or more tracked points. Therefore, the motion data (KielMATRecording.data) are organized as a dictionary where the dictionary keys refer to the tracking systems, and the corresponding values the actual (raw) data as apandas.DataFrame. The description of data channels (KielMATRecording.channels`) is availabe as a dictionary with the same keys, and the values contain the channels description.

Example 1: Custom Dataset

You can create a KielMATRecording instance from your own motion data. Suppose you have motion data from your tracking system in a CSV file structured as follows:

python timestamp YourTrackedPoint_ACCEL_x YourTrackedPoint_ACCEL_y YourTrackedPoint_ACCEL_z YourTrackedPoint_GYRO_x YourTrackedPoint_GYRO_y YourTrackedPoint_GYRO_z 0 0.00 0.1 0.2 9.8 0.01 0.02 0.03 1 0.01 0.1 0.2 9.8 0.01 0.02 0.03 ... ... ... ... ... ... ... ...

You can create a KielMATRecording as follows:

```python import pandas as pd from kielmat.utils.kielmat_dataclass import KielMATRecording

Load your motion data into a pandas DataFrame

motiondata = pd.readcsv("pathtoyour_data.csv")

Calculate the sampling frequency using the timestamp column

timediff = motiondata["timestamp"].diff().dropna() # Calculate time differences samplingfrequency = 1 / timediff.mean() # Sampling frequency in Hz

Drop the timestamp column, as it is not needed in the motion data

motiondata = motiondata.drop(columns=["timestamp"])

Define the tracking system and tracked point names

trackingsystem = "YourTrackingSystem" trackedpoint = "YourTrackedPoint"

Create the data dictionary

data = {trackingsystem: motiondata}

Create the channels DataFrame

channelsinfo = pd.DataFrame({ "name": [f"{trackedpoint}ACCELx", f"{trackedpoint}ACCELy", f"{trackedpoint}ACCELz", f"{trackedpoint}GYROx", f"{trackedpoint}GYROy", f"{trackedpoint}GYROz"], "type": ["ACCEL", "ACCEL", "ACCEL", "GYRO", "GYRO", "GYRO"], "component": ["x", "y", "z", "x", "y", "z"], "trackedpoint": [trackedpoint] * 6, "units": ["g", "g", "g", "deg/s", "deg/s", "deg/s"], "samplingfrequency": [sampling_frequency] * 6 })

Create the channels dictionary

channels = {trackingsystem: channelsinfo}

Create a KielMATRecording instance

recording = KielMATRecording(data=data, channels=channels)

Print data and channels information

print(recording.data) print(recording.channels) python {'YourTrackingSystem': YourTrackedPointACCELx YourTrackedPointACCELy \ 0 0.1 0.2
1 0.1 0.2
... ... ...

  YourTrackedPoint_ACCEL_z  YourTrackedPoint_GYRO_x  YourTrackedPoint_GYRO_y  \

0 9.8 0.01 0.02
1 9.8 0.01 0.02
... ... ... ...

  YourTrackedPoint_GYRO_z  

0 0.03
1 0.03
... ... }

{'YourTrackingSystem': name component type trackedpoint units \ 0 YourTrackedPointACCELx x ACCEL YourTrackedPoint g
1 YourTrackedPoint
ACCELy y ACCEL YourTrackedPoint g
2 YourTrackedPoint
ACCELz z ACCEL YourTrackedPoint g
3 YourTrackedPoint
GYROx x GYRO YourTrackedPoint deg/s
4 YourTrackedPoint
GYROy y GYRO YourTrackedPoint deg/s
5 YourTrackedPoint
GYRO_z z GYRO YourTrackedPoint deg/s

  sampling_frequency  

0 100.0
1 100.0
2 100.0
3 100.0
4 100.0
5 100.0 } ```

Example 2: Mobilise-D Dataset

You can also load data from the Mobilise-D dataset, one of the datasets available in the toolbox. To do this, use the load_recording() function in the kielmat.datasets.mobilised.

```python import numpy as np from pathlib import Path from kielmat.datasets import mobilised

Load data from the Mobilise-D dataset

recording = mobilised.load_recording()

The keys of the recording

recording.dict.keys() dictkeys(['data', 'channels', 'info', 'events', 'eventsinfo'])

Print the data information

print(recording.data) {'SU': LowerBackACCELx LowerBackACCELy LowerBackACCELz \ 0 0.933334 0.084820 -0.302665
1 0.932675 0.084844 -0.300591
2 0.932350 0.082886 -0.310576
3 0.929716 0.081786 -0.303551
4 0.932825 0.077879 -0.308859
... ... ... ...
693471 -0.192553 -0.016052 -0.984290
693472 -0.189575 -0.016449 -0.988130
693473 -0.191176 -0.017954 -0.983820
693474 -0.189691 -0.014539 -0.986376
693475 -0.192993 -0.015306 -0.989452

           LowerBack_GYRO_x  LowerBack_GYRO_y  LowerBack_GYRO_z  \

0 5.600066 1.120697 0.489152
1 5.440734 1.401663 0.279477
2 5.196312 1.168802 0.435765
3 5.553083 1.116346 0.383447
4 5.437505 0.892803 -0.150115
... ... ... ...
693471 -0.225874 0.832856 0.704711
693472 -0.393438 0.598116 0.522755
693473 -0.430749 0.417541 0.282336
693474 -0.279277 0.559122 0.418693
693475 -0.563741 0.478618 0.411295

           LowerBack_MAGN_x  LowerBack_MAGN_y  LowerBack_MAGN_z  \

0 -93.972011 -25.023998 44.675028
1 -93.958012 -25.016007 44.610055
2 -93.946010 -25.000014 44.520078
3 -93.938007 -24.980018 44.411097
4 -93.935003 -24.957021 44.287113
... ... ... ...
693471 -50.718928 -36.997006 34.111960
693472 -50.649929 -37.003005 34.072972
693473 -50.579936 -37.008003 34.044986
693474 -50.515946 -37.011000 34.031004
693475 -50.460961 -37.010996 34.035025

           LowerBack_BARO_n/a  

0 990.394600
1 990.395100
2 990.395600
3 990.396199
4 990.396700
... ...
693471 990.204600
693472 990.204900
693473 990.205200
693474 990.205500
693475 990.205800

[693476 rows x 10 columns]}

Print the channels information

print(recording.channels) {'SU':
name type component trackedpoint units samplingfrequency 0 LowerBackACCELx Acc x LowerBack g 100.0 1 LowerBackACCELy Acc y LowerBack g 100.0 2 LowerBackACCELz Acc z LowerBack g 100.0 3 LowerBackANGVELx Gyr x LowerBack deg/s 100.0 4 LowerBackANGVELy Gyr y LowerBack deg/s 100.0 5 LowerBackANGVELz Gyr z LowerBack deg/s 100.0 6 LowerBackMAGNx Mag x LowerBack µT 100.0 7 LowerBackMAGNy Mag y LowerBack µT 100.0 8 LowerBackMAGNz Mag z LowerBack µT 100.0 9 LowerBackBAROn/a Bar n/a LowerBack hPa 100.0, } ```

[!NOTE] In the examples you find a tutorial (Load data into KielMAT) that explains the basics of the dataclass and how to work with them.

Contributing

We welcome contributions to KielMAT! Please refer to our contributing guide for more details.

Paper

The paper has been recently published in JOSS. You can find the paper here.

Authors

Masoud Abedinifar, Julius Welzel, Walter Maetzler, Clint Hansen & Robbin Romijnders

NeurogeriatricsLogo

Owner

  • Name: Neurogeriatrics Kiel
  • Login: neurogeriatricskiel
  • Kind: organization
  • Email: r.romijnders@neurologie.uni-kiel.de

GitHub Events

Total
  • Issues event: 4
  • Watch event: 3
  • Issue comment event: 12
  • Push event: 100
  • Pull request event: 1
  • Pull request review event: 11
  • Pull request review comment event: 13
  • Fork event: 2
  • Create event: 3
Last Year
  • Issues event: 4
  • Watch event: 3
  • Issue comment event: 12
  • Push event: 100
  • Pull request event: 1
  • Pull request review event: 11
  • Pull request review comment event: 13
  • Fork event: 2
  • Create event: 3

Committers

Last synced: 8 months ago

All Time
  • Total Commits: 731
  • Total Committers: 5
  • Avg Commits per committer: 146.2
  • Development Distribution Score (DDS): 0.611
Past Year
  • Commits: 64
  • Committers: 4
  • Avg Commits per committer: 16.0
  • Development Distribution Score (DDS): 0.438
Top Committers
Name Email Commits
masoudabedinifar 1****r 284
Julius Welzel j****l@g****m 252
rmndrs89 r****s@g****m 110
github-actions g****s@g****m 80
dependabot[bot] 4****] 5
Committer Domains (Top 20 + Academic)

Issues and Pull Requests

Last synced: 7 months ago

All Time
  • Total issues: 71
  • Total pull requests: 31
  • Average time to close issues: 22 days
  • Average time to close pull requests: 6 days
  • Total issue authors: 4
  • Total pull request authors: 3
  • Average comments per issue: 2.65
  • Average comments per pull request: 0.42
  • Merged pull requests: 30
  • Bot issues: 0
  • Bot pull requests: 5
Past Year
  • Issues: 9
  • Pull requests: 10
  • Average time to close issues: about 1 month
  • Average time to close pull requests: 4 days
  • Issue authors: 3
  • Pull request authors: 2
  • Average comments per issue: 1.89
  • Average comments per pull request: 0.8
  • Merged pull requests: 9
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • rmndrs89 (14)
  • JuliusWelzel (6)
  • masoudabedinifar (2)
  • davidpagnon (1)
Pull Request Authors
  • JuliusWelzel (21)
  • masoudabedinifar (7)
  • dependabot[bot] (5)
Top Labels
Issue Labels
enhancement (4) for 0.1.0 release (2) question (2) v1.0.0 (1) wontfix (1) help wanted (1) bug (1)
Pull Request Labels
dependencies (5) enhancement (2)

Packages

  • Total packages: 1
  • Total downloads:
    • pypi 25 last-month
  • Total dependent packages: 0
  • Total dependent repositories: 0
  • Total versions: 1
  • Total maintainers: 1
pypi.org: kielmat

The KielMotionAnalysisToolbox (KielMAT) is a Python-based toolbox for processing motion data.

  • Versions: 1
  • Dependent Packages: 0
  • Dependent Repositories: 0
  • Downloads: 25 Last month
Rankings
Dependent packages count: 10.6%
Average: 35.2%
Dependent repos count: 59.7%
Maintainers (1)
Last synced: 7 months ago