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.
Files changed (44) hide show
  1. micromotion-0.6.0/.github/workflows/docs.yml +30 -0
  2. micromotion-0.6.0/.github/workflows/publish.yml +54 -0
  3. micromotion-0.6.0/.github/workflows/tests.yml +16 -0
  4. micromotion-0.6.0/.gitignore +11 -0
  5. micromotion-0.6.0/CHANGELOG.md +113 -0
  6. micromotion-0.6.0/CITATION.cff +25 -0
  7. micromotion-0.6.0/LICENSE +674 -0
  8. micromotion-0.6.0/PKG-INFO +122 -0
  9. micromotion-0.6.0/README.md +91 -0
  10. micromotion-0.6.0/docs/api.md +39 -0
  11. micromotion-0.6.0/docs/conventions.md +86 -0
  12. micromotion-0.6.0/docs/formats.md +76 -0
  13. micromotion-0.6.0/docs/index.md +42 -0
  14. micromotion-0.6.0/docs/interop.md +106 -0
  15. micromotion-0.6.0/docs/quickstart.md +71 -0
  16. micromotion-0.6.0/docs/rates.md +63 -0
  17. micromotion-0.6.0/mkdocs.yml +50 -0
  18. micromotion-0.6.0/pyproject.toml +43 -0
  19. micromotion-0.6.0/src/micromotion/__init__.py +194 -0
  20. micromotion-0.6.0/src/micromotion/align.py +193 -0
  21. micromotion-0.6.0/src/micromotion/balance.py +573 -0
  22. micromotion-0.6.0/src/micromotion/circular.py +144 -0
  23. micromotion-0.6.0/src/micromotion/dynamics.py +457 -0
  24. micromotion-0.6.0/src/micromotion/filters.py +164 -0
  25. micromotion-0.6.0/src/micromotion/group.py +204 -0
  26. micromotion-0.6.0/src/micromotion/io.py +376 -0
  27. micromotion-0.6.0/src/micromotion/mocap.py +214 -0
  28. micromotion-0.6.0/src/micromotion/physio.py +141 -0
  29. micromotion-0.6.0/src/micromotion/posture.py +93 -0
  30. micromotion-0.6.0/src/micromotion/qom.py +717 -0
  31. micromotion-0.6.0/src/micromotion/record.py +113 -0
  32. micromotion-0.6.0/src/micromotion/resample.py +182 -0
  33. micromotion-0.6.0/src/micromotion/spectral.py +216 -0
  34. micromotion-0.6.0/tests/mgt/test_mgt_mocap.py +112 -0
  35. micromotion-0.6.0/tests/mgt/test_mgt_physio.py +66 -0
  36. micromotion-0.6.0/tests/mgt/test_mgt_posture.py +245 -0
  37. micromotion-0.6.0/tests/mgt/test_mgt_qom.py +188 -0
  38. micromotion-0.6.0/tests/test_align.py +100 -0
  39. micromotion-0.6.0/tests/test_dynamics.py +220 -0
  40. micromotion-0.6.0/tests/test_group.py +166 -0
  41. micromotion-0.6.0/tests/test_posture_circular.py +151 -0
  42. micromotion-0.6.0/tests/test_qom.py +214 -0
  43. micromotion-0.6.0/tests/test_resample.py +81 -0
  44. 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,11 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .pytest_cache/
4
+ .ruff_cache/
5
+ *.egg-info/
6
+ build/
7
+ dist/
8
+ .venv/
9
+ .DS_Store
10
+
11
+ site/
@@ -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"