Skip to content

jhuwit/walking

Repository files navigation

walking

R-CMD-check

The goal of walking is to provide some algorithms to detect walking in tri-axial accelerometers.

Installation

You can install the development version of walking from GitHub with:

# install.packages("devtools")
devtools::install_github("muschellij2/walking")

walking no longer tries to install forest for you. Install forest in your own Python environment first, then load walking from R.

If you hit clang++: error: unsupported option '-fopenmp' or the LLVM mismatch described in onnela-lab/forest#293 and numba/llvmlite#1389, use a Python environment where forest and its dependencies already resolve cleanly, then point reticulate at that environment with use_condaenv() or use_python().

Example

This is a basic example which shows you how to solve a common problem:

library(walking)
csv_file = system.file("test_data_bout.csv", package = "walking")
x = readr::read_csv(csv_file)
#> Rows: 98 Columns: 6
#> ── Column specification ────────────────────────────────────────────────────────
#> Delimiter: ","
#> chr  (1): accuracy
#> dbl  (4): timestamp, x, y, z
#> dttm (1): UTC time
#> 
#> ℹ Use `spec()` to retrieve the full column specification for this data.
#> ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
colnames(x)[colnames(x) == "UTC time"] = "time"
res = find_walking(data = x)
#> Preprocessing Bout
#> Bout is Preprocessed
#> OAK: Find walking is done
print(res)
#>                   time steps
#> 1  2020-02-25 18:18:31  1.65
#> 2  2020-02-25 18:18:32  1.60
#> 3  2020-02-25 18:18:33  1.55
#> 4  2020-02-25 18:18:34  1.60
#> 5  2020-02-25 18:18:35  1.55
#> 6  2020-02-25 18:18:36  1.85
#> 7  2020-02-25 18:18:37  1.80
#> 8  2020-02-25 18:18:38  1.75
#> 9  2020-02-25 18:18:39  1.75
#> 10 2020-02-25 18:18:40  1.70

Potential Conflicts

Running forest and stepcount.

The two Python modules (forest and stepcount) can have different conflicts of python dependencies and python versions. You can do specific call-outs with callr to try to resolve this:

Running Walking with Different Python Environments

If you want to use both walking estimation from forest and stepcount, you can run them in separate R processes using callr to avoid Python package conflicts. Here’s how you can do it:

library(callr)
library(stepcount)
#> Warning in reticulate::py_require("stepcount>=3.11.0", python_version = "3.10"): Python version requirements cannot be changed after Python has been initialized.
#> * Python version request: '3.10' (from package:stepcount)
#> * Python version initialized: '3.11.15'
csv_file = system.file("test_data_bout.csv", package = "walking")
data = readr::read_csv(csv_file)
#> Rows: 98 Columns: 6
#> ── Column specification ────────────────────────────────────────────────────────
#> Delimiter: ","
#> chr  (1): accuracy
#> dbl  (4): timestamp, x, y, z
#> dttm (1): UTC time
#> 
#> ℹ Use `spec()` to retrieve the full column specification for this data.
#> ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
colnames(data)[colnames(data) == "UTC time"] = "time"

stepcount_callr = function(data,
                           ...) {
  
  reticulate::py_require("stepcount==3.11.0", python_version = "3.10")
  sc <- reticulate::import("stepcount")
  stepcount::stepcount_check()
  
  res = stepcount::stepcount(data, ...)
  return(res)
}

# 2. Run the isolated background R process
result <- callr::r(
  func = stepcount_callr,
  show = TRUE,
  args = list(data = data) # Safely injects data into the process
)
#> Loading model...
#> Downloading https://wearables-files.ndph.ox.ac.uk/files/models/stepcount/ssl-20230208.joblib.lzma...
#> Checking Data
#> Writing file to CSV...
#> Reading in Data for Stepcount
#> /Users/johnmuschelli/Library/Caches/org.R-project.R/R/reticulate/uv/cache/archive-v0/12AzDesQwp07_KC6/lib/python3.10/site-packages/actipy/processing.py:387: UserWarning: Skipping calibration: Insufficient stationary samples: 0 < 50
#>   warnings.warn(f"Skipping calibration: Insufficient stationary samples: {len(xyz)} < {calib_min_samples}")
#> Predicting from Model
#> Running step counter...
#> Gravity calibration...Gravity calibration... Done! (0.01s)
#> Nonwear detection...Nonwear detection... Done! (0.01s)
#> Resampling...Resampling... Done! (0.03s)
#> Defining windows...
#>   0%|          | 0/1 [00:00<?, ?it/s]100%|██████████| 1/1 [00:00<00:00, 506.07it/s]
#> /Users/johnmuschelli/Library/Caches/org.R-project.R/R/reticulate/uv/cache/archive-v0/12AzDesQwp07_KC6/lib/python3.10/site-packages/stepcount/models.py:467: UserWarning: No data to predict
#>   warnings.warn("No data to predict")
#> Processing Result
#> Using local /Users/johnmuschelli/Library/Caches/org.R-project.R/R/reticulate/uv/cache/archive-v0/12AzDesQwp07_KC6/lib/python3.10/site-packages/stepcount/torch_hub_cache/OxWearables_ssl-wearables_v1.0.0
#> /usr/local/Cellar/python@3.10/3.10.20_1/Frameworks/Python.framework/Versions/3.10/lib/python3.10/multiprocessing/resource_tracker.py:224: UserWarning: resource_tracker: There appear to be 1 leaked semaphore objects to clean up at shutdown
#>   warnings.warn('resource_tracker: There appear to be %d '
head(result)
#> $steps
#> # A tibble: 1 × 2
#>   time                steps
#>   <dttm>              <dbl>
#> 1 2020-02-25 18:18:31   NaN
#> 
#> $walking
#> # A tibble: 1 × 2
#>   time                walking
#>   <dttm>                <dbl>
#> 1 2020-02-25 18:18:31     NaN
#> 
#> $step_times
#> [1] time
#> <0 rows> (or 0-length row.names)
#> 
#> $info
#> $info$CalibNumSamples
#> [1] 0
#> 
#> $info$`CalibErrorBefore(mg)`
#> [1] NaN
#> 
#> $info$`CalibErrorAfter(mg)`
#> [1] NaN
#> 
#> $info$CalibOK
#> [1] 0
#> 
#> $info$`NonwearTime(days)`
#> [1] 0
#> 
#> $info$NumNonwearEpisodes
#> [1] 0
#> 
#> $info$`WearTime(days)`
#> [1] 0.0001126389
#> 
#> $info$NumInterrupts
#> [1] 0
#> 
#> $info$Covers24hOK
#> [1] 0
#> 
#> $info$ResampleRate
#> [1] 30
#> 
#> $info$NumTicksAfterResample
#> [1] 293
#> 
#> $info$Filename
#> [1] "/private/var/folders/1s/wrtqcpxn685_zk570bnx9_rr0000gr/T/Rtmpteefb1/file4e0f3962f3e5.csv"
#> 
#> $info$Device
#> [1] ".csv"
#> 
#> $info$`Filesize(MB)`
#> [1] 0
#> 
#> $info$SampleRate
#> [1] 10
#> 
#> $info$StartTime
#> [1] "2020-02-25 18:18:31"
#> 
#> $info$EndTime
#> [1] "2020-02-25 18:18:40"

forest_callr = function(data,
                        ...) {
  reticulate::py_require(
    "git+https://github.com/onnela-lab/forest@45fb41038bd46c25d9e6a4442aa74fa03b501317", 
    python_version = "3.11")
  fr = reticulate::import("forest")
  oak = fr$oak$base
  oak
  res = walking::estimate_steps_forest(data, ...)
  return(res)
}

# 2. Run the isolated background R process
fresult <- callr::r(
  func = forest_callr,
  show = TRUE,
  args = list(data = data) # Safely injects data into the process
)
#> Preprocessing Bout
#> Bout is Preprocessed
#> OAK: Find walking is done
head(fresult)
#>                  time steps
#> 1 2020-02-25 18:18:31  1.65
#> 2 2020-02-25 18:18:32  1.60
#> 3 2020-02-25 18:18:33  1.55
#> 4 2020-02-25 18:18:34  1.60
#> 5 2020-02-25 18:18:35  1.55
#> 6 2020-02-25 18:18:36  1.85

About

Interfaces the forest Python module (https://github.com/onnela-lab/forest) to segment walking and other activities from accelerometry data.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages