The Rust core¶
Sylva's computations live in the Rust core (crates/sylva-rs); the Python
package (crates/sylva-py + python/sylva) is a thin layer over it. An R
package on the same core, with the same functions under the same names and
tests that check R against Python outputs, is kept on the r-package
branch.
Design¶
- The core owns the logic. Anything numerical, any decision (accept a
pair, merge two stems), any file format and any orchestration (the
coregistration pipeline, RiSCAN project parsing, mesh writers) lives in
sylva-rs, so that any language binding gets it unchanged. - Bindings convert, the language layer presents.
sylva-pyonly converts arguments and results.python/sylvakeeps Python's idiom (dataclasses and NumPy arrays), the docstrings and argument checking. - Containers stay data. Result objects such as
GapProfile,SurveyResultorQSMare plain containers of arrays; their methods call stateless core functions with those arrays, and they pickle. - Per-language only: the command-line interface (Python, and the
sylvabinary) and the progress bar.
Changing or adding a computation¶
- Record.
tests/parity/cases_<module>.pybuilds fixed inputs from seeded NumPy generators and returns the outputs;python tests/parity/capture.py <module>records them from the current code. - Change. Implement in
sylva-rswith Rust unit tests and call it from Python through_core, keeping the Python signature and docstring. - Check.
tests/test_parity.py(tolerance 1e-9 relative) and the full Python suite must pass unchanged. A recording is regenerated only for a documented, intended change of behaviour, in its own commit. The recordings belong to the machine that made them: another CPU or C library shifts the last digits, and the coregistration's accept/reject decisions can follow, so the release workflow runs every test except these.
sylva_rs::numeric holds NumPy-exact helpers (histograms, quantiles,
arange, gradient, pairwise sums), and sylva_rs::util::nprandom reproduces
NumPy's default_rng streams (uniform, ziggurat normal and integer draws,
choice), so ported code can match what NumPy gave to the bit.