
<!-- README.md is generated from README.Rmd. Edit the .Rmd and re-knit. -->

# actiRhythm <img src="man/figures/logo.png" align="right" height="139" alt="actiRhythm hex logo" />

<!-- badges: start -->

[![R-CMD-check](https://github.com/rdazadda/actiRhythm/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/rdazadda/actiRhythm/actions/workflows/R-CMD-check.yaml)
[![License:
MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
<!-- badges: end -->

**actiRhythm turns activity counts or raw acceleration into the full set
of circadian rest-activity measures.** It reads ActiGraph `.agd` counts
and raw `.gt3x`, `.cwa`, and `.bin` recordings, auto-calibrates the raw
signal, and derives the ENMO, MAD, and z-angle metrics that agree with
GGIR. From a single recording it computes what a chronobiology analysis
reports, from the nonparametric measures and cosinor through
periodograms and fractal structure to wavelet and empirical-mode
decomposition, sleep scoring, and a hidden Markov rest-activity model.
Methods that usually live in separate packages, or in no R package at
all, sit behind one consistent interface, and every analysis returns a
typed object that prints its own summary and draws its own plots.

Each method carries the reference that defined it, and where a trusted
implementation already exists, actiRhythm is checked against it: the raw
metrics against GGIR, the single-component cosinor against the `cosinor`
package, and the nonparametric measures against `nparACT` and `ActCR`.
Those cross-checks run live in the package’s [validation
article](https://rdazadda.github.io/actiRhythm/articles/validation.html).

You can usually see the answer before you compute it. Plot a recording
as an actogram and a regular sleeper forms a single vertical band of
activity at the same clock time each day, while a drifting rhythm
scatters across the panel. The numbers that follow put a figure to what
the picture shows, from Witting (1990) and van Someren (1999) through
Cornelissen (2014) and the periodogram.

## Installation

``` r
# install.packages("remotes")
remotes::install_github("rdazadda/actiRhythm")
```

actiRhythm needs R 4.1 or newer and a C++17 compiler (Rtools on Windows,
the Xcode command-line tools on macOS) for the small backend behind its
nonparametric metrics.

## A first analysis

One ActiGraph recording ships with the package, so this runs without any
data of your own. The bundled file is a single de-identified
60-second-epoch recording, included only so the examples run.

``` r
library(actiRhythm)

# Read the bundled .agd and pull the count series
agd <- agd.counts(read.agd(example_agd(1), verbose = FALSE))

# Describe the rest-activity rhythm without assuming a waveform
rhythm <- circadian.rhythm(agd$axis1, agd$timestamp)
rhythm
#> 
#> Circadian Rhythm Analysis
#> 
#> Data Summary
#>   Days analyzed:            8
#>   Valid circadian days:     6
#>   Epoch length:             60 seconds
#> 
#> Non-Parametric Metrics (IS/IV: Witting et al. 1990; RA/L5/M10: van Someren et al. 1999)
#>   L5 (least active 5h):     6.10 counts/min, onset 01:28
#>   M10 (most active 10h):    602.93 counts/min, onset 12:02
#>   L1 (least active 1h):     3.10 counts/min, onset 02:35
#>   M1 (most active 1h):      1175.51 counts/min, onset 17:43
#>   Relative Amplitude (RA):  0.9800 (range 0-1, higher=stronger rhythm)
#>   Interdaily Stability (IS): 0.2279 (range 0-1, higher=more consistent)
#>   Intradaily Variability (IV): 1.0008 (near 0 = sine, near 2 = noise)
#>   Phi (autocorrelation):    0.4151 (higher=more predictable)
#> 
#> Sleep-Based & Variability Metrics
#>   Sleep Regularity Index:   Not calculated (requires sleep_state input)
#>   Onset timing variability: 2.23 hours
#>   L5 timing variability:    0.77 hours (circular SD)
#>   M10 timing variability:   3.70 hours (circular SD)
#> 
#> References: Witting (1990), van Someren (1999)
```

The actogram is usually the first thing worth plotting.

``` r
plot_actogram(agd$axis1, agd$timestamp)
```

<div class="figure">

<img src="man/figures/README-actogram-1.png" alt="Double-plotted actogram: each row is one day shown twice across 48 hours, so a stable rhythm forms a vertical band of activity at the same clock time each day, while scattered fill marks a fragmented or shifting rhythm." width="100%" />
<p class="caption">

Double-plotted actogram: each row is one day shown twice across 48
hours, so a stable rhythm forms a vertical band of activity at the same
clock time each day, while scattered fill marks a fragmented or shifting
rhythm.
</p>

</div>

For this recording a high relative amplitude near 0.98 sits with a low
interdaily stability near 0.23: the days are strongly active, but the
pattern does not land at the same clock time from one day to the next.
Every number and figure here regenerates from the installed package and
its bundled recording, and the calculations behind them are exercised by
the package’s test suite.

## What the package covers

**Cosinor and the spectrum.** `cosinor.analysis()` fits a 24-hour cosine
(Cornelissen 2014) and `rhythmicity.test()` checks whether the rhythm is
statistically real; `cosinor.multicomponent()` adds harmonics and
`population.cosinor()` compares groups. `circadian.period()` estimates
the free-running period from a Lomb-Scargle periodogram (Lomb 1976) and
`chi.sq.periodogram()` from the chi-square periodogram (Sokolove and
Bushell 1978); `period.ci()` puts a bootstrap interval on it, and
`circadian.spectrogram()` shows how the period drifts across the
recording. `fractal.dfa()` measures the long-range correlation in the
series (Peng et al. 1994), and `mfdfa()` and `multiscale.entropy()`
describe its finer nonlinear structure.

**Rhythms that move rather than repeat.** A set of nonstationary methods
reads the change directly. `circadian.wavelet()` returns the
time-frequency power surface with its cone of influence,
`circadian.emd()` with `hilbert.huang()` give a data-adaptive
decomposition and an instantaneous period, and `circadian.ssa()`
separates the series into trend, circadian, and residual components.
`circadian.flm()` fits a functional model of the daily profile,
`rest.hmm()` infers rest and active states with a hidden Markov model,
`sleep.changepoints()` locates each night’s onset and wake straight from
the counts (Chen and Sun 2024), and `curve.registration()` aligns the
days on their active-phase landmark for a scale-invariant phase marker.

**Sleep, regularity, and fragmentation.** `sleep.cole.kripke()` and
`sleep.sadeh()` score each epoch as sleep or wake (Cole et al. 1992;
Sadeh et al. 1994). `rest.periods()` (Roenneberg et al. 2015) returns
every consolidated rest bout, naps included, while `rest.crespo()`
(Crespo et al. 2012) detects the main daily rest periods.
`sleep.regularity.index()` (Phillips et al. 2017), `social.jet.lag()`,
and `lids()` (Winnebeck 2018) summarise sleep regularity, chronotype
misalignment, and the ultradian sleep cycle, and `phase.concentration()`
and `state.transitions()` test day-to-day phase clustering and
rest-activity fragmentation.

**From files to counts to raw acceleration.** Counts can come from more
than `.agd` files: `read.actigraph.csv()` reads ActiLife epoch CSVs, and
`read.raw()` turns raw `.gt3x`, `.cwa`, and `.bin` files into counts
with the agcounts implementation of the ActiGraph count algorithm
(Neishabouri 2022); `gt3x.counts()`, `axivity.counts()`, and
`geneactiv.counts()` do the same per brand, with cross-brand counts
treated as an approximation rather than native ActiGraph output.
`raw.metrics()` returns per-epoch ENMO, MAD, and the z-angle with van
Hees (2014) auto-calibration, and `circadian.raw()` runs every method
above on ENMO from one call. The z-angle drives a diary-free sleep
pipeline that counts cannot: `rest.spt()` finds the nightly sleep-period
window (HDCZA, van Hees et al. 2018), `sib.vanhees()` scores
sustained-inactivity bouts (van Hees et al. 2015), and
`sleep.from.spt()` reports onset, wake, WASO, and efficiency.
`detect.nonwear.choi()`, `detect.nonwear.troiano()`, and
`detect.nonwear.raw()` flag non-wear time (Choi et al. 2011; Troiano et
al. 2008; van Hees et al. 2013).

**Plots and batch reports.** Every analysis prints a readable summary
and draws a themed `ggplot`: the actogram and periodogram, the
spectrogram, the cosinor fit and confidence ellipse, the wavelet
scalogram, the singular-spectrum components, a circular phase rose, and
a rest-detector comparison strip, each one you can recolour with
`theme_actiRhythm()` and save with `save.circadian.plot()`. When a study
has many files, `circadian.batch()` runs the whole pipeline over a
folder and returns one row per recording, and `circadian.workbook()`
writes the full analysis to a multi-sheet Excel file.

## Documentation

The package website, <https://rdazadda.github.io/actiRhythm/>, collects
the full documentation. `vignette("actiRhythm")` is the get-started
walkthrough and `vignette("output-codebook")` is a data dictionary for
every metric the package reports. A set of articles goes deeper:
[Choosing a
method](https://rdazadda.github.io/actiRhythm/articles/choosing-a-method.html)
maps each question to the right function, [Validation against reference
packages](https://rdazadda.github.io/actiRhythm/articles/validation.html)
cross-checks the metrics live against GGIR, `nparACT`, `ActCR`, and the
`cosinor` package, and the method-family articles (nonparametric,
cosinor, period, fractal, nonstationary, phase and regularity, sleep,
raw acceleration, batch) each work one family from the math to a worked
example. Every function’s help page also carries its method reference,
so `?circadian.rhythm`, `?cosinor.analysis`, and `?circadian.period` are
good places to read more. Questions and bug reports go to the issue
tracker at <https://github.com/rdazadda/actiRhythm/issues>, and
contributions are welcome.

## Citation

Run `citation("actiRhythm")` for the entry to use in published work.
When you publish results, report the version you ran, from
`packageVersion("actiRhythm")`, so the analysis stays reproducible
across releases.

## License

MIT, see [LICENSE](LICENSE).

actiRhythm is developed and maintained by the Center for Alaska Native
Health Research at the University of Alaska Fairbanks.
