<a id="api-everyday-calls"></a>

# API: everyday calls

This page lists the calls a refinement session makes, with each signature, its fields and the first line of its docstring.

Everything is reached as `rx.` after `import rietx as rx`.
`help(obj)` prints a call’s full docstring.
Calls for one technique, such as magnetic refinement or another program’s files, are on [API: techniques](api-techniques.html.md), and every other exported name is on [API: everything else](api-types.html.md).

<a id="reading-data"></a>

## Reading data

### rx.read_pattern(path: str | Path, \*, diagnostics: list[[Diagnostic](#rx.Diagnostic)] | None = None, \*\*options: Any) → [PatternData](#rx.PatternData)

Read any supported pattern file, dispatching on *content* first.

### rx.read_pdcif(path: str | Path, \*, block: str | None = None, diagnostics: list[[Diagnostic](#rx.Diagnostic)] | None = None) → [PatternData](#rx.PatternData)

Read a powder pattern from a pdCIF file.

#### *classmethod* Structure.from_cif(path: str | os.PathLike[str], \*, phase_name: str | None = None, aniso: bool = False, moment_ions: dict[str, str] | None = None, moment_g: dict[str, float] | None = None, nuclear_group: 'auto' | 'parent' | 'file' = 'auto', diagnostics: list | None = None) → [Structure](#rx.Structure)

Read a CIF, or a **magCIF**, into a `Structure`.

#### *classmethod* Instrument.bragg_brentano(\*, radiation: str = 'CuKa', goniometer_radius_mm: float = 217.5, monochromator_two_theta: float | None = None, ka2_ratio: float = 0.5, mu_t: float | None = None, thickness_mm: float | None = None) → [Instrument](#rx.Instrument)

Lab flat-plate diffractometer preset with a Kα1/Kα2 doublet.

#### *classmethod* Instrument.debye_scherrer(wavelength: float, \*, polarization: float = 0.99, goniometer_radius_mm: float | None = None, capillary_radius_mm: float | None = None, packing_fraction: float = 0.6, mu_r: float | None = None) → [Instrument](#rx.Instrument)

Synchrotron/capillary preset with a single wavelength.

### rx.estimate_mu_r(structure: [Structure](#rx.Structure), instrument: [Instrument](#rx.Instrument)) → float | None

Starting µR for a packed capillary, from composition and geometry.

### rx.auto_background(data: [PatternData](#rx.PatternData), \*, kind: str = 'pspline', diagnostics: PatternDiagnostics | None = None, wavelength: float | None = None, two_theta_limits: tuple[float, float] | None = None, source: object | None = None, seed: bool = False) → BackgroundChoice

Background sized to the data, with the scores it was sized on.

### rx.diagnose(data: [PatternData](#rx.PatternData), \*, wavelength: float | None = None, baseline_lambda: float | None = None, source: object | None = None) → PatternDiagnostics

`PatternDiagnostics` of a raw pattern.

### rx.load_instrument_profile(path: str | Path, \*, diagnostics: list[[Diagnostic](#rx.Diagnostic)] | None = None) → [Instrument](#rx.Instrument)

Read a profile file back as a **frozen** instrument.

### rx.save_instrument_profile(instrument: [Instrument](#rx.Instrument), path: str | Path)

Write the instrument’s calibrated state to a JSON profile file.

### rx.capabilities() → Capabilities

Everything this build can do.

### rx.help_for(path: str) → [HelpEntry](api-types.html.md#rx.HelpEntry) | None

The entry for a parameter dot-path, or `None` if no family claims it.

<a id="model-objects"></a>

## Model objects

### *class* rx.Parameter

A single refinable scalar.

* `value: float`
* `vary: bool = False`
* `min: float = -inf`
* `max: float = inf`
* `expr: str | None = None`
* `unit: str | None = None`
* `stderr: float | None = None`

### *class* rx.Structure

The phases refined against one pattern.

* `phases: list[Phase]`

### *class* rx.Phase

A crystalline phase: symmetry, cell, atoms, scale, sample broadening.

* `name: str`
* `space_group: str`
* `symmetry_operations: list[str] | None = None`
* `cell: Cell`
* `atoms: list[Atom]`
* `scale: Parameter = Parameter(1.0, min=0.0)`
* `extinction: Parameter = Parameter(0.0, min=0.0)`
* `preferred_orientation: PreferredOrientation | None = None`
* `texture: SphericalHarmonicTexture | None = None`
* `lor_size: Parameter = Parameter(0.0, min=0.0)`
* `lor_strain: Parameter = Parameter(0.0, min=0.0)`
* `magnetic_lor_size: Parameter = Parameter(0.0, min=0.0)`
* `magnetic_lor_strain: Parameter = Parameter(0.0, min=0.0)`
* `gauss_size: Parameter = Parameter(0.0, min=0.0)`
* `gauss_strain: Parameter = Parameter(0.0, min=0.0)`
* `microstrain: StephensStrain | None = None`
* `particle_radius_um: float | None = None`
* `propagation_vector: tuple[str, str, str] | None = None`
* `magnetic_symmetry: MagneticSymmetry | None = None`
* `restraints: list[BondRestraint | AngleRestraint | ValueRestraint] = []`
* `floating_origin: 'hold' | 'centroid' | None = None`

### *class* rx.Atom

One site in the asymmetric unit.

* `label: str`
* `species: str`
* `x: Parameter`
* `y: Parameter`
* `z: Parameter`
* `occ: Parameter = Parameter(1.0, min=0.0)`
* `biso: Parameter = Parameter(0.5)`
* `aniso: AnisoU | None = None`
* `moment: Moment | None = None`
* `disorder_assembly: str | None = None`
* `disorder_group: str | None = None`

### *class* rx.Cell

The lattice parameters: three lengths (Å) and three angles (degrees).

* `a: Parameter`
* `b: Parameter`
* `c: Parameter`
* `alpha: Parameter`
* `beta: Parameter`
* `gamma: Parameter`

### *class* rx.AnisoU

Anisotropic displacement tensor in the CIF `U^ij` convention (Å²).

* `u11: Parameter`
* `u22: Parameter`
* `u33: Parameter`
* `u12: Parameter = Parameter(0.0)`
* `u13: Parameter = Parameter(0.0)`
* `u23: Parameter = Parameter(0.0)`

### *class* rx.PreferredOrientation

Single-axis March-Dollase preferred-orientation correction (Dollase 1986).

* `axis: tuple[int, int, int]`
* `r: Parameter = Parameter(1.0, min=1e-06)`

### *class* rx.StephensStrain

Anisotropic strain broadening coefficients `S_HKL` (Stephens, 1999).

* `s400: Parameter = Parameter(0.0)`
* `s310: Parameter = Parameter(0.0)`
* `s301: Parameter = Parameter(0.0)`
* `s220: Parameter = Parameter(0.0)`
* `s211: Parameter = Parameter(0.0)`
* `s202: Parameter = Parameter(0.0)`
* `s130: Parameter = Parameter(0.0)`
* `s121: Parameter = Parameter(0.0)`
* `s112: Parameter = Parameter(0.0)`
* `s103: Parameter = Parameter(0.0)`
* `s040: Parameter = Parameter(0.0)`
* `s031: Parameter = Parameter(0.0)`
* `s022: Parameter = Parameter(0.0)`
* `s013: Parameter = Parameter(0.0)`
* `s004: Parameter = Parameter(0.0)`

### *class* rx.Instrument

Everything about the measurement except the sample.

* `source: Source | NeutronSource | TOFSource`
* `geometry: Geometry = Geometry(…)`
* `zero_shift: Parameter = Parameter(0.0)`
* `profile: ProfileTCHZ = ProfileTCHZ(…)`
* `background: BackgroundChebyshev | BackgroundFixedPlusChebyshev | BackgroundPSpline = BackgroundChebyshev(…)`
* `extra_components: list[HumpComponent | PeakComponent] = []`

### *class* rx.Source

Constant-wavelength X-ray source.

* `kind: 'xray_cw' = 'xray_cw'`
* `lines: list[EmissionLine]`
* `polarization: Parameter = Parameter(0.5, min=0.0, max=1.0)`
* `kbeta: 'filter' | 'monochromator' | 'mirror' | None = None`
* `dispersion: Dispersion | None = Dispersion(…)`
* `harmonics: list[Harmonic] = []`

### *class* rx.NeutronSource

Constant-wavelength **neutron** source: one wavelength, nuclear scattering.

* `kind: 'neutron_cw' = 'neutron_cw'`
* `wavelength: Parameter`
* `harmonics: list[Harmonic] = []`

### *class* rx.Geometry

Diffraction geometry.

* `kind: 'debye_scherrer' | 'bragg_brentano' | 'flat_plate_transmission' = 'debye_scherrer'`
* `goniometer_radius_mm: float | None = None`
* `surface_roughness: RoughnessSuortti | RoughnessPitschke | None = None`
* `sample_displacement: Parameter = Parameter(0.0)`
* `sample_transparency: Parameter = Parameter(0.0, min=0.0)`
* `capillary_offset_along_beam: Parameter = Parameter(0.0)`
* `capillary_offset_across_beam: Parameter = Parameter(0.0)`
* `axial_sl: Parameter = Parameter(0.0, min=0.0)`
* `axial_hl: Parameter = Parameter(0.0, min=0.0)`
* `mu_r: float | None = None`
* `capillary_radius_mm: float | None = None`
* `mu_t: float | None = None`
* `thickness_mm: float | None = None`
* `packing_fraction: float = 0.6`

### *class* rx.ProfileTCHZ

Thompson-Cox-Hastings pseudo-Voigt width parameters.

* `shape: 'tchz_pv' | 'voigt' = 'tchz_pv'`
* `u: Parameter = Parameter(0.0, min=-32400.0, max=32400.0)`
* `v: Parameter = Parameter(0.0, min=-32400.0, max=32400.0)`
* `w: Parameter = Parameter(0.001, min=1e-08, max=32400.0)`
* `x: Parameter = Parameter(0.001, min=0.0, max=180.0)`
* `y: Parameter = Parameter(0.0, min=-180.0, max=180.0)`

### *class* rx.BackgroundChebyshev

Shifted-Chebyshev background, linear in its coefficients.

* `kind: 'chebyshev' = 'chebyshev'`
* `coefficients: list[Parameter] = [Parameter(0.0) × 4]`

### *class* rx.BackgroundPSpline

Penalised cubic P-spline background, co-refined with the structure.

* `kind: 'pspline' = 'pspline'`
* `breakpoints: list[float]`
* `coefficients: list[Parameter]`
* `lambda_smooth: float = 1.0`
* `lambda_units: 'dimensionless' | 'intensity' = 'dimensionless'`
* `air_scatter: Parameter | None = None`

### *class* rx.BackgroundFixedPlusChebyshev

A fixed curve held in the model, a small refinable Chebyshev correction on top, and a scale on the curve itself.

* `kind: 'fixed_plus_chebyshev' = 'fixed_plus_chebyshev'`
* `fixed_two_theta: list[float]`
* `fixed_intensity: list[float]`
* `fixed_sigma: list[float] | None = None`
* `fixed_source: str | None = None`
* `scale: Parameter = Parameter(1.0, min=0.0)`
* `chebyshev: BackgroundChebyshev = BackgroundChebyshev(…)`

### *class* rx.Dispersion

Anomalous scattering corrections f′, f″ at the source wavelengths.

* `table: 'cromer_liberman' = 'cromer_liberman'`
* `overrides: dict[str, tuple[float, float]] = {}`

### *class* rx.PatternData

A powder pattern.

* `two_theta: list[float] | None = None`
* `tof: list[float] | None = None`
* `intensity: list[float]`
* `sigma: list[float] | None = None`
* `excluded_regions: list[tuple[float, float]] = []`
* `metadata: dict[str, str] = {}`

<a id="refinement"></a>

## Refinement

### *class* rx.Refinement(structure: [Structure](#rx.Structure), instrument: [Instrument](#rx.Instrument), \*, backend: str = 'numpy', solver: str = 'lm', history: bool | str | Path | [RefinementTree](api-types.html.md#rx.RefinementTree) = True)

Refine `structure` + `instrument` against a powder pattern.

#### Refinement.fit(data: [PatternData](#rx.PatternData), \*, mode: Mode = 'rietveld', plan: [RefinementPlan](#rx.RefinementPlan) | str = 'mccusker_default', two_theta_limits: tuple[float, float] | None = None, events=None, cancel=None, telemetry=None, label: str | None = None, stage_reports: bool = False, progress=None) → [RefinementResult](#rx.RefinementResult)

Run a staged refinement.

#### Refinement.report(\*, plan: [RefinementPlan](#rx.RefinementPlan) | str | None = None, \*\*kw)

The full `rietx.report.FitReport` for the last fit.

#### Refinement.summary(\*, deliverable: str | None = None, plot: str | None = None, plan: [RefinementPlan](#rx.RefinementPlan) | str | None = None, report: [FitReport](#rx.FitReport) | None = None, levels: dict[str, str] | None = None) → str

The termination view (WP-1302): “done, or not, and why” from one call.

#### Refinement.suggest(data: [PatternData](#rx.PatternData), \*, top_n: int = 5, include: str | list[str] = '\*', exclude: list[str] | tuple[str, ...] = (), mode: Mode | None = None, two_theta_limits: tuple[float, float] | None = None, report=None) → [SuggestionResult](#rx.SuggestionResult)

Which held parameter should be freed next?

#### Refinement.predict(two_theta=None) → np.ndarray

Evaluate `y_calc` at the current parameters, without a fit.

#### Refinement.run_stage(data: [PatternData](#rx.PatternData), stage: [Stage](#rx.Stage), \*, mode: Mode | None = None, two_theta_limits: tuple[float, float] | None = None, correlation_guard: float = 0.98, phase_support_sigma: float | None = 3.0, window_area_tol: float | None = None, events=None, cancel=None, telemetry=None, label: str | None = None) → [RefinementResult](#rx.RefinementResult)

Run a single stage from the current state, recording a child node.

#### Refinement.parameters(\*, mode: Mode | None = None) → list[[ParameterRow](#rx.ParameterRow)]

Every parameter as data, with fixed, locked and tied rows included.

#### Refinement.set_vary(path_globs: list[str] | str, vary: bool = True) → list[str]

Free (or hold) every parameter matching `path_globs`.

#### Refinement.set_values(values: dict[str, float])

Set parameter values by dot-path, recording a `set_value` node.

#### Refinement.tie(path: str, source: str | dict[str, float] | Sequence[tuple[str, float]], \*, scale: float = 1.0, offset: float = 0.0) → str

Constrain `path` to `scale·source + offset`, recording a node.

#### Refinement.tie_equal(paths: list[str] | str, \*, source: str | None = None) → list[str]

Make every parameter matching `paths` one parameter.

#### Refinement.untie(paths: list[str] | str) → list[str]

Release user ties, recording a `set_tie` node.

#### Refinement.add_variable(name: str, value: float, \*, vary: bool = False, min: float = -inf, max: float = inf, unit: str | None = None) → str

Declare a named variable other parameters can follow.

#### Refinement.remove_variable(name: str) → str

Delete a named variable, refusing while anything follows it.

#### Refinement.hold(path_globs: list[str] | str) → list[str]

Declare that these parameters do not move, whatever a plan asks.

#### Refinement.unhold(path_globs: list[str] | str) → list[str]

Take back a hold.

#### Refinement.edit(\*, structure: [Structure](#rx.Structure) | None = None, instrument: [Instrument](#rx.Instrument) | None = None, label: str = '') → str | None

Record a change to the model itself, such as adding an impurity phase, raising the background order or swapping the geometry.

### rx.refine(data: [PatternData](#rx.PatternData), structure: [Structure](#rx.Structure), instrument: [Instrument](#rx.Instrument), \*, mode: Mode = 'rietveld', plan: [RefinementPlan](#rx.RefinementPlan) | str = 'mccusker_default', two_theta_limits: tuple[float, float] | None = None, backend: str = 'numpy', solver: str = 'lm', history: bool | str | Path | [RefinementTree](api-types.html.md#rx.RefinementTree) = False, events=None, cancel=None, telemetry=None, label: str | None = None) → [RefinementResult](#rx.RefinementResult)

One-shot functional API: `refine(data, structure, instrument)`.

### *class* rx.RefinementPlan

* `stages: list[Stage]`
* `correlation_guard: float = 0.98`
* `intermediate_ftol: float | None = 1e-06`
* `lebail_passes: int = 1`
* `phase_support_sigma: float | None = 3.0`
* `closing_window_tol: float | None = 0.001`

### *class* rx.Stage

One turn-on group of a staged plan.

* `name: str`
* `turn_on: list[str]`
* `max_iter: int = 100`
* `ftol: float | None = None`
* `lebail_cycles: int = 3`
* `seed: float = 0.0`
* `strain_seed: float = 0.0`
* `restraint_weight_scale: float = 1.0`
* `window_slack_deg: float | None = None`

### rx.PLAN_INFO

A dict. Keys: `mccusker_default`, `mccusker_structural`, `lab_bragg_brentano`, `lab_calibrate`, `lab_sample_refine`, `profile_only`, `pawley_default`, `magnetic_width`.

### *class* rx.ParameterRow

One row of the parameter table, mirroring `params.vector.Entry`.

* `path: str`
* `value: float`
* `vary: bool = False`
* `lo: float = -inf`
* `hi: float = inf`
* `tie: TieSpec | None = None`
* `locked: bool = False`
* `held: bool = False`
* `esd: float | None = None`
* `mode_fixed: bool = False`
* `needs_held_cell: bool = False`
* `origin_axis: tuple[int, int, int] | None = None`
* `help_key: str | None = None`

<a id="results"></a>

## Results

### *class* rx.RefinementResult

What a fit returns: the answer, its statistics, and what the engine found wrong with it.

* `status: 'converged' | 'max_iter' | 'diverged'`
* `mode: 'rietveld' | 'lebail' | 'pawley'`
* `parameters: list[RefinedParameter]`
* `statistics: Statistics`
* `stages: list[StageResult] = []`
* `diagnostics: list[Diagnostic] = []`
* `provenance: Provenance`
* `node_id: str | None = None`
* `tree_id: str | None = None`
* `two_theta: list[float] = []`
* `y_obs: list[float] = []`
* `y_calc: list[float] = []`
* `y_background: list[float] = []`
* `sigma: list[float] = []`
* `ticks: dict[str, list[float]] = {}`
* `tick_hkl: dict[str, list[list[int]]] = {}`
* `qpa: QuantitativePhaseAnalysis | None = None`
* `phase_agreement: list[PhaseAgreement] = []`
* `texture: list[PhaseTexture] = []`
* `data_support: DataSupport | None = None`
* `absorption: AbsorptionCorrection | None = None`
* `restraints: RestraintReport | None = None`
* `geometry: GeometryTable | None = None`
* `cell_volumes: list[CellVolume] | None = None`
* `microstructure: list[PhaseMicrostructure] = []`
* `identifiability: Identifiability | None = None`
* `parametric: list[ParametricCoefficient] | None = None`
* `parametric_form: list[ParametricFormTest] | None = None`
* `parametric_form_joint: ParametricFormReading | None = None`
* `parametric_equations: list[RefinedParametricEquation] | None = None`
* `n_extra_components: int | None = None`
* `n_background_components: int | None = None`
* `histograms: list[HistogramResult] = []`

### *class* rx.StageResult

One stage’s outcome.

* `name: str`
* `status: 'converged' | 'max_iter' | 'diverged'`
* `n_iterations: int`
* `cost_initial: float`
* `cost_final: float`
* `freed: list[str] = []`
* `ftol: float | None = None`
* `window_area_tol: float | None = None`
* `n_constraint_truncations: int = 0`
* `n_degenerate_cell_probes: int = 0`
* `n_lapack_fallbacks: int = 0`
* `held: list[str] = []`
* `held_reach: dict[str, list[str]] = {}`
* `scale_b_held: dict[int, float] | None = None`
* `width_twins_held: dict[str, list[str]] | None = None`
* `released: list[str] = []`
* `moment_flat_axes: dict[str, list[float]] = {}`
* `moment_turned: list[str] = []`
* `blocked_by_hold: list[str] = []`
* `unknown_paths: list[str] | None = None`
* `unreached_histograms: dict[int, list[str]] | None = None`
* `seeded: dict[str, float] | None = None`
* `moment_angle_tests: list[MomentAngleTest] | None = None`
* `cell_reset: list[str] | None = None`
* `collapsed: list[str] | None = None`

### *class* rx.Statistics

Agreement indices, defined per Toby (2006), Powder Diffraction 21, 67.

* `rwp: float`
* `rp: float`
* `rexp: float`
* `chi2: float`
* `gof: float`
* `rwp_background_subtracted: float | None = None`
* `durbin_watson: float | None = None`
* `esd_inflation: float | None = None`
* `n_points: int`
* `n_free_parameters: int`
* `max_shift_over_esd: float | None = None`
* `identifiability_clause: str | None = None`

### *class* rx.RefinedParameter

One row of `RefinementResult.parameters`.

* `path: str`
* `value: float`
* `stderr: float | None = None`
* `stderr_uncorrected: float | None = None`
* `vary: bool = True`
* `at_bound: bool | None = None`
* `equations: list[str] | None = None`
* `interval: ParameterInterval | None = None`

### *class* rx.Diagnostic

A structured, actionable message produced by the engine.

* `level: 'info' | 'warning' | 'error'`
* `code: str`
* `message: str`
* `where: list[str] = []`
* `suggestion: str | None = None`
* `value: float | None = None`

### *class* rx.SeriesResult

The result of a sequential refinement over an ordered set of patterns.

* `mode: 'rietveld' | 'lebail' | 'pawley' = 'rietveld'`
* `entries: list[SeriesEntry] = []`
* `x_label: str = 'index'`
* `direction: 'forward' | 'backward' | 'both' = 'forward'`
* `backward: SeriesResult | None = None`
* `diagnostics: list[Diagnostic] = []`
* `discontinuities: list[SeriesStep] | None = None`
* `relative_paths: list[str] | None = None`
* `angle_paths: list[str] | None = None`
* `failures: list[SeriesFailure] = []`
* `n_failed: int = 0`
* `provenance: Provenance | None = None`

#### SeriesResult.trajectory(path: str) → [Trajectory](api-types.html.md#rx.Trajectory)

One parameter’s trajectory across the series.

#### SeriesResult.to_table(\*, paths: list[str] | None = None) → tuple[list[str], list[list]]

`(header, rows)`: one row per pattern, a column per path (+ esd where that kind of path has one).

#### SeriesResult.write_csv(path, \*, delimiter: str | None = None, paths: list[str] | None = None)

Write `to_table` to CSV/TSV (delimiter inferred from suffix).

#### SeriesResult.summary(\*, max_entries: int = 5, deliverable: str | None = None, parametric: [RefinementResult](#rx.RefinementResult) | None = None, levels: dict[str, str] | None = None) → str

The series termination view (WP-1302): the trajectory table, the `SEQUENTIAL_*` rows, first and last `max_entries` with the count.

### *class* rx.SeriesEntry

One pattern’s place in the series: what was fitted and how it went.

* `index: int`
* `label: str = ''`
* `x: float | None = None`
* `status: 'converged' | 'max_iter' | 'diverged' = 'converged'`
* `statistics: Statistics | None = None`
* `parameters: list[RefinedParameter] = []`
* `qpa: QuantitativePhaseAnalysis | None = None`
* `phase_agreement: list[PhaseAgreement] = []`
* `magnetic: list[MomentEvidence] = []`
* `diagnostics: list[Diagnostic] = []`
* `n_iterations: int = 0`
* `reseeded: bool = False`
* `rwp_warm: float | None = None`
* `rung: 'warm' | 'warm_staged' | 'cold' = 'warm'`
* `rungs_tried: list[str] = []`
* `rungs_raised: dict[str, str] = {}`
* `rwp_fence: float | None = None`
* `node_id: str | None = None`
* `tree_id: str | None = None`

### *class* rx.IndexingResult

What `rietx.index_pattern` returns: a list of candidates, with no `.cell` or `.best`.

* `candidates: list[CellCandidate] = []`
* `engines_run: list[str] = []`
* `systems_searched: list[str] = []`
* `search_complete: dict[str, bool] = {}`
* `engine_stats: dict[str, float] = {}`
* `fom_panel_disagrees: bool = False`
* `quality: DataQualityReport | None = None`
* `validated: bool = False`
* `wavelength: float = 0.0`
* `n_usable_lines: int = 0`
* `provenance: Provenance`
* `preset: str | None = None`
* `thresholds_version: str = '1.11'`
* `diagnostics: list[Diagnostic] = []`

#### IndexingResult.best_or_none() → [CellCandidate](api-types.html.md#rx.CellCandidate) | None

The single candidate, or None.

#### IndexingResult.evidence() → [IndexingEvidence](api-types.html.md#rx.IndexingEvidence)

The machine-readable evidence view (WP-1043).

### *class* rx.SuggestionResult

Ranked, gated answer to “which parameter should be freed next?”.

* `groups: list[CandidateGroup] = []`
* `non_separable: list[ParameterCandidate] = []`
* `skipped: list[str] = []`
* `n_evaluated: int = 0`
* `chi2_red: float`
* `noise_floor: float`
* `summary: str`
* `n_effective: float | None = None`

### *class* rx.CandidateGroup

One candidate, or a tie of candidates the data cannot split.

* `members: list[ParameterCandidate]`
* `gain: float`
* `resolved: bool`
* `delta_bic: float`
* `delta_bic_raw_n: float | None = None`

<a id="fit-report"></a>

## Fit report

### rx.build_report(result: [RefinementResult](#rx.RefinementResult), \*, model=None, values=None, plan=None, free_paths: list[str] | None = None, structure=None, instrument=None, held: list[str] | None = None, top_n: int = 15, match_tol_deg: float = 0.08, min_peak_sigma: float = 5.0) → [FitReport](#rx.FitReport)

Build the report, going as deep as the inputs allow.

### *class* rx.FitReport

All three layers.

* `thresholds_version: str = '1.13'`
* `rwp: float`
* `gof: float`
* `cumulative_chi2_breakpoints: list[float] = []`
* `regions: list[Region] = []`
* `n_regions_total: int = 0`
* `unmatched: list[UnmatchedPeak] = []`
* `satellites: list[SatelliteEvidence] = []`
* `magnetic: list[MomentEvidence] = []`
* `lebail_gap: LeBailGap | None = None`
* `background: BackgroundEvidence | None = None`
* `identifiability: IdentifiabilityEvidence | None = None`
* `summary: str = ''`
* `attribution: list[RegionAttribution] = []`
* `trends: list[TrendAnalysis] = []`
* `texture: list[TextureAnalysis] = []`
* `strain: list[StrainAnalysis] = []`
* `restraints: RestraintReport | None = None`
* `geometry: GeometryTable | None = None`
* `microstructure: list[PhaseMicrostructure] = []`
* `layer1_available: bool = False`
* `abstained_reason: str | None = None`
* `abstained_kind: 'immature' | 'resolution_limited' | 'unreadable' | None = None`
* `suggested_actions: list[SuggestedAction] = []`

#### report.compare_rivals(refinement, data, finding: ExchangeFinding | tuple[str, str]) → RivalComparison

Fit each member of an exchangeable pair alone, the other at its null.

#### report.predict_then_verify(refinement, data, action: [SuggestedAction](api-types.html.md#rx.SuggestedAction), \*, min_improvement: float = 0.01) → VerificationOutcome

Try an action on a branch, keep it only if χ² actually improves.

#### report.compare_freed(restricted, full) → [FreedComparison](#rx.report.FreedComparison)

ΔBIC of the parameters `full` frees beyond `restricted`, each one’s t beside it.

#### *class* report.FreedComparison

The effect of freeing parameters, as ΔBIC with each one’s t-ratio beside it.

* `freed: list[FreedParameter]`
* `n_added: int`
* `n_points: int`
* `chi2_restricted: float`
* `chi2_full: float`
* `esd_inflation: float | None = None`
* `n_effective: float`
* `delta_bic: float`
* `delta_bic_raw_n: float`

#### *class* report.FreedParameter

One parameter the fuller fit frees and the restricted fit held.

* `path: str`
* `held_at: float | None = None`
* `value: float`
* `esd: float | None = None`
* `t_ratio: float | None = None`

<a id="series-history-projects"></a>

## Series, history, projects

### rx.refine_sequential(patterns: Sequence[[PatternData](#rx.PatternData)], structure: [Structure](#rx.Structure), instrument: [Instrument](#rx.Instrument), \*, carry: Sequence[str] = '\*', carry_hkl_intensities: bool = True, backend: str = 'numpy', solver: str = 'lm', history: bool | str | Path = False, \*\*kw) → [SeriesResult](#rx.SeriesResult)

One-shot functional API for a warm-started series.

### *class* rx.SequentialRefinement(structure: [Structure](#rx.Structure), instrument: [Instrument](#rx.Instrument), \*, backend: str = 'numpy', solver: str = 'lm', carry: Sequence[str] = '\*', carry_hkl_intensities: bool = True, history: bool | str | Path = False)

Refine an ordered series of patterns, each warm-started from the last.

### rx.refine_multi(data: list[[PatternData](#rx.PatternData)], structure: [Structure](#rx.Structure) | list[[Structure](#rx.Structure)], instruments: list[[Instrument](#rx.Instrument)], \*, plan: [RefinementPlan](#rx.RefinementPlan) | str = 'mccusker_default', sharing: [SharingMap](api-types.html.md#rx.SharingMap) | None = None, coordinates: [CoordinateTable](api-types.html.md#rx.CoordinateTable) | None = None, parametric: list[[ParametricEquation](api-types.html.md#rx.ParametricEquation)] | None = None, two_theta_limits=None, weights: list[float] | None = None, backend: str = 'numpy', solver: str = 'lm', events=None, cancel=None, telemetry=None, label: str | None = None, progress=None) → [RefinementResult](#rx.RefinementResult)

One-shot joint refinement of `structure` against several `data`/ `instruments` pairs.

### *class* rx.MultiHistogramRefinement(structure: [Structure](#rx.Structure) | list[[Structure](#rx.Structure)], instruments: list[[Instrument](#rx.Instrument)], \*, sharing: [SharingMap](api-types.html.md#rx.SharingMap) | None = None, coordinates: [CoordinateTable](api-types.html.md#rx.CoordinateTable) | None = None, parametric: list[[ParametricEquation](api-types.html.md#rx.ParametricEquation)] | None = None, backend: str = 'numpy', solver: str = 'lm')

Joint Rietveld refinement of a shared structure against several patterns.

#### MultiHistogramRefinement.report(histogram: int, \*, plan: [RefinementPlan](#rx.RefinementPlan) | str | None = None, \*\*kw)

The `rietx.report.FitReport` for one histogram of the last fit.

#### Refinement.checkout(node_id: str) → [Refinement](#rx.Refinement)

Restore the state recorded at `node_id` (a node id or a tag).

#### Refinement.branch(node_id: str | None = None) → [Refinement](#rx.Refinement)

A second working tree over the same history, for a rival strategy.

#### Refinement.merge(other: str, \*, prefer: str = 'theirs', label: str = '') → str

Three-way merge of another branch into the current state.

#### Refinement.cherry_pick(node_id: str, data: [PatternData](#rx.PatternData)) → [RefinementResult](#rx.RefinementResult)

Re-run another node’s *stage action* on top of the current state.

### rx.replay(tree: [RefinementTree](api-types.html.md#rx.RefinementTree), node_id: str, data: [PatternData](#rx.PatternData)) → [RefinementResult](#rx.RefinementResult)

Recompute the curves and statistics of a recorded node.

### *class* rx.Project(path: str | Path, doc: [ProjectDoc](api-types.html.md#rx.ProjectDoc), data: [PatternData](#rx.PatternData), refinement: [Refinement](#rx.Refinement), data_diagnostics: list[[Diagnostic](#rx.Diagnostic)] | None = None, history_diagnostics: list[[Diagnostic](#rx.Diagnostic)] | None = None)

A refinement session stored on disk, which you can open and save.

#### *classmethod* Project.create(path: str | Path, \*, pattern: str | Path, structure: [Structure](#rx.Structure) | None = None, instrument: [Instrument](#rx.Instrument), mode: Mode = 'rietveld', plan: Any = None, two_theta_limits: tuple[float, float] | None = None, excluded_regions: list[tuple[float, float]] | None = None, reader_options: dict[str, Any] | None = None, ui: dict[str, Any] | None = None, backend: str = 'numpy', solver: str = 'lm') → [Project](#rx.Project)

Create a project directory around a pattern file and a model.

#### *classmethod* Project.open(path: str | Path, \*, backend: str = 'numpy', solver: str = 'lm') → [Project](#rx.Project)

Open an existing project, resuming at the history head.

#### Project.save()

Rewrite `project.json`.

### *class* rx.CancelToken

A thread-safe “stop asking for evaluations” flag.

<a id="peaks-and-indexing"></a>

## Peaks and indexing

### rx.pick_peaks(data: [PatternData](#rx.PatternData), instrument: [Instrument](#rx.Instrument), \*, two_theta_range: tuple[float, float] | None = None, shoulders: bool = True, flag_contamination: bool = True) → [PeakList](api-types.html.md#rx.PeakList)

Every resolvable line in `data`, with a fitted position and its esd.

### rx.fit_peaks(data: [PatternData](#rx.PatternData), instrument: [Instrument](#rx.Instrument), positions: np.ndarray | list[float], \*, two_theta_range: tuple[float, float] | None = None) → [PeakList](api-types.html.md#rx.PeakList)

Profile-fit the peaks at `positions` and nothing else, with no structure, space group or refinement.

### rx.index_pattern(peaks: [PeakList](api-types.html.md#rx.PeakList) | None = None, \*, data: [PatternData](#rx.PatternData) | None = None, instrument: [Instrument](#rx.Instrument) | None = None, spec=None, preset: str | None = None, engines: Sequence[str] | None = None, quality=None, shift_from_pairs: bool = True, validate: bool = True, check_top: int | None = None, two_theta_limits: tuple[float, float] | None = None, formula: str | None = None, temperature: float = 298.0, events=None, cancel=None)

Find the unit cell, or say in the shape of the answer that it cannot be found.

### rx.determine_extinction_symbol(data: [PatternData](#rx.PatternData), candidate: [CellCandidate](api-types.html.md#rx.CellCandidate), instrument: [Instrument](#rx.Instrument), \*, peaks: [PeakList](api-types.html.md#rx.PeakList) | None = None, two_theta_limits: tuple[float, float] | None = None, k_sigma: float = 3.0, max_classes: int | None = None, refine_cell: bool = False, restrict: [ExtinctionPrior](api-types.html.md#rx.ExtinctionPrior) | dict | None = None, cancel=None) → [ExtinctionScreen](api-types.html.md#rx.ExtinctionScreen)

Rank the extinction classes of a lattice.

<a id="export-and-plots"></a>

## Export and plots

### rx.write_refinement_cif(result: [RefinementResult](#rx.RefinementResult), structure: [Structure](#rx.Structure), instrument: [Instrument](#rx.Instrument), path: str | Path, \*, pattern: [PatternData](#rx.PatternData) | None = None)

Write a refinement CIF: structure, fit and pattern.

### rx.write_qpa_table(qpa: [QuantitativePhaseAnalysis](api-types.html.md#rx.QuantitativePhaseAnalysis), path: str | Path, \*, delimiter: str | None = None)

Write the QPA table to CSV/TSV (delimiter inferred from suffix).

### rx.write_reflection_table(rows: list[[ReflectionRow](api-types.html.md#rx.ReflectionRow)], path: str | Path, \*, delimiter: str | None = None)

Write reflection rows to CSV/TSV (delimiter inferred from suffix).

### rx.reflection_table(model: CompiledModel, values: dict[str, float], structure: [Structure](#rx.Structure)) → list[[ReflectionRow](api-types.html.md#rx.ReflectionRow)]

Reflection rows for every (emission line, reflection) of every phase.

### rx.format_su(value: float, esd: float | None, \*, decimals: int = 6) → str

A number with its standard uncertainty in `value(su)` notation.

#### viz.plot_result(result: [RefinementResult](#rx.RefinementResult), \*, path: str | None = None, two_theta_range: tuple[float, float] | None = None, show_background: bool = True, weighted: bool = False, style: str = 'light', wavelength: float | None = None, x_axis: str = 'two_theta', y_scale: str = 'linear', label_align: str = 'bottom', figsize: tuple[float, float] | None = None, font_size: float = 11.0, dpi: int = 300, title: str | None = None)

Standard Rietveld panel: observed, calculated, difference, tick rows.

#### viz.plot_for_vlm(result: [RefinementResult](#rx.RefinementResult), report=None, \*, path: str, n_regions: int = 4, dpi: int = 140)

Annotated multi-panel montage drawn for a vision-language model to read.

### rietx.viz.html.write_html(result: [RefinementResult](#rx.RefinementResult), path: str, \*, weighted: bool = False, max_points: int | None = None)

Render a `RefinementResult` to a self-contained HTML file.
