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.
- jumpmetrics-0.1.1/.dockerignore +53 -0
- jumpmetrics-0.1.1/.gitattributes +8 -0
- jumpmetrics-0.1.1/.github/workflows/draft-pdf.yml +20 -0
- jumpmetrics-0.1.1/.github/workflows/python-tests.yml +34 -0
- jumpmetrics-0.1.1/.gitignore +21 -0
- jumpmetrics-0.1.1/Dockerfile +41 -0
- jumpmetrics-0.1.1/LICENSE +21 -0
- jumpmetrics-0.1.1/MANIFEST.in +29 -0
- jumpmetrics-0.1.1/PKG-INFO +384 -0
- jumpmetrics-0.1.1/README.md +336 -0
- jumpmetrics-0.1.1/docker_example/input/F02_CTRL1.txt +40001 -0
- jumpmetrics-0.1.1/docker_example/output/displacement_curve.png +0 -0
- jumpmetrics-0.1.1/docker_example/output/force_curve.png +0 -0
- jumpmetrics-0.1.1/docker_example/output/jump_metrics.csv +2 -0
- jumpmetrics-0.1.1/docker_example/output/kinematic_data.csv +4001 -0
- jumpmetrics-0.1.1/docker_example/output/velocity_curve.png +0 -0
- jumpmetrics-0.1.1/docker_example/scripts/docker_example.py +77 -0
- jumpmetrics-0.1.1/docs/api/core.md +72 -0
- jumpmetrics-0.1.1/docs/api/events.md +75 -0
- jumpmetrics-0.1.1/docs/api/metrics.md +89 -0
- jumpmetrics-0.1.1/docs/api/signal_processing.md +67 -0
- jumpmetrics-0.1.1/docs/development/contributing.md +248 -0
- jumpmetrics-0.1.1/docs/development/testing.md +0 -0
- jumpmetrics-0.1.1/docs/index.md +45 -0
- jumpmetrics-0.1.1/example_images/acceleration.png +0 -0
- jumpmetrics-0.1.1/example_images/displacement.png +0 -0
- jumpmetrics-0.1.1/example_images/force.png +0 -0
- jumpmetrics-0.1.1/example_images/force_sqj.png +0 -0
- jumpmetrics-0.1.1/example_images/force_sqj2.png +0 -0
- jumpmetrics-0.1.1/example_images/velocity.png +0 -0
- jumpmetrics-0.1.1/paper/paper.bib +104 -0
- jumpmetrics-0.1.1/paper/paper.md +177 -0
- jumpmetrics-0.1.1/paper/paper.pdf +0 -0
- jumpmetrics-0.1.1/pixi.lock +9834 -0
- jumpmetrics-0.1.1/pyproject.toml +105 -0
- jumpmetrics-0.1.1/pytest.ini +2 -0
- jumpmetrics-0.1.1/src/jumpmetrics/__init__.py +7 -0
- jumpmetrics-0.1.1/src/jumpmetrics/core/__init__.py +0 -0
- jumpmetrics-0.1.1/src/jumpmetrics/core/io.py +254 -0
- jumpmetrics-0.1.1/src/jumpmetrics/core/jump_processing.py +150 -0
- jumpmetrics-0.1.1/src/jumpmetrics/core/processors.py +667 -0
- jumpmetrics-0.1.1/src/jumpmetrics/events/__init__.py +0 -0
- jumpmetrics-0.1.1/src/jumpmetrics/events/cmj_events.py +154 -0
- jumpmetrics-0.1.1/src/jumpmetrics/events/landing_events.py +17 -0
- jumpmetrics-0.1.1/src/jumpmetrics/events/sqj_events.py +164 -0
- jumpmetrics-0.1.1/src/jumpmetrics/metrics/__init__.py +0 -0
- jumpmetrics-0.1.1/src/jumpmetrics/metrics/metrics.py +174 -0
- jumpmetrics-0.1.1/src/jumpmetrics/signal_processing/__init__.py +0 -0
- jumpmetrics-0.1.1/src/jumpmetrics/signal_processing/filters.py +31 -0
- jumpmetrics-0.1.1/src/jumpmetrics/signal_processing/numerical.py +197 -0
- jumpmetrics-0.1.1/test_install.py +6 -0
- jumpmetrics-0.1.1/tests/KNOWN_TEST_LIMITATIONS.md +102 -0
- jumpmetrics-0.1.1/tests/core/test_core.py +411 -0
- jumpmetrics-0.1.1/tests/core/test_io.py +475 -0
- jumpmetrics-0.1.1/tests/core/test_processors_edge_cases.py +493 -0
- jumpmetrics-0.1.1/tests/events/__init__.py +1 -0
- jumpmetrics-0.1.1/tests/events/test_cmj_events.py +402 -0
- jumpmetrics-0.1.1/tests/events/test_landing_events.py +187 -0
- jumpmetrics-0.1.1/tests/events/test_sqj_events.py +383 -0
- jumpmetrics-0.1.1/tests/example_data/batch_processed_data.csv +497 -0
- jumpmetrics-0.1.1/tests/example_data/example_process_jump_trial_output.csv +2 -0
- jumpmetrics-0.1.1/tests/example_data/example_process_squat_jump_trial_output.csv +2 -0
- jumpmetrics-0.1.1/tests/example_data/kinematic_data/F02/CTRL2/group_cutoff.csv +3962 -0
- jumpmetrics-0.1.1/tests/example_data/kinematic_data/F02/CTRL2/group_cutoff_force_series.csv +3962 -0
- jumpmetrics-0.1.1/tests/example_data/kinematic_data/M07/CTRL1/group_cutoff.csv +4001 -0
- jumpmetrics-0.1.1/tests/example_data/kinematic_data/M07/CTRL1/group_cutoff_force_series.csv +4001 -0
- jumpmetrics-0.1.1/tests/example_data/kinematic_data/M15/CTRL1/group_cutoff.csv +4001 -0
- jumpmetrics-0.1.1/tests/example_data/kinematic_data/M15/CTRL1/group_cutoff_force_series.csv +4001 -0
- jumpmetrics-0.1.1/tests/example_data/p30_squat_jump_example_results.csv +2 -0
- jumpmetrics-0.1.1/tests/example_data/p31_squat_jump_example_results.csv +2 -0
- jumpmetrics-0.1.1/tests/example_data/raw_data/F02_CTRL1.txt +40001 -0
- jumpmetrics-0.1.1/tests/example_data/raw_data/F02_CTRL2_filtered.txt +3966 -0
- jumpmetrics-0.1.1/tests/example_data/raw_data/FHOC_P30_SQT300007.txt +20001 -0
- jumpmetrics-0.1.1/tests/example_data/raw_data/FHOC_P31_SQT900020.txt +20001 -0
- jumpmetrics-0.1.1/tests/example_data/raw_data/M07_CTRL1_filtered.txt +4727 -0
- jumpmetrics-0.1.1/tests/example_data/raw_data/M15_CTRL1_filtered.txt +4730 -0
- jumpmetrics-0.1.1/tests/metrics/__init__.py +1 -0
- jumpmetrics-0.1.1/tests/metrics/test_metrics.py +440 -0
- jumpmetrics-0.1.1/tests/signal_processing/test_filters.py +192 -0
- 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
|
+
[](https://opensource.org/licenses/MIT)
|
|
52
|
+
[](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
|
+

|
|
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 .
|
|
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/).
|