---
title: "Physical activity intensity from ActTrust/GT3X+ counts"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Physical activity intensity from ActTrust/GT3X+ counts}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(
  collapse  = TRUE,
  comment   = "#>",
  fig.width = 9,
  fig.height = 5,
  dpi       = 150,
  out.width = "100%"
)
library(zeitR)
if (!requireNamespace("ggplot2", quietly = TRUE)) {
  knitr::opts_chunk$set(eval = FALSE)
  message("ggplot2 is required for the plots in this vignette. Install with install.packages(\"ggplot2\").")
} else {
  library(ggplot2)
}
```

zeitR's pipeline so far has been about one half of the 24 h rest-activity
cycle: sleep. `pa_equations()`, `estimate_ee()`, `classify_pa_intensity()`,
and `classify_pa_counts()` add the other half -- estimating energy
expenditure (METs) and classifying physical activity (PA) intensity from the
same raw activity counts, using equations published in Batista et al. (2026,
*PLoS ONE*, [doi.org/10.1371/journal.pone.0348631](https://doi.org/10.1371/journal.pone.0348631)).

**Read `?pa_equations` before using this in a real analysis.** These
equations come from a single controlled-treadmill validation study, and the
help page spells out exactly what that does and doesn't license (population,
device, modelling caveats). This vignette shows the mechanics; it isn't a
substitute for that discussion.

---

## The equation

The source study fits `sqrt(MET) ~ sqrt(activity_counts) * device_placement`
via a linear model on indirect-calorimetry data, then reports the fitted
coefficients (their Table 2). zeitR doesn't re-fit that model -- it can't,
without breath-by-breath VO2 data -- it applies the *published* coefficients
directly:

$$\text{MET} = \left(\beta_0 + \beta_1 \sqrt{\text{activity\_counts}}\right)^2$$

`pa_equations()` returns this table for all four device x placement
combinations the source study validated:

```{r equations}
pa_equations()
```

`ACTT` is Condor Instruments' ActTrust device (PIM mode); `GT3X+` is
ActiGraph's GT3X+ (vector magnitude). `cut3`/`cut6`/`cut9` are the published
count/min cut-points at the 3, 6, and 9 MET thresholds -- provided for
reference; the functions below classify on estimated METs directly rather
than re-deriving these.

---

## Estimating METs from counts

`estimate_ee()` applies the equation for a given device and placement:

```{r estimate}
counts <- c(0, 1000, 5000, 25000, 50000)
estimate_ee(counts, device = "ACTT", placement = "hip")
```

Placement matters -- the same count value implies different METs at the hip
than at the wrist, since wrist movement is a noisier proxy for whole-body
energy expenditure:

```{r estimate-placement}
data.frame(
  counts = counts,
  hip    = estimate_ee(counts, device = "ACTT", placement = "hip"),
  wrist  = estimate_ee(counts, device = "ACTT", placement = "wrist")
)
```

---

## Classifying PA intensity

`classify_pa_intensity()` bins any MET value into the four WHO-style
intensity bands (light, moderate, vigorous, very vigorous) used throughout
the source study:

```{r classify-mets}
mets <- estimate_ee(counts, device = "ACTT", placement = "hip")
classify_pa_intensity(mets)
```

`classify_pa_counts()` combines the two steps -- counts straight to an
intensity factor -- for the common case where you don't need the
intermediate MET values:

```{r classify-counts}
classify_pa_counts(counts, device = "ACTT", placement = "hip")
```

---

## Applying it to a real recording

The bundled ActTrust recording used elsewhere in zeitR's vignettes was
collected in `PIM/TAT/ZCM` mode (see its header), so its `activity` column
is already PIM counts/min -- the exact input `estimate_ee()`/
`classify_pa_counts()` expect for `device = "ACTT"`. ActTrust is normally
worn on the wrist for sleep monitoring, so `placement = "wrist"` is the
appropriate choice here.

```{r pipeline}
FILE <- system.file("extdata", "input1.txt", package = "zeitR")
TZ   <- "America/Sao_Paulo"

result <- run_pipeline_native(FILE, tz = TZ, quiet = TRUE)

result$data$pa_intensity <- classify_pa_counts(
  result$data$activity,
  device    = "ACTT",
  placement = "wrist"
)

table(result$data$pa_intensity)
```

Remember what this recording actually represents before over-reading that
table: the source equations were fit on a controlled treadmill protocol
(walking/running, 3-9 km/h), not free-living daily activity. Applying them
to a full multi-day free-living recording -- as done here -- is exactly the
kind of extrapolation flagged in `?pa_equations`. Treat the resulting
intensity labels as illustrative of the mechanics, not as a validated
free-living PA measure.

A quick visual of intensity across the whole recording:

```{r pa-plot, fig.height = 4}
daily <- result$data
daily$date <- as.Date(daily$datetime)
daily <- aggregate(list(n = daily$activity), by = list(
  date = daily$date, pa_intensity = daily$pa_intensity
), FUN = length)

ggplot(daily, aes(x = date, y = n, fill = pa_intensity)) +
  geom_col(width = 1) +
  scale_fill_manual(
    values = c(light = "#D9C8A0", moderate = "#F0A500",
               vigorous = "#C25E2A", very_vigorous = "#2D2640"),
    drop = FALSE
  ) +
  labs(x = NULL, y = "Epochs/day", fill = "PA intensity") +
  theme_minimal(base_size = 12)
```

---

## Choosing an equation set

`equation_set` is exposed as an explicit argument on all four functions
(default, and currently only, `"batista2026"`) so that a future validation
study -- covering a different population, device, or free-living protocol --
can be added later as an alternative set without changing this API:

```{r future-set, eval = FALSE}
# Not yet available -- illustrative only
estimate_ee(counts, device = "ACTT", placement = "wrist",
            equation_set = "some_future_study")
```

---

## Next steps

- `?pa_equations` -- the full generalisability discussion: sample
  characteristics, cross-study cut-point variability, and why the GT3X+
  equations here are diagnosable against Sasaki et al. (2011)'s transparent
  two-regression model but not against Santos-Lozano et al. (2013)'s ANN
- `vignette("sleep-analysis")` -- the sleep half of the 24 h cycle
- `?compute_sleep_metrics`, `?compute_cpd_metrics` -- combine with PA
  intensity for a fuller rest-activity picture
