![logo](docs/assets/logo-name.png)
High-performance C implementation with Python bindings for sampling from joint Gaussian Processes with integral and derivative relationships.

## Overview

Sample from joint GP $(f, g, h, u)$ where:

- $f(x) \sim \mathcal{GP}(0, k_f)$ — original process with RBF kernel
- $g(x) = \int_0^x f(t) dt$ — integrated process
- $h(x) = f'(x)$ — derivative process
- $u(x) = f''(x)$ — second derivative process

All are correlated through proper cross-covariance structures.

## Key Features

- **Fast C implementation** using GSL (GNU Scientific Library)
- **Zero-copy Cython wrapper** for seamless NumPy integration
- **Four-way joint sampling** of function, integral, derivative, and second derivative
- **Posterior sampling** conditioned on observed data
- **Mixed observations** — observe f, predict h or u, or any combination
- **Multiple kernels** — RBF, Matérn 5/2, Matérn 3/2, periodic, locally-periodic
- **Hyperparameter optimization** via `fit()` — maximize log marginal likelihood
- **Mathematically rigorous** covariance structure
- **Fully tested** with comprehensive unit tests

## Quick Install

### Prerequisites

Install GSL first:

```bash
# macOS
brew install gsl

# Ubuntu/Debian
sudo apt-get install libgsl-dev

# Fedora/RHEL
sudo dnf install gsl-devel
```

### Install Package

```bash
pip install -e .
```

## Quick Start

```python
import numpy as np
from gp4c import sample_prior, SamplingSpec

x = np.linspace(0, 5, 100)
spec = SamplingSpec(x_f=x, x_g=x)
result = sample_prior(
    spec,
    sigma2=1.0,
    ell=0.5,
    n_samples=5,
    seed=42
)
# result.f contains f samples, result.g contains integral samples
```

## Documentation

Full documentation is available at: **[https://rcalderonb6.github.io/gp4c](https://rcalderonb6.github.io/gp4c)**

Or build locally:

```bash
pip install mkdocs-material
mkdocs serve
```

### Quick Links

- [Installation Guide](https://rcalderonb6.github.io/gp4c/getting-started/installation/)
- [Quick Start Tutorial](https://rcalderonb6.github.io/gp4c/getting-started/quickstart/)
- [API Reference](https://rcalderonb6.github.io/gp4c/api/functions/)
- [Mathematical Background](https://rcalderonb6.github.io/gp4c/math/kernels/)
- [Examples](https://rcalderonb6.github.io/gp4c/examples/python/)

## Examples

Basic usage:

```python
# Sample f and its derivative h
from gp4c import sample_prior, SamplingSpec

spec = SamplingSpec(x_f=x, x_h=x)
result = sample_prior(spec, sigma2=1.0, ell=0.5, n_samples=5)
```

Second derivative sampling:

```python
# Sample f and its second derivative u = f''
from gp4c import sample_prior, SamplingSpec

spec = SamplingSpec(x_f=x, x_u=x)
result = sample_prior(spec, sigma2=1.0, ell=0.5, n_samples=5)
# result.f contains f samples, result.u contains f'' samples
```

Posterior sampling:

```python
# Condition on observations
from gp4c import sample_posterior, Observations, SamplingSpec

x_train = np.array([0.0, 1.0, 2.0, 3.0, 4.0])
y_train = np.sin(x_train)
obs = Observations(x_f=x_train, y_f=y_train, noise_f=0.01)

x_test = np.linspace(0, 5, 100)
spec = SamplingSpec(x_f=x_test)

result = sample_posterior(obs, spec, ell=1.0, n_samples=10)
```

Hyperparameter optimization:

```python
# Automatically find the best kernel parameters
import gp4c
import numpy as np

x = np.linspace(0, 10, 50)
y = np.sin(x) + np.random.default_rng(0).normal(0, 0.1, len(x))
obs = gp4c.Observations(x_f=x, y_f=y, noise_f=0.01)

result = gp4c.fit(obs, kernel='rbf')
print(f"sigma2={result.sigma2:.3f}, ell={result.ell:.3f}")
# Use result.sigma2 and result.ell directly in sample_posterior
```

See the [examples/](examples/) directory and [documentation](https://rcalderonb6.github.io/gp4c/examples/python/) for more.

## Testing

```bash
pytest tests/ -v
```

## C Library

The core can be used directly in C/C++ projects. See [C Integration Guide](https://rcalderonb6.github.io/gp4c/examples/c-integration/).

Quick install as system library:

```bash
./install_library.sh        # System-wide (requires sudo)
./install_library.sh --user # User install (no sudo)
```

## Project Structure

```
gp4c/
├── gp4c/                # Python package
│   ├── gp4c.c           # C implementation
│   ├── gp4c.h           # C headers and constants
│   ├── _core.pyx        # Cython wrapper
│   ├── types.py         # Type definitions
│   ├── optimize.py      # Hyperparameter optimization
│   └── cli.py           # CLI commands (gp4c install, etc.)
├── docs/                # MkDocs documentation
├── tests/               # Test suite
├── examples/            # Example scripts
├── notebooks/           # Jupyter notebooks
└── mkdocs.yml           # Documentation config
```

## Contributing

Contributions welcome! See [Contributing Guide](https://rcalderonb6.github.io/gp4c/reference/contributing/).

1. Fork the repository
2. Create a feature branch
3. Add tests for new functionality
4. Submit a pull request

## License

MIT License - see LICENSE file for details.

## Citation

If you use this package in your research, please cite:

```bibtex
@software{gp4c,
  title = {gp4c: Fast Joint Gaussian Process Sampling with integral and derivative information},
  author = {Calderón, Rodrigo},
  year = {2026},
  url = {https://github.com/rcalderonb6/gp4c}
}
```

## References

1. Solak et al. (2003) - Derivative observations in Gaussian process models
2. Rasmussen & Williams (2006) - Gaussian Processes for Machine Learning
3. GSL Manual - https://www.gnu.org/software/gsl/doc/html/
