Metadata-Version: 2.4
Name: magli
Version: 1.0.0
Summary: magli (Modelo Aditivo Generalizado Lineal): Modern Pythonic Generalized Additive Models (GAMs) with Eilers-Marx (1996) and Wood (2011) backends
Author: David Ávila Cortés
License-Expression: GPL-3.0-or-later
Project-URL: Homepage, https://github.com/dacts23/magli
Project-URL: Repository, https://github.com/dacts23/magli
Project-URL: Documentation, https://dacts23.github.io/magli/
Keywords: gam,generalized-additive-models,splines,regression,mgcv,pygam,reml,p-splines,shape-constraints,interpretable-ml,explainable-ai,statistics,machine-learning,magli
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Mathematics
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.20
Requires-Dist: scipy>=1.7
Requires-Dist: matplotlib>=3.5
Provides-Extra: docs
Requires-Dist: sphinx>=9; extra == "docs"
Requires-Dist: furo; extra == "docs"
Requires-Dist: sphinx-copybutton; extra == "docs"
Dynamic: license-file

# magli: Generalized Additive Models (GAMs) in Python

**magli (Modelo Aditivo Generalizado Lineal)**: Modern Pythonic Generalized Additive Models (GAMs) based on classical statistical literature. It supports both single-term smooths (`GAM` / `LinGAM`) and multi-term formula-based models (`GAMCore`) with automatic hyperparameter tuning.

> **Full documentation:** [https://dacts23.github.io/magli/](https://dacts23.github.io/magli/)

---

## Which Backend Engine Should I Use?

`magli` provides two complementary statistical engines under a unified API:

| Feature / Goal | **`backend="wood"`** (Default) | **`backend="eilers"`** |
| :--- | :--- | :--- |
| **Smoothing parameter ($\lambda$)** | **Continuous REML or GCV optimization** (automatic during `.fit()`, no grid search needed) | **Discrete GCV grid search** over candidate $(\lambda, K)$ pairs |
| **Basis function suite** | Thin plate (`tp`, `ts`), Cubic (`cr`, `cs`), Cyclic (`cc`), P-splines (`ps`, `cp`), B-splines (`bs`), Random effects (`re`) | Uniform B-splines (`bs`) with linear extrapolation |
| **Statistical summaries** | Full summary tables with **approximate F-tests and p-values** (Wood 2013) | Basic statistics (EDF, GCV, deviance explained) |
| **Shape constraints** | Periodic boundaries via cyclic bases (`cc`, `cp`) | **Soft constraints**: `mono_inc`, `mono_dec`, `convex`, `concave`, `periodic` |
| **Observation weights** | Weighted penalized least-squares (`weights=...`) | Weighted penalized least-squares (`weights=...`) |

* **Use `wood`** for general regression, automatic parameter tuning, hypothesis testing, and maximum flexibility in basis types (equivalent to R's `mgcv`).
* **Use `eilers`** when you have physical domain constraints (e.g. monotonicity or convexity) or want explicit B-spline grid sweeps.

---

## Why magli?

* **R's `mgcv` parity in pure Python**: `magli` implements Simon Wood's continuous REML smoothing parameter selection, Wood 2013 approximate F-tests and p-values, thin plate splines, and cyclic cubic bases without requiring an R runtime or rpy2.
* **Shape constraints**: Soft shape constraints (monotonic increasing, monotonic decreasing, convex, concave) via the Eilers-Marx B-spline engine.
* **Fast and numerically stable**: SVD data augmentation and cached QR with Cholesky factorization avoid squaring condition numbers.
* **Interpretable machine learning**: Every term produces clean component decomposition plots and Bayesian confidence intervals.

---

## Features

- **Dual backend engines**: choose between `wood` (Wood 2011) and `eilers` (Eilers & Marx 1996)
- **Automatic hyperparameter tuning**: continuous REML/GCV optimization or cached QR+Cholesky GCV grid search
- **Rich basis suite**: thin plate splines, cubic regression splines, cyclic cubic splines, P-splines, B-splines, random effects
- **Tensor-product interactions**: multidimensional smooths (`te`) with Kronecker sum penalties
- **Shape constraints**: monotonic increasing/decreasing, convex, concave, and periodic
- **Observation weights**: prior precision or frequency weights (`weights=...`) in `fit()` and `gridsearch()`
- **Uncertainty quantification**: Bayesian posterior covariance and frequentist confidence/prediction intervals
- **Summary tables**: parametric coefficients, EDF, approximate F-statistics, and p-values (Wood 2013)

---

## Installation

```bash
pip install numpy scipy matplotlib
pip install -e .
```

---

## Quick Start

### 1. Wood (2011) Engine (Automatic REML Smoothing)

In the Wood engine, smoothing parameters are estimated continuously during fit via REML (no manual grid search required):

```python
import numpy as np
from magli import GAM, GAMCore

np.random.seed(42)
x = np.linspace(0, 1, 200)
y = np.sin(2 * np.pi * x) + np.random.normal(0, 0.2, len(x))

# Single-term model with cubic regression splines
model = GAM(k=10, bs="cr", backend="wood")
model.fit(x, y)

print(model.summary())
y_pred = model.predict(x)
ci = model.confidence_intervals(x, width=0.95)
```

Multi-term formula with tensor-product interactions and linear terms:

```python
# Multi-term dataset: 2 interactive variables + 1 linear variable
X = np.random.uniform(0, 10, (200, 3))
y_multi = np.sin(X[:, 0]) + 0.5 * X[:, 1] + 1.2 * X[:, 2] + np.random.normal(0, 0.2, 200)

gam = GAMCore("te(0, 1, bs='cr', k=4) + l(2)", backend="wood")
gam.fit(X, y_multi)
print(gam.summary())
```

### 2. Eilers & Marx (1996) Engine (B-Splines & Constraints)

The Eilers-Marx engine provides discrete GCV grid searches and shape constraints:

```python
import numpy as np
from magli import GAM

# Reusing synthetic data x, y or generating new series
x = np.linspace(0, 1, 200)
y = np.sin(2 * np.pi * x) + np.random.normal(0, 0.2, len(x))

# Fast B-spline grid search over candidate lambda and spline counts
model = GAM(backend="eilers")
model.gridsearch(x, y)

y_pred = model.predict(x)
ci = model.confidence_intervals(x, width=0.95)
model.plot_decomposition(x, y)
```

Enforcing soft shape constraints (e.g. monotonic increasing dose-response):

```python
# Enforce monotonic increasing trend
mono_model = GAM(n_splines=12, constraint="mono_inc", backend="eilers")
mono_model.fit(x, y)
```

Fitting with observation weights (e.g. inverse variance or down-weighted outliers):

```python
# Weighted penalized least-squares
weighted_model = GAM(n_splines=12, backend="eilers")
weighted_model.fit(x, y, weights=w)
```

---

## Formula Syntax

`GAMCore` uses an intuitive additive formula specification:

| Term Syntax | Meaning | Example |
| :--- | :--- | :--- |
| `s(col, ...)` | Univariate smooth spline | `s(0, k=10, bs='cr')` or `s(0, n_splines=12, constraint='mono_inc')` |
| `te(c1, c2, ...)` | Multidimensional tensor product | `te(0, 1, k=5, bs='cr')` |
| `f(col, ...)` | Categorical factor | `f(2, coding='dummy')` or `f(2, coding='one-hot')` |
| `l(col, ...)` | Parametric linear effect | `l(3)` |

*Note: Predictor variables are identified by 0-indexed column numbers in input arrays.*

---

## Documentation

Full documentation, mathematical foundations, and end-to-end tutorials are available at:

### [→ https://dacts23.github.io/magli/](https://dacts23.github.io/magli/)

- **[Quick Start](https://dacts23.github.io/magli/quickstart.html)**: installation and basic workflows
- **[Mathematical Foundations](https://dacts23.github.io/magli/math.html)**: theory behind both engines:
  - *Part I:* [Shared Foundations & Additive Decomposition](https://dacts23.github.io/magli/math/foundations.html)
  - *Part II:* [Eilers & Marx B-Splines, Penalties, & SVD Solver](https://dacts23.github.io/magli/math/eilers.html)
  - *Part III:* [Wood Basis Suite, Identifiability, & REML Optimization](https://dacts23.github.io/magli/math/wood.html)
  - *Part IV:* [Side-by-Side Comparison & Engine Selection](https://dacts23.github.io/magli/math/comparison.html)
- **[Shape Constraints](https://dacts23.github.io/magli/constraints.html)**: monotonic, convex, concave, and periodic splines
- **[Smoothing Optimization](https://dacts23.github.io/magli/gridsearch.html)**: continuous REML and discrete GCV grid search
- **[Examples & Case Studies](https://dacts23.github.io/magli/examples.html)**: worked examples across diverse problems
- **[API Reference](https://dacts23.github.io/magli/api.html)**: full class and method documentation
- **[Changelog](https://dacts23.github.io/magli/changelog.html)**: release history and version notes

---

## Demo Scripts

Run any of the 15 self-contained demo scripts in the `examples/` directory:

```bash
python examples/01_basic_lingam.py
python examples/10_engineering_case_study.py
python examples/11_wood_backend.py
python examples/12_concrete_demo.py
python examples/13_eilers_vs_wood_comparison.py
python examples/14_wood_basis_decomposition_plots.py
python examples/15_eilers_basis_decomposition_plots.py
```

---

## License

GNU General Public License v3.0 (GPL-3.0-or-later) © 2026 David Ávila Cortés.
See [LICENSE](LICENSE) for full terms and third-party attributions (Simon N. Wood / `mgcv` and Daniel Serven / `pygam`).
