Metadata-Version: 2.4
Name: presurfer
Version: 2.0.0
Summary: MATLAB-free MP2RAGE preprocessing using SPM Standalone containers
Author: Sriranga Kashyap
License-Expression: MIT
Project-URL: Homepage, https://github.com/srikash/presurfer-box
Project-URL: Source, https://github.com/srikash/presurfer-box
Project-URL: Issues, https://github.com/srikash/presurfer-box/issues
Project-URL: Citation, https://doi.org/10.5281/zenodo.22163094
Keywords: MRI,MP2RAGE,SPM,neuroimaging,presurfer,Docker,Apptainer
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: click>=8.1
Requires-Dist: nibabel>=5.0
Requires-Dist: numpy>=1.24
Requires-Dist: rich>=15.0.0
Dynamic: license-file

# presurfer-box [![DOI](https://zenodo.org/badge/1350566808.svg)](https://doi.org/10.5281/zenodo.22163094)

MATLAB-free MP2RAGE preprocessing using SPM Standalone in Docker,
Singularity, or Apptainer.

`presurfer-box` runs presurfer workflows in the
[official SPM Standalone container](https://github.com/spm/spm-docker), so it
does not need a local MATLAB installation or licence. The original MATLAB
implementation remains available as a Git submodule.

> **Status:** This implementation uses SPM25 Standalone. Results have not yet
> been numerically validated against the historical SPM12/MATLAB pipeline.

## Install

`presurfer-box` needs Python 3.11 or later and either Docker, Singularity,
or Apptainer. Install it from PyPI:

```bash
pip install presurfer
```

To work on the code, clone the repository instead:

```bash
git clone https://github.com/srikash/presurfer-box.git
cd presurfer-box
```

Fetch the pinned legacy MATLAB submodule only when you need to inspect or run
the historical implementation:

```bash
git submodule update --init --recursive
```

### Docker

```bash
docker pull ghcr.io/spm/spm-docker:docker-matlab-25.01.02
presurfer-box --check
```

### Singularity / Apptainer

```bash
singularity pull --name spm.sif \
  oras://ghcr.io/spm/spm-docker:singularity-matlab-25.01.02

presurfer-box --sif spm.sif --check
```

## Quick start

```bash
# Create a bias-corrected image and bias field
presurfer-box biascorrect IMAGE.nii

# Create MPRAGEised UNI
presurfer-box MPRAGEise INV2.nii UNI.nii

# Create an INV2-derived strip mask
presurfer-box stripmask INV2.nii

# Create UNI tissue classes, brain mask, and white-matter mask
presurfer-box brainmask UNI.nii
```

Use a local Singularity or Apptainer image with `--sif`:

```bash
presurfer-box --sif spm.sif stripmask INV2.nii
```

Docker is the default runtime. Use `--image IMAGE` to select another image.

Each run writes to a new UTC timestamped directory beside its input, for
example `250101T12:34:56_presurfer/presurf_INV2/`. Same-second runs receive a
numeric suffix. MPRAGEise's intermediate bias-correction directory begins
with `tmp_` and is removed after processing.

## Development

```bash
uv sync
uv run ruff format --check
uv run ruff check
uv run mypy .
uv run pytest
```

## Choose a workflow

| Need | CLI command | Python function | Primary output |
| --- | --- | --- | --- |
| Bias-correct an image | `biascorrect IMAGE` | `spm_biascorrect()` | Bias-corrected image and bias field |
| Create MPRAGEised UNI | `MPRAGEise INV2 UNI` | `spm_mprageise()` | `*_MPRAGEised.nii` |
| Create a strip mask | `stripmask INV2` | `spm_stripmask()` | `*_stripmask.nii` |
| Create UNI-derived masks | `brainmask UNI` | `spm_seg()` | Tissue classes, brain mask, and WM mask |

`MPRAGEise` bias-corrects INV2, min-max normalises the corrected INV2,
then multiplies it voxelwise with UNI. It does not run the strip-mask workflow.

## Python API

```python
from presurfer import spm_biascorrect, spm_mprageise, spm_seg, spm_stripmask

spm_biascorrect("INV2.nii")
spm_mprageise("INV2.nii", "UNI.nii")
spm_stripmask("INV2.nii")
spm_seg("UNI.nii")
```

All functions accept `image=` and `runtime=` keywords. Use
`runtime="singularity"` with a local SIF path passed as `image=`.

## Outputs

Each workflow writes its output beneath a timestamped run directory beside the
input:

```text
YYMMDDThh:mm:ss_presurfer/presurf_biascorrect/
YYMMDDThh:mm:ss_presurfer/presurf_MPRAGEise/
YYMMDDThh:mm:ss_presurfer/presurf_INV2/
YYMMDDThh:mm:ss_presurfer/presurf_UNI/
```

Compressed `.nii.gz` inputs are supported. The source file stays unchanged and
the workflow creates an uncompressed working copy in the output directory.

## Legacy MATLAB implementation

The original MATLAB implementation lives in
[srikash/presurfer](https://github.com/srikash/presurfer) and remains available
here as a pinned Git submodule:

```text
src/matlab/presurfer
```

For MATLAB use:

```matlab
addpath('src/matlab/presurfer/func')
```

Update the submodule only when adopting a newer presurfer commit deliberately.

## Reproducibility and validation

- Default image: `ghcr.io/spm/spm-docker:docker-matlab-25.01.02`
- SPM runtime: SPM25 Standalone
- Historical implementation: SPM12 with MATLAB
- Numerical equivalence has not yet been validated with reference NIfTI data.

## Licence

MIT. See [LICENSE](LICENSE).

## Citation

See [CITATION.cff](CITATION.cff).
