Metadata-Version: 2.2
Name: pyvoro2
Version: 0.4.0
Summary: Python bindings for Voro++ (3D Voronoi and Laguerre tessellations) with periodic and topology utilities.
Author-Email: "Ivan Yu. Chernyshov" <ivan.chernyshoff@gmail.com>
License: MIT License
         
         Copyright (c) 2026 Ivan Yu. Chernyshov
         
         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.
         
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Scientific/Engineering :: Chemistry
Classifier: Topic :: Scientific/Engineering :: Physics
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
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: Programming Language :: C++
Project-URL: Homepage, https://github.com/IvanChernyshov/pyvoro2
Project-URL: Repository, https://github.com/IvanChernyshov/pyvoro2
Project-URL: Issues, https://github.com/IvanChernyshov/pyvoro2/issues
Requires-Python: >=3.10
Requires-Dist: numpy<2,>=1.23; python_version < "3.11"
Requires-Dist: numpy<3,>=1.23; python_version >= "3.11"
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: flake8; extra == "dev"
Requires-Dist: tomli; python_version < "3.11" and extra == "dev"
Provides-Extra: docs
Requires-Dist: mkdocs>=1.6; extra == "docs"
Requires-Dist: mkdocs-material>=9.5; extra == "docs"
Requires-Dist: mkdocstrings[python]>=0.27; extra == "docs"
Requires-Dist: mkdocs-jupyter>=0.25; extra == "docs"
Requires-Dist: pymdown-extensions>=10.0; extra == "docs"
Requires-Dist: mkdocs-section-index>=0.3.9; extra == "docs"
Provides-Extra: viz
Requires-Dist: py3Dmol; extra == "viz"
Description-Content-Type: text/markdown

# pyvoro2

[![CI](https://github.com/IvanChernyshov/pyvoro2/actions/workflows/ci.yml/badge.svg)](https://github.com/IvanChernyshov/pyvoro2/actions/workflows/ci.yml) [![Docs](https://github.com/IvanChernyshov/pyvoro2/actions/workflows/docs.yml/badge.svg)](https://github.com/IvanChernyshov/pyvoro2/actions/workflows/docs.yml) [![PyPI](https://img.shields.io/pypi/v/pyvoro2.svg)](https://pypi.org/project/pyvoro2/) [![Python Versions](https://img.shields.io/pypi/pyversions/pyvoro2.svg)](https://pypi.org/project/pyvoro2/) [![License](https://img.shields.io/pypi/l/pyvoro2.svg)](https://github.com/IvanChernyshov/pyvoro2/blob/main/LICENSE)

**Documentation:** https://IvanChernyshov.github.io/pyvoro2/


---

**pyvoro2** is a Python interface to the C++ library **Voro++** for computing
**3D tessellations** around a set of points:

- **Voronoi tessellations** (standard, unweighted)
- **power / Laguerre tessellations** (weighted Voronoi, via per-site radii)

The focus is not only on computing polyhedra, but on making the results *useful* in
scientific settings that are common in chemistry, materials science, and condensed
matter physics — especially **periodic boundary conditions** and **neighbor graphs**.

pyvoro2 is designed to be **honest and predictable**:

- it vendors and wraps **unmodified** upstream Voro++;
- the core tessellation modes are **standard Voronoi** and **power/Laguerre**.

## Quickstart

### 1) Standard Voronoi in a bounding box

For 3D visualization, install the optional dependency: `pip install "pyvoro2[viz]"`.

```python
import numpy as np
import pyvoro2 as pv
from pyvoro2.viz3d import view_tessellation

points = np.random.default_rng(0).uniform(-1.5, 1.5, size=(10, 3))
box = pv.Box(((-2, 2), (-2, 2), (-2, 2)))
cells = pv.compute(points, domain=box, mode='standard')

view_tessellation(
    cells,
    domain=box,
    show_vertices=False,
)
```

<img src="https://raw.githubusercontent.com/IvanChernyshov/pyvoro2/main/docs/assets/quickstart_box.png" width="50%" alt="Voronoi tessellation in a box" />

### 2) Power/Laguerre tessellation (weighted Voronoi)

```python
radii = np.full(len(points), 1.2)

cells = pv.compute(
    points,
    domain=box,
    mode='power',
    radii=radii,
    include_empty=True,  # power diagrams can have zero-volume cells
)
```

### 3) Periodic crystal cell with neighbor image shifts

```python
cell = pv.PeriodicCell(
    vectors=(
        (10.0, 0.0, 0.0),
        (2.0,  9.0, 0.0),
        (1.0,  0.5, 8.0),
    )
)

cells = pv.compute(points, domain=cell, return_face_shifts=True)

# Each face can include:
#   adjacent_cell  (neighbor id)
#   adjacent_shift (which periodic image produced the face)
```

## Numerical safety notes

Voro++ uses a few fixed absolute tolerances internally (most importantly a hard
near-duplicate check around ~`1e-5` in container distance units). For very small
or very large coordinate systems, this can lead to hard process termination or
loss of accuracy.

pyvoro2 does **not** silently rescale your coordinates. If you work in unusual
units, rescale explicitly before calling into the C++ layer.

As an additional safety net, you can ask pyvoro2 to run a fast Python-side
near-duplicate pre-check before entering the C++ layer:

```python
cells = pv.compute(points, domain=cell, duplicate_check='raise')
```

For stricter post-hoc checks, see:

- `pyvoro2.validate_tessellation(..., level='strict')`
- `pyvoro2.validate_normalized_topology(..., level='strict')`

## Platform note (macOS)

On some macOS builds, fully periodic **power/Laguerre** tessellations can
occasionally produce a non-reciprocal face/neighbor graph. In that case,
requesting `return_face_shifts=True` may raise a `ValueError` because pyvoro2
cannot assign consistent periodic shifts.

Workarounds:

- Avoid requesting shifts (`return_face_shifts=False`), or
- disable shift validation (`validate_face_shifts=False`, shifts may be
  unreliable), or
- run strict periodic power workflows on Linux/Windows.

## Why use pyvoro2

Voro++ is fast and feature-rich, but it is a C++ library with a low-level API.
pyvoro2 aims to be a *scientific* interface that stays close to Voro++ while adding
practical pieces that are easy to get wrong:

- **triclinic periodic cells** (`PeriodicCell`) with robust coordinate mapping
- **partially periodic orthorhombic cells** (`OrthorhombicCell`) for slabs and wires
- optional **per-face periodic image shifts** (`adjacent_shift`) for building periodic graphs
- **diagnostics** and **normalization utilities** for reproducible topology work
- convenience operations beyond full tessellation:
  - `locate(...)` (owner lookup for arbitrary query points)
  - `ghost_cells(...)` (probe cell at a query point without inserting it)
  - inverse fitting utilities for **fitting power weights** from desired pairwise plane locations

## Documentation overview

The documentation is written as a short scientific tutorial: it starts with the
geometric ideas, then explains domains and operations, and only then dives into
implementation-oriented details.

| Section | What it contains |
|---|---|
| [Concepts](https://IvanChernyshov.github.io/pyvoro2/guide/concepts/) | What Voronoi and power/Laguerre tessellations are, and what you can expect from them. |
| [Domains](https://IvanChernyshov.github.io/pyvoro2/guide/domains/) | Which containers exist (`Box`, `OrthorhombicCell`, `PeriodicCell`) and how to choose between them. |
| [Operations](https://IvanChernyshov.github.io/pyvoro2/guide/operations/) | How to compute tessellations, assign query points, and compute probe (ghost) cells. |
| [Topology and graphs](https://IvanChernyshov.github.io/pyvoro2/guide/topology/) | How to build a neighbor graph that respects periodic images, and how normalization helps. |
| [Inverse fitting](https://IvanChernyshov.github.io/pyvoro2/guide/inverse/) | Fit power/Laguerre radii from desired pairwise plane positions (with optional constraints/penalties). |
| [Visualization](https://IvanChernyshov.github.io/pyvoro2/guide/visualization/) | Optional py3Dmol helpers for debugging and exploratory analysis. |
| [Examples (notebooks)](https://IvanChernyshov.github.io/pyvoro2/notebooks/01_basic_compute/) | End-to-end examples that combine the pieces above. |
| [API reference](https://IvanChernyshov.github.io/pyvoro2/reference/api/) | The full reference (docstrings). |

## Installation

Most users should install a prebuilt wheel:

```bash
pip install pyvoro2
```

To build from source (requires a C++ compiler and Python development headers):

```bash
pip install -e .
```

## Testing

pyvoro2 uses **pytest**. The default test suite is intended to be fast and deterministic:

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

Additional test groups are **opt-in**:

- **Fuzz/property tests** (randomized):

  ```bash
  pytest -m fuzz --fuzz-n 100
  ```

- **Cross-check tests vs `pyvoro`** (requires installing `pyvoro` first):

  ```bash
  pip install pyvoro
  pytest -m pyvoro --fuzz-n 100
  ```

- **Slow tests** (if any are added in the future):

  ```bash
  pytest -m slow
  ```

Tip: you can combine markers, e.g. `pytest -m "fuzz and pyvoro" --fuzz-n 100`.

## Project status

pyvoro2 is currently in **beta**.

The core tessellation modes (standard and power/Laguerre) are stable, and a large
part of the work in this repository focuses on tests and documentation.
A future 1.0 release is planned once the inverse-fitting workflow is more mature
and native 2D support is added.

## AI-assisted development

Some parts of the implementation, tests, and documentation were developed with
AI assistance (OpenAI ChatGPT). The maintainer reviews and integrates changes,
and remains responsible for the resulting code and scientific claims.

Details are documented in the [AI usage](https://IvanChernyshov.github.io/pyvoro2/project/ai/) page.

## License

- pyvoro2 is released under the **MIT License**.
- Voro++ is vendored and redistributed under its original license (see the project pages).

---

*This README is auto-generated from the MkDocs sources in `docs/`.*
To update it, edit the docs pages and re-run: `python tools/gen_readme.py`.

