---
title: HRF Generators
author: Bradley R. Buchsbaum
date: '`r Sys.Date()`'
output:
  albersdown::albers_vignette:
    family: red
    preset: interaction
    toc: yes
    toc_depth: 2.0

vignette: |
  %\VignetteIndexEntry{HRF Generators}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  # Sharper website figures; keep the CRAN vignette archive compact.
  fig.retina = if (identical(Sys.getenv("IN_PKGDOWN"), "true")) 2 else 1,
  fig.width = 7,
  fig.height = 4,
  message = FALSE,
  warning = FALSE
)
# CRAN builds: skip dark-mode figure twins to keep the source package small;
# the pkgdown site (IN_PKGDOWN = "true") keeps them.
if (!identical(Sys.getenv("IN_PKGDOWN"), "true")) {
  options(albersdown.dark_figures = FALSE)
}
library(fmrihrf)
library(ggplot2)
library(dplyr)
library(tidyr)
```

## Why Generators?

Most pre-defined HRFs in `fmrihrf` (like `HRF_SPMG1` or `HRF_GAUSSIAN`) are ready-to-use objects.
However, some HRFs are actually *generators*. A generator is a function that
creates a new HRF object when you call it. This allows you to specify the number
of basis functions (`nbasis`) and the time span (`span`) at creation time.

The library provides generators for flexible basis sets such as B-splines and
finite impulse response (FIR) models. They are available through the internal
`HRF_REGISTRY` and are also returned by `list_available_hrfs()` with type
"generator".

```{r list-generators}
list_available_hrfs(details = TRUE) %>%
  dplyr::filter(type == "generator")
```

## Creating a Basis with a Generator

To obtain an actual HRF object from a generator, simply call the generator
function with your desired parameters. For example, to create a B-spline basis
with 8 functions spanning 32 seconds:

```{r create-basis}
# Create a B-spline basis using gen_hrf
bs8 <- gen_hrf(hrf_bspline, N = 8, span = 32)
print(bs8)
```

The returned value is a standard `HRF` object, so you can evaluate it or use it
in model formulas like any other HRF.

```{r eval-basis}
times <- seq(0, 32, by = 0.5)
mat <- bs8(times)
head(mat)
```

## Visualising FIR Basis Functions

A finite impulse response (FIR) basis makes no assumption about the shape of
the response: each basis function is a boxcar covering one time bin after the
event, and the fitted weights trace out the response bin by bin. Here we
create a basis with 10 bins over a 20-second window; each bin is a 2-second
boxcar, labelled at its top:

```{r fir-basis, fig.alt="Ten FIR basis functions, each a 2 second boxcar of height 1 labelled B1 to B10; bin k covers 2(k-1) to 2k seconds after the event, so together they tile 0 to 20 seconds."}
fir10 <- hrf_fir_generator(nbasis = 10, span = 20)
print(fir10)

plot_hrfs(fir10, time = seq(0, 22, by = 0.02),
          title = "FIR basis: 10 bins of 2 s")
```

<!-- ## Using `getHRF`

The helper `getHRF()` is an internal function that selects either a pre-defined object or a generator based on
name. This functionality is not exposed in the public API.

```{r gethrf, eval=FALSE}
# Internal usage only:
# custom_fir <- getHRF("fir", nbasis = 6, span = 18)
# custom_fir
``` -->

## Summary

Generator functions are simple factories that let you customise flexible HRF
bases. They return normal `HRF` objects, which means you can evaluate them,
combine them with decorators, or insert them into regressors just like the
built-in HRFs.
