qens.models

Top-level imports

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]

Submodules

qens.models.lineshapes

Normalised lineshape primitives.

qens.models.lineshapes.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.lineshapes.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.lineshapes.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.translation

Translational diffusion HWHM models.

qens.models.translation.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.translation.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.translation.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.rotation

Rotational structure-factor models for axially symmetric molecules.

qens.models.rotation.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.rotation.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.rotation.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.rotation.DEFAULT_RADIUS: float = 2.48

default radius of gyration in Å. Override for non-benzene molecules.

qens.models.forward

Full forward model for QENS line shape inference.

qens.models.forward.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.forward.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.registry

Forward-model registry.

qens.models.registry.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.registry.get_model(name)[source]

Look up a forward model by name.

Raises KeyError if not registered.

Return type:

ForwardModel

Parameters:

name (str)

qens.models.registry.available_models()[source]

Return the list of currently-registered model names.

Return type:

list[str]