labda 0.0.13.dev0__tar.gz → 0.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.
Files changed (168) hide show
  1. {labda-0.0.13.dev0 → labda-0.1.0}/.gitignore +53 -14
  2. labda-0.1.0/LICENSE +28 -0
  3. labda-0.1.0/PKG-INFO +50 -0
  4. {labda-0.0.13.dev0 → labda-0.1.0}/README.md +2 -3
  5. labda-0.1.0/pyproject.toml +119 -0
  6. labda-0.1.0/src/labda/accelerometers/__init__.py +3 -0
  7. labda-0.1.0/src/labda/accelerometers/intensity/__init__.py +5 -0
  8. labda-0.1.0/src/labda/accelerometers/intensity/acceleration.py +123 -0
  9. labda-0.1.0/src/labda/accelerometers/intensity/counts.py +119 -0
  10. labda-0.1.0/src/labda/accelerometers/intensity/intensity.py +213 -0
  11. labda-0.1.0/src/labda/accelerometers/intensity/vilpa.py +49 -0
  12. labda-0.1.0/src/labda/accelerometers/metrics/__init__.py +5 -0
  13. labda-0.1.0/src/labda/accelerometers/metrics/counts.py +95 -0
  14. labda-0.1.0/src/labda/accelerometers/metrics/enmo.py +37 -0
  15. labda-0.1.0/src/labda/accelerometers/metrics/mad.py +24 -0
  16. labda-0.1.0/src/labda/accelerometers/metrics/metrics.py +37 -0
  17. labda-0.1.0/src/labda/accelerometers/preprocessing/__init__.py +4 -0
  18. labda-0.1.0/src/labda/accelerometers/preprocessing/calibration.py +206 -0
  19. labda-0.1.0/src/labda/accelerometers/preprocessing/wear.py +177 -0
  20. labda-0.1.0/src/labda/core/__init__.py +21 -0
  21. labda-0.1.0/src/labda/core/bouts.py +148 -0
  22. labda-0.1.0/src/labda/core/contexts.py +142 -0
  23. labda-0.1.0/src/labda/core/expander.py +24 -0
  24. labda-0.1.0/src/labda/core/exposures.py +24 -0
  25. labda-0.1.0/src/labda/core/filter.py +72 -0
  26. labda-0.1.0/src/labda/core/merger.py +89 -0
  27. labda-0.1.0/src/labda/core/resampler.py +137 -0
  28. labda-0.1.0/src/labda/core/sampling_frequency.py +55 -0
  29. labda-0.1.0/src/labda/core/utils.py +64 -0
  30. labda-0.1.0/src/labda/core/wear.py +185 -0
  31. labda-0.1.0/src/labda/parsers/__init__.py +16 -0
  32. labda-0.1.0/src/labda/parsers/actigraph.py +181 -0
  33. labda-0.1.0/src/labda/parsers/axivity.py +85 -0
  34. labda-0.1.0/src/labda/parsers/palms.py +61 -0
  35. labda-0.1.0/src/labda/parsers/parser.py +58 -0
  36. labda-0.1.0/src/labda/parsers/qstarz.py +130 -0
  37. labda-0.1.0/src/labda/parsers/sens/__init__.py +4 -0
  38. labda-0.1.0/src/labda/parsers/sens/api.py +209 -0
  39. labda-0.1.0/src/labda/parsers/sens/file.py +116 -0
  40. labda-0.1.0/src/labda/parsers/traccar.py +150 -0
  41. labda-0.1.0/src/labda/spatial/__init__.py +29 -0
  42. labda-0.1.0/src/labda/spatial/estimater.py +43 -0
  43. labda-0.1.0/src/labda/spatial/events.py +214 -0
  44. labda-0.1.0/src/labda/spatial/expander.py +109 -0
  45. labda-0.1.0/src/labda/spatial/filter.py +78 -0
  46. labda-0.1.0/src/labda/spatial/imputation.py +6 -0
  47. labda-0.1.0/src/labda/spatial/indoor.py +67 -0
  48. labda-0.1.0/src/labda/spatial/map.py +153 -0
  49. labda-0.1.0/src/labda/spatial/preprocess.py +184 -0
  50. labda-0.1.0/src/labda/spatial/st_dbscan.py +47 -0
  51. labda-0.1.0/src/labda/spatial/transport.py +193 -0
  52. labda-0.1.0/src/labda/spatial/trips.py +276 -0
  53. labda-0.1.0/src/labda/spatial/utils.py +16 -0
  54. labda-0.1.0/src/labda/surveys/__init__.py +5 -0
  55. labda-0.1.0/src/labda/surveys/indicators/__init__.py +3 -0
  56. labda-0.1.0/src/labda/surveys/indicators/indicators.py +61 -0
  57. labda-0.1.0/src/labda/surveys/indicators/who_bmi_z_score.parquet +0 -0
  58. labda-0.1.0/src/labda/surveys/kidscreen/__init__.py +3 -0
  59. labda-0.1.0/src/labda/surveys/kidscreen/kidscreen.py +38 -0
  60. labda-0.1.0/src/labda/surveys/kidscreen/kidscreen27.py +1171 -0
  61. labda-0.1.0/src/labda/surveys/pedsql/__init__.py +3 -0
  62. labda-0.1.0/src/labda/surveys/pedsql/pedsql.py +42 -0
  63. labda-0.1.0/src/labda/surveys/pedsql/pedsql4.py +255 -0
  64. labda-0.1.0/src/labda/validation.py +289 -0
  65. labda-0.0.13.dev0/.github/workflows/ci.yml +0 -28
  66. labda-0.0.13.dev0/.pre-commit-config.yaml +0 -24
  67. labda-0.0.13.dev0/CHANGELOG.md +0 -10
  68. labda-0.0.13.dev0/CONTRIBUTING.md +0 -8
  69. labda-0.0.13.dev0/LICENSE.md +0 -21
  70. labda-0.0.13.dev0/PKG-INFO +0 -52
  71. labda-0.0.13.dev0/ROADMAP.md +0 -8
  72. labda-0.0.13.dev0/docs/CNAME +0 -1
  73. labda-0.0.13.dev0/docs/abbreviations.md +0 -4
  74. labda-0.0.13.dev0/docs/assets/images/labda_logo.png +0 -0
  75. labda-0.0.13.dev0/docs/changelog.md +0 -1
  76. labda-0.0.13.dev0/docs/concepts/index.md +0 -1
  77. labda-0.0.13.dev0/docs/contributing.md +0 -1
  78. labda-0.0.13.dev0/docs/help.md +0 -0
  79. labda-0.0.13.dev0/docs/index.md +0 -6
  80. labda-0.0.13.dev0/docs/learn/index.md +0 -0
  81. labda-0.0.13.dev0/docs/overrides/main.html +0 -5
  82. labda-0.0.13.dev0/docs/reference/accelerometer.md +0 -0
  83. labda-0.0.13.dev0/docs/reference/index.md +0 -0
  84. labda-0.0.13.dev0/docs/reference/parsers/actigraph.md +0 -4
  85. labda-0.0.13.dev0/docs/reference/parsers/qstarz.md +0 -4
  86. labda-0.0.13.dev0/docs/reference/spatial.md +0 -0
  87. labda-0.0.13.dev0/docs/reference/subject.md +0 -21
  88. labda-0.0.13.dev0/docs/roadmap.md +0 -1
  89. labda-0.0.13.dev0/examples/01-pipeline.ipynb +0 -376
  90. labda-0.0.13.dev0/examples/actigraph.csv +0 -22685
  91. labda-0.0.13.dev0/examples/qstarz.csv +0 -15852
  92. labda-0.0.13.dev0/mkdocs.yml +0 -161
  93. labda-0.0.13.dev0/pyproject.toml +0 -92
  94. labda-0.0.13.dev0/pyproject_poetry.toml +0 -64
  95. labda-0.0.13.dev0/src/labda/__init__.py +0 -9
  96. labda-0.0.13.dev0/src/labda/accelerometer/__init__.py +0 -11
  97. labda-0.0.13.dev0/src/labda/accelerometer/calibration.py +0 -166
  98. labda-0.0.13.dev0/src/labda/accelerometer/counts.py +0 -140
  99. labda-0.0.13.dev0/src/labda/accelerometer/metrics.py +0 -37
  100. labda-0.0.13.dev0/src/labda/accelerometer/wear.py +0 -83
  101. labda-0.0.13.dev0/src/labda/analysis/validity.py +0 -64
  102. labda-0.0.13.dev0/src/labda/contexts.py +0 -124
  103. labda-0.0.13.dev0/src/labda/core/__init__.py +0 -4
  104. labda-0.0.13.dev0/src/labda/core/bouts.py +0 -117
  105. labda-0.0.13.dev0/src/labda/core/charts.py +0 -132
  106. labda-0.0.13.dev0/src/labda/core/contexts.py +0 -30
  107. labda-0.0.13.dev0/src/labda/core/event.py +0 -16
  108. labda-0.0.13.dev0/src/labda/core/expanders.py +0 -28
  109. labda-0.0.13.dev0/src/labda/core/merge.py +0 -50
  110. labda-0.0.13.dev0/src/labda/core/resample.py +0 -143
  111. labda-0.0.13.dev0/src/labda/core/summary.py +0 -72
  112. labda-0.0.13.dev0/src/labda/core/utils.py +0 -161
  113. labda-0.0.13.dev0/src/labda/core/wear_times.py +0 -137
  114. labda-0.0.13.dev0/src/labda/metadata.py +0 -81
  115. labda-0.0.13.dev0/src/labda/object.py +0 -118
  116. labda-0.0.13.dev0/src/labda/osm_features.py +0 -110
  117. labda-0.0.13.dev0/src/labda/parsers/__init__.py +0 -22
  118. labda-0.0.13.dev0/src/labda/parsers/actigraph.py +0 -251
  119. labda-0.0.13.dev0/src/labda/parsers/axivity.py +0 -81
  120. labda-0.0.13.dev0/src/labda/parsers/file.py +0 -88
  121. labda-0.0.13.dev0/src/labda/parsers/motus.py +0 -50
  122. labda-0.0.13.dev0/src/labda/parsers/palms.py +0 -305
  123. labda-0.0.13.dev0/src/labda/parsers/qstarz.py +0 -332
  124. labda-0.0.13.dev0/src/labda/parsers/sens/__init__.py +0 -3
  125. labda-0.0.13.dev0/src/labda/parsers/sens/api.py +0 -361
  126. labda-0.0.13.dev0/src/labda/parsers/sens/file.py +0 -62
  127. labda-0.0.13.dev0/src/labda/parsers/traccar.py +0 -257
  128. labda-0.0.13.dev0/src/labda/spatial/__init__.py +0 -5
  129. labda-0.0.13.dev0/src/labda/spatial/charts.py +0 -163
  130. labda-0.0.13.dev0/src/labda/spatial/contexts.py +0 -17
  131. labda-0.0.13.dev0/src/labda/spatial/event.py +0 -169
  132. labda-0.0.13.dev0/src/labda/spatial/expanders.py +0 -107
  133. labda-0.0.13.dev0/src/labda/spatial/fuzzy_features.py +0 -138
  134. labda-0.0.13.dev0/src/labda/spatial/impute_old.py +0 -184
  135. labda-0.0.13.dev0/src/labda/spatial/indoor.py +0 -54
  136. labda-0.0.13.dev0/src/labda/spatial/interpolate.py +0 -209
  137. labda-0.0.13.dev0/src/labda/spatial/locations.py +0 -327
  138. labda-0.0.13.dev0/src/labda/spatial/osm/__init__.py +0 -1
  139. labda-0.0.13.dev0/src/labda/spatial/st_dbscan.py +0 -65
  140. labda-0.0.13.dev0/src/labda/spatial/transportation.py +0 -242
  141. labda-0.0.13.dev0/src/labda/spatial/trips.py +0 -235
  142. labda-0.0.13.dev0/src/labda/spatial/utils.py +0 -216
  143. labda-0.0.13.dev0/src/labda/subject.py +0 -486
  144. labda-0.0.13.dev0/tests/__init__.py +0 -0
  145. labda-0.0.13.dev0/uv.lock +0 -2292
  146. labda-0.0.13.dev0/work-in-progress/adrian.ipynb +0 -287
  147. labda-0.0.13.dev0/work-in-progress/contexts/analysis.csv +0 -111
  148. labda-0.0.13.dev0/work-in-progress/contexts/contexts.ipynb +0 -290
  149. labda-0.0.13.dev0/work-in-progress/docs/traccar.md +0 -105
  150. labda-0.0.13.dev0/work-in-progress/event.ipynb +0 -117
  151. labda-0.0.13.dev0/work-in-progress/fuzzy_reference.ipynb +0 -127
  152. labda-0.0.13.dev0/work-in-progress/interpolate/analysis.ipynb +0 -271
  153. labda-0.0.13.dev0/work-in-progress/interpolate/fuzzy.ipynb +0 -68
  154. labda-0.0.13.dev0/work-in-progress/interpolate/impute_data.ipynb +0 -119
  155. labda-0.0.13.dev0/work-in-progress/interpolate/kalman_filter.ipynb +0 -108
  156. labda-0.0.13.dev0/work-in-progress/interpolate/map.py +0 -35
  157. labda-0.0.13.dev0/work-in-progress/interpolate/prepare_data.py +0 -212
  158. labda-0.0.13.dev0/work-in-progress/interpolate/randomly_remove_data.ipynb +0 -206457
  159. labda-0.0.13.dev0/work-in-progress/locations/locations.ipynb +0 -228
  160. labda-0.0.13.dev0/work-in-progress/locations/old.ipynb +0 -120
  161. labda-0.0.13.dev0/work-in-progress/locations/prepare_file_from_ipen.ipynb +0 -510
  162. labda-0.0.13.dev0/work-in-progress/osm_road.ipynb +0 -255
  163. labda-0.0.13.dev0/work-in-progress/patterns/enmo.ipynb +0 -42
  164. labda-0.0.13.dev0/work-in-progress/raw_files/3.cwa +0 -0
  165. labda-0.0.13.dev0/work-in-progress/raw_files/cwa.ipynb +0 -47
  166. labda-0.0.13.dev0/work-in-progress/raw_files/gt3x.ipynb +0 -0
  167. {labda-0.0.13.dev0/src/labda/analysis → labda-0.1.0/src/labda}/__init__.py +0 -0
  168. /labda-0.0.13.dev0/docs/concepts/parsers-format.md → /labda-0.1.0/src/labda/py.typed +0 -0
@@ -1,6 +1,6 @@
1
1
  # Byte-compiled / optimized / DLL files
2
2
  __pycache__/
3
- *.py[cod]
3
+ *.py[codz]
4
4
  *$py.class
5
5
 
6
6
  # C extensions
@@ -46,7 +46,7 @@ htmlcov/
46
46
  nosetests.xml
47
47
  coverage.xml
48
48
  *.cover
49
- *.py,cover
49
+ *.py.cover
50
50
  .hypothesis/
51
51
  .pytest_cache/
52
52
  cover/
@@ -94,20 +94,35 @@ ipython_config.py
94
94
  # install all needed dependencies.
95
95
  #Pipfile.lock
96
96
 
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ #uv.lock
102
+
97
103
  # poetry
98
104
  # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99
105
  # This is especially recommended for binary packages to ensure reproducibility, and is more
100
106
  # commonly ignored for libraries.
101
107
  # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102
108
  #poetry.lock
109
+ #poetry.toml
103
110
 
104
111
  # pdm
105
112
  # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
106
115
  #pdm.lock
107
- # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108
- # in version control.
109
- # https://pdm.fming.dev/#use-with-ide
110
- .pdm.toml
116
+ #pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ #pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
111
126
 
112
127
  # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113
128
  __pypackages__/
@@ -121,6 +136,7 @@ celerybeat.pid
121
136
 
122
137
  # Environments
123
138
  .env
139
+ .envrc
124
140
  .venv
125
141
  env/
126
142
  venv/
@@ -159,14 +175,37 @@ cython_debug/
159
175
  # option (not recommended) you can uncomment the following to ignore the entire idea folder.
160
176
  #.idea/
161
177
 
162
- # Poetry
163
- poetry.lock
178
+ # Abstra
179
+ # Abstra is an AI-powered process automation framework.
180
+ # Ignore directories containing user credentials, local state, and settings.
181
+ # Learn more at https://abstra.io/docs
182
+ .abstra/
183
+
184
+ # Visual Studio Code
185
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
186
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
187
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
188
+ # you could uncomment the following to ignore the entire vscode folder
189
+ # .vscode/
190
+
191
+ # Ruff stuff:
192
+ .ruff_cache/
193
+
194
+ # PyPI configuration file
195
+ .pypirc
196
+
197
+ # Cursor
198
+ # Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
199
+ # exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
200
+ # refer to https://docs.cursor.com/context/ignore-files
201
+ .cursorignore
202
+ .cursorindexingignore
203
+
204
+ # Marimo
205
+ marimo/_static/
206
+ marimo/_lsp/
207
+ __marimo__/
164
208
 
165
209
  # Custom
166
210
  temp
167
- examples/cache
168
- .ruff_cache
169
- *.parquet
170
- cache
171
- prepared
172
- diaries
211
+ *.zip
labda-0.1.0/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2025, Josef Heidler
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
labda-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,50 @@
1
+ Metadata-Version: 2.4
2
+ Name: labda
3
+ Version: 0.1.0
4
+ Summary: A Python package built for health researchers, transforms raw movement data into compelling stories about human behaviour.
5
+ Project-URL: Homepage, https://labda.josefheidler.cz
6
+ Project-URL: Documentation, https://labda.josefheidler.cz
7
+ Project-URL: Source, https://github.com/josefheidler/labda
8
+ Project-URL: Changelog, https://github.com/josefheidler/labda/blob/main/CHANGELOG.md
9
+ Author-email: Josef Heidler <jheidler@health.sdu.dk>
10
+ License-Expression: BSD-3-Clause
11
+ License-File: LICENSE
12
+ Keywords: accelerometers,gnss,gps,movement-behavior,physical-activity,sedentary-behaviour,transportation,wearables
13
+ Classifier: Intended Audience :: Education
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Scientific/Engineering
22
+ Requires-Python: >=3.11
23
+ Requires-Dist: agcounts>=0.2.6
24
+ Requires-Dist: altair>=5.5.0
25
+ Requires-Dist: colorcet>=3.1.0
26
+ Requires-Dist: geopandas>=1.1.1
27
+ Requires-Dist: httpx>=0.28.1
28
+ Requires-Dist: numba>=0.61.2
29
+ Requires-Dist: osmnx>=2.0.5
30
+ Requires-Dist: pandas>=2.3.1
31
+ Requires-Dist: pingouin>=0.5.5
32
+ Requires-Dist: pyarrow>=20.0.0
33
+ Requires-Dist: pydeck>=0.9.1
34
+ Requires-Dist: pygt3x>=0.7.1
35
+ Requires-Dist: resampy>=0.4.3
36
+ Requires-Dist: rich>=14.2.0
37
+ Requires-Dist: scikit-digital-health>=0.17.9
38
+ Requires-Dist: timezonefinder>=7.0.2
39
+ Requires-Dist: vegafusion[embed]>=2.0.2
40
+ Requires-Dist: vl-convert-python>=1.8.0
41
+ Description-Content-Type: text/markdown
42
+
43
+ [![pypi](https://img.shields.io/pypi/v/labda.svg)](https://pypi.python.org/pypi/labda)
44
+ [![versions](https://img.shields.io/pypi/pyversions/labda.svg)](https://github.com/josefheidler/labda)
45
+ [![downloads](https://static.pepy.tech/badge/labda/month)](https://pepy.tech/project/labda)
46
+ [![discord](https://img.shields.io/discord/1165947556807848016)](https://discord.gg/qu6ax5Q64j)
47
+
48
+ # LABDA: Library for Advanced Behavioural Data Analysis
49
+
50
+ LABDA, a Python package built for health researchers, transforms raw movement data into compelling stories about human behaviour.
@@ -1,9 +1,8 @@
1
1
  [![pypi](https://img.shields.io/pypi/v/labda.svg)](https://pypi.python.org/pypi/labda)
2
- [![downloads](https://static.pepy.tech/badge/labda/month)](https://pepy.tech/project/labda)
3
2
  [![versions](https://img.shields.io/pypi/pyversions/labda.svg)](https://github.com/josefheidler/labda)
3
+ [![downloads](https://static.pepy.tech/badge/labda/month)](https://pepy.tech/project/labda)
4
4
  [![discord](https://img.shields.io/discord/1165947556807848016)](https://discord.gg/qu6ax5Q64j)
5
5
 
6
6
  # LABDA: Library for Advanced Behavioural Data Analysis
7
7
 
8
- LABDA, a Python package built for health researchers, transforms raw movement data into compelling stories about human behaviour.
9
-
8
+ LABDA, a Python package built for health researchers, transforms raw movement data into compelling stories about human behaviour.
@@ -0,0 +1,119 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+ include = [
5
+ "src/labda/surveys/indicators/who_bmi_z_score.parquet"
6
+ ]
7
+
8
+ [project]
9
+ name = "labda"
10
+ version = "0.1.0"
11
+ description = "A Python package built for health researchers, transforms raw movement data into compelling stories about human behaviour."
12
+ readme = "README.md"
13
+ authors = [
14
+ { name = "Josef Heidler", email = "jheidler@health.sdu.dk" }
15
+ ]
16
+ license = "BSD-3-Clause"
17
+ license-files = ["LICENSE"]
18
+ keywords = ["wearables", "accelerometers", "gps", "gnss", "movement-behavior", "physical-activity", "sedentary-behaviour", "transportation"]
19
+ classifiers = [
20
+ "Programming Language :: Python",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3 :: Only",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ 'Operating System :: OS Independent',
26
+ "Intended Audience :: Education",
27
+ "Intended Audience :: Science/Research",
28
+ "Topic :: Scientific/Engineering",
29
+ ]
30
+ requires-python = ">=3.11"
31
+ dependencies = [
32
+ "agcounts>=0.2.6",
33
+ "altair>=5.5.0",
34
+ "colorcet>=3.1.0",
35
+ "geopandas>=1.1.1",
36
+ "httpx>=0.28.1",
37
+ "numba>=0.61.2",
38
+ "osmnx>=2.0.5",
39
+ "pandas>=2.3.1",
40
+ "pingouin>=0.5.5",
41
+ "pyarrow>=20.0.0",
42
+ "pydeck>=0.9.1",
43
+ "pygt3x>=0.7.1",
44
+ "resampy>=0.4.3",
45
+ "rich>=14.2.0",
46
+ "scikit-digital-health>=0.17.9",
47
+ "timezonefinder>=7.0.2",
48
+ "vegafusion[embed]>=2.0.2",
49
+ "vl-convert-python>=1.8.0",
50
+ ]
51
+
52
+ [project.urls]
53
+ Homepage = 'https://labda.josefheidler.cz'
54
+ Documentation = 'https://labda.josefheidler.cz'
55
+ Source = 'https://github.com/josefheidler/labda'
56
+ Changelog = 'https://github.com/josefheidler/labda/blob/main/CHANGELOG.md'
57
+
58
+ [dependency-groups]
59
+ dev = [
60
+ "acti-motus",
61
+ "black>=25.12.0",
62
+ "fiona>=1.10.1",
63
+ "keplergl>=0.3.7",
64
+ "pre-commit>=4.2.0",
65
+ "pytest>=8.4.1",
66
+ ]
67
+ jupyter = [
68
+ "ipykernel>=6.29.5",
69
+ "ipywidgets>=8.1.7",
70
+ "openpyxl>=3.1.5",
71
+ ]
72
+ docs = [
73
+ "mkdocs>=1.6.1",
74
+ "mkdocs-material>=9.7.1",
75
+ "mkdocs-glightbox>=0.5.2",
76
+ "mkdocstrings[python]>=1.0.0",
77
+ ]
78
+
79
+ [tool.hatch.build.targets.sdist]
80
+ # Limit which files are included in the sdist (.tar.gz) asset,
81
+ include = [
82
+ '/README.md',
83
+ '/src',
84
+ ]
85
+
86
+ [tool.hatch.build.targets.wheel]
87
+ packages = ["src/labda"]
88
+
89
+ [tool.ruff.lint]
90
+ pydocstyle = { convention = 'google' }
91
+
92
+ [tool.ruff]
93
+ line-length = 120
94
+ target-version = 'py311'
95
+
96
+ [tool.ruff.format]
97
+ quote-style = 'double'
98
+
99
+ [tool.pytest.ini_options]
100
+ testpaths = ["tests"]
101
+ python_files = ["test_*.py"]
102
+ python_classes = ["Test*"]
103
+ python_functions = ["test_*"]
104
+ addopts = [
105
+ "-v",
106
+ "--tb=short",
107
+ "--strict-markers",
108
+ "--disable-warnings",
109
+ ]
110
+ markers = [
111
+ "slow: marks tests as slow (deselect with '-m \"not slow\"')",
112
+ "integration: marks tests as integration tests",
113
+ ]
114
+
115
+ [tool.uv]
116
+ default-groups = ["jupyter"]
117
+
118
+ [tool.uv.sources]
119
+ acti-motus = { path = "../acti-motus", editable = true}
@@ -0,0 +1,3 @@
1
+ from .intensity import *
2
+ from .metrics import *
3
+ from .preprocessing import *
@@ -0,0 +1,5 @@
1
+ from .acceleration import MAD_CUT_POINTS
2
+ from .counts import COUNTS_CUT_POINTS
3
+ from .intensity import ActivityIntensity
4
+
5
+ __all__ = ["COUNTS_CUT_POINTS", "ActivityIntensity", "MAD_CUT_POINTS"]
@@ -0,0 +1,123 @@
1
+ import logging
2
+ from datetime import timedelta
3
+ from typing import Any
4
+
5
+ import pandas as pd
6
+
7
+ from ...core.utils import check_for_required_data
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+ ENMO_CUT_POINTS: dict[str, Any] = {
12
+ "hildebrand_2014-2017": {
13
+ "name": "Hildebrand (2014-2017, Actigraph)",
14
+ "reference": [
15
+ "https://doi.org/10.1249/MSS.0000000000000289",
16
+ "https://doi.org/10.1111/sms.12795",
17
+ ],
18
+ "epoch": "5s",
19
+ "category": "adults",
20
+ "placement": "hip",
21
+ "required_data": ["enmo"],
22
+ "thresholds": [
23
+ {"name": "sedentary", "max": 47.4},
24
+ {"name": "light", "max": 69.1},
25
+ {"name": "moderate", "max": 258.7},
26
+ {"name": "vigorous", "max": float("inf")},
27
+ ],
28
+ },
29
+ }
30
+
31
+
32
+ MAD_CUT_POINTS: dict[str, Any] = {
33
+ "aittasalo_children_2015": {
34
+ "name": "Aittasalo (2015, Actigraph)",
35
+ "reference": "https://doi.org/10.1186/s13102-015-0010-0",
36
+ "epoch": "5s",
37
+ "category": "children",
38
+ "placement": "hip",
39
+ "required_data": ["mad"],
40
+ "thresholds": [
41
+ {"name": "sedentary", "max": 26.9},
42
+ {"name": "light", "max": 332.0},
43
+ {"name": "moderate", "max": 558.3},
44
+ {"name": "vigorous", "max": float("inf")},
45
+ ],
46
+ },
47
+ "beck_children_thigh_2023": {
48
+ "name": "Beck Children (2023, Thigh, Move4)",
49
+ "reference": "https://doi.org/10.1186/s13102-023-00775-4",
50
+ "epoch": "5s",
51
+ "category": "children",
52
+ "placement": "thigh",
53
+ "required_data": ["mad"],
54
+ "thresholds": [
55
+ {"name": "sedentary", "max": 62.4},
56
+ {"name": "light", "max": 260.7},
57
+ {"name": "moderate", "max": 674.5},
58
+ {"name": "vigorous", "max": float("inf")},
59
+ ],
60
+ },
61
+ "beck_children_hip_2023": {
62
+ "name": "Beck Children (2023, Hip, Move4)",
63
+ "reference": "https://doi.org/10.1186/s13102-023-00775-4",
64
+ "epoch": "5s",
65
+ "category": "children",
66
+ "placement": "hip",
67
+ "required_data": ["mad"],
68
+ "thresholds": [
69
+ {"name": "sedentary", "max": 52.9},
70
+ {"name": "light", "max": 173.3},
71
+ {"name": "moderate", "max": 543.6},
72
+ {"name": "vigorous", "max": float("inf")},
73
+ ],
74
+ },
75
+ "vaha-ypya_hip_2015-2017": {
76
+ "name": "Vaha-Ypya Adults (2015-2017, Hip, Hookie AM20)",
77
+ "reference": [
78
+ "https://doi.org/10.1371/journal.pone.0134813",
79
+ "https://doi.org/10.1111/sms.13017",
80
+ ],
81
+ "epoch": "5s", # Originally 6s, but opted for 5s here for consistency, and should have minimal impact
82
+ "category": "adults",
83
+ "placement": "hip",
84
+ "required_data": ["mad"],
85
+ "thresholds": [
86
+ {"name": "sedentary", "max": 22.5},
87
+ {"name": "light", "max": 91},
88
+ {"name": "moderate", "max": 414},
89
+ {"name": "vigorous", "max": float("inf")},
90
+ ],
91
+ },
92
+ }
93
+
94
+
95
+ def get_activity_intensities_from_acceleration_metric(
96
+ df: pd.DataFrame,
97
+ thresholds: dict[str, Any],
98
+ epoch: timedelta,
99
+ ):
100
+ # TODO: Reformat this function and function from counts.py to reduce redundancy
101
+ epoch_cut_points = pd.to_timedelta(thresholds["epoch"])
102
+ required_data = thresholds["required_data"]
103
+
104
+ cut_points = thresholds["thresholds"]
105
+ bins = [-float("inf")] + [cp["max"] for cp in cut_points]
106
+ labels = [cp["name"] for cp in cut_points]
107
+
108
+ check_for_required_data(required_data, df.columns)
109
+
110
+ if epoch_cut_points != epoch:
111
+ raise ValueError(
112
+ "Resampling is not supported for acceleration metric based intensity classification. Please provide data with the same epoch as the cut points."
113
+ )
114
+
115
+ if not len(required_data) == 1:
116
+ raise ValueError("For acceleration metric data, only one axis (variable) is supported.")
117
+
118
+ required_data = required_data[0]
119
+
120
+ intensities = pd.cut(df[required_data], bins=bins, labels=labels)
121
+ intensities.name = "activity_intensity"
122
+
123
+ return intensities
@@ -0,0 +1,119 @@
1
+ from datetime import timedelta
2
+ from typing import Any
3
+
4
+ import pandas as pd
5
+
6
+ from ...core.expander import Expander
7
+ from ...core.resampler import Resampler
8
+ from ...core.utils import check_for_required_data
9
+
10
+ COUNTS_CUT_POINTS: dict[str, Any] = {
11
+ "freedson_adults_1998": {
12
+ "name": "Freedson Adults (1998)",
13
+ "reference": "https://journals.lww.com/acsm-msse/fulltext/1998/05000/calibration_of_the_computer_science_and.21.aspx",
14
+ "epoch": "60s",
15
+ "category": "adults",
16
+ "placement": "hip",
17
+ "required_data": ["counts_y"],
18
+ "thresholds": [
19
+ {"name": "sedentary", "max": 99},
20
+ {"name": "light", "max": 1951},
21
+ {"name": "moderate", "max": 5724},
22
+ {"name": "vigorous", "max": 9498},
23
+ {"name": "very-vigorous", "max": float("inf")},
24
+ ],
25
+ },
26
+ "freedson_adults_vm3_2011": {
27
+ "name": "Freedson Adults VM3 (2011)",
28
+ "reference": "https://doi.org/10.1016/j.jsams.2011.04.003",
29
+ "epoch": "60s",
30
+ "category": "adults",
31
+ "placement": "hip",
32
+ "required_data": ["counts_x", "counts_y", "counts_z"],
33
+ "thresholds": [
34
+ {"name": "light", "max": 2689},
35
+ {"name": "moderate", "max": 6166},
36
+ {"name": "vigorous", "max": 9642},
37
+ {"name": "very-vigorous", "max": float("inf")},
38
+ ],
39
+ },
40
+ "freedson_children_2005": {
41
+ "name": "Freedson Children (2005)",
42
+ "reference": "https://doi.org/10.1249/01.mss.0000185658.28284.ba",
43
+ "epoch": "60s",
44
+ "category": "children",
45
+ "placement": "hip",
46
+ "required_data": ["counts_y"],
47
+ "thresholds": [
48
+ {"name": "sedentary", "max": 149},
49
+ {"name": "light", "max": 499},
50
+ {"name": "moderate", "max": 3999},
51
+ {"name": "vigorous", "max": 7599},
52
+ {"name": "very-vigorous", "max": float("inf")},
53
+ ],
54
+ },
55
+ "evenson_children_2018": {
56
+ "name": "Evenson Children (2008)",
57
+ "reference": "https://doi.org/10.1080/02640410802334196",
58
+ "epoch": "15s",
59
+ "category": "children",
60
+ "placement": "hip",
61
+ "required_data": ["counts_y"],
62
+ "thresholds": [
63
+ {"name": "sedentary", "max": 25},
64
+ {"name": "light", "max": 573},
65
+ {"name": "moderate", "max": 1002},
66
+ {"name": "vigorous", "max": float("inf")},
67
+ ],
68
+ },
69
+ "troiano_adults_2008": {
70
+ "name": "Troiano Adults (2008)",
71
+ "reference": "https://doi.org/10.1249/mss.0b013e31815a51b3",
72
+ "epoch": "60s",
73
+ "category": "adults",
74
+ "placement": "hip",
75
+ "required_data": ["counts_y"],
76
+ "thresholds": [
77
+ {"name": "sedentary", "max": 99},
78
+ {"name": "light", "max": 2019},
79
+ {"name": "moderate", "max": 5998},
80
+ {"name": "vigorous", "max": float("inf")},
81
+ ],
82
+ },
83
+ }
84
+
85
+
86
+ def get_activity_intensities_from_counts(
87
+ df: pd.DataFrame,
88
+ thresholds: dict[str, Any],
89
+ epoch: timedelta,
90
+ ) -> pd.Series:
91
+ epoch_cut_points = pd.to_timedelta(thresholds["epoch"])
92
+ required_data = thresholds["required_data"]
93
+
94
+ cut_points = thresholds["thresholds"]
95
+ bins = [-float("inf")] + [cp["max"] for cp in cut_points]
96
+ labels = [cp["name"] for cp in cut_points]
97
+
98
+ check_for_required_data(required_data, df.columns)
99
+
100
+ if epoch_cut_points > epoch:
101
+ df = Resampler(epoch_cut_points).resample(df[required_data], epoch)
102
+ elif epoch_cut_points < epoch:
103
+ raise ValueError(
104
+ f"Epoch for cut points ({epoch_cut_points}) is smaller than the epoch of the data ({epoch}). Upsampling is not supported."
105
+ )
106
+
107
+ if required_data == ["counts_x", "counts_y", "counts_z"]:
108
+ df = df[["counts_x", "counts_y", "counts_z"]].copy()
109
+ df["counts_vm"] = Expander().vector_magnitude(df[required_data])
110
+ required_data = "counts_vm"
111
+ elif len(required_data) == 1:
112
+ required_data = required_data[0]
113
+ else:
114
+ raise ValueError("For counts data, only uniaxial or vector magnitude data is supported.")
115
+
116
+ intensities = pd.cut(df[required_data], bins=bins, labels=labels)
117
+ intensities.name = "activity_intensity"
118
+
119
+ return intensities