Metadata-Version: 2.5
Name: opfython
Version: 2.0.1
Summary: Python-Inspired Optimum-Path Forest Classifier
Author-email: Gustavo Rosa <gustavo.rosa@unesp.br>
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Education
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: Libraries :: Python Modules
License-File: LICENSE
Requires-Dist: numba>=0.67.0
Requires-Dist: numpy>=2.4.4
Requires-Dist: coverage>=7.10.0 ; extra == "tests"
Requires-Dist: flake8>=7.3.0 ; extra == "tests"
Requires-Dist: pytest>=9.0.0 ; extra == "tests"
Project-URL: Documentation, https://opfython.readthedocs.io
Project-URL: Homepage, https://github.com/gugarosa/opfython
Project-URL: Issues, https://github.com/gugarosa/opfython/issues
Provides-Extra: tests
Import-Name: opfython

# OPFython

[![PyPI](https://img.shields.io/pypi/v/opfython.svg)](https://pypi.org/project/opfython/)
[![CI](https://github.com/gugarosa/opfython/actions/workflows/ci.yml/badge.svg)](https://github.com/gugarosa/opfython/actions/workflows/ci.yml)
[![Documentation](https://readthedocs.org/projects/opfython/badge/?version=latest)](https://opfython.readthedocs.io/)
[![DOI](https://img.shields.io/badge/DOI-10.1016/j.simpa.2021.100113-006DB9.svg)](https://doi.org/10.1016/j.simpa.2021.100113)
[![License](https://img.shields.io/github/license/gugarosa/opfython.svg)](LICENSE)

OPFython is a Python implementation of the Optimum-Path Forest family of
classifiers. It provides supervised, semi-supervised, unsupervised, and
KNN-supervised models backed by NumPy and Numba.

This implementation follows [LibOPF](https://github.com/jppbsi/LibOPF).
Please cite the original LibOPF authors as well as OPFython when using it in
research.

OPFython requires Python 3.11 or newer.

## Installation

```bash
uv add opfython
```

## Quick start

```python
import numpy as np

from opfython.models import SupervisedOPF

X_train = np.asarray([[0.0, 0.0], [0.1, 0.2], [1.0, 1.0], [1.1, 0.9]])
Y_train = np.asarray([0, 0, 1, 1])
X_test = np.asarray([[0.05, 0.1], [1.05, 1.0]])

classifier = SupervisedOPF()
classifier.fit(X_train, Y_train)
predictions = classifier.predict(X_test)
```

Labels must be zero-based and sequential. Pre-computed distance matrices can
be supplied through each classifier's `pre_computed_distance` constructor
argument.

Features, labels, and optional sample indexes must have matching sample
counts; mismatches raise `opfython.utils.exception.SizeError`. Supervised
and semi-supervised models also support a single labeled class. KNN models
require `1 <= k < number of training samples`.

When splitting a pre-computed matrix's dataset, retain its original sample
indexes with `stream.splitter.split_with_index` and pass the corresponding
indexes to `fit` and `predict`. The matrix must cover those indexes, not
merely match the training subset's size. See the
[`pre-computed distance example`](examples/applications/supervised_opf_pre_computed_distances.py).

## Classifiers

| Class | Purpose |
|---|---|
| `SupervisedOPF` | Complete-graph supervised classification |
| `KNNSupervisedOPF` | Supervised classification with learned KNN adjacency |
| `SemiSupervisedOPF` | Learning from labeled and unlabeled samples |
| `UnsupervisedOPF` | Density-based clustering and label propagation |

The package also includes 47 distance metrics, random generators, OPF
evaluation measures, dataset loaders and splitters, package logging and
exception helpers, and converters for LibOPF binary datasets.

Clustering purity is independent of cluster numbering and supports more
clusters than true classes. Evaluation measures require one prediction for
each true label and handle class IDs missing from an evaluation split.

See [the documentation](https://opfython.readthedocs.io/) and the
[`examples/applications`](examples/applications) directory for complete
workflows.

## Development

```bash
uv sync --all-groups
uv run pytest
uv run pre-commit run --all-files
uv run --group docs sphinx-build -W -b html docs docs/_build/html
uv build --no-sources
```

## Citation

```bibtex
@article{rosa2021simpa,
    title = {OPFython: A Python implementation for Optimum-Path Forest},
    author = {Gustavo H. {de Rosa} and Joao P. Papa},
    journal = {Software Impacts},
    pages = {100113},
    year = {2021},
    issn = {2665-9638},
    doi = {https://doi.org/10.1016/j.simpa.2021.100113}
}
```

```bibtex
@misc{rosa2021speedup,
    title = {Speeding Up OPFython with Numba},
    author = {Gustavo H. de Rosa and Joao Paulo Papa},
    year = {2021},
    eprint = {2106.11828},
    archivePrefix = {arXiv},
    primaryClass = {cs.LG}
}
```

OPFython is licensed under the Apache License 2.0.

