Metadata-Version: 2.4
Name: brain-spi
Version: 0.1.0
Summary: SPI connectivity-analysis pipeline for fMRI group comparisons
Author-email: Pavel Popov <kapssula@gmail.com>
License: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: numpy>=1.24
Requires-Dist: scipy>=1.11
Requires-Dist: scikit-learn>=1.3
Requires-Dist: matplotlib>=3.7
Requires-Dist: pandas>=2.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: pyspi
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: pytest-mpl; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Requires-Dist: mypy; extra == "dev"

# brain-spi

![Mean Kendall-tau connectivity (left) and its significant-difference AND mask (right)](https://raw.githubusercontent.com/neuroneural/brain-spi/main/docs/header.png)

Comparison of pairwise statistics for fMRI connectivity estimation, and a
pipeline for finding group differences across them.

`brain_spi` wraps the SPI connectivity-analysis workflow into a small, importable
library. It lets you run the full pipeline in one call and then inspect either the
aggregated cross-SPI result or any individual SPI's intermediate artifacts.

**Try it now in Colab** (no install, nothing to clone):
[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuroneural/brain-spi/blob/main/examples/colab_quickstart.ipynb)

## What it does

- **Connectivity** — derive functional network connectivity (FNC) matrices from
  multivariate fMRI time series using many pairwise statistics (SPIs), via
  [pyspi](https://github.com/DynamicsAndNeuralSystems/pyspi) plus a small custom set.
- **Group differences** — per SPI, find edges that differ between two groups using
  a Welch t-test (Bonferroni-corrected) **and** a Random-Forest importance mask, then
  intersect them.
- **Aggregate** — average the per-SPI masks into a consensus matrix: the fraction of
  SPIs that flag each edge.
- **Robustness** — subject-resampling (`bootstrap`) and label-shuffle permutation nulls.
- **Plots & caching** — heatmaps with network guides, per-SPI triptychs, the aggregate
  panel; on-disk caching of the (slow) pyspi computations.

## Install

I recommend installing `brains-spi` in a separate python enviroment: `brains-spi` relies on `pyspi`, and it relies on `numpy < 2`, which can conflict with other packages.

```bash
pip install -e .            # from the repo root
# core deps: numpy, scipy, scikit-learn, matplotlib, pandas, pyyaml, pyspi
```

## Quickstart

```python
import numpy as np
from brain_spi import BrainSPI

# data: (B subjects, T timepoints, C channels/ROIs);  labels: (B,) with 2 unique values
pipe   = BrainSPI(group_names=('HC', 'patient'))   # sensible defaults (9 curated SPIs)
result = pipe.fit(data, labels)

# headline result — cross-SPI aggregate (computed lazily, cached on first access)
result.aggregate.mean_and        # (C, C) float: fraction of SPIs flagging each edge
result.aggregate.plot()          # one-shot figure

# inspect a single SPI
result['kendalltau'].mean_matrix()       # (C, C) mean connectivity across subjects
result['kendalltau'].and_mask            # significant-p AND RF-important edges
result['kendalltau'].plot_triptych()     # 3-panel: sig-p / RF / AND

# not sure what's available? every result object has a repr + .help()
result.help()
```

### Choosing SPIs

```python
BrainSPI()                                   # default 9-SPI curated set
BrainSPI(spis='spis_all')                    # the broad pyspi set
BrainSPI(spis='/path/to/my_spis.yaml')       # a config file
BrainSPI(spis=['kendalltau', 'spearmanr'])   # an explicit list
```

SPIs are computed one at a time across all subjects, with a progress bar and a
per-SPI wall-time log (enable with `logging.basicConfig(level=logging.INFO)`), so
it's easy to spot and drop slow ones.

### Robustness

```python
boot = result.bootstrap(n=20, frac=0.66)     # 20 subject-resampled cross-SPI AND maps
boot.mean                                     # average of the 20 (resampling-smoothed aggregate)
boot.survival_rate()                          # how often each edge is flagged (reproducibility)

null = result.label_shuffle(n=100)            # permutation null
null.p_value(result.aggregate.mean_and)       # per-edge permutation p-values (low = significant)
```

### Saving results

The first `fit` is slow (pyspi dominates); subsequent fits on the same data are
near-instant thanks to the on-disk cache (`~/.cache/brain_spi/`, override with
`BrainSPI(cache_dir=...)`). To save a finished result:

```python
result.to_npz('result.npz')              # portable — open with plain numpy.load, no package needed
result.to_pickle('result.pkl')           # exact object

import brain_spi
result = brain_spi.load_npz('result.npz')   # or load_pickle(...)
```

The `.npz` is a flat collection of arrays with a self-describing `README` key inside.

## Example notebook

[`examples/colab_quickstart.ipynb`](https://github.com/neuroneural/brain-spi/blob/main/examples/colab_quickstart.ipynb)
[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/neuroneural/brain-spi/blob/main/examples/colab_quickstart.ipynb)
runs end-to-end on public data — ABIDE (controls vs. autism) by default, or COBRE
(schizophrenia) via a one-line switch. Part 1 computes SPIs and inspects their mean
connectivity; Part 2 runs the significant-differences pipeline. Datasets download
automatically via [`examples/datasets.py`](https://github.com/neuroneural/brain-spi/blob/main/examples/datasets.py).
