Metadata-Version: 2.4
Name: hdr-clustering
Version: 0.1.3
Summary: HDR X-Means and HDR++ Merge clustering algorithms based on high-density-region ellipsoid intersections.
Project-URL: Homepage, https://github.com/General-Clustering/hdr_clustering
Project-URL: Repository, https://github.com/General-Clustering/hdr_clustering
Project-URL: Issues, https://github.com/General-Clustering/hdr_clustering/issues
Author: Hugo J. Bello
License-Expression: MIT
License-File: LICENSE
Keywords: clustering,ellipsoids,hdr,k-means,x-means
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
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: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.9
Requires-Dist: numpy>=1.23
Requires-Dist: scikit-learn>=1.2
Requires-Dist: scipy>=1.9
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: hatchling>=1.25; extra == 'dev'
Requires-Dist: matplotlib>=3.8; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Requires-Dist: twine>=5.0; extra == 'dev'
Provides-Extra: examples
Requires-Dist: matplotlib>=3.8; extra == 'examples'
Description-Content-Type: text/markdown

# HDR Clustering

[![PyPI version](https://img.shields.io/badge/PyPI-v0.1.2-blue.svg)](https://pypi.org/project/hdr-clustering/)
[![Python versions](https://img.shields.io/pypi/pyversions/hdr-clustering.svg)](https://pypi.org/project/hdr-clustering/)

Author: **Hugo J. Bello**

Repository: <https://github.com/General-Clustering/hdr_clustering>

Python implementation of the clustering algorithms introduced in **Automatic Cluster Discovery via High-Density Regions**:

- **HDR X-Means**: starts from an upper bound `kmax`, fits k-means, and reduces the number of clusters when their high-density-region ellipsoids intersect.
- **HDR++ Merge**: uses k-means++ seeding to create an initial partition, then merges connected components of intersecting HDR ellipsoids.

Both estimators expose a scikit-learn-like API with `fit`, `fit_predict`, `predict`, `labels_`, `cluster_centers_`, and `n_clusters_`.

![HDR X-Means on a 3-cluster 2D point cloud](https://github.com/General-Clustering/hdr_clustering/blob/main/docs/figures/hdr_x_means_3_clusters.png?raw=true)

## Reference

Hugo J. Bello, Domingo Gómez Pérez, and Steven Van Vaerenbergh. **Automatic Cluster Discovery via High-Density Regions**.

## Installation

From PyPI:

```bash
pip install hdr-clustering
```

From a local checkout:

```bash
pip install .
```

For development:

```bash
pip install -e ".[dev]"
pytest
```

## Quick Start

```python
import numpy as np
from hdr_clustering import HDRPlusPlusMerge, HDRXMeans

rng = np.random.default_rng(42)
X = np.vstack([
    rng.normal(loc=(-3, 0), scale=0.4, size=(100, 2)),
    rng.normal(loc=(3, 0), scale=0.4, size=(100, 2)),
])

xmeans = HDRXMeans(kmax=10, confidence=0.95, random_state=0)
labels = xmeans.fit_predict(X)

print(xmeans.n_clusters_)
print(xmeans.cluster_centers_)

merge = HDRPlusPlusMerge(kmax=10, confidence=0.95, random_state=0)
merge.fit(X)
new_labels = merge.predict(X[:5])
```

## 2D Examples

The figure above is generated from a reproducible 2D point-cloud example in:

```text
examples/plot_2d_examples.py
```

Regenerate the README figures with:

```bash
pip install -e ".[examples]"
python examples/plot_2d_examples.py
```

The example creates three Gaussian point clouds, fits **HDR X-Means**, and draws the final labels, centers, and HDR ellipsoids.

## HDR Merge Rule

Both algorithms use an ellipsoidal approximation of each cluster's high-density region. For a cluster with empirical center `mu` and regularized covariance `Sigma`, the HDR ellipsoid is:

```text
(x - mu)^T Sigma^-1 (x - mu) <= chi2.ppf(confidence, d)
```

where `d` is the data dimension. If two cluster ellipsoids intersect, the algorithms treat them as part of the same connected HDR component and merge them.

![HDR ellipsoid merge rule](https://github.com/General-Clustering/hdr_clustering/blob/main/docs/figures/hdr_ellipsoid_merge.svg?raw=true)

### HDR X-Means

`HDRXMeans` is useful when you want a k-means-style final assignment but do not want to choose the final number of clusters directly.

1. Start with `k = kmax`.
2. Fit k-means with `k` clusters.
3. Build one HDR ellipsoid per non-empty cluster.
4. If ellipsoids intersect, replace `k` with the number of connected components in the intersection graph.
5. Repeat until no intersections remain or `max_iter` is reached.
6. Fit final k-means with the selected `k`.

### HDR++ Merge

`HDRPlusPlusMerge` is useful when you want the HDR merge rule to act directly on an initial k-means++ partition.

1. Select up to `kmax` initial centers with k-means++ sampling.
2. Assign each sample to its nearest initial center.
3. Build HDR ellipsoids for the current clusters.
4. Merge connected components of intersecting ellipsoids.
5. Repeat until no intersections remain or `max_iter` is reached.

## API

### `HDRXMeans`

```python
HDRXMeans(
    kmax=20,
    confidence=0.99,
    random_state=None,
    ridge=1e-6,
    max_iter=100,
    n_jobs=None,
    n_init=10,
)
```

### `HDRPlusPlusMerge`

```python
HDRPlusPlusMerge(
    kmax=20,
    confidence=0.99,
    random_state=None,
    ridge=1e-6,
    max_iter=100,
    n_jobs=None,
)
```

Common parameters:

- `kmax`: maximum number of initial clusters.
- `confidence`: HDR mass level. Larger values produce larger ellipsoids and therefore more merging.
- `random_state`: reproducibility seed.
- `ridge`: diagonal covariance regularization for numerical stability.
- `max_iter`: maximum number of merge iterations.
- `n_jobs`: number of threads for HDR ellipsoid construction and pairwise intersection checks. Use `None` or `-1` for all available cores.

Fitted attributes:

- `labels_`: cluster label for each fitted sample.
- `cluster_centers_`: final cluster centers.
- `n_clusters_`: final number of clusters.
- `ellipsoids_`: final HDR ellipsoids.

## Backward Compatibility

The old class names remain available:

```python
from hdr_clustering import XMeansHDR, KMeansPPHDRMerge
```

The old root modules also re-export the new classes:

```python
from xmeans_hdr_multi import XMeansHDR
from kmeanspp_hdr_merge_robust_multi import KMeansPPHDRMerge
```

New code should prefer:

```python
from hdr_clustering import HDRXMeans, HDRPlusPlusMerge
```

The implementation modules are named after the algorithms:

```python
from hdr_clustering.hdr_x_means import HDRXMeans
from hdr_clustering.hdr_plus_plus_merge import HDRPlusPlusMerge
```

## Publishing

Build and upload with the helper script:

```bash
scripts/publish_pypi.sh
```

The script asks for the PyPI API token without echoing it in the terminal, bumps the patch version, rebuilds `dist/`, runs `twine check`, and uploads the wheel and source distribution.

To publish to TestPyPI instead:

```bash
scripts/publish_pypi.sh testpypi
```

Version bump options:

```bash
scripts/publish_pypi.sh pypi patch
scripts/publish_pypi.sh pypi minor
scripts/publish_pypi.sh pypi major
scripts/publish_pypi.sh pypi none
```

The package metadata already points to the GitHub repository and author information.
