geopyv-dev 0.1.15__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/.readthedocs.yaml +1 -1
- geopyv_dev-0.2.0/CLAUDE.md +134 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/Cargo.lock +3 -3
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/Cargo.toml +1 -1
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/PKG-INFO +1 -1
- geopyv_dev-0.2.0/geopyv_dev/__init__.py +794 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/geopyv_dev/plots.py +296 -29
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/geopyv_dev/wrappers.py +2 -1
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/pyproject.toml +1 -1
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/python/Cargo.toml +1 -1
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/python/src/py_field.rs +13 -17
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/python/src/py_image.rs +18 -1
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/python/src/py_mask.rs +12 -4
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/python/src/py_mesh.rs +425 -6
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/python/src/py_particle.rs +212 -4
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/python/src/py_sequence.rs +78 -6
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/python/src/py_speckle.rs +41 -5
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/python/src/py_subset.rs +33 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/src/field.rs +209 -26
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/src/geometry/mod.rs +1 -0
- geopyv_dev-0.2.0/src/geometry/rasterize.rs +674 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/src/image.rs +60 -40
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/src/io.rs +636 -17
- geopyv_dev-0.2.0/src/masks.rs +573 -0
- geopyv_dev-0.2.0/src/mesh.rs +3574 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/src/particle.rs +982 -20
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/src/sequence.rs +35 -1
- geopyv_dev-0.2.0/src/speckle.rs +1523 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/src/subset.rs +650 -72
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/src/validation.rs +5 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/tests/python/image/test_image.py +44 -37
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/tests/python/io/test_io.py +2 -1
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/tests/python/plots/test_plots.py +346 -1
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/tests/python/sequence/test_sequence.py +191 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/tests/python/subset/test_subset.py +113 -16
- geopyv_dev-0.1.15/geopyv_dev/__init__.py +0 -409
- geopyv_dev-0.1.15/src/masks.rs +0 -301
- geopyv_dev-0.1.15/src/mesh.rs +0 -1714
- geopyv_dev-0.1.15/src/speckle.rs +0 -696
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/.github/workflows/release.yml +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/.gitignore +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/LICENSE +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/Makefile +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/README.md +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/basictest.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/_static/gifs/intro_hero.gif +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/_static/gifs/quad_deformation.gif +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/_static/gifs/region_motion.gif +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/_static/gifs/sequence_distortion.gif +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/_static/gifs/subset_shape_order.gif +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/_static/img/c2_subset.png +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/_static/img/combined_25_standard_error.png +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/_static/img/mask_local_vs_global.png +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/_static/img/mesh_solve_flow.png +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/_static/img/sequence_solve_flow.png +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/_static/img/subset_quality.png +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/api/index.rst +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/conf.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/index.rst +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/installation.rst +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/requirements-docs.txt +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/scripts/build_images_assets.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/scripts/build_intro_gif.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/scripts/build_mesh_flow.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/scripts/build_region_motion_gif.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/scripts/build_sequence_distortion_gif.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/scripts/build_sequence_flow.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/scripts/build_subset_assets.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/scripts/common.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/tutorials/00_introduction.rst +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/tutorials/01_images_and_masks.rst +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/tutorials/02_subset.rst +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/tutorials/03_mesh.rst +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/tutorials/04_sequence.rst +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/tutorials/05_particle.rst +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/tutorials/06_field.rst +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/tutorials/07_validation.rst +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/tutorials/08_calibration.rst +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/docs/tutorials/index.rst +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/geopyv-dev-tutorials/00_introduction.ipynb +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/geopyv-dev-tutorials/01_images_and_masks.ipynb +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/geopyv-dev-tutorials/02_subset.ipynb +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/geopyv-dev-tutorials/03_mesh.ipynb +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/geopyv-dev-tutorials/04_sequence.ipynb +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/geopyv-dev-tutorials/05_particle_and_field.ipynb +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/geopyv-dev-tutorials/data/sequence/seq_0.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/geopyv-dev-tutorials/data/sequence/seq_1.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/geopyv-dev-tutorials/data/sequence/seq_2.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/geopyv-dev-tutorials/data/sequence/seq_3.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/geopyv-dev-tutorials/data/sequence/seq_4.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/geopyv-dev-tutorials/data/single/intro_0.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/geopyv-dev-tutorials/data/single/intro_1.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/geopyv_dev/calibration.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/SB/SB_0.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/SB/SB_1.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/SB/SB_2.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/SB/SB_3.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/SB/SB_4.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/SB/SB_5.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/SB/speckle_SB.pyv +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/comp/compression_0.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/comp/compression_1.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/comp/compression_10.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/comp/compression_2.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/comp/compression_3.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/comp/compression_4.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/comp/compression_5.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/comp/compression_6.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/comp/compression_7.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/comp/compression_8.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/comp/compression_9.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/quality/quality_speckle.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/shear/shear_0.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/shear/shear_1.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/shear/shear_2.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/shear/shear_3.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/shear/shear_4.jpg +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/images/shear/speckle_shear.pyv +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/python/geopyv-dev/__init__.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/python/src/lib.rs +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/python/src/py_calibration.rs +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/python/src/py_geometry.rs +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/python/src/py_io.rs +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/python/src/py_validation.rs +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/python/src/utils.rs +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/src/calibration.rs +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/src/error.rs +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/src/geometry/meshing.rs +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/src/geometry/region.rs +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/src/geometry/triangulation.rs +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/src/geometry/utilities.rs +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/src/lib.rs +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/tests/python/calibration/test_calibration.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/tests/python/field/test_field.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/tests/python/geometry/test_geometry.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/tests/python/mesh/test_mesh.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/tests/python/particle/test_particle.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/tests/python/plots/__init__.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/tests/python/plots/conftest.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/tests/python/templates/test_templates.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/tests/python/validation/test_validation.py +0 -0
- {geopyv_dev-0.1.15 → geopyv_dev-0.2.0}/tests/python/validation/test_validation_solve.py +0 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
### Build & develop
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Build the Rust core library only
|
|
11
|
+
cargo build
|
|
12
|
+
|
|
13
|
+
# Build the Python extension (debug)
|
|
14
|
+
cargo build -p geopyv-dev-python
|
|
15
|
+
|
|
16
|
+
# Build and install the Python package into the venv (required after any Rust change)
|
|
17
|
+
source .venv/bin/activate
|
|
18
|
+
maturin develop --manifest-path python/Cargo.toml
|
|
19
|
+
|
|
20
|
+
# Run all Rust unit tests
|
|
21
|
+
cargo test
|
|
22
|
+
|
|
23
|
+
# Run a single Rust test by name
|
|
24
|
+
cargo test test_solve_icgn_order1_golden
|
|
25
|
+
|
|
26
|
+
# Run Python tests
|
|
27
|
+
source .venv/bin/activate
|
|
28
|
+
pytest tests/python/
|
|
29
|
+
|
|
30
|
+
# Run a single Python test file
|
|
31
|
+
pytest tests/python/mesh/test_mesh.py
|
|
32
|
+
|
|
33
|
+
# Run the integration smoke-test (requires images/ directory)
|
|
34
|
+
source .venv/bin/activate && python basictest.py
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Build the GUI (separate binary crate)
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
cargo build -p geopyv-gui
|
|
41
|
+
cargo run -p geopyv-gui
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Publishing a release to PyPI
|
|
45
|
+
|
|
46
|
+
The `.github/workflows/release.yml` workflow triggers **only on version tags** — pushing a branch does nothing. Steps:
|
|
47
|
+
|
|
48
|
+
1. Update the version string in all three places (they must match):
|
|
49
|
+
- `Cargo.toml` (workspace root) — `version = "x.y.z"`
|
|
50
|
+
- `pyproject.toml` — `version = "x.y.z"`
|
|
51
|
+
- `python/Cargo.toml` — `version = "x.y.z"`
|
|
52
|
+
|
|
53
|
+
2. Commit the version bump and push the branch:
|
|
54
|
+
```bash
|
|
55
|
+
git add Cargo.toml pyproject.toml python/Cargo.toml
|
|
56
|
+
git commit -m "Bump version to x.y.z"
|
|
57
|
+
git push origin <branch>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
3. Create and push the version tag:
|
|
61
|
+
```bash
|
|
62
|
+
git tag vx.y.z
|
|
63
|
+
git push origin vx.y.z
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The tag push triggers the workflow: it builds manylinux + aarch64 + Windows wheels and an sdist, then publishes everything to PyPI via trusted publishing (no API token needed).
|
|
67
|
+
|
|
68
|
+
## Architecture
|
|
69
|
+
|
|
70
|
+
### Three-crate workspace
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
geopyv-dev/ ← workspace root
|
|
74
|
+
src/ ← Rust core library (crate: geopyv-dev)
|
|
75
|
+
python/src/ ← PyO3 extension (crate: geopyv-dev-python → _geopyv_dev.so)
|
|
76
|
+
geopyv-gui/src/ ← egui desktop app (crate: geopyv-gui)
|
|
77
|
+
geopyv_dev/ ← Python package (imports .so + adds wrappers/plots)
|
|
78
|
+
tests/python/ ← pytest suite for the Python API
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The Python package that users import (`geopyv_dev`) is **not** the `.so` directly. It lives in `geopyv_dev/` and consists of:
|
|
82
|
+
- `__init__.py` — re-exports `_geopyv_dev.*`, then shadows the raw Rust classes (`Subset`, `Mesh`, `Sequence`, `Field`, `Particle`) with thin Python wrappers that add `.solve()`, `.inspect()`, `.convergence()`, `.contour()`.
|
|
83
|
+
- `wrappers.py` — `MeshWrapper`, `SequenceSolutionWrapper`, `FieldWrapper`, `ParticleWrapper`, `SubsetWrapper` — returned by `.solve()` on the wrapper classes.
|
|
84
|
+
- `plots.py` — all matplotlib visualisation functions.
|
|
85
|
+
- `_geopyv_dev.cpython-*.so` — the compiled Rust extension.
|
|
86
|
+
|
|
87
|
+
The installed `.so` is also shadowed: `maturin` writes to `geopyv_dev/_geopyv_dev.so` directly, which means `maturin develop` + the existing `geopyv_dev/` package are the runtime. There is a `python/geopyv-dev/` stub that is only used during the maturin build and can be ignored.
|
|
88
|
+
|
|
89
|
+
### Rust core → PyO3 boundary
|
|
90
|
+
|
|
91
|
+
Each domain module in `src/` has a corresponding `python/src/py_*.rs` wrapper:
|
|
92
|
+
|
|
93
|
+
| Core (`src/`) | Wrapper (`python/src/`) | Python class |
|
|
94
|
+
|---|---|---|
|
|
95
|
+
| `image.rs` | `py_image.rs` | `Image` |
|
|
96
|
+
| `templates.rs` | `py_templates.rs` | `Template` |
|
|
97
|
+
| `geometry/` | `py_geometry.rs` | `CircleRegion`, `PathRegion`, free fns |
|
|
98
|
+
| `subset.rs` | `py_subset.rs` | `Subset` |
|
|
99
|
+
| `mesh.rs` | `py_mesh.rs` | `Mesh`, `MeshSolution` |
|
|
100
|
+
| `sequence.rs` | `py_sequence.rs` | `Sequence`, `SequenceSolution` |
|
|
101
|
+
| `particle.rs` | `py_particle.rs` | `Particle`, `ParticleSolution` |
|
|
102
|
+
| `field.rs` | `py_field.rs` | `Field`, `FieldSolution` |
|
|
103
|
+
| `io.rs` | `py_io.rs` | `save`, `load` |
|
|
104
|
+
| `validation.rs` | `py_validation.rs` | free validation fns |
|
|
105
|
+
|
|
106
|
+
Error bridging: `geopyv_dev::Error` cannot implement `From<PyErr>` directly (orphan rule). The `python/src/lib.rs` newtype `Error(geopyv_dev::Error)` bridges via two `From` impls. Every wrapper method uses `.map_err(Error::from)?`.
|
|
107
|
+
|
|
108
|
+
### Data flow: DIC solve
|
|
109
|
+
|
|
110
|
+
`Image::from_file` → FFT → B-spline coefficients (QCQT matrix, stored on `Image`) → `Subset::new` takes QCQT + template coordinates + centre → computes `f`, `f_m`, `delta_f`, `grad_f` → `solve_icgn` / `solve_fagn` takes target QCQT + initial warp → returns `SolveResult`.
|
|
111
|
+
|
|
112
|
+
At the Python level: `gp.Image(filepath=...)` → `gp.Template(...)` → `gp.Subset(coord, template, f_img)` → `subset.solve(g_img, p_0)`.
|
|
113
|
+
|
|
114
|
+
### Mesh pipeline
|
|
115
|
+
|
|
116
|
+
`Mesh.generate(borders, segments, curves, ...)` calls `spade` (Delaunay/CDT) internally. `borders`/`segments`/`curves` are produced by `define_roi` (in `geometry/meshing.rs` / `py_geometry.rs`), which takes raw boundary nodes and exclusion-region node arrays and computes the constraint topology. `Mesh.solve(f_img, g_img, template, seed_coord, seed_warp)` runs reliability-guided propagation across all nodes, calling `Subset::new` + `solve_icgn/fagn` per node.
|
|
117
|
+
|
|
118
|
+
### Serialisation
|
|
119
|
+
|
|
120
|
+
`.pyv` files: 4-byte magic `GPYV` + 1-byte version `0x01` + bincode-v2 encoded `GeopyvObject` (a serde enum over `MeshSolution`, `FieldSolution`, `SequenceSolution`, `SubsetSolution`, `ParticleSolution`). Incompatible with the Python `geopyv` pickle format.
|
|
121
|
+
|
|
122
|
+
### Coordinate convention
|
|
123
|
+
|
|
124
|
+
`coord[0]` = x (column), `coord[1]` = y (row). `bspline_eval` uses `coords[:,0]` as the column index and `coords[:,1]` as the row index. This matches `_subset.cpp` in the original Python package.
|
|
125
|
+
|
|
126
|
+
### Tolerance tiers (used in test names and comments)
|
|
127
|
+
|
|
128
|
+
- **Tier A** `atol = 1e-12` — pure matrix algebra, no floating-point chains.
|
|
129
|
+
- **Tier B** `rtol = 1e-8` — FFT / B-spline coefficient computation.
|
|
130
|
+
- **Tier C** `rtol = 1e-5` — solver outputs (ZNCC, converged warp).
|
|
131
|
+
|
|
132
|
+
### Original Python package reference
|
|
133
|
+
|
|
134
|
+
The Rust code is a rewrite of `geopyv` (Python). C++ extension functions (`_subset.cpp`, etc.) are the numerical ground-truth. Comments throughout `src/` note which Python/C++ function each Rust function matches (e.g. `// Matches _intensity in _subset.cpp`). Golden test values come from running the Python package on the same inputs. The Python test images live at `geopyv/tests/ref.jpg` and `tar.jpg` relative to `CARGO_MANIFEST_DIR`; integration tests skip gracefully if the files are absent.
|
|
@@ -1531,7 +1531,7 @@ dependencies = [
|
|
|
1531
1531
|
|
|
1532
1532
|
[[package]]
|
|
1533
1533
|
name = "geopyv-dev"
|
|
1534
|
-
version = "0.
|
|
1534
|
+
version = "0.2.0"
|
|
1535
1535
|
dependencies = [
|
|
1536
1536
|
"bincode",
|
|
1537
1537
|
"image",
|
|
@@ -1550,7 +1550,7 @@ dependencies = [
|
|
|
1550
1550
|
|
|
1551
1551
|
[[package]]
|
|
1552
1552
|
name = "geopyv-dev-python"
|
|
1553
|
-
version = "0.
|
|
1553
|
+
version = "0.2.0"
|
|
1554
1554
|
dependencies = [
|
|
1555
1555
|
"geopyv-dev",
|
|
1556
1556
|
"ndarray",
|
|
@@ -1560,7 +1560,7 @@ dependencies = [
|
|
|
1560
1560
|
|
|
1561
1561
|
[[package]]
|
|
1562
1562
|
name = "geopyv-gui"
|
|
1563
|
-
version = "0.
|
|
1563
|
+
version = "0.2.0"
|
|
1564
1564
|
dependencies = [
|
|
1565
1565
|
"dirs",
|
|
1566
1566
|
"eframe",
|