Skip to content

Install

pip install sylva-rs             # Python: import sylva
cargo add sylva-rs               # Rust library: use sylva_rs::...
cargo install sylva-cli          # the sylva command without Python

The wheels on PyPI carry the compiled core for Linux (x86-64 and arm64), macOS (Intel and Apple silicon) and Windows, and serve every Python from 3.10. The distribution is called sylva-rs because an unrelated project owns the name sylva on PyPI; the package you import is sylva, and the two cannot be installed in the same environment.

From source

A conda environment carries the Python, the Rust toolchain and the C linker together, so the core builds with nothing installed system-wide:

conda create -n sylva -c conda-forge python=3.12 rust maturin c-compiler
conda activate sylva
maturin develop --release        # builds the Rust core into the environment

Or from the environment file in the repository, which adds pytest and the notebook extras:

conda env create -f environment.yml
conda activate sylva
maturin develop --release

maturin develop puts an editable install in the active environment: Python changes are picked up at once, Rust changes after re-running it. pip install -e . builds the same way through maturin.

error: linkerccnot found

rustc hands the final link to a program called cc. Conda's rust package does not bring one, so an environment of python rust maturin alone fails at the first crate that has a build script. Adding c-compiler installs gcc under the plain cc name inside the environment, and its activation script sets CC, CFLAGS and LDFLAGS to match. On a machine that already has a system compiler the build works without it, which is why it is easy to miss.

Without conda, any Python >= 3.10 with a Rust toolchain from rustup, a system C compiler (gcc or build-essential on Linux, the Xcode command line tools on macOS) and pip install maturin does the same job, in a virtual environment of your choice.

Reading RIEGL .rxp files needs RiVLib's libscanifc (proprietary; download from RIEGL). Point RIVLIB_PATH at the extracted directory or pass library= to sylva.io.read_rxp. To convert .rxp the way RiSCAN PRO does (MTA resolution and its filters, see the I/O guide), build the small shim once from the same SDK; it needs a C++ compiler:

RIVLIB=/path/to/rivlib-2_6_0-x86_64-linux-gcc11 crates/sylva-rs/rivlib-shim/build.sh

Reading .rdbx databases (RiSCAN PRO's imported scans) likewise needs librdb from RIEGL's RDB SDK: point RDBLIB_PATH at the extracted directory or pass library= to sylva.io.read_rdbx. All of these are loaded at run time; nothing else is affected when they are absent.

Containers

The Dockerfile builds an image with the sylva command and nothing else to install. Run it on the files in the current directory:

docker build -t sylva .
docker run --rm -v "$PWD":/data sylva trees plot_norm.laz

Each push to main also publishes the image to GitHub's container registry as ghcr.io/uq-eorc/sylva (:latest, and :X.Y.Z for releases). It is private like the repository, so docker login ghcr.io with a GitHub token that can read packages first:

docker run --rm -v "$PWD":/data ghcr.io/uq-eorc/sylva trees plot_norm.laz

RIEGL does not allow RiVLib to be redistributed, so it isn't in the image. Mount your own copy at /opt/rivlib to read .rxp:

docker run --rm -v ~/.local/lib/rivlib:/opt/rivlib:ro -v "$PWD":/data sylva coreg survey.PROJ

For development, .devcontainer/ opens the repository in VS Code (or any dev-container tool) with Python, the Rust toolchain and a C compiler. Sylva is installed editable in /opt/venv with the test, lint and docs extras. After a Rust change, run maturin develop --release. Serve the docs with mkdocs serve -a 0.0.0.0:8000.

Two things to know:

  • RiVLib. Uncomment the RiVLib mount in devcontainer.json to read .rxp.
  • Rootless Podman. Add "runArgs": ["--userns=keep-id"] so files keep your ownership.

Podman works in place of Docker for both.