Metadata-Version: 2.4
Name: rollout-cp-scfm
Version: 0.1.0
Summary: Rollout-calibrated conformal prediction for autoregressive single-cell foundation models.
Project-URL: Homepage, https://github.com/shenfuqili/acp-scfm
Project-URL: Repository, https://github.com/shenfuqili/acp-scfm
Project-URL: Issues, https://github.com/shenfuqili/acp-scfm/issues
Author: Zhibin Wang
License: MIT
License-File: LICENSE
Keywords: autoregressive,conformal-prediction,foundation-models,rollout-calibration,single-cell,uncertainty-quantification
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
Requires-Python: >=3.11
Requires-Dist: numpy>=1.26
Provides-Extra: dev
Requires-Dist: black<25.0,>=24.4; extra == 'dev'
Requires-Dist: isort<6.0,>=5.13; extra == 'dev'
Requires-Dist: mypy<1.12,>=1.10; extra == 'dev'
Requires-Dist: pytest-cov<6.0,>=5.0; extra == 'dev'
Requires-Dist: pytest<9.0,>=8.2; extra == 'dev'
Requires-Dist: ruff<0.6,>=0.4; extra == 'dev'
Provides-Extra: repro
Requires-Dist: hydra-core<1.4,>=1.3; extra == 'repro'
Requires-Dist: matplotlib>=3.8; extra == 'repro'
Requires-Dist: omegaconf<2.4,>=2.3; extra == 'repro'
Requires-Dist: pandas>=2.2; extra == 'repro'
Requires-Dist: pyyaml>=6.0; extra == 'repro'
Requires-Dist: scikit-learn>=1.4; extra == 'repro'
Requires-Dist: scipy>=1.13; extra == 'repro'
Requires-Dist: tqdm>=4.66; extra == 'repro'
Provides-Extra: scfm
Requires-Dist: anndata>=0.10; extra == 'scfm'
Requires-Dist: scanpy>=1.10; extra == 'scfm'
Requires-Dist: torch>=2.3; extra == 'scfm'
Description-Content-Type: text/markdown

# rollout-cp-scfm

**Rollout-calibrated conformal prediction for autoregressive single-cell foundation models.**

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)

> When should we trust a cell-state prediction? `rollout-cp-scfm` is a
> distribution-free uncertainty wrapper for autoregressive scFMs
> (CellTempo, PerturbGen, autoregressive ImmuneWorld), with finite-sample
> coverage guarantees that explicitly handle the deployment-time rollout
> regime.

PyPI distribution: `rollout-cp-scfm`. Python import path: `acp`
(`from acp.calibration import RolloutSplitConformalRegressor`); the
distribution / import split mirrors `scikit-learn` / `sklearn`.

## What this package does

The library implements split conformal prediction with **four** score
functions, all sharing a common API:

| Module | Use case | Reference |
|---|---|---|
| `split_cp.py` | Marginal CP for one-shot scFM outputs | Vovk 2005, Lei et al. 2018 |
| `weighted_cp.py` | CP under covariate shift across cohorts | Tibshirani et al. 2019 |
| `adaptive_cp.py` | Online ACI for streaming time series | Gibbs & Candès 2021 |
| **`rollout_cp.py`** | **Per-step / cumulative CP under autoregressive rollouts** | This work |

The `rollout_cp` wrapper is what's needed when the scFM is autoregressive
(CellTempo-style next-state generation), because teacher-forced
calibration provably produces narrower bands than the deployment-time
rollout regime requires (see `docs/THEOREM_DRAFT.md` Corollary 1).
Rollout calibration restores nominal coverage at every horizon `t`.

## Why this exists

Existing CP wrappers for scFMs (e.g. Cilantro-SL for Geneformer) target
one-shot prediction, not multi-step rollouts. Existing rollout-CP work
(HopCast, CP-Traj, ConformalDAgger, Conformal Language Modeling) targets
robotics / forecasting / language, not single-cell foundation models.
This package is the bridge: a clean, tested, pip-installable wrapper for
autoregressive scFMs.

## Quick start

```bash
# Once published to PyPI, just:
#   pip install rollout-cp-scfm

# Or, to develop / reproduce §4 figures from source:
git clone https://github.com/shenfuqili/acp-scfm
cd acp-scfm
python3.11 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev,repro]"                    # core + repro + dev tooling
pytest tests/                                    # 18 tests should pass
python scripts/simulate_autoregressive.py        # generates E3 figure
```

Expected output of the simulation:

```
linear   ε_M ≈ 0.000  cov_TF[20] = 0.736  cov_RO[20] = 0.901
misspec  ε_M ≈ 0.085  cov_TF[20] = 0.272  cov_RO[20] = 0.901
```

The simulation produces `figures/E3/E3_sim_coverage_vs_horizon.png`,
which is the paper's main experimental figure: rollout calibration
holds nominal coverage 0.90 across 20 horizons in both well-specified
and misspecified linear-Gaussian regimes; teacher-forced calibration
collapses to 0.27 in the misspec regime.

## API at a glance

```python
import numpy as np
from acp.calibration.rollout_cp import (
    RolloutSplitConformalRegressor,
    per_step_coverage,
)

# cal_rollouts: shape (n_cal, T, d) -- recursive M̂^t(x_0) on cal trajectories.
# cal_truths:   shape (n_cal, T, d) -- ground-truth states at t=1..T.
cp = RolloutSplitConformalRegressor(alpha=0.1, mode="per_step").fit(
    cal_rollouts, cal_truths
)

# At deployment we only have rollouts; CP gives per-coord prediction bands.
lower, upper = cp.predict_interval(test_rollouts)

curve = per_step_coverage(lower, upper, test_truths)
print(f"per-step coverage: {curve.round(3)}")  # ~ [0.9, 0.9, 0.9, ...]
```

`mode="cumulative"` aggregates the score across the entire trajectory
and produces a single qhat — useful when joint trajectory coverage
`P[∀ t: y_t ∈ C_t]` is the quantity of interest.

## Repository layout

```
src/acp/
  calibration/
    split_cp.py         marginal CP (classifier + regressor)
    weighted_cp.py      Tibshirani 2019 weighted CP, weight clipping
    adaptive_cp.py      Gibbs & Candès 2021 ACI
    rollout_cp.py       this work — rollout-calibrated split CP
  evaluation/
    coverage.py         empirical-coverage / efficiency metrics
    selective_pred.py   risk-coverage curves
  backbones/
    base.py             abstract BackboneWrapper interface

scripts/
  simulate_autoregressive.py   E3 simulation, two regimes
  run_E1_sklearn.py            E1 sklearn-LR baseline on Norman 2019

tests/                          pytest suite for split + rollout CP

docs/
  PIVOT_PLAN.md         strategic plan (post v1/v2/v3 adversarial review)
  THEOREM_DRAFT.md      Proposition 1 + Corollary 1 with proofs
  RELATED_WORK.md       paper related-work section
  E1/                   sklearn-LR Norman 2019 baseline writeup
  E3/                   synthetic AR experiment writeup
```

## Experiments

| | Goal | Backbone | Status |
|---|---|---|---|
| **E1** marginal coverage | Norman 2019 (290 perturbations) | sklearn LR baseline | done (±0.002 hit at 5 alphas) |
| **E1-Geneformer** | same, with Geneformer | Geneformer | planned |
| **E3-sim** | rollout vs teacher-forced | linear M̂ on linear truth | done (`figures/E3/`) |
| **E3-misspec** | activate ε_M term | linear M̂ on tanh-perturbed truth | done (`figures/E3/`) |
| **E3-real** | autoregressive scFM | CellTempo on scBaseTraj | planned |

## Citing

A bibtex entry will be added once the arXiv preprint is up. For now:

```
@misc{wang2026rolloutcpscfm,
  author = {Zhibin Wang},
  title  = {rollout-cp-scfm: Rollout-calibrated conformal prediction for
            autoregressive single-cell foundation models},
  year   = {2026},
  url    = {https://github.com/shenfuqili/acp-scfm}
}
```

## License

MIT.
