API Reference

Config

Configuration dataclass - runtime parameters for the QENS analysis pipeline.

Holds every tunable knob in one place: file lists, Q range, energy window, binning, MCMC settings and output directory.

Save/restore as JSON for reuse.

class qens.config.Config(files_to_fit=<factory>, primary_file='', resolution_file=None, frozen_temp_threshold=270, q_min=0.3, q_max=2.5, energy_window=1.25, n_q_bins=12, n_walkers=32, n_warmup=500, n_keep=2000, thin=5, n_map_starts=30, random_seed=42, save_dir='qens_results')[source]

Bases: object

Runtime parameters for the analysis pipeline.

Parameters:
files_to_fit

Filenames to load (relative to data_dir passed to qens.io.load_dataset()).

Type:

list[str]

primary_file

Which of the loaded files is the target spectrum to fit.

Type:

str

resolution_file

Frozen-sample file used as resolution function. If None, the loader auto-picks any T ≤ frozen_temp_threshold incoherent file.

Type:

str | None

frozen_temp_threshold

Files at T ≤ this temperature (K) are treated as resolution refs.

Type:

int

q_min, q_max

Q range in Å⁻¹ over which the fit is performed.

Type:

float

energy_window

Half-width of the ω window in meV used for the joint fit (paper found ±1.25 meV needed for benzene anisotropy).

Type:

float

n_q_bins

Number of Q-bins for the joint S(Q,ω) fit.

Type:

int

n_walkers

Number of emcee walkers (must be even, ≥ 2 × n_dim).

Type:

int

n_warmup, n_keep

Burn-in and production steps per walker.

Type:

int

thin

Chain thinning factor.

Type:

int

n_map_starts

Random starts for the MAP search.

Type:

int

random_seed

Master seed for reproducibility.

Type:

int

save_dir

Output directory for figures, samples, summaries.

Type:

str

files_to_fit: List[str]
primary_file: str = ''
resolution_file: str | None = None
frozen_temp_threshold: int = 270
q_min: float = 0.3
q_max: float = 2.5
energy_window: float = 1.25
n_q_bins: int = 12
n_walkers: int = 32
n_warmup: int = 500
n_keep: int = 2000
thin: int = 5
n_map_starts: int = 30
random_seed: int = 42
save_dir: str = 'qens_results'
to_dict()[source]
Return type:

dict

to_json(path)[source]
Return type:

None

Parameters:

path (str)

classmethod from_json(path)[source]
Return type:

Config

Parameters:

path (str)

Fitting

Inference primitives: likelihood, prior, MAP search, plus utilities to bin the data and build per Q bin resolution kernels.

qens.fitting.build_data_bins(d, cfg=None)[source]

Bin a dataset into “n_q_bins “ equal occupancy Q-bins.

Parameters:
  • d (dict) –

    A processed dataset dict (must already have “e “, “good “, “q “,

    ”data “, “errs “).

  • cfg (Config)

Return type:

list[tuple[ndarray, ndarray, ndarray, float]]

Returns:

  • list of “(omega, spec, errs, q_centre) “ tuples — one per Q-bin —

  • where “omega “ is restricted to ±cfg.energy_window and “q_centre “

  • is the mean Q of the detectors in the bin.

qens.fitting.build_resolution_bins(d_ref, cfg=None, q_centres=None)[source]

Build a measured per Q bin resolution kernel from a frozen sample.

For each Q bin in the data, average the frozen sample spectra at detectors with similar Q to produce a measured resolution function. Use this kernel inside the forward model, it captures the Lorentzian wings of the real instrument that a pure Gaussian fit misses.

Parameters:
  • d_ref (dict) – Resolution reference dataset (typically the frozen low T inc file). Must already have “e “, “good “, “q “, “data “.

  • cfg (Config)

  • q_centres (array, optional) – If given, build kernels at these Q centres instead of percentile bins. Useful when matching the binning of a different (target) dataset.

Return type:

list[ndarray]

Returns:

qens.fitting.extract_hwhm(d, cfg=None)[source]

Fit “elastic + Lorentzian + bg “ independently in each Q-bin.

Parameters:
Return type:

tuple[ndarray, ndarray, ndarray, ndarray]

Returns:

  • q_centres, hwhm, hwhm_err, eisf (1D arrays of length n_qbins (or fewer)

  • if some bins fail to fit).

qens.fitting.save_hwhm_csv(q_centres, hwhm, hwhm_err, eisf, save_dir)[source]

Write the HWHM table to “<save_dir>/hwhm_table.csv “.

Return type:

str

Parameters:
qens.fitting.log_likelihood(params, data_bins, sigma_res, model='anisotropic_rotor', **extras)[source]

Joint X^2 log-likelihood across all Q-bins.

For each bin a 2 column NNLS fits “[overall_amp, flat_bg] “, so the physics determined Bessel weight ratios inside the forward model are preserved as a global Q-constraint.

Parameters:
  • params (array) – Parameter vector matching the registered model.

  • data_bins (list of (omega, spec, errs, q)) – From build_data_bins().

  • sigma_res (float | array | list[array]) – Resolution: scalar Gaussian , single measured kernel, or one kernel per Q-bin (list of arrays).

  • model (str) – Name of a registered forward model. Default “”anisotropic_rotor” “.

  • extras – Forwarded to the model’s “predict “ callable.

Return type:

float

qens.fitting.log_prior(params, model='anisotropic_rotor')[source]

Log-prior: 0 inside the registered model’s prior box, “-inf “ outside.

Return type:

float

Parameters:
qens.fitting.log_posterior(params, data_bins, sigma_res, model='anisotropic_rotor', **extras)[source]

Convenience wrapper: prior + likelihood.

Return type:

float

Parameters:

model (str)

qens.fitting.find_map(data_bins, sigma_res, model='anisotropic_rotor', cfg=None, n_starts=None, verbose=True, **extras)[source]

Maximum- a posteriori search via Nelder Mead from random starts.

Parameters:
  • data_bins (list)

  • sigma_res (float | array | list[array])

  • model (str) – Name of a registered forward model.

  • cfg (Config)

  • n_starts (int, optional) – Random starts. If None uses “cfg.n_map_starts “.

  • verbose (bool)

  • extras – Forwarded to the model’s “predict “ callable.

Return type:

tuple[ndarray, float]

Returns:

(params_map, neg_logp) ((ndarray, float))

Models

Physical models for QENS line shape analysis.

This subpackage is structured so that:

qens.models.lineshapes provides the building blocks

(Lorentzian, Gaussian).

qens.models.translation contains models for translational

diffusion (Fickian, Chudley-Elliott, Singwi-Sjölander).

qens.models.rotation contains models for rotational diffusion

(isotropic and anisotropic axial rotor).

qens.models.forward assembles a full forward model

S(Q,ω) = exp(-Q²<u²>/3) · [translation x rotation] x resolution.

qens.models.registry lets users register their own forward

models without touching the core code.

For a typical user, from qens.models import predict_sqw is enough.

qens.models.lorentz(omega, gamma)[source]

Area normalised Lorentzian, half-width-at-half-maximum gamma.

\[L(\omega; \Gamma) = \frac{1}{\pi} \frac{\Gamma}{\omega^2 + \Gamma^2}\]
Parameters:
  • omega (array) – Energy-transfer grid (any unit; HWHM gamma must match).

  • gamma (float) – HWHM. Will be clipped to GAMMA_FLOOR if smaller, to avoid producing a δ-function and breaking later FFT-convolutions.

Return type:

ndarray

qens.models.gnorm(omega, sigma)[source]

Area-normalised Gaussian with standard deviation sigma.

\[G(\omega; \sigma) = \frac{1}{\sigma\sqrt{2\pi}} \exp\!\left( -\frac{\omega^2}{2\sigma^2} \right)\]

For FWHM use sigma = FWHM / 2.355.

Return type:

ndarray

Parameters:
qens.models.lorentz_sum(omega, weights, gammas)[source]

Weighted sum of Lorentzians: Σ w_i L(ω; Γ_i).

Vectorised — useful for evaluating multi-channel rotational models on a Q-grid efficiently.

Parameters:
  • omega (array, shape (N,))

  • weights (array, shape (M,))

  • gammas (array, shape (M,))

Return type:

ndarray

Returns:

array, shape (N,)

qens.models.fickian_hwhm(q, d)[source]

Fickian (continuum) diffusion: Γ = ℏ D Q².

Parameters:
  • q (array) – Momentum transfer in Å⁻¹.

  • d (float) – Self-diffusion coefficient in Ų/ps.

Return type:

ndarray

Returns:

Γ in meV.

qens.models.ce_hwhm(q, d, ell)[source]

Chudley-Elliott jump-diffusion HWHM in meV.

Parameters:
  • q (array)

  • d (float) – Self-diffusion coefficient in Ų/ps.

  • ell (float) – Mean jump length in Å.

Return type:

ndarray

Returns:

Γ in meV.

qens.models.ss_hwhm(q, d, tau_s)[source]

Singwi-Sjölander HWHM: Γ = ℏ D Q² / (1 + D Q² τ_s).

Parameters:
  • q (array)

  • d (float) – Self-diffusion coefficient in Ų/ps.

  • tau_s (float) – Residence time in ps.

Return type:

ndarray

Returns:

Γ in meV.

qens.models.rot_widths_isotropic(d_r)[source]

HWHMs for the isotropic axial-rotor model.

Returns “(Γ_1, Γ_2)” in meV, the widths of the l = 1 and l = 2 Lorentzian channels:

\[\Gamma_1 = 2 \hbar D_r,\quad \Gamma_2 = 6 \hbar D_r\]
Parameters:

d_r (float) – Rotational diffusion coefficient in ps⁻¹.

Return type:

tuple[float, float]

qens.models.rot_widths_anisotropic(d_t, d_s)[source]

HWHMs for the anisotropic axial-rotor model (oblate top, e.g. benzene).

Returns (Γ_1, Γ_2, Γ_3)” in meV

Parameters:
  • d_t (float) – Tumbling rotational diffusion coefficient in ps⁻¹.

  • d_s (float) – Spinning rotational diffusion coefficient in ps⁻¹.

Return type:

tuple[float, float, float]

qens.models.bessel_weights(q, R=2.48)[source]

Spherical-Bessel weights “(j₀², j₁², j₂²)” at this Q.

These weight the l = 0, 1, 2 channels of the rotational structure factor. “j₀²(QR)” is the elastic-rotational weight (the EISF in the rotation-only limit). At low Q, j₀² → 1; at high Q it falls off and j₂² dominates.

Parameters:
  • q (float) – Momentum transfer in Å⁻¹.

  • R (float) – Radius of gyration in Å. Defaults to 2.48 Å (benzene).

Return type:

tuple[float, float, float]

Returns:

(j0², j1², j2²)

qens.models.predict_sqw(omega, q, *, d_translation, u2, rotation, rotation_model='anisotropic', sigma_res, radius=2.48)[source]

Predict the resolution-convolved S_inc(Q, ω) for one Q-bin.

Parameters:
  • omega (array, shape (N,)) – Energy grid in meV. Must be uniformly spaced.

  • q (float) – Momentum transfer in Å⁻¹.

  • d_translation (float) – Translational self-diffusion coefficient D* in Ų/ps.

  • u2 (float) – Mean-square displacement ⟨u²⟩ in Ų (Debye-Waller factor).

  • rotation (tuple) – “(D_r,)” for isotropic, “(D_t, D_s)” for anisotropic. Both in ps⁻¹.

  • rotation_model (str) – “”isotropic”” or “”anisotropic””.

  • sigma_res (float or array) – Resolution: Gaussian sigma in meV (scalar) or measured kernel (1-d array same length as “omega”).

  • radius (float) – Radius of gyration in Å. Default 2.48 (benzene).

Return type:

ndarray

Returns:

array, shape (N,) – Predicted shape, unscaled — the inference layer fits an overall amplitude and a flat background per Q-bin via NNLS, so this function only encodes the physics.

class qens.models.ForwardModel(name, param_names, prior_lo, prior_hi, predict, extras=None)[source]

Bases: object

Encapsulates a forward-model definition for the inference layer.

A ForwardModel knows:

its name (for logging) the parameter names (in order) the prior box (uniform, “[lo, hi]” per parameter) how to predict S(Q,ω) for one Q-bin given a parameter vector

Custom forward models register here (see qens.models.registry).

Parameters:
name
Type:

str

param_names
Type:

tuple[str, …]

prior_lo, prior_hi

Uniform-prior bounds, same length as “param_names”.

Type:

tuple[float, …]

predict

“predict(omega, q, params, sigma_res, **extras) -> array”.

Type:

callable

extras

Extra keyword arguments forwarded to “predict” (e.g. “radius”).

Type:

dict

name: str
param_names: tuple[str, ...]
prior_lo: tuple[float, ...]
prior_hi: tuple[float, ...]
predict: Callable[[...], ndarray]
extras: dict = None
property n_params: int
in_prior(params)[source]

True iff every parameter is inside its uniform-prior box.

Return type:

bool

Parameters:

params (ndarray)

random_in_prior(rng)[source]

Draw a single random parameter vector from the prior box.

Return type:

ndarray

Parameters:

rng (Generator)

qens.models.register_model(name, *, param_names, prior_lo, prior_hi, predict, extras=None, overwrite=False)[source]

Add a new forward model to the registry, or replace an existing one.

Parameters:
  • name (str) – Identifier used everywhere (in qens.fitting.find_map(), qens.sampling.run_mcmc(), etc.).

  • param_names (tuples) – Same length. Defines a uniform prior box.

  • prior_lo (tuples) – Same length. Defines a uniform prior box.

  • prior_hi (tuples) – Same length. Defines a uniform prior box.

  • predict (callable) – predict(omega, q, params, sigma_res, **extras) -> array.

  • extras (dict, optional) – Extra kwargs passed to predict (e.g. radius for a rotor).

  • overwrite (bool) – Required to overwrite an existing model.

Return type:

ForwardModel

Returns:

The registered ForwardModel instance.

qens.models.get_model(name)[source]

Look up a forward model by name.

Raises KeyError if not registered.

Return type:

ForwardModel

Parameters:

name (str)

qens.models.available_models()[source]

Return the list of currently-registered model names.

Return type:

list[str]