API reference#
PackLab keeps compiled extensions alongside its public Python APIs. The reference below is generated from the installed package, so signatures and docstrings remain aligned with the released interfaces.
Start with one of these public namespaces:
PackLab.samplersfor radius distributions;PackLab.monte_carlofor random sequential adsorption (RSA);PackLab.analyticalfor Percus–Yevick mixture calculations;PackLab.scatteringfor the optional PyMieSim integration.
Only public classes and functions are listed below. Use the module-source link next to each object when implementation details are useful.
Radius samplers#
Radius sampler classes for RSA simulations with optional radius binning.
- class ConstantRadiusSampler#
Bases:
RadiusSamplerRadius sampler that always returns one radius.
- Parameters:
radius (pint.Quantity) – Particle radius.
bins (int, default=0) – Optional number of radius bins.
- class DiscreteRadiusSampler#
Bases:
RadiusSamplerFinite set of particle radii with explicit probability weights.
- Parameters:
radii (pint.Quantity, shape (n,)) – Discrete radius values.
weights (array-like, shape (n,)) – Non-negative relative probabilities. They are normalized internally.
- class LogNormalRadiusSampler#
Bases:
RadiusSamplerLog-normal distribution of strictly positive particle radii.
- Parameters:
median_radius (pint.Quantity) – Median radius.
geometric_standard_deviation (float) – Multiplicative standard deviation; must exceed one.
maximum_radius_clip (pint.Quantity) – Upper radius cutoff.
bins (int, default=0) – Optional number of radius bins.
- class NormalRadiusSampler#
Bases:
RadiusSamplerClipped normal distribution of particle radii.
- Parameters:
mean (pint.Quantity) – Parameters of the normal distribution.
standard_deviation (pint.Quantity) – Parameters of the normal distribution.
maximum_clip (pint.Quantity, optional) – Upper radius cutoff. Defaults to
mean + 5 * standard_deviation.bins (int, default=0) – Optional number of radius bins.
- class RadiusSampler#
Bases:
pybind11_objectBase class for particle-radius distributions.
Notes
Concrete samplers generate radii in SI units internally. Their Python constructors accept Pint quantities and
to_binsreturns radii in meters.- property number_of_bins#
Number of bins; zero means that binning is disabled.
- Type:
int
- plot_histogram(self: PackLab.samplers.RadiusSampler, ax: object = None, unit: object = 'nanometer', **kwargs) object#
Plot the binned radius distribution as a probability-mass histogram.
The bars show the representative radius classes and normalized number fractions returned by
to_bins(). Continuous samplers therefore requirebinsto be positive.- Parameters:
ax (matplotlib.axes.Axes, optional) – Axes receiving the bars. The current axes are used when omitted.
unit (str or pint.Unit, default="nanometer") – Unit used on the radius axis.
**kwargs – Additional keyword arguments forwarded to
matplotlib.axes.Axes.bar().
- Returns:
The axes containing the histogram.
- Return type:
matplotlib.axes.Axes
- set_number_of_bins(self: PackLab.samplers.RadiusSampler, bins: SupportsInt | SupportsIndex) None#
Set the number of discrete radius bins.
- Parameters:
bins (int) – Number of bins. A value of zero disables binning.
- to_bins(self: PackLab.samplers.RadiusSampler) tuple[object, numpy.typing.NDArray[numpy.float64]]#
Convert the distribution to representative discrete radius classes.
- Returns:
radii (pint.Quantity, shape (n_bins,)) – Representative radii in meters.
weights (numpy.ndarray, shape (n_bins,))
Normalized probability weights.
- class UniformRadiusSampler#
Bases:
RadiusSamplerUniform distribution of particle radii.
- Parameters:
minimum_radius (pint.Quantity) – Inclusive bounds of the radius distribution.
maximum_radius (pint.Quantity) – Inclusive bounds of the radius distribution.
bins (int, default=0) – Optional number of radius bins.
Monte-Carlo hard-sphere workflows#
Packing domain#
- class PackingDomain#
Bases:
pybind11_objectThree-dimensional rectangular domain for random sequential addition.
- Parameters:
length_x (pint.Quantity) – Positive box lengths, convertible to meters.
length_y (pint.Quantity) – Positive box lengths, convertible to meters.
length_z (pint.Quantity) – Positive box lengths, convertible to meters.
use_periodic_boundaries (bool) – Whether to apply periodic boundary conditions on all three axes.
- property length_x#
Length of the x axis in meters.
- Type:
pint.Quantity
- property length_y#
Length of the y axis in meters.
- Type:
pint.Quantity
- property length_z#
Length of the z axis in meters.
- Type:
pint.Quantity
- scale(self: PackLab.monte_carlo.domain.PackingDomain, scale_factor: SupportsFloat | SupportsIndex) None#
Scale all box lengths in place.
- Parameters:
scale_factor (float) – Positive multiplicative scale factor.
- property use_periodic_boundaries#
Whether periodic boundary conditions are enabled.
- Type:
bool
- property volume#
Box volume in cubic meters.
- Type:
float
RSA simulation#
Random sequential addition of non overlapping spheres in a 3D box
- class PackingConfiguration#
Bases:
pybind11_objectSphere centers, radii, and size-class labels of a packing.
- property classes_index#
Integer class index for each sphere
- property count#
Number of spheres in the configuration.
- property number_of_classes#
Number of distinct particle radius classes
- property positions#
List of sphere center positions
- property radii#
List of sphere radii
- total_sphere_volume(self: PackLab.monte_carlo.simulator.PackingConfiguration) object#
Compute the total volume occupied by the spheres.
- class RSAOptions#
Bases:
pybind11_objectStopping criteria and numerical settings for an RSA simulation.
- maximum_attempts#
Total trial-insertion limit.
- Type:
int
- maximum_spheres#
Sphere-count limit; zero disables this criterion.
- Type:
int
- target_packing_fraction#
Target volume fraction; zero disables this criterion.
- Type:
float
- class RSASimulator#
Bases:
pybind11_objectRandom Sequential Addition simulator for non-overlapping spheres.
- Parameters:
domain (PackingDomain) – Spatial domain and boundary conditions.
radius_sampler (RadiusSampler) – Distribution used for candidate sphere radii.
options (RSAOptions) – Stopping criteria and numerical settings.
Notes
Call
run()to generate aPackingResult.- reset(self: PackLab.monte_carlo.simulator.RSASimulator) None#
Reset the simulation to its initial state.
- run(self: PackLab.monte_carlo.simulator.RSASimulator) object#
Run the simulation and return a PackingResult.
- property sphere_configuration#
Current sphere configuration
Metropolis sampling#
Equilibrium Metropolis sampling for hard-sphere configurations.
- class MetropolisOptions#
Bases:
pybind11_objectNumerical settings for fixed-volume hard-sphere Metropolis sampling.
The maximum displacement is the maximum absolute displacement proposed along each coordinate in one move. Tune it to obtain a practical acceptance rate.
- property maximum_displacement#
Maximum absolute displacement along each coordinate.
- Type:
pint.Quantity
- class MetropolisSimulator#
Bases:
pybind11_objectEquilibrate a non-overlapping hard-sphere configuration using Metropolis moves.
- Parameters:
domain (PackingDomain) – Fixed simulation domain and boundary conditions.
initial_configuration (PackingConfiguration) – Valid, non-overlapping configuration, for example from
RSASimulator.options (MetropolisOptions) – Sweep count, proposal displacement, and seed.
Notes
This sampler holds particle count, radii, and class labels fixed. It is an equilibrium workflow and is not a continuation of RSA deposition.
- reset(self: PackLab.monte_carlo.metropolis.MetropolisSimulator) None#
Restore the supplied initial configuration.
- run(self: PackLab.monte_carlo.metropolis.MetropolisSimulator) object#
Run all configured sweeps and return a PackingResult.
- property sphere_configuration#
Current configuration after accepted displacement moves.
- property statistics#
Metropolis displacement-move statistics.
- class MetropolisStatistics#
Bases:
pybind11_objectMove statistics from an equilibrium hard-sphere Metropolis simulation.
Unlike
PackingStatistics, these counters describe displacement moves, not RSA insertion attempts.
Results and visualisation#
- post_mpl_plot(plot_function)[source]#
Return a plotting wrapper with the former
showconvenience option.
- class PackingResult(binding)[source]#
Bases:
objectOutput container for an RSA simulation run.
Holds arrays plus domain metadata, computed statistics, and plotting helpers.
- property positions: ndarray#
Get the sphere center positions as a NumPy array of shape (N, 3).
- Returns:
Array of sphere center positions.
- Return type:
np.ndarray
- property radii: ndarray#
Get the sphere radii as a NumPy array of shape (N,).
- Returns:
Array of sphere radii.
- Return type:
np.ndarray
- property statistics#
Get the simulation statistics.
- Returns:
The simulation statistics.
- Return type:
Statistics
- property sphere_configuration#
Get the sphere configuration object.
- Returns:
The configuration of spheres in the simulation.
- Return type:
SphereConfiguration
- property domain#
Get the simulation domain.
- Returns:
The domain (box) dimensions and boundary conditions.
- Return type:
Domain
- compute_partial_pair_correlation_function(**kwargs) tuple[source]#
Compute the partial pair correlation function g_ij(r).
- Parameters:
**kwargs (dict) – Keyword arguments passed to the binding method.
- Returns:
A tuple containing: - centers (Quantity): The radial distances with units. - g_ij (np.ndarray): The partial pair correlation values.
- Return type:
tuple
- property partial_volume_fractions: ndarray#
Get the partial volume fractions of each component.
- Returns:
Array of partial volume fractions.
- Return type:
np.ndarray
- property partial_volumes: ndarray#
Get the partial volumes of each component.
- Returns:
Array of partial volumes.
- Return type:
np.ndarray
- compute_pair_correlation_function(**kwargs) None[source]#
Compute the total pair correlation function g(r).
- Parameters:
**kwargs (dict) – Keyword arguments passed to the binding method.
- property pair_correlation_centers: ndarray#
Get the radial centers for the pair correlation function.
- Returns:
Array of radial centers.
- Return type:
np.ndarray
- property pair_correlation_values: ndarray#
Get the values of the pair correlation function g(r).
- Returns:
Array of pair correlation values.
- Return type:
np.ndarray
- plot_centers_3d(maximum_points_3d: int = 10000) Figure[source]#
Plot the sphere centers in a 3D scatter plot.
- Parameters:
maximum_points_3d (int) – Maximum number of points to plot (subsampling if necessary).
- Returns:
The matplotlib Figure object containing the 3D scatter plot.
- Return type:
plt.Figure
- plot_radius_distribution(bins: int = 40, density: bool = True, alpha: float = 0.85) Figure[source]#
Plot the distribution of sphere radii.
- Parameters:
bins (int) – Number of histogram bins.
density (bool) – Whether to normalize the histogram to form a probability density.
alpha (float) – Transparency level for the histogram bars.
- plot_slice_2d(slice_axis: Literal['x', 'y', 'z'] = 'z', slice_center_fraction: float = 0.5, slice_thickness_fraction: float = 0.08, maximum_circles_in_slice: int = 2500) Figure[source]#
Plot a 2D slice of the sphere configuration.
- Parameters:
slice_axis (Literal["x", "y", "z"]) – Axis along which to take the slice.
slice_center_fraction (float) – Fractional position along the slice axis where the slice is centered (0.0 to 1.0).
slice_thickness_fraction (float) – Fractional thickness of the slice relative to the box length along the slice axis (0.0 to 1.0).
maximum_circles_in_slice (int) – Maximum number of circles to plot in the slice (subsampling if necessary).
- plot_pair_correlation(n_bins: int = 80, maximum_pairs: int = 300000) Figure[source]#
Plot the partial pair correlation functions g_ij(r) obtained from the RSA configuration, overlaying all (i, j) curves on a single axis.
- Parameters:
n_bins (int) – Number of radial distance bins.
maximum_pairs (int) – Number of Monte Carlo sampled pairs used for estimation.
- Returns:
Figure containing the overlaid plot of all g_ij(r) curves.
- Return type:
matplotlib.figure.Figure
Statistics and ensemble estimates#
- class PackingStatistics#
Bases:
pybind11_objectSummary statistics from an RSA simulation.
- sphere_count#
Number of accepted spheres.
- Type:
int
- packing_fraction_geometry#
Packing fraction calculated from accepted sphere volumes.
- Type:
float
- total_runtime_seconds#
Wall-clock runtime of the simulation.
- Type:
float
- print(self: PackLab.monte_carlo.statistics.PackingStatistics) None#
Print a human-readable statistics summary.
- class EstimatorStatistics#
Bases:
pybind11_objectAggregate diagnostics from the most recent
PackingEstimator.estimatecall.- requested_samples, completed_samples
Requested and successfully completed RSA realisations.
- Type:
int
- attempted_insertions, accepted_insertions, rejected_insertions
Totals over all completed realisations.
- Type:
int
- acceptance_rate#
Accepted insertions divided by attempted insertions.
- Type:
float
- mean_sphere_count, mean_packing_fraction
Per-realisation means.
- Type:
float
- total_runtime_seconds, mean_runtime_seconds
Wall-clock simulation times.
- Type:
float
- print(self: PackLab.monte_carlo.estimator.EstimatorStatistics) None#
Print a tabular summary of the aggregate diagnostics.
- class PackingEstimate#
Bases:
pybind11_objectEnsemble estimate of partial pair-correlation functions.
- centers#
Radial bin centers in meters.
- Type:
pint.Quantity, shape (n_bins,)
- mean_g, std_g
Mean and sample standard deviation of partial pair correlations.
- Type:
numpy.ndarray, shape (n_species, n_species, n_bins)
- class PackingEstimator#
Bases:
pybind11_objectEstimate pair-correlation statistics over repeated RSA simulations.
- Parameters:
domain (PackingDomain) – Simulation domain.
radius_sampler (RadiusSampler) – Particle-radius distribution.
options (RSAOptions) – RSA simulation configuration.
number_of_bins (int) – Number of radial bins used for each estimate.
- estimate(self: PackLab.monte_carlo.estimator.PackingEstimator, number_of_samples: SupportsInt | SupportsIndex, maximum_pairs: SupportsInt | SupportsIndex = 0, progress: bool = False, progress_interval: SupportsInt | SupportsIndex = 1) PackLab.monte_carlo.estimator.PackingEstimate#
Estimate partial pair correlations from independent RSA realizations.
- Parameters:
number_of_samples (int) – Number of independent packing realizations.
maximum_pairs (int, default=0) – Pair-sampling limit per realization; zero selects the native default.
progress (bool, default=False) – Print completed-sample progress and per-sample insertion diagnostics.
progress_interval (int, default=1) – Print every this many completed samples when
progress=True.
- Returns:
Mean and standard deviation of the partial pair-correlation functions.
- Return type:
- print_statistics(self: PackLab.monte_carlo.estimator.PackingEstimator) None#
Print aggregate diagnostics from the most recent estimate.
- property statistics#
Aggregate diagnostics from the most recent estimate.
Analytical model#
Mixture domain#
Polydisperse cubic domain (analytical) with unit handling performed in the pybind11 wrapper.
This module exposes a C++ implementation of a cubic simulation domain containing a polydisperse population of spherical particles. The numerical core operates in base SI units (meters), while the Python interface accepts and returns Pint quantities.
Key conventions#
All lengths are stored internally in meters.
Radii arrays are returned as Pint quantities in meters.
Volumes are returned as Pint quantities in meter**3.
Number densities are returned as Pint quantities in 1/meter**3.
Fractions (number fractions and volume fractions) are dimensionless NumPy arrays.
The domain is specified by: - size: cubic side length - radii: per bin particle radii - volume_fraction: total occupied volume fraction - number_fractions: per bin number fractions (normalized to sum to 1)
The class provides deterministic conversion from fractional counts to integer particle counts using the configured rounding mode.
- class PercusYevickDomain#
Bases:
pybind11_objectCubic simulation domain containing a polydisperse population of spherical particles.
The numerical core stores all lengths in meters and all fractions as dimensionless floating point values. The wrapper converts Pint quantities to meters on input and reconstructs Pint quantities on output.
- Parameters:
size (pint.Quantity) – Side length of the cubic domain. Converted to meters internally.
radii (pint.Quantity[ndarray]) – One dimensional array of particle radii defining the bins. Converted to meters internally.
volume_fraction (float) – Total occupied volume fraction (dimensionless). Typical range is (0, 1].
number_fractions (array_like of float) – Number fractions per bin. Must be non negative and sum to a positive value. The constructor normalizes them to sum to 1.
rounding_mode (RoundingMode, default=floor) – Rounding mode used when converting expected counts to integers.
Notes
The model uses number fractions and a total volume fraction as its sole specification mechanism. Alternative specifications should use separate constructors. Returned arrays are NumPy arrays; quantities use SI units (meter, meter**3, 1/meter**3).
- bins_table(self: PackLab.analytical.domain.PercusYevickDomain, precision: SupportsInt | SupportsIndex = 6) str#
Return the per bin table as a string.
- Parameters:
precision (int, default=6) – Significant digits used for numeric formatting.
- Returns:
Formatted table in base units.
- Return type:
str
- property mean_particle_volume_number_weighted#
Number weighted mean particle volume.
- Returns:
Mean per particle volume in meter**3 computed using number_fractions as weights.
- Return type:
pint.Quantity
- property number_fractions#
Per bin number fractions.
- Returns:
One dimensional array of number fractions (dimensionless). Always normalized to sum to 1.
- Return type:
numpy.ndarray
- property number_of_particles_per_radius#
Per bin integer particle counts.
- Returns:
One dimensional integer array of particle counts per radius bin.
- Return type:
numpy.ndarray
- property number_of_particles_total#
Total inferred particle count.
This is computed from: - total_particle_volume = volume_fraction * volume - mean_particle_volume_number_weighted and then rounded according to rounding_mode.
- Returns:
Total integer particle count.
- Return type:
int
- property particle_densities_per_radius#
Per bin number densities.
- Returns:
One dimensional array of number densities in 1/meter**3.
- Return type:
pint.Quantity[ndarray]
- property particle_density_total#
Total number density over all bins.
- Returns:
Total number density in 1/meter**3.
- Return type:
pint.Quantity
- property particle_volumes#
Per bin particle volumes.
- Returns:
One dimensional array of per particle volumes in meter**3 computed as (4/3)π r^3.
- Return type:
pint.Quantity[ndarray]
- print_bins(self: PackLab.analytical.domain.PercusYevickDomain, precision: SupportsInt | SupportsIndex = 6) None#
Print a per bin table describing the polydisperse population.
The table is printed in base units and includes: - radius (m) - per particle volume (m^3) - number fraction (dimensionless) - volume fraction (dimensionless) - particle count (integer) - number density (1/m^3)
- Parameters:
precision (int, default=6) – Significant digits used for numeric formatting.
- Return type:
None
- property radii#
Particle radii bins.
- Returns:
One dimensional Pint quantity array of radii in meters.
- Return type:
pint.Quantity[ndarray]
- sample_radii(self: PackLab.analytical.domain.PercusYevickDomain, number_of_samples: SupportsInt | SupportsIndex, seed: object = None) object#
Sample particle radii according to number_fractions.
- Parameters:
number_of_samples (int) – Number of radii draws.
seed (Optional[int]) – RNG seed. If None, a non deterministic seed is used.
- Returns:
One dimensional Pint quantity array of sampled radii in meters.
- Return type:
pint.Quantity[ndarray]
- property size#
PYDomain side length.
- Returns:
The cubic side length as a Pint quantity in meters.
- Return type:
pint.Quantity
- property total_particle_volume#
Total occupied particle volume.
- Returns:
Total occupied volume in meter**3 computed as volume_fraction * volume.
- Return type:
pint.Quantity
- property volume#
PYDomain volume.
- Returns:
Total cubic volume in meter**3.
- Return type:
pint.Quantity
- property volume_fraction#
Total occupied volume fraction.
- Returns:
Dimensionless occupied volume fraction used to infer total particle volume.
- Return type:
float
- property volume_fraction_per_radius#
Per bin occupied volume fractions.
- Returns:
One dimensional array of per bin volume fractions (dimensionless).
- Return type:
numpy.ndarray
- class RoundingMode#
Bases:
pybind11_objectRounding mode used when converting expected (non integer) particle counts to integers.
flooralways rounds down.roundrounds to the nearest integer. The selected mode affects particle counts and densities derived from the supplied number fractions.Members:
floor
round
- RoundingMode.name -> str
Wavenumber grids#
Utilities for constructing reciprocal-space grids.
- make_wavenumber_grid(radial_resolution: Any, maximum_distance: Any, samples_per_oscillation: int = 12) Any[source]#
Create a reciprocal-space grid for the radial inverse transform.
- Parameters:
radial_resolution (pint.Quantity) – Smallest real-space feature to resolve. It determines the maximum wavenumber through
pi / radial_resolution.maximum_distance (pint.Quantity) – Largest real-space distance at which the correlation function will be evaluated. It determines the wavenumber spacing.
samples_per_oscillation (int, default=12) – Samples used for one period of the sinc kernel at
maximum_distance. Values below 8 are not recommended.
- Returns:
A uniformly spaced, zero-inclusive wavenumber grid with units of inverse length.
- Return type:
pint.Quantity
Percus–Yevick solver#
Percus Yevick mixture solver (C++ core, Pint handled in wrapper).
- class PercusYevickResult#
Bases:
pybind11_objectResult of a multicomponent Percus-Yevick calculation.
- radii#
Particle radii in meters.
- Type:
pint.Quantity, shape (n_species,)
- densities#
Number densities in inverse cubic meters.
- Type:
pint.Quantity, shape (n_species,)
- wavenumber#
Wavenumber grid in inverse meters used for the inverse transform.
- Type:
pint.Quantity, shape (n_wavenumber,)
- g, h, H
Real-space and reciprocal-space correlation functions.
- Type:
numpy.ndarray
- class PercusYevickSolver#
Bases:
pybind11_objectSolve the multicomponent Percus-Yevick hard-sphere model.
- Parameters:
densities (pint.Quantity, shape (n_species,)) – Species number densities, convertible to inverse cubic meters.
radii (pint.Quantity, shape (n_species,)) – Species radii, convertible to meters.
wavenumber (pint.Quantity or "auto", default="auto") – Strictly increasing wavenumber grid, convertible to inverse meters.
"auto"derives a grid whencompute()receives the requested distances.radial_resolution (pint.Quantity or None, optional) – Smallest real-space feature to resolve when
wavenumber="auto". By default this is one twentieth of the smallest particle radius.samples_per_oscillation (int, default=12) – Reciprocal-space samples per sinc-kernel oscillation at the largest requested distance when
wavenumber="auto". Must be at least 8.
Notes
The inverse radial transform must resolve the sinc kernel at the largest requested distance.
compute()emits aRuntimeWarningwhen this grid has fewer than eight samples per kernel oscillation. UsePackLab.analytical.make_wavenumber_gridto construct a balanced grid.- compute(self: PackLab.analytical.solver.PercusYevickSolver, distances: object) PackLab.analytical.solver.PercusYevickResult#
Compute the correlation functions on a real-space distance grid.
- Parameters:
distances (pint.Quantity, shape (n_r,)) – Radial positions, convertible to meters.
- Returns:
Computed structural and correlation functions.
- Return type:
Scattering tools#
Data containers#
- class ScatteringData(S1: Any, S2: Any, k: Any, Csca: Any, phi: Any)[source]#
Bases:
objectFar-field scattering data for a single particle diameter.
The quantity-bearing fields intentionally use
Anybecause TypedUnit/Pint quantities are generic at runtime and may wrap scalar or array values.
- class ScatteringDataset(iterable=(), /)[source]#
Bases:
listContainer for multi size scattering data and mixture level post processing.
This class stores
ScatteringDatainstances, one for each diameter. It also provides mixture formulas for a number density distribution over diameters and an inter particle correlation term H(wavenumber).- e_theta, e_phi
Unit basis vectors for the polarization basis used in get_F_matrix. This code treats the scattering amplitude as a 2 component vector in a (theta, phi) polarization basis.
- Type:
NDArray, shape (2,)
- k#
Optical wavenumber in the surrounding medium (1/length).
- phi#
Polar scattering angle grid in radians. Expected range is [0, pi].
- S1, S2
Arrays assembled by process() from each per diameter element.
- Csca#
Per diameter scattering cross section assembled by process().
Notes
Derived arrays are refreshed automatically by the mixture methods. Calling
process()explicitly remains useful when inspecting those arrays.- process()[source]#
Stack per diameter fields into dense arrays.
After calling this method, the object provides:
self.S1: ndarray, shape (N, Pphi)
self.S2: ndarray, shape (N, Pphi)
self.Csca: Pint Quantity, shape (N,), units meter**2
where N is the number of diameters (len(self)) and Pphi is the number of angular samples in each per diameter result.
- Return type:
None
- get_alpha_beta_factor(densities: ndarray[tuple[int, ...], dtype[_ScalarType_co]]) tuple[ndarray[tuple[int, ...], dtype[_ScalarType_co]], ndarray[tuple[int, ...], dtype[_ScalarType_co]]][source]#
Build number density factors for mixture sums.
- Parameters:
densities (NDArray, shape (N,)) – Species number densities n_alpha. Units should be 1/length**3. N must match the number of size classes stored in this object.
- Returns:
n_alpha (NDArray, shape (N,)) – Same array as input (returned for convenience).
sqrt_alpha_beta (NDArray, shape (N, N)) – Matrix with entries sqrt(n_alpha * n_beta). This is commonly used in symmetric mixture formulations to weight cross correlations.
Notes
This uses the outer product and then takes a square root:
sqrt_alpha_beta[a, b] = sqrt(n_alpha[a] * n_alpha[b])
- get_F_matrix(theta_points: int = 100) tuple[source]#
Construct the vector scattering amplitude tensor F for each size, angle, and azimuth.
This builds a 2 component vector amplitude in the (e_theta, e_phi) basis using the convention in your code:
F(θ_azimuth, φ_polar) = (i / k) * [ e_theta * S2(φ) * cos(θ) - e_phi * S1(φ) * sin(θ) ]
- Parameters:
theta_points – Number of azimuthal sampling points in [0, 2*pi]. This is a rotation around the incident axis.
- Returns:
F (NDArray, complex, shape (2, N, Pphi, Ptheta)) – Vector amplitude tensor.
Index meaning: * first axis (size 2): polarization component (theta, phi) * second axis: size class index (N) * third axis: polar scattering angle samples (Pphi), from self.phi * fourth axis: azimuthal angle samples (Ptheta), generated internally
theta (NDArray, shape (Ptheta,)) – Azimuthal angle grid in radians spanning [0, 2*pi].
Notes
The name theta here refers to an azimuthal angle. The polar scattering angle is stored in self.phi.
- get_mu_independant(densities: ndarray[tuple[int, ...], dtype[_ScalarType_co]])[source]#
Compute the independent scattering contribution to the attenuation coefficient.
- Parameters:
densities (NDArray, shape (N,)) – Species number densities n_alpha. Units should be 1/length**3.
- Returns:
Scalar attenuation coefficient contribution with units 1/length.
- Return type:
mu_independant_scattering
Notes
This implements a standard independent scattering approximation term:
mu_s,ind = sum_alpha n_alpha * Csca_alpha
The supplied density vector is validated against the number of species.
- get_mu_dependant(densities: ndarray[tuple[int, ...], dtype[_ScalarType_co]], H: ndarray[tuple[int, ...], dtype[_ScalarType_co]], wavenumber: ndarray[tuple[int, ...], dtype[_ScalarType_co]], theta_points: int = 150)[source]#
Compute the dependent scattering contribution using inter particle correlations H(wavenumber).
- Parameters:
densities (NDArray, shape (N,)) – Species number densities n_alpha. Units should be 1/length**3.
H (NDArray, shape (N, N, Pp)) – Mixture total correlation function in reciprocal space, evaluated on the wavenumber grid. This should correspond to the same ordering as size classes.
wavenumber (NDArray, shape (Pp,)) – Reciprocal space radial grid (1/length). Must cover the range needed to evaluate H at wavenumber = 2k sin(φ/2) for φ in [0, pi].
theta_points – Number of azimuthal samples for the integral over the rotation angle.
- Returns:
Scalar attenuation coefficient contribution. Units depend on the exact normalization conventions of F and H used in the integrand, but it is intended to be in 1/length.
- Return type:
mu_dependant_scattering
Notes
The core integrand is:
term[p_index, theta_index] = sum_{a,b} sqrt(n_a n_b) F_a(wavenumber,theta) F*_b(wavenumber,theta) H_ab(wavenumber)
then integrated over polar angle (self.phi) and azimuth (theta).
- get_mu(densities: ndarray[tuple[int, ...], dtype[_ScalarType_co]], H: ndarray[tuple[int, ...], dtype[_ScalarType_co]], wavenumber: ndarray[tuple[int, ...], dtype[_ScalarType_co]], theta_points: int = 150) ndarray[tuple[int, ...], dtype[_ScalarType_co]][source]#
Compute total scattering attenuation coefficient mu_s.
- Parameters:
densities (NDArray, shape (N,)) – Species number densities.
H (NDArray, shape (N, N, Pp)) – Correlation function in wavenumber space.
wavenumber (NDArray, shape (Pp,)) – wavenumber space grid (1/length).
theta_points – Azimuthal sampling count.
- Returns:
Total scattering attenuation coefficient (intended units 1/length), computed as:
mu = mu_independant + mu_dependant
- Return type:
mu
- interpolate_last_axis_linear(H: ndarray, wavenumber: ndarray, evaluation_wavenumber: ndarray) ndarray[source]#
Linear interpolation of H(…, wavenumber) onto evaluation_wavenumber, along the last axis.
- Parameters:
H (ndarray, shape (..., Pp)) – Values sampled on grid wavenumber along the last axis.
wavenumber (ndarray, shape (Pp,)) – Strictly increasing sample points.
evaluation_wavenumber (ndarray, shape (Pq,)) – Query points.
- Returns:
Interpolated values.
- Return type:
ndarray, shape (…, Pq)
- get_interpolated_H(H, wavenumber)[source]#
Interpolate H(wavenumber) onto the scattering wavevector magnitude wavenumber = 2k sin(φ/2).
- Parameters:
H (array like, shape (N, N, Pp)) – Correlation tensor sampled on the input wavenumber grid.
wavenumber (array like, shape (Pp,)) – Radial reciprocal space grid (1/length).
- Returns:
interpolated_H – H evaluated at the scattering wavenumber for φ in [0, pi], where:
wavenumber(φ) = 2 k sin(φ/2)
- Return type:
NDArray, shape (N, N, Pphi)
Notes
This method assumes: * self.phi spans [0, pi] and is the polar scattering angle * wavenumber is provided in increasing order
- get_phase_function(densities: ndarray[tuple[int, ...], dtype[_ScalarType_co]], H: ndarray[tuple[int, ...], dtype[_ScalarType_co]], wavenumber: ndarray[tuple[int, ...], dtype[_ScalarType_co]], theta_points: int = 150) tuple[ndarray[tuple[int, ...], dtype[_ScalarType_co]], ndarray[tuple[int, ...], dtype[_ScalarType_co]], ndarray[tuple[int, ...], dtype[_ScalarType_co]]][source]#
Compute the mixture phase function including dependent scattering corrections.
- Parameters:
densities (NDArray, shape (N,)) – Species number densities n_alpha.
H (NDArray, shape (N, N, Pp)) – Correlation tensor in reciprocal space on the wavenumber grid.
wavenumber (NDArray, shape (Pp,)) – wavenumber space grid (1/length).
theta_points – Number of azimuthal samples.
- Returns:
phi (ndarray, shape (Pphi,)) – Polar angle grid in radians.
theta (ndarray, shape (Ptheta,)) – Azimuthal angle grid in radians.
phase_function (NDArray, shape (Pphi, Ptheta)) – Phase function indexed first by polar angle, then by azimuth.
Notes
The phase function is assembled as:
Independent term: sum of
n |F|^2over species.Dependent term: weighted cross terms involving
F, its conjugate, and the correlation tensorH.
Amplitude generation#
- compute_scattering_amplitudes(wavelength: Length, diameters: Length, material: RefractiveIndex, medium: RefractiveIndex, phi: Angle, plot: bool = False, polarization: float = <Quantity(0, 'degree')>, debug_mode: bool = False) ScatteringDataset[source]#
Compute far field amplitude scattering functions S1 and S2 for a set of sphere diameters.
This helper constructs a Gaussian source and a Sphere scatterer for each diameter, calls Setup.get_s1s2(…), and stores the resulting objects in a ScatteringDataset container.
- Parameters:
phi – Angle grid relative to the transverse plane. The amplitudes are evaluated at
phi + pi / 2and the returned dataset stores this physical polar-angle grid in the interval[0, pi].diameters – Iterable of particle diameters. Each element is expected to be a Pint Quantity with length units (for example 6 * ureg.nanometer).
plot – If True, call data.plot(…) for each diameter.
- Returns:
A list like container where each element is the return value of Setup.get_s1s2(angles=…). Additional attributes are attached:
datas.k: optical wavenumber of the source (1/length)
datas.phi: angular sampling grid taken from the first result (radians)
after calling datas.process(), arrays S1, S2, Csca are available
- Return type:
Notes
This function sets two extra attributes on each data element:
data.k is set to source.wavenumber
data.Csca is set to scatterer.Csca
The ScatteringDataset instance also receives k and phi from the last and first element respectively. If you want stricter correctness, you should assert that all returned data.phi grids are identical.
Phase-function plots#
- plot_phase_function_3d(phi: ndarray, theta: ndarray, phase_function: ndarray, *, mode: Literal['spherical', 'surface'] = 'spherical', normalize: bool = True, use_magnitude: bool = True) Figure[source]#
Plot a 3D representation of the phase function P(phi, theta).
- Parameters:
phi – Polar scattering angle grid in radians, expected in [0, pi].
theta – Azimuthal angle grid in radians, expected in [0, 2*pi].
phase_function – Phase function sampled on (phi, theta) or (theta, phi).
mode – “spherical”: map intensity to radius on a sphere and render a 3D surface. “surface”: plot a 3D surface with axes (theta, phi, P).
normalize – If True, normalize the plotted values by their maximum for visual clarity.
use_magnitude – If True, plot abs(P). If False, plot real(P).
- Returns:
Matplotlib figure containing the 3D plot.
- Return type:
figure
Notes
In “spherical” mode, the surface is parameterized as:
x = r * sin(phi) * cos(theta) y = r * sin(phi) * sin(theta) z = r * cos(phi)
where r is the (optionally normalized) phase function.
- plot_phase_function_2d_projection(phi: ndarray, theta: ndarray, phase_function: ndarray, *, projection: Literal['azimuth_average', 'heatmap'] = 'azimuth_average', use_magnitude: bool = True, normalize: bool = False) Figure[source]#
Plot a 2D representation of the phase function.
- Parameters:
phi – Polar scattering angle grid in radians, expected in [0, pi].
theta – Azimuthal angle grid in radians, expected in [0, 2*pi].
phase_function – Phase function sampled on (phi, theta) or (theta, phi).
projection – “azimuth_average”: plot P_avg(phi) = (1/2pi) * integral P(phi,theta) dtheta. “heatmap”: plot a 2D image of P(phi,theta) with axes theta and phi.
use_magnitude – If True, plot abs(P). If False, plot real(P).
normalize – If True, normalize plotted values by their maximum.
- Returns:
Matplotlib figure containing the 2D plot.
- Return type:
figure
Notes
The azimuth averaged projection is the closest analogue to typical S1 and S2 plots because it reduces the 2D angular dependence into a 1D curve versus phi.