progenax.diagnostics¶
Auto-generated by scripts/build_api_reference.py from progenax source. Re-run after public-API changes; the script is idempotent.
Module path: progenax/diagnostics/
Public symbols: 13
Contents¶
diagnostics.compute_lambda_msr¶
function
compute_lambda_msr(positions: 'np.ndarray', masses: 'np.ndarray', N_massive: 'int' = 10, N_random_samples: 'int' = 50, seed: 'int' = 42) -> 'Tuple[float, float]'Compute Λ_MSR mass segregation ratio (Allison et al. 2009).
Uses Minimum Spanning Tree lengths to compare the spatial distribution of massive stars vs. random subsets:
Λ_MSR = <L_random> / L_massive ± σ_random / L_massiveInterpretation: - Λ_MSR ≈ 1: No mass segregation - Λ_MSR > 1: Massive stars more concentrated (segregated) - Λ_MSR >> 1 (e.g., 3-5): Strong segregation - Λ_MSR < 1: Inverse segregation (rare)
Args
| Parameter | Description |
|---|---|
positions | Stellar positions (N, 3) as NumPy array |
masses | Stellar masses (N,) as NumPy array |
N_massive | Number of most massive stars to use for comparison. Typical values: 10-20 for clusters with N~1000. |
N_random_samples | Number of random subsets for comparison. Default 50 is for quick validation; use >= 200 for science-quality results. |
seed | Random seed for reproducibility |
Returns: lambda_msr: Mass segregation ratio error: Standard error estimate (σ_random / L_massive)
Raises: ValueError: If N_massive < 2 or N_massive >= N
Example. >>> import numpy as np
positions = np.random.randn(1000, 3) masses = np.random.power(2.3, 1000) lam, err = compute_lambda_msr(positions, masses, N_massive=10) print(f"Λ_MSR = {lam:.2f} ± {err:.2f}")
Notes. Uses scipy.sparse.csgraph.minimum_spanning_tree for MST computation. Not differentiable; for validation/calibration only.
Caution: Strongly affected by binaries (massive binaries have very short MST edges). For systems with binaries, consider using only binary center-of-mass positions.
References. Allison et al. (2009), MNRAS 395, 1449 — formal Λ_MSR definition. Allison et al. (2009), ApJ 700, L99 — application (note: L99 Eq. 1 is the Spitzer t_seg relation, NOT Λ_MSR; verified against the held PDF 2026-06-08).
Source: src/progenax/diagnostics/mass_segregation.py#L43
diagnostics.compute_q_parameter¶
function
compute_q_parameter(positions: 'np.ndarray') -> 'float'Compute Cartwright & Whitworth Q parameter for spatial substructure.
Implements the exact CW04 definition: Q = m̄ / s̄
Where: - s̄ = (mean pairwise separation) / R_cluster - m̄ = L_MST / sqrt(N × A) - R_cluster = max distance from cluster center - A = π R_cluster² (CW04 convention, NOT convex-hull area)
This is the substructure metric, NOT the virial ratio Q_vir.
Args
| Parameter | Description |
|---|---|
positions | Stellar positions (N, 2) or (N, 3) as NumPy array. If 3D, positions are projected to x-y plane (CW04 methodology). |
Returns: Q: Cartwright-Whitworth Q parameter CW04 Table 1 — published Q = m̄/s̄ (artificial clusters, N≈100-300, 3D→2D projected): - Uniform sphere (3D0): s̄=0.80, m̄=0.63, Q=0.79 ± 0.02 - r^-1 radial (3D1): Q = 0.84 ± 0.02 - r^-2 radial (3D2): Q = 0.93 ± 0.03 - Fractal D=2.5 (F2.5): Q = 0.73 ± 0.06 - Fractal D=2.0 (F2.0): Q = 0.61 ± 0.08 - Fractal D=1.5 (F1.5): Q = 0.45 ± 0.09 This estimator (area A=πR²) reproduces the RADIAL Q to <0.01. For the FRACTAL clusters it returns Q ≈ 0.47/0.58/0.70 at D=1.5/2.0/2.5 — consistent within CW04’s ±0.06-0.09 but offset ~0.02-0.03 from the published values, most likely because CW04 normalize by a different cluster-footprint area (a clumpy fractal deviates most from πR²). Only the radial anchors trace verbatim to CW04 Table 1. Interpretation: - Q < 0.80: Substructured (fractal, clumpy) - Q ≈ 0.80: Homogeneous sphere - Q > 0.80: Centrally concentrated (radial profile dominates)
Example. >>> import numpy as np
Random uniform sphere¶
rng = np.random.default_rng(42) u = rng.uniform(0, 1, 300) r = u**(1/3) theta = np.arccos(2rng.uniform(0, 1, 300) - 1) phi = rng.uniform(0, 2np.pi, 300) positions = np.column_stack([ ... r * np.sin(theta) * np.cos(phi), ... r * np.sin(theta) * np.sin(phi), ... r * np.cos(theta), ... ]) Q = compute_q_parameter(positions) print(f"Q = {Q:.2f}") # Should be ~0.79 for uniform sphere
Notes. O(N²) complexity due to pairwise distance computation. For large N (> 5000), consider using a random subsample.
Not differentiable; for validation/calibration only.
References. Cartwright & Whitworth (2004), MNRAS 348, 589
Source: src/progenax/diagnostics/substructure.py#L48
diagnostics.compute_azimuthal_variation¶
function
compute_azimuthal_variation(positions: 'np.ndarray', n_bins: 'int' = 12) -> 'float'Compute azimuthal density variation σ_Σ / <Σ>.
Divides the projected cluster into azimuthal bins and computes the relative standard deviation of star counts. This metric correlates linearly with fractal dimension:
σ_Σ/<Σ> ≈ -0.46 * D + 1.45Where D is the fractal dimension (1.5-3.0).
Args
| Parameter | Description |
|---|---|
positions | Stellar positions (N, 3) as NumPy array |
n_bins | Number of azimuthal bins (default 12, i.e., 30° sectors) |
Returns: sigma_over_mean: Relative variation σ_Σ / <Σ>
Example. >>> import numpy as np
positions = np.random.randn(1000, 3) # Gaussian cluster var = compute_azimuthal_variation(positions) print(f"σ_Σ/<Σ> = {var:.3f}")
Notes. Practical alternative to Q parameter for large clusters.
The linear relation to D allows estimation of fractal dimension: D ≈ (1.45 - σ_Σ/<Σ>) / 0.46
References. Küpper et al. (2011), MNRAS 417, 2300
Source: src/progenax/diagnostics/substructure.py#L167
diagnostics.q_approx¶
function
📇 model card · ∇ gradient-verified — 1 audit case
q_approx(positions: "Float[Array, 'N 3']", project_to_2d: 'bool' = True, method: "Literal['auto', 'naive', 'fast']" = 'auto', calibration: 'float' = 1.287344, **kwargs) -> "Float[Array, '']"Compute approximate Q parameter with automatic method selection.
Args
| Parameter | Description |
|---|---|
positions | Particle positions [N, 3] or [N, 2] |
project_to_2d | Project to xy plane (CW04 methodology) |
method | “auto” (default), “naive”, or “fast” |
calibration | Multiplicative calibration factor |
**kwargs | Passed to underlying implementation |
Returns: Q_approx: Approximate Q parameter (scalar)
Source: src/progenax/diagnostics/q_approx.py#L255
diagnostics.q_approx_naive¶
function
q_approx_naive(positions: "Float[Array, 'N 3']", project_to_2d: 'bool' = True, calibration: 'float' = 1.287344) -> "Float[Array, '']"Compute approximate Q parameter using O(N^2) brute-force kNN.
Suitable for N < 2000 where O(N^2) is acceptable.
Args
| Parameter | Description |
|---|---|
positions | Particle positions [N, 3] or [N, 2] |
project_to_2d | Project to xy plane (CW04 methodology) |
calibration | Multiplicative calibration factor |
Returns: Q_approx: Approximate Q parameter (scalar)
Source: src/progenax/diagnostics/q_approx.py#L45
diagnostics.q_approx_fast¶
function
q_approx_fast(positions: "Float[Array, 'N 3']", project_to_2d: 'bool' = True, nbins_per_dim: 'int' = 16, calibration: 'float' = 1.287344) -> "Float[Array, '']"Compute approximate Q parameter using O(N log N) spatial indexing.
Uses Morton-based spatial binning from jaxstro.spatial for efficient k-nearest neighbor computation.
Args
| Parameter | Description |
|---|---|
positions | Particle positions [N, 3] or [N, 2] |
project_to_2d | Project to xy plane (CW04 methodology) |
nbins_per_dim | Spatial bins per dimension (16-32 recommended) |
calibration | Multiplicative calibration factor |
Returns: Q_approx: Approximate Q parameter (scalar)
Source: src/progenax/diagnostics/q_approx.py#L113
diagnostics.calibrate_q_approx¶
function
calibrate_q_approx(n_samples: 'int' = 100, N_stars: 'int' = 500, seed: 'int' = 42) -> 'dict[str, float]'Determine calibration factor by comparing to exact scipy Q.
Args
| Parameter | Description |
|---|---|
n_samples | Number of random samples |
N_stars | Particles per sample |
seed | Random seed |
Returns: Dictionary with calibration factors and statistics
Source: src/progenax/diagnostics/q_approx.py#L296
diagnostics.DEFAULT_CALIBRATION¶
value
Convert a string or number to a floating-point number, if possible.
diagnostics.soft_mass_weights¶
function
soft_mass_weights(masses: Float[Array, 'N'], m_cut: ArrayLike, tau: ArrayLike) -> Float[Array, 'N']Smooth soft mass-cut weights w_i = sigmoid((m_i - m_cut) / tau).
The shared weighting kernel for every differentiable segregation observable. As
tau -> 0 the weights approach the hard indicator 1[m_i > m_cut].
Args
| Parameter | Description |
|---|---|
masses | Stellar masses (N,). |
m_cut | Mass cut defining the “massive” population (same units as masses). |
tau | Softness scale; smaller is sharper. Must be > 0. |
Returns: Weights (N,) in the open interval (0, 1).
Source: src/progenax/diagnostics/segregation_approx.py#L52
diagnostics.radial_concentration_approx¶
function
radial_concentration_approx(positions: Float[Array, 'N D'], masses: Float[Array, 'N'], *, m_cut: ArrayLike, tau: ArrayLike, project_to_2d: bool = True, calibration: float = 1.0) -> Float[Array, '']Mass-weighted radial-concentration segregation observable.
Compares the (soft-mass-weighted) mean cluster-centric radius of the massive population to the unweighted mean radius of all stars::
C = [ sum_i w_i r_i / sum_i w_i ] / [ mean_i r_i ]where r_i = |x_i - xbar_w| and xbar_w is the mass-weighted centroid.
Interpretation:
- C < 1: massive stars more centrally concentrated (segregated).
- C ~ 1: no segregation.
- C > 1: inverse segregation.
Smooth in positions and m_cut; no graph, no ranking -- the cleanest-gradient
member of the family. As tau -> 0 it reduces to the exact mass-cut radial
ratio.
Args
| Parameter | Description |
|---|---|
positions | Positions (N, 3) or (N, 2). |
masses | Stellar masses (N,). |
m_cut | Mass cut for the massive population. |
tau | Soft mass-cut softness (> 0). |
project_to_2d | Use projected (x, y) positions (observer-faithful) if True. |
calibration | Multiplicative calibration factor (fit vs the exact oracle). |
Returns: Scalar concentration C.
Source: src/progenax/diagnostics/segregation_approx.py#L73
diagnostics.lambda_msr_approx¶
function
📇 model card · ∇ gradient-verified — 1 audit case
lambda_msr_approx(positions: Float[Array, 'N D'], masses: Float[Array, 'N'], *, m_cut: ArrayLike, tau: ArrayLike, beta: ArrayLike = 0.1, project_to_2d: bool = True, calibration: float = 1.0) -> Float[Array, '']Soft Lambda_MSR segregation observable (MST-ratio surrogate).
Differentiable analogue of the Allison et al. (2009) mass-segregation ratio
Lambda_MSR = <L_random> / L_massive (cf. :func:compute_lambda_msr), softening
both discrete operations:
The combinatorial MST length is replaced by a per-star softmin nearest-neighbour distance (the
q_approxL_MST ~ (N-1) <d_1NN>estimator, with a smoothmin).The Monte-Carlo “random subset” baseline is replaced by its closed-form expectation: the unweighted mean NN-length over all stars. No sampling::
Lambda_soft = mean_i d_i / ( sum_i w_i d_i / sum_i w_i )where
d_iis the softmin 1-NN distance andw_ithe soft mass-cut weight.
Interpretation:
- Lambda > 1: massive stars more clustered (segregated).
- Lambda ~ 1: no segregation.
- Lambda < 1: inverse segregation.
As tau, beta -> 0 this reduces (up to the multiplicative calibration) to the
exact Lambda_MSR -- the central validation route (Oracle 1).
Args
| Parameter | Description |
|---|---|
positions | Positions (N, 3) or (N, 2). |
masses | Stellar masses (N,). |
m_cut | Mass cut for the massive population. |
tau | Soft mass-cut softness (> 0). |
beta | Softmin temperature for the nearest-neighbour distance (> 0). |
project_to_2d | Use projected (x, y) positions if True (observer-faithful). |
calibration | Multiplicative calibration vs the exact Lambda_MSR oracle. |
Returns: Scalar Lambda_soft.
Source: src/progenax/diagnostics/segregation_approx.py#L152
diagnostics.sigma_m_approx¶
function
sigma_m_approx(positions: Float[Array, 'N D'], masses: Float[Array, 'N'], *, m_cut: ArrayLike, tau: ArrayLike, k: int = 6, project_to_2d: bool = True, calibration: float = 1.0) -> Float[Array, '']Soft Sigma--m segregation observable (Maschberger & Clarke 2011).
Measures whether massive stars sit in locally denser regions, via the correlation between the soft mass-cut weight and the local surface density::
S = corr_i( w_i , log Sigma_i ), Sigma_i = (k - 1) / (pi r_ik^2)where r_ik is the distance to the k-th nearest neighbour. The local
surface-density estimator Sigma = (k-1)/(pi r_k^2) and the k = 6 choice
follow von Hoerner (1963) / Casertano & Hut (1985), as adopted by Maschberger &
Clarke (2011, Eq. 4). The k-NN radius is computed with
jnp.sort -- the exact k-th order statistic, which (unlike argsort) has a
well-defined JVP, so the observable is differentiable in positions without any
softening of the radius.
Interpretation:
- S > 0: massive stars in denser regions (segregated).
- S ~ 0: no mass--density correlation.
- S < 0: massive stars in sparser regions (inverse).
Args
| Parameter | Description |
|---|---|
positions | Positions (N, 3) or (N, 2). |
masses | Stellar masses (N,). |
m_cut | Mass cut for the massive population. |
tau | Soft mass-cut softness (> 0). |
k | Nearest-neighbour rank for the local-density estimator (k = 6; Casertano & Hut 1985, via Maschberger & Clarke 2011). Must satisfy 2 <= k < N. |
project_to_2d | Use projected (x, y) positions if True (observer-faithful; surface density is intrinsically a projected quantity). |
calibration | Multiplicative calibration vs the exact Sigma--m oracle. |
Returns: Scalar correlation S.
Source: src/progenax/diagnostics/segregation_approx.py#L216
diagnostics.calibrate_segregation_approx¶
function
calibrate_segregation_approx(n_samples: int = 100, N_stars: int = 300, n_massive: int = 20, m_cut: float = 2.0, tau: float = 0.5, beta: float = 0.1, k: int = 6, seed: int = 42) -> dictCalibrate the soft observables against their exact non-differentiable oracles.
Mirrors :func:calibrate_q_approx. Generates clusters spanning a range of
segregation strengths (massive-star core scale swept from tight to diffuse) and,
for each soft observable, reports mean(exact) / mean(soft) (the multiplicative
calibration) and the Pearson correlation between soft and exact across the sample.
Exact oracles: :func:compute_lambda_msr (SciPy MST), a hard-cut radial
concentration, and a SciPy cKDTree k-NN Sigma--m correlation.
Args
| Parameter | Description |
|---|---|
n_samples | Number of random clusters. |
N_stars | Stars per cluster. |
n_massive | Number of massive stars (placed in a core of varying tightness). m_cut, tau, beta, k: Observable hyperparameters. |
seed | Base PRNG seed. |
Returns: Dict of calibration factors, correlations, and n_samples.