Metadata-Version: 2.4
Name: heterodecomp
Version: 0.1.0
Summary: Shared and individual pattern decomposition for heterogeneous data
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: numpy>=1.23
Requires-Dist: openpyxl>=3.1
Requires-Dist: pandas>=1.5
Requires-Dist: pillow>=9
Requires-Dist: scipy>=1.9
Requires-Dist: tensorly>=0.8
Requires-Dist: torch>=2.0
Provides-Extra: eeg
Requires-Dist: mne>=1.6; extra == "eeg"
Provides-Extra: test
Requires-Dist: build>=1; extra == "test"
Requires-Dist: twine>=5; extra == "test"

# HeteroDecomp

HeteroDecomp separates repeated data items into shared, individual-specific, and
residual patterns. It accepts time-series tables (BOLD, EEG, and similar
signals), general matrices (including symmetric FC matrices), and common image
formats.

## Install for development

```bash
python -m pip install -e .
```

Install the optional EEG reader for MNE FIF files:

```bash
python -m pip install -e ".[eeg]"
```

## Basic API

```python
from heterodecomp import decompose

result = decompose(
    r"D:\data\bold",
    kind="timeseries",
    algorithm="perpca",
    shared_rank=5,
    individual_rank=2,
    params={"epochs": 200, "lr": 0.01},
)

print(result.summary_metrics)
print(result.output_dir)
```

Before fitting, HeteroDecomp prints detected shapes, headers, index columns, missing
values, constant columns, symmetry, and a recommended truncation length when
time series differ in duration. Use explicit `header=` and `index=` arguments
to override conservative automatic detection.

By default, outputs are saved beside the input directory in separate `shared`,
`individual`, `reconstruction`, and `residual` folders. Per-item metrics,
summary metrics, the data audit, and model metadata are saved with them.

## Functional-connectivity matrices

```python
result = decompose(
    r"D:\data\fc",
    kind="matrix",
    algorithm="perpca",
    shared_rank=10,
    individual_rank=3,
    output_format="xlsx",
)
```

If every input is square and symmetric within tolerance, every saved shared and
individual FC component is explicitly symmetrized and keeps its detected row
and column labels.

## Images

```python
result = decompose(
    r"D:\data\frames",
    kind="image",
    algorithm="perpca",
    shared_rank=5,
    individual_rank=20,
    image_format="png",
)
```

PNG previews are accompanied by `exact_components.npz`, which preserves signed
individual and residual arrays without visualization clipping.

## Simulated ground truth

```python
from heterodecomp import evaluate_ground_truth

metrics = evaluate_ground_truth(
    result,
    r"D:\data\shared_signal",
    r"D:\data\individual_signal",
)
```

Ground-truth recovery metrics are kept separate from real-data metrics so that
recovery claims cannot accidentally be made for empirical datasets.

## P300 validation

```python
from heterodecomp import prepare_p300, validate_p300

prepared = prepare_p300(r"D:\data\P300")
validation = validate_p300(prepared, shared_rank=5, individual_rank=2)
print(validation.pearson_r, validation.permutation_p)
```

P300 validation matches the recovered shared spatial basis to the group target
topography, applies a maximum-component channel-label permutation test, and
reports target/non-target projection effects and peak latency.

## Algorithms

`perpca`, `hmf`, `jive`, `robust_jive`, `rajive`, `slide`, `pertucker`,
`percdl`, and `robust_pca` share one interface. Algorithm-specific settings are
passed through `params`; see each adapter in `heterodecomp/_engine/models` for the
accepted options.

All algorithms print interpretable quality metrics approximately every 1% of
the configured iterations (`epochs=300` prints every 3 iterations), including
explained variance, reconstruction correlation, residual energy, and—where
available—shared/individual energy allocation. Internal optimizer losses are
not printed. Runs shorter than 100 iterations print every iteration. Pass
`params={"progress": False}` to disable progress. RaJIVE has no epoch loop, so
it reports the equivalent block and decomposition stages instead.

Complete runnable examples for every algorithm are in
[`examples/README.md`](examples/README.md).

## Test

```bash
python -m unittest discover -s tests -v
python -m build
python -m twine check dist/*
```
