Python API Reference
The nereids Python package is a PyO3 layer over the Rust pipeline. This
page is a curated narrative reference covering the typed APIs Python users
reach for most often, with argument tables, array-shape contracts, and
dispatch rules.
For the exhaustive auto-generated reference (every function, class, and
attribute exported by the package), see the generated Python API
reference built by pdoc from the
installed wheel and the shipped nereids/__init__.pyi type stubs.
Install the base package with:
pip install nereids
Optional extras are:
pip install "nereids[mcp]" # MCP server console script
pip install "nereids[gui]" # GUI wheel dependency, when available for your platform
Data Objects
ResonanceData
Returned by load_endf(...), load_endf_file(...), and
create_resonance_data(...).
Important properties:
| Property | Type | Meaning |
|---|---|---|
z | int | Atomic number. |
a | int | Mass number. |
awr | float | Atomic weight ratio. |
n_resonances | int | Resonance count across parsed ranges. |
target_spin | float | Target spin from the first evaluable range (parse-and-skip placeholders are skipped). |
scattering_radius | float | Effective scattering radius in fm, from the first evaluable range. |
l_values | list[int] | Orbital angular momentum values present in the data. |
has_unevaluated_ranges | bool | True when the file carries parsed-but-not-evaluated spans (LRF=7 / URR / LRU=0); those spans contribute zero cross-section. |
skipped_ranges | list[str] | One description per parsed-but-not-evaluated span. |
FitResult
Returned by fit_spectrum_typed(...) and fit_counts_spectrum_typed(...).
| Property | Type | Meaning |
|---|---|---|
densities | NDArray[float64] | Fitted areal densities in atoms/barn. |
uncertainties | NDArray[float64] | One-sigma density uncertainties; entries may be NaN when covariance is unavailable. |
reduced_chi_squared | float | Pearson chi-squared per degree of freedom for LM/transmission paths. |
deviance_per_dof | float or None | Primary goodness-of-fit for counts-KL fits. |
converged | bool | Whether the optimizer converged. |
iterations | int | Iteration count. |
temperature_k | float or None | Fitted temperature when fit_temperature=True. |
t0_us, l_scale | float or None | Fitted energy-scale parameters when fit_energy_scale=True. |
InputData
Opaque typed 3D input for spatial mapping. Create it with:
data = nereids.from_transmission(transmission, uncertainty)
data = nereids.from_counts(sample_counts, open_beam_counts)
The spectral axis is always axis 0, so arrays have shape
(n_energy, height, width).
SpatialResult
Returned by spatial_map_typed(...).
| Property | Type | Meaning |
|---|---|---|
density_maps | list[NDArray[float64]] | One (height, width) density map per isotope or isotope group. |
uncertainty_maps | list[NDArray[float64]] | Per-pixel density uncertainty maps. |
chi_squared_map | NDArray[float64] | Per-pixel reduced chi-squared for LM/transmission paths. |
deviance_per_dof_map | NDArray[float64] or None | Primary GOF map for counts-KL spatial fits. |
converged_map | NDArray[bool_] | Per-pixel convergence flags. |
n_converged, n_failed, n_total | int | Pixel fit counts. |
temperature_map | NDArray[float64] or None | Fitted temperature map when enabled. |
temperature_uncertainty_map | NDArray[float64] or None | Per-pixel 1σ temperature uncertainty (K) when fit_temperature=True. Covariance-only lower bound on the raw-count joint-Poisson path: it captures only statistical curvature (inverse Fisher matrix), omits baseline/model noise, and on real data can underestimate the observed per-superpixel scatter by ~3–4×. Pass scale_by_chi2=True for a goodness-of-fit-scaled estimate: σ is multiplied by sqrt of the deviance_per_dof each pixel’s result reports. This inflates σ for an under-fit pixel (D/dof > 1) and, less commonly, shrinks it for an over-fit one (D/dof < 1). The flag is a no-op on the already-χ²-scaled LM transmission path. |
anorm_map, background_maps | NDArray[float64] / list[...] or None | SAMMY Anorm and the polynomial background [BackA, BackB, BackC] per pixel when background=True. |
back_d_map, back_f_map | NDArray[float64] or None | SAMMY exponential background BackD / BackF per pixel when background=True and fit_back_d=True / fit_back_f=True. Counts-KL spatial runs always return None for both (the joint-Poisson dispatch never fits the exponential tail). |
t0_us_map, l_scale_map | NDArray[float64] or None | Energy-scale maps when enabled. |
NexusData
Returned by load_nexus_histogram(...) and load_nexus_events(...).
| Property | Type | Meaning |
|---|---|---|
counts | NDArray[float64] | Counts cube with shape (n_tof, height, width). |
tof_edges_us | NDArray[float64] | TOF bin edges in microseconds, length n_tof + 1. |
flight_path_m | float or None | Flight path from NeXus metadata when available. |
dead_pixels | NDArray[bool_] or None | Dead-pixel mask, True means dead. |
n_rotation_angles | int | Number of rotation angles in histogram input. |
event_total, event_kept | int or None | Event loader statistics. |
ENDF Loading
u238 = nereids.load_endf(92, 238, library="endf8.1")
u238_local = nereids.load_endf_file("examples/data/u238_ex027.endf")
load_endf(...) fetches and caches evaluated nuclear data. Supported library
names include endf8.0, endf8.1, jeff3.3, jendl5, tendl2023, and
cendl3.2. First use can require network access; cached files are reused
afterwards. load_endf_file(...) parses a local ENDF file and does not
download data.
Both loaders evaluate resolved LRF=1/2/3 ranges only. A file with no
evaluable range (for example a pure LRF=7 evaluation such as W-182) raises
ValueError — loading it would yield zero cross-section everywhere. A mixed
evaluation loads, emits a UserWarning naming the skipped spans, and flags
them via has_unevaluated_ranges / skipped_ranges.
Forward Modeling
import numpy as np
import nereids
u238 = nereids.load_endf(92, 238)
energies = np.linspace(1.0, 30.0, 2000)
transmission = nereids.forward_model(
energies,
[(u238, 0.001)],
temperature_k=300.0,
flight_path_m=25.0,
delta_t_us=5.0,
delta_l_m=0.005,
)
forward_model(...) returns a 1D float64 transmission spectrum on the
input energy grid. Pass either isotopes=[(ResonanceData, density), ...] or
groups=[(IsotopeGroup, density), ...], but not both. Gaussian resolution is
enabled by the flight_path_m, delta_t_us, and delta_l_m parameters.
Tabulated resolution can be supplied with resolution=load_resolution(...).
delta_t_us and delta_l_m are W-parameters, the width in
exp(-x^2/W^2), not standard deviations.
The conversions are sigma = W/sqrt(2) and FWHM = 2*sqrt(ln 2)*W = 1.6651*W.
This is SAMMY’s convention, shared with the Doppler width, so the two kernels
compose without a conversion.
A measured 1-sigma timing jitter must be converted before it is passed here;
supplying it unconverted gives a kernel 29 % too narrow, and a resolution that
is too narrow is absorbed into a fitted temperature that is too high.
Two helpers do the conversion, so no one has to scale by hand:
| Function | Converts | Formula |
|---|---|---|
width_from_sigma(sigma) | a standard deviation | W = sigma * sqrt(2) |
width_from_fwhm(fwhm) | a full width at half maximum | W = FWHM / (2*sqrt(ln 2)) |
resolution = nereids.resolution_broaden(
energies,
cross_sections,
flight_path_m=25.0,
delta_t_us=nereids.width_from_sigma(0.5), # 0.5 us measured 1-sigma
delta_l_m=nereids.width_from_sigma(2e-3),
)
width_from_fwhm is also the conversion SAMMY’s Deltag needs, so a timing
width read from a SAMMY .inp can be passed straight through it.
Single-Spectrum Fitting
Transmission Data
result = nereids.fit_spectrum_typed(
transmission,
uncertainty,
energies,
[(u238, 0.0005)],
temperature_k=300.0,
solver="lm",
)
Shape contract:
transmission,uncertainty, andenergiesare 1D arrays with the same length.energiesis in eV and should be ascending.isotopessupplies(ResonanceData, initial_density)pairs.
Keyword arguments:
| Option | Meaning |
|---|---|
temperature_k=293.6 | Sample temperature in kelvin. |
fit_temperature=False | Fit sample temperature in addition to densities. |
max_iter=200 | Maximum optimizer iterations. |
solver="lm" | "lm" (default) or "auto". The count-likelihood names ("kl", "poisson", "joint_poisson") are rejected for normalized transmission — a ratio is not Poisson count data. |
background=False | Enable SAMMY-style transmission background parameters. |
fit_back_d=False, fit_back_f=False | Fit optional exponential background terms. |
back_d_init=0.01, back_f_init=1.0 | Initial exponential background values. |
fit_energy_scale=False | Fit TOF energy-scale parameters t0_us and l_scale. |
t0_init_us=0.0, l_scale_init=1.0 | Initial energy-scale values. |
energy_scale_flight_path_m=25.0 | Nominal flight path for energy-scale fitting. |
resolution=... | Tabulated resolution from load_resolution(...). Mutually exclusive with the Gaussian parameters below — pass either resolution= (tabulated) or the flight_path_m/delta_t_us/delta_l_m trio (Gaussian), never both. |
flight_path_m=..., delta_t_us=..., delta_l_m=... | Gaussian resolution parameters (mutually exclusive with resolution=). |
fit_energy_range=(emin, emax) | Restrict the cost function to an energy window. |
groups=[...] | Fit isotope groups instead of individual isotopes. |
initial_densities=[...] | Initial density guesses when fitting groups. |
tzero_jacobian="..." | Select the TZERO Jacobian implementation. |
Raw Counts
result = nereids.fit_counts_spectrum_typed(
sample_counts,
open_beam_counts,
energies,
[(u238, 0.0005)],
solver="auto",
c=1.0,
)
solver="auto", "kl", "poisson", and "joint_poisson" all route counts
data to the counts-KL dispatch; solver="lm" is rejected because dividing the
count arms into transmission loses count statistics. Use c=Q_s / Q_ob when
sample and open-beam counts have different proton charge or dwell-time
normalization. The primary GOF for this path is FitResult.deviance_per_dof.
Counts fitting accepts the same temperature, background, and group options as transmission fitting.
Resolved Counts (Exact Separate-Arm Response)
Instrument response acts on the open and sample count arms separately: the
detector observes O_i = Σ_j F_j R_ij and S_i = Σ_j F_j T_j R_ij, never a
broadened transmission ratio R[T]. To fit raw counts with an active
resolution, supply the exact-response inputs:
result = nereids.fit_counts_spectrum_typed(
sample_counts, # per measured detector-time bin
open_beam_counts, # per measured detector-time bin
energies, # true-energy quadrature (may differ in length)
[(u238, 0.0005)],
solver="kl",
resolution=response, # TabulatedResolution or IkedaCarpenter
incident_fluence_weights=F, # F_j = w_j * eps(E_j) * Phi(E_j)
detector_time_edges_us=edges, # len(edges) == len(sample_counts) + 1
timing_offset_us=0.0,
)
The true-energy grid and the measured detector-time bins are different axes:
energies drives the physics model while the count arrays live on the
detector clock. two_arm_count_response(...) is the same operator exposed
standalone for synthesizing or checking expected counts (it additionally
reports the per-arm acquisition-window loss). A resolution without the
exact-response inputs still fails closed with a ValueError, and
fit_energy_scale / fit_energy_range are not yet supported through the
exact response (the response clock and the energy axis would disagree).
Counts specific options are:
| Option | Meaning |
|---|---|
detector_background=... | Reserved detector background spectrum; the counts-KL dispatch rejects non-zero values. |
c=1.0 | Proton-charge ratio Q_s / Q_ob. |
enable_polish=True/False/None | Override counts-KL polish behavior; None uses the dispatcher default. |
resolution=..., incident_fluence_weights=..., detector_time_edges_us=..., timing_offset_us=0.0 | Exact separate-arm response inputs (see above). |
The counts-domain alpha_1/alpha_2 nuisance parameters are not fit by
fit_counts_spectrum_typed or spatial_map_typed. Only
compute_model_jacobian retains the alpha parameters, as a research/UQ
surface.
Independently Measured Count Backgrounds
background_fit = nereids.fit_two_arm_background_templates(
observed_open_counts,
observed_sample_counts,
open_signal, # from two_arm_count_response(...)
sample_signal,
open_exposure_scale,
sample_exposure_scale,
["blocked_beam"],
open_background_templates, # 2-D, one row per named component
sample_background_templates,
initial_amplitudes,
open_loss, # the two losses from the same
sample_loss, # two_arm_count_response(...) call
)
Each row of the two template matrices is a fixed detector-bin shape from an independent measurement such as blocked-beam or detector-only data. NEREIDS fits only a non-negative amplitude per component and returns all three pieces for each arm — the fixed neutron signal, the fitted background, and their exact total — so they are never conflated. This count background is added after the instrument response and is not the SAMMY transmission-level background.
The code deliberately does not generate a flexible residual curve, and it cannot establish a template’s provenance: fitting a free curve to the residual it is meant to explain would identify nothing physical, so callers must retain the independent measurement record themselves.
open_exposure_scale and sample_exposure_scale are required. They convert
the common reference neutron signal into expected counts for each complete
acquisition (proton charge, live time, or another documented exposure), so a
run-normalization difference between the arms cannot be absorbed as background.
The scales apply to the neutron signal and its window losses only — templates
are never multiplied by them, so supply each arm’s template already expressed
in that arm’s own exposure. (Supplying a per-unit-exposure template to a
3× exposure arm biases its amplitude by ~50% while the fit still looks only
mildly poor.)
open_window_loss and sample_window_loss are also required: pass the two
losses that two_arm_count_response returned alongside the signals. They are
the acquisition-window disclosure the result carries forward, exposure-scaled;
they are never defaulted, because a default of zero would be a false “no loss”
report.
The returned TwoArmBackgroundFitResult reports whether the amplitudes are
separately determined:
| Attribute | Meaning |
|---|---|
amplitudes, names | Fitted non-negative amplitude per named component. |
amplitudes_identifiable | False when two supplied shapes are linearly dependent. The total background is still valid, but the individual amplitudes are not physically interpretable. |
amplitude_uncertainties | One-sigma values from the expected (Fisher) information of the constrained fit, or None when withheld (the fit did not converge, the amplitudes are not identifiable, or the free block of the information matrix is singular). Free amplitudes are conditioned on any partner held at its bound. An individual entry is NaN when its variance is non-positive or when its template is sensitive on a bin with zero expectation, where the expected information diverges; a reported number is never zero. |
amplitude_at_bound | True where the data pull an amplitude negative and the non-negativity bound holds it at zero. Its reported sigma is then a one-sided curvature scale, not a symmetric interval. |
open_total, sample_total | neutron_signal + background, exactly. |
open_window_loss, sample_window_loss | Expected counts lost outside the acquisition window, exposure-scaled and reported rather than renormalized away. |
poisson_deviance, deviance_per_dof | Goodness of fit. |
n_informative | Bins that contribute to the deviance — the observation, the neutron signal, or at least one template is nonzero there. Bins where all three are exactly zero are excluded from the degrees of freedom. |
Background amplitude estimation is a standalone analysis surface: it is not a
solver route, and the counts-KL dispatch still rejects a non-zero
detector_background (see the option table above).
Spatial Mapping
Pre-Normalized Transmission Cubes
data = nereids.from_transmission(transmission_3d, uncertainty_3d)
result = nereids.spatial_map_typed(
data,
energies,
[u238],
initial_densities=[0.0005],
solver="auto",
)
For from_transmission(...) inputs both solver="lm" (default) and
solver="auto" route to LM; a Poisson/KL count likelihood is rejected for
normalized transmission because the separate open/sample count arms are no
longer available. density_maps[0] is the fitted U-238 map.
Raw Count Cubes
data = nereids.from_counts(sample_counts_3d, open_beam_counts_3d)
result = nereids.spatial_map_typed(
data,
energies,
[u238],
initial_densities=[0.0005],
solver="auto",
c=1.0,
)
solver="auto" uses counts-KL for from_counts(...) data and populates
deviance_per_dof_map.
Shape contract:
sample_counts_3d,open_beam_counts_3d,transmission_3d, anduncertainty_3duse shape(n_energy, height, width).energies.shape == (n_energy,).dead_pixels, when supplied, uses shape(height, width)withTruemarking pixels to skip.
Keyword arguments:
| Option | Meaning |
|---|---|
temperature_k=293.6, fit_temperature=False | Fixed or fitted sample temperature. |
initial_densities=[...] | Initial density guesses. |
dead_pixels=... | (height, width) skip mask. |
max_iter=200 | Maximum per-pixel optimizer iterations. |
solver="auto" | Dispatch from input type unless explicitly set. |
background=False | Enable SAMMY-style background for LM/transmission paths. |
fit_back_d=False, fit_back_f=False | Fit the SAMMY exponential background tail (BackD * exp(-BackF / √E)). Requires background=True. Per-pixel back_d_map / back_f_map are populated on the returned SpatialResult (issue #538). |
back_d_init=0.01, back_f_init=1.0 | Initial values for the exponential tail. |
c=1.0 | Proton-charge ratio for counts-KL spatial fitting. |
enable_polish=True/False/None | Override counts-KL polish behavior; None auto-disables polish for multi-pixel maps. |
fit_energy_scale=False | Fit per-pixel t0_us and l_scale maps. |
t0_init_us=0.0, l_scale_init=1.0 | Initial energy-scale values. |
energy_scale_flight_path_m=25.0 | Nominal flight path for energy-scale fitting. |
resolution=... | Tabulated resolution from load_resolution(...). Mutually exclusive with the Gaussian parameters below — pass either resolution= (tabulated) or the flight_path_m/delta_t_us/delta_l_m trio (Gaussian), never both. Rejected for count cubes: counts input with active resolution fails closed (the exact separate-arm model is single-spectrum only for now) — fit pre-normalized transmission cubes instead. |
flight_path_m=..., delta_t_us=..., delta_l_m=... | Gaussian resolution parameters (mutually exclusive with resolution=; same count-cube rejection applies). |
groups=[...] | Fit isotope groups instead of individual isotopes. |
tzero_jacobian="..." | Select the TZERO Jacobian implementation. |
fit_energy_range=(emin, emax) | Restrict the cost function to an energy window. |
Pixel Masks
Pixel masks exist only to exclude pipeline-corrupting pixels (dead or
hot/railed detector defects). They are not a data-quality or coverage
filter: low-count pixels are alive and must be kept (the KL-domain fitters
handle them), and coverage/thickness inhomogeneity is a model concern, not a
masking concern. Downstream, a masked pixel is hard-excluded — never
fitted, NaN in the result maps. Masks are (height, width) boolean
arrays, True = exclude, and feed directly into
spatial_map(dead_pixels=...).
# Recommended entry point: dead ∪ hot over sample AND open beam.
mask = nereids.detect_bad_pixels(sample, open_beam=open_beam)
# Individual criteria:
dead = nereids.detect_dead_pixels(sample) # exactly zero in every TOF bin
hot = nereids.detect_hot_pixels(sample, k_mad=6.0) # railed/hot point defects
gone = nereids.detect_dead_pixels_chunked([chunk_a, chunk_b]) # intermittent deadness
result = nereids.spatial_map(cube, energies, isotopes, dead_pixels=mask)
detect_bad_pixels(sample, open_beam=None, hot_k_mad=6.0)
Union mask dead(sample) ∪ hot(sample) [∪ dead(ob) ∪ hot(ob)] — deadness
and hotness are per-acquisition, so a mask built from one stack alone misses
failures in the other. This is the validating entry point (rejects
non-finite/negative counts and empty TOF axes with ValueError).
hot_k_mad=None disables the hot screen (dead-only mask).
detect_dead_pixels(data)
Legacy single-stack detector: flags pixels that are exactly 0.0 in every
TOF bin. Assumes counts already validated finite and non-negative; prefer
detect_bad_pixels for new code.
detect_hot_pixels(data, k_mad=6.0)
Two-stage hot/railed screen on raw counts: a global robust cut on log
total counts (median + k_mad · max(1.4826 · MAD, Poisson floor)) nominates
candidates, and a local 8-neighbor confirmation (≥ 10× the neighbors’
median, iterated to a fixpoint) keeps contiguous bright scene regions —
open-beam areas, slit apertures — unmasked while catching isolated point,
line, and small-cluster defects. Pass raw detected counts, not
proton-charge-normalized rates or transmission ratios: scaling breaks the
Poisson floor.
detect_dead_pixels_chunked(chunks)
Intermittent deadness: a pixel dead for part of the acquisition is invisible in a summed stack (uniformly reduced counts, no zeros). Given per-chunk stacks (e.g. per-run splits or event data re-histogrammed in time windows), flags pixels all-zero in any chunk. Chunk so that live pixels expect λ ≥ 20 counts each (false-flag probability ≤ m·e^(−λ)). Spatial dims must match across chunks; the TOF axis may differ.
TIFF and NeXus I/O
stack = nereids.load_tiff_stack("transmission_stack.tif", pixel_policy="allow")
folder_stack, info = nereids.load_tiff_folder(
"frames",
pattern="frame_*.tif",
sum_chunks=True, # sum chunked VENUS runs element-wise (default)
pixel_policy="reject", # "reject" | "clip" | "allow" (default "reject")
return_info=True, # also return the load-provenance dict
)
info["n_chunks"] # DAQ chunks detected (1 if not chunked)
info["chunks_summed"] # True when they were summed element-wise
info["n_clipped_pixels"] # pixels clamped under pixel_policy="clip"
# full key set: n_files, n_chunks, chunk_ids, chunks_summed,
# n_clipped_pixels, chunk_inconsistent, n_unrecognized_files,
# unrecognized_examples
edges_us = nereids.read_tof_sidecar(
"run_764/run_764_Spectra.txt",
n_frames=folder_stack.shape[0],
)
sample = nereids.load_nexus_histogram("sample.nxs")
open_beam = nereids.load_nexus_histogram("open_beam.nxs")
energies = nereids.tof_to_energy_centers(
sample.tof_edges_us,
sample.flight_path_m or 25.0,
)
health = nereids.run_health("sample.nxs") # RunHealth: pause/beam-dip fractions
load_tiff_folder detects chunked VENUS folders
(<prefix>_<chunk>_<frame>.tif) and sums chunks element-wise by default,
emitting a UserWarning naming the summed chunks (and one with the
clipped-pixel count under pixel_policy="clip"); return_info=True
returns the load provenance as a second value. read_tof_sidecar
converts a VENUS *_Spectra.txt sidecar (frame start times in
seconds — the left bin edges, verified on measured autoreduce output)
into the N+1 ascending microsecond TOF bin edges that
tof_to_energy_centers expects. Negative or non-finite pixels are rejected
at load time unless pixel_policy says otherwise. run_health returns a
RunHealth summary of the /entry/DASlogs pause and beam-power logs using
last-value-held time-weighted integration (SNS PV-name defaults).
See Data I/O and NeXus/TOF for ordering and pairing rules, chunk semantics, the pixel-value policy, and run health.
Beam-State Filtering (DASlogs and Event Banks)
Facility NeXus files record slow-control PVs under /entry/DASlogs/<pv> as
transition logs: each value takes effect at its timestamp and persists
until the next entry. Averaging the value array directly is wrong whenever
entries are unevenly spaced — on a real VENUS run the entry-mean of the
pause log read 0.43 while the time-weighted pause fraction was 0.90.
read_run_log(path, pv)
Returns a RunLog with times (seconds since run start), values,
duration_s, offset_iso (ISO-8601 epoch of the clock), and
n_dropped_corrupt — the number of corrupt device-reconnect records
(backward time jumps or subnormal garbage payloads, both seen in real SNS
files) dropped from the log.
intervals_where(times, values, duration_s, min_value=None, max_value=None)
Derives (t_start, t_end) intervals where the PV satisfies the bounds,
under correct step-function semantics: the last value persists to
duration_s (padded one f32 ULP — SNS records duration in float32 while
pulse times are float64, and the final pulse of about half of real runs is
stamped just beyond it), time before the first entry never matches, NaN
never matches, and adjacent segments merge.
intervals_intersect(a, b)
Composes conditions across PVs (e.g. not-paused AND beam power above threshold). Inputs are validated and normalised (sorted, merged).
load_nexus_bank_spectrum(path, bank, n_bins, tof_min_us, tof_max_us, keep_intervals=None)
Loads one NXevent_data bank (e.g. "monitor1") as a BankSpectrum — a 1-D
TOF spectrum (tof_edges_us, counts) with retention statistics
(pulses_total/pulses_kept, events_total/events_kept, drop counters,
pulse_time_offset_iso). With keep_intervals, only pulses whose
event_time_zero falls inside the intervals (half-open, DASlogs clock)
are histogrammed. units attributes are required on both event datasets
(never guess a scale); a bank with zero events loads gracefully to a zero
spectrum — on VENUS every imaging-detector bank is empty because tpx1 is
frame-mode, and only monitors carry events.
pause = nereids.read_run_log("run.nxs.h5", "pause")
live = nereids.intervals_where(
pause.times, pause.values, pause.duration_s, max_value=0.5
)
power = nereids.read_run_log("run.nxs.h5", "BL10:Det:rtdl:BeamPowerAvg")
stable = nereids.intervals_where(
power.times, power.values, power.duration_s, min_value=1.5
)
keep = nereids.intervals_intersect(live, stable)
mon = nereids.load_nexus_bank_spectrum(
"run.nxs.h5", "monitor1",
n_bins=500, tof_min_us=0.0, tof_max_us=16667.0,
keep_intervals=keep,
)
print(mon.pulses_kept, "/", mon.pulses_total, "pulses in stable beam")
Element and Utility APIs
nereids.element_symbol(92) # "U"
nereids.element_name(92) # "Uranium"
nereids.parse_isotope_str("U-238") # (92, 238)
nereids.natural_abundance(92, 238)
nereids.natural_isotopes(26)
nereids.tof_to_energy(tof_us, flight_path_m)
nereids.energy_to_tof(energy_ev, flight_path_m)
How This Page Is Generated
The published docs site renders three things side by side:
| Site path | Source | What it shows |
|---|---|---|
/ (this page) | Hand-maintained docs/guide/src/python-api.md | Curated narrative tour of the typed APIs |
/python/ | pdoc over the installed nereids wheel and nereids/__init__.pyi stubs | Auto-generated exhaustive reference |
/api/ | cargo doc (rustdoc) | Rust crate API reference |
To rebuild the whole site locally:
pixi run doc-build # depends on: doc-guide, doc-api, doc-python
pixi run doc # serves target/book/ at http://localhost:8000
doc-python invokes pdoc -o target/book/python --no-show-source nereids
after pixi run build has produced an importable wheel. Whenever
bindings/python/python/nereids/__init__.pyi or PyO3 docstrings in
bindings/python/src/lib.rs change, both the auto-generated python/
reference and any affected sections of this curated page should be reviewed
in the same PR.
This page does not execute notebooks or compile-test Python snippets. The
Rust quickstart on this site IS compile-tested by cargo check --workspace --examples (see crates/nereids-fitting/examples/quickstart.rs).