Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AUTHORS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# PyEQSP: Python Equal Area Sphere Partitioning Library

**Release 1.0b2** (2026-06-07): Copyright 2026 Paul Leopardi
**Release 1.0b3** (2026-08-30): Copyright 2026 Paul Leopardi

# Authors and Acknowledgements

Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.0b3] - 2026-08-30
**Git Tag**: `release_1_0b3` | **Distribution**: `PyPI / GitHub`

### Added
- **PyVista Visualization Backend**: Transitioned 3D visualization subsystem from MayaVi to PyVista (`pyvista`), providing cross-platform rendering stability (Wayland / Fedora Asahi Remix) and alignment with PyClical and GluCat.
- **Off-Screen Rendering Support**: Enabled `off_screen=True` execution for headless CI environments, Sphinx doc generation, and unit testing.

### Changed
- **Metadata Synchronization**: Bumped project version to `1.0b3`.
- **Dependency Removal**: Completely removed MayaVi (`mayavi`) and PyQt5 optional dependencies in favor of PyVista (`pyvista`).
- **Test Suite Modernization**: Refactored `tests/src/test_visualizations_mock.py` and `tests/run_coverage.py` to mock and verify PyVista off-screen plotting, preserving 100.00% test coverage.

## [1.0b2] - 2026-06-07
**Git Tag**: `release_1_0b2` | **Distribution**: `PyPI / GitHub`

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Contributing to PyEQSP

**Release 1.0b2** (2026-06-07): Copyright 2026 Paul Leopardi
**Release 1.0b3** (2026-08-30): Copyright 2026 Paul Leopardi

Thank you for helping us refine the Recursive Zonal Equal Area Sphere Partitioning (**PyEQSP**) library! This project is currently in Beta testing, and your feedback is invaluable.

Expand Down
11 changes: 5 additions & 6 deletions INSTALL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# PyEQSP: Python Equal Area Sphere Partitioning Library

**Release 1.0b2** (2026-06-07): Copyright 2026 Paul Leopardi
**Release 1.0b3** (2026-08-30): Copyright 2026 Paul Leopardi

# Installation

Expand All @@ -16,8 +16,7 @@ The package depends on:
- `numpy`
- `scipy`
- `matplotlib`
- `mayavi` (optional)
- `PyQt5` (optional)
- `pyvista` (optional)

Installing **PyEQSP** via `pip` automatically installs these dependencies.

Expand All @@ -36,7 +35,7 @@ python3 -m venv VENV
source VENV/bin/activate
```

If you need to use system-installed packages such as Mayavi, create
If you need to use system-installed packages such as PyVista, create
the environment with the `--system-site-packages` flag instead:

```bash
Expand Down Expand Up @@ -72,9 +71,9 @@ To install the package:
pip install .
```

To install with Mayavi support:
To install with PyVista support:
```bash
pip install ".[mayavi]"
pip install ".[pyvista]"
```

### Step 3: Install in Editable Mode (For Developers)
Expand Down
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# PyEQSP: Python Equal Area Sphere Partitioning Library

**Release 1.0b2** (2026-06-07): Copyright 2026 Paul Leopardi
**Release 1.0b3** (2026-08-30): Copyright 2026 Paul Leopardi

PyEQSP is a Python library that implements the **Recursive Zonal Equal Area (EQ) Sphere Partitioning** algorithm, originally developed as a Matlab toolbox by Paul Leopardi.

An **EQ partition** divides Sᵈ (the unit sphere in ℝ<sup>d+1</sup>) into a finite number of regions of equal area. Area measurement uses the Lebesgue measure inherited from the surrounding space.

> **Naming Distinction**: While the project and GitHub repository share the name **PyEQSP** (or **pyeqsp** on PyPI), you import the package as **eqsp**.

Release **1.0b2** achieves **100% project-wide coverage** for both the core library and the entire maintenance ecosystem.
Release **1.0b3** achieves **100% project-wide coverage** for both the core library and the entire maintenance ecosystem.

The **diameter** of a region is the maximum distance between any two of its points (formally the supremum of the Euclidean distance). EQ partitions produce regions with small diameter; specifically, there exists a constant C(d) such that the greatest diameter for an N-region partition of Sᵈ is bounded by C(d)·N<sup>-1/d</sup>.

Expand Down Expand Up @@ -97,7 +97,7 @@ energy, min_dist = eq_energy_dist(dim, [N], s)
```

### Step 3: Produce Illustrations
PyEQSP provides both Matplotlib-based 2D projections and interactive 3D renderings via Mayavi:
PyEQSP provides both Matplotlib-based 2D projections and interactive 3D renderings via PyVista:

#### 2D Illustrations (Matplotlib)

Expand All @@ -122,7 +122,7 @@ illustrate_eq_algorithm(3, 10)
plt.show()
```

#### 3D Visualizations (Mayavi)
#### 3D Visualizations (PyVista)

Display a 3D rendering of the EQ partition of S² into N
regions:
Expand All @@ -131,7 +131,7 @@ regions:
from eqsp.visualizations import show_s2_partition

show_s2_partition(10)
# Opens a native Mayavi GUI window.
# Opens an interactive PyVista rendering window.
```

Display a 3D stereographic projection of the EQ partition of
Expand Down Expand Up @@ -185,9 +185,9 @@ large `N`, the functions may be slow or memory-intensive.
- `illustrations.illustrate_eq_algorithm(dim, N)`:
Step-by-step visualization (Matplotlib).
- `visualizations.show_s2_partition(N)`:
3D plot of S² partition (Mayavi).
3D plot of S² partition (PyVista).
- `visualizations.project_s3_partition(N, proj=...)`:
3D projection of S³ partition (Mayavi).
3D projection of S³ partition (PyVista).

See the docstrings for more details (e.g.
`help(eqsp.visualizations.show_s2_partition)`).
Expand All @@ -203,7 +203,7 @@ See the docstrings for more details (e.g.
- `eqsp.region_props`: Properties of regions
(diameter, vertex max dist).
- `eqsp.illustrations`: 2D visualizations (Matplotlib).
- `eqsp.visualizations`: 3D visualizations (Mayavi).
- `eqsp.visualizations`: 3D visualizations (PyVista).

## Reporting Bugs & Contributing

Expand Down
18 changes: 8 additions & 10 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,16 @@
from unittest.mock import MagicMock

# Mock optional dependencies for headless doctest environments.
# We catch all exceptions because some libraries (like mayavi/vtk) may be
# We catch all exceptions because some libraries (like pyvista/vtk) may be
# installed but fail to initialize in headless CI runners.
try:
import mayavi # noqa: F401
import PyQt5 # noqa: F401
import pyvista # noqa: F401

pyvista.OFF_SCREEN = True
except Exception:
mock_mayavi = MagicMock()
sys.modules["mayavi"] = mock_mayavi
sys.modules["mayavi.mlab"] = mock_mayavi
sys.modules["PyQt5"] = MagicMock()
sys.modules["PyQt5.QtWidgets"] = MagicMock()
sys.modules["PyQt5.QtCore"] = MagicMock()
mock_pyvista = MagicMock()
mock_pyvista.OFF_SCREEN = True
sys.modules["pyvista"] = mock_pyvista
Comment thread
penguian marked this conversation as resolved.

from importlib.metadata import PackageNotFoundError
from importlib.metadata import version as _pkg_version
Expand Down Expand Up @@ -109,7 +107,7 @@
]
myst_heading_anchors = 3

autodoc_mock_imports = ["mayavi", "mayavi.mlab", "PyQt5"]
autodoc_mock_imports = ["pyvista"]

templates_path = ["_templates"]
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
Expand Down
10 changes: 5 additions & 5 deletions doc/maintainer/design_and_architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ The library is organized to separate performance-critical mathematics logic from
### Public API (`eqsp.*`)
- **`partitions.py`**: The core of the EQ algorithm. Contains `eq_regions` and `eq_point_set`.
- **`point_set_props.py`**: Modules for measuring distance, energy, and density.
- **`visualizations.py`**: High-level wrappers for Matplotlib and Mayavi.
- **`visualizations.py`**: High-level wrappers for Matplotlib and PyVista.
- **`utilities.py`**: Coordinate system transformations.

```{mermaid}
Expand Down Expand Up @@ -38,20 +38,20 @@ Modules prefixed with an underscore are intended for internal use and may change

PyEQSP uses a "composite" visualization strategy:
1. **Matplotlib** is used for 2D projections and publishing-quality PDF/EPS output.
2. **Mayavi/VTK** is used for real-time 3D interaction.
2. **PyVista** is used for real-time 3D interaction and off-screen rendering.
The `visualizations` module acts as a bridge, choosing the best backend for the requested manifold ($S^2$ vs $S^3$).

```{mermaid}
graph LR
User([User Call]) --> V[visualizations.py]

V -->|Manifold = S^2, 2D| MAT[Matplotlib]
V -->|Manifold = S^2, 3D| MAY[Mayavi/VTK]
V -->|Manifold = S^3| MAY
V -->|Manifold = S^2, 3D| PV[PyVista]
V -->|Manifold = S^3| PV

subgraph Backends ["Plotting Engines"]
MAT
MAY
PV
end

style User fill:#d4edda,stroke:#28a745
Expand Down
2 changes: 1 addition & 1 deletion doc/maintainer/documentation_maintenance.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ To ensure stability across CI/CD and diverse local environments, these scripts a
## Guide Lifecycle

- **Volume 1 (User)**: Should be updated whenever a new public feature or visualization method is added.
- **Volume 2 (Maintenance)**: Should be updated when internal architecture changes (e.g., transitioning from Mayavi to a new 3D engine) or when benchmarks are re-run.
- **Volume 2 (Maintenance)**: Should be updated when internal architecture changes (e.g., transitioning 3D rendering engines) or when benchmarks are re-run.

### Automated SourceForge Upload
The project includes a utility script to automate the Sphinx build and print the exact transfer command for the SourceForge mirror:
Expand Down
19 changes: 19 additions & 0 deletions doc/maintainer/release_notes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
# Appendix G: Historical Release Notes

## 1.0b3
**2026-08-30**

Release **1.0b3** completes the migration of the PyEQSP 3D visualization subsystem from MayaVi to PyVista (`pyvista`), resolving cross-platform GUI and Wayland/Fedora Asahi Remix compatibility issues and aligning visualization infrastructure with PyClical and GluCat.

### Key Changes
- **PyVista 3D Visualization Backend**: Replaced MayaVi with PyVista in `eqsp/visualizations.py`, offering clean cross-platform rendering for $S^2$ and $S^3$ partitions.
- **Off-Screen Rendering Support**: Configured headless off-screen plotting (`off_screen=True`) to support automated unit testing, Sphinx doc generation, and CI environments.
- **Zero Backwards Compatibility**: Completely removed legacy `mayavi` and `PyQt5` optional dependencies across installation configuration (`pyproject.toml`, `INSTALL.md`, `README.md`) and scripts.
- **Metadata Sync**: Bumped project version to `1.0b3` and synchronized version counters across all documentation and project headers.

### Release Metadata
- **Version**: 1.0b3
- **Tag**: `release_1_0b3`
- **Distribution**: PyPI / GitHub
- **Verification**: [PASSED] 100% Project-wide Coverage, 0 Ruff errors, 0 Sphinx warnings.

---

## 1.0b2
**2026-06-07**

Expand Down
8 changes: 8 additions & 0 deletions doc/maintainer/release_roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,14 @@ This roadmap outlines the development phases from the initial beta through the 1
- [x] **Maintenance Guide Expansion**: Formalize the "Technical Rationale" for the Defense in Depth strategy, detailing the local/remote distinction for Git hooks and security implications.
- [x] **Accumulating Changes**: Track community feedback and bug fixes for the next beta release.

### 1.0b3 Open Beta: PyVista Visualization Backend
**Target: 2026-08-30** | **Git Tag: release_1_0b3** | **Distribution: PyPI / GitHub**

- [x] **PyVista Backend Migration**: Replaced MayaVi with PyVista (`pyvista`) for 3D sphere partition rendering and stereographic projections.
- [x] **Off-Screen Rendering**: Configured PyVista off-screen rendering for headless CI environments, doctests, and Sphinx builds.
- [x] **Zero Backwards Compatibility**: Completely removed legacy MayaVi and PyQt5 dependencies across configuration and build scripts.
- [x] **Metadata Sync**: Bumped project version to `1.0b3` and synchronized version counters across all documentation and project headers.

### 1.0 General Release [PLANNED]

- [ ] **User Feedback Audit**: Address final community feedback from the beta cycle.
Expand Down
2 changes: 1 addition & 1 deletion doc/maintainer/technical_symmetry.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ PyEQSP's recursive partitioning uses a `_private` cache for $S^{d-1}$ partitions
To maintain polymorphic compatibility, all property functions must accept `even_collars`, even if the property (like total area error) is parity-invariant. This ensures call-site stability for users while allowing internal mathematics to exploit symmetry when available.
For foundational citations, see the Volume 2 [References](references_vol2.md).

## Audit Summary (PyEQSP 1.0b2 Beta)
## Audit Summary (PyEQSP 1.0b3 Beta)

- **Derivation Alignment**: The `even_collars` algebraic derivation structurally mirrors the runtime calculation in `eq_caps()` (`eqsp/partitions.py`).
- **Cache Integrity**: The $n_{\text{collars}}/2$ cache boundary correctly mirrors collar $k$ to $n_{\text{collars}} - k + 1$ ensuring 100% cache utilization for $S^3$ southern hemisphere regions.
Expand Down
4 changes: 2 additions & 2 deletions doc/maintainer/testing_details.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The `eqsp` package uses a **Hybrid Testing Approach** that integrates standard u
* Verify core mathematical logic using static assertions.
* Compare results against known-good values from the original MATLAB implementation.
2. **Mock Tests (`tests/src/*_mock.py`)**:
* Verify library interaction (e.g., Mayavi/Matplotlib) without needing a display.
* Verify library interaction (e.g., PyVista/Matplotlib) without needing a display.
* Check if the correct arguments are passed to the plotting engines.
3. **Extra Tests (`tests/src/*_extra.py`)**:
* Introspective integration tests.
Expand Down Expand Up @@ -76,7 +76,7 @@ cd examples/phd-thesis
# Run a numerical plot (Agg backend, saves PNG)
python3 fig_4_2_min_dist_s2.py --upper-bound 5000

> **Note:** The virtual environment configuration (`VENV`) used for automated and manual testing was specific to a standardized Linux build (e.g. Kubuntu 25.10). For full 3D functionality, ensure that your environment has **Mayavi** and its dependencies installed.
> **Note:** The virtual environment configuration (`VENV`) used for automated and manual testing was specific to a standardized Linux build (e.g. Kubuntu 25.10). For full 3D functionality, ensure that your environment has **PyVista** and its dependencies installed.

For instructions on running these scripts and a full mapping of scripts to thesis figures, see [Thesis Research Reproduction](../user/phd-thesis-examples.md).

Expand Down
41 changes: 12 additions & 29 deletions doc/user/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,51 +34,34 @@ pip install --pre pyeqsp
```

(venv-sys-setup)=
## 3D Plotting & System-Integrated Setup (venv_sys)
## 3D Plotting & Visualizations Setup

While 2D illustrations work with standard Matplotlib, **3D interactive visualizations** require **Mayavi**. Heavy mathematical and visualization libraries like **Mayavi**, **VTK**, and **PyQt5** can be difficult to compile from source via `pip`.
While 2D illustrations work with standard Matplotlib, **3D interactive visualizations** require **PyVista**.

For these features, we recommend the `venv_sys` approach, which leverages pre-compiled binaries provided by your OS package manager (e.g., `apt`).

### 1. Install System Dependencies (Ubuntu/Debian)

```bash
sudo apt update
sudo apt install python3-venv python3-mayavi python3-numpy python3-scipy python3-matplotlib
```

### 2. Create and Activate
### 1. Install PyVista

```bash
python3 -m venv --system-site-packages .venvs/.venv_sys
source .venvs/.venv_sys/bin/activate
pip install --pre "pyeqsp[pyvista]"
```

### 3. Display Calibration (Kubuntu/Linux)
### 2. Display Calibration & Off-Screen Rendering

For environments using KDE/Plasma or specific Qt versions, you may need to export these variables to ensure Mayavi initializes correctly:
PyVista supports both interactive GUI windows and headless off-screen rendering for CI environments or Jupyter notebooks:

```bash
export QT_API="pyqt5"
export QT_QPA_PLATFORM="xcb"
export PYVISTA_OFF_SCREEN=true
```

:::{important}
This specific calibration was validated on **Kubuntu Linux 25.10**. Other distributions may require `offscreen` backends for CI or different `QT_API` targets.
:::

## Jupyter Notebook Integration

To use 3D features in Jupyter, you must register `venv_sys` as a kernel:
PyVista integrates with Jupyter Notebooks for interactive 3D rendering:

```bash
pip install ipykernel ipyevents
python3 -m ipykernel install --user --name=venv_sys --display-name "Python (venv_sys)"
pip install trame ipywidgets
```

## Troubleshooting

If Mayavi fails to open a window:
1. Verify `echo $DISPLAY` is set.
2. Check if `QT_QPA_PLATFORM` matches your display server (X11 vs. Wayland).
3. Try running `python3 tests/src/inspect_visualizations.py` to check for specific VTK error messages.
If PyVista fails to open a window:
1. Verify `echo $DISPLAY` is set (or set `export PYVISTA_OFF_SCREEN=true` for headless environments).
2. Try running `python3 tests/src/inspect_visualizations.py` to verify PyVista rendering.
8 changes: 4 additions & 4 deletions doc/user/migration_matlab.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ Most core functions keep their names. The main differences are in coordinate con
| `project_s2_partition` | `illustrations.project_s2_partition` | Matplotlib, 2D projection. |
| `project_point_set` | `illustrations.project_point_set` | Matplotlib, 2D projection. |
| **3D Visualizations** | | |
| `plot_s2_partition` | `visualizations.show_s2_partition` | Mayavi (optional). |
| `project_s3_partition` | `visualizations.project_s3_partition` | Mayavi (optional). |
| `plot_s2_partition` | `visualizations.show_s2_partition` | PyVista (optional). |
| `project_s3_partition` | `visualizations.project_s3_partition` | PyVista (optional). |

> **Note:** Internal-only utilities from the original MATLAB code (like `fatcurve`) are not exposed in the public Python API.

Expand Down Expand Up @@ -114,7 +114,7 @@ MATLAB and NumPy differ in their default memory layout (Column-major vs Row-majo
The Python port uses two separate modules for plotting, unlike the single MATLAB illustration module:

* **`eqsp.illustrations`** (Matplotlib, always available): Handles 2D projections (`project_s2_partition`) and algorithm step diagrams (`illustrate_eq_algorithm`).
* **`eqsp.visualizations`** (Mayavi, optional): Handles all 3D interactive rendering — `show_s2_partition`, `project_s3_partition`, `show_r3_point_set`, etc. Requires Mayavi.
* **`eqsp.visualizations`** (PyVista, optional): Handles all 3D interactive rendering — `show_s2_partition`, `project_s3_partition`, `show_r3_point_set`, etc. Requires PyVista.

### Documentation Philosophy: Two Volumes
Starting with 0.99.4, the documentation is divided into a **User Guide (Volume 1)** for researchers and a **Maintenance Guide (Volume 2)** for developers. This ensures that technical implementation details (like CI setup or release procedures) do not clutter the practical usage guides.
Expand All @@ -128,7 +128,7 @@ The package is organized into logical modules:
* `eqsp.point_set_props`: Properties of point sets (energy, distance).
* `eqsp.histograms`: Point-in-region lookup and counting for S^2.
* `eqsp.illustrations`: 2D Matplotlib plotting and algorithm diagrams.
* `eqsp.visualizations`: 3D Mayavi visualizations (optional dependency).
* `eqsp.visualizations`: 3D PyVista visualizations (optional dependency).



Expand Down
Loading
Loading