# FunctionalGAM


Scalar-on-function GAM.


Usage

``` python
FunctionalGAM(
    response,
    functional_terms,
    *,
    scalar_terms=None,
    family=None,
)
```


Fits a model where the response is scalar but one or more predictors are functional, i.e. each observation carries an entire curve `X_i(t)` measured over a domain (such as a temperature profile over time, or a spectral curve over wavelength), rather than a single number. Each functional covariate contributes a linear functional term to the predictor,

\int X_i(t)\\\beta(t)\\dt,

where `beta(t)` is an unknown smooth coefficient function that must itself be estimated. This integral is approximated numerically (trapezoidal quadrature over the observed grid) and `beta(t)` is expanded in a B-spline or Fourier basis with a roughness penalty, turning the infinite-dimensional problem of estimating a function into a finite penalized regression that can be fit with the same machinery as any other GAM smooth term.

Use [FunctionalGAM](FunctionalGAM.md#whittaker.FunctionalGAM) when your predictors are naturally curves or profiles rather than scalars, and you want to recover how different regions of the domain contribute to the response (e.g. "does temperature early in the season matter more than temperature late in the season?").


## Parameters


`response: str`  
Name of the scalar response variable.

`functional_terms: list[FunctionalTerm | dict]`  
List of [FunctionalTerm](FunctionalTerm.md#whittaker.FunctionalTerm) specifications (or dicts with the same keys), one per functional covariate.

`scalar_terms: str | None = None`  
Optional formula string for additional scalar smooth/linear terms (e.g. `"s(temperature) + humidity"`) fit alongside the functional terms.

`family: Family | None = None`  
Response distribution family. Defaults to [Gaussian()](Gaussian.md#whittaker.Gaussian).


## Notes

For each functional term, the coefficient function is expanded as `\beta(t) = \sum_{k=1}^{K} c_k \phi_k(t)` in a basis `\{\phi_k\}` (B-spline or Fourier), so the functional effect for observation `i` becomes a finite inner product with a numerically integrated design column:

\int X_i(t)\\\beta(t)\\dt \\\approx\\ \sum\_{k=1}^{K} c_k \underbrace{\sum_t X_i(t)\\\phi_k(t)\\w_t}\_{J\_{i,k}}

where `w_t` are trapezoidal quadrature weights. The coefficients `c_k` are penalized by a difference penalty (B-spline) or a frequency-based penalty (Fourier) of order `penalty_order`, controlling the smoothness of the recovered `beta(t)`. All functional and scalar design columns are combined into one design matrix and fit jointly via penalized IRLS (`pirls_fit`), so the smoothing parameters for each functional term's coefficient function, and for any scalar smooth terms, are selected simultaneously.


## Examples


``` python
import numpy as np
from whittaker.functional import FunctionalGAM, FunctionalTerm

rng = np.random.default_rng(0)
n, T = 300, 50
t_grid = np.linspace(0, 1, T)
beta_true = np.sin(2 * np.pi * t_grid)

X_curves = rng.normal(size=(n, T)) + np.sin(3 * t_grid)
y = X_curves @ beta_true / T + rng.normal(scale=0.3, size=n)

model = FunctionalGAM("y", [FunctionalTerm(name="X_curves", n_basis=12)])
model.fit({"y": y, "X_curves": X_curves})
cf = model.coefficient_function("X_curves")
print(cf.values[:5])
```


    [0.29887787 0.33565746 0.3707274  0.40413803 0.4359397 ]


## Attributes

| Name | Description |
|----|----|
| [coefficients](#coefficients) | Fitted coefficient vector for the combined design matrix. |
| [deviance](#deviance) | Deviance of the fitted model. |
| [edf_total](#edf_total) | Total effective degrees of freedom across all functional and scalar terms. |
| [functional_terms](#functional_terms) | List of [FunctionalTerm](FunctionalTerm.md#whittaker.FunctionalTerm) specifications used by this model. |
| [is_fitted](#is_fitted) | Whether `fit()` has been called successfully. |
| [response](#response) | Name of the scalar response variable. |
| [scale](#scale) | Estimated scale (dispersion) parameter of the fitted model. |

------------------------------------------------------------------------


### coefficients


Fitted coefficient vector for the combined design matrix.


`coefficients: NDArray`


------------------------------------------------------------------------


### deviance


Deviance of the fitted model.


`deviance: float`


------------------------------------------------------------------------


### edf_total


Total effective degrees of freedom across all functional and scalar terms.


`edf_total: float`


------------------------------------------------------------------------


### functional_terms


List of [FunctionalTerm](FunctionalTerm.md#whittaker.FunctionalTerm) specifications used by this model.


`functional_terms: list[FunctionalTerm]`


------------------------------------------------------------------------


### is_fitted


Whether `fit()` has been called successfully.


`is_fitted: bool`


------------------------------------------------------------------------


### response


Name of the scalar response variable.


`response: str`


------------------------------------------------------------------------


### scale


Estimated scale (dispersion) parameter of the fitted model.


`scale: float`


## Methods

| Name | Description |
|----|----|
| [coefficient_function()](#coefficient_function) | Extract the estimated coefficient function beta(t) for a functional term. |
| [edf()](#edf) | Effective degrees of freedom per functional term. |
| [fit()](#fit) | Fit the functional GAM. |
| [predict()](#predict) | Predict on new data. |
| [summary()](#summary) | Build a text summary of the fitted functional GAM. |

------------------------------------------------------------------------


### coefficient_function()


Extract the estimated coefficient function beta(t) for a functional term.


Usage

``` python
coefficient_function(
    term_name,
    *,
    n_grid=200,
    level=0.95,
)
```


#### Parameters


`term_name: str`  
Name of the functional term.

`n_grid: int = ``200`  
Number of grid points for evaluation.

`level: float = ``0.95`  
Confidence level for pointwise intervals.


#### Returns


`CoefficientFunction`  


------------------------------------------------------------------------


### edf()


Effective degrees of freedom per functional term.


Usage

``` python
edf()
```


#### Returns


`dict[str, float]`  


------------------------------------------------------------------------


### fit()


Fit the functional GAM.


Usage

``` python
fit(
    data,
    *,
    method="REML",
    select=False,
)
```


For each functional term, builds its basis matrix and penalty over the observed grid, computes the numerically integrated functional design columns (mean-centered for identifiability), and combines them with any scalar terms into a single design matrix. The combined model is then fit by penalized IRLS (`pirls_fit`), jointly selecting smoothing parameters for every functional term's coefficient function and any scalar smooths.


#### Parameters


`data: InputData`  
Column-oriented data. Scalar covariates and the response are 1-D arrays. Functional covariates are 2-D arrays of shape `(n, T)` where `T` is the number of grid points.

`method: str = ``"REML"`  
Smoothing parameter selection method (e.g. `"REML"`, `"GCV"`, `"ML"`).

`select: bool = ``False`  
Enable double-penalty variable selection for the scalar terms.


#### Returns


`FunctionalGAM`  
Returns `self` for method chaining.


------------------------------------------------------------------------


### predict()


Predict on new data.


Usage

``` python
predict(
    new_data,
    *,
    se=False,
)
```


Rebuilds the functional design columns for `new_data` using the basis matrices fit on the training data (so no new basis/penalty is estimated), forms the linear predictor, and maps it through the family's inverse link to the response scale.


#### Parameters


`new_data: InputData`  
Data dict with the same functional and scalar covariates as training data.

`se: bool = ``False`  
If `True`, return `(predictions, standard_errors)` instead of just predictions, where standard errors are computed on the linear predictor scale from the reconstructed training-data information matrix `(X'WX + S)`.


#### Returns


`NDArray or tuple[NDArray, NDArray]`  


------------------------------------------------------------------------


### summary()


Build a text summary of the fitted functional GAM.


Usage

``` python
summary()
```


Reports the response name, family, number of observations, total EDF, deviance, and scale, followed by per-functional-term details (basis type, number of basis functions, domain, and EDF) and, if present, the scalar terms formula.


#### Returns


`str`  
Multi-line summary text.
