Metadata-Version: 2.4
Name: longcombat-py
Version: 0.1.1
Summary: Python port of longCombat (Beer et al. 2020): longitudinal ComBat harmonization in a linear mixed-effects model framework.
Author-email: Tyler Ard <tylerard@ini.usc.edu>
License-Expression: Artistic-2.0
Project-URL: Homepage, https://github.com/NoiseFilterT/longcombat-py
Project-URL: Repository, https://github.com/NoiseFilterT/longcombat-py
Project-URL: Issues, https://github.com/NoiseFilterT/longcombat-py/issues
Project-URL: Upstream R package, https://github.com/jcbeer/longCombat
Project-URL: Paper (Beer et al. 2020), https://doi.org/10.1016/j.neuroimage.2020.117129
Keywords: combat,harmonization,neuroimaging,longitudinal,mixed-effects
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: numpy>=1.26
Requires-Dist: scipy>=1.11
Requires-Dist: pandas>=2.0
Requires-Dist: statsmodels>=0.14
Provides-Extra: plot
Requires-Dist: matplotlib>=3.7; extra == "plot"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: matplotlib>=3.7; extra == "dev"
Dynamic: license-file

# longcombat-py

Python port of [jcbeer/longCombat](https://github.com/jcbeer/longCombat).
The API mirrors [`neuroCombat`](https://github.com/Jfortin1/neuroCombat) where
concepts overlap so the two can be used side-by-side.

Longitudinal ComBat uses an empirical Bayes method to harmonize the means and
variances of the residuals across batches in a linear mixed-effects model
framework. See:

> Beer JC, Tustison NJ, Cook PA, Davatzikos C, Sheline YI, Shinohara RT,
> Linn KA (2020). *Longitudinal ComBat: A method for harmonizing
> longitudinal multi-scanner imaging data.* NeuroImage, 220:117129.
> <https://doi.org/10.1016/j.neuroimage.2020.117129>

> **Deviations from the R original** — this port is *not* bit-identical to
> the R package. Please read
> [`DIFFERENCES_FROM_R.md`](https://github.com/NoiseFilterT/longcombat-py/blob/main/DIFFERENCES_FROM_R.md)
> before using, especially if comparing results to the R output.

## Install

```bash
pip install longcombat-py            # core
pip install "longcombat-py[plot]"    # + matplotlib for visualization helpers
```

## Quick start

Long-format `pandas.DataFrame` with one row per (subject, visit):

```python
import pandas as pd
from longcombat import long_combat

result = long_combat(
    data=df,
    batch_col="scanner",
    id_col="subid",
    time_col="visit",
    features=["feature1", "feature2", "feature3"],
    formula="age + diagnosis*visit",     # Patsy RHS, fixed effects
    ranef="(1|subid)",                   # lme4-style random effects
)
harmonized = result.data_combat
```

`long_combat` returns a `LongCombatResult` with:

- `.data_combat` — harmonized DataFrame
  (`[id_col, time_col, batch_col, feature1.combat, ...]`)
- `.gammahat`, `.delta2hat` — method-of-moments estimates of additive and
  multiplicative batch effects on the standardized residuals
- `.gammastarhat`, `.delta2starhat` — empirical-Bayes shrunk estimates

## API surface

| Function | R analog |
|---|---|
| `long_combat` | `longCombat` |
| `add_test` | `addTest` (LRT only — see `DIFFERENCES_FROM_R.md`) |
| `mult_test` | `multTest` |
| `batch_time_viz` | `batchTimeViz` |
| `batch_boxplot` | `batchBoxplot` |
| `traj_plot` | `trajPlot` |

Parameter naming mirrors `neuroCombat` where the concept exists
(`batch_col`, `eb`, `mean_only`). Additional concepts from `longCombat`
(`id_col`, `time_col`, `ranef`, `formula`, `niter`, `method`) preserve the
R names.

## License

Artistic License 2.0. See
[`LICENSE`](https://github.com/NoiseFilterT/longcombat-py/blob/main/LICENSE) and
[`NOTICE`](https://github.com/NoiseFilterT/longcombat-py/blob/main/NOTICE).
