jumpmetrics 0.1.1__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.
Files changed (80) hide show
  1. jumpmetrics-0.1.1/.dockerignore +53 -0
  2. jumpmetrics-0.1.1/.gitattributes +8 -0
  3. jumpmetrics-0.1.1/.github/workflows/draft-pdf.yml +20 -0
  4. jumpmetrics-0.1.1/.github/workflows/python-tests.yml +34 -0
  5. jumpmetrics-0.1.1/.gitignore +21 -0
  6. jumpmetrics-0.1.1/Dockerfile +41 -0
  7. jumpmetrics-0.1.1/LICENSE +21 -0
  8. jumpmetrics-0.1.1/MANIFEST.in +29 -0
  9. jumpmetrics-0.1.1/PKG-INFO +384 -0
  10. jumpmetrics-0.1.1/README.md +336 -0
  11. jumpmetrics-0.1.1/docker_example/input/F02_CTRL1.txt +40001 -0
  12. jumpmetrics-0.1.1/docker_example/output/displacement_curve.png +0 -0
  13. jumpmetrics-0.1.1/docker_example/output/force_curve.png +0 -0
  14. jumpmetrics-0.1.1/docker_example/output/jump_metrics.csv +2 -0
  15. jumpmetrics-0.1.1/docker_example/output/kinematic_data.csv +4001 -0
  16. jumpmetrics-0.1.1/docker_example/output/velocity_curve.png +0 -0
  17. jumpmetrics-0.1.1/docker_example/scripts/docker_example.py +77 -0
  18. jumpmetrics-0.1.1/docs/api/core.md +72 -0
  19. jumpmetrics-0.1.1/docs/api/events.md +75 -0
  20. jumpmetrics-0.1.1/docs/api/metrics.md +89 -0
  21. jumpmetrics-0.1.1/docs/api/signal_processing.md +67 -0
  22. jumpmetrics-0.1.1/docs/development/contributing.md +248 -0
  23. jumpmetrics-0.1.1/docs/development/testing.md +0 -0
  24. jumpmetrics-0.1.1/docs/index.md +45 -0
  25. jumpmetrics-0.1.1/example_images/acceleration.png +0 -0
  26. jumpmetrics-0.1.1/example_images/displacement.png +0 -0
  27. jumpmetrics-0.1.1/example_images/force.png +0 -0
  28. jumpmetrics-0.1.1/example_images/force_sqj.png +0 -0
  29. jumpmetrics-0.1.1/example_images/force_sqj2.png +0 -0
  30. jumpmetrics-0.1.1/example_images/velocity.png +0 -0
  31. jumpmetrics-0.1.1/paper/paper.bib +104 -0
  32. jumpmetrics-0.1.1/paper/paper.md +177 -0
  33. jumpmetrics-0.1.1/paper/paper.pdf +0 -0
  34. jumpmetrics-0.1.1/pixi.lock +9834 -0
  35. jumpmetrics-0.1.1/pyproject.toml +105 -0
  36. jumpmetrics-0.1.1/pytest.ini +2 -0
  37. jumpmetrics-0.1.1/src/jumpmetrics/__init__.py +7 -0
  38. jumpmetrics-0.1.1/src/jumpmetrics/core/__init__.py +0 -0
  39. jumpmetrics-0.1.1/src/jumpmetrics/core/io.py +254 -0
  40. jumpmetrics-0.1.1/src/jumpmetrics/core/jump_processing.py +150 -0
  41. jumpmetrics-0.1.1/src/jumpmetrics/core/processors.py +667 -0
  42. jumpmetrics-0.1.1/src/jumpmetrics/events/__init__.py +0 -0
  43. jumpmetrics-0.1.1/src/jumpmetrics/events/cmj_events.py +154 -0
  44. jumpmetrics-0.1.1/src/jumpmetrics/events/landing_events.py +17 -0
  45. jumpmetrics-0.1.1/src/jumpmetrics/events/sqj_events.py +164 -0
  46. jumpmetrics-0.1.1/src/jumpmetrics/metrics/__init__.py +0 -0
  47. jumpmetrics-0.1.1/src/jumpmetrics/metrics/metrics.py +174 -0
  48. jumpmetrics-0.1.1/src/jumpmetrics/signal_processing/__init__.py +0 -0
  49. jumpmetrics-0.1.1/src/jumpmetrics/signal_processing/filters.py +31 -0
  50. jumpmetrics-0.1.1/src/jumpmetrics/signal_processing/numerical.py +197 -0
  51. jumpmetrics-0.1.1/test_install.py +6 -0
  52. jumpmetrics-0.1.1/tests/KNOWN_TEST_LIMITATIONS.md +102 -0
  53. jumpmetrics-0.1.1/tests/core/test_core.py +411 -0
  54. jumpmetrics-0.1.1/tests/core/test_io.py +475 -0
  55. jumpmetrics-0.1.1/tests/core/test_processors_edge_cases.py +493 -0
  56. jumpmetrics-0.1.1/tests/events/__init__.py +1 -0
  57. jumpmetrics-0.1.1/tests/events/test_cmj_events.py +402 -0
  58. jumpmetrics-0.1.1/tests/events/test_landing_events.py +187 -0
  59. jumpmetrics-0.1.1/tests/events/test_sqj_events.py +383 -0
  60. jumpmetrics-0.1.1/tests/example_data/batch_processed_data.csv +497 -0
  61. jumpmetrics-0.1.1/tests/example_data/example_process_jump_trial_output.csv +2 -0
  62. jumpmetrics-0.1.1/tests/example_data/example_process_squat_jump_trial_output.csv +2 -0
  63. jumpmetrics-0.1.1/tests/example_data/kinematic_data/F02/CTRL2/group_cutoff.csv +3962 -0
  64. jumpmetrics-0.1.1/tests/example_data/kinematic_data/F02/CTRL2/group_cutoff_force_series.csv +3962 -0
  65. jumpmetrics-0.1.1/tests/example_data/kinematic_data/M07/CTRL1/group_cutoff.csv +4001 -0
  66. jumpmetrics-0.1.1/tests/example_data/kinematic_data/M07/CTRL1/group_cutoff_force_series.csv +4001 -0
  67. jumpmetrics-0.1.1/tests/example_data/kinematic_data/M15/CTRL1/group_cutoff.csv +4001 -0
  68. jumpmetrics-0.1.1/tests/example_data/kinematic_data/M15/CTRL1/group_cutoff_force_series.csv +4001 -0
  69. jumpmetrics-0.1.1/tests/example_data/p30_squat_jump_example_results.csv +2 -0
  70. jumpmetrics-0.1.1/tests/example_data/p31_squat_jump_example_results.csv +2 -0
  71. jumpmetrics-0.1.1/tests/example_data/raw_data/F02_CTRL1.txt +40001 -0
  72. jumpmetrics-0.1.1/tests/example_data/raw_data/F02_CTRL2_filtered.txt +3966 -0
  73. jumpmetrics-0.1.1/tests/example_data/raw_data/FHOC_P30_SQT300007.txt +20001 -0
  74. jumpmetrics-0.1.1/tests/example_data/raw_data/FHOC_P31_SQT900020.txt +20001 -0
  75. jumpmetrics-0.1.1/tests/example_data/raw_data/M07_CTRL1_filtered.txt +4727 -0
  76. jumpmetrics-0.1.1/tests/example_data/raw_data/M15_CTRL1_filtered.txt +4730 -0
  77. jumpmetrics-0.1.1/tests/metrics/__init__.py +1 -0
  78. jumpmetrics-0.1.1/tests/metrics/test_metrics.py +440 -0
  79. jumpmetrics-0.1.1/tests/signal_processing/test_filters.py +192 -0
  80. jumpmetrics-0.1.1/tests/signal_processing/test_numerical.py +273 -0
@@ -0,0 +1,53 @@
1
+ # Git
2
+ .git
3
+ .gitignore
4
+
5
+ # Python
6
+ __pycache__/
7
+ *.py[cod]
8
+ *$py.class
9
+ *.so
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ *.egg-info/
24
+ .installed.cfg
25
+ *.egg
26
+
27
+ # Environment
28
+ .env
29
+ .venv
30
+ env/
31
+ venv/
32
+ ENV/
33
+ env.bak/
34
+ venv.bak/
35
+ *.yml
36
+
37
+ # IDE
38
+ .idea/
39
+ .vscode/
40
+ *.swp
41
+ *.swo
42
+
43
+ # Project specific
44
+ analyses/
45
+ docs/
46
+ tests/
47
+ paper/
48
+ .pytest_cache/
49
+ docker_example/
50
+
51
+ # Docker
52
+ .dockerignore
53
+ Dockerfile
@@ -0,0 +1,8 @@
1
+ # Mark image directories as export-ignore so they don't get included in pip install
2
+ analyses export-ignore
3
+ *.png export-ignore
4
+ *.jpg export-ignore
5
+ *.jpeg export-ignore
6
+ *.gif export-ignore
7
+ # SCM syntax highlighting & preventing 3-way merges
8
+ pixi.lock merge=binary linguist-language=YAML linguist-generated=true
@@ -0,0 +1,20 @@
1
+ name: Draft PDF
2
+ on: [push]
3
+
4
+ jobs:
5
+ paper:
6
+ runs-on: ubuntu-latest
7
+ name: Paper Draft
8
+ steps:
9
+ - name: Checkout
10
+ uses: actions/checkout@v4
11
+ - name: Build draft PDF
12
+ uses: openjournals/openjournals-draft-action@master
13
+ with:
14
+ journal: joss
15
+ paper-path: paper/paper.md
16
+ - name: Upload
17
+ uses: actions/upload-artifact@v4
18
+ with:
19
+ name: paper
20
+ path: paper/paper.pdf
@@ -0,0 +1,34 @@
1
+ name: Python Tests
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ test:
7
+ name: Test on ${{ matrix.os }} with Python ${{ matrix.python-version }}
8
+ runs-on: ${{ matrix.os }}
9
+ strategy:
10
+ fail-fast: false
11
+ matrix:
12
+ os: [ubuntu-latest, windows-latest, macos-latest, macos-14]
13
+ python-version: ["3.10", "3.11", "3.12"]
14
+ exclude:
15
+ - os: macos-latest
16
+ python-version: "3.11"
17
+
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - name: Install Pixi
22
+ uses: prefix-dev/setup-pixi@v0.8.1
23
+ with:
24
+ pixi-version: v0.54.2
25
+ cache: true
26
+
27
+ - name: Install dependencies
28
+ run: pixi install
29
+
30
+ - name: Run tests
31
+ run: pixi run -e test test
32
+
33
+ - name: Run type checking
34
+ run: pixi run -e test typecheck
@@ -0,0 +1,21 @@
1
+ .DS_Store
2
+ __pycache__/
3
+ .pyc
4
+ dist/
5
+ *.egg-info/
6
+ local_dev/
7
+ .pytest_cache/
8
+ mypy_output.txt
9
+ flake8_output.txt
10
+
11
+ # Coverage reports
12
+ htmlcov/
13
+ .coverage
14
+ .coverage.*
15
+ coverage.xml
16
+ *.cover
17
+ .hypothesis/
18
+ # pixi environments
19
+ .pixi/*
20
+ !.pixi/config.toml
21
+ CLAUDE.md
@@ -0,0 +1,41 @@
1
+ # Use Python 3.10 as base image
2
+ FROM python:3.10-slim
3
+
4
+ # Set working directory
5
+ WORKDIR /app
6
+
7
+ # Install system dependencies
8
+ RUN apt-get update && apt-get install -y \
9
+ gcc \
10
+ && rm -rf /var/lib/apt/lists/*
11
+
12
+ # Copy only the necessary files for package installation
13
+ COPY jumpmetrics/ /app/jumpmetrics/
14
+ COPY setup.py /app/
15
+ COPY README.md /app/
16
+ COPY LICENSE /app/
17
+
18
+ # Update pip
19
+ RUN pip install --upgrade pip
20
+
21
+ # Install Python dependencies
22
+ RUN pip install --no-cache-dir \
23
+ pandas==2.0.* \
24
+ matplotlib \
25
+ scipy==1.14.* \
26
+ scikit-learn==1.3.* \
27
+ pip==23.* \
28
+ pyyaml
29
+
30
+ # Install the package in editable mode
31
+ RUN pip install -e .
32
+
33
+ # Create directories for data mounting
34
+ RUN mkdir -p /data/input /data/output
35
+
36
+ # Set environment variables
37
+ ENV PYTHONPATH=/app
38
+ ENV PYTHONUNBUFFERED=1
39
+
40
+ # Default command to start Python interpreter
41
+ CMD ["python"]
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Steven Hirsch
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # Include environment and documentation files
2
+ include env.yml
3
+ include readme.md
4
+
5
+ # Include any additional files you might want to distribute
6
+ include *.md
7
+ include LICENSE*
8
+
9
+ # Include any data files in the package
10
+
11
+ # Exclude development files
12
+ exclude .gitignore
13
+ exclude *.ipynb
14
+ exclude test_*.py
15
+ exclude *.pyc
16
+ exclude __pycache__
17
+ prune tests
18
+
19
+ # Exclude images and analyses when building package
20
+ prune analyses/*
21
+ exclude *.png
22
+ exclude *.jpg
23
+ exclude *.jpeg
24
+ exclude *.gif
25
+
26
+ # Exclude Docker-related files and examples
27
+ prune docker_example
28
+ exclude Dockerfile
29
+ exclude .dockerignore
@@ -0,0 +1,384 @@
1
+ Metadata-Version: 2.4
2
+ Name: jumpmetrics
3
+ Version: 0.1.1
4
+ Summary: A Python package for computing countermovement and squat jump events and metrics from force plate data
5
+ Project-URL: Homepage, https://github.com/stevenhirsch/force-plate-jump-analyses
6
+ Project-URL: Repository, https://github.com/stevenhirsch/force-plate-jump-analyses
7
+ Project-URL: Documentation, https://github.com/stevenhirsch/force-plate-jump-analyses/tree/main/docs
8
+ Project-URL: Bug Tracker, https://github.com/stevenhirsch/force-plate-jump-analyses/issues
9
+ Author-email: Steven Hirsch <stevehirsch94@gmail.com>
10
+ License: MIT License
11
+
12
+ Copyright (c) 2024 Steven Hirsch
13
+
14
+ Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ of this software and associated documentation files (the "Software"), to deal
16
+ in the Software without restriction, including without limitation the rights
17
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ copies of the Software, and to permit persons to whom the Software is
19
+ furnished to do so, subject to the following conditions:
20
+
21
+ The above copyright notice and this permission notice shall be included in all
22
+ copies or substantial portions of the Software.
23
+
24
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
+ SOFTWARE.
31
+ License-File: LICENSE
32
+ Keywords: biomechanics,countermovement jump,force plate,sports science,squat jump,vertical jump
33
+ Classifier: Development Status :: 4 - Beta
34
+ Classifier: Intended Audience :: Science/Research
35
+ Classifier: License :: OSI Approved :: MIT License
36
+ Classifier: Programming Language :: Python :: 3
37
+ Classifier: Programming Language :: Python :: 3.10
38
+ Classifier: Programming Language :: Python :: 3.11
39
+ Classifier: Programming Language :: Python :: 3.12
40
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
41
+ Requires-Python: >=3.10
42
+ Requires-Dist: matplotlib>=3.6.0
43
+ Requires-Dist: numpy>=2.0.0
44
+ Requires-Dist: pandas>=2.0.0
45
+ Requires-Dist: scikit-learn>=1.3.0
46
+ Requires-Dist: scipy>=1.14.0
47
+ Description-Content-Type: text/markdown
48
+
49
+ # JumpMetrics
50
+
51
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
52
+ [![Python Version](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
53
+
54
+ ## Overview
55
+
56
+ The `JumpMetrics` package is a completely free, open-source toolkit for analyzing force plate data during countermovement and squat (pause) jumps. The package provides comprehensive analyses to help in understanding various aspects of jump performance and mechanics and helps with batch processing jump trials.
57
+
58
+ ## Features
59
+ - Batch processing of countermovement jump and squat jump data from `.txt` files exported from force plates (e.g., NetForce).
60
+ - Signal processing and filtering.
61
+ - Automated data cropping, events, metrics, and visualization tools.
62
+ - Easy-to-use functions for detailed jump performance insights.
63
+ - Extensible framework for additional analysis and custom data processing.
64
+
65
+ ## Installation
66
+
67
+ ### Prerequisites
68
+ - **Python**: Ensure Python 3.10 or higher is installed.
69
+ - **pixi**: Install [pixi](https://pixi.sh/latest/) on your machine.
70
+
71
+ ### Option 1: Install via PyPI
72
+
73
+ *NOTE:* Pending upload to PyPI- This has not been completed yet, so skip Option 1 for now.
74
+
75
+ Simply run:
76
+ ```bash
77
+ pip install jumpmetrics
78
+ ```
79
+
80
+ or if using pixi, run:
81
+ ```bash
82
+ pixi add jumpmetrics
83
+ ```
84
+
85
+ ### Option 2: Direct Installation from GitHub (may be slow due to repo size)
86
+ Ensure that you have `pip` installed in your python environment. Then, just run:
87
+ ```bash
88
+ pip install git+https://github.com/stevenhirsch/force-plate-jump-analyses.git
89
+ ```
90
+
91
+ or if using pixi, run:
92
+ ```bash
93
+ pixi add git+https://github.com/stevenhirsch/force-plate-jump-analyses.git
94
+ ```
95
+
96
+
97
+ #### Method B: Using pip directly
98
+ 1. Clone the repository:
99
+ ```bash
100
+ git clone https://github.com/stevenhirsch/force-plate-jump-analyses.git
101
+ cd force-plate-jump-analyses
102
+ ```
103
+
104
+ 2. Build the package:
105
+ ```bash
106
+ pip install build
107
+ python -m build
108
+ ```
109
+
110
+ 3. Install the wheel file (adjust the filename to whichever version you have built):
111
+ ```bash
112
+ pip install dist/jumpmetrics-0.1.0-py3-none-any.whl
113
+ ```
114
+
115
+ After going through these steps, verify the installation:
116
+ ```bash
117
+ python test_install.py
118
+ ```
119
+
120
+ ### Option 3: Development Setup with pixi
121
+ 1. Clone the repository:
122
+ ```bash
123
+ git clone https://github.com/stevenhirsch/force-plate-jump-analyses.git
124
+ cd force-plate-jump-analyses
125
+ ```
126
+
127
+ 2. Create and activate the development environment:
128
+ ```bash
129
+ pixi install
130
+ pixi shell --feature dev
131
+ ```
132
+
133
+ This will set up a development environment with all necessary dependencies including:
134
+ - Core dependencies: pandas, matplotlib, scipy, scikit-learn
135
+ - Development tools: pytest, mypy, flake8, jupyter, ipython
136
+ - Visualization libraries: plotly, seaborn
137
+ - Build tools and utilities
138
+
139
+ The development environment provides additional tools for contributing to the project.
140
+
141
+ ### Available pixi Tasks
142
+
143
+ The project includes several predefined tasks that can be run using `pixi run <task-name>`:
144
+
145
+ #### Main Tasks (Default Environment)
146
+ - `verify`: Run installation verification test
147
+ - `batch_process_study_1`: Process data for study 1
148
+ - `batch_process_study_2`: Process data for study 2
149
+ - `batch_process_study_3`: Process data for study 3
150
+
151
+ #### Development Tasks
152
+ - `build`: Build the package distribution
153
+ - `lint`: Run flake8 linting on source code
154
+ - `clean`: Remove build artifacts and cache files
155
+ - `test`: Run pytest test suite
156
+ - `typecheck`: Run mypy type checking
157
+
158
+ Example usage:
159
+ ```bash
160
+ # Run tests
161
+ pixi run test
162
+
163
+ # Build the package
164
+ pixi run build
165
+
166
+ # Run linting
167
+ pixi run lint
168
+ ```
169
+
170
+ ### Option 4: Using Docker
171
+ For users who prefer Docker or desire a reproducible environment across different systems, we also provide a Dockerfile to easily set up and run jumpmetrics. This Dockerfile provides a way for you to separate your environment (the Docker image) from the analysis code (mounted scripts).
172
+
173
+ 1. Build the Docker image:
174
+ ```bash
175
+ docker build -t jumpmetrics .
176
+ ```
177
+
178
+ You can also add tags to this build:
179
+ ```bash
180
+ docker build -t jumpmetrics:v1.0 .
181
+ ```
182
+
183
+ 2. Create your analysis script. See an example at [docker_example/scripts/docker_example.py](/docker_example/scripts/docker_example.py).
184
+
185
+ 3. Run your analysis with Docker:
186
+ ```bash
187
+ docker run -it --rm \
188
+ -v /path/to/your/scripts:/scripts \
189
+ -v /path/to/your/input/data:/data/input \
190
+ -v /path/to/your/output:/data/output \
191
+ jumpmetrics python /scripts/my_analysis.py
192
+ ```
193
+
194
+ The Docker container provides a pre-configured environment with jumpmetrics installed. You can:
195
+ - Mount your analysis scripts using `-v /path/to/your/scripts:/scripts`
196
+ - Mount your input data using `-v /path/to/your/input/data:/data/input`
197
+ - Mount an output directory using `-v /path/to/your/output:/data/output`
198
+
199
+ Directory structure example:
200
+ ```
201
+ ~/my_jump_analysis/
202
+ ├── scripts/
203
+ │ └── my_analysis.py # Your analysis script
204
+ ├── input/
205
+ │ └── F02_CTRL1.txt # Your force plate data
206
+ └── output/ # Results will appear here
207
+ ├── jump_metrics.csv
208
+ ├── kinematic_data.csv
209
+ └── force_curve.png
210
+ ```
211
+
212
+ With the current repository structure, you could therefore run:
213
+ ```bash
214
+ docker run -it --rm \
215
+ -v ./docker_example/scripts:/scripts \
216
+ -v ./docker_example/input:/data/input \
217
+ -v ./docker_example/output:/data/output \
218
+ jumpmetrics python /scripts/docker_example.py
219
+ ```
220
+
221
+ to test this output (check out [/docker_example/input](/docker_example/input/) and [/docker_example/output](/docker_example/output/) to see what this looks like).
222
+
223
+ This setup allows you to:
224
+ 1. Keep your analysis scripts separate from the package
225
+ 2. Modify your analysis without rebuilding the Docker image
226
+ 3. Run different analyses using the same container
227
+ 4. Share your analysis scripts while ensuring they run in the same environment
228
+
229
+ If you want to explore this environment interactively, run:
230
+ ```bash
231
+ docker run -it jumpmetrics bash
232
+ ```
233
+
234
+ ## Data Processing
235
+ The following code snippet should help to generally showcase how one could get started quickly with `jumpmetrics` for calculating takeoff metrics:
236
+ ```python
237
+ from jumpmetrics.core.processors import ForceTimeCurveCMJTakeoffProcessor
238
+ from jumpmetrics.core.io import (
239
+ load_raw_force_data_with_no_column_headers, sum_dual_force_components,
240
+ find_first_frame_where_force_exceeds_threshold,
241
+ find_frame_when_off_plate, get_n_seconds_before_takeoff
242
+ )
243
+ from jumpmetrics.signal_processing.filters import butterworth_filter
244
+
245
+ # Load a force dataset
246
+ tmp_force_df = load_raw_force_data_with_no_column_headers(filepath)
247
+ # Sum the vertical force components from a data collection that uses dual force plates
248
+ # Note that the goal is to simply just get a force waveform, and these are helper functions to do so
249
+ # However, you could use your own custom code to obtain a force trace for processing
250
+ full_summed_force = sum_dual_force_components(tmp_force_df)
251
+ # Helper function to help narrow force series to identify when someone is on or off the plate
252
+ frame = find_first_frame_where_force_exceeds_threshold(
253
+ force_trace=full_summed_force,
254
+ threshold=1000
255
+ )
256
+ # Helper function to find when someone is off the plate. Can be used to determine the moment of takeoff
257
+ takeoff_frame = find_frame_when_off_plate(
258
+ force_trace=full_summed_force.iloc[frame:],
259
+ sampling_frequency=2000
260
+ )
261
+ # Cropped force trace provides just the first n seconds before takeoff for processing
262
+ cropped_force_trace = get_n_seconds_before_takeoff(
263
+ force_trace=full_summed_force,
264
+ sampling_frequency=2000,
265
+ takeoff_frame=takeoff_frame,
266
+ n=TIME_BEFORE_TAKEOFF
267
+ )
268
+ # Filtering the force trace data (optional step)
269
+ filtered_force_series = butterworth_filter(
270
+ arr=cropped_force_trace,
271
+ cutoff_frequency=50,
272
+ fps=2000,
273
+ padding=2000
274
+ )
275
+ # Instantiative the takeoff processor class
276
+ CMJ = ForceTimeCurveCMJTakeoffProcessor(
277
+ force_series=filtered_force_series,
278
+ sampling_frequency=2000
279
+ )
280
+ # Get the jump events
281
+ CMJ.get_jump_events()
282
+ # Get the jump metrics
283
+ CMJ.compute_jump_metrics()
284
+ # Create a jump metric dataframe
285
+ CMJ.create_jump_metrics_dataframe()
286
+ # Create a kinematic data dataframe
287
+ CMJ.create_kinematic_dataframe()
288
+ # Plot the waveform data
289
+ CMJ.plot_waveform(
290
+ waveform_type='force',
291
+ title='Testing',
292
+ savefig=True,
293
+ figname=os.path.join('force.png')
294
+ )
295
+ # Save the dataframe
296
+ CMJ.save_kinematic_dataframe(
297
+ dataframe_filepath=os.path.join(pid_data_dir, 'kinematic_data.csv')
298
+ )
299
+ ```
300
+
301
+ Processing an entire jump (takeoff and landing) can be done using the following code example OR building your own wrapper functions using the landing and takeoff classes.
302
+ ```python
303
+ tmp_force_df = load_raw_force_data_with_no_column_headers(filepath)
304
+ full_summed_force = sum_dual_force_components(tmp_force_df)
305
+ results_dict = process_jump_trial(
306
+ full_force_series=full_summed_force,
307
+ sampling_frequency=2000,
308
+ jump_type='countermovement',
309
+ weighing_time=0.25,
310
+ pid='test1',
311
+ threshold_for_helping_determine_takeoff=1000,
312
+ lowpass_filter=True,
313
+ lowpass_cutoff_frequency=26.64,
314
+ compute_jump_height_from_flight_time=True
315
+ )
316
+ ```
317
+
318
+ For a complete guide on available functions and their usage, please refer to the [Documentation](./docs/index.md).
319
+
320
+ ### Example Output
321
+
322
+ The following is an example of the events that can be detected during the takeoff phase of a vertical jump:
323
+
324
+ ![Example countermovement jump force-time trace with events detected during the takeoff phase.](/example_images/force.png)
325
+
326
+
327
+ These events are the foundation for all computed metrics. For a full list of metrics for both the takeoff and landing phases, please refer to the tables in ![](/paper/paper.md).
328
+
329
+ ## Assumptions In this Package
330
+
331
+ Please read the paper for full details. A summary of a portion of the paper is provided below:
332
+
333
+ > To compute the relevant events and metrics, there are specific methods that a user should adhere to that are outlined in previous literature. These methods underpin the assumptions required to collect and process data with the code provided in this package. First, the jumper must stand still (i.e., minimizing swaying or any other body movements) at the start of the data collection and for at least 1 second before starting the initiation of the jump. This quiet standing is used to calculate one's bodyweight, and bodyweight is used for subsequent acceleration, velocity, and displacement calculations used for event detections (as well as for computing net vertical impulse). The default setting in this package is currently to use the first 0.4 seconds of the trial to compute bodyweight (as this was found to work well for previous analyses), but users can tune this parameter themselves for their own data collections depending on the length of the quiet standing at the start of the data collection. For a countermovement jump, the functions in this package also require the person to perform one continuous downwards and upwards motion during the jump; any pausing may negatively impact the event detection algorithms provided. In contrast, for the squat jump the default parameter for identifying the start of the propulsive phase expects at least a 1 second pause. In practice, previous research has outlined a pause should be approximately 3 seconds. The functions provided in `JumpMetrics` permit the user to select a different minimum pause to assume if the default of 1 second is not appropriate for their research.
334
+
335
+ ## Reporting Issues
336
+ If you encounter any issues, please open an [issue on GitHub](https://github.com/stevenhirsch/force-plate-jump-analyses/issues).
337
+
338
+ ## Contributing
339
+ We welcome contributions from researchers, practitioners, and developers! Please see our [Contributing Guidelines](docs/development/contributing.md) for details on how to get started.
340
+
341
+ ## Testing and Code Coverage
342
+
343
+ JumpMetrics maintains a comprehensive test suite to ensure reliability and correctness of the analysis algorithms.
344
+
345
+ ### Test Coverage
346
+ - **Overall Coverage**: 84% (543/650 lines)
347
+ - **Test Suite**: 203 tests including unit tests, integration tests, and edge case validation
348
+ - **Critical Algorithm Coverage**: 100% coverage of event detection, metrics computation, and signal processing modules
349
+
350
+ ### Coverage Breakdown
351
+ | Module | Coverage | Lines Covered |
352
+ |--------|----------|---------------|
353
+ | `events/` | 95%+ | Event detection algorithms |
354
+ | `metrics/` | 100% | Jump metrics computation |
355
+ | `signal_processing/` | 98%+ | Filtering and numerical methods |
356
+ | `core/io.py` | 96% | Data loading and file handling |
357
+ | `core/processors.py` | 66% | Main processor classes |
358
+
359
+ ### Running Tests
360
+ ```bash
361
+ # Run all tests
362
+ pixi run test
363
+
364
+ # Run tests with coverage report
365
+ pixi run test --cov=src/jumpmetrics --cov-report=html
366
+
367
+ # View detailed coverage report
368
+ open htmlcov/index.html
369
+ ```
370
+
371
+ ### Test Philosophy
372
+ The test suite emphasizes:
373
+ - **Comprehensive edge case testing** to ensure robust error handling
374
+ - **Integration tests** with real force plate data to validate end-to-end functionality
375
+ - **Algorithm correctness** verification for all event detection and metrics computation
376
+ - **Graceful failure handling** for unusual or invalid input data
377
+
378
+ All critical analysis algorithms maintain 100% test coverage, ensuring reliable scientific computations.
379
+
380
+ ## License
381
+ This project is licensed under the MIT License. See the [LICENSE](./LICENSE) file for details.
382
+
383
+ ## Contact
384
+ For any questions or further information, please contact me on my [website](https://www.stevenhirsch.ca/contact/) or via [LinkedIn](https://www.linkedin.com/in/steven-m-hirsch/).