Metadata-Version: 2.4
Name: jamica
Version: 0.3.0
Summary: Native Python implementation of AMICA for MNE-Python and scientific EEG workflows.
Author-email: Sina Esmaeili <sina.esmaeili@umontreal.ca>
License-Expression: BSD-3-Clause
Project-URL: Homepage, https://github.com/snesmaeili/jamica
Project-URL: Documentation, https://snesmaeili.github.io/jamica/
Project-URL: Repository, https://github.com/snesmaeili/jamica.git
Project-URL: Issues, https://github.com/snesmaeili/jamica/issues
Project-URL: Changelog, https://github.com/snesmaeili/jamica/blob/main/CHANGELOG.md
Keywords: jamica,amica,ica,eeg,mne,neuroscience,blind-source-separation
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.21
Requires-Dist: scipy>=1.7
Provides-Extra: jax
Requires-Dist: jax>=0.4; extra == "jax"
Provides-Extra: gpu
Requires-Dist: jax[cuda12]>=0.4; extra == "gpu"
Provides-Extra: mne
Requires-Dist: mne>=1.0; extra == "mne"
Provides-Extra: hdf5
Requires-Dist: h5io; extra == "hdf5"
Provides-Extra: icalabel
Requires-Dist: mne-icalabel>=0.4; extra == "icalabel"
Requires-Dist: onnxruntime; extra == "icalabel"
Provides-Extra: viz
Requires-Dist: matplotlib>=3.5; extra == "viz"
Provides-Extra: test
Requires-Dist: jamica[jax,viz]; extra == "test"
Requires-Dist: pytest>=8.0; extra == "test"
Requires-Dist: pytest-cov; extra == "test"
Requires-Dist: pytest-xdist; extra == "test"
Requires-Dist: pytest-timeout; extra == "test"
Requires-Dist: pandas>=2.0; extra == "test"
Requires-Dist: scikit-learn>=1.0; extra == "test"
Requires-Dist: psutil; extra == "test"
Requires-Dist: python-picard; extra == "test"
Requires-Dist: h5io; extra == "test"
Provides-Extra: docs
Requires-Dist: sphinx>=7.0; extra == "docs"
Requires-Dist: numpydoc; extra == "docs"
Requires-Dist: sphinx-gallery; extra == "docs"
Requires-Dist: pydata-sphinx-theme; extra == "docs"
Requires-Dist: myst-parser; extra == "docs"
Requires-Dist: sphinx-copybutton; extra == "docs"
Requires-Dist: sphinx-design; extra == "docs"
Requires-Dist: towncrier; extra == "docs"
Requires-Dist: linkify-it-py; extra == "docs"
Provides-Extra: dev
Requires-Dist: jamica[docs,test]; extra == "dev"
Requires-Dist: pre-commit>=3.0; extra == "dev"
Requires-Dist: ruff>=0.9; extra == "dev"
Requires-Dist: towncrier>=23.0; extra == "dev"
Requires-Dist: nox; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"
Provides-Extra: release
Requires-Dist: build; extra == "release"
Requires-Dist: twine; extra == "release"
Requires-Dist: towncrier>=23.0; extra == "release"
Provides-Extra: all
Requires-Dist: jamica[docs,hdf5,icalabel,jax,mne,test,viz]; extra == "all"
Dynamic: license-file

<p align="center">
  <picture>
    <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/snesmaeili/jamica/main/docs/_static/logo-dark.png?v=4">
    <img src="https://raw.githubusercontent.com/snesmaeili/jamica/main/docs/_static/logo.png?v=4" alt="jamica - Adaptive Mixture Independent Component Analysis, powered by JAX" width="420">
  </picture>
</p>

<p align="center"><strong>JAX-accelerated Adaptive Mixture Independent Component Analysis for Python.</strong></p>

[![CI](https://img.shields.io/github/actions/workflow/status/snesmaeili/jamica/tests.yml?branch=main&label=CI)](https://github.com/snesmaeili/jamica/actions/workflows/tests.yml)
[![Docs](https://img.shields.io/github/actions/workflow/status/snesmaeili/jamica/docs.yml?branch=main&label=docs)](https://snesmaeili.github.io/jamica/)
[![Codecov](https://img.shields.io/codecov/c/github/snesmaeili/jamica)](https://codecov.io/gh/snesmaeili/jamica)
[![PyPI - Version](https://img.shields.io/pypi/v/jamica.svg)](https://pypi.org/project/jamica/)
[![conda-forge](https://img.shields.io/conda/vn/conda-forge/jamica.svg)](https://anaconda.org/conda-forge/jamica)
[![Python Versions](https://img.shields.io/pypi/pyversions/jamica.svg)](https://pypi.org/project/jamica/)
[![License](https://img.shields.io/badge/license-BSD--3--Clause-blue.svg)](LICENSE)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.21817485.svg)](https://doi.org/10.5281/zenodo.21817485)

jamica is a JAX implementation of **AMICA** (Adaptive Mixture Independent Component Analysis), an algorithm for blind source separation. It is aimed mainly at EEG.

AMICA is one of the strongest methods in the ICA family for EEG decomposition. The original implementation is a Fortran program from UCSD, usually run through MATLAB or EEGLAB. jamica rewrites it in Python on top of JAX, so the same code JIT-compiles and runs on either CPU or GPU, and it works directly with **MNE-Python**.

______________________________________________________________________

# Why jamica?

JAX + AMICA = jamica. The name also describes the problem AMICA solves.

Record a jam session with a few microphones. Each one picks up a different blend of the same players. Getting the individual instruments back out of those recordings is blind source separation, which is what ICA does for EEG: electrodes pick up mixtures of cortical, muscular and ocular activity, and the job is to pull them apart again.

A jam is rarely one fixed mixture, though. Players drop in and out. Someone takes a solo. The statistics of what the microphones hear keep shifting. AMICA handles this by fitting several mixture models instead of one, and by learning the shape of each source distribution rather than assuming it. That makes it a good match for data a single stationary ICA model does not describe well.

jamica runs that algorithm on JAX, on CPU or GPU, inside the usual Python scientific stack.

> **Status:** jamica reproduces the Fortran AMICA 1.7 reference on the tested single-model configurations. See [Validation](#validation).

______________________________________________________________________

# Highlights

- The AMICA algorithm in Python, JIT-compiled through **JAX**
- Runs on CPU or GPU without changing your code
- Numerical agreement with the Fortran AMICA 1.7 reference on the tested configurations
- Native integration with **MNE-Python**
- Support for **multi-model AMICA**
- Modern scientific Python API
- Extensive testing and continuous integration
- Fully open source (BSD-3-Clause)

______________________________________________________________________

# Installation

```bash
pip install "jamica[jax]"
```

or, from conda-forge:

```bash
conda install -c conda-forge jamica jax
```

> **Renamed from `amica`.** Releases up to 0.1.0 were published as `amica`.
> That name installed a top-level `amica` module, which collided with
> `amica-python` — an independent implementation of the same algorithm by
> another author — so the two could not coexist in one environment. Since
> 0.2.0 this project installs as `jamica`, and the two can be installed side
> by side.

For NVIDIA GPUs, take the CUDA build of JAX instead:

```bash
pip install "jamica[gpu]"        # JAX with CUDA 12 (Linux only)
```

The other extras are separate, so you only install what you need:

```bash
pip install "jamica[mne]"        # MNE-Python integration, fit_ica()
pip install "jamica[icalabel]"   # ICLabel component classification
pip install "jamica[viz]"        # plotting and density diagnostics
pip install "jamica[all]"        # everything above
```

## From source

For development, or to run the test suite:

```bash
git clone https://github.com/snesmaeili/jamica.git
cd jamica
pip install -e ".[dev]"
```

With `uv`:

```bash
git clone https://github.com/snesmaeili/jamica.git
cd jamica
uv venv && source .venv/bin/activate
uv pip install -e ".[dev]"
```

______________________________________________________________________

# Quick Start

```python
from jamica import Amica, AmicaConfig

config = AmicaConfig(
    max_iter=2000,
    num_mix_comps=3,
)

model = Amica(config, random_state=42)

result = model.fit(data)

sources = model.transform(data)
```

For MNE-Python:

```python
from jamica import fit_ica

ica = fit_ica(raw)

ica.plot_components()
ica.apply(raw)
```

For integrations that already whiten and PCA-reduce their data, `jamica.amica`
is the stable single-model solver boundary:

```python
from jamica import amica

_, W, sources, n_iter = amica(
    X_ica,
    whiten=False,
    return_n_iter=True,
    random_state=42,
)
```

Here `X_ica` is shaped `(n_components, n_samples)`, `sources == W @ X_ica`,
and JAMICA performs no additional centering, whitening, or PCA. Multi-model
adaptive ICA and its model probabilities remain available through the native
JAMICA API rather than this conventional-ICA boundary.

See the [MNE single-model solver contract](docs/mne_solver_contract.md) for
the exact matrix, preprocessing, random-state, and error guarantees.

______________________________________________________________________

# Examples

Example scripts are available in the `examples/` directory, including:

- MNE-Python integration
- Native AMICA API
- JAX acceleration
- Multi-model AMICA
- HPC / SLURM execution

______________________________________________________________________

# Documentation

Full documentation, API reference, validation experiments, and tutorials are available at

**https://snesmaeili.github.io/jamica/**

______________________________________________________________________

# Validation

jamica reproduces the **Fortran AMICA 1.7** reference on single-model fits: final log-likelihoods,
unmixing matrices and adaptive-density parameters agree closely across `K=1` and `K=3` density terms,
under both Newton and natural-gradient updates, and on a 100-iteration audit on real EEG.

Protocols, the patched reference build, comparisons against other AMICA implementations and against
Picard, extended Infomax and FastICA, and every figure and table in the manuscript are in
**[jamica-benchmark](https://github.com/snesmaeili/jamica-benchmark)**. Exact scope is in the
[documentation](https://snesmaeili.github.io/jamica/explanation.html#numerical-validation).

______________________________________________________________________

# Contributing

Contributions are welcome!

Please read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a pull request.

Parts of jamica were written with AI assistance; [AI_USAGE.md](AI_USAGE.md) says where, and what it
does not change about how the package is verified.

______________________________________________________________________

# Citation

If jamica contributes to your research, please cite the original AMICA publications.

Citation metadata is available in
[CITATION.cff](CITATION.cff).

______________________________________________________________________

# License

jamica is distributed under the terms of the BSD 3-Clause License.
