API Reference
Complete reference for the public symbols exported by pyFracAggregate
(the package’s __all__), grouped by layer: the top-level facade, the core
data structures and scaling laws, the two generation algorithms, the
analysis functions, the I/O exporters, and the placement strategies.
Top-level API
The facade functions cover the common workflow: build an aggregate with
generate() (which validates the method × scaling × placement
coordinate and dispatches), then summarize its morphology with analyze()
(returning a MorphologyReport).
- pyFracAggregate.generate(n_particles: int, df: float, kf: float, method: Literal['pca', 'cca'] = 'pca', scaling: Literal['count', 'mass'] = 'mass', placement: Literal['sampled', 'solved', 'constructed'] = 'solved', particle_dist: ParticleDistribution | None = None, overlap_tolerance: float = 1e-05, seed: int | None = None, **kwargs) Aggregate[source]
High-level API to generate a fractal aggregate.
- Parameters:
n_particles (int) – Target number of particles.
df (float) – Fractal dimension (typically 1.5 - 2.5).
kf (float) – Fractal prefactor (typically 1.0 - 2.0).
method (str) – Algorithm family: ‘pca’ (particle-cluster) or ‘cca’ (cluster-cluster). ‘fracval’ is a deprecated alias for (cca, mass, constructed).
scaling (str) – ‘count’ (Filippov 2000 count weighting) or ‘mass’ (Moran 2019 mass weighting; polydispersity-correct). Default ‘mass’.
placement (str) – ‘sampled’ (Monte Carlo), ‘solved’ (closed-form tangency; default), or ‘constructed’ (FracVAL contact construction; cca only).
particle_dist – Particle radius distribution (defaults to Monodisperse(1.0)).
overlap_tolerance (float) – Allowed overlap between spheres.
seed (int) – Seed for reproducible generation (None = fresh entropy).
- Returns:
The generated fractal aggregate.
- Return type:
- pyFracAggregate.analyze(aggregate: Aggregate, estimator: Literal['sandbox', 'pcf'] = 'sandbox') MorphologyReport[source]
Compute the core morphological properties of an aggregate.
- Parameters:
aggregate (Aggregate) – Cluster object.
estimator (str) – ‘sandbox’ (default) fits the cumulative mass-radius curves <N(r)> and <M(r)> — statistically robust for both measures; ‘pcf’ fits the differenced pair-correlation curves C(r) and C_m(r) — the counting path is the classic estimator, the mass path is noisy on single realizations.
Core
Aggregate is the central data structure every other layer produces or
consumes: a pre-allocated (max_particles, 5) NumPy array of
[x, y, z, radius, mass] rows whose positions, radii, and masses
properties are zero-copy views. The distribution classes describe
primary-particle sizes and are passed to generators via the particle_dist
argument; the scaling laws own the parallel-axis target-distance equations
(count- vs mass-weighted).
- class pyFracAggregate.core.aggregate.Aggregate(max_particles: int, length_unit: str = 'nm', mass_unit: str = 'g', density: float = 1.0)[source]
Core physical entity representing a fractal cluster.
Uses pre-allocated contiguous memory via NumPy for high data locality and access performance.
- add_particle(x: float, y: float, z: float, r: float, m: float) None[source]
Adds a new particle. O(1) complexity.
- property masses: ndarray
Gets particle masses.
- Returns:
A zero-copy view with shape (N,).
- Return type:
np.ndarray
- property positions: ndarray
Gets particle coordinates.
- Returns:
A zero-copy view with shape (N, 3).
- Return type:
np.ndarray
- class pyFracAggregate.core.distributions.Monodisperse(radius: float)[source]
Monodisperse distribution (all particles have the same radius).
- sample(n: int, rng: Generator | None = None) ndarray[source]
Samples n particle sizes.
- Parameters:
n (int) – Number of particle sizes to generate.
rng (np.random.Generator, optional) – Random generator; None uses NumPy’s global legacy stream.
- Returns:
An array of particle sizes with shape (n,).
- Return type:
np.ndarray
- class pyFracAggregate.core.distributions.LognormalDistribution(mean: float, std: float)[source]
Lognormal distribution.
- sample(n: int, rng: Generator | None = None) ndarray[source]
Samples n particle sizes.
- Parameters:
n (int) – Number of particle sizes to generate.
rng (np.random.Generator, optional) – Random generator; None uses NumPy’s global legacy stream.
- Returns:
An array of particle sizes with shape (n,).
- Return type:
np.ndarray
- class pyFracAggregate.core.distributions.FixedRadii(radii: ndarray)[source]
Replays a pre-sampled radius array verbatim.
Used to seed CCA subclusters from an already-sampled global distribution.
- sample(n: int, rng: Generator | None = None) ndarray[source]
Samples n particle sizes.
- Parameters:
n (int) – Number of particle sizes to generate.
rng (np.random.Generator, optional) – Random generator; None uses NumPy’s global legacy stream.
- Returns:
An array of particle sizes with shape (n,).
- Return type:
np.ndarray
- class pyFracAggregate.core.scaling.ScalingLaw(df: float, kf: float)[source]
Strategy for target distances in PCA steps and CCA merges.
- abstractmethod cca_gamma(agg1: Aggregate, agg2: Aggregate) float[source]
Required center-of-mass separation for merging two clusters.
- abstractmethod char_radius(radii: ndarray) float[source]
Characteristic primary radius for the scaling-law target.
- abstractmethod pca_step(agg: Aggregate, r_new: float, m_new: float, all_radii: ndarray) tuple[ndarray, float][source]
Reference center and step distance for adding one particle.
- Parameters:
agg – Aggregate with n-1 existing particles.
r_new – Radius of the incoming particle.
m_new – Mass of the incoming particle.
all_radii – Radii of all n particles (existing + incoming).
- Returns:
the placement reference point and the required distance of the new particle from it.
- Return type:
(center, distance)
- class pyFracAggregate.core.scaling.CountScaling(df: float, kf: float)[source]
Count-weighted parallel axis law (Filippov et al., 2000).
- cca_gamma(agg1: Aggregate, agg2: Aggregate) float[source]
Required center-of-mass separation for merging two clusters.
- char_radius(radii: ndarray) float[source]
Characteristic primary radius for the scaling-law target.
- pca_step(agg: Aggregate, r_new: float, m_new: float, all_radii: ndarray) tuple[ndarray, float][source]
Reference center and step distance for adding one particle.
- Parameters:
agg – Aggregate with n-1 existing particles.
r_new – Radius of the incoming particle.
m_new – Mass of the incoming particle.
all_radii – Radii of all n particles (existing + incoming).
- Returns:
the placement reference point and the required distance of the new particle from it.
- Return type:
(center, distance)
- class pyFracAggregate.core.scaling.MassScaling(df: float, kf: float)[source]
Mass-weighted parallel axis law (Moran et al., 2019, FracVAL).
- cca_gamma(agg1: Aggregate, agg2: Aggregate) float[source]
Required center-of-mass separation for merging two clusters.
- char_radius(radii: ndarray) float[source]
Characteristic primary radius for the scaling-law target.
- pca_step(agg: Aggregate, r_new: float, m_new: float, all_radii: ndarray) tuple[ndarray, float][source]
Reference center and step distance for adding one particle.
- Parameters:
agg – Aggregate with n-1 existing particles.
r_new – Radius of the incoming particle.
m_new – Mass of the incoming particle.
all_radii – Radii of all n particles (existing + incoming).
- Returns:
the placement reference point and the required distance of the new particle from it.
- Return type:
(center, distance)
Generators
Both algorithms share the BaseGenerator constructor contract
(n_particles, df, kf, particle_dist, overlap_tolerance, scaling, placement, seed) and each returns an Aggregate from its generate()
method. Users normally reach them through generate(method=...); the
classes are public for direct use and subclassing.
- class pyFracAggregate.generators.pca.PCAGenerator(n_particles: int, df: float, kf: float, particle_dist: ParticleDistribution, overlap_tolerance: float = 1e-05, length_unit: str = 'nm', mass_unit: str = 'g', density: float = 1.0, placement: str | PlacementStrategy = 'solved', scaling: ScalingLaw | str | None = None, seed: int | None = None, surface_beta: float | None = None, rng: Generator | None = None)[source]
Particle-Cluster Aggregation with pluggable placement strategy.
- class pyFracAggregate.generators.cca.CCAGenerator(n_particles: int, df: float, kf: float, particle_dist: ParticleDistribution, overlap_tolerance: float = 1e-05, length_unit: str = 'nm', mass_unit: str = 'g', density: float = 1.0, placement: str | PlacementStrategy = 'solved', scaling: ScalingLaw | str | None = None, seed: int | None = None, surface_beta: float | None = None, rng: Generator | None = None)[source]
Cluster-Cluster Aggregation with pluggable scaling and placement.
Analysis
Morphological descriptors computed from an Aggregate: global quantities
(radius of gyration, center of mass), per-measure fractal-dimension
estimators — the sandbox (mass-radius) family for the robust default, the
pair-correlation family for the classic counting path — and matplotlib
diagnostics. analyze(estimator=...) bundles both measures into a
MorphologyReport.
- class pyFracAggregate.MorphologyReport(rg: float, com: ndarray, n: int, estimator: str, df_num_est: float, r2_num: float, r_num: ndarray, num_correlation: ndarray, df_mass_est: float, r2_mass: float, r_mass: ndarray, mass_correlation: ndarray)[source]
Typed morphology summary of an aggregate, per measure.
estimatorrecords which family produced the report: “sandbox” (cumulative <N(r)>/<M(r)> curves, default) or “pcf” (differenced pair-correlation curves). Curve field contents follow the estimator; export_yaml serializes all fields under the v0.6 snapshot key names.
- pyFracAggregate.analysis.morphology.radius_of_gyration(aggregate: Aggregate) float[source]
Calculate the radius of gyration (Rg) of the aggregate. Uses the parallel axis theorem to account for the finite size of the primary particles. For a solid sphere, the radius of gyration about its own center is sqrt(3/5) * r.
- pyFracAggregate.analysis.morphology.center_of_mass(aggregate: Aggregate) ndarray[source]
Calculate the center of mass of the aggregate.
- Parameters:
aggregate (Aggregate) – The aggregate object.
- Returns:
A 1D array of shape (3,) representing the (x, y, z) coordinates of the center of mass.
- Return type:
np.ndarray
- pyFracAggregate.analysis.correlation.pair_correlation_function(aggregate: Aggregate, bins: int = 50, r_max: float | None = None) tuple[ndarray, ndarray][source]
Calculates the two-point density correlation function C(r).
Efficient calculation based on scipy.spatial.cKDTree.
C(r) = n(r) / (4 * pi * r^2 * h * N) where n(r) is the number of particle pairs between distance r and r+h, N is the total number of particles, and h is the step size (bin width).
- Parameters:
- Returns:
- (r_centers, C_r) where r_centers are the bin
center distances and C_r are the corresponding correlation values.
- Return type:
tuple[np.ndarray, np.ndarray]
- pyFracAggregate.analysis.correlation.mass_pair_correlation_function(aggregate: Aggregate, bins: int = 50, r_max: float | None = None) tuple[ndarray, ndarray][source]
Calculates the mass-weighted pair correlation function C_m(r).
Each pair (i, j) contributes weight m_i * m_j with m_i = r_i**3 (volume; with constant material density mass- and volume-weighting are identical up to a constant factor, so the slope is unaffected):
- C_m(r) = (sum of m_i*m_j over ordered pairs (i != j) with distance
in [r, r+h]) / (4 * pi * r^2 * h * M)
where M = sum_i m_i and h is the linear bin width. Each unordered pair contributes twice (once per endpoint), matching
pair_correlation_function’s ordered-pair counting so the two curves are absolutely comparable (monodisperse: C_m = r^3 * C).Statistical caveat: a single-realization C_m(r) is noisy — it is dominated by the few largest primaries (participation ratio sum(m)^2/sum(m^2) is small for lognormal radii). Prefer
mass_sandbox_dimensionfor a single aggregate’s Df,m; use this function for ensemble-averaged curves.
- pyFracAggregate.analysis.correlation.estimate_fractal_dimension(r_centers: ndarray, c_r: ndarray, r_min: float | None = None, r_max: float | None = None) tuple[float, float, dict][source]
Estimates the fractal dimension Df from the pair correlation function C(r).
Performs log-log linear regression on the fractal regime (a < r < Rg). Df is calculated as: Df = slope + 3.
- Parameters:
- Returns:
- (Df, R_squared, fit_results)
Df: Estimated fractal dimension.
R_squared: Coefficient of determination.
fit_results: Dictionary containing ‘slope’, ‘intercept’, ‘x_fit’, ‘y_fit’.
- Return type:
- pyFracAggregate.analysis.correlation.plot_pair_correlation(aggregate: Aggregate, bins: int = 50, show_fit: bool = True, reference_df: float | None = None, measure: str = 'num', save_path: str | None = None) None[source]
Plots the pair correlation function(s) and optionally the fractal fit.
- Parameters:
aggregate (Aggregate) – Cluster object.
bins (int) – Number of bins for the PCF.
show_fit (bool) – Whether to show the fractal dimension fit.
reference_df (float, optional) – Reference Df to show in plot.
measure (str) – ‘num’ (C(r), default), ‘mass’ (C_m(r)), or ‘both’. Single-realization ‘mass’ curves are noisy — see mass_pair_correlation_function.
save_path (str, optional) – Path to save the figure.
- pyFracAggregate.analysis.sandbox.number_radius_function(aggregate: Aggregate, bins: int = 15, r_min: float | None = None, r_max: float | None = None) tuple[ndarray, ndarray][source]
<N(r)>: mean number of primary centres within r of a primary.- Parameters:
- Returns:
(r_centers, N_r).
- Return type:
tuple[np.ndarray, np.ndarray]
- pyFracAggregate.analysis.sandbox.mass_radius_function(aggregate: Aggregate, bins: int = 15, r_min: float | None = None, r_max: float | None = None) tuple[ndarray, ndarray][source]
<M(r)>: mean summed primary mass within r of a primary.Weights are
r_i**3(volume); with constant material density mass- and volume-weighting differ only by a constant factor and yield identical exponents.- Parameters:
- Returns:
(r_centers, M_r).
- Return type:
tuple[np.ndarray, np.ndarray]
- pyFracAggregate.analysis.sandbox.number_sandbox_dimension(aggregate: Aggregate, bins: int = 15, r_min: float | None = None, r_max: float | None = None) tuple[float, float, dict][source]
Estimate the number-based fractal dimension Df,n from
<N(r)>.Fits
<N(r)> ~ r**Dfon a log-log grid (default window: mean primary radius to Rg); returns (Df, R_squared, fit_results) likeestimate_fractal_dimension.
- pyFracAggregate.analysis.sandbox.mass_sandbox_dimension(aggregate: Aggregate, bins: int = 15, r_min: float | None = None, r_max: float | None = None) tuple[float, float, dict][source]
Estimate the mass-based fractal dimension Df,m from
<M(r)>.Fits
<M(r)> ~ r**(Df, m); weights arer_i**3(volume ≡ mass at constant density). For monodisperse primaries the result is identical tonumber_sandbox_dimension(constant weights cancel in the slope).
- pyFracAggregate.analysis.sandbox.plot_sandbox(aggregate: Aggregate, bins: int = 15, show_fit: bool = True, reference_df: float | None = None, measure: str = 'both', save_path: str | None = None) None[source]
Plot
<N(r)>and/or<M(r)>on log-log axes with fractal fits.The default
measure="both"overlays the number and mass curves with their respective fits — the measure-comparison figure.- Parameters:
I/O
Export an Aggregate for downstream use: a YAML snapshot bundling the particle
data with generation parameters and analysis results, VTK/VTM files built with
pyvista for ParaView and other tools, and off-screen rendered PNG images or
MP4 rotation videos. The render and video exporters require a working pyvista
3D backend (see the user guide for headless-environment notes).
- pyFracAggregate.io.data.export_yaml(aggregate: Aggregate, output_path: str, *, generation_params: dict | None = None, analysis_results: dict | MorphologyReport | None = None) None[source]
Export aggregate to YAML with optional generation params and analysis results.
- Parameters:
aggregate – The fractal aggregate object to export.
output_path – Path to save the YAML file.
generation_params – Optional dict of generation parameters (method, df, kf, etc.).
analysis_results – Optional dict of analysis results, or a MorphologyReport from pfa.analyze (serialized under the v0.6 key names “Rg”/”CoM”/”N”/”estimator”/”Df_num_estimated”/ “R2_num”/”r_num”/”num_correlation”/”Df_mass_estimated”/ “R2_mass”/”r_mass”/”mass_correlation”).
- pyFracAggregate.io.visualization.save_screenshot(aggregate: Aggregate, path: str, color: str = 'lightblue', opacity: float = 0.8, color_by: str | None = None, cmap: str = 'viridis', background: str = 'white', camera_position: str | tuple = 'iso', window_size: tuple[int, int] = (1024, 768)) None[source]
Render an off-screen 3D screenshot of the aggregate and save as PNG.
- Parameters:
aggregate – The fractal aggregate to render.
path – Output file path (must end in .png).
color – Sphere color name or hex; ignored when color_by=”radius”.
opacity – Sphere opacity (0.0 to 1.0).
color_by – None (solid color) or “radius” (colormap over monomer radii).
cmap – Colormap name for color_by=”radius”.
background – Background color name or hex.
camera_position – Preset name (“iso”, “xy”, “xz”, “yz”) or a (position, focal_point, up) tuple.
window_size – (width, height) in pixels.
- Raises:
ValueError – If path does not end in .png, the aggregate is empty, or color_by is invalid.
- pyFracAggregate.io.visualization.save_rotation_video(aggregate: Aggregate, path: str, color: str = 'lightblue', opacity: float = 0.8, color_by: str | None = None, cmap: str = 'viridis', background: str = 'white', window_size: tuple[int, int] = (1024, 768), n_frames: int = 72, fps: int = 24, elevation: float = 30.0) None[source]
Generate a 360-degree rotation animation of the aggregate and save as MP4.
The camera is auto-framed from the mesh bounds (aerosol3d rule) and orbits once around the aggregate at the given elevation.
- Parameters:
aggregate – The fractal aggregate to animate.
path – Output file path (must end in .mp4).
color – Sphere color name or hex; ignored when color_by=”radius”.
opacity – Sphere opacity (0.0 to 1.0).
color_by – None (solid color) or “radius” (colormap over monomer radii).
cmap – Colormap name for color_by=”radius”.
background – Background color name or hex.
window_size – (width, height) in pixels.
n_frames – Total frames for the full 360 degree rotation.
fps – Frames per second in the output video.
elevation – Camera elevation angle in degrees.
- Raises:
ValueError – If path does not end in .mp4, the aggregate is empty, or color_by is invalid.
ImportError – If imageio is not installed.
Placement
Placement strategies decide where a new particle or cluster touches the
existing structure while respecting the overlap tolerance; every generator
selects one via placement= (name or instance). All classes implement the
same two entry points: place_particle() for particle-cluster stages and
merge_clusters() for cluster-cluster stages.
- class pyFracAggregate.generators.placement.solved.SolvedPlacement(overlap_tolerance: float = 1e-05, surface_beta: float = 0.3, rng: Generator | None = None)[source]
Emergent contact via closed-form tangency solving (Skorupski et al., 2014, FLAGE), with Monte Carlo fallback.
- class pyFracAggregate.generators.placement.sampled.SampledPlacement(overlap_tolerance: float = 1e-05, rng: Generator | None = None)[source]
Emergent contact via Monte Carlo sampling (Filippov et al., 2000).
- merge_clusters(pos1: ndarray, r1: ndarray, agg1: Aggregate, pos2_centered: ndarray, r2: ndarray, agg2: Aggregate, Gamma: float, mean_radius: float) ndarray[source]
Merge two sub-clusters (CCA stage).
- Parameters:
pos1 – Positions of cluster 1 centered at origin.
r1 – Radii of cluster 1.
agg1 – Cluster 1 aggregate.
pos2_centered – Positions of cluster 2 centered at its COM.
r2 – Radii of cluster 2.
agg2 – Cluster 2 aggregate.
Gamma – Required COM distance between clusters.
mean_radius – Mean particle radius.
- Returns:
pos2_final array (N2, 3), or None if merge failed.
- place_particle(agg: Aggregate, candidate_radius: float, candidate_mass: float, geom_center: ndarray, L: float, mean_radius: float) tuple | None[source]
Place a single particle onto the Gamma sphere (PCA stage).
- Parameters:
agg – Current aggregate with existing particles.
candidate_radius – Radius of the new particle.
candidate_mass – Mass of the new particle.
geom_center – Geometric center of existing particles.
L – Required distance from center to new particle.
mean_radius – Mean particle radius.
- Returns:
(x, y, z) position tuple, or None if placement failed.
- class pyFracAggregate.generators.placement.constructed.ConstructedPlacement(overlap_tolerance: float = 1e-05, rng: Generator | None = None)[source]
Specified contact pair + attitude construction + COM correction (Moran et al., 2019, FracVAL sub-steps b-d).
- merge_clusters(pos1: ndarray, r1: ndarray, agg1: Aggregate, pos2_centered: ndarray, r2: ndarray, agg2: Aggregate, Gamma: float, mean_radius: float) ndarray[source]
Merge two sub-clusters (CCA stage).
- Parameters:
pos1 – Positions of cluster 1 centered at origin.
r1 – Radii of cluster 1.
agg1 – Cluster 1 aggregate.
pos2_centered – Positions of cluster 2 centered at its COM.
r2 – Radii of cluster 2.
agg2 – Cluster 2 aggregate.
Gamma – Required COM distance between clusters.
mean_radius – Mean particle radius.
- Returns:
pos2_final array (N2, 3), or None if merge failed.
- place_particle(agg: Aggregate, candidate_radius: float, candidate_mass: float, geom_center: ndarray, L: float, mean_radius: float) tuple | None[source]
Place a single particle onto the Gamma sphere (PCA stage).
- Parameters:
agg – Current aggregate with existing particles.
candidate_radius – Radius of the new particle.
candidate_mass – Mass of the new particle.
geom_center – Geometric center of existing particles.
L – Required distance from center to new particle.
mean_radius – Mean particle radius.
- Returns:
(x, y, z) position tuple, or None if placement failed.