From 81070eb9e8ec041919a2dafaeff0b717e1a3ed00 Mon Sep 17 00:00:00 2001 From: Lukas Adamowicz Date: Thu, 8 Feb 2024 08:26:58 -0500 Subject: [PATCH 01/15] remove python 3.6/3.7 from list --- pyproject.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 590f9a65..4f4a86bc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,8 +33,6 @@ classifiers = [ "Development Status :: 4 - Beta", "License :: OSI Approved :: MIT License", "Programming Language :: Python", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", From 80fc9723215505da8bb83a7e51d7d1ee8a52467e Mon Sep 17 00:00:00 2001 From: Lukas Adamowicz Date: Thu, 8 Feb 2024 08:31:58 -0500 Subject: [PATCH 02/15] Update papers with published journal and DOI --- docs/src/research.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/research.rst b/docs/src/research.rst index 3dfea105..f4ebc1f7 100644 --- a/docs/src/research.rst +++ b/docs/src/research.rst @@ -2,7 +2,7 @@ Peer Reviewed Journal Articles Using SKDH ========================================= - W. Lin et al., “Can Gait Characteristics Be Represented by Physical Activity Measured with Wrist-Worn Accelerometers?,” Sensors, vol. 23, no. 20, Art. no. 20, Jan. 2023, doi: 10.3390/s23208542. -- W. Lin et al., "SciKit Digital Health Package for Accelerometry-Measured Physical Activity: Comparisons to Existing Solutions and Investigations of Age Effects in Healthy Adults", In Preperation +- W. Lin et al., "SciKit Digital Health Package for Accelerometry-Measured Physical Activity: Comparisons to Existing Solutions and Investigations of Age Effects in Healthy Adults", Front. Digit. Health, 26 Nov. 2023, doi: 10.3389/fdgth.2023.1321086 - J. Di et al., "Wearable Accelerometers as An Innovative Approach to Monitor Physical Activity and Gait in Children and Adolescents", In Preparation - P. Sheriff et al., "In-Clinic and Natural Gait Observations (I-CAN-GO) an Observational Low-Interventional Master Protocol to Validate Gait and Physical Activity in Adults", In Preparation - N. Camerlingo et al., "Measuring gait parameters from a chest-worn accelerometer in healthy individuals: a validation study", In Preparation From ab5c686a5bd7e14c87e46d3579efc208670d2fba Mon Sep 17 00:00:00 2001 From: Lukas Adamowicz Date: Mon, 12 Feb 2024 07:53:39 -0500 Subject: [PATCH 03/15] Fix typos and rename ambulation to context in docs --- docs/ref/index.rst | 2 +- src/skdh/gait/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/ref/index.rst b/docs/ref/index.rst index bdfdee12..ead5c9a0 100644 --- a/docs/ref/index.rst +++ b/docs/ref/index.rst @@ -10,10 +10,10 @@ SKDH Reference io preprocessing features + context sleep activity gait gait_old sit2stand utility - ambulation diff --git a/src/skdh/gait/__init__.py b/src/skdh/gait/__init__.py index fff8530f..3caf022d 100644 --- a/src/skdh/gait/__init__.py +++ b/src/skdh/gait/__init__.py @@ -4,7 +4,7 @@ .. currentmodule:: skdh.gait -Pipeline gait processing +Pipeline Gait Processing ------------------------ .. autosummary:: From e586f5cc9a42a7317707e775400ad8d187b18be6 Mon Sep 17 00:00:00 2001 From: Lukas Adamowicz Date: Mon, 12 Feb 2024 08:00:10 -0500 Subject: [PATCH 04/15] Update scipy intersphinx link --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index ae8ae774..c721f0b5 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -221,7 +221,7 @@ intersphinx_mapping = { "python": ("https://docs.python.org/dev", None), "numpy": ("https://numpy.org/doc/stable/", None), - "scipy": ("https://docs.scipy.org/doc/scipy/reference", None), + "scipy": ('https://docs.scipy.org/doc/scipy', None), "pandas": ("https://pandas.pydata.org/pandas-docs/stable", None), } From bcda1d4ad38a37f1b8b6bb354bd4b3ee13af8ae0 Mon Sep 17 00:00:00 2001 From: Lukas Adamowicz Date: Mon, 12 Feb 2024 08:04:10 -0500 Subject: [PATCH 05/15] update path for scipy external ref --- src/skdh/gait/substeps/s1_preprocessing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/skdh/gait/substeps/s1_preprocessing.py b/src/skdh/gait/substeps/s1_preprocessing.py index 3795b863..76424e8a 100644 --- a/src/skdh/gait/substeps/s1_preprocessing.py +++ b/src/skdh/gait/substeps/s1_preprocessing.py @@ -54,7 +54,7 @@ class PreprocessGaitBout(BaseProcess): - `btype`: band - `output`: sos - NOTE that this will always be set/overriden - See :scipy-signal:func:`scipy.signal.butter` for full options. + See :func:`scipy.signal.butter` for full options. """ def __init__( From c86e11192d4f19875c6d78cee759b7c802238642 Mon Sep 17 00:00:00 2001 From: Lukas Adamowicz Date: Mon, 12 Feb 2024 08:06:52 -0500 Subject: [PATCH 06/15] update path for scipy external ref --- src/skdh/gait/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/skdh/gait/core.py b/src/skdh/gait/core.py index 7e5b1c6b..3324c571 100644 --- a/src/skdh/gait/core.py +++ b/src/skdh/gait/core.py @@ -77,7 +77,7 @@ class GaitLumbar(BaseProcess): - `btype`: band - `output`: sos - NOTE that this will always be set/overriden - See :scipy-signal:func:`scipy.signal.butter` for full options. + See :func:`scipy.signal.butter` for full options. ic_prom_factor : float, optional [:meth:`skdh.gaitv3.substeps.ApCwtGaitEvents`] Factor multiplied by the standard deviation of the CWT coefficients to obtain a minimum prominence From 9a57af77c3825631a165613864a2ca98396566ff Mon Sep 17 00:00:00 2001 From: Lukas Adamowicz Date: Mon, 12 Feb 2024 08:13:41 -0500 Subject: [PATCH 07/15] Pass Path objects into tests to make sure they can be passed to reader functions --- tests/io/conftest.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/io/conftest.py b/tests/io/conftest.py index 74eb1be5..ec0e490f 100644 --- a/tests/io/conftest.py +++ b/tests/io/conftest.py @@ -48,7 +48,7 @@ def predict(self, *, test_input=None, **kwargs): @fixture def gnactv_file(path_tests): - return str(path_tests / "io" / "data" / "gnactv_sample.bin") + return path_tests / "io" / "data" / "gnactv_sample.bin" @fixture @@ -63,7 +63,7 @@ def gnactv_truth(path_tests): @fixture def ax3_file(path_tests): - return str(path_tests / "io" / "data" / "ax3_sample.cwa") + return path_tests / "io" / "data" / "ax3_sample.cwa" @fixture @@ -78,7 +78,7 @@ def ax3_truth(path_tests): @fixture def ax6_file(path_tests): - return str(path_tests / "io" / "data" / "ax6_sample.cwa") + return path_tests / "io" / "data" / "ax6_sample.cwa" @fixture @@ -93,7 +93,7 @@ def ax6_truth(path_tests): @fixture def apdm_file(path_tests): - return str(path_tests / "io" / 'data' / "apdm_sample.h5") + return path_tests / "io" / 'data' / "apdm_sample.h5" @fixture From 34168c02c7d90de61cd1dcdf5c6568b2a4c598d1 Mon Sep 17 00:00:00 2001 From: Lukas Adamowicz Date: Mon, 12 Feb 2024 08:16:37 -0500 Subject: [PATCH 08/15] Convert to strings for binary readers, #139 --- src/skdh/io/axivity.py | 2 +- src/skdh/io/geneactiv.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/skdh/io/axivity.py b/src/skdh/io/axivity.py index 30121db7..beb1e7ad 100644 --- a/src/skdh/io/axivity.py +++ b/src/skdh/io/axivity.py @@ -91,7 +91,7 @@ def predict(self, *, file, **kwargs): super().predict(expect_days=False, expect_wear=False, file=file, **kwargs) # read the file - fs, n_bad_samples, imudata, ts, temperature = read_axivity(file) + fs, n_bad_samples, imudata, ts, temperature = read_axivity(str(file)) # end = None if n_bad_samples == 0 else -n_bad_samples end = None diff --git a/src/skdh/io/geneactiv.py b/src/skdh/io/geneactiv.py index fc2c3dc8..784d531c 100644 --- a/src/skdh/io/geneactiv.py +++ b/src/skdh/io/geneactiv.py @@ -79,7 +79,7 @@ def predict(self, *, file, **kwargs): super().predict(expect_days=False, expect_wear=False, file=file, **kwargs) # read the file - n_max, fs, acc, time, light, temp = read_geneactiv(file) + n_max, fs, acc, time, light, temp = read_geneactiv(str(file)) results = { self._time: time[:n_max], From 17be7645e70cbcef15e5ae72c25e6d24918cfb12 Mon Sep 17 00:00:00 2001 From: Lukas Adamowicz Date: Mon, 12 Feb 2024 08:20:38 -0500 Subject: [PATCH 09/15] Update statement for adding of time delta values for pandas rules on copies and setting --- src/skdh/io/csv.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/skdh/io/csv.py b/src/skdh/io/csv.py index f3d1ce95..a3dd904e 100644 --- a/src/skdh/io/csv.py +++ b/src/skdh/io/csv.py @@ -81,7 +81,7 @@ def handle_timestamp_inconsistency(df, fill_gaps, accel_col_names, accel_in_g, g t_delta = to_timedelta(t_delta, unit="s") # add the time delta so that we have unique timestamps - df["_datetime_"] += t_delta + df.loc[:, "_datetime_"] += t_delta # check if we are filling gaps or not if fill_gaps: From 61574991c53a1d15d72b2cd05fa39e55dd9c4f5b Mon Sep 17 00:00:00 2001 From: Lukas Adamowicz Date: Mon, 12 Feb 2024 08:31:05 -0500 Subject: [PATCH 10/15] catch warnings for divide by zero for angle z since it can handle them --- src/skdh/activity/metrics.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/skdh/activity/metrics.py b/src/skdh/activity/metrics.py index b2044cd0..332dcce8 100644 --- a/src/skdh/activity/metrics.py +++ b/src/skdh/activity/metrics.py @@ -4,6 +4,8 @@ Lukas Adamowicz Copyright (c) 2021. Pfizer Inc. All rights reserved. """ +import warnings + from numpy import maximum, abs, repeat, arctan, sqrt, pi from numpy.linalg import norm from scipy.signal import butter, sosfiltfilt @@ -38,9 +40,11 @@ def metric_anglez(accel, wlen, *args, **kwargs): anglez : numpy.ndarray (N, ) array of angles between accelerometer z axis and horizontal plane in degrees. """ - anglez = arctan(accel[:, 2] / sqrt(accel[:, 0] ** 2 + accel[:, 1] ** 2)) * ( - 180 / pi - ) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", message="divide by zero encountered in divide") + anglez = arctan(accel[:, 2] / sqrt(accel[:, 0] ** 2 + accel[:, 1] ** 2)) * ( + 180 / pi + ) return moving_mean(anglez, wlen, wlen) From 0aa0a88c5f547b9b58866ac5a853c9ba42c72f7c Mon Sep 17 00:00:00 2001 From: Lukas Adamowicz Date: Mon, 12 Feb 2024 15:29:48 -0500 Subject: [PATCH 11/15] update scipy min version for cumulative_trapezoid to be available --- pyproject.toml | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4f4a86bc..f0012dfd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,7 +49,7 @@ classifiers = [ requires-python = ">=3.6" dependencies = [ "numpy>=1.17.2", - "scipy>=1.3.1", + "scipy>=1.12.0", "pandas>=1.0.0", "lightgbm>=2.3.0", "pywavelets", diff --git a/requirements.txt b/requirements.txt index f6969a22..6e20d3f9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ numpy>=1.17.2 -scipy>=1.3.1 +scipy>=1.12.0 pandas>=0.23.4 lightgbm>=2.3.0 pywavelets From b37ce9d8652a8e449f61bb2566db9b9f951e8253 Mon Sep 17 00:00:00 2001 From: Lukas Adamowicz Date: Fri, 1 Mar 2024 13:43:12 -0500 Subject: [PATCH 12/15] add timezone conversion to local time for APDM files --- src/skdh/io/apdm.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/skdh/io/apdm.py b/src/skdh/io/apdm.py index 4bb6352f..cc67ef46 100644 --- a/src/skdh/io/apdm.py +++ b/src/skdh/io/apdm.py @@ -24,6 +24,9 @@ class ReadApdmH5(BaseProcess): sensor_location : str Sensor location to get data from. Looks at the `Label 0` key to find the desired sensor. + localize_timestamps : bool, optional + Convert timestamps to local time from UTC. Default is True. Uses APDM's + timezone offset attribute for the sensor being extracted. gravity_acceleration : float, optional Acceleration due to gravity. Used to convert values to units of `g`. Default is 9.81 m/s^2. @@ -46,10 +49,11 @@ class ReadApdmH5(BaseProcess): - Sternum """ - def __init__(self, sensor_location, gravity_acceleration=9.81, ext_error="warn"): + def __init__(self, sensor_location, localize_timestamps=True, gravity_acceleration=9.81, ext_error="warn"): super().__init__( # kwargs sensor_location=sensor_location, + localize_timestamps=localize_timestamps, gravity_acceleration=gravity_acceleration, ext_error=ext_error, ) @@ -59,6 +63,7 @@ def __init__(self, sensor_location, gravity_acceleration=9.81, ext_error="warn") else: raise ValueError("`ext_error` must be one of 'raise', 'warn', 'skip'.") + self.localize_time = localize_timestamps self.sens = sensor_location self.g = gravity_acceleration @@ -113,4 +118,12 @@ def predict(self, *, file, **kwargs): res[self._gyro] = f["Sensors"][sid]["Gyroscope"][()] res[self._temp] = f["Sensors"][sid]["Temperature"][()] + # if we are converting to local time + if self.localize_time: + offset_hours = f['Sensors'][sid]['Configuration'].attrs["Timezone Offset"] + # convert to seconds + offset_sec = offset_hours * 3600.0 + + res[self._time] += offset_sec + return res From b2be31ff6e9d49f221be71e001c887b9c48ecc3d Mon Sep 17 00:00:00 2001 From: Lukas Adamowicz Date: Fri, 1 Mar 2024 13:56:30 -0500 Subject: [PATCH 13/15] convert offset to float and add tz offset conversion to tests for APDM --- src/skdh/io/apdm.py | 2 +- tests/io/test_apdm.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/skdh/io/apdm.py b/src/skdh/io/apdm.py index cc67ef46..eed57ae9 100644 --- a/src/skdh/io/apdm.py +++ b/src/skdh/io/apdm.py @@ -120,7 +120,7 @@ def predict(self, *, file, **kwargs): # if we are converting to local time if self.localize_time: - offset_hours = f['Sensors'][sid]['Configuration'].attrs["Timezone Offset"] + offset_hours = float(f['Sensors'][sid]['Configuration'].attrs["Timezone Offset"]) # convert to seconds offset_sec = offset_hours * 3600.0 diff --git a/tests/io/test_apdm.py b/tests/io/test_apdm.py index 8493b84c..636f979f 100644 --- a/tests/io/test_apdm.py +++ b/tests/io/test_apdm.py @@ -10,12 +10,12 @@ class TestApdmReader: def test(self, apdm_file): - res = ReadApdmH5("Lumbar", gravity_acceleration=9.81).predict(file=apdm_file) + res = ReadApdmH5("Lumbar", localize_timestamps=True, gravity_acceleration=9.81).predict(file=apdm_file) lumbar_sens = "XI-010284" with h5py.File(apdm_file) as f: acc = f["Sensors"][lumbar_sens]["Accelerometer"][()] / 9.81 - time = f["Sensors"][lumbar_sens]["Time"][()] / 1e6 # to seconds + time = f["Sensors"][lumbar_sens]["Time"][()] / 1e6 - 5 * 3600 # to seconds, convert to local gyro = f["Sensors"][lumbar_sens]["Gyroscope"][()] temp = f["Sensors"][lumbar_sens]["Temperature"][()] From ed58a5cb505910dde330e07e20f70dee0e95f018 Mon Sep 17 00:00:00 2001 From: Lukas Adamowicz Date: Fri, 1 Mar 2024 14:22:14 -0500 Subject: [PATCH 14/15] APDM test tweaks --- tests/io/test_apdm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/io/test_apdm.py b/tests/io/test_apdm.py index 636f979f..b2b7d9b7 100644 --- a/tests/io/test_apdm.py +++ b/tests/io/test_apdm.py @@ -15,7 +15,7 @@ def test(self, apdm_file): lumbar_sens = "XI-010284" with h5py.File(apdm_file) as f: acc = f["Sensors"][lumbar_sens]["Accelerometer"][()] / 9.81 - time = f["Sensors"][lumbar_sens]["Time"][()] / 1e6 - 5 * 3600 # to seconds, convert to local + time = f["Sensors"][lumbar_sens]["Time"][()] / 1e6 - 4 * 3600 # to seconds, convert to local gyro = f["Sensors"][lumbar_sens]["Gyroscope"][()] temp = f["Sensors"][lumbar_sens]["Temperature"][()] From 8a2f96d7437dc1f9167405891a619cb760ea0d7d Mon Sep 17 00:00:00 2001 From: Lukas Adamowicz Date: Fri, 1 Mar 2024 14:22:39 -0500 Subject: [PATCH 15/15] version bump --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index f6bd72b8..874aa520 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project( 'scikit-digital-health', 'c', - version: '0.14.0', + version: '0.14.1', license: 'MIT', meson_version: '>=1.1', )