paradigma 1.0.4__tar.gz → 1.1.0__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.
- paradigma-1.1.0/PKG-INFO +229 -0
- paradigma-1.1.0/README.md +204 -0
- {paradigma-1.0.4 → paradigma-1.1.0}/pyproject.toml +19 -4
- paradigma-1.1.0/src/paradigma/__init__.py +15 -0
- {paradigma-1.0.4 → paradigma-1.1.0}/src/paradigma/classification.py +14 -14
- {paradigma-1.0.4 → paradigma-1.1.0}/src/paradigma/config.py +38 -29
- {paradigma-1.0.4 → paradigma-1.1.0}/src/paradigma/constants.py +10 -2
- {paradigma-1.0.4 → paradigma-1.1.0}/src/paradigma/feature_extraction.py +106 -75
- paradigma-1.1.0/src/paradigma/load.py +476 -0
- paradigma-1.1.0/src/paradigma/orchestrator.py +670 -0
- {paradigma-1.0.4 → paradigma-1.1.0}/src/paradigma/pipelines/gait_pipeline.py +488 -97
- {paradigma-1.0.4 → paradigma-1.1.0}/src/paradigma/pipelines/pulse_rate_pipeline.py +278 -46
- {paradigma-1.0.4 → paradigma-1.1.0}/src/paradigma/pipelines/pulse_rate_utils.py +176 -137
- paradigma-1.1.0/src/paradigma/pipelines/tremor_pipeline.py +594 -0
- paradigma-1.1.0/src/paradigma/prepare_data.py +409 -0
- {paradigma-1.0.4 → paradigma-1.1.0}/src/paradigma/preprocessing.py +345 -77
- {paradigma-1.0.4 → paradigma-1.1.0}/src/paradigma/segmenting.py +57 -42
- {paradigma-1.0.4 → paradigma-1.1.0}/src/paradigma/testing.py +14 -9
- {paradigma-1.0.4 → paradigma-1.1.0}/src/paradigma/util.py +36 -22
- paradigma-1.0.4/PKG-INFO +0 -140
- paradigma-1.0.4/README.md +0 -116
- paradigma-1.0.4/src/paradigma/__init__.py +0 -6
- paradigma-1.0.4/src/paradigma/pipelines/tremor_pipeline.py +0 -374
- {paradigma-1.0.4 → paradigma-1.1.0}/LICENSE +0 -0
- {paradigma-1.0.4 → paradigma-1.1.0}/src/paradigma/assets/gait_detection_clf_package.pkl +0 -0
- {paradigma-1.0.4 → paradigma-1.1.0}/src/paradigma/assets/gait_filtering_clf_package.pkl +0 -0
- {paradigma-1.0.4 → paradigma-1.1.0}/src/paradigma/assets/ppg_quality_clf_package.pkl +0 -0
- {paradigma-1.0.4 → paradigma-1.1.0}/src/paradigma/assets/tremor_detection_clf_package.pkl +0 -0
- {paradigma-1.0.4 → paradigma-1.1.0}/src/paradigma/pipelines/__init__.py +0 -0
paradigma-1.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: paradigma
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: ParaDigMa - A toolbox for deriving Parkinson's disease Digital Markers from real-life wrist sensor data
|
|
5
|
+
License: Apache-2.0
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Author: Erik Post
|
|
8
|
+
Author-email: erik.post@radboudumc.nl
|
|
9
|
+
Requires-Python: >=3.11,<4.0
|
|
10
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Requires-Dist: avro (>=1.12.1,<2.0.0)
|
|
17
|
+
Requires-Dist: nbconvert (>=7.16.6,<8.0.0)
|
|
18
|
+
Requires-Dist: pandas (>=2.1.4,<3.0.0)
|
|
19
|
+
Requires-Dist: pyarrow (>=22.0.0,<23.0.0)
|
|
20
|
+
Requires-Dist: python-dateutil (>=2.9.0.post0,<3.0.0)
|
|
21
|
+
Requires-Dist: scikit-learn (>=1.3.2,<1.6.1)
|
|
22
|
+
Requires-Dist: tsdf (>=0.6.1,<0.7.0)
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
<p align="center">
|
|
26
|
+
<img src="https://raw.githubusercontent.com/biomarkersParkinson/paradigma/main/docs/source/_static/img/paradigma-logo-banner.png" alt="ParaDigMa logo"/>
|
|
27
|
+
</p>
|
|
28
|
+
|
|
29
|
+
| Badges | |
|
|
30
|
+
|:----:|----|
|
|
31
|
+
| **Packages and Releases** | [](https://github.com/biomarkersparkinson/paradigma/releases/latest) [](https://pypi.python.org/pypi/paradigma/) [](https://research-software-directory.org/software/paradigma) |
|
|
32
|
+
| **DOI** | [](https://doi.org/10.5281/zenodo.13838392) |
|
|
33
|
+
| **Build Status** | [](https://www.python.org/downloads/) [](https://github.com/biomarkersParkinson/paradigma/actions/workflows/build-and-test.yml) [](https://github.com/biomarkersParkinson/paradigma/actions/workflows/pages/pages-build-deployment) |
|
|
34
|
+
| **License** | [](https://github.com/biomarkersparkinson/paradigma/blob/main/LICENSE) |
|
|
35
|
+
|
|
36
|
+
## Overview
|
|
37
|
+
|
|
38
|
+
ParaDigMa (Parkinson's disease Digital Markers) is a Python toolbox for extracting validated digital biomarkers from wrist sensor data in Parkinson's disease. It processes accelerometer, gyroscope, and PPG signals collected during passive monitoring in daily life.
|
|
39
|
+
|
|
40
|
+
**Key Features:**
|
|
41
|
+
- Arm swing during gait analysis
|
|
42
|
+
- Tremor analysis
|
|
43
|
+
- Pulse rate analysis
|
|
44
|
+
- Scientifically validated in peer-reviewed publications
|
|
45
|
+
- Modular, extensible architecture for custom analyses
|
|
46
|
+
|
|
47
|
+
## Quick Start
|
|
48
|
+
|
|
49
|
+
### Installation
|
|
50
|
+
|
|
51
|
+
**For regular use:**
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install paradigma
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Requires Python 3.11+.
|
|
58
|
+
|
|
59
|
+
**For development or running tutorials:**
|
|
60
|
+
|
|
61
|
+
Example data requires git-lfs. See the [installation guide](https://biomarkersparkinson.github.io/paradigma/guides/installation.html) for setup instructions.
|
|
62
|
+
|
|
63
|
+
### Basic Usage
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
from paradigma.orchestrator import run_paradigma
|
|
67
|
+
|
|
68
|
+
# Example 1: Single DataFrame with default output directory
|
|
69
|
+
results = run_paradigma(
|
|
70
|
+
dfs=df,
|
|
71
|
+
pipelines=['gait', 'tremor'],
|
|
72
|
+
watch_side='left', # Required for gait pipeline
|
|
73
|
+
save_intermediate=['quantification', 'aggregation'] # Saves to ./output by default
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Example 2: Multiple DataFrames as list (assigned to 'df_1', 'df_2', etc.)
|
|
77
|
+
results = run_paradigma(
|
|
78
|
+
dfs=[df1, df2, df3],
|
|
79
|
+
pipelines=['gait', 'tremor'],
|
|
80
|
+
output_dir="./results", # Custom output directory
|
|
81
|
+
watch_side='left',
|
|
82
|
+
save_intermediate=['quantification', 'aggregation']
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
# Example 3: Dictionary of DataFrames (custom segment/file names)
|
|
86
|
+
results = run_paradigma(
|
|
87
|
+
dfs={'morning_session': df1, 'evening_session': df2},
|
|
88
|
+
pipelines=['gait', 'tremor'],
|
|
89
|
+
watch_side='right',
|
|
90
|
+
save_intermediate=[] # No files saved - results only in memory
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# Example 4: Load from data directory
|
|
94
|
+
results = run_paradigma(
|
|
95
|
+
data_path='./my_data',
|
|
96
|
+
pipelines=['gait', 'tremor'],
|
|
97
|
+
watch_side='left',
|
|
98
|
+
file_pattern='*.parquet',
|
|
99
|
+
save_intermediate=['quantification', 'aggregation']
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# Access results (nested by pipeline)
|
|
103
|
+
gait_measures = results['quantifications']['gait']
|
|
104
|
+
tremor_measures = results['quantifications']['tremor']
|
|
105
|
+
gait_aggregates = results['aggregations']['gait']
|
|
106
|
+
tremor_aggregates = results['aggregations']['tremor']
|
|
107
|
+
|
|
108
|
+
# Check for errors
|
|
109
|
+
if results['errors']:
|
|
110
|
+
print(f"Warning: {len(results['errors'])} error(s) occurred")
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**See our [tutorials](https://biomarkersparkinson.github.io/paradigma/tutorials/index.html) for complete examples.**
|
|
114
|
+
|
|
115
|
+
## Pipelines
|
|
116
|
+
|
|
117
|
+
<p align="center">
|
|
118
|
+
<img src="https://raw.githubusercontent.com/biomarkersParkinson/paradigma/main/docs/source/_static/img/pipeline-architecture.png" alt="Pipeline architeecture"/>
|
|
119
|
+
</p>
|
|
120
|
+
|
|
121
|
+
### Validated Processing Pipelines
|
|
122
|
+
|
|
123
|
+
| Pipeline | Input sensors | Output week-level aggregation | Publications | Tutorial |
|
|
124
|
+
| ---- | ---- | ------- | ---- | ---- |
|
|
125
|
+
| **Arm swing during gait** | Accelerometer + Gyroscope | Typical, maximum & variability of arm swing range of motion | [Post 2025](https://doi.org/10.1186/s12984-025-01578-z), [Post 2026*](https://doi.org/10.64898/2026.01.06.26343500) | [Guide](https://biomarkersparkinson.github.io/paradigma/tutorials/gait_analysis) |
|
|
126
|
+
| **Tremor** | Gyroscope | % tremor time, typical & maximum tremor power | [Timmermans 2025a](https://doi.org/10.1038/s41531-025-01056-2), [Timmermans 2025b*](https://www.medrxiv.org/content/10.64898/2025.12.23.25342892v1) | [Guide](https://biomarkersparkinson.github.io/paradigma/tutorials/tremor_analysis) |
|
|
127
|
+
| **Pulse rate** | PPG (+ Accelerometer) | Resting & maximum pulse rate | [Veldkamp 2025*](https://doi.org/10.1101/2025.08.15.25333751) | [Guide](https://biomarkersparkinson.github.io/paradigma/tutorials/pulse_rate_analysis) |
|
|
128
|
+
|
|
129
|
+
*\* Indicates pre-print*
|
|
130
|
+
|
|
131
|
+
### Pipeline Architecture
|
|
132
|
+
|
|
133
|
+
ParaDigMa can best be understood by categorizing the sequential processes:
|
|
134
|
+
| Process | Description |
|
|
135
|
+
| ---- | ---- |
|
|
136
|
+
| **Preprocessing** | Preparing raw sensor signals for further processing |
|
|
137
|
+
| **Feature extraction** | Extracting features based on windowed sensor signals |
|
|
138
|
+
| **Classification** | Detecting segments of interest using validated classifiers (e.g., gait segments) |
|
|
139
|
+
| **Quantification** | Extracting specific measures from the detected segments (e.g., arm swing measures) |
|
|
140
|
+
| **Aggregation** | Aggregating the measures over a specific time period (e.g., week-level aggregates)
|
|
141
|
+
|
|
142
|
+
## Usage
|
|
143
|
+
### Documentation
|
|
144
|
+
|
|
145
|
+
- **[Tutorials](https://biomarkersparkinson.github.io/paradigma/tutorials/index.html)** - Step-by-step usage examples
|
|
146
|
+
- **[Installation Guide](https://biomarkersparkinson.github.io/paradigma/guides/installation.html)** - Setup and troubleshooting
|
|
147
|
+
- **[Sensor Requirements](https://biomarkersparkinson.github.io/paradigma/guides/sensor_requirements.html)** - Data specifications and compliance
|
|
148
|
+
- **[Supported Devices](https://biomarkersparkinson.github.io/paradigma/guides/supported_devices.html)** - Validated hardware
|
|
149
|
+
- **[Input Formats Guide](https://biomarkersparkinson.github.io/paradigma/guides/input_formats.html)** - Input format options and data loading
|
|
150
|
+
- **[Configuration Guide](https://biomarkersparkinson.github.io/paradigma/guides/config.html)** - Pipeline configuration
|
|
151
|
+
- **[Scientific Validation](https://biomarkersparkinson.github.io/paradigma/guides/validation.html)** - Validation studies and publications
|
|
152
|
+
- **[API Reference](https://biomarkersparkinson.github.io/paradigma/autoapi/paradigma/index.html)** - Complete API documentation
|
|
153
|
+
|
|
154
|
+
### Sensor Requirements & Supported Devices
|
|
155
|
+
|
|
156
|
+
ParaDigMa is designed for wrist sensor data collected during passive monitoring in persons with Parkinson's disease. While designed to work with any compliant device, it has been empirically validated on:
|
|
157
|
+
|
|
158
|
+
- **Verily Study Watch** (gait, tremor, pulse rate)
|
|
159
|
+
- **Axivity AX6** (gait, tremor)
|
|
160
|
+
- **Gait-up Physilog 4** (gait, tremor)
|
|
161
|
+
- **Empatica EmbracePlus** (data loading)
|
|
162
|
+
|
|
163
|
+
Please check before running the pipelines whether your sensor data complies with the requirements for the sensor configuration and context of use. See the [sensor requirements guide](https://biomarkersparkinson.github.io/paradigma/guides/sensor_requirements.html) for data specifications and the [supported devices guide](https://biomarkersparkinson.github.io/paradigma/guides/supported_devices.html) for device-specific setup instructions.
|
|
164
|
+
|
|
165
|
+
### Data Formats
|
|
166
|
+
|
|
167
|
+
ParaDigMa supports the following data formats:
|
|
168
|
+
|
|
169
|
+
- In-memory (recommended): **Pandas DataFrames** (see examples above)
|
|
170
|
+
- Data loading file extensions: **TSDF, Parquet, CSV, Pickle** and **several device-specific formats** (AVRO (Empatica), CWA (Axivity))
|
|
171
|
+
|
|
172
|
+
### Troubleshooting
|
|
173
|
+
|
|
174
|
+
For installation issues, see the [installation guide troubleshooting section](https://biomarkersparkinson.github.io/paradigma/guides/installation.html#troubleshooting).
|
|
175
|
+
|
|
176
|
+
For other issues, check our [issue tracker](https://github.com/biomarkersParkinson/paradigma/issues) or contact paradigma@radboudumc.nl.
|
|
177
|
+
|
|
178
|
+
## Scientific Validation
|
|
179
|
+
|
|
180
|
+
ParaDigMa pipelines are validated in peer-reviewed publications:
|
|
181
|
+
|
|
182
|
+
| Pipeline | Publication |
|
|
183
|
+
|----------|-------------|
|
|
184
|
+
| **Arm swing during gait** | Post et al. (2025, 2026) |
|
|
185
|
+
| **Tremor** | Timmermans et al. (2025a, 2025b) |
|
|
186
|
+
| **Pulse rate** | Veldkamp et al. (2025) |
|
|
187
|
+
|
|
188
|
+
See the [validation guide](https://biomarkersparkinson.github.io/paradigma/guides/validation.html) for full publication details.
|
|
189
|
+
|
|
190
|
+
## Contributing
|
|
191
|
+
|
|
192
|
+
We welcome contributions! Please see:
|
|
193
|
+
|
|
194
|
+
- [Contributing Guidelines](https://biomarkersparkinson.github.io/paradigma/contributing.html)
|
|
195
|
+
- [Code of Conduct](https://biomarkersparkinson.github.io/paradigma/conduct.html)
|
|
196
|
+
|
|
197
|
+
## Citation
|
|
198
|
+
|
|
199
|
+
If you use ParaDigMa in your research, please cite:
|
|
200
|
+
|
|
201
|
+
```bibtex
|
|
202
|
+
@software{paradigma2024,
|
|
203
|
+
author = {Post, Erik and Veldkamp, Kars and Timmermans, Nienke and
|
|
204
|
+
Soriano, Diogo Coutinho and Kasalica, Vedran and
|
|
205
|
+
Kok, Peter and Evers, Luc},
|
|
206
|
+
title = {ParaDigMa: Parkinson's disease Digital Markers},
|
|
207
|
+
year = {2024},
|
|
208
|
+
doi = {10.5281/zenodo.13838392},
|
|
209
|
+
url = {https://github.com/biomarkersParkinson/paradigma}
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## License
|
|
214
|
+
|
|
215
|
+
Licensed under the Apache License 2.0. See [LICENSE](LICENSE) for details.
|
|
216
|
+
|
|
217
|
+
## Acknowledgements
|
|
218
|
+
|
|
219
|
+
**Core Team**: Erik Post, Kars Veldkamp, Nienke Timmermans, Diogo Coutinho Soriano, Vedran Kasalica, Peter Kok, Twan van Laarhoven, Luc Evers
|
|
220
|
+
|
|
221
|
+
**Advisors**: Max Little, Jordan Raykov, Hayriye Cagnan, Bas Bloem
|
|
222
|
+
|
|
223
|
+
**Funding**: the initial release was funded by the Michael J Fox Foundation (grant #020425) and the Dutch Research Council (grants #ASDI.2020.060, #2023.010)
|
|
224
|
+
|
|
225
|
+
## Contact
|
|
226
|
+
|
|
227
|
+
- Email: paradigma@radboudumc.nl
|
|
228
|
+
- [Issue Tracker](https://github.com/biomarkersParkinson/paradigma/issues)
|
|
229
|
+
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/biomarkersParkinson/paradigma/main/docs/source/_static/img/paradigma-logo-banner.png" alt="ParaDigMa logo"/>
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
| Badges | |
|
|
6
|
+
|:----:|----|
|
|
7
|
+
| **Packages and Releases** | [](https://github.com/biomarkersparkinson/paradigma/releases/latest) [](https://pypi.python.org/pypi/paradigma/) [](https://research-software-directory.org/software/paradigma) |
|
|
8
|
+
| **DOI** | [](https://doi.org/10.5281/zenodo.13838392) |
|
|
9
|
+
| **Build Status** | [](https://www.python.org/downloads/) [](https://github.com/biomarkersParkinson/paradigma/actions/workflows/build-and-test.yml) [](https://github.com/biomarkersParkinson/paradigma/actions/workflows/pages/pages-build-deployment) |
|
|
10
|
+
| **License** | [](https://github.com/biomarkersparkinson/paradigma/blob/main/LICENSE) |
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
ParaDigMa (Parkinson's disease Digital Markers) is a Python toolbox for extracting validated digital biomarkers from wrist sensor data in Parkinson's disease. It processes accelerometer, gyroscope, and PPG signals collected during passive monitoring in daily life.
|
|
15
|
+
|
|
16
|
+
**Key Features:**
|
|
17
|
+
- Arm swing during gait analysis
|
|
18
|
+
- Tremor analysis
|
|
19
|
+
- Pulse rate analysis
|
|
20
|
+
- Scientifically validated in peer-reviewed publications
|
|
21
|
+
- Modular, extensible architecture for custom analyses
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
### Installation
|
|
26
|
+
|
|
27
|
+
**For regular use:**
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install paradigma
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Requires Python 3.11+.
|
|
34
|
+
|
|
35
|
+
**For development or running tutorials:**
|
|
36
|
+
|
|
37
|
+
Example data requires git-lfs. See the [installation guide](https://biomarkersparkinson.github.io/paradigma/guides/installation.html) for setup instructions.
|
|
38
|
+
|
|
39
|
+
### Basic Usage
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from paradigma.orchestrator import run_paradigma
|
|
43
|
+
|
|
44
|
+
# Example 1: Single DataFrame with default output directory
|
|
45
|
+
results = run_paradigma(
|
|
46
|
+
dfs=df,
|
|
47
|
+
pipelines=['gait', 'tremor'],
|
|
48
|
+
watch_side='left', # Required for gait pipeline
|
|
49
|
+
save_intermediate=['quantification', 'aggregation'] # Saves to ./output by default
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# Example 2: Multiple DataFrames as list (assigned to 'df_1', 'df_2', etc.)
|
|
53
|
+
results = run_paradigma(
|
|
54
|
+
dfs=[df1, df2, df3],
|
|
55
|
+
pipelines=['gait', 'tremor'],
|
|
56
|
+
output_dir="./results", # Custom output directory
|
|
57
|
+
watch_side='left',
|
|
58
|
+
save_intermediate=['quantification', 'aggregation']
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# Example 3: Dictionary of DataFrames (custom segment/file names)
|
|
62
|
+
results = run_paradigma(
|
|
63
|
+
dfs={'morning_session': df1, 'evening_session': df2},
|
|
64
|
+
pipelines=['gait', 'tremor'],
|
|
65
|
+
watch_side='right',
|
|
66
|
+
save_intermediate=[] # No files saved - results only in memory
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# Example 4: Load from data directory
|
|
70
|
+
results = run_paradigma(
|
|
71
|
+
data_path='./my_data',
|
|
72
|
+
pipelines=['gait', 'tremor'],
|
|
73
|
+
watch_side='left',
|
|
74
|
+
file_pattern='*.parquet',
|
|
75
|
+
save_intermediate=['quantification', 'aggregation']
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# Access results (nested by pipeline)
|
|
79
|
+
gait_measures = results['quantifications']['gait']
|
|
80
|
+
tremor_measures = results['quantifications']['tremor']
|
|
81
|
+
gait_aggregates = results['aggregations']['gait']
|
|
82
|
+
tremor_aggregates = results['aggregations']['tremor']
|
|
83
|
+
|
|
84
|
+
# Check for errors
|
|
85
|
+
if results['errors']:
|
|
86
|
+
print(f"Warning: {len(results['errors'])} error(s) occurred")
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**See our [tutorials](https://biomarkersparkinson.github.io/paradigma/tutorials/index.html) for complete examples.**
|
|
90
|
+
|
|
91
|
+
## Pipelines
|
|
92
|
+
|
|
93
|
+
<p align="center">
|
|
94
|
+
<img src="https://raw.githubusercontent.com/biomarkersParkinson/paradigma/main/docs/source/_static/img/pipeline-architecture.png" alt="Pipeline architeecture"/>
|
|
95
|
+
</p>
|
|
96
|
+
|
|
97
|
+
### Validated Processing Pipelines
|
|
98
|
+
|
|
99
|
+
| Pipeline | Input sensors | Output week-level aggregation | Publications | Tutorial |
|
|
100
|
+
| ---- | ---- | ------- | ---- | ---- |
|
|
101
|
+
| **Arm swing during gait** | Accelerometer + Gyroscope | Typical, maximum & variability of arm swing range of motion | [Post 2025](https://doi.org/10.1186/s12984-025-01578-z), [Post 2026*](https://doi.org/10.64898/2026.01.06.26343500) | [Guide](https://biomarkersparkinson.github.io/paradigma/tutorials/gait_analysis) |
|
|
102
|
+
| **Tremor** | Gyroscope | % tremor time, typical & maximum tremor power | [Timmermans 2025a](https://doi.org/10.1038/s41531-025-01056-2), [Timmermans 2025b*](https://www.medrxiv.org/content/10.64898/2025.12.23.25342892v1) | [Guide](https://biomarkersparkinson.github.io/paradigma/tutorials/tremor_analysis) |
|
|
103
|
+
| **Pulse rate** | PPG (+ Accelerometer) | Resting & maximum pulse rate | [Veldkamp 2025*](https://doi.org/10.1101/2025.08.15.25333751) | [Guide](https://biomarkersparkinson.github.io/paradigma/tutorials/pulse_rate_analysis) |
|
|
104
|
+
|
|
105
|
+
*\* Indicates pre-print*
|
|
106
|
+
|
|
107
|
+
### Pipeline Architecture
|
|
108
|
+
|
|
109
|
+
ParaDigMa can best be understood by categorizing the sequential processes:
|
|
110
|
+
| Process | Description |
|
|
111
|
+
| ---- | ---- |
|
|
112
|
+
| **Preprocessing** | Preparing raw sensor signals for further processing |
|
|
113
|
+
| **Feature extraction** | Extracting features based on windowed sensor signals |
|
|
114
|
+
| **Classification** | Detecting segments of interest using validated classifiers (e.g., gait segments) |
|
|
115
|
+
| **Quantification** | Extracting specific measures from the detected segments (e.g., arm swing measures) |
|
|
116
|
+
| **Aggregation** | Aggregating the measures over a specific time period (e.g., week-level aggregates)
|
|
117
|
+
|
|
118
|
+
## Usage
|
|
119
|
+
### Documentation
|
|
120
|
+
|
|
121
|
+
- **[Tutorials](https://biomarkersparkinson.github.io/paradigma/tutorials/index.html)** - Step-by-step usage examples
|
|
122
|
+
- **[Installation Guide](https://biomarkersparkinson.github.io/paradigma/guides/installation.html)** - Setup and troubleshooting
|
|
123
|
+
- **[Sensor Requirements](https://biomarkersparkinson.github.io/paradigma/guides/sensor_requirements.html)** - Data specifications and compliance
|
|
124
|
+
- **[Supported Devices](https://biomarkersparkinson.github.io/paradigma/guides/supported_devices.html)** - Validated hardware
|
|
125
|
+
- **[Input Formats Guide](https://biomarkersparkinson.github.io/paradigma/guides/input_formats.html)** - Input format options and data loading
|
|
126
|
+
- **[Configuration Guide](https://biomarkersparkinson.github.io/paradigma/guides/config.html)** - Pipeline configuration
|
|
127
|
+
- **[Scientific Validation](https://biomarkersparkinson.github.io/paradigma/guides/validation.html)** - Validation studies and publications
|
|
128
|
+
- **[API Reference](https://biomarkersparkinson.github.io/paradigma/autoapi/paradigma/index.html)** - Complete API documentation
|
|
129
|
+
|
|
130
|
+
### Sensor Requirements & Supported Devices
|
|
131
|
+
|
|
132
|
+
ParaDigMa is designed for wrist sensor data collected during passive monitoring in persons with Parkinson's disease. While designed to work with any compliant device, it has been empirically validated on:
|
|
133
|
+
|
|
134
|
+
- **Verily Study Watch** (gait, tremor, pulse rate)
|
|
135
|
+
- **Axivity AX6** (gait, tremor)
|
|
136
|
+
- **Gait-up Physilog 4** (gait, tremor)
|
|
137
|
+
- **Empatica EmbracePlus** (data loading)
|
|
138
|
+
|
|
139
|
+
Please check before running the pipelines whether your sensor data complies with the requirements for the sensor configuration and context of use. See the [sensor requirements guide](https://biomarkersparkinson.github.io/paradigma/guides/sensor_requirements.html) for data specifications and the [supported devices guide](https://biomarkersparkinson.github.io/paradigma/guides/supported_devices.html) for device-specific setup instructions.
|
|
140
|
+
|
|
141
|
+
### Data Formats
|
|
142
|
+
|
|
143
|
+
ParaDigMa supports the following data formats:
|
|
144
|
+
|
|
145
|
+
- In-memory (recommended): **Pandas DataFrames** (see examples above)
|
|
146
|
+
- Data loading file extensions: **TSDF, Parquet, CSV, Pickle** and **several device-specific formats** (AVRO (Empatica), CWA (Axivity))
|
|
147
|
+
|
|
148
|
+
### Troubleshooting
|
|
149
|
+
|
|
150
|
+
For installation issues, see the [installation guide troubleshooting section](https://biomarkersparkinson.github.io/paradigma/guides/installation.html#troubleshooting).
|
|
151
|
+
|
|
152
|
+
For other issues, check our [issue tracker](https://github.com/biomarkersParkinson/paradigma/issues) or contact paradigma@radboudumc.nl.
|
|
153
|
+
|
|
154
|
+
## Scientific Validation
|
|
155
|
+
|
|
156
|
+
ParaDigMa pipelines are validated in peer-reviewed publications:
|
|
157
|
+
|
|
158
|
+
| Pipeline | Publication |
|
|
159
|
+
|----------|-------------|
|
|
160
|
+
| **Arm swing during gait** | Post et al. (2025, 2026) |
|
|
161
|
+
| **Tremor** | Timmermans et al. (2025a, 2025b) |
|
|
162
|
+
| **Pulse rate** | Veldkamp et al. (2025) |
|
|
163
|
+
|
|
164
|
+
See the [validation guide](https://biomarkersparkinson.github.io/paradigma/guides/validation.html) for full publication details.
|
|
165
|
+
|
|
166
|
+
## Contributing
|
|
167
|
+
|
|
168
|
+
We welcome contributions! Please see:
|
|
169
|
+
|
|
170
|
+
- [Contributing Guidelines](https://biomarkersparkinson.github.io/paradigma/contributing.html)
|
|
171
|
+
- [Code of Conduct](https://biomarkersparkinson.github.io/paradigma/conduct.html)
|
|
172
|
+
|
|
173
|
+
## Citation
|
|
174
|
+
|
|
175
|
+
If you use ParaDigMa in your research, please cite:
|
|
176
|
+
|
|
177
|
+
```bibtex
|
|
178
|
+
@software{paradigma2024,
|
|
179
|
+
author = {Post, Erik and Veldkamp, Kars and Timmermans, Nienke and
|
|
180
|
+
Soriano, Diogo Coutinho and Kasalica, Vedran and
|
|
181
|
+
Kok, Peter and Evers, Luc},
|
|
182
|
+
title = {ParaDigMa: Parkinson's disease Digital Markers},
|
|
183
|
+
year = {2024},
|
|
184
|
+
doi = {10.5281/zenodo.13838392},
|
|
185
|
+
url = {https://github.com/biomarkersParkinson/paradigma}
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## License
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License 2.0. See [LICENSE](LICENSE) for details.
|
|
192
|
+
|
|
193
|
+
## Acknowledgements
|
|
194
|
+
|
|
195
|
+
**Core Team**: Erik Post, Kars Veldkamp, Nienke Timmermans, Diogo Coutinho Soriano, Vedran Kasalica, Peter Kok, Twan van Laarhoven, Luc Evers
|
|
196
|
+
|
|
197
|
+
**Advisors**: Max Little, Jordan Raykov, Hayriye Cagnan, Bas Bloem
|
|
198
|
+
|
|
199
|
+
**Funding**: the initial release was funded by the Michael J Fox Foundation (grant #020425) and the Dutch Research Council (grants #ASDI.2020.060, #2023.010)
|
|
200
|
+
|
|
201
|
+
## Contact
|
|
202
|
+
|
|
203
|
+
- Email: paradigma@radboudumc.nl
|
|
204
|
+
- [Issue Tracker](https://github.com/biomarkersParkinson/paradigma/issues)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "paradigma"
|
|
3
|
-
version = "1.0
|
|
3
|
+
version = "1.1.0"
|
|
4
4
|
description = "ParaDigMa - A toolbox for deriving Parkinson's disease Digital Markers from real-life wrist sensor data"
|
|
5
5
|
authors = [ "Erik Post <erik.post@radboudumc.nl>",
|
|
6
6
|
"Kars Veldkamp <kars.veldkamp@radboudumc.nl>",
|
|
@@ -17,10 +17,11 @@ readme = "README.md"
|
|
|
17
17
|
python = "^3.11"
|
|
18
18
|
pandas = "^2.1.4"
|
|
19
19
|
scikit-learn = ">=1.3.2,<1.6.1"
|
|
20
|
-
tsdf = "^0.
|
|
21
|
-
pytype = "^2024.4.11"
|
|
20
|
+
tsdf = "^0.6.1"
|
|
22
21
|
python-dateutil = "^2.9.0.post0"
|
|
23
22
|
nbconvert = "^7.16.6"
|
|
23
|
+
pyarrow = "^22.0.0"
|
|
24
|
+
avro = "^1.12.1"
|
|
24
25
|
|
|
25
26
|
[tool.poetry.group.testing.dependencies]
|
|
26
27
|
ipykernel = "^6.27.1"
|
|
@@ -39,7 +40,6 @@ myst-parser = "^4.0.0"
|
|
|
39
40
|
nbsphinx = "^0.9.6"
|
|
40
41
|
|
|
41
42
|
[tool.poetry.group.dev.dependencies]
|
|
42
|
-
pytype = "^2024.10.11"
|
|
43
43
|
notebook = "^7.4.5"
|
|
44
44
|
ipykernel = "^6.30.1"
|
|
45
45
|
pre-commit = "^4.3.0"
|
|
@@ -47,11 +47,26 @@ jupyter-client = "^8.6.3"
|
|
|
47
47
|
nbstripout = "^0.8.1"
|
|
48
48
|
nb-clean = "^4.0.1"
|
|
49
49
|
jupyter = "^1.1.1"
|
|
50
|
+
jupyterlab-widgets = "<=3.0.15"
|
|
50
51
|
|
|
51
52
|
[tool.poetry.scripts]
|
|
52
53
|
build-docs = "scripts.build_docs:main"
|
|
53
54
|
serve-docs = "scripts.serve_docs:main"
|
|
54
55
|
|
|
56
|
+
[tool.ruff]
|
|
57
|
+
line-length = 88
|
|
58
|
+
target-version = "py311"
|
|
59
|
+
|
|
60
|
+
[tool.ruff.lint]
|
|
61
|
+
select = [
|
|
62
|
+
"E", # pycodestyle errors
|
|
63
|
+
"W", # pycodestyle warnings
|
|
64
|
+
"F", # pyflakes
|
|
65
|
+
"I", # isort
|
|
66
|
+
"N", # pep8-naming
|
|
67
|
+
"UP", # pyupgrade
|
|
68
|
+
]
|
|
69
|
+
|
|
55
70
|
[build-system]
|
|
56
71
|
requires = ["poetry-core>=1.0.0"]
|
|
57
72
|
build-backend = "poetry.core.masonry.api"
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ParaDigMa: Parkinson Digital Biomarker Analysis Toolbox
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
# read version from installed package
|
|
6
|
+
from importlib.metadata import version
|
|
7
|
+
|
|
8
|
+
__version__ = version("paradigma")
|
|
9
|
+
|
|
10
|
+
# Import main pipeline functions for easy access
|
|
11
|
+
from .orchestrator import run_paradigma
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"run_paradigma",
|
|
15
|
+
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import pickle
|
|
2
2
|
from pathlib import Path
|
|
3
|
-
from typing import Any
|
|
3
|
+
from typing import Any
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
from sklearn.base import BaseEstimator
|
|
@@ -10,9 +10,9 @@ from sklearn.preprocessing import StandardScaler
|
|
|
10
10
|
class ClassifierPackage:
|
|
11
11
|
def __init__(
|
|
12
12
|
self,
|
|
13
|
-
classifier:
|
|
14
|
-
threshold:
|
|
15
|
-
scaler:
|
|
13
|
+
classifier: BaseEstimator | None = None,
|
|
14
|
+
threshold: float | None = None,
|
|
15
|
+
scaler: Any | None = None,
|
|
16
16
|
):
|
|
17
17
|
"""
|
|
18
18
|
Initialize the ClassifierPackage with a classifier, threshold, and scaler.
|
|
@@ -30,13 +30,13 @@ class ClassifierPackage:
|
|
|
30
30
|
self.threshold = threshold
|
|
31
31
|
self.scaler = scaler
|
|
32
32
|
|
|
33
|
-
def transform_features(self,
|
|
33
|
+
def transform_features(self, x) -> np.ndarray:
|
|
34
34
|
"""
|
|
35
35
|
Transform the input features using the scaler.
|
|
36
36
|
|
|
37
37
|
Parameters
|
|
38
38
|
----------
|
|
39
|
-
|
|
39
|
+
x : np.ndarray
|
|
40
40
|
The input features.
|
|
41
41
|
|
|
42
42
|
Return
|
|
@@ -45,8 +45,8 @@ class ClassifierPackage:
|
|
|
45
45
|
The transformed features.
|
|
46
46
|
"""
|
|
47
47
|
if not self.scaler:
|
|
48
|
-
return
|
|
49
|
-
return self.scaler.transform(
|
|
48
|
+
return x
|
|
49
|
+
return self.scaler.transform(x)
|
|
50
50
|
|
|
51
51
|
def update_scaler(self, x_train: np.ndarray) -> None:
|
|
52
52
|
"""
|
|
@@ -60,13 +60,13 @@ class ClassifierPackage:
|
|
|
60
60
|
scaler = StandardScaler()
|
|
61
61
|
self.scaler = scaler.fit(x_train)
|
|
62
62
|
|
|
63
|
-
def predict_proba(self,
|
|
63
|
+
def predict_proba(self, x) -> float:
|
|
64
64
|
"""
|
|
65
65
|
Make predictions using the classifier and apply the threshold.
|
|
66
66
|
|
|
67
67
|
Parameters
|
|
68
68
|
----------
|
|
69
|
-
|
|
69
|
+
x : np.ndarray
|
|
70
70
|
The input features.
|
|
71
71
|
|
|
72
72
|
Return
|
|
@@ -77,15 +77,15 @@ class ClassifierPackage:
|
|
|
77
77
|
"""
|
|
78
78
|
if not self.classifier:
|
|
79
79
|
raise ValueError("Classifier is not loaded.")
|
|
80
|
-
return self.classifier.predict_proba(
|
|
80
|
+
return self.classifier.predict_proba(x)[:, 1]
|
|
81
81
|
|
|
82
|
-
def predict(self,
|
|
82
|
+
def predict(self, x) -> int:
|
|
83
83
|
"""
|
|
84
84
|
Make predictions using the classifier and apply the threshold.
|
|
85
85
|
|
|
86
86
|
Parameters
|
|
87
87
|
----------
|
|
88
|
-
|
|
88
|
+
x : np.ndarray
|
|
89
89
|
The input features.
|
|
90
90
|
|
|
91
91
|
Return
|
|
@@ -96,7 +96,7 @@ class ClassifierPackage:
|
|
|
96
96
|
"""
|
|
97
97
|
if not self.classifier:
|
|
98
98
|
raise ValueError("Classifier is not loaded.")
|
|
99
|
-
return int(self.predict_proba(
|
|
99
|
+
return int(self.predict_proba(x) >= self.threshold)
|
|
100
100
|
|
|
101
101
|
def save(self, filepath: str | Path) -> None:
|
|
102
102
|
"""
|