---
title: "Getting started with dynR"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Getting started with dynR}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment  = "#>",
  message  = FALSE,
  fig.alt  = ""
)
library(dynR)
library(ggplot2)
```

## What is dynamic functional connectivity?

Resting-state fMRI measures the BOLD signal across brain regions over time.
**Static** functional connectivity (FC) compresses this into a single
correlation matrix — the time-averaged co-activation pattern across the
entire scan. Convenient, but it discards everything that changes.

**Dynamic functional connectivity (dynFC)** treats the time dimension
seriously. It asks: does the pattern of co-activation between brain regions
shift during a scan, and can those shifts tell us something about cognition,
clinical state, or neural mechanisms?

`dynR` computes dynFC representations from preprocessed multivariate
timeseries, implementing two complementary families of methods:

| Family | Core functions | What it captures |
|---|---|---|
| **Phase-based** | `hilbert_phases()`, `dyn_phase_lock()`, `kuramoto()` | Instantaneous synchrony via the analytic signal |
| **Correlation-based** | `corr_slide()`, `cofluct()`, `corr_corr()` | Windowed co-activation and edge dynamics |

Both families produce outputs that feed directly into
[`stateR`](https://github.com/CoDe-Neuro/stateR) for brain state
quantification.

---

## When to use which approach

Choosing between phase-based and correlation-based methods depends on your
research question:

| | Phase-based | Correlation-based |
|---|---|---|
| **Temporal resolution** | Frame-by-frame (no window needed) | One estimate per window |
| **Feature dimensionality** | *N* (one eigenvector per timepoint) | *N(N−1)/2* (upper triangle) |
| **Window length choice** | Not required | Critical parameter |
| **Best for** | Synchrony research, tractable state clustering, metastability | Interpretable FC, task-event alignment, edge dynamics |

If you are new to dynFC, the **phase-based / LEiDA** pipeline is a good
starting point: it requires no window length decision and produces compact,
interpretable features. **Sliding-window FC** is more directly comparable to
the broader published literature and easier to relate to task structure or
behavioural events.

---

## Package data

`dynR` ships with a resting-state BOLD fMRI timeseries from the
[edge-ts](https://github.com/brain-networks/edge-ts) repository
(Faskowitz et al., 2020), parcellated into 200 regions of interest. This
dataset is used throughout all three vignettes. The methods themselves are
not restricted to fMRI — they apply equally to EEG, LFP, or any
band-limited neurophysiological signal.

```{r load-data}
data(ts)   # [200 × 600] BOLD timeseries
data(fc)   # [200 × 200] static FC matrix (ground truth)

dim(ts)
dim(fc)
```

200 parcels, 600 timepoints — approximately 20 minutes at TR = 2 s.

---

## Pipeline overview

```
BOLD timeseries [N × Tmax]
        │
        ├─── bandpass_filter()       optional: restrict to 0.01–0.1 Hz
        │
        ├─── PHASE-BASED ─────────────────────────────────────────────
        │     hilbert_phases()   →  instantaneous phases  [N × Tmax]
        │     dyn_phase_lock()   →  dPL matrices + LEiDA eigenvectors
        │     kuramoto()         →  synchrony, metastability, entropy
        │
        └─── CORRELATION-BASED ───────────────────────────────────────
              corr_slide()      →  FC matrices  [N × N × windows]
              cofluct()         →  edge time series + RSS
              corr_corr()       →  FC recurrence  [Tmax × Tmax]
                    │
                    ▼
              stateR  ──  fractional occupancy
                      ──  dwell time
                      ──  Markov transitions
```

---

## Quick example: phase-based pipeline

```{r phase-pipeline}
# Instantaneous phases via the Hilbert transform
phases <- hilbert_phases(ts)

# Dynamic phase-locking matrices + LEiDA eigenvectors
dpl <- dyn_phase_lock(phases)
cat("LEiDA matrix:", nrow(dpl$leida), "timepoints ×",
    ncol(dpl$leida), "parcels\n")

# Kuramoto order parameter
kop <- kuramoto(phases)
cat("Metastability:", round(kop$metastability, 4), "\n")
```

```{r phase-plot, fig.width = 7, fig.height = 3}
ggplot(data.frame(t = seq_along(kop$synchrony), R = kop$synchrony),
       aes(x = t, y = R)) +
  geom_line(colour = "#8D9FD7", linewidth = 0.7) +
  geom_hline(yintercept = mean(kop$synchrony),
             colour = "#9E3C30", linetype = "dashed", linewidth = 0.9) +
  scale_y_continuous(limits = c(0, 1)) +
  labs(x = "Timepoint", y = "R(t)",
       title = "Kuramoto order parameter",
       subtitle = paste0("Metastability = ",
                         round(kop$metastability, 4))) +
  theme_minimal(base_size = 13) +
  theme(panel.grid.minor = element_blank())
```

---

## Quick example: correlation-based pipeline

```{r sw-pipeline}
# Sliding-window FC: 30-timepoint windows, step 5
sw <- corr_slide(ts, window = 30, step = 5)
cat("Windows:", dim(sw$corr_mats)[3], "\n")

# Edge-centric cofluctuations
ec <- cofluct(ts)
cat("Edges:", nrow(ec$edge_ts), "× Timepoints:", ncol(ec$edge_ts), "\n")
```

```{r sw-plot, fig.width = 7, fig.height = 3}
ggplot(data.frame(t = seq_along(ec$rss), rss = ec$rss),
       aes(x = t, y = rss)) +
  geom_line(colour = "#8D9FD7", linewidth = 0.7) +
  geom_hline(yintercept = mean(ec$rss) + 2 * sd(ec$rss),
             colour = "#9E3C30", linetype = "dashed", linewidth = 0.9) +
  labs(x = "Timepoint", y = "RSS",
       title = "Root-sum-square cofluctuation",
       subtitle = "Dashed line: mean + 2 SD") +
  theme_minimal(base_size = 13) +
  theme(panel.grid.minor = element_blank())
```

---

## Sanity check: single window equals static FC

A single window spanning the full timeseries must recover the static FC matrix
exactly — a useful first validation for any new dataset.

```{r sanity}
full_window <- corr_slide(ts, window = ncol(ts))
max_diff    <- max(abs(full_window$corr_mats[, , 1] - fc))
cat("Max deviation from static FC:", formatC(max_diff, format = "e"), "\n")
```

---

## Further reading

- `vignette("phase-based-fc")` — Hilbert transform, LEiDA, K-means, and the Kuramoto order parameter in depth
- `vignette("sliding-window-fc")` — window length trade-offs, edge cofluctuations, and FC recurrence
- [`stateR`](https://github.com/CoDe-Neuro/stateR) — downstream brain state metrics

---

## References

Faskowitz, J. et al. (2020). Edge-centric functional network representations
of human cerebral cortex reveal overlapping system-level architecture.
*Nature Neuroscience*, 23(12), 1644–1654.
https://doi.org/10.1038/s41593-020-00719-y
