Metadata-Version: 2.4
Name: pamica
Version: 0.4.0
Summary: pAMICA: Python implementation of the Adaptive Mixture ICA algorithm
Author-email: Seyed Yahya Shirazi <shirazi@ieee.org>
Maintainer-email: Seyed Yahya Shirazi <shirazi@ieee.org>
License: BSD-3-Clause
Project-URL: Homepage, https://github.com/sccn/pAMICA
Project-URL: Repository, https://github.com/sccn/pAMICA
Project-URL: Documentation, https://eeglab.org/pAMICA/
Project-URL: Changelog, https://eeglab.org/pAMICA/changelog/
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy
Requires-Dist: scipy
Requires-Dist: matplotlib
Requires-Dist: tqdm
Requires-Dist: json5
Requires-Dist: torch>=2.12.1
Requires-Dist: threadpoolctl>=3
Provides-Extra: mlx
Requires-Dist: mlx>=0.32; extra == "mlx"
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.5; extra == "docs"
Requires-Dist: mkdocstrings[python]>=0.26; extra == "docs"
Requires-Dist: mkdocs-git-revision-date-localized-plugin>=1.2; extra == "docs"
Provides-Extra: viz
Requires-Dist: mne>=1.6; extra == "viz"
Provides-Extra: mne
Requires-Dist: mne>=1.6; extra == "mne"
Dynamic: license-file

# pAMICA: Adaptive Mixture ICA

[![CI](https://github.com/sccn/pAMICA/actions/workflows/ci.yml/badge.svg)](https://github.com/sccn/pAMICA/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/sccn/pAMICA/branch/main/graph/badge.svg)](https://codecov.io/gh/sccn/pAMICA)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.21312148.svg)](https://doi.org/10.5281/zenodo.21312148)
[![Docs](https://img.shields.io/badge/docs-eeglab.org%2FpAMICA-blue)](https://eeglab.org/pAMICA/)
[![status](https://joss.theoj.org/papers/891de3e30f0973ab984ff879105dad35/status.svg)](https://joss.theoj.org/papers/891de3e30f0973ab984ff879105dad35)

Python (PyTorch) implementation of Adaptive Mixture Independent Component Analysis
(AMICA) that reproduces the reference Fortran implementation within numerical
tolerance, with CPU, NVIDIA GPU (CUDA), and Apple GPU (MLX) support. It targets
EEG/EMG blind source separation and is a drop-in replacement for EEGLAB's AMICA:
single-model output is written in exactly the reference's on-disk format and
loads directly in EEGLAB.

Single-model results match the Fortran reference (Hungarian-matched component correlation 0.9996
on well-determined data, Newton disabled, with the reference agreeing with itself at 0.998); see the
[documentation](https://eeglab.org/pAMICA/) for validation details and the backend-selection guide.

## Overview

AMICA (Adaptive Mixture ICA) is an advanced blind source separation algorithm that uses adaptive mixtures of independent component analyzers. This implementation provides:

- Multiple source models
- Different PDF types
- Newton optimization
- Component sharing
- Outlier rejection
- Data preprocessing (mean removal, sphering)

## Installation

Released versions are on PyPI: `uv add pamica` (or `uv pip install pamica`).
The development version, with the changes listed as unreleased in the
[changelog](https://eeglab.org/pAMICA/changelog/), installs from source; the
canonical environment is [uv](https://docs.astral.sh/uv/):

```bash
git clone https://github.com/sccn/pAMICA.git
cd pAMICA
uv sync                     # install dependencies into a managed venv
uv run pytest               # optional: run the tests
```

The optional Apple-GPU backend (MLX, Apple Silicon only) installs with the `mlx`
extra: `uv sync --extra mlx` from source, or `uv add "pamica[mlx]"`.

## Usage

pamica exposes a scikit-learn-style estimator backed by the PyTorch
natural-gradient EM implementation:

```python
import numpy as np
from pamica import AMICA

# X is (n_channels, n_samples) of real EEG/EMG; float64 gives Fortran parity
model = AMICA(n_models=1, n_mix=3).fit(X)

sources = model.transform(X)       # (n_sources, n_samples)
maps = model.get_sensor_mixing_matrix()  # scalp maps, (n_channels, n_sources)
order = model.variance_order()     # EEGLAB IC order (IC1 = highest variance)
```

### Backends and precision

The wrapper auto-selects a device and computes in float64 for Fortran parity;
on a Mac, where the Metal Performance Shaders (MPS) device has no float64, a default fit runs on the CPU.

- CPU and CUDA (float64) are bit-reproducible; use them for parity runs.
- float32 (about 7 significant digits, not parity) is required on the Apple GPUs
  and modestly faster on CPU; it is not a general speedup, since CUDA is
  overhead-bound (float32 is about as fast as float64).
- On Apple Silicon the MLX backend is the fastest option and carries the full
  feature surface (all pdf families, Newton, rejection, EEGLAB export, and
  Mutual Information Reduction (MIR) diagnostics); select it with
  `backend="mlx"` on `AMICA` or the MNE wrapper `AMICAICA` (float32 only).

```python
AMICA(device="cuda").fit(X)               # NVIDIA GPU, float64
AMICA(backend="mlx").fit(X)               # Apple GPU, float32 (install the mlx extra)
```

### EEGLAB interoperability

pamica writes results in EEGLAB's AMICA output format, so a run drops into an
EEGLAB workflow with no manual re-ordering or sign-flipping:

```python
model.write_amica_output("amicaout")   # gm, W, S, mean, c, alpha, mu, sbeta, rho, ...
```

```matlab
mod = loadmodout15('amicaout');   % components in EEGLAB variance order
```

pamica's defaults follow the compiled amica15 binary (`lrate` 0.1, Newton off),
and EEGLAB's `runamica15.m` sets its own (`lrate` 0.05, Newton on).
To rerun an EEGLAB decomposition, fit from the `input.param` that `runamica15.m` wrote beside its output:
`AMICA.from_params_file("amicaouttmp/input.param").fit(X)`.
The [defaults table](https://eeglab.org/pAMICA/guides/amica-differences/#default-settings-issue-354) lists every setting in the three sources.

### Legacy NumPy CLI

The NumPy reference backend keeps a command-line interface, driven by a
pamica JSON parameter file or a Fortran `input.param`:

```bash
python -m pamica.numpy_impl.cli params.json --outdir results
```

See the [documentation](https://eeglab.org/pAMICA/) for the full API, the
parameter reference, and the backend-selection and validation guides.

## Citation

If you use pamica, please cite it (see [CITATION.cff](CITATION.cff)) and the
original AMICA method:

> Palmer, J. A., Kreutz-Delgado, K., & Makeig, S. (2012). AMICA: An adaptive
> mixture of independent component analyzers with shared components. Technical
> report, Swartz Center for Computational Neuroscience, UC San Diego.

## License

This project is licensed under the BSD 3-Clause License - see the [LICENSE](LICENSE) file for details.
