Metadata-Version: 2.4
Name: augmentrum
Version: 0.0.3
Summary: A Data Augmentation Package for MR Spectroscopy
Author-email: "John T. LaMaster" <jlamaste@gmail.com>, "Julian P. Merkofer" <j.p.merkofer@tue.nl>, "Kay C. Igwe" <kci2104@columbia.edu>
License: Apache-2.0
Project-URL: Homepage, https://github.com/julianmer/Augmentrum
Project-URL: Documentation, https://github.com/julianmer/Augmentrum#readme
Project-URL: Repository, https://github.com/julianmer/Augmentrum
Project-URL: Bug Tracker, https://github.com/julianmer/Augmentrum/issues
Keywords: MRS,spectroscopy,data augmentation,medical imaging,machine learning
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
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 :: Medical Science Apps.
Classifier: Topic :: Scientific/Engineering :: Physics
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.21.0
Requires-Dist: scipy>=1.7.0
Requires-Dist: nifti-mrs>=0.1.0
Requires-Dist: nifti-mrs-plus[ops]>=0.2.1
Requires-Dist: spec2nii>=0.6.0
Requires-Dist: tqdm>=4.62.0
Requires-Dist: matplotlib>=3.4.0
Requires-Dist: shutup>=0.2.0
Provides-Extra: fsl
Requires-Dist: fsl-mrs>=2.1.0; extra == "fsl"
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-cov>=3.0.0; extra == "dev"
Requires-Dist: pytest-mock>=3.10.0; extra == "dev"
Requires-Dist: black>=22.0.0; extra == "dev"
Requires-Dist: flake8>=4.0.0; extra == "dev"
Requires-Dist: mypy>=0.950; extra == "dev"
Provides-Extra: torch
Requires-Dist: torch>=1.10.0; extra == "torch"
Provides-Extra: jax
Requires-Dist: jax>=0.4.0; extra == "jax"
Requires-Dist: jaxlib>=0.4.0; extra == "jax"
Provides-Extra: nufft
Requires-Dist: torch>=1.10.0; extra == "nufft"
Requires-Dist: torchkbnufft>=1.3.0; extra == "nufft"
Provides-Extra: tensorflow
Requires-Dist: tensorflow>=2.8.0; extra == "tensorflow"
Provides-Extra: csm
Requires-Dist: h5py>=3.0.0; extra == "csm"
Provides-Extra: keras
Requires-Dist: keras>=3.0.0; extra == "keras"
Provides-Extra: seq
Requires-Dist: pypulseq>=1.4.0; extra == "seq"
Provides-Extra: docs
Requires-Dist: sphinx; extra == "docs"
Requires-Dist: sphinx-autobuild; extra == "docs"
Requires-Dist: sphinx-autodoc-typehints; extra == "docs"
Requires-Dist: sphinx-copybutton; extra == "docs"
Requires-Dist: myst-parser; extra == "docs"
Requires-Dist: furo; extra == "docs"
Provides-Extra: all
Requires-Dist: torch>=1.10.0; extra == "all"
Requires-Dist: torchkbnufft>=1.3.0; extra == "all"
Requires-Dist: h5py>=3.0.0; extra == "all"
Requires-Dist: tensorflow>=2.8.0; extra == "all"
Requires-Dist: keras>=3.0.0; extra == "all"
Requires-Dist: jax>=0.4.0; extra == "all"
Requires-Dist: jaxlib>=0.4.0; extra == "all"
Requires-Dist: pypulseq>=1.4.0; extra == "all"
Dynamic: license-file

<div align="center">
  <img src="https://raw.githubusercontent.com/julianmer/Augmentrum/main/assets/logo/logo.png" alt="Augmentrum Logo" width="100" style="margin-bottom: -10px;"/>
  <h1 style="margin-top: 5px; margin-bottom: 5px;">Augmentrum</h1>
  <p style="margin-top: 0px;"><em>A Data Augmentation Package for MR Spectroscopy</em></p>
  
  [![PyPI version](https://badge.fury.io/py/augmentrum.svg)](https://badge.fury.io/py/augmentrum)
  [![Python](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/)
  [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
  [![ISMRM 2026](https://img.shields.io/badge/ISMRM-Abstract%20%2305685-lightgrey.svg)](https://submissions.mirasmart.com/ISMRM2026/Itinerary/PresentationDetail.aspx?evdid=1450)
</div>

---

## Overview
**Augmentrum** is a modular Python framework designed to help researchers with limited *in-vivo* MRS data create diverse, physically consistent datasets through flexible augmentation. It supports **k-space resampling**, **coil and average sampling**, **signal-level perturbations**, and **synthetic artifact generation**, expanding both synthetic and *in-vivo* data in a realistic and controlled manner.

<div align="center">
  <img src="https://raw.githubusercontent.com/julianmer/Augmentrum/main/assets/figures/overview.png" alt="Augmentrum Pipeline Overview" width="800"/>
</div>

Built for data-driven MRS applications, Augmentrum streamlines the integration of data augmentation into existing workflows. It operates on the **NIfTI-MRS** standard, making it compatible with any acquisition format. Simply load your data as NIfTI (using `spec2nii` if needed) and apply either predefined augmentation settings or build a custom pipeline by combining modules. Each augmentation can be parameterized or used with default ranges to populate a dense and diverse dataset environment.

From MRSI reconstruction and acquisition variability to spectral perturbations and artifact synthesis, Augmentrum handles it all in a **modular**, **flexible**, and **easy-to-use** structure. Dataloaders allow **on-the-fly augmentation** for deep learning backends such as **PyTorch**, **TensorFlow**, **Keras**, and **JAX**, enabling robust training beyond static datasets.

> **Note:** Augmentrum is currently in **alpha development**. It is an active research framework and may undergo changes as modules and interfaces evolve.

---

## Features
- Modular augmentation across time, frequency, and k-space domains
- Physically valid transformations for realistic variability
- Native NIfTI-MRS I/O and metadata tracking
- Customizable pipelines with user-defined parameters
- On-the-fly augmentation for machine learning workflows

---

## Installation
```bash
pip install augmentrum
```
or from source:
```bash
git clone https://github.com/julianmer/Augmentrum.git
cd Augmentrum
pip install -e .
```

---

## Quick Start
```python
from augmentrum import Augmentrum

data   # list of NIfTI-MRS files
water   # list of corresponding water reference files (optional)

# initialize Augmentrum with data and optional water references
augmenter = Augmentrum(
    data=data, 
    water=water, 
    
    # custom pipeline example
    pipeline = [
        'coil_sampling',
        'average_sampling',
        'processing',
        'line_broadening',
        'baseline',
        'noise',
    ],
    
    # general settings
    batch_size=16,
    backend='pytorch',  # or 'tensorflow', 'keras', 'jax', 'numpy'
)

# get a dataloader for PyTorch with on-the-fly augmentation
train_data = augmenter.dataloader()
```

### Supervised Pairs: Taps and `outputs`

Any pipeline stage can be named with a `'tap:<name>'` marker and yielded by the
dataloaders through the `outputs` spec — an arbitrarily nested tuple of stage
tokens (`'data'` / `'water'` for the pipeline end, `'<tap>'` / `'<tap>.water'`
for a tapped stage). The classic `(data, water)` pair stays the default.

```python
augmenter = Augmentrum(
    data=data,
    pipeline=['coil_sampling', 'macromolecules', 'tap:clean', 'undersampling'],
    outputs=(('data', 'water'), ('clean', 'clean.water')),
    backend='pytorch',
)

# supervised reconstruction pairs: input fully augmented, target frozen at the tap
for (x, x_water), (y, y_water) in augmenter.dataloader():
    train_step(x, y)
```

### Per-Step Parameters, Seeds and Subject-Wise Splits

A keyword argument reaches every module whose constructor names it, so
`lb_hz=(0, 5)` would move `LineBroadening` *and* `Apodization` (you get a
warning). A pipeline entry can carry its own kwargs, which reach that step only
and override the globals there; a kwarg no module accepts raises with the
closest valid names instead of being ignored.

```python
augmenter = Augmentrum(
    data=data,
    groups=subject_ids,                     # one id per item: a subject never straddles splits
    split_fractions={'val': 0.1, 'test': 0.1},
    pipeline=[
        'coil_sampling',
        {'noise': {'sigma_frac': (0.0, 0.02)}},
        {'line_broadening': {'lb_hz': (0.0, 5.0)}},
        ('apodization', {'mode': 'exponential', 'lb_hz': 2.0}),
        'baseline_bspline',                 # registry alias fixing mode='bspline'
    ],
    n_coils=(1, 8),                         # integer-typed ranges are inclusive
    seed=1,                                 # fixes the split, subject draws, ranges and modules
)
augmenter.split_groups['val']               # the subject ids held out for validation
```

Without `groups`, a user-defined `SubjectID` header-extension field is used
when every item carries one. `seed` makes the whole run replay — including
`num_workers > 0` DataLoaders, where each worker is reseeded from it — and
`augmenter.reseed(k)` restarts every stream; `'fixed'` mode draws its ranges
once per split and keeps them across `dataloader()` calls.

---

## Module Reference & Backend Support

Every module is called as `module(nifti_plus, water)`.  When a backend is not
natively supported, the base class automatically routes the call through the
NIfTI-list path and returns the result in the original backend format —
no manual conversion needed.

| Module | Modes / Methods                                         | NIfTI | NumPy | PyTorch | TensorFlow | JAX | Keras |
|:---|:--------------------------------------------------------|:-----:|:---:|:---:|:---:|:---:|:---:|
| `AmplitudeScaling` | uniform, normal                                         |   ✓   | ✓ | ✓ | ✓ | ✓ | ✓ |
| `Apodization` | exponential, gaussian, hamming, truncate                |   ✓   | ✓† | ✓† | ✓† | ✓† | ✓† |
| `ArtificialPeaks` | Lorentzian, Gaussian, Voigt                             |   ✓   | ✓ | ✓ | ✓ | ✓ | ✓ |
| `AverageSampler` | random, consecutive, strided, deterministic             |   ✓   | ✓ | ✓ | ✓ | ✓ | ✓ |
| `BaselineAugmentation` | random_walk, bspline, polynomial                        |   ✓   | ✓ | ✓ | ✓ | ✓ | ✓ |
| `CoilSampler` | draw random, reweight, grow from CSMs |   ✓   | ✓ | ✓ | ✓ | ✓ | ✓ |
| `EddyCurrent` | synthetic, water (call-time reference or source library) |   ✓   | ✓ | ✓ | ✓ | ✓ | ✓ |
| `EditCombiner` | diff, sum along DIM_EDIT            |   ~   | ✓ | ✓ | ✓ | ✓ | ✓ |
| `FrequencyShift` | shift_hz                                                |   ✓   | ✓ | ✓ | ✓ | ✓ | ✓ |
| `Noise` | sigma, sigma_frac, snr, snr_db                          |   ✓   | ✓ | ✓ | ✓ | ✓ | ✓ |
| `KspaceUndersampling` | cartesian, gridded, nufft, dual trajectory              |   ~   | ✓ | ✓ | ✓ | ✓ | ✓ |
| `LineBroadening` | lorentzian, gaussian, voigt                             |   ✓   | ✓ | ✓ | ✓ | ✓ | ✓ |
| `Macromolecules` | parametrized, measured, supplied     |   ~   | ✓ | ✓ | ✓ | ✓ | ✓ |
| `RawProcessor` | coil combination, registration, ECC, ... |   ✓   | ✓‡ | ✓‡ | ✓‡ | ✓‡ | ✓‡ |
| `PhaseShift` | zero_order, first_order                                 |   ✓   | ✓ | ✓ | ✓ | ✓ | ✓ |
| `ResidualWater` | lobes, turco (7-Lorentzian WaterFit)                    |   ✓   | ✓ | ✓ | ✓ | ✓ | ✓ |
| `SpatialAugmentations` | 2-D / 3-D affine, flip, zoom, shear                     |   ✓   | ✓ | ✓ | ✓ | ✓ | ✓ |
| `SpuriousEchoes` | echo, replica, hybrid                                   |   ✓   | ✓ | ✓ | ✓ | ✓ | ✓ |
| `Tap` | marker: snapshot a stage for `outputs`         |   ✓   | ✓ | ✓ | ✓ | ✓ | ✓ |
| `TransientSynthesizer` | correlated drift, respiration, motion events            |   ~   | ✓ | ✓ | ✓ | ✓ | ✓ |
| `ZeroFill` | pad FID to target length                                |   ✓   | ✓† | ✓† | ✓† | ✓† | ✓† |

**✓** native — data tensor stays in the target framework throughout.  
**~** automatic — the base class routes the call through the NIfTI-list path; the result is returned in the original backend format. Functional, but not natively differentiable.  
**—** not supported / not applicable.

Modes that differ in backend support get a row each, named `Module[mode]`.

> **†** `Apodization[truncate]` and `ZeroFill` both change `N_PTS`. Because `target_pts` / `n_pts` is a module-level scalar, the **same length is applied uniformly to every batch member** — the output is still a uniform tensor.

> **‡** `RawProcessor[remove_outliers]` on tensor backends **zeroes outlier transients instead of dropping them** — a batched tensor cannot go ragged. 

---

## Contact

For questions, issues, or collaborations:

- **GitHub Issues**: [github.com/julianmer/Augmentrum/issues](https://github.com/julianmer/Augmentrum/issues)
- **Email**: jlamaste@gmail.com, j.p.merkofer@tue.nl, kci2104@columbia.edu

---

## Citation
J. T. LaMaster, J. P. Merkofer, K. C. Igwe, "Augmentrum: A Data Augmentation Package for MR Spectroscopy", _International Society for Magnetic Resonance in Medicine (ISMRM)_, Abstract #05685, Cape Town, South Africa, 2026.

---

<div align="center">
  <sub>Built with ❤️ for the MRS community</sub>
</div>
