Python API

The Python package returns float64 and complex128 results; double-double values are available from Rust (Rust API). Both APIs follow the Conventions.

scatrs

scatrs: fast, linearized, rigorously validated single-scattering calculations.

scatrs.__version__: str

The installed package’s version: the version of the Rust workspace, in PEP 440 form (the pre-release 0.1.0-alpha.1, for example, is 0.1.0a1).

The package also re-exports the exceptions of scatrs.errors and the modules scatrs.mie, scatrs.layered, scatrs.tmatrix, scatrs.ensemble, scatrs.particles, scatrs.refractive, scatrs.size and scatrs.special. The classes below are defined in scatrs.particles, scatrs.size and scatrs.ensemble, and used from the top level.

Particles, ensembles and mixtures

Particles: what an Ensemble is made of.

class scatrs.Sphere(refractive_index)

A homogeneous sphere (Lorenz–Mie).

refractive_index is a scatrs.refractive model; a number becomes Constant and any other callable Function.

Raises:
TypeError

For anything else, including arrays: an array of m means something only together with its wavelengths, which Table holds.

refractive_index
class scatrs.LayeredSphere(refractive_index, radius_fraction=())

A layered sphere: a core and concentric shells (see scatrs.layered).

In an Ensemble the size distribution gives the outer radius, and each interface stays at a fixed fraction of it. The core’s volume fraction is the cube of its radius fraction: a core of a quarter of the particle’s volume has radius_fraction=[0.25 ** (1 / 3)].

Parameters:
refractive_indexsequence

Each layer’s refractive index, the core first: scatrs.refractive models, numbers (Constant) or other callables (Function), as for Sphere. Stored as a tuple.

radius_fractionsequence of float

The outer radius of each layer but the last, as a fraction of the particle’s radius: L − 1 values, nondecreasing in (0, 1] (empty for one layer). Stored as a tuple.

Raises:
TypeError

If refractive_index is not a sequence of models, numbers or callables, or radius_fraction not a sequence of real numbers.

ValueError

If there is no layer, or the fractions are not L − 1 values nondecreasing in (0, 1].

refractive_index
radius_fraction = ()
classmethod coated(core, shell, *, core_fraction)

A core of refractive index core in a shell of shell, the core’s radius core_fraction of the particle’s.

property layers

The number of layers L.

class scatrs.Spheroid(refractive_index, aspect_ratio)

Randomly oriented spheroids of one aspect ratio (see scatrs.tmatrix).

A spheroid has semi-axes a, a, c, c along its axis of symmetry, and aspect ratio aspect_ratio = a / c: oblate above 1, prolate below 1, a sphere at 1. In an Ensemble the size distribution gives the radius of the sphere of equal volume, and its cross sections are per particle, as for spheres. Each size node solves a T-matrix, which costs milliseconds to seconds rather than the microseconds of a sphere (see Ensembles).

Parameters:
refractive_index

A scatrs.refractive model; a number becomes Constant and any other callable Function, as for Sphere.

aspect_ratiofloat

a/c, finite and positive.

Raises:
TypeError

If refractive_index is not a model, number or callable, or aspect_ratio not a real number.

ValueError

If aspect_ratio is not finite and positive.

refractive_index
aspect_ratio
class scatrs.Ensemble(particle, size)

Particles of one kind over a size distribution.

Parameters:
particleSphere, LayeredSphere or Spheroid

The particle, with its refractive-index models.

sizeLogNormal, Gamma, ModifiedGamma, PowerLaw, Monodisperse, Tabulated, MultiModal or list

The number size distribution of the particle’s radius (of a layered sphere’s outer radius, its interfaces at fixed fractions of it; of a spheroid’s equal-volume radius). If its parameters are arrays, the ensemble is a grid of distributions, one per point of their broadcast shape. A list (or tuple) of distributions with scalar parameters, of any kinds, is a batch with one axis, one point per distribution; it is stored as a tuple.

Raises:
TypeError

If particle is not a Sphere, a LayeredSphere or a Spheroid, or size or an element of a list not a distribution.

ValueError

If the distribution’s array-valued parameters do not broadcast together, or an element of a list is a grid.

particle
size
property grid_shape

The shape of the grid of distributions: () if no parameter is an array, and (len(size),) for a list.

compute(wavelength, *, greek=None, mu=None, normalized=True, derivatives=False, rtol=1e-06, max_panels=4096, allow_unvalidated=False, refine_backscatter=False)

Averages over the ensemble at each wavelength.

Parameters:
wavelengtharray_like

Wavelengths, in the unit of the radii (real, scalar or any shape).

greekint, “all” or None, optional

The Greek coefficients to compute: up to this order, every order, or none (the default).

muarray_like, optional

Cosines of the scattering angle at which to compute the phase matrix.

normalizedbool, optional

Normalize the phase matrix and the Greek coefficients (alpha1[..., 0] = 1, the default) or give them per particle (alpha1[..., 0] = c_sca).

derivativesbool or sequence of str, optional

The parameters to differentiate with respect to (True for all): the distribution’s ("median_radius", …; "mode{j}.<name>" and "mode{j}.weight" for a multimodal one), then the particle’s: "m_real" and "m_imag" (Re m and Im m at each wavelength) of a Sphere; "layer{l}.m_real" and "layer{l}.m_imag" of each layer of a LayeredSphere, then "layer{l}.radius_fraction" of each layer but the last (at a fixed outer radius); "m_real", "m_imag" and "aspect_ratio" of a Spheroid (at a fixed equal-volume radius). Not available for a grid or a list. A LayeredSphere’s derivatives along its own parameters, and a monodisperse one’s radius derivative, are validated up to an outer size parameter of 1000.

rtolfloat, optional

Relative tolerance of the size integration, in [1e-13, 0.1].

max_panelsint, optional

The most size panels per wavelength (shared by the points of a grid or a list); reaching it sets converged to False.

allow_unvalidatedbool, optional

Compute sizes outside the validated domain of the Mie solution instead of raising.

refine_backscatterbool, optional

Also refine on c_back (to rtol of the larger of c_back and c_sca), which makes its error estimate, and the lidar ratio’s, a calibrated bound. Off by default: the backscattering of weakly absorbing spheres is a sum of narrow glory ripples that can take far more size panels than the cross sections.

Returns:
EnsembleResult

Every array of shape grid + wavelength.shape (grid is grid_shape). The points of a grid or a list share their size nodes and each meets its own rtol: being at least as refined as on its own, a point’s values differ from those of its own ensemble within the error estimates.

Raises:
InvalidInputError

For invalid distribution parameters, wavelengths, refractive indices (including a model with no valid value at a wavelength) or options, or outputs that would exceed 2 * MAX_MIE_VALUES real values (the bound of scatrs.mie; with greek="all", known only after the computation).

OutsideValidatedDomainError

If a size node is outside the validated domain, unless allow_unvalidated; the message names the wavelength and the radius.

TypeError, ValueError

For arguments of the wrong type, or unknown or repeated parameter names.

NotImplementedError

For derivatives of a grid or a list.

BufferError

If another rust-numpy extension holds a writeable borrow of an input.

MemoryError

If the outputs cannot be allocated.

Notes

The cost grows with the size parameters and with the order of the Greek coefficients (see Limitations and known issues). The call releases the GIL, so other Python threads keep running, but it cannot be interrupted: Ctrl+C takes effect only once it returns.

class scatrs.Mixture(components)

An external mixture: ensembles with relative number concentrations.

Cross sections and moments are averaged with the number fractions wᵢ/Σw, phase matrices with wᵢ times the c_sca of ensemble i.

Parameters:
componentssequence of (float, Ensemble)

The weights wᵢ ≥ 0 (finite, not all zero) and the ensembles, each of one distribution (not a grid or a list).

Raises:
TypeError

If a component is not a (weight, Ensemble) pair, or a weight not a real number.

ValueError

If an ensemble is a grid or a list.

components
compute(wavelength, *, greek=None, mu=None, normalized=True, derivatives=False, rtol=1e-06, max_panels=4096, allow_unvalidated=False, refine_backscatter=False)

Averages over the mixture at each wavelength.

Parameters:
wavelengtharray_like

Wavelengths, in the unit of the radii (real, scalar or any shape).

greekint, “all” or None, optional

The Greek coefficients to compute: up to this order, every order, or none (the default).

muarray_like, optional

Cosines of the scattering angle at which to compute the phase matrix.

normalizedbool, optional

Normalize the phase matrix and the Greek coefficients (alpha1[..., 0] = 1, the default) or give them per particle (alpha1[..., 0] = c_sca).

derivativesbool or sequence of str, optional

The parameters to differentiate with respect to (True for all): each component’s distribution and particle parameters (as for Ensemble.compute()), prefixed by "c{i}.", and the weights "c{i}.weight".

rtolfloat, optional

Relative tolerance of the size integration, in [1e-13, 0.1].

max_panelsint, optional

The most size panels per component and wavelength; reaching it sets converged to False.

allow_unvalidatedbool, optional

Compute sizes outside the validated domain of the Mie solution instead of raising.

refine_backscatterbool, optional

Also refine on c_back (to rtol of the larger of c_back and c_sca), which makes its error estimate, and the lidar ratio’s, a calibrated bound. Off by default: the backscattering of weakly absorbing spheres is a sum of narrow glory ripples that can take far more size panels than the cross sections.

Returns:
EnsembleResult

Every array of the wavelengths’ shape (refractive_index is a tuple of each component’s).

Raises:
InvalidInputError

For invalid distribution parameters, wavelengths, refractive indices (including a model with no valid value at a wavelength) or options, or outputs that would exceed 2 * MAX_MIE_VALUES real values (the bound of scatrs.mie; with greek="all", known only after the computation).

OutsideValidatedDomainError

If a size node is outside the validated domain, unless allow_unvalidated; the message names the wavelength and the radius.

TypeError, ValueError

For arguments of the wrong type, or unknown or repeated parameter names.

BufferError

If another rust-numpy extension holds a writeable borrow of an input.

MemoryError

If the outputs cannot be allocated.

Notes

The cost grows with the size parameters and with the order of the Greek coefficients (see Limitations and known issues). The call releases the GIL, so other Python threads keep running, but it cannot be interrupted: Ctrl+C takes effect only once it returns.

Size distributions

Number size distributions of particles.

Radii are in any length unit, the unit of the wavelengths they are computed with. Every numeric parameter may be an array: the parameters of a distribution broadcast together into a grid of distributions, which scatrs.Ensemble.compute() computes at once (see Ensembles). Arrays are copied and stored read-only, so distributions are immutable values that compare and hash by their parameters.

class scatrs.LogNormal(median_radius, width)

n(r) ∝ exp(−(ln r − ln r_g)²/(2 ln²σ_g))/r: median_radius r_g > 0, width σ_g > 1.

median_radius
width
class scatrs.Gamma(effective_radius, effective_variance)

Hansen & Travis’s gamma distribution, n(r) ∝ r^((1−3b)/b) exp(−r/(ab)): effective_radius a > 0, effective_variance 0 < b < 1/2.

effective_radius
effective_variance
class scatrs.ModifiedGamma(alpha, b, gamma)

Deirmendjian’s modified gamma distribution, n(r) ∝ r^α exp(−b r^γ): alpha > −1, b > 0, gamma > 0.

alpha
b
gamma
class scatrs.PowerLaw(exponent, min_radius, max_radius)

n(r) ∝ r^(−α) on [min_radius, max_radius]: exponent α (the limits are not differentiable).

exponent
min_radius
max_radius
class scatrs.Monodisperse(radius)

Spheres of one radius.

radius
class scatrs.Tabulated(radius, density)

n(r) linear between the points (radius[i], density[i]) and 0 outside: radii increasing, densities ≥ 0. The table is data, not parameters: it is neither differentiated nor broadcast into a grid.

radius
density
class scatrs.MultiModal(modes)

Σⱼ wⱼ nⱼ(r), each mode normalized: modes is a sequence of (weight wⱼ > 0, mode). The modes’ parameters are named "mode{j}.<name>", their weights "mode{j}.weight".

modes

Results

class scatrs.EnsembleResult(c_ext, c_sca, c_abs, c_back, ssa, g, lidar_ratio, depolarization, effective_radius, mean_area, mean_volume, greek=None, phase=None, *, error, converged, panels, wavelength, refractive_index, grid, params=(), _d=(), _d_errors=())

EnsembleOutputs with their error estimates and derivatives.

Attributes:
errorEnsembleOutputs

Non-negative error estimates of every output (see Internal validation).

convergednumpy.ndarray

bool per point: whether every refined quantity met rtol within max_panels panels.

panelsnumpy.ndarray

int64 per point: the number of size panels (shared by the points of a grid).

paramstuple of str

The parameters d() accepts.

wavelengthnumpy.ndarray

The wavelengths, as given.

refractive_indexnumpy.ndarray or tuple of numpy.ndarray

m at the wavelengths: of the wavelengths’ shape for a Sphere or a Spheroid, and (L,) + wavelength.shape for a LayeredSphere of L layers; for a Mixture, a tuple of each component’s.

gridMapping[str, numpy.ndarray]

Each array-valued distribution parameter, by name (as in params), broadcast to the grid’s shape; empty if there is no grid.

error
converged
panels
wavelength
refractive_index
grid
params = ()
d(param)

The derivatives with respect to param.

Raises:
ValueError

If the derivative was not requested.

d_error(param)

The error estimates of the derivatives with respect to param.

Raises:
ValueError

If the derivative was not requested.

class scatrs.EnsembleOutputs(c_ext, c_sca, c_abs, c_back, ssa, g, lidar_ratio, depolarization, effective_radius, mean_area, mean_volume, greek=None, phase=None)

The outputs of an ensemble (or their error estimates, or their derivatives with respect to one parameter), each an array of shape grid + wavelength.shape.

Attributes:
c_ext, c_sca, c_abs, c_backnumpy.ndarray

Number-averaged cross sections per particle; c_back is Bohren & Huffman’s backscattering cross section (4π times dσ/dΩ at 180°).

ssa, gnumpy.ndarray

Single-scattering albedo and asymmetry parameter.

lidar_ratio, depolarizationnumpy.ndarray

4π c_ext/c_back, and the linear depolarization ratio (F₁₁ − F₂₂)/(F₁₁ + F₂₂) at 180° (exactly 0 for spheres).

effective_radius, mean_area, mean_volumenumpy.ndarray

⟨r³⟩/⟨r²⟩, ⟨πr²⟩ and ⟨4πr³/3⟩.

greekEnsembleGreek or None

The Greek coefficients, if requested.

phaseEnsemblePhase or None

The phase matrix, if requested.

c_ext
c_sca
c_abs
c_back
ssa
g
lidar_ratio
depolarization
effective_radius
mean_area
mean_volume
greek = None
phase = None
class scatrs.EnsembleGreek(alpha1, alpha2, alpha3, alpha4, beta1, beta2)

Greek coefficients per wavelength, arrays of shape wavelength.shape + (L + 1,) (after the grid’s axes), zero-padded to the largest order (see scatrs.mie.MieGreek for the expansion).

alpha1
alpha2
alpha3
alpha4
beta1
beta2
class scatrs.EnsemblePhase(f11, f12, f22, f33, f34, f44)

The phase matrix per wavelength at the cosines mu, arrays of shape wavelength.shape + mu.shape (after the grid’s axes): its six independent elements, with f22 equal to f11 and f44 to f33 for spheres and layered spheres.

f11
f12
f22
f33
f34
f44
scatrs.ensemble.SCALARS = ('c_ext', 'c_sca', 'c_abs', 'c_back', 'ssa', 'g', 'lidar_ratio', 'depolarization', 'effective_radius', 'mean_area', 'mean_volume')

The scalar outputs of EnsembleOutputs, in order.

scatrs.ensemble

Ensembles of particles: size distributions, adaptive size integration and mixtures.

An Ensemble is a particle (Sphere, LayeredSphere or Spheroid) and a size distribution (scatrs.size) of its radius (a layered sphere’s outer radius, a spheroid’s equal-volume radius); a Mixture is several ensembles with relative number concentrations. Their compute methods average the optical properties over the sizes at each wavelength. Radii and wavelengths are in the same (any) unit; cross sections are per particle, averaged over the number distribution, in that unit squared. See Ensembles for the method and the error estimates.

The size integral is adaptive (Gauss–Kronrod panels in ln r, refined until the cross sections, g and the distribution moments, and optionally the backscattering, meet rtol). Every output comes with an error estimate (error) and, with derivatives, its derivatives with respect to the distribution parameters, the particle’s ("m_real" and "m_imag"; each layer’s "layer{l}.m_real", "layer{l}.m_imag" and "layer{l}.radius_fraction"; a spheroid’s "aspect_ratio") and the mixture weights (d()).

A distribution whose parameters are arrays is a grid of distributions, computed at once with shared size nodes (as an optics table needs): the results have the grid’s axes first.

Each call runs in Rust with the GIL released, in parallel over wavelengths and size panels; results are bitwise the same for any number of threads. Results are frozen dataclasses of read-only arrays.

scatrs.refractive

Refractive-index models: m(λ) = n + ik relative to the surrounding medium.

Im m ≥ 0 means absorbing (see Conventions); codes that write m = n − ik need the complex conjugate. Wavelengths are in the unit of the particle’s radii, and so are the coefficients of Cauchy and Sellmeier: published coefficients usually assume micrometres. A model evaluated at a wavelength where it has no valid value raises InvalidInputError naming that wavelength; there is no extrapolation.

Every model names its differentiable parameters (RefractiveIndex.parameters) and gives ∂m/∂θ for each (RefractiveIndex.derivatives()).

class scatrs.refractive.Cauchy(A, B=0.0, C=0.0, k=0.0)

n = A + B/λ² + C/λ⁴ and Im m = k. Parameters "A", "B", "C", "k".

A
B = 0.0
C = 0.0
k = 0.0
property parameters

The names of the differentiable parameters, in the order of derivatives().

class scatrs.refractive.Constant(m)

m at every wavelength. Parameters "n" = Re m and "k" = Im m.

m
property parameters

The names of the differentiable parameters, in the order of derivatives().

class scatrs.refractive.Function(f)

m = f(wavelength) for any callable f that takes a float64 array and returns m of its shape. No parameters; compares by identity.

f
class scatrs.refractive.RefractiveIndex

A refractive-index model m(λ): the base class of the models in this module.

evaluate() gives m at any wavelengths, parameters names the model’s differentiable parameters and derivatives() gives ∂m/∂θ for each. Subclassing is not a supported way to add a model; for a custom m(λ) wrap a callable in Function.

property parameters

The names of the differentiable parameters, in the order of derivatives().

evaluate(wavelength)

m at wavelength (real, any shape), of the wavelengths’ shape.

Raises:
InvalidInputError

If a wavelength is not finite and positive, or m is not a finite complex array of the wavelengths’ shape with Im m ≥ 0, naming the first wavelength where it fails.

derivatives(wavelength)

∂m/∂θ at wavelength for each parameter θ of parameters, of shape (len(parameters),) + wavelength.shape.

Raises:
InvalidInputError

If a wavelength is not finite and positive, a model such as Sellmeier has no valid value there, or a derivative is not finite, naming the parameter and the first wavelength where it fails.

class scatrs.refractive.Sellmeier(B, C, k=0.0)

n² = 1 + Σᵢ Bᵢλ²/(λ² − Cᵢ) and Im m = k, for sequences B and C of the same length. Parameters "B0", …, "C0", …, "k". Evaluating it where n² ≤ 0 (at or between poles, where the law does not describe the material) raises.

B
C
k = 0.0
property parameters

The names of the differentiable parameters, in the order of derivatives().

class scatrs.refractive.Table(wavelength, m, interpolation='linear')

m tabulated at increasing wavelength (at least two), interpolated between them.

interpolation="linear" interpolates Re m and Im m linearly in λ; "log_k" interpolates ln Im m instead, for absorption spanning decades, and needs Im m > 0 at every node. The table is data: there are no parameters.

wavelength
m
interpolation = 'linear'

scatrs.mie

Lorenz–Mie scattering by homogeneous spheres (vectorized wrappers over the Rust core).

The size parameters x and refractive indices m broadcast against each other to a shape S; every result has that shape, extended by the orders or the angles. Conventions are those of Bohren & Huffman (1983): time dependence e^(−iωt), so absorbing media have Im m >= 0, and x = 2 pi r / wavelength. See Homogeneous spheres (Lorenz–Mie) for the method and Internal validation for the validated domain and the accuracy.

Each function runs entirely in Rust, with the GIL released, over all elements in turn. derivatives is True (all of "x", "m_real", "m_imag") or a sequence of those names; the result’s d method (for example MieEfficiencies.d()) then returns the derivative with respect to one of them, in the same structure. Derivatives cost less than finite differences would: all three together take 1.2 to 2.3 times as long as the values alone.

Results are frozen dataclasses of read-only arrays (copy an array to modify it); they compare by identity.

scatrs.mie.MAX_GREEK_ORDER = 2097152

The largest order greek() accepts: 2**21, twice MAX_MIE_ORDER.

scatrs.mie.MAX_MIE_ORDER = 1048576

The largest number of terms accepted: 2**20.

scatrs.mie.MAX_MIE_VALUES = 134217728

The most complex values one call returns, counting derivatives: 2**27 (2 GiB); twice as many real values for efficiencies(), phase_matrix() and greek().

scatrs.mie.PARAMETERS = ('x', 'm_real', 'm_imag')

The parameters derivatives may name.

class scatrs.mie.MieAmplitudes(s1, s2, params=(), _derivatives=None)

Amplitude scattering functions S₁(μ), S₂(μ), arrays of shape S + mu.shape.

Attributes:
s1, s2numpy.ndarray

complex128 (Bohren & Huffman 1983, Eq. 4.74).

paramstuple of str

The parameters d() accepts.

s1
s2
params = ()
d(param)

The derivatives with respect to param: "x", "m_real", "m_imag", or "m" for the complex derivative d/dm.

Raises:
ValueError

If the derivative was not requested.

class scatrs.mie.MieCoefficients(a, b, n_terms, params=(), _derivatives=None)

Mie coefficients aₙ, bₙ of spheres, arrays of shape S + (N,), with N the largest number of terms of any sphere; a[..., n - 1] is aₙ, zero beyond each sphere’s n_terms.

Attributes:
a, bnumpy.ndarray

complex128.

n_termsnumpy.ndarray

int64, shape S: the number of terms of each sphere.

paramstuple of str

The parameters d() accepts.

a
b
n_terms
params = ()
d(param)

The derivatives with respect to param: "x", "m_real", "m_imag", or "m" for the complex derivative d/dm (which equals ∂/∂(Re m); ∂/∂(Im m) is i d/dm).

Raises:
ValueError

If the derivative was not requested.

class scatrs.mie.MieEfficiencies(q_ext, q_sca, q_abs, q_back, g, params=(), _jacobian=None)

Efficiencies and asymmetry parameter of spheres, each an array of shape S.

Attributes:
q_ext, q_sca, q_abs, q_backnumpy.ndarray

Extinction, scattering, absorption and backscattering efficiencies (cross sections divided by pi r**2). q_abs is computed without the cancellation of q_ext - q_sca, and is exactly 0 for real m; q_ext = q_sca + q_abs.

gnumpy.ndarray

Asymmetry parameter.

paramstuple of str

The parameters d() accepts.

q_ext
q_sca
q_abs
q_back
g
params = ()
d(param)

The derivatives with respect to param ("x", "m_real" or "m_imag").

Raises:
ValueError

If the derivative was not requested.

class scatrs.mie.MieGreek(alpha1, alpha2, alpha3, alpha4, beta1, beta2, n_terms, params=(), _derivatives=None)

Greek (generalized-spherical-function) expansion coefficients of the phase matrix of spheres, arrays of shape S + (L + 1,); alpha1[..., l] is the coefficient of order l (Mishchenko, Travis & Lacis 2002, Eqs. 4.75–4.80): F11 = sum alpha1[l] d00_l, F22 + F33 = sum (alpha2 + alpha3)[l] d22_l, F22 - F33 = sum (alpha2 - alpha3)[l] d2-2_l, F44 = sum alpha4[l] d00_l, F12 = sum beta1[l] d02_l, F34 = sum beta2[l] d02_l, with dmn_l the Wigner d-functions of scatrs.special.wigner_d() at the cosine of the scattering angle.

Attributes:
alpha1, alpha2, alpha3, alpha4, beta1, beta2numpy.ndarray

float64. Normalized, alpha1[..., 0] is 1 and alpha1[..., 1] is 3 g; unnormalized, they are those times q_sca. Orders above a sphere’s 2 n_terms are exactly 0.

n_termsnumpy.ndarray

int64, shape S: the number of terms of each sphere.

paramstuple of str

The parameters d() accepts.

alpha1
alpha2
alpha3
alpha4
beta1
beta2
n_terms
params = ()
d(param)

The derivatives with respect to param ("x", "m_real" or "m_imag").

Raises:
ValueError

If the derivative was not requested.

class scatrs.mie.MiePhaseMatrix(f11, f12, f33, f34, params=(), _derivatives=None)

The phase matrix of spheres, arrays of shape S + mu.shape (Bohren & Huffman 1983, §4.4). For a sphere F22 = F11 and F44 = F33; the other elements are 0.

Attributes:
f11, f12, f33, f34numpy.ndarray

(|S1|**2 + |S2|**2)/2, (|S2|**2 - |S1|**2)/2, Re(S2 conj(S1)) and Im(S2 conj(S1)), times 4/(x**2 q_sca) (normalized: F11 averages to 1 over the sphere of directions) or 4/x**2 (unnormalized: per unit geometric cross section, which sums over a size distribution).

paramstuple of str

The parameters d() accepts.

f11
f12
f33
f34
params = ()
d(param)

The derivatives with respect to param ("x", "m_real" or "m_imag"); normalized derivatives include that of q_sca.

Raises:
ValueError

If the derivative was not requested.

scatrs.mie.amplitudes(x, m, mu, *, n_max=None, derivatives=False, allow_unvalidated=False)

Amplitude scattering functions S₁ and S₂ of spheres.

Parameters:
xarray_like

Size parameters, 2 pi r / wavelength (real).

marray_like

Refractive indices relative to the medium (real or complex), broadcast against x. Aligned, C-contiguous, native-endian float64 x and complex128 m are read in place; anything else is converted first. Do not modify or resize them from another thread during the call.

muarray_like

Cosines of the scattering angle, in [-1, 1].

n_maxint, optional

The number of terms; by default ceil(x + 6 x**(1/3) + 3). Fewer terms than the default are outside the validated domain.

derivativesbool or sequence of str, optional

Also compute derivatives with respect to these of "x", "m_real" and "m_imag" (True for all three); read them with the result’s d method.

allow_unvalidatedbool, optional

Compute outside the validated domain (1e-6 <= x <= 2e4, 0 < Re m <= 10, 0 <= Im m <= 10, |m| >= 0.1) instead of raising OutsideValidatedDomainError.

Returns:
MieAmplitudes

Shape S + mu.shape.

Raises:
InvalidInputError

For x outside [1e-30, 1e6], non-finite m, Re m < 0 or Im m < 0 (gain media), |m| outside [1e-6, 1e3], n_max outside [1, MAX_MIE_ORDER], mu outside [-1, 1] or NaN, or an output above MAX_MIE_VALUES complex values (2 * MAX_MIE_VALUES real values). The message names the first failing element (in C order).

OutsideValidatedDomainError

For valid inputs outside the validated domain, unless allow_unvalidated.

TypeError

For non-numeric x or m (complex x), a non-integer n_max (float and bool values are rejected), derivatives that is neither a bool nor a sequence of names, or a non-bool allow_unvalidated.

ValueError

For an unknown parameter name, or (from numpy) shapes that do not broadcast.

BufferError

If another rust-numpy extension holds a writeable borrow of an input.

MemoryError

If the outputs cannot be allocated.

Notes

The cost per sphere grows like x + |m| x (see Homogeneous spheres (Lorenz–Mie)): the largest accepted |m| x take seconds per sphere. The call releases the GIL, so other Python threads keep running, but it cannot be interrupted: Ctrl+C takes effect only once it returns.

scatrs.mie.coefficients(x, m, *, n_max=None, derivatives=False, allow_unvalidated=False)

Mie coefficients aₙ and bₙ of spheres.

Parameters:
xarray_like

Size parameters, 2 pi r / wavelength (real).

marray_like

Refractive indices relative to the medium (real or complex), broadcast against x. Aligned, C-contiguous, native-endian float64 x and complex128 m are read in place; anything else is converted first. Do not modify or resize them from another thread during the call.

n_maxint, optional

The number of terms; by default ceil(x + 6 x**(1/3) + 3). Fewer terms than the default are outside the validated domain.

derivativesbool or sequence of str, optional

Also compute derivatives with respect to these of "x", "m_real" and "m_imag" (True for all three); read them with the result’s d method.

allow_unvalidatedbool, optional

Compute outside the validated domain (1e-6 <= x <= 2e4, 0 < Re m <= 10, 0 <= Im m <= 10, |m| >= 0.1) instead of raising OutsideValidatedDomainError.

Returns:
MieCoefficients

Shape S + (N,), zero-padded to the largest number of terms N.

Raises:
InvalidInputError

For x outside [1e-30, 1e6], non-finite m, Re m < 0 or Im m < 0 (gain media), |m| outside [1e-6, 1e3], n_max outside [1, MAX_MIE_ORDER], or an output above MAX_MIE_VALUES complex values (2 * MAX_MIE_VALUES real values). The message names the first failing element (in C order).

OutsideValidatedDomainError

For valid inputs outside the validated domain, unless allow_unvalidated.

TypeError

For non-numeric x or m (complex x), a non-integer n_max (float and bool values are rejected), derivatives that is neither a bool nor a sequence of names, or a non-bool allow_unvalidated.

ValueError

For an unknown parameter name, or (from numpy) shapes that do not broadcast.

BufferError

If another rust-numpy extension holds a writeable borrow of an input.

MemoryError

If the outputs cannot be allocated.

Notes

The cost per sphere grows like x + |m| x (see Homogeneous spheres (Lorenz–Mie)): the largest accepted |m| x take seconds per sphere. The call releases the GIL, so other Python threads keep running, but it cannot be interrupted: Ctrl+C takes effect only once it returns.

scatrs.mie.default_n_max(x)

The default number of terms, ceil(x + 6 x**(1/3) + 3), for each size parameter.

Parameters:
xarray_like

Size parameters (real).

Returns:
numpy.ndarray

int64, the shape of x.

Raises:
InvalidInputError

For x outside [1e-30, 1e6] (or NaN); the message names the first failing element (in C order).

TypeError

For non-real x.

scatrs.mie.efficiencies(x, m, *, n_max=None, derivatives=False, allow_unvalidated=False)

Efficiencies and asymmetry parameter of spheres.

Parameters:
xarray_like

Size parameters, 2 pi r / wavelength (real).

marray_like

Refractive indices relative to the medium (real or complex), broadcast against x. Aligned, C-contiguous, native-endian float64 x and complex128 m are read in place; anything else is converted first. Do not modify or resize them from another thread during the call.

n_maxint, optional

The number of terms; by default ceil(x + 6 x**(1/3) + 3). Fewer terms than the default are outside the validated domain.

derivativesbool or sequence of str, optional

Also compute derivatives with respect to these of "x", "m_real" and "m_imag" (True for all three); read them with the result’s d method.

allow_unvalidatedbool, optional

Compute outside the validated domain (1e-6 <= x <= 2e4, 0 < Re m <= 10, 0 <= Im m <= 10, |m| >= 0.1) instead of raising OutsideValidatedDomainError.

Returns:
MieEfficiencies

Each field has the broadcast shape of x and m.

Raises:
InvalidInputError

For x outside [1e-30, 1e6], non-finite m, Re m < 0 or Im m < 0 (gain media), |m| outside [1e-6, 1e3], n_max outside [1, MAX_MIE_ORDER], or an output above MAX_MIE_VALUES complex values (2 * MAX_MIE_VALUES real values). The message names the first failing element (in C order).

OutsideValidatedDomainError

For valid inputs outside the validated domain, unless allow_unvalidated.

TypeError

For non-numeric x or m (complex x), a non-integer n_max (float and bool values are rejected), derivatives that is neither a bool nor a sequence of names, or a non-bool allow_unvalidated.

ValueError

For an unknown parameter name, or (from numpy) shapes that do not broadcast.

BufferError

If another rust-numpy extension holds a writeable borrow of an input.

MemoryError

If the outputs cannot be allocated.

Notes

The cost per sphere grows like x + |m| x (see Homogeneous spheres (Lorenz–Mie)): the largest accepted |m| x take seconds per sphere. The call releases the GIL, so other Python threads keep running, but it cannot be interrupted: Ctrl+C takes effect only once it returns.

scatrs.mie.greek(x, m, order=None, *, normalized=True, n_max=None, derivatives=False, allow_unvalidated=False)

Greek expansion coefficients of the phase matrix of spheres.

Exact up to rounding: the phase matrix at the nodes of a Gauss–Legendre rule with n_terms + ceil((L + 1)/2) points, projected onto the Wigner d-functions.

Parameters:
xarray_like

Size parameters, 2 pi r / wavelength (real).

marray_like

Refractive indices relative to the medium (real or complex), broadcast against x. Aligned, C-contiguous, native-endian float64 x and complex128 m are read in place; anything else is converted first. Do not modify or resize them from another thread during the call.

orderint, optional

The highest order L; by default 2 n_terms of the largest sphere, which is all of them. Orders above 2 n_terms are exactly 0.

normalizedbool, optional

Normalize alpha1[..., 0] to 1 (the default), or to q_sca.

n_maxint, optional

The number of terms; by default ceil(x + 6 x**(1/3) + 3). Fewer terms than the default are outside the validated domain.

derivativesbool or sequence of str, optional

Also compute derivatives with respect to these of "x", "m_real" and "m_imag" (True for all three); read them with the result’s d method.

allow_unvalidatedbool, optional

Compute outside the validated domain (1e-6 <= x <= 2e4, 0 < Re m <= 10, 0 <= Im m <= 10, |m| >= 0.1) instead of raising OutsideValidatedDomainError.

Returns:
MieGreek

Shape S + (L + 1,).

Raises:
InvalidInputError

For x outside [1e-30, 1e6], non-finite m, Re m < 0 or Im m < 0 (gain media), |m| outside [1e-6, 1e3], n_max outside [1, MAX_MIE_ORDER], a negative order or one above MAX_GREEK_ORDER, a sphere whose rule would need more than 2**17 nodes, or an output above MAX_MIE_VALUES complex values (2 * MAX_MIE_VALUES real values). The message names the first failing element (in C order).

OutsideValidatedDomainError

For valid inputs outside the validated domain, unless allow_unvalidated.

TypeError

For non-numeric x or m (complex x), a non-integer n_max (float and bool values are rejected), derivatives that is neither a bool nor a sequence of names, or a non-bool allow_unvalidated or normalized, or a non-integer order.

ValueError

For an unknown parameter name, or (from numpy) shapes that do not broadcast.

BufferError

If another rust-numpy extension holds a writeable borrow of an input.

MemoryError

If the outputs cannot be allocated.

Notes

The cost per sphere grows like x + |m| x (see Homogeneous spheres (Lorenz–Mie)): the largest accepted |m| x take seconds per sphere. The call releases the GIL, so other Python threads keep running, but it cannot be interrupted: Ctrl+C takes effect only once it returns.

Projecting adds about n_terms * L operations per sphere to the amplitudes at the n_terms + ceil((L + 1)/2) nodes: all orders take about 0.09 s at x = 1e3 and 7.6 s at x = 1e4.

scatrs.mie.phase_matrix(x, m, mu, *, normalized=True, n_max=None, derivatives=False, allow_unvalidated=False)

The phase matrix F11, F12, F33, F34 of spheres.

Parameters:
xarray_like

Size parameters, 2 pi r / wavelength (real).

marray_like

Refractive indices relative to the medium (real or complex), broadcast against x. Aligned, C-contiguous, native-endian float64 x and complex128 m are read in place; anything else is converted first. Do not modify or resize them from another thread during the call.

muarray_like

Cosines of the scattering angle, in [-1, 1].

normalizedbool, optional

Divide by q_sca (the default), so that F11 averages to 1.

n_maxint, optional

The number of terms; by default ceil(x + 6 x**(1/3) + 3). Fewer terms than the default are outside the validated domain.

derivativesbool or sequence of str, optional

Also compute derivatives with respect to these of "x", "m_real" and "m_imag" (True for all three); read them with the result’s d method.

allow_unvalidatedbool, optional

Compute outside the validated domain (1e-6 <= x <= 2e4, 0 < Re m <= 10, 0 <= Im m <= 10, |m| >= 0.1) instead of raising OutsideValidatedDomainError.

Returns:
MiePhaseMatrix

Shape S + mu.shape.

Raises:
InvalidInputError

For x outside [1e-30, 1e6], non-finite m, Re m < 0 or Im m < 0 (gain media), |m| outside [1e-6, 1e3], n_max outside [1, MAX_MIE_ORDER], mu outside [-1, 1] or NaN, or an output above MAX_MIE_VALUES complex values (2 * MAX_MIE_VALUES real values). The message names the first failing element (in C order).

OutsideValidatedDomainError

For valid inputs outside the validated domain, unless allow_unvalidated.

TypeError

For non-numeric x or m (complex x), a non-integer n_max (float and bool values are rejected), derivatives that is neither a bool nor a sequence of names, or a non-bool allow_unvalidated or normalized.

ValueError

For an unknown parameter name, or (from numpy) shapes that do not broadcast.

BufferError

If another rust-numpy extension holds a writeable borrow of an input.

MemoryError

If the outputs cannot be allocated.

Notes

The cost per sphere grows like x + |m| x (see Homogeneous spheres (Lorenz–Mie)): the largest accepted |m| x take seconds per sphere. The call releases the GIL, so other Python threads keep running, but it cannot be interrupted: Ctrl+C takes effect only once it returns.

scatrs.layered

Scattering by layered spheres: a core and concentric shells (vectorized wrappers over the Rust core).

x and m have a trailing axis of layers, core first: x[..., l] is the size parameter 2 pi r_l / wavelength of the outer surface of layer l (nondecreasing along the axis, the last the particle’s) and m[..., l] the refractive index of layer l relative to the medium. Their leading axes broadcast against each other to a shape S, and every result has that shape, extended as in scatrs.mie. A single layer is a sphere: its results are scatrs.mie’s, bitwise. Conventions are those of scatrs.mie; the outer size parameter normalizes the efficiencies and the phase matrix. See Layered spheres for the method and Internal validation for the validated domain.

derivatives is True (every layer’s "layer{l}.x", "layer{l}.m_real" and "layer{l}.m_imag") or a sequence of those names; the result’s d method returns the derivative with respect to one of them, or "layer{l}.m" (the complex derivative) for the complex outputs. The derivatives are validated up to an outer size parameter of 1000.

The results are those of scatrs.mie (MieEfficiencies, …), with d accepting the layers’ parameter names.

scatrs.layered.MAX_LAYERS = 1024

The largest number of layers accepted: 2**10.

class scatrs.layered.LayeredAmplitudes(s1, s2, params=(), _derivatives=None)

MieAmplitudes of layered spheres; d takes the layers’ parameter names ("layer{l}.m": the complex derivative d/dm_l).

d(param)

The derivatives with respect to param: "x", "m_real", "m_imag", or "m" for the complex derivative d/dm.

Raises:
ValueError

If the derivative was not requested.

class scatrs.layered.LayeredCoefficients(a, b, n_terms, params=(), _derivatives=None)

MieCoefficients of layered spheres; d takes the layers’ parameter names ("layer{l}.m": the complex derivative d/dm_l).

d(param)

The derivatives with respect to param: "x", "m_real", "m_imag", or "m" for the complex derivative d/dm (which equals ∂/∂(Re m); ∂/∂(Im m) is i d/dm).

Raises:
ValueError

If the derivative was not requested.

class scatrs.layered.LayeredEfficiencies(q_ext, q_sca, q_abs, q_back, g, params=(), _jacobian=None)

MieEfficiencies of layered spheres, per unit geometric cross section of the outer surface; d takes the layers’ parameter names.

d(param)

The derivatives with respect to param ("x", "m_real" or "m_imag").

Raises:
ValueError

If the derivative was not requested.

class scatrs.layered.LayeredGreek(alpha1, alpha2, alpha3, alpha4, beta1, beta2, n_terms, params=(), _derivatives=None)

MieGreek of layered spheres; d takes the layers’ parameter names.

d(param)

The derivatives with respect to param ("x", "m_real" or "m_imag").

Raises:
ValueError

If the derivative was not requested.

class scatrs.layered.LayeredPhaseMatrix(f11, f12, f33, f34, params=(), _derivatives=None)

MiePhaseMatrix of layered spheres; d takes the layers’ parameter names.

d(param)

The derivatives with respect to param ("x", "m_real" or "m_imag"); normalized derivatives include that of q_sca.

Raises:
ValueError

If the derivative was not requested.

scatrs.layered.amplitudes(x, m, mu, *, n_max=None, derivatives=False, allow_unvalidated=False)

Amplitude scattering functions S₁ and S₂ of layered spheres.

Parameters:
xarray_like

Size parameters of the interfaces, 2 pi r_l / wavelength, along a trailing axis of layers (core first, nondecreasing).

marray_like

Refractive indices of the layers relative to the medium (real or complex), along the same trailing axis; the leading axes broadcast against those of x.

muarray_like

Cosines of the scattering angle, in [-1, 1].

n_maxint, optional

The number of terms; by default the sphere’s at the outer size parameter. Fewer terms than the default are outside the validated domain.

derivativesbool or sequence of str, optional

Also compute derivatives with respect to these of "layer{l}.x", "layer{l}.m_real" and "layer{l}.m_imag" (True for all); read them with the result’s d method. Validated up to an outer size parameter of 1000.

allow_unvalidatedbool, optional

Compute outside the validated domain instead of raising OutsideValidatedDomainError (see Internal validation).

Returns:
LayeredAmplitudes

Shape S + mu.shape.

Raises:
InvalidInputError

For invalid inputs (as scatrs.mie’s, for every layer), size parameters that decrease from the core out, or more than MAX_LAYERS layers, mu outside [-1, 1] or NaN. The message names the first failing particle (in C order).

OutsideValidatedDomainError

For valid inputs outside the validated domain, unless allow_unvalidated.

TypeError

For non-numeric x or m, or arguments of the wrong type.

ValueError

For an unknown parameter name, no layer axis, last axes of different lengths, or (from numpy) leading shapes that do not broadcast.

scatrs.layered.coefficients(x, m, *, n_max=None, derivatives=False, allow_unvalidated=False)

Mie coefficients aₙ and bₙ of layered spheres.

Parameters:
xarray_like

Size parameters of the interfaces, 2 pi r_l / wavelength, along a trailing axis of layers (core first, nondecreasing).

marray_like

Refractive indices of the layers relative to the medium (real or complex), along the same trailing axis; the leading axes broadcast against those of x.

n_maxint, optional

The number of terms; by default the sphere’s at the outer size parameter. Fewer terms than the default are outside the validated domain.

derivativesbool or sequence of str, optional

Also compute derivatives with respect to these of "layer{l}.x", "layer{l}.m_real" and "layer{l}.m_imag" (True for all); read them with the result’s d method. Validated up to an outer size parameter of 1000.

allow_unvalidatedbool, optional

Compute outside the validated domain instead of raising OutsideValidatedDomainError (see Internal validation).

Returns:
LayeredCoefficients

Shape S + (N,), zero-padded to the largest number of terms N.

Raises:
InvalidInputError

For invalid inputs (as scatrs.mie’s, for every layer), size parameters that decrease from the core out, or more than MAX_LAYERS layers. The message names the first failing particle (in C order).

OutsideValidatedDomainError

For valid inputs outside the validated domain, unless allow_unvalidated.

TypeError

For non-numeric x or m, or arguments of the wrong type.

ValueError

For an unknown parameter name, no layer axis, last axes of different lengths, or (from numpy) leading shapes that do not broadcast.

scatrs.layered.default_n_max(x)

The default number of terms: the sphere’s (scatrs.mie.default_n_max()) at the outer size parameter x[..., -1].

scatrs.layered.efficiencies(x, m, *, n_max=None, derivatives=False, allow_unvalidated=False)

Efficiencies and asymmetry parameter of layered spheres.

Parameters:
xarray_like

Size parameters of the interfaces, 2 pi r_l / wavelength, along a trailing axis of layers (core first, nondecreasing).

marray_like

Refractive indices of the layers relative to the medium (real or complex), along the same trailing axis; the leading axes broadcast against those of x.

n_maxint, optional

The number of terms; by default the sphere’s at the outer size parameter. Fewer terms than the default are outside the validated domain.

derivativesbool or sequence of str, optional

Also compute derivatives with respect to these of "layer{l}.x", "layer{l}.m_real" and "layer{l}.m_imag" (True for all); read them with the result’s d method. Validated up to an outer size parameter of 1000.

allow_unvalidatedbool, optional

Compute outside the validated domain instead of raising OutsideValidatedDomainError (see Internal validation).

Returns:
LayeredEfficiencies

Each field has the broadcast leading shape S.

Raises:
InvalidInputError

For invalid inputs (as scatrs.mie’s, for every layer), size parameters that decrease from the core out, or more than MAX_LAYERS layers. The message names the first failing particle (in C order).

OutsideValidatedDomainError

For valid inputs outside the validated domain, unless allow_unvalidated.

TypeError

For non-numeric x or m, or arguments of the wrong type.

ValueError

For an unknown parameter name, no layer axis, last axes of different lengths, or (from numpy) leading shapes that do not broadcast.

scatrs.layered.greek(x, m, order=None, *, normalized=True, n_max=None, derivatives=False, allow_unvalidated=False)

Greek expansion coefficients of the phase matrix of layered spheres, exact up to rounding, as scatrs.mie.greek().

Parameters:
xarray_like

Size parameters of the interfaces, 2 pi r_l / wavelength, along a trailing axis of layers (core first, nondecreasing).

marray_like

Refractive indices of the layers relative to the medium (real or complex), along the same trailing axis; the leading axes broadcast against those of x.

orderint, optional

The highest order L; by default 2 n_terms of the largest particle.

normalizedbool, optional

Normalize alpha1[..., 0] to 1 (the default), or to q_sca.

n_maxint, optional

The number of terms; by default the sphere’s at the outer size parameter. Fewer terms than the default are outside the validated domain.

derivativesbool or sequence of str, optional

Also compute derivatives with respect to these of "layer{l}.x", "layer{l}.m_real" and "layer{l}.m_imag" (True for all); read them with the result’s d method. Validated up to an outer size parameter of 1000.

allow_unvalidatedbool, optional

Compute outside the validated domain instead of raising OutsideValidatedDomainError (see Internal validation).

Returns:
LayeredGreek

Shape S + (L + 1,).

Raises:
InvalidInputError

For invalid inputs (as scatrs.mie’s, for every layer), size parameters that decrease from the core out, or more than MAX_LAYERS layers, a negative order or one above MAX_GREEK_ORDER. The message names the first failing particle (in C order).

OutsideValidatedDomainError

For valid inputs outside the validated domain, unless allow_unvalidated.

TypeError

For non-numeric x or m, or arguments of the wrong type.

ValueError

For an unknown parameter name, no layer axis, last axes of different lengths, or (from numpy) leading shapes that do not broadcast.

scatrs.layered.parameters(layers)

The parameter names of a particle of layers layers, in the order of the results.

scatrs.layered.phase_matrix(x, m, mu, *, normalized=True, n_max=None, derivatives=False, allow_unvalidated=False)

The phase matrix F11, F12, F33, F34 of layered spheres.

Parameters:
xarray_like

Size parameters of the interfaces, 2 pi r_l / wavelength, along a trailing axis of layers (core first, nondecreasing).

marray_like

Refractive indices of the layers relative to the medium (real or complex), along the same trailing axis; the leading axes broadcast against those of x.

muarray_like

Cosines of the scattering angle, in [-1, 1].

normalizedbool, optional

Divide by q_sca (the default), so that F11 averages to 1.

n_maxint, optional

The number of terms; by default the sphere’s at the outer size parameter. Fewer terms than the default are outside the validated domain.

derivativesbool or sequence of str, optional

Also compute derivatives with respect to these of "layer{l}.x", "layer{l}.m_real" and "layer{l}.m_imag" (True for all); read them with the result’s d method. Validated up to an outer size parameter of 1000.

allow_unvalidatedbool, optional

Compute outside the validated domain instead of raising OutsideValidatedDomainError (see Internal validation).

Returns:
LayeredPhaseMatrix

Shape S + mu.shape.

Raises:
InvalidInputError

For invalid inputs (as scatrs.mie’s, for every layer), size parameters that decrease from the core out, or more than MAX_LAYERS layers, mu outside [-1, 1] or NaN. The message names the first failing particle (in C order).

OutsideValidatedDomainError

For valid inputs outside the validated domain, unless allow_unvalidated.

TypeError

For non-numeric x or m, or arguments of the wrong type.

ValueError

For an unknown parameter name, no layer axis, last axes of different lengths, or (from numpy) leading shapes that do not broadcast.

scatrs.tmatrix

Scattering by randomly oriented spheroids, by the T-matrix method (vectorized wrappers over the Rust core).

A spheroid has semi-axes a, a, c, c along its symmetry axis, and aspect ratio aspect_ratio = a / c: oblate above 1, prolate below 1, a sphere at 1. Its size is the size parameter x = 2 pi r_v / wavelength of the sphere of equal volume (r_v**3 = a**2 c), which also normalizes the efficiencies (cross sections divided by pi r_v**2) and the unnormalized phase matrix and Greek coefficients. x, m and aspect_ratio broadcast against each other to a shape S; every result has that shape, extended by the orders or the angles. Conventions are those of scatrs.mie, averaged uniformly over orientations. See Spheroids for the method and Internal validation for the validated domain.

Each spheroid’s T-matrix is converged to the relative tolerance rtol in its number of orders and quadrature nodes; the results carry n_terms, n_theta and an error estimate per spheroid. derivatives is True (all of "x", "aspect_ratio", "m_real", "m_imag") or a sequence of those names; the result’s d method returns the derivative with respect to one of them.

scatrs.tmatrix.MAX_TMATRIX_ORDER = 500

The largest number of orders N accepted: 500.

scatrs.tmatrix.PARAMETERS = ('x', 'aspect_ratio', 'm_real', 'm_imag')

The parameters derivatives may name.

class scatrs.tmatrix.SpheroidEfficiencies(q_ext, q_sca, q_abs, q_back, g, params=(), _jacobian=None, n_terms=<factory>, n_theta=<factory>, error=<factory>)

Orientation-averaged efficiencies of spheroids (MieEfficiencies, per unit geometric cross section of the equal-volume sphere; q_abs = q_ext - q_sca), with the convergence information of each spheroid.

Attributes:
n_terms, n_thetanumpy.ndarray

int64, shape S: the number of orders and of quadrature nodes (in a half range of the polar angle) each T-matrix converged at.

errornumpy.ndarray

float64, shape S: each spheroid’s estimated relative error.

n_terms
n_theta
error
d(param)

The derivatives with respect to param (one of PARAMETERS).

class scatrs.tmatrix.SpheroidGreek(alpha1, alpha2, alpha3, alpha4, beta1, beta2, n_terms, params=(), _derivatives=None)

Greek expansion coefficients of the orientation-averaged phase matrix of spheroids (MieGreek, with F22 and F44 independent); orders above a spheroid’s 2 n_terms are exactly 0.

d(param)

The derivatives with respect to param (one of PARAMETERS).

class scatrs.tmatrix.SpheroidPhaseMatrix(f11, f12, f22, f33, f34, f44, params=(), _derivatives=None)

The orientation-averaged phase matrix of spheroids, arrays of shape S + mu.shape: its six independent elements (the others are 0), normalized (F11 averages to 1 over the sphere of directions) or unnormalized (times q_sca). For a sphere F22 = F11 and F44 = F33.

Attributes:
f11, f12, f22, f33, f34, f44numpy.ndarray

The elements.

paramstuple of str

The parameters d() accepts.

f11
f12
f22
f33
f34
f44
params = ()
d(param)

The derivatives with respect to param (one of PARAMETERS); normalized derivatives include that of q_sca.

class scatrs.tmatrix.TMatrix(obj, params)

The converged T-matrix of one spheroid, from compute().

Attributes:
n_terms, n_thetaint

The number of orders and of quadrature nodes.

n_modesint

The number of azimuthal modes computed, m = 0, ..., n_modes - 1 (at most n_terms + 1): the modes above, whose elements fall below rtol / 10 of the largest element of T, are negligible and not computed.

error_estimatefloat

The estimated relative error of the outputs.

convergedbool

False only for a result returned at a cap with allow_unconverged.

precision_pathstuple of str

How each computed mode m = 0, ..., n_modes - 1 was solved: "f64", "refined" or "double-double".

paramstuple of str

The parameters of the derivatives, if computed.

params
property n_terms
property n_theta
property n_modes
property error_estimate
property converged
property precision_paths
block(m)

The blocks of mode m, one of the computed modes 0 to n_modes - 1.

Raises:
IndexError

For m outside 0 to n_modes - 1.

efficiencies()

The orientation-averaged efficiencies (scalars), with their derivatives if computed.

greek(order=None, *, normalized=True)

The Greek coefficients up to order (default 2 n_terms).

phase_matrix(mu, *, normalized=True)

The six-element phase matrix at the cosines mu.

random_orientation(mu=None, order=None, *, normalized=True)

The orientation-averaged outputs: efficiencies, Greek coefficients up to order and, with cosines mu, the phase matrix.

scatrs.tmatrix.compute(x, m, aspect_ratio, *, rtol=1e-08, precision='auto', n_terms=None, n_theta=None, derivatives=False, allow_unconverged=False, allow_unvalidated=False)

The converged T-matrix of one spheroid, with its convergence information and orientation-averaged outputs.

Parameters:
xfloat

The equal-volume size parameter, 2 pi r_v / wavelength (real).

marray_like

Refractive indices relative to the medium (real or complex).

aspect_ratioarray_like

a / c: oblate above 1, prolate below 1 (real, positive).

rtolfloat, optional

The relative tolerance of each T-matrix’s convergence (default 1e-8).

precision{“auto”, “f64”, “double-double”}, optional

The precision paths allowed: "auto" refines in mixed precision the modes whose error estimate requires it; "f64" never does (fastest); "double-double" computes everything in double-double (slowest, for checks).

n_terms, n_thetaint, optional

Fix the number of orders or of quadrature nodes instead of converging them.

derivativesbool or sequence of str, optional

Also compute derivatives with respect to these of PARAMETERS (True for all four); read them with the result’s d method.

allow_unconvergedbool, optional

Return the last step of a convergence that reached its cap, with its error estimate, instead of raising NotConvergedError.

allow_unvalidatedbool, optional

Compute outside the validated domain instead of raising OutsideValidatedDomainError.

Returns:
TMatrix
Raises:
InvalidInputError

For non-positive or non-finite x or aspect_ratio, non-finite m, Re m <= 0 or Im m < 0, rtol outside (0, 1). The message names the first failing element (in C order).

OutsideValidatedDomainError

For valid inputs outside the validated domain, unless allow_unvalidated.

NotConvergedError

If a T-matrix reaches the cap of its orders or nodes, unless allow_unconverged.

ValueError

For an unknown parameter name or precision, or shapes that do not broadcast.

Notes

The cost per spheroid grows like the fourth power of |m| x_max, with x_max the size parameter of the longest semi-axis, and steeply for extreme aspect ratios, where the refinement engages; the call releases the GIL but cannot be interrupted.

scatrs.tmatrix.efficiencies(x, m, aspect_ratio, *, rtol=1e-08, precision='auto', n_terms=None, n_theta=None, derivatives=False, allow_unconverged=False, allow_unvalidated=False)

Orientation-averaged efficiencies of spheroids.

Parameters:
xarray_like

Equal-volume size parameters, 2 pi r_v / wavelength (real).

marray_like

Refractive indices relative to the medium (real or complex).

aspect_ratioarray_like

a / c: oblate above 1, prolate below 1 (real, positive).

rtolfloat, optional

The relative tolerance of each T-matrix’s convergence (default 1e-8).

precision{“auto”, “f64”, “double-double”}, optional

The precision paths allowed: "auto" refines in mixed precision the modes whose error estimate requires it; "f64" never does (fastest); "double-double" computes everything in double-double (slowest, for checks).

n_terms, n_thetaint, optional

Fix the number of orders or of quadrature nodes instead of converging them.

derivativesbool or sequence of str, optional

Also compute derivatives with respect to these of PARAMETERS (True for all four); read them with the result’s d method.

allow_unconvergedbool, optional

Return the last step of a convergence that reached its cap, with its error estimate, instead of raising NotConvergedError.

allow_unvalidatedbool, optional

Compute outside the validated domain instead of raising OutsideValidatedDomainError.

Returns:
SpheroidEfficiencies

Shape S.

Raises:
InvalidInputError

For non-positive or non-finite x or aspect_ratio, non-finite m, Re m <= 0 or Im m < 0, rtol outside (0, 1). The message names the first failing element (in C order).

OutsideValidatedDomainError

For valid inputs outside the validated domain, unless allow_unvalidated.

NotConvergedError

If a T-matrix reaches the cap of its orders or nodes, unless allow_unconverged.

ValueError

For an unknown parameter name or precision, or shapes that do not broadcast.

Notes

The cost per spheroid grows like the fourth power of |m| x_max, with x_max the size parameter of the longest semi-axis, and steeply for extreme aspect ratios, where the refinement engages; the call releases the GIL but cannot be interrupted.

scatrs.tmatrix.greek(x, m, aspect_ratio, order=None, *, normalized=True, rtol=1e-08, precision='auto', n_terms=None, n_theta=None, derivatives=False, allow_unconverged=False, allow_unvalidated=False)

Greek expansion coefficients of the orientation-averaged phase matrix of spheroids.

Parameters:
xarray_like

Equal-volume size parameters, 2 pi r_v / wavelength (real).

marray_like

Refractive indices relative to the medium (real or complex).

aspect_ratioarray_like

a / c: oblate above 1, prolate below 1 (real, positive).

orderint, optional

The highest order L.

normalizedbool, optional

Normalize so that alpha1[..., 0] is 1 (the default); otherwise times q_sca.

rtolfloat, optional

The relative tolerance of each T-matrix’s convergence (default 1e-8).

precision{“auto”, “f64”, “double-double”}, optional

The precision paths allowed: "auto" refines in mixed precision the modes whose error estimate requires it; "f64" never does (fastest); "double-double" computes everything in double-double (slowest, for checks).

n_terms, n_thetaint, optional

Fix the number of orders or of quadrature nodes instead of converging them.

derivativesbool or sequence of str, optional

Also compute derivatives with respect to these of PARAMETERS (True for all four); read them with the result’s d method.

allow_unconvergedbool, optional

Return the last step of a convergence that reached its cap, with its error estimate, instead of raising NotConvergedError.

allow_unvalidatedbool, optional

Compute outside the validated domain instead of raising OutsideValidatedDomainError.

Returns:
SpheroidGreek

Shape S + (L + 1,), with L = order, by default the largest 2 n_terms.

Raises:
InvalidInputError

For non-positive or non-finite x or aspect_ratio, non-finite m, Re m <= 0 or Im m < 0, rtol outside (0, 1), order above MAX_GREEK_ORDER. The message names the first failing element (in C order).

OutsideValidatedDomainError

For valid inputs outside the validated domain, unless allow_unvalidated.

NotConvergedError

If a T-matrix reaches the cap of its orders or nodes, unless allow_unconverged.

ValueError

For an unknown parameter name or precision, or shapes that do not broadcast.

Notes

The cost per spheroid grows like the fourth power of |m| x_max, with x_max the size parameter of the longest semi-axis, and steeply for extreme aspect ratios, where the refinement engages; the call releases the GIL but cannot be interrupted.

scatrs.tmatrix.phase_matrix(x, m, aspect_ratio, mu, *, normalized=True, rtol=1e-08, precision='auto', n_terms=None, n_theta=None, derivatives=False, allow_unconverged=False, allow_unvalidated=False)

The six-element orientation-averaged phase matrix of spheroids.

Parameters:
xarray_like

Equal-volume size parameters, 2 pi r_v / wavelength (real).

marray_like

Refractive indices relative to the medium (real or complex).

aspect_ratioarray_like

a / c: oblate above 1, prolate below 1 (real, positive).

muarray_like

Cosines of the scattering angle, in [-1, 1].

normalizedbool, optional

Normalize so that F11 averages to 1 (the default); otherwise times q_sca.

rtolfloat, optional

The relative tolerance of each T-matrix’s convergence (default 1e-8).

precision{“auto”, “f64”, “double-double”}, optional

The precision paths allowed: "auto" refines in mixed precision the modes whose error estimate requires it; "f64" never does (fastest); "double-double" computes everything in double-double (slowest, for checks).

n_terms, n_thetaint, optional

Fix the number of orders or of quadrature nodes instead of converging them.

derivativesbool or sequence of str, optional

Also compute derivatives with respect to these of PARAMETERS (True for all four); read them with the result’s d method.

allow_unconvergedbool, optional

Return the last step of a convergence that reached its cap, with its error estimate, instead of raising NotConvergedError.

allow_unvalidatedbool, optional

Compute outside the validated domain instead of raising OutsideValidatedDomainError.

Returns:
SpheroidPhaseMatrix

Shape S + mu.shape.

Raises:
InvalidInputError

For non-positive or non-finite x or aspect_ratio, non-finite m, Re m <= 0 or Im m < 0, rtol outside (0, 1), mu outside [-1, 1]. The message names the first failing element (in C order).

OutsideValidatedDomainError

For valid inputs outside the validated domain, unless allow_unvalidated.

NotConvergedError

If a T-matrix reaches the cap of its orders or nodes, unless allow_unconverged.

ValueError

For an unknown parameter name or precision, or shapes that do not broadcast.

Notes

The cost per spheroid grows like the fourth power of |m| x_max, with x_max the size parameter of the longest semi-axis, and steeply for extreme aspect ratios, where the refinement engages; the call releases the GIL but cannot be interrupted.

scatrs.special

Special functions and quadrature rules (thin wrappers over the Rust core).

Arguments are converted here (see scatrs._args), their values are checked by the Rust core, and the computation runs in Rust with the GIL released. See scatrs.errors for which exception each kind of bad argument raises.

scatrs.special.MAX_GAUSS_LEGENDRE_POINTS = 131072

The largest n that gauss_legendre() accepts: 2**17 = 131072.

scatrs.special.MAX_WIGNER_D_VALUES = 268435456

The most values one wigner_d() call returns: 2**28, 2 GiB of float64.

The bound applies to max(x.size, 1) * (l_max + 1), so l_max is bounded even for an empty x. It keeps a request from being accepted by an overcommitting allocator and then killed for lack of memory; it may be raised in a later release.

scatrs.special.gauss_legendre(n)

Gauss–Legendre nodes and weights on [-1, 1].

Parameters:
nint

Number of nodes, 1 <= n <= MAX_GAUSS_LEGENDRE_POINTS (2**17). The rule integrates polynomials of degree up to 2 * n - 1 exactly. Python and numpy integers are accepted.

Returns:
nodesnumpy.ndarray

Nodes in ascending order, shape (n,).

weightsnumpy.ndarray

Weights, shape (n,).

Raises:
InvalidInputError

If n < 1 or n > MAX_GAUSS_LEGENDRE_POINTS.

TypeError

If n is not an integer; float and bool values are rejected.

NotConvergedError

If a Newton iteration fails to converge. No n where this happens is known.

Notes

For n <= 100 the rule is computed in double-double arithmetic and rounded once, so nodes and weights are accurate to about half an ulp. Above, it comes from Bogaert’s (2014) asymptotic expansions, with node absolute errors and weight relative errors of at most 32 * 2**-52 (measured: 2.8 and 4.0 units of 2**-52). Either way the weights next to +-1 are as accurate as the others, and the rule is exactly symmetric.

The cost is O(n): about 0.3 ms at n = 1000 and 40 ms at the cap on an Apple M4 Pro. The call releases the GIL, so other Python threads keep running.

scatrs.special.wigner_d(m, n, l_max, x)

Wigner d-functions \(d^l_{mn}(\theta)\) for \(l = 0, \ldots, l_{max}\).

Uses the convention of Mishchenko, Travis & Lacis (2002), Appendix B, for example \(d^1_{01}(\theta) = \sin\theta / \sqrt{2}\).

Parameters:
m, nint

Orders, any 32-bit signed integers.

l_maxint

Largest degree (at least 0).

xarray_like

\(\cos\theta\), with every element in [-1, 1]. An aligned, C-contiguous, native-endian float64 array is read in place; anything else real (integer or other float dtypes, other memory layouts, lists, scalars) is converted to one first. Do not modify or resize x from another thread during the call.

Returns:
numpy.ndarray

Shape np.shape(x) + (l_max + 1,). Entries with l < max(|m|, |n|) are zero.

Raises:
InvalidInputError

If l_max < 0, if an element of x is NaN or outside [-1, 1], or if max(x.size, 1) * (l_max + 1) > MAX_WIGNER_D_VALUES (2**28).

TypeError

If m, n or l_max is not an integer (float and bool values are rejected), or if x is not real: complex, boolean, string, object, datetime or timedelta.

ValueError

Raised by numpy if x is a ragged nested sequence.

OverflowError

If m or n is outside the 32-bit signed range.

BufferError

If another extension built on rust-numpy holds a writeable borrow of x.

MemoryError

If the output cannot be allocated.

Notes

The absolute error is within 16 * (l + 1) * 2**-52, a bound measured against Arb (not proven): up to degree 2.5e5 for (m, n) = (0, 0) and (0, 2), and for general orders at sampled degrees up to 2000 (up to 4000 in two cases next to the poles).

The cost is O(max(|m|, |n|)) per element of x for the start value, then about 3 ns per degree (2.6 to 3.7 ns on an Apple M4 Pro); the output takes 8 * x.size * (l_max + 1) bytes. The call releases the GIL but cannot be interrupted.

scatrs.errors

Exception hierarchy raised by scatrs.

Every scatrs-specific failure is a ScatrsError:

Standard exceptions are used where Python itself would raise them:

  • TypeError for an argument of the wrong type: a float or bool (Python or numpy) where an integer is needed, or non-real values (complex, strings, objects) where real numbers are needed;

  • ValueError, raised by numpy, for a ragged nested sequence where an array is needed;

  • OverflowError for an integer that does not fit the type the Rust core uses, such as a Wigner order outside the 32-bit signed range;

  • BufferError when another extension built on rust-numpy holds a writeable borrow of an input array;

  • MemoryError when an output cannot be allocated.

exception scatrs.errors.InvalidInputError

Bases: ScatrsError, ValueError

An input is outside its valid range.

That is its mathematical domain (a NaN, or x outside [-1, 1] for x = cos(theta)) or a documented limit, such as MAX_GAUSS_LEGENDRE_POINTS or MAX_WIGNER_D_VALUES.

exception scatrs.errors.NotConvergedError(message, achieved=None, requested=None)

Bases: ScatrsError, ArithmeticError

A computation did not reach the requested accuracy.

Parameters:
messagestr

Description of the failure.

achievedfloat, optional

Accuracy actually reached (may be inf).

requestedfloat, optional

Accuracy that was requested.

exception scatrs.errors.OutsideValidatedDomainError

Bases: ScatrsError, ValueError

Inputs are valid but outside the domain where accuracy has been validated.

exception scatrs.errors.ScatrsError

Bases: Exception

Base class for every error raised by scatrs.