Statistically grounded topological data analysis for Python.
akriti.io ·
Apache-2.0 ·
built on GUDHI and Ripser
Persistence diagrams tell you what shape your data has. Akriti tells you whether the answer is significant.
It provides the statistical layer that Python's TDA stack lacks — hypothesis tests, effect sizes, per-region significance, and sample-size calculation for persistence diagrams — while delegating persistence computation to the established engines rather than reimplementing them.
Status
Early development. The API is unstable and much of what is described below is not written yet.
akriti 0.1.0is on PyPI as of 2026-08-27 — one working module,akriti.diagrams, and nothing else. Star the repository to follow progress, or watch akriti.io.
We would rather be accurate than impressive, so:
| Module | What it is | State |
|---|---|---|
akriti.diagrams |
One persistence-diagram type, with adapters for GUDHI, Ripser, giotto-tda, persim and plain arrays — specified by RFC-0001 | building |
akriti.castle |
Two-sample test, sample-size calculator, per-region significance map, robustness certificate, reporting card | planned — scaffold in review |
akriti.core |
Landmark embeddings (PLACE / PALACE), closed-form selectors, certificate radii | planned — core/distances.py is specified by RFC-0001 §9.1 and not yet written |
akriti.compute |
Diagrams from point clouds, images, time series and graphs — delegated, with defended defaults | planned |
akriti.vectorise |
Persistence images, landscapes, Betti curves, landmark embeddings, plus a maintained benchmark | planned |
akriti.compat |
Compatibility layer for giotto-tda pipelines | planned |
Why
Three gaps, stated as precisely as we can:
- Statistical inference for diagrams lives in R, not Python. The
TDA,TDAstatsandtdaversepackages have offered permutation tests and bootstrap confidence sets for years. Python users have had essentially nothing. - No library, in any language, calculates sample size for a topological effect. "How many samples do I need to detect a bottleneck-distance difference of size δ?" is a question applied statistics answers routinely, and topology has never answered at all.
- Python's general-purpose TDA layer has gone quiet. giotto-tda has had no commits since 2024 while still being installed thousands of times a month. Its users deserve somewhere maintained to land.
Design commitments
- We delegate computation. Persistence, bottleneck and Wasserstein distances go to GUDHI, Ripser and Hera. We do not reimplement them, and we will not.
- Backend-agnostic input. Bring diagrams from any library, or none.
- Honest defaults. Where our theory supports a principled choice of filtration, scale or descriptor, the library makes it and explains why. Where it provably does not — the landmark budget, placement, bandwidth, and the concatenation rules — the library says so and points you at cross-validation instead of pretending.
- Permissive by default. Apache-2.0, and the default install closure is permissive-only — verified in CI, not asserted. Every backend has a copyleft dependency somewhere in its closure, so every backend is an opt-in extra.
Specifications
Before the code, the contract. RFC-0001 — Persistence Diagram Interchange pins down what a persistence diagram is across Python's backends: infinite bars, ordering, precision, equality, metadata and serialization. It is open for comment, and it is useful whether or not you ever install this library — the R ecosystem solved interchange first, and Python has not.
Every convention in it was measured against GUDHI, Ripser, persim and giotto-tda
rather than recalled. rfcs/evidence/probe_backends.py reproduces every number.
Three findings you may want regardless of Akriti:
- giotto-tda silently drops the essential H0 bar — under every
infinity_valuessetting. 40 points, 40 components, 39 reported. - giotto-tda's batch padding is indistinguishable from real bars. The same point cloud yields 2 one-dimensional bars alone and 11 when batched with another; the padding is written with a genuine birth value.
persim.bottleneckreturns a finite distance between diagrams that are infinitely far apart — 0.5 where the answer is ∞. It does warn that it is dropping the infinite bars, but the warning describes the mechanism rather than the consequence, and it fires more often on the case it gets right than on the case it gets wrong.
Install
pip install akriti # interchange layer — zero dependencies
pip install akriti[rips] # + Ripser (MIT, GPLv3 transitively)
pip install akriti[alpha] # + GUDHI (GPLv3)
pip install akriti[distances] # + persim (MIT, GPLv3 transitively)
pip install akriti[numpy] # + NumPy namespace / Python-row fallback
pip install akriti[parquet] # + PyArrow (Apache-2.0)
pip install akriti[torch] # + torch and array-api-compat
pip install akriti[jax] # + JAX (Apache-2.0); see the note below
pip install akriti[bio] # + anndata (BSD-3)
Currently a placeholder release; real functionality is coming.
Nothing is a required dependency — no persistence backend, and no NumPy
either. Native array inputs retain their Python array API namespace. Accepted
Python-row adapter inputs lazily use akriti[numpy]; torch tensors use the
compatibility resolver supplied by akriti[torch]; and Parquet imports
PyArrow only when requested through akriti[parquet]. JAX arrays need no such
boundary -- they expose the namespace natively, so akriti[jax] is a
convenience that installs JAX for you and nothing more. "Bring your own
diagrams" remains the primary path by design. The licence consequences above
are stated here rather than in a footnote because they are real: persim
depends on hopcroftkarp, which is GPLv3 and has had no release since 2019,
and the gudhi wheel bundles CGAL-dependent modules and ships no licence
metadata at all. See DEPENDENCIES.md for the verified
closure, and tools/check_license_closure.py for the CI gate that keeps it
honest.
JAX needs a 64-bit configuration that you set, not us. A diagram stores
float64 births and deaths, and a default JAX install truncates both to
float32 -- so building one raises a ValueError naming the dtype it got.
Either lever fixes it, and the first is narrower and preferred, changing only
what akriti asks for rather than every default dtype in your process:
import jax
jax.config.update("jax_explicit_x64_dtypes", "allow") # preferred
jax.config.update("jax_enable_x64", True) # heavier alternative
akriti will not set either for you. Both are process-global, so a library setting one would silently change the numerics of unrelated JAX code in your program. See RFC-0001 §3.3 and D23.
The research behind it
| CASTLE (Paper IV) | A practitioner's toolkit for topological two-sample testing, sample-size calculation and robustness certification · in preparation |
| Paper III | A statistical-inference pipeline for persistence-landmark kernels: CLT, Berry–Esseen and functional limits · in preparation |
| PLACE (Paper I) | A closed-form persistence-landmark pipeline for certified point-cloud and graph classification · arXiv:2605.02836 · TMLR, under review |
| PALACE (Paper II) | Adaptive landmark embeddings for persistence diagrams · arXiv:2605.04046 · JMLR, under review |
CASTLE is the practitioner-facing product; the others are the machinery that makes its guarantees possible.
Contributing
Contributions are welcome, including — especially — from maintainers of the projects we build on. If you maintain a TDA library and something here does not interoperate cleanly with yours, that is a bug and we would like to hear about it.
Please read CONTRIBUTING.md and CODE_OF_CONDUCT.md. Security reports go to SECURITY.md.
Team
- Sushovan Majhi — Data Science, GW · lead, library architecture
- Pramita Bagchi — biostatistics · practitioner statistics
- Atish Mitra — Mathematics, Montana Tech · theoretical foundations
- Žiga Virk — Mathematics, Ljubljana · theory advisor
- Alexander Silberman — GW · library development
- Edward Bae — GW · library development
Built on GUDHI (INRIA), Ripser, Hera and persim, and on the landmark embedding of Mitra & Virk (2024). With thanks to the wider TDA community, including scikit-tda, giotto-tda and the R tdaverse.
Licence
Apache-2.0 — see LICENSE. The explicit patent grant is deliberate: it is what makes the library usable inside institutions whose legal review would otherwise block adoption.
Contact
Metadata
Release files for akriti 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| akriti-0.2.0.tar.gz | 401.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| akriti-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 489.0 kB
Release files / akriti-0.2.0.tar.gz
| Download URL | akriti-0.2.0.tar.gz |
|---|---|
| Size | 401.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e515d798821c00850cd3056cab274186c3aa4eed05b5c38e9382542960ff1993
|
|
BLAKE2b-256 checksum How to use checksums |
b93bba5b2c6b10743c5b3303d06021823fff109c2cb3116cf7910cb0439604bc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.2
|
Release files / akriti-0.2.0-py3-none-any.whl
| Download URL | akriti-0.2.0-py3-none-any.whl |
|---|---|
| Size | 87.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fb06302462fe61acf2594117fcda7c8b43994241016249c62c11242049c3f53f
|
|
BLAKE2b-256 checksum How to use checksums |
5fa38e0bb38544be777bc01dc82e8b3ce780e11e459ac80a5eb394e8a12021d1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.2
|
Security for akriti 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.