Calling rietx from a program#
A program drives rietx through the Python API a person types, stores an answer as JSON, and asks capabilities() what the installed build supports.
The package has no separate wire format. Its objects are the API, and their JSON dumps are what a program stores or sends.
The Python API#
A program calls the same functions a script calls, such as read_pattern, Structure, Refinement.fit, refine_sequential and build_report.
import rietx as rx
data = rx.read_pattern("my_sample.xye")
ref = rx.Refinement(structure, instrument)
result = ref.fit(data, plan="mccusker_default")
print(ref.summary())
A first fit in Python builds the structure and the instrument this block assumes.
Refinement.summary returns one string that says whether the fit is done, and why.
Versions up to 1.2 also had an agent module.
It took one JSON request and answered with an {"ok": …} envelope.
Version 1.3 removed it, after four traced rounds of agent runs recorded no call to it.
Its requests carried each pattern inline, so one lab pattern made a request of about 11 000 tokens and a 68-pattern series one of about 754 000.
Errors#
A failure raises an exception.
Exception |
Raised when |
|---|---|
|
rietx refuses a model, a plan, an argument or a file. A pattern reader’s message names the file |
|
a refining call gets a structure with no phases. It is a subclass of |
|
a call needs a fit that has not run, such as |
|
a |
Answer types#
Each call that answers returns its own type.
Call |
Answer |
|---|---|
|
|
|
|
|
|
|
|
An IndexingResult holds ranked candidate cells and has no single cell.
Indexing is declared provisional (Provisional by declaration), so its answer type may change in any release.
Reports#
Refinement.report builds the FitReport for the last fit.
Refinement.fit with stage_reports=True also builds a report at the end of every stage, and leaves them in Refinement.stage_reports_.
A fit’s final state is often its least informative one, so read the stage reports on a run you will act on (Reports at every stage).
Answers as JSON#
Every answer type is a pydantic model, so a program on the other side needs nothing from rietx to read one.
model_dump_json() writes an answer as JSON text, and model_validate_json reads it back.
A non-finite float is written as the string "Infinity", "-Infinity" or "NaN", so an unbounded parameter limit survives the round trip.
model_dump(mode="json") returns a dict of JSON types, with one exception.
A non-finite float stays a Python float.
Python’s json.dumps then writes it as a bare Infinity.
A strict JSON parser refuses that token.
Store or send the text that model_dump_json() writes.
from rietx import Parameter
bound = Parameter(value=1.0) # no limits: min is -inf and max is +inf
text = bound.model_dump_json()
assert '"max":"Infinity"' in text
assert Parameter.model_validate_json(text).max == float("inf")
assert bound.model_dump(mode="json")["max"] == float("inf") # a float, not a string
Tool definitions#
rietx ships no tool definition for a tool-calling model. To offer refinement as a tool, wrap the Python API in your own tool. Give it paths as arguments, such as a pattern file, a CIF or a project directory. A pattern passed inline makes every call large.
A dedicated tool adds something where it gates, renders, audits or runs work in parallel. An agent that has a shell needs none of those to refine a pattern.
The agent skill#
The rietx skill is the protocol an agent reads before it drives a fit. It gives the order to free parameters in, the checks to make before a number is believed, and how to read a report that declines to answer. For agents says how to install it.
Capabilities.skill_path is the directory holding the copy this build carries, or None where the build carries none.
rietx skill --path prints the same directory.
In a checkout of the repository it is docs/skill/rietx/.
import rietx as rx
from pathlib import Path
print(Path(rx.capabilities().skill_path, "SKILL.md").read_text())
capabilities()#
capabilities() returns a Capabilities object that says what the installed build supports.
Each arm is read from the registry it describes, so a new backend, plan or file format appears in it without an edit to this page. Read the call when your program runs, and do not copy its contents into code.
import rietx as rx
caps = rx.capabilities()
assert "rietveld" in caps.modes
assert any(backend.name == "numpy" and backend.available for backend in caps.backends)
choices = {plan.name: plan.when_to_use for plan in caps.plans}
Version strings#
Capabilities.package_version is the installed rietx version, the same string as rietx.__version__.
It moves with every release.
Six more strings version the data contracts, and each moves on its own:
Capabilities.schema_version, the pydantic models;Capabilities.report_thresholds_version, theFitReportgates and thresholds;Capabilities.event_schema_version, the streaming event ladder;Capabilities.project_format_version, the.rexproject directory;Capabilities.textdoc_format_version, the.rxttext document;Capabilities.indexing_thresholds_version, the indexing gates and the grade and caveat vocabularies.
The six version strings says what a change to each means.
Store the contract versions beside any answer you store.
A threshold compared across two report_thresholds_version values compares two different tests.
Arms#
Arm |
Holds |
|---|---|
|
one |
|
the names |
|
the fit modes: Rietveld, Le Bail and Pawley |
|
one |
|
one |
|
one |
|
the |
|
one |
|
one |
|
one |
|
one |
|
one |
|
the crystal systems in the order an indexing search enters them, from cubic to triclinic. Each system takes longer to search than the one before it |
|
for each crystal system, the Bravais centring letters it admits |
|
the systematic-shift models the indexing screen can fit |
|
feature flags, name to true or false |
|
why the compiled kernels did not load, or |
A feature flag is computed from the thing it reports, such as a schema field’s presence or a top-level function’s existence.
It turns true by itself in the release that adds the feature.
features["compiled_kernels"] says whether the compiled kernels loaded, and features["compiled_kernels_active"] whether the next fit will use them.
Backends#
Field |
Meaning |
|---|---|
|
the value to pass as |
|
whether the backend’s optional dependency imports on this machine |
|
true for a backend kept for validation and not for production fits |
|
the distribution to install, or |
|
the precision the backend computes at |
Plans#
Field |
Meaning |
|---|---|
|
the preset name |
|
a short title for a menu |
|
what the preset frees, in order |
|
the fit modes the preset runs under |
|
the situation the preset is for |
A program can offer the choice in its own interface without a hard-coded list. Plan presets draws each preset’s stages.
Radiations#
Capabilities.radiations lists every source kind.
Read it before Capabilities.anodes, which describes the X-ray kind alone.
A program that reads only the anodes would conclude that the build handles X-rays only.
Field |
Meaning |
|---|---|
|
the |
|
a one-line name |
|
what does the scattering, and so whether the amplitude falls off with Q |
|
whether the source carries anomalous dispersion (f′ and f″) |
|
how many wavelengths the source can carry: |
|
whether the polarisation factor can refine |
|
whether the source accepts declared λ/n monochromator harmonics (Monochromator harmonics) |
|
whether a pattern from this source carries the magnetic scattering of a phase that declares moments |
Each flag is computed from the source class, so it changes by itself when the class gains the feature. A listed kind is one the schema accepts, which does not mean every fit runs on it. This version reads a time-of-flight bank and refines none (Time-of-flight bank).
Anodes#
Field |
Meaning |
|---|---|
|
the anode name, such as |
|
the emission wavelengths in Å |
|
true for an entry such as |
|
the Kβ wavelength for the contamination check, or |
Pattern formats#
Field |
Meaning |
|---|---|
|
the format’s name |
|
a title for a file dialogue |
|
the file extensions |
|
how a file is recognised as this format |
|
where the intensity uncertainties come from, which differs between vendors |
|
the reader keywords this format honours |
|
why the format is declined, or |
A format with a ReaderCapability.refuses string is one the build recognises in order to decline it, such as a peak list.
“This is the wrong kind of file” is a different answer from “this file cannot be opened”.
Field |
Meaning |
|---|---|
|
the keyword, such as |
|
|
|
what the keyword selects |
A reader keyword means the same in every format that takes it, so Capabilities.reader_options describes each one once.
Refinement formats#
Field |
Meaning |
|---|---|
|
the format’s name |
|
a title for a file dialogue |
|
the file extensions |
|
how a file is recognised as this format |
|
what the file holds beyond a structure, in words |
|
where the reader reports its repairs: |
|
the function that writes this format, or |
|
why the format is declined, or |
Indexing#
Field |
Meaning |
|---|---|
|
the value to pass as |
|
a short title |
|
what the preset searches |
|
the situation the preset is for |
|
true for the preset |
|
the ceiling on the whole run in seconds, or |
|
the range of run times measured on known cells |
|
the engine’s name |
|
how the engine searches |
An indexing search runs against a budget. A program that has to promise a response time reads the ceiling here.