Skip to content

Commit

Permalink
Adds TIB algorithm implementation (#22)
Browse files Browse the repository at this point in the history
* adds implementation of TIB algorithm

* updates quick start docs
  • Loading branch information
Trybnetic authored Feb 28, 2024
1 parent cc7f3bd commit 32f8f95
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 13 deletions.
9 changes: 3 additions & 6 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ examples and more information on the functions can be found in the documentation
data, sample_freq = paat.read_gt3x('path/to/gt3x/file')
# Detect non-wear time
data.loc[:, "Non Wear Time"] = paat.detect_non_wear_time_syed2021(data, sample_freq)
data.loc[:, "Non Wear Time"] = paat.detect_non_wear_time_hees2011(data, sample_freq)
# Detect sleep episodes
data.loc[:, "Sleep"] = paat.detect_sleep_weitz2022(data, sample_freq)
data.loc[:, "Sleep"] = paat.detect_time_in_bed_weitz2024(data, sample_freq)
# Classify moderate-to-vigorous and sedentary behavior
data.loc[:, ["MVPA", "SB"]] = paat.calculate_pa_levels(data, sample_freq)
Expand All @@ -58,9 +58,6 @@ examples and more information on the functions can be found in the documentation
.. note::

In this example, methods of `Syed et al. (2021) <https://doi.org/10.1038/s41598-021-87757-z>`_
and `Weitz et al. (2022) <https://www.medrxiv.org/content/10.1101/2022.03.07.22270992>`_ and activity
thresholds of `Sanders et al. (2019) <https://doi.org/10.1080/02640414.2018.1555904>`_.
However, these are only examples. There are multiple methods implemented in PAAT
Note that these are only examples. There are multiple methods implemented in PAAT
and the processing pipeline can easily be adjusted to individual needs. More examples
can be found in the examples section.
2 changes: 1 addition & 1 deletion paat/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from .estimates import calculate_pa_levels, create_activity_column
from .features import calculate_actigraph_counts, calculate_vector_magnitude, calculate_brond_counts
from .io import read_gt3x
from .sleep import detect_sleep_weitz2022, detect_sleep_triaxial_weitz2022
from .sleep import detect_sleep_weitz2022, detect_sleep_triaxial_weitz2022, detect_time_in_bed_weitz2024
from .wear_time import detect_non_wear_time_naive, detect_non_wear_time_hees2011, detect_non_wear_time_syed2021

try:
Expand Down
Binary file added paat/models/TIB_model.h5
Binary file not shown.
68 changes: 67 additions & 1 deletion paat/sleep.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,16 @@
import numpy as np
from torch import nn
import torch
import tensorflow as tf
from tensorflow.keras import models

from . import features
# Hide GPU from visible devices
tf.config.set_visible_devices([], 'GPU')
#tf.compat.v1.disable_eager_execution()

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

from . import features

class _SleepModel(nn.Module):
def __init__(self, input_dim, hid_dim, output_dim, n_layers, dropout, batch_first=False):
Expand Down Expand Up @@ -49,6 +56,9 @@ def detect_sleep_weitz2022(data, sample_freq, means=None, stds=None):
"""
Infer time in bed from raw acceleration signal using frequency features.
.. warning::
This method turned out to work not as accurately as initially thought. Use with care!
Parameters
----------
data : DataFrame
Expand Down Expand Up @@ -101,6 +111,9 @@ def detect_sleep_triaxial_weitz2022(data, sample_freq, resampled_frequency="1min
"""
Infer time in bed from raw acceleration signal.
.. warning::
This method turned out to work not as accurately as initially thought. Use with care!
Parameters
----------
data : DataFrame
Expand Down Expand Up @@ -154,3 +167,56 @@ def detect_sleep_triaxial_weitz2022(data, sample_freq, resampled_frequency="1min
predictions = np.repeat(predictions, seconds * sample_freq)

return predictions

def detect_time_in_bed_weitz2024(data, sample_freq, resampled_frequency="1min", means=None, stds=None, model=None):
"""
Infer time in bed from raw acceleration signal.
Parameters
----------
data : DataFrame
a DataFrame containg the raw acceleration data
sample_freq : int
the sampling frequency in which the data was recorded
resampled_frequency : str (optional)
a str indicating to what frequency the data should be resampled. This depends
on the model used to predict, defaults to 1min.
means : array_like (optional)
a numpy array with the channel means, will be calculated for the sample
if not specified
stds : array_like (optional)
a numpy array with the channel stds, will be calculated for the sample
if not specified
model : nn.Module (optional)
a loaded pytorch custom model.
Returns
-------
predicted_time_in_bed : np.array (n_samples,)
a numpy array indicating whether the values of the acceleration data were spent in bed
"""
if resampled_frequency:
data = data[['X', 'Y', 'Z']].resample(resampled_frequency).mean()

X = data.reset_index()[["Y", "X", "Z"]].values.copy()

# If no means and stds are given, calculate subject's mean and std
# to normalize by this
if not means or not stds:
means, stds = X.mean(axis=0), X.std(axis=0)

# Normalize input
X = (X - means) / stds

# Load model if not specified
if not model:
model_path = os.path.join(os.path.pardir, os.path.dirname(__file__), 'models', 'TIB_model.h5')
model = models.load_model(model_path)

predictions = (model.predict(X[np.newaxis], verbose=0).squeeze() >= .5)

seconds = pd.Timedelta(resampled_frequency).seconds
predictions = np.repeat(predictions, seconds * sample_freq)

return predictions
9 changes: 4 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "paat"
version = "1.0.0-beta.2"
version = "1.0.0b3"
description = "A comprehensive toolbox to analyse and model raw physical activity data"

license = "MIT"
Expand Down Expand Up @@ -28,15 +28,14 @@ classifiers = [

[tool.poetry.dependencies]
python = ">=3.9,<3.11" # Compatible python versions must be declared here
pandas = "^1.2.4"
scipy = "^1.6.2"
pandas = "^1.5.3"
psutil = "^5.8.0"
glob2 = "^0.7"
resampy = "^0.2.2"
joblib = "^1.0.1"
numpy = "^1.20.3"
numpy = "1.23.5"
bitstring = "^3.1.7"
tensorflow = "^2.7.0"
tensorflow = "^2.11.0"
torch = "^1.10.1"
agcounts = "^0.1.1"
toml = "^0.10.2"
Expand Down

0 comments on commit 32f8f95

Please sign in to comment.