Install rietx#
rietx needs Python 3.11 or newer and installs from PyPI into a virtual environment, one per project.
With uv, which
creates the environment and installs in one tool:
uv venv --python 3.12
uv pip install rietx
source .venv/bin/activate
With pip:
python3 -m venv .venv
source .venv/bin/activate
pip install rietx
On an Apple-silicon Mac, check that the environment’s Python is a native build:
python -c "import platform; print(platform.machine())" prints arm64.
If it prints x86_64, the environment runs under Rosetta and a fit takes 1.6 to 2 times
as long. Name the build when you create it: uv venv --python cpython-3.12-macos-aarch64-none.
With uv, which
creates the environment and installs in one tool:
uv venv --python 3.12
uv pip install rietx
source .venv/bin/activate
With pip:
python3 -m venv .venv
source .venv/bin/activate
pip install rietx
With uv, which
creates the environment and installs in one tool:
uv venv --python 3.12
uv pip install rietx
.venv\Scripts\activate
With pip:
py -m venv .venv
.venv\Scripts\activate
pip install rietx
Check it:
python -c "import rietx; print(rietx.__version__)"
That prints the version you installed, 1.10.0 for the copy this manual was built from. Then run a first fit, in Python or in the GUI.
Requirements#
Requirement |
Purpose |
|---|---|
Python ≥ 3.11 |
|
|
the fp64 arrays the core computes in |
|
the bounded linear solves inside the default driver, and the |
|
the data models: validation, defaults, JSON round-trip |
|
CIF reading, space groups, symmetry operations |
|
site symmetry, Wyckoff positions, cell reduction |
|
the compiled peak kernels, one wheel per platform (The compiled kernels) |
|
figures: |
Those seven are the whole install, and nothing in that list is optional.
Matplotlib is imported only when a figure is drawn, so import rietx does not
load it. The install reads patterns and CIFs, applies every correction, runs
the staged refinement machinery, builds the report, draws the figures, indexes
an unknown cell, and keeps projects and history.
Optional extras#
No extra changes a refined number. Name one in brackets to install it, quoting
the argument because zsh reads bare brackets as a glob:
pip install "rietx[jax]" # one extra
pip install "rietx[jax,docs]" # several, comma-separated, no spaces
uv pip install -e ".[dev]" # from a source checkout
Extra |
Installs |
Purpose |
|---|---|---|
|
nothing |
Empty since 1.7, and kept so an existing |
|
nothing |
Empty, and kept so an existing |
|
|
The |
|
|
Experimental. |
|
|
Builds this manual. |
|
|
Executes notebooks headless: the tutorial builder in |
|
the |
The test suite. |
Note
backend="numpy" is the default and the only backend a refinement needs. The
others hold the analytic Jacobian to an independent account: an Apple-GPU
refinement runs 46 to 182 times slower than numpy, because the work is
launch-latency-bound. Precision is not the trade either way. A GPU backend may
compute Jacobian columns in fp32, but the residual used for the cost and the
statistics, and the solve itself, stay fp64 on the host.
The compiled kernels#
The peak profile, its derivatives and the accumulation that scatters them onto the pattern are evaluated by compiled kernels rather than by numpy expressions. They are on by default and there is nothing to install or select. Measured on a four-phase Cu Kα refinement they take the fit from 17.6 s to 8.9 s; on a three-phase one, from 4.2 s to 2.2 s; on a two-phase synchrotron pattern with no axial divergence, from 0.54 s to 0.40 s.
The kernels are written in Rust and ship as a separate package, rietx-kernels,
which pip installs with rietx. It is one compiled wheel per platform, between
140 and 250 kB: Linux (glibc) on x86_64 and aarch64, macOS on arm64 and x86_64,
and Windows on x64. There is no compile step and no cache. Importing the wheel
is the whole start-up cost. Releases before the kernels became a wheel compiled
them with numba on first use and cached the result in ~/.rietx/numba-cache.
That directory is no longer read, and you can delete it.
The structure figure draws with two more kernels from the same wheel, and the
switch below reaches them too. The dichotomy indexing engine tests its boxes in
the wheel as well, from rietx-kernels 1.3, the oldest wheel rietx accepts. On
a monoclinic search of 161 705 grid boxes the grid took about 4 s of CPU,
against 13.5 s on the numpy loop.
Turn the kernels off with RIETX_COMPILED=0, which needs no reinstall. Every
kernel has the numpy expression it replaces standing behind it, so refinements
and figures run correctly, only slower. Use it for a run that has to reproduce
another one exactly.
RIETX_COMPILED=0 python my_refinement.py
An install without the wheel also runs the numpy path (see Troubleshooting).
It warns once per process, at the first refinement, structure figure,
dichotomy search or capabilities() call:
RuntimeWarning: rietx's compiled kernels did not load, because importing
rietx_kernels raised ModuleNotFoundError (No module named 'rietx_kernels').
Fits, structure figures and indexing run the numpy path, which is slower.
Install the kernels with pip install "rietx-kernels>=1.3,<2", or set
RIETX_COMPILED=0 to choose the numpy path and silence this warning.
The same warning names a wheel of another major version, whose kernel interface this rietx does not call. It also names a wheel older than 1.3, which lacks the dichotomy indexing engine’s kernels.
capabilities() answers the three questions in three fields, because they can
disagree. features["compiled_kernels"] is whether the wheel loaded here.
features["compiled_kernels_active"] is whether the next refinement, figure
or indexing search will use it. Capabilities.compiled_kernels_unavailable is the reason the wheel did not
load, or None when it did.
from rietx import capabilities
caps = capabilities()
caps.features["compiled_kernels"]
caps.features["compiled_kernels_active"]
caps.compiled_kernels_unavailable
The accumulation is bit-for-bit identical on both paths, being multiplication
and addition in a fixed order with no library function in it. The peak shapes
call exp, whose last bit belongs to whichever library provides it, so they
land on the same doubles on some platforms and one part in 3e-17 away on
others. Peaks carrying the axial-divergence correction differ by about 1e-16, a
different summation order for the same quadrature. From rietx-kernels 1.2.0,
on x86-64, those peaks use a port of SLEEF’s exp, held to 1.0 ulp. The arm64
wheels keep the C library’s. A slow test holds a whole fit on the kernels
within 5 esd of the numpy path’s, and on Linux x86-64 the gap measured
0.42 esd. The structure figure calls no library function, so both paths draw
the same picture to the bit.
Checking an install#
Ask the package rather than a table that goes stale. capabilities() reports
the versions, the backends, the plans, the modes, the anodes, the pattern
formats it can open, and the feature flags. For each backend it reports whether
the optional dependency imports here:
from rietx import capabilities
caps = capabilities()
caps.package_version
[backend.name for backend in caps.backends if backend.available]
[fmt.name for fmt in caps.reader_formats]
Capabilities.backends is the field that answers “did the jax extra take?”.
Each BackendCapability carries BackendCapability.available (does it import
here), BackendCapability.requires (the distribution to install) and
BackendCapability.experimental. API: everything else lists the
rest of the object’s fields.
rietx.__version__ is the version of the installed distribution, the same
string capabilities().package_version reports and every Provenance,
TreeHeader and project.json is stamped with, so a result and the package
that produced it can never disagree about it. A source checkout is the one
exception. If its pyproject.toml has moved on since its editable install,
the source’s version is stamped instead, with the commit as a local label (see
Troubleshooting).
Installing from source#
Install from source to contribute, or to run against an unreleased change:
git clone https://github.com/yue-here/rietx
cd rietx
uv venv --python 3.12 && uv pip install -e ".[dev]"
Then run the suite. The fast selection is the unit and property tests. The full selection adds the real-data acceptance suites, which refine certified standards and take tens of minutes:
.venv/bin/python -m pytest -n auto --dist loadgroup -m "not slow" # fast
.venv/bin/python -m pytest -n auto --dist loadgroup # everything
--dist loadgroup is not optional. It honours the marks that keep a shared
refinement fixture on one worker; plain --dist load refits it on every worker and says nothing, so the
suite refuses a parallel run without it and names what to pass. The suite
prints its own counts, and those counts depend on the extras installed: jax and
torch turn skips into passes.
Troubleshooting#
zsh: no matches found: rietx[jax]. zsh expanded the brackets as a glob.
Quote the argument: pip install "rietx[jax]".
rietx.__version__ reads 0.0.0+dev. No distribution of that name is
installed, and what you imported is a source checkout sitting on sys.path
ahead of its own install. Install it (uv pip install -e .) before refining
anything: that string is stamped into the provenance of every result, every
history tree and every project file the session writes.
RuntimeWarning: the installed rietx metadata says '1.4.0' but the source tree it is imported from says '1.6.0.dev0'. The checkout’s version was bumped after
its editable install, which writes its metadata once, when it is installed.
Results are stamped with the source version and the commit
(1.6.0.dev0+g and twelve hex digits, .dirty if a tracked file was edited),
so they still name the code that ran. Reinstall (uv pip install -e ".[dev]")
to make the two agree.
No matching distribution found for rietx-kernels. Your platform has no
rietx-kernels wheel, and the package publishes no source to build one from.
Two common cases are a musllinux system such as Alpine, and a free-threaded
Python build (3.13t or 3.14t), which cannot load the wheels that exist. Install
rietx without its dependencies and run the numpy path. The first refinement
warns once that the kernels did not load, and RIETX_COMPILED=0 silences it.
pip install --no-deps rietx
pip install numpy scipy pydantic gemmi spglib matplotlib
Validation and accuracy claims#
docs/VALIDATION.md
tabulates every real-data assertion in the repository and says what each
tolerance is referenced to. It is generated from the suite, so it is the
accuracy claim, and nothing in this manual restates it. Validation against other codes says
which reference each comparison was made against.
It opens with the rule to read it under: judge a correction by what it changed, never by ΔRwp. Of the eight corrections in v0.5, two provably cannot move Rwp, one moves it the wrong way when it is right, and the two largest accuracy wins are invisible in it.