morphology — Minkowski functionals and tensors¶
- foregrounds_diffusion.morphology.compute_mfs(maps_nhw, norm_fn, thresholds, n_jobs=1)[source]¶
Compute Minkowski functionals M0, M1, M2 across a stack of maps.
Requires the
quantimpypackage (Boelens & Tchelepi 2021).- Parameters:
maps_nhw (ndarray, shape (N, H, W))
norm_fn (callable) – Normalisation function mapping a 2D array to [0, 1] (e.g.
apply_maxmin_normalization()).thresholds (array_like) – Intensity thresholds ν.
n_jobs (int) – Number of parallel workers (joblib). 1 = serial (default). -1 = all cores.
- Returns:
M0, M1, M2 (ndarray, each shape (N, len(thresholds))) – M0 = area fraction, M1 = perimeter, M2 = Euler characteristic.
- foregrounds_diffusion.morphology.compute_minkowski_tensors(maps_nhw, norm_fn, thresholds, tensor_types=('W012',), centred=True, n_jobs=1)[source]¶
Compute Minkowski tensor anisotropy indices across intensity thresholds.
For each map and threshold ν, the map is binarised to the excursion set K = {x : T(x) > ν}. The requested rank-2 Minkowski tensor(s) are computed from K, then eigendecomposed to give the anisotropy index β = λ_min/λ_max and the major-axis orientation θ.
- Parameters:
maps_nhw (ndarray, shape (N, H, W)) – Stack of flat-sky patches.
norm_fn (callable) – Normalisation function applied to each 2D patch before thresholding (e.g.
apply_maxmin_normalization). Passlambda x: xto use raw pixel values.thresholds (array_like) – Intensity thresholds ν in the normalised range.
tensor_types (tuple of str) – Which tensor(s) to compute. Any subset of:
'W012'W^{0,2}_1 — interface normal tensor (default). Boundary normals n⊗n via Sobel gradients. Most sensitive to boundary shape.
'W200'W^{2,0}_0 — area inertia tensor. Interior pixel positions r⊗r. Measures elongation of filled regions.
'W201'W^{2,0}_1 — boundary position tensor. Boundary pixel positions r⊗r. Hybrid between W012 and W200.
centred (bool) – If True (default), subtract the excursion-set centroid from position vectors before forming the tensor. Affects W200 and W201 only.
n_jobs (int) – Number of parallel workers (joblib). 1 = serial (default). −1 = use all cores.
- Returns:
results (dict) – Keyed by tensor type string. Each value is a dict:
'beta'ndarray, shape (N, len(thresholds))Anisotropy index β = λ_min/λ_max ∈ [0, 1]. 1 = isotropic.
'theta'ndarray, shape (N, len(thresholds))Major-axis orientation in radians ∈ (-π/2, π/2].
Notes
β = 1 and θ = 0 are returned for empty or full excursion sets (fewer than 2 interior pixels or fewer than 2 exterior pixels). As a sanity check, a Gaussian random field should give β ≈ 1 at all thresholds.
Examples
>>> thresholds = np.linspace(0.05, 0.95, 50) >>> results = compute_minkowski_tensors( ... maps, apply_maxmin_normalization, thresholds, ... tensor_types=('W012', 'W200')) >>> beta_W012 = results['W012']['beta'] # shape (N, 50) >>> theta_W012 = results['W012']['theta'] # shape (N, 50)