Metadata-Version: 2.4
Name: entropy-spine
Version: 0.1.0
Summary: SPINE: Scale Partitioning by Incremental Nested Entropy. Cut a nonnegative measure into scale strata, with no threshold to tune and no group count to declare.
Author-email: Abd AlRahman AlMomani <almomaniar@gmail.com>
License: MIT
Project-URL: Homepage, https://almomaa.github.io/entropy-spine/
Project-URL: Documentation, https://almomaa.github.io/entropy-spine/docs/python/index.html
Project-URL: Repository, https://github.com/almomaa/entropy-spine
Keywords: entropy,multiscale,scale separation,partitioning,outlier detection,information theory
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Operating System :: OS Independent
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.22
Provides-Extra: plot
Requires-Dist: matplotlib>=3.5; extra == "plot"
Dynamic: license-file

# entropy-spine

**SPINE — Scale Partitioning by Incremental Nested Entropy**

SPINE takes a nonnegative measure over a collection of objects and cuts it
into scale strata. It finds where the collection separates into distinct
scales, and how strongly, without being told how many groups to look for and
without a detection threshold to tune.

You supply two things: a **measure**, one nonnegative number per object, and
an **orientation**, saying which end of that measure is the atypical one.
Those are the scientific input. Everything after them is computed.

```bash
pip install entropy-spine          # numpy only
pip install "entropy-spine[plot]"  # with the figures (matplotlib)
```

```python
import numpy as np
from entropy_spine import spine, spine_summary

rng = np.random.default_rng(11)
X = np.vstack([rng.standard_normal((200, 2)),
               rng.standard_normal((12, 2)) + 9])

scores, result = spine(X, "dist2mean", "upper")
spine_summary(result)

result.n_strata          # 2
result.boundary_values   # the measure value at the cut, in your units
```

`scores` runs from 0 for the typical stratum to 1 for the most atypical, one
value per object, in your object order. **When there is nothing to find,
SPINE returns a single stratum** — an answer, not a failure.

## Documentation

- [User guide](https://almomaa.github.io/entropy-spine/docs/python/user-guide.html) —
  worked scenarios, runnable cell by cell
- [Function reference](https://almomaa.github.io/entropy-spine/docs/python/index.html) —
  one page per function, every example executed at build
- [Choosing a measure](https://almomaa.github.io/entropy-spine/docs/measure-guide.html) —
  the piece to read before applying SPINE to your own problem
- [The theory](https://almomaa.github.io/entropy-spine/) — why the construction
  works, in figures and equations

## Verified against the reference implementation

This package is developed in the same repository as the MATLAB reference
implementation and is checked against the shared cross-language conformance
fixtures: candidate sets, boundaries, and strata assignments must agree
**exactly**, continuous quantities to the stated tolerance. The layout
mirrors the reference: `core/` is the deterministic computation, `interface/`
everything a user touches, and nothing in core imports from interface.

https://github.com/almomaa/entropy-spine

## Citation

> A. R. AlMomani. *Scale Partitioning by Incremental Nested Entropy: A
> Measure-Oriented Theory of Multiscale Structure.* Embry-Riddle Aeronautical
> University, 2026.

## License

MIT
