micromotion 0.6.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.
- micromotion-0.6.0/.github/workflows/docs.yml +30 -0
- micromotion-0.6.0/.github/workflows/publish.yml +54 -0
- micromotion-0.6.0/.github/workflows/tests.yml +16 -0
- micromotion-0.6.0/.gitignore +11 -0
- micromotion-0.6.0/CHANGELOG.md +113 -0
- micromotion-0.6.0/CITATION.cff +25 -0
- micromotion-0.6.0/LICENSE +674 -0
- micromotion-0.6.0/PKG-INFO +122 -0
- micromotion-0.6.0/README.md +91 -0
- micromotion-0.6.0/docs/api.md +39 -0
- micromotion-0.6.0/docs/conventions.md +86 -0
- micromotion-0.6.0/docs/formats.md +76 -0
- micromotion-0.6.0/docs/index.md +42 -0
- micromotion-0.6.0/docs/interop.md +106 -0
- micromotion-0.6.0/docs/quickstart.md +71 -0
- micromotion-0.6.0/docs/rates.md +63 -0
- micromotion-0.6.0/mkdocs.yml +50 -0
- micromotion-0.6.0/pyproject.toml +43 -0
- micromotion-0.6.0/src/micromotion/__init__.py +194 -0
- micromotion-0.6.0/src/micromotion/align.py +193 -0
- micromotion-0.6.0/src/micromotion/balance.py +573 -0
- micromotion-0.6.0/src/micromotion/circular.py +144 -0
- micromotion-0.6.0/src/micromotion/dynamics.py +457 -0
- micromotion-0.6.0/src/micromotion/filters.py +164 -0
- micromotion-0.6.0/src/micromotion/group.py +204 -0
- micromotion-0.6.0/src/micromotion/io.py +376 -0
- micromotion-0.6.0/src/micromotion/mocap.py +214 -0
- micromotion-0.6.0/src/micromotion/physio.py +141 -0
- micromotion-0.6.0/src/micromotion/posture.py +93 -0
- micromotion-0.6.0/src/micromotion/qom.py +717 -0
- micromotion-0.6.0/src/micromotion/record.py +113 -0
- micromotion-0.6.0/src/micromotion/resample.py +182 -0
- micromotion-0.6.0/src/micromotion/spectral.py +216 -0
- micromotion-0.6.0/tests/mgt/test_mgt_mocap.py +112 -0
- micromotion-0.6.0/tests/mgt/test_mgt_physio.py +66 -0
- micromotion-0.6.0/tests/mgt/test_mgt_posture.py +245 -0
- micromotion-0.6.0/tests/mgt/test_mgt_qom.py +188 -0
- micromotion-0.6.0/tests/test_align.py +100 -0
- micromotion-0.6.0/tests/test_dynamics.py +220 -0
- micromotion-0.6.0/tests/test_group.py +166 -0
- micromotion-0.6.0/tests/test_posture_circular.py +151 -0
- micromotion-0.6.0/tests/test_qom.py +214 -0
- micromotion-0.6.0/tests/test_resample.py +81 -0
- micromotion-0.6.0/tests/test_spectral.py +112 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: docs
|
|
2
|
+
on:
|
|
3
|
+
push: { branches: [main] }
|
|
4
|
+
permissions:
|
|
5
|
+
contents: read
|
|
6
|
+
pages: write
|
|
7
|
+
id-token: write
|
|
8
|
+
concurrency:
|
|
9
|
+
group: pages
|
|
10
|
+
cancel-in-progress: false
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with: { python-version: "3.12" }
|
|
18
|
+
- run: pip install -e . mkdocs-material mkdocstrings[python]
|
|
19
|
+
- run: mkdocs build --strict
|
|
20
|
+
- uses: actions/upload-pages-artifact@v3
|
|
21
|
+
with: { path: site }
|
|
22
|
+
deploy:
|
|
23
|
+
needs: build
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
environment:
|
|
26
|
+
name: github-pages
|
|
27
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
28
|
+
steps:
|
|
29
|
+
- id: deployment
|
|
30
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: publish
|
|
2
|
+
|
|
3
|
+
# Publishes to PyPI when a GitHub release is published. Authentication is by PyPI Trusted
|
|
4
|
+
# Publishing (OIDC), so there is no API token to store or rotate: PyPI is configured to trust
|
|
5
|
+
# this repository, this workflow file and the `pypi` environment, and nothing else.
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
release:
|
|
9
|
+
types: [published]
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
strategy:
|
|
15
|
+
matrix:
|
|
16
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
- uses: actions/setup-python@v5
|
|
20
|
+
with: { python-version: "${{ matrix.python-version }}" }
|
|
21
|
+
- run: pip install -e ".[test]"
|
|
22
|
+
- run: pytest -q
|
|
23
|
+
|
|
24
|
+
build:
|
|
25
|
+
needs: test
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
- uses: actions/setup-python@v5
|
|
30
|
+
with: { python-version: "3.12" }
|
|
31
|
+
- run: pip install build
|
|
32
|
+
- run: python -m build
|
|
33
|
+
# Fail here rather than at upload if the version and the tag disagree.
|
|
34
|
+
- name: Check the built version matches the release tag
|
|
35
|
+
run: |
|
|
36
|
+
version=$(ls dist/*.tar.gz | sed -E 's/.*micromotion-(.*)\.tar\.gz/\1/')
|
|
37
|
+
tag="${GITHUB_REF_NAME#v}"
|
|
38
|
+
test "$version" = "$tag" || {
|
|
39
|
+
echo "pyproject version $version does not match release tag $tag"; exit 1; }
|
|
40
|
+
- uses: actions/upload-artifact@v4
|
|
41
|
+
with: { name: dist, path: dist/ }
|
|
42
|
+
|
|
43
|
+
publish:
|
|
44
|
+
needs: build
|
|
45
|
+
runs-on: ubuntu-latest
|
|
46
|
+
environment:
|
|
47
|
+
name: pypi
|
|
48
|
+
url: https://pypi.org/p/micromotion
|
|
49
|
+
permissions:
|
|
50
|
+
id-token: write
|
|
51
|
+
steps:
|
|
52
|
+
- uses: actions/download-artifact@v4
|
|
53
|
+
with: { name: dist, path: dist/ }
|
|
54
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: tests
|
|
2
|
+
on:
|
|
3
|
+
push: { branches: [main] }
|
|
4
|
+
pull_request:
|
|
5
|
+
jobs:
|
|
6
|
+
test:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
strategy:
|
|
9
|
+
matrix:
|
|
10
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
- uses: actions/setup-python@v5
|
|
14
|
+
with: { python-version: "${{ matrix.python-version }}" }
|
|
15
|
+
- run: pip install -e ".[test]"
|
|
16
|
+
- run: pytest -q
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.6.0
|
|
4
|
+
|
|
5
|
+
First release published to PyPI.
|
|
6
|
+
|
|
7
|
+
**The lower band edge moved from 0.3 Hz to 0.2 Hz, and every number this package produces changes
|
|
8
|
+
with it.** 0.3 was inherited rather than chosen. Swept across seven optical datasets and 665
|
|
9
|
+
recordings, the between-dataset spread is 3.2 per cent at 0.15 Hz, 2.1 at 0.20, 2.7 at 0.25, 6.2
|
|
10
|
+
at 0.30 and 10.1 at 0.40. 0.2 is a clear optimum and is where the 20 Hz origin dataset stops being
|
|
11
|
+
an outlier in either direction. Checked against the failure this edge exists to prevent: on
|
|
12
|
+
accelerometer data the mean-to-median speed ratio, which rises when integration drift leaks in, is
|
|
13
|
+
2.07 at 0.2 Hz against 2.00 at 0.3 — flat, so integration is safe. Absolute values rise about 73
|
|
14
|
+
per cent because more low-frequency content is kept.
|
|
15
|
+
|
|
16
|
+
One real cost, now under test: the filter transient runs 40 s at each end rather than 27, so a
|
|
17
|
+
recording under about two minutes has no clean interior at all.
|
|
18
|
+
|
|
19
|
+
- `bandpass` warns when the sampling rate exceeds the upper band edge by more than 40:1. Porting
|
|
20
|
+
the analysis scripts turned up a filter that is wrong in published work rather than merely
|
|
21
|
+
different: a 0.1–0.5 Hz third-order band-pass at 250 Hz, written the usual way as
|
|
22
|
+
`butter(3, [lo/ny, hi/ny])` with `filtfilt`, has a largest pole radius of 0.9979 and a measured
|
|
23
|
+
passband gain of 0.84 at 0.15 Hz where it should be 0.99. Nothing raises and nothing looks
|
|
24
|
+
wrong; every amplitude downstream is sixteen per cent low. This package uses second-order
|
|
25
|
+
sections and was never affected, but it accepted such a band silently, and a caller designing
|
|
26
|
+
their own filter deserves to be told. The warning names the fix, which is to decimate first.
|
|
27
|
+
- `bandpass` and `lowpass` take a `margin` argument. The upper edge was pinned at 0.99 of Nyquist
|
|
28
|
+
with no way to change it, and the Still Standing corpus uses 0.999 throughout, so no script
|
|
29
|
+
written against that convention could be ported.
|
|
30
|
+
- `detect_breaths_adaptive`, added with its benchmark and an explicit note not to default to it.
|
|
31
|
+
The expectation was that rejecting chest rises which never cross an adaptive baseline would beat
|
|
32
|
+
plain peak detection. Measured, it does not: on twelve belt recordings the two agree, and on
|
|
33
|
+
eight chest accelerometers — the case the rejection was meant to help — it over-counts badly,
|
|
34
|
+
10.3 breaths/min against 3.6 for the peak-based detector.
|
|
35
|
+
- The balance readers are described by content rather than by a `.tsv` extension they no longer
|
|
36
|
+
have.
|
|
37
|
+
|
|
38
|
+
164 tests.
|
|
39
|
+
|
|
40
|
+
## 0.5.0
|
|
41
|
+
|
|
42
|
+
The integration rule used to turn acceleration into speed is now selectable, and it was hiding a
|
|
43
|
+
systematic 0.26 per cent. This package integrated with a rectangle sum; the StillStanding365 and
|
|
44
|
+
fNIRS pipelines use the trapezoid rule, and on real phone data the two differ consistently because
|
|
45
|
+
the rectangle sum lags the signal by half a sample.
|
|
46
|
+
|
|
47
|
+
Both are available. The default stays rectangle, and not because it is the better rule — it is
|
|
48
|
+
not. It is what the harmonised cross-collection table and every figure derived from it were
|
|
49
|
+
computed with, and it reproduces the deposited Taqasim value, 93.140 against 93.091 mm/s, where
|
|
50
|
+
trapezoid gives 93.405. Changing the default would silently invalidate numbers already published.
|
|
51
|
+
Which rule the project standardises on is left open.
|
|
52
|
+
|
|
53
|
+
## 0.4.0
|
|
54
|
+
|
|
55
|
+
Added `group`, for the question everything else here could not ask. The rest of the package
|
|
56
|
+
describes one recording or relates a pair; this answers whether a room full of people moved at the
|
|
57
|
+
same moments.
|
|
58
|
+
|
|
59
|
+
- `event_train` — continuous signal to point process, thresholded relative to each person's own
|
|
60
|
+
variability, so a quiet participant and a loud one both register events.
|
|
61
|
+
- `coincidence_test` — surrogates shift each person by an independent bounded random offset, so
|
|
62
|
+
every individual keeps their own event rate and local structure and only the between-person
|
|
63
|
+
alignment is destroyed.
|
|
64
|
+
- `participation_ratio` — the fraction of people whose motion fell after an event. Sign-based, so
|
|
65
|
+
sensors differing by an order of magnitude do not shift it.
|
|
66
|
+
|
|
67
|
+
## 0.3.0
|
|
68
|
+
|
|
69
|
+
Absorbed the quantity-of-motion modules from `musicalgestures`, whose unreleased main branch
|
|
70
|
+
carried `band_limited_qom`, `accel_to_speed`, `read_qtm_tsv`, `cop_sway_metrics` and
|
|
71
|
+
`respiration_rate`, all credited in their docstrings to the same source study as this package.
|
|
72
|
+
Rather than ship a competing fifth implementation of the project's central measure, they move here
|
|
73
|
+
and MGT depends on micromotion.
|
|
74
|
+
|
|
75
|
+
MGT's behaviour is preserved exactly rather than silently reconciled. `band_limited_qom` still
|
|
76
|
+
defaults to a 0.3–15 Hz band, differentiates with a two-point difference and does not band-limit
|
|
77
|
+
again afterwards; on a 200 Hz optical recording it still returns 5.675 mm/s against 5.455 for this
|
|
78
|
+
package's `qom()`. They are different measures and are documented as such.
|
|
79
|
+
|
|
80
|
+
## 0.2.0
|
|
81
|
+
|
|
82
|
+
Added the function families an audit against the source study's 159 analysis scripts found
|
|
83
|
+
missing.
|
|
84
|
+
|
|
85
|
+
- `align` — offset recovery between recordings sharing no clock, by cross-correlation or
|
|
86
|
+
direct search, plus instantaneous rate tracking and transient detection. Reproduces the
|
|
87
|
+
fNIRS session's 126.0 s offset, which the deposited sync clap independently confirms.
|
|
88
|
+
- `circular` — mean direction, Rayleigh and its axial form, V test, circular and
|
|
89
|
+
circular-linear correlation, axial dispersion.
|
|
90
|
+
- `posture` — sway anisotropy and principal axis, 95 per cent confidence ellipse, path
|
|
91
|
+
length, dispersion radius.
|
|
92
|
+
- `spectral` — peak with signal-to-noise ratio, band RMS, band power fractions, mean
|
|
93
|
+
frequency, breath detection.
|
|
94
|
+
- `dynamics` — approximate entropy, detrended cross-correlation.
|
|
95
|
+
- `resample` — short-gap interpolation with a stated ceiling, and gap reporting.
|
|
96
|
+
- `qom` — tilt decomposition made public, with `tilt_fraction`.
|
|
97
|
+
|
|
98
|
+
`xcorr_lag` now differences its inputs by default. Correlating two drifting series and taking
|
|
99
|
+
the best lag is the spurious-regression trap: over 200 independent random-walk pairs the
|
|
100
|
+
best-lag correlation had a median of 0.47, exceeded 0.5 forty per cent of the time and
|
|
101
|
+
reached 0.98 at worst. Differenced, the same pairs never passed 0.16.
|
|
102
|
+
|
|
103
|
+
89 tests.
|
|
104
|
+
|
|
105
|
+
## 0.1.0
|
|
106
|
+
|
|
107
|
+
First release. Filters, quantity of motion, resampling, spectral peaks, dynamics, seven
|
|
108
|
+
readers and a common record type, extracted from 159 analysis scripts in which 58 defined
|
|
109
|
+
their own band-pass filter and 37 computed quantity of motion.
|
|
110
|
+
|
|
111
|
+
Restores two validations that had been lost: the time-reversal test returns z = +0.85 on an
|
|
112
|
+
AR(1) process and z = -41 on a logistic map. A report stated both; no script implementing
|
|
113
|
+
them had survived.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
title: "micromotion: analysis of human micromotion in motion time series"
|
|
3
|
+
message: "If you use this software, please cite it."
|
|
4
|
+
type: software
|
|
5
|
+
authors:
|
|
6
|
+
- family-names: Jensenius
|
|
7
|
+
given-names: Alexander Refsum
|
|
8
|
+
orcid: "https://orcid.org/0000-0003-4703-9411"
|
|
9
|
+
affiliation: "RITMO Centre for Interdisciplinary Studies in Rhythm, Time and Motion, University of Oslo"
|
|
10
|
+
repository-code: "https://github.com/fourMs/micromotion"
|
|
11
|
+
abstract: >-
|
|
12
|
+
One implementation of quantity of motion — the average speed of a body part,
|
|
13
|
+
band-limited to 0.2-10 Hz, in millimetres per second — for optical marker data,
|
|
14
|
+
body-worn accelerometers and force-plate centre of pressure, together with the
|
|
15
|
+
readers, resampling rules, scaling measures and alignment methods that surround it.
|
|
16
|
+
keywords:
|
|
17
|
+
- micromotion
|
|
18
|
+
- standstill
|
|
19
|
+
- quantity of motion
|
|
20
|
+
- motion capture
|
|
21
|
+
- accelerometer
|
|
22
|
+
- postural sway
|
|
23
|
+
license: GPL-3.0-or-later
|
|
24
|
+
version: 0.6.0
|
|
25
|
+
date-released: "2026-07-30"
|