Metadata-Version: 2.4
Name: pi-oplsda
Version: 1.1.0
Summary: A Python OPLS-DA estimator with scikit-learn style APIs, ropls-compatible computation modes, automatic orthogonal component selection, and publication-ready diagnostics.
Author-email: KaikunXu <xukaikun.bio@qq.com>
License: MIT License
        
        Copyright (c) 2026 KaikunXu
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://github.com/KaikunXu/pi-oplsda
Project-URL: Bug Tracker, https://github.com/KaikunXu/pi-oplsda/issues
Project-URL: Source, https://github.com/KaikunXu/pi-oplsda
Project-URL: Changelog, https://github.com/KaikunXu/pi-oplsda/blob/main/CHANGELOG.md
Keywords: chemistry,metabolomics,bioinformatics,chemometrics,lc-ms,mass-spectrometry,data-analysis,statistics,opls,opls-da,oplsda,ropls,scikit-learn,multivariate analysis,machine learning
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: Programming Language :: Python :: 3.13
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
Classifier: Topic :: Scientific/Engineering :: Chemistry
Classifier: Topic :: Scientific/Engineering :: Visualization
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.21.0
Requires-Dist: pandas>=1.3.0
Requires-Dist: scipy>=1.7.0
Requires-Dist: scikit-learn>=1.0.2
Requires-Dist: joblib>=1.3.0
Requires-Dist: matplotlib>=3.3.0
Requires-Dist: seaborn>=0.11.0
Requires-Dist: tqdm>=4.65.0
Requires-Dist: patchworklib>=0.6.2
Requires-Dist: plotnine>=0.10.1
Provides-Extra: test
Requires-Dist: pytest>=7.0.0; extra == "test"
Requires-Dist: tabulate>=0.10.0; extra == "test"
Requires-Dist: rpy2>=3.5.0; extra == "test"
Requires-Dist: packaging>=23.0; extra == "test"
Requires-Dist: pygments>=2.0; extra == "test"
Requires-Dist: python-dateutil>=2.8; extra == "test"
Requires-Dist: six>=1.16; extra == "test"
Requires-Dist: colorama>=0.4.6; platform_system == "Windows" and extra == "test"
Provides-Extra: benchmark
Requires-Dist: rpy2>=3.5.0; extra == "benchmark"
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: tabulate>=0.10.0; extra == "dev"
Requires-Dist: rpy2>=3.5.0; extra == "dev"
Requires-Dist: jupyter>=1.0.0; extra == "dev"
Requires-Dist: ipykernel>=6.0.0; extra == "dev"
Requires-Dist: packaging>=23.0; extra == "dev"
Requires-Dist: pygments>=2.0; extra == "dev"
Requires-Dist: python-dateutil>=2.8; extra == "dev"
Requires-Dist: six>=1.16; extra == "dev"
Requires-Dist: colorama>=0.4.6; platform_system == "Windows" and extra == "dev"
Dynamic: license-file

# `pi-oplsda`: pi-OPLS-DA

[![PyPI version](https://badgen.net/pypi/v/pi-oplsda)](https://pypi.org/project/pi-oplsda/)
[![License](https://badgen.net/github/license/KaikunXu/pi-oplsda)](https://github.com/KaikunXu/pi-oplsda/blob/main/LICENSE)
[![Python Version](https://badgen.net/pypi/python/pi-oplsda)](https://pypi.org/project/pi-oplsda/)

`pi-oplsda` bridges the rigorous algorithmic foundation of the R package `ropls` with the modern Python data science ecosystem. It provides native Pandas support, parallel permutation testing, scikit-learn style estimator methods, ropls-compatible statistical reporting, and publication-ready visualizations in one lightweight package.

## Core Capabilities

- **ropls-compatible computation:** Reproduces ropls-style OPLS-DA summaries, including cumulative $R^2X$, $R^2Y$, $Q^2$, RMSEE, VIP scores, predictive scores/loadings, and orthogonal scores.
- **Automatic orthogonal component selection:** Set `n_ortho="auto"` to select the number of orthogonal components with ropls-style rules.
- **Two compatibility modes:** Use `compatibility="ropls"` for R comparison and visualization consistency, or `compatibility="sklearn"` for fold-local preprocessing and modern Python ML conventions.
- **Scikit-learn style API:** `fit`, `predict`, `decision_function`, `transform`, `fit_transform`, and `score` are available on `OPLSDA`.
- **Pandas native:** `pandas.DataFrame` inputs preserve sample IDs and feature names in exported result tables.
- **Multi-core acceleration:** Permutation tests are parallelized with `joblib` and reported with `tqdm`.
- **Publication-ready graphics:** `OPLSDA_Visualizer` generates diagnostic plots for model summary, scores, outliers, permutation tests, VIP rankings, and S-plot style feature statistics.
- **Structured export:** Model metadata, component summaries, sample scores, and feature statistics are available as DataFrames.

> **Note:** Due to the nature of latent-variable models, scores and loadings may be flipped in sign between platforms. This is mathematically equivalent and does not affect interpretation.

## Installation

Install from PyPI:

```bash
pip install pi-oplsda
```

Install from GitHub:

```bash
pip install git+https://github.com/KaikunXu/pi-oplsda.git
```

Install from source for development:

```bash
git clone https://github.com/KaikunXu/pi-oplsda.git
cd pi-oplsda
pip install -e ".[dev]"
```

For benchmark/testing against R `ropls`, install the Python-side optional dependencies:

```bash
pip install -e ".[test]"
```

The R package `ropls` should be installed in your regular R installation. It is not bundled with this Python package.

## Quickstart & Tutorials

Interactive examples are provided in the `examples` directory:

- **[Quickstart Tutorial](https://github.com/KaikunXu/pi-oplsda/blob/main/examples/quickstart.ipynb):** ropls-compatible workflow with automatic orthogonal component selection.
- **[R-ropls Equivalence Benchmark](https://github.com/KaikunXu/pi-oplsda/blob/main/examples/benchmark.ipynb):** numerical comparison between Python and R implementations.
- **[Terminal Tutorial](https://github.com/KaikunXu/pi-oplsda/blob/main/examples/tutorial.py):** a script-oriented workflow.

Minimal ropls-compatible usage:

```python
from piopls import OPLSDA, load_sacurine

X, y, feature_names, sample_names = load_sacurine()

model = OPLSDA(
    n_ortho="auto",
    max_ortho=10,
    cv_folds=7,
    compatibility="ropls",
    random_state=42,
)

model.fit_pipeline(X, y, run_permutations=False)

print(model.n_ortho_)
print(model.get_model_info_df())
print(model.get_summary_df())
```

For a scikit-learn style workflow, use the default `compatibility="sklearn"` or set it explicitly:

```python
model = OPLSDA(n_ortho=1, compatibility="sklearn", random_state=42)
model.fit(X, y)

y_pred = model.predict(X)
y_score = model.decision_function(X)
accuracy = model.score(X, y)
```

## Visualization

Running `OPLSDA_Visualizer` generates a suite of diagnostic subplots:

- **Model Overview:** Step-wise and cumulative model quality metrics.
- **X-Score Plot:** Sample clustering in predictive and orthogonal latent spaces with confidence ellipses.
- **Observation Diagnostics:** Score distance and orthogonal distance / DModX for outlier inspection.
- **Permutation Test:** Original $R^2Y$ and $Q^2$ against permuted null distributions.
- **VIP Bar Plot:** Top features contributing to group separation.
- **S-Plot:** Feature covariance and correlation diagnostics for binary models.

```python
from piopls import OPLSDA_Visualizer

vis = OPLSDA_Visualizer(
    model=model,
    y=y,
    feature_names=feature_names,
    sample_names=sample_names,
    vip_threshold=1.0,
    top_n_vip=20,
)

vis.plot_all()
```

![pi-oplsda_visualizer](https://raw.githubusercontent.com/KaikunXu/pi-oplsda/main/assets/pi-oplsda_visualizer.png)

## Mathematical Equivalence & Benchmarking

`pi-oplsda` is validated against the R/Bioconductor package `ropls` to ensure scientific consistency. The benchmark uses the Sacurine human urine metabolomics dataset with 183 samples and 109 metabolites.

The current benchmark aligns the two implementations as follows:

- Python: `OPLSDA(n_ortho="auto", compatibility="ropls")`
- R: `ropls::opls(..., predI = 1, orthoI = NA, crossvalI = 7)`

Both implementations select two orthogonal components on the Sacurine dataset.

| Metric | Description | Comparison |
| :--- | :--- | :--- |
| **Global Quality** | Cumulative $R^2X$, $R^2Y$, and $Q^2$ | Approximately equal |
| **Error Assessment** | Root Mean Square Error of Estimation (RMSEE) | Approximately equal |
| **Latent Space** | Predictive scores, predictive loadings, and orthogonal scores | Pearson's r ~= 1 |
| **Variable Importance** | Variable Importance in Projection (VIP) scores | Pearson's r ~= 1 |

The benchmark figure summarizes global metrics and five vector-level comparisons: predictive scores (`t1`), predictive loadings (`p1`), VIP scores, and two orthogonal score vectors (`to1`, `to2`).

![pi_oplsda_benchmark.png](https://raw.githubusercontent.com/KaikunXu/pi-oplsda/main/assets/pi_oplsda_benchmark.png)

## Testing

Run the test suite with:

```bash
pytest tests
```

The R benchmark test uses `rpy2` and skips cleanly when a standalone R installation or the R package `ropls` is unavailable. On Windows, the benchmark setup expects a regular R installation such as `D:/R/R-4.5.2`.

## Changelog

Release notes are maintained separately in [CHANGELOG.md](https://github.com/KaikunXu/pi-oplsda/blob/main/CHANGELOG.md).

## Acknowledgements

The algorithmic foundation of `pi-oplsda` is inspired by the excellent R package [`ropls`](https://bioconductor.org/packages/ropls/).

## Contributing

Contributions, issues, and feature requests are welcome. Feel free to check the [issues page](https://github.com/KaikunXu/pi-oplsda/issues).

## License

This project is licensed under the **MIT License**.
