Analytic Green’s function (spectroxide.greens)#

Important

This module is the analytic three-component approximation of Chluba (2013, MNRAS 436, 2232; arXiv:1304.6120), implemented in pure Python. It is not the PDE solver — for production work prefer the PDE solver. Use this module for fast estimates, pedagogical exploration, and the spectral templates M(x), Y_SZ(x), G_bb(x) that downstream code consumes.

The Chluba ansatz decomposes the distortion into three channels — μ, y, and a temperature shift — weighted by redshift-dependent visibility / branching functions:

\[G_{th}(x, z_h) = \frac{3}{\kappa_c}\, J_\mu(z_h)\, J_{bb}^*(z_h)\, M(x) + \tfrac{1}{4} J_y(z_h)\, Y_{SZ}(x) + \tfrac{1}{4} \bigl(1 - J_{bb}^*(z_h)\bigr)\, G_{bb}(x).\]

The visibility coefficients J_μ, J_y, J_bb* are fits to PDE output. See j_mu(), j_y(), j_bb_star() for the specific functional forms and references.

Note

Accuracy vs. PDE<5% deep μ-era (z_h > 2 × 10⁵), <1% y-era (z_h < 10⁴), ~8–13% shape error in the μ↔y transition (3 × 10⁴–10⁵). For the transition region prefer the PDE-based numerical Green’s function in PDE-based numerical Green’s function (spectroxide.greens_table).

Quick example#

import numpy as np
from spectroxide.greens import greens_function, distortion_from_heating

# Distortion from a delta-function injection at z_h = 2e5
x = np.logspace(-2, 1.5, 200)
dn = greens_function(x, z_h=2e5)            # per unit Δρ/ρ

# Distortion from a heating history dQ/dz(z)
dq_dz = lambda z: 1e-9 / (1.0 + z)          # toy decaying source
dn_total = distortion_from_heating(x, dq_dz, z_min=1e3, z_max=1e7)

Green’s function for the cosmological thermalization problem.

Provides a fast, approximate method for computing spectral distortions from arbitrary energy release histories. The distortion from a delta-function energy injection at redshift z_h is decomposed into mu, y, and temperature shift components using visibility/branching functions.

Ported from src/greens.rs and src/spectrum.rs.

Conventions#

  • Frequency variable: x = h ν / (k_B T_z), dimensionless.

  • Redshift z is dimensionless; z_h denotes the injection redshift.

  • All cosmology routines accept either DEFAULT_COSMO (Chluba 2013), PLANCK2015_COSMO, or PLANCK2018_COSMO (re-exported from this module) — or any user dict with the same keys.

References

  • Chluba (2013), MNRAS 436, 2232 [arXiv:1304.6120].

  • Chluba & Jeong (2014), MNRAS 438, 2065 [arXiv:1306.5751].

  • Chluba (2015), MNRAS 454, 4182 [arXiv:1506.06582].

Constants and presets#

Module-level constants used across the Green’s-function machinery.

Z_MU

Mu-era thermalization redshift.

BETA_MU

Mu-distortion zero crossing \(\beta_\mu = 3\,\zeta(3)/\zeta(2)\).

KAPPA_C

Mu-distortion normalisation \(\kappa_c = 12/\beta_\mu - 9\,G_2/G_3\).

G3_PLANCK

Planck integral \(G_3 = \int_0^\infty x^3\, n_{pl}(x)\, dx = \pi^4/15\).

G2_PLANCK

Planck integral \(G_2 = \int_0^\infty x^2\, n_{pl}(x)\, dx = 2\,\zeta(3)\).

G1_PLANCK

Planck integral \(G_1 = \int_0^\infty x\, n_{pl}(x)\, dx = \pi^2/6\).

ALPHA_RHO

Photon-number-to-energy ratio \(\alpha_\rho = G_2/G_3 \approx 0.3702\).

X_BALANCED

Balanced injection frequency \(x_0 = 4/(3\,\alpha_\rho) \approx 3.60\).

Cosmology presets#

All routines that take a cosmo argument expect a plain dict with keys h, omega_b, omega_m, y_p, t_cmb, n_eff. Three presets are provided:

Preset

Parameters

DEFAULT_COSMO

Chluba (2013): h=0.71, Ω_b=0.044, Ω_m=0.26, Y_p=0.24, T_CMB=2.726, N_eff=3.046.

PLANCK2015_COSMO

Planck 2015 (matches CosmoTherm DI files): h=0.6727, Ω_b=0.04917, Ω_m=0.3139, Y_p=0.2467.

PLANCK2018_COSMO

Planck 2018 (Planck VI 2020, TT,TE,EE+lowE+lensing): h=0.6736, Ω_b=0.04930, Ω_m=0.3153, Y_p=0.2454.

spectroxide.greens.Z_MU = 1980000.0[source]#

Mu-era thermalization redshift.

spectroxide.greens.BETA_MU = 2.192288908204316[source]#

Mu-distortion zero crossing \(\beta_\mu = 3\,\zeta(3)/\zeta(2)\).

spectroxide.greens.KAPPA_C = 2.141851504502377[source]#

Mu-distortion normalisation \(\kappa_c = 12/\beta_\mu - 9\,G_2/G_3\).

spectroxide.greens.G3_PLANCK = 6.493939402266828[source]#

Planck integral \(G_3 = \int_0^\infty x^3\, n_{pl}(x)\, dx = \pi^4/15\).

spectroxide.greens.G2_PLANCK = 2.4041138063191885[source]#

Planck integral \(G_2 = \int_0^\infty x^2\, n_{pl}(x)\, dx = 2\,\zeta(3)\).

spectroxide.greens.G1_PLANCK = 1.6449340668482264[source]#

Planck integral \(G_1 = \int_0^\infty x\, n_{pl}(x)\, dx = \pi^2/6\).

spectroxide.greens.ALPHA_RHO = 0.3702088451087161[source]#

Photon-number-to-energy ratio \(\alpha_\rho = G_2/G_3 \approx 0.3702\).

spectroxide.greens.X_BALANCED = 3.6015707105587516[source]#

Balanced injection frequency \(x_0 = 4/(3\,\alpha_\rho) \approx 3.60\).

Photon injection at \(x = x_0\) produces zero net \(\mu\)-distortion.

Spectral shapes#

Dimensionless spectral templates M(x), Y_SZ(x), G_bb(x) that multiply the μ, y, and temperature-shift coefficients in the Green’s function decomposition.

planck

Planck (blackbody) occupation number n_pl(x) = 1 / (e^x 1).

g_bb

Blackbody derivative G_bb(x) = x e^x / (e^x 1)^2.

mu_shape

μ-distortion spectral shape M(x) = (x/β_μ 1) · G_bb(x) / x.

y_shape

y-distortion (Sunyaev–Zel'dovich) spectral shape.

temperature_shift_shape

Temperature shift spectral shape G(x) = x e^x / (e^x 1)^2.

from spectroxide.greens import mu_shape, y_shape
x = np.linspace(0.1, 10, 100)
M_x  = mu_shape(x)       # μ-distortion shape (peaks at x ~ 3.83)
Y_x  = y_shape(x)        # SZ y-distortion shape
spectroxide.greens.planck(x)[source]#

Planck (blackbody) occupation number n_pl(x) = 1 / (e^x 1).

Uses series expansions for x < 1e-6 and x > 500 to avoid catastrophic cancellation and overflow.

Parameters:

x (array_like) – Dimensionless frequency h ν / (k_B T_z).

Returns:

ndarray of float64 – Planck occupation number.

spectroxide.greens.g_bb(x)[source]#

Blackbody derivative G_bb(x) = x e^x / (e^x 1)^2.

Equal to -x · dn_pl/dx and represents the spectral response of a blackbody to a small temperature shift ΔT/T.

Parameters:

x (array_like) – Dimensionless frequency h ν / (k_B T_z).

Returns:

ndarray of float64G_bb(x) evaluated pointwise.

spectroxide.greens.mu_shape(x)[source]#

μ-distortion spectral shape M(x) = (x/β_μ 1) · G_bb(x) / x.

Crosses zero at x = β_μ 2.19 (frequency of the mu-distortion null).

Parameters:

x (array_like) – Dimensionless frequency.

Returns:

ndarray of float64M(x) evaluated pointwise.

spectroxide.greens.y_shape(x)[source]#

y-distortion (Sunyaev–Zel’dovich) spectral shape.

Y_SZ(x) = G_bb(x) · [x coth(x/2) 4].

Crosses zero at x 3.83 (the SZ null in the CMB intensity spectrum).

Parameters:

x (array_like) – Dimensionless frequency.

Returns:

ndarray of float64Y_SZ(x) evaluated pointwise.

spectroxide.greens.temperature_shift_shape(x)[source]#

Temperature shift spectral shape G(x) = x e^x / (e^x 1)^2.

Identical to g_bb(); provided as a separate name to make decomposition expressions read more clearly. Represents the response ΔI ∝ dB/dT to a small temperature perturbation.

Parameters:

x (array_like) – Dimensionless frequency.

Returns:

ndarray of float64G(x) evaluated pointwise.

Visibility functions#

Redshift-dependent branching functions that route injected energy into μ-, y-, or temperature-shift channels.

j_bb

Thermalization visibility J_bb(z) = exp(−(z/z_μ)^{5/2}).

j_bb_star

Improved thermalization visibility with the Chluba (2015) correction.

j_mu

μ-distortion branching ratio.

j_y

y-distortion branching ratio.

spectroxide.greens.j_bb(z)[source]#

Thermalization visibility J_bb(z) = exp(−(z/z_μ)^{5/2}).

Probability that injected energy at redshift z is fully thermalized into a blackbody by the present epoch.

Both z_μ and the exponent 5/2 are analytically derived: z_μ from equating the DC+BR photon production rate to the Hubble rate (Chluba & Sunyaev 2012), and 5/2 from the DC opacity scaling (Danese & de Zotti 1982; Hu & Silk 1993). These are not fit parameters.

Parameters:

z (float or array_like) – Injection redshift.

Returns:

ndarray of float64J_bb(z) ∈ [0, 1].

spectroxide.greens.j_bb_star(z)[source]#

Improved thermalization visibility with the Chluba (2015) correction.

J_bb*(z) = 0.983 · J_bb(z) · (1 0.0381 · (z/z_μ)^{2.29}).

Reference: Chluba (2015), arXiv:1506.06582, Eq. 13. Valid for 3 × 10⁵ ≲ z ≲ 6 × 10⁶ in the standard cosmology (Chluba 2014 fit, neglecting relativistic temperature corrections that become noticeable at z_i ≳ 4 × 10⁶). The prefactor 0.983 absorbs the small residual blackbody mismatch during the mu-era. The base j_bb() exponent (5/2) and z_μ are analytically derived.

The result is clamped at 0 because the empirical correction factor becomes negative for z/z_μ 3.9, outside the fit’s range of validity.

Parameters:

z (float or array_like) – Injection redshift.

Returns:

ndarray of float64J_bb*(z) ∈ [0, 1].

spectroxide.greens.j_mu(z)[source]#

μ-distortion branching ratio.

J_mu(z) = 1 exp(−((1+z)/5.8 × 10⁴)^{1.88}).

Reference: Chluba (2013), arXiv:1304.6120, Eq. 5. Approaches 0 for z ≪ 5.8 × 10⁴ (no μ) and 1 for z ≫ 5.8 × 10⁴ (pure μ). The transition scale is physically motivated by y_γ(z) ~ 1, but the precise value and exponent are fit parameters.

Parameters:

z (float or array_like) – Injection redshift.

Returns:

ndarray of float64J_μ(z) ∈ [0, 1].

spectroxide.greens.j_y(z)[source]#

y-distortion branching ratio.

J_y(z) = 1 / (1 + ((1+z)/6.0 × 10⁴)^{2.58}).

Reference: Chluba (2013), arXiv:1304.6120, Eq. 5. Least-squares fit to the PDE Green’s function in the μ–y transition era. Approaches 1 for z ≪ 6 × 10⁴ (pure y-era) and 0 for z ≫ 6 × 10⁴. The transition scale z ~ 6 × 10⁴ is physically motivated by y_γ(z) ~ 1, but the precise value and exponent are fit parameters.

Note that J_y 1 J_μ in the transition region; using the independent fit gives better spectral agreement with PDE results.

Parameters:

z (float or array_like) – Injection redshift.

Returns:

ndarray of float64J_y(z) ∈ [0, 1].

Energy injection#

Three-component Green’s function and convolutions over a heating history dQ/dz.

greens_function

Three-component Green's function G_th(x, z_h) (Chluba 2013).

distortion_from_heating

Spectral distortion from an arbitrary energy release history.

mu_from_heating

μ parameter from the Green's function approximation.

y_from_heating

Compton-y parameter from the Green's function approximation.

from spectroxide.greens import mu_from_heating, y_from_heating

# Decaying dark-matter-like heating: dQ/dz ∝ exp(-Γt(z))
import numpy as np
from spectroxide.greens import cosmic_time
dq_dz = lambda z: 1e-7 * np.exp(-1e-15 * cosmic_time(z))

mu = mu_from_heating(dq_dz, z_min=1e3, z_max=5e6)
y  = y_from_heating(dq_dz,  z_min=1e3, z_max=5e6)

The cosmo keyword (where supported) folds the post-recombination Compton visibility into the y-channel automatically (via the bundled free-electron history).

spectroxide.greens.greens_function(x, z_h)[source]#

Three-component Green’s function G_th(x, z_h) (Chluba 2013).

Spectral distortion observed at z = 0 per unit Δρ/ρ injected as a delta function at redshift z_h:

\[G_{th}(x, z_h) = \frac{3}{\kappa_c} J_\mu J_{bb}^* M(x) + \frac{1}{4} J_y \, Y_{SZ}(x) + \frac{1}{4} (1 - J_{bb}^*) G_{bb}(x),\]

where J_mu, J_y, and J_bb* are independently fitted visibility functions. The temperature-shift weight (1 J_bb*)/4 follows the Chluba (2013) convention.

Accuracy (vs. PDE)#

  • Deep μ-era (z_h > 2 × 10⁵): spectral shape accurate to <5%.

  • y-era (z_h < 10⁴): spectral shape accurate to <1%.

  • Transition era (z_h ~ 3 × 10⁴–10⁵): ~8–13% shape error.

param x:

Dimensionless frequency h ν / (k_B T_z).

type x:

float or array_like

param z_h:

Injection redshift (must be positive and finite).

type z_h:

float

returns:

ndarray of float64 – Spectral distortion Δn(x) per unit Δρ/ρ.

raises ValueError:

If z_h 0 or x contains non-positive entries.

See also

distortion_from_heating

convolution over a heating history.

References

  • Chluba (2013), MNRAS 436, 2232 [arXiv:1304.6120].

spectroxide.greens.distortion_from_heating(x_grid, dq_dz, z_min, z_max, n_z=5000)[source]#

Spectral distortion from an arbitrary energy release history.

\[\Delta n(x) = \int_{z_{min}}^{z_{max}} G_{th}(x, z') \frac{d(\Delta\rho/\rho_\gamma)}{dz'} \, dz'.\]

Integration is performed in ln(1 + z) for numerical stability, using the trapezoidal rule.

Parameters:
  • x_grid (array_like) – Frequency grid (must be positive and finite).

  • dq_dz (callable) – Heating rate d(Δρ/ρ_γ)/dz as a function of redshift. Sign convention: positive for heating. Should accept either a scalar or an array; vectorized calls are attempted first and fall back to scalar evaluation on broadcasting failure.

  • z_min (float) – Minimum integration redshift (must satisfy 0 z_min < z_max).

  • z_max (float) – Maximum integration redshift.

  • n_z (int, optional) – Number of redshift integration points. Default 5000; recommended ≥ 2000 per log10(1+z) decade for broad ranges.

Returns:

ndarray of float64 – Distortion Δn(x) evaluated on x_grid.

Raises:

ValueError – If x_grid contains non-positive entries or the redshift range is invalid.

spectroxide.greens.mu_from_heating(dq_dz, z_min, z_max, n_z=5000)[source]#

μ parameter from the Green’s function approximation.

\[\mu = \frac{3}{\kappa_c} \int_{z_{min}}^{z_{max}} J_{bb}^*(z) \, J_\mu(z) \frac{d(\Delta\rho/\rho)}{dz} \, dz.\]
Parameters:
  • dq_dz (callable) – Heating rate d(Δρ/ρ_γ)/dz (positive for heating).

  • z_min (float) – Minimum integration redshift.

  • z_max (float) – Maximum integration redshift.

  • n_z (int, optional) – Number of redshift integration points (default 5000).

Returns:

float – Chemical-potential parameter μ (dimensionless).

spectroxide.greens.y_from_heating(dq_dz, z_min, z_max, n_z=5000)[source]#

Compton-y parameter from the Green’s function approximation.

\[y = \frac{1}{4} \int_{z_{min}}^{z_{max}} J_y(z) \frac{d(\Delta\rho/\rho)}{dz} \, dz.\]

Uses the independently fitted J_y (see j_y()), which gives better agreement with PDE results than (1 J_μ).

Parameters:
  • dq_dz (callable) – Heating rate d(Δρ/ρ_γ)/dz (positive for heating).

  • z_min (float) – Minimum integration redshift.

  • z_max (float) – Maximum integration redshift.

  • n_z (int, optional) – Number of redshift integration points (default 5000).

Returns:

float – Compton y-parameter (dimensionless).

Photon injection#

Monochromatic photon injection at frequency x_inj and redshift z_h (Chluba 2015). Includes critical frequencies for DC/BR absorption and the photon survival probability P_s.

x_c_dc

Critical frequency for double-Compton absorption.

x_c_br

Critical frequency for bremsstrahlung absorption.

x_c

Combined critical frequency for photon absorption.

photon_survival_probability

Analytic photon survival probability P_s(x, z) = exp(−x_c(z)/x).

greens_function_photon

Green's function for monochromatic photon injection.

mu_from_photon_injection

μ from monochromatic photon injection.

distortion_from_photon_injection

Spectral distortion from a photon injection history.

from spectroxide.greens import greens_function_photon, mu_from_photon_injection

# Δn(x_obs) for ΔN/N injected at x_inj = 0.5, z_h = 5e5
x_obs = np.logspace(-2, 1.5, 200)
dn = greens_function_photon(x_obs, x_inj=0.5, z_h=5e5)

# Total μ from a fractional photon-number injection of 1e-6
mu = mu_from_photon_injection(x_inj=0.5, z_h=5e5, delta_n_over_n=1e-6)
spectroxide.greens.x_c_dc(z)[source]#

Critical frequency for double-Compton absorption.

x_c^{DC}(z) = 8.60 × 10⁻³ · ((1+z)/2 × 10⁶)^{1/2}.

Reference: Chluba (2015), arXiv:1506.06582, Eq. 25a.

Parameters:

z (float or array_like) – Redshift.

Returns:

ndarray of float64 – Dimensionless critical frequency.

spectroxide.greens.x_c_br(z)[source]#

Critical frequency for bremsstrahlung absorption.

x_c^{BR}(z) = 1.23 × 10⁻³ · ((1+z)/2 × 10⁶)^{−0.672}.

Reference: Chluba (2015), arXiv:1506.06582, Eq. 25b.

Parameters:

z (float or array_like) – Redshift.

Returns:

ndarray of float64 – Dimensionless critical frequency.

spectroxide.greens.x_c(z)[source]#

Combined critical frequency for photon absorption.

x_c² = x_c^{DC}² + x_c^{BR}² (quadrature addition).

Photons with x x_c are absorbed by DC/BR; photons with x x_c survive.

Parameters:

z (float or array_like) – Redshift.

Returns:

ndarray of float64 – Dimensionless critical frequency.

spectroxide.greens.photon_survival_probability(x, z)[source]#

Analytic photon survival probability P_s(x, z) = exp(−x_c(z)/x).

Probability that an injected photon at frequency x survives absorption by DC/BR processes.

Reference: Chluba (2015), arXiv:1506.06582, Eq. 24.

Parameters:
  • x (float or array_like) – Dimensionless frequency.

  • z (float) – Redshift.

Returns:

ndarray of float64 – Survival probability P_s [0, 1]; zero for non-positive x.

spectroxide.greens.greens_function_photon(x_obs, x_inj, z_h, sigma_x=0.0, number_conserving=False, cosmo=None)[source]#

Green’s function for monochromatic photon injection.

Returns Δn(x_obs) per unit ΔN/N injected at frequency x_inj and redshift z_h. Uses the universal J_μ(z) visibility (same as heat injection) to blend between pure-μ-era and pure-y-era contributions:

G_ph = J_μ G_μ + (1 J_μ) G_y.

The surviving photon δ-function is represented as a Gaussian of width sigma_x (set 0 to omit it, e.g. for P_s 0 tests).

When P_s = 0, reduces to α_ρ x_inj · greens_function(x_obs, z_h).

Reference: Chluba (2015), arXiv:1506.06582.

Parameters:
  • x_obs (float or array_like) – Observation frequency.

  • x_inj (float) – Injection frequency (must be positive and finite).

  • z_h (float) – Injection redshift. Must lie outside the μ–y transition band (5e4, 2e5); otherwise a ValueError is raised.

  • sigma_x (float, optional) – Gaussian width for the surviving photon δ-function (default 0).

  • number_conserving (bool, optional) – If True, drop the temperature-shift component so the result satisfies G dx 0 (CosmoTherm convention for stored Green’s function entries). Default False.

  • cosmo (Mapping, optional) – Cosmological parameters for Compton y-parameter broadening. Defaults to DEFAULT_COSMO.

Returns:

ndarray of float64 – Spectral distortion Δn(x_obs) per unit ΔN/N.

Raises:

ValueError – If x_obs, x_inj, or z_h are out of range, or if z_h falls inside the μ–y transition.

spectroxide.greens.mu_from_photon_injection(x_inj, z_h, delta_n_over_n)[source]#

μ from monochromatic photon injection.

\[\mu = \alpha_\rho \, x_{inj} \, \frac{3}{\kappa_c} J_{bb}^*(z_h) J_\mu(z_h) \left(1 - P_s \frac{x_0}{x_{inj}}\right) \frac{\Delta N}{N}.\]

Uses the universal J_μ(z) visibility function (same as heat injection).

Sign behaviour#

  • x_inj > x₀ and P_s 1: μ > 0 (energy-dominated).

  • x_inj < x₀ and P_s 1: μ < 0 (number-dominated).

  • P_s 0 (soft photons absorbed): μ > 0 always (pure energy injection).

Reference: Chluba (2015), arXiv:1506.06582.

param x_inj:

Injection frequency (positive, finite).

type x_inj:

float

param z_h:

Injection redshift (must lie outside the μ–y transition band).

type z_h:

float

param delta_n_over_n:

Fractional photon-number perturbation ΔN/N.

type delta_n_over_n:

float

returns:

float – Dimensionless μ-parameter.

spectroxide.greens.distortion_from_photon_injection(x_grid, x_inj, dn_dz, z_min, z_max, n_z=5000, sigma_x=0.0, cosmo=None)[source]#

Spectral distortion from a photon injection history.

\[\Delta n(x) = \int_{z_{min}}^{z_{max}} G_{ph}(x, x_{inj}, z') \, \frac{d(\Delta N / N)}{dz'} \, dz'.\]

Active redshifts must avoid the μ–y transition band (5e4, 2e5); if the integration range overlaps it, points landing in the band raise ValueError (preceded by a warning).

Parameters:
  • x_grid (array_like) – Observation frequency grid.

  • x_inj (float) – Injection frequency (positive, finite).

  • dn_dz (callable) – Source rate d(ΔN/N)/dz (positive for injection).

  • z_min (float) – Minimum integration redshift.

  • z_max (float) – Maximum integration redshift.

  • n_z (int, optional) – Number of redshift integration points (default 5000).

  • sigma_x (float, optional) – Gaussian width for the surviving photon δ-function (default 0).

  • cosmo (Mapping, optional) – Cosmological parameters for Compton y-parameter broadening. Defaults to DEFAULT_COSMO.

Returns:

ndarray of float64 – Distortion Δn(x) evaluated on x_grid.

Raises:

ValueError – If any active source redshift falls in the μ–y transition band.

For the flat ΛCDM background quantities (Hubble rate, densities, recombination history) and cosmology presets, see Cosmology (spectroxide.cosmology).

Decomposition utilities#

Decompose an arbitrary Δn(x) into (μ, y, ΔT/T) components and convert to intensity units (MJy/sr).

decompose_distortion

Decompose Δn(x) into (μ, y, ΔT/T) components.

delta_n_to_delta_I

Convert Δn(x) to [GHz], ΔI [Jy/sr]).

from spectroxide.greens import decompose_distortion, delta_n_to_delta_I

mu, y, dT_T = decompose_distortion(x, dn)
dI = delta_n_to_delta_I(x, dn)            # intensity in MJy/sr

decompose_distortion() is the entry point — it dispatches via a method= keyword to the non-linear blackbody-temperature solve ("be", default) or the linear Gram-Schmidt fit ("gs"). Both underlying routines are private (_decompose_nonlinear_be / _decompose_gram_schmidt); reach them through decompose_distortion.

spectroxide.greens.decompose_distortion(x_grid, delta_n, z_h=None, method='bf')[source]#

Decompose Δn(x) into (μ, y, ΔT/T) components.

Default method: Bianchini & Fabbian (2022) nonlinear Bose–Einstein fit (method="bf"), matching the Rust spectroxide::distortion::decompose_distortion.

``method=”bf”`` (default): Nonlinear least-squares fit of Δn(x) = [n_pl(x/(1+δ)) − n_pl(x)] + [n_BE(x+μ) − n_pl(x)] + y·Y_SZ(x) on x ∈ [0.5, 18], bootstrapped from a linear Gram-Schmidt initial guess and refined by Levenberg-Marquardt. See _decompose_nonlinear_be().

``method=”gs”``: Linear Gram-Schmidt orthogonalisation of (Y_SZ, M, G) over the same band (Chluba & Jeong 2014, Appendix A). Agrees with bf on μ and y to numerical precision at realistic injection amplitudes; see _decompose_gram_schmidt().

``method=”gf_fit”`` (requires z_h): Three-component Green’s-function spectral fit for visibility-function calibration against PDE spectra. NC-strips the spectrum, fixes J_y from Chluba (2013) Eq. 5, then fits J_μ and J_bb* by minimising the x³-weighted residual. Use this for visibility calibration, NOT for production μ/y extraction.

Parameters:
  • x_grid (array_like) – Dimensionless frequency grid x = h ν / (k_B T_z).

  • delta_n (array_like) – Spectral distortion Δn(x) (same length as x_grid).

  • z_h (float, optional) – Injection redshift. Required when method="gf_fit"; ignored (with a warning) for the other methods.

  • method ({"bf", "gs", "gf_fit"}, optional) – Decomposition method (default "bf").

Returns:

dict – Keys mu (float), y (float), dT (float, ΔT/T), drho (float, Δρ/ρ), dn_over_n (float, ΔN/N), and residual (ndarray, Δn model on x_grid). When gf_fit is used, also includes j_mu_fit, j_bb_star_fit, j_y, fit_success, fit_residual.

Raises:
  • ValueError – If method is unknown, or if method="gf_fit" is selected without supplying z_h.

  • RuntimeError – If the gf_fit L-BFGS-B optimisation fails to converge.

spectroxide.greens.delta_n_to_delta_I(x, dn, t_cmb=2.726)[source]#

Convert Δn(x) to [GHz], ΔI [Jy/sr]).

Uses ΔI = (2 h ν³ / c²) Δn with ν = x k_B T₀ / h.

Parameters:
  • x (array_like) – Dimensionless frequency x = h ν / (k_B T_z).

  • dn (array_like) – Spectral distortion Δn(x).

  • t_cmb (float, optional) – CMB temperature today, in K. Default 2.726.

Returns:

  • nu_ghz (ndarray of float64) – Frequency in GHz.

  • di_jy (ndarray of float64) – Intensity distortion in Jy/sr (= 10⁻²⁶ W m⁻² Hz⁻¹ sr⁻¹).

Number-conservation stripping#

FIRAS measures the CMB spectrum with the absolute temperature as a free parameter, so a uniform shift \(\Delta T/T\) is unobservable. CosmoTherm therefore defines the distortion as the number-conserving part of \(\Delta n\) (the part satisfying \(\int x^2 \Delta n\,dx = 0\)); any nonzero photon-number perturbation is absorbed into \(\alpha \cdot G_{bb}(x)\). strip_gbb performs this projection in occupation-number space.

spectroxide.cosmotherm.strip_gbb

Remove the unobservable temperature-shift component of a spectrum.

spectroxide.cosmotherm.strip_gbb(x, delta_n)[source]#

Remove the unobservable temperature-shift component of a spectrum.

FIRAS measures the CMB spectrum with the absolute temperature as a free parameter, so a uniform shift ΔT/T is unobservable. CosmoTherm therefore defines the distortion as the number-conserving part of Δn (Chluba & Sunyaev 2012, arXiv:1109.6552): the part satisfying Δn dx = 0. Any nonzero photon-number perturbation is absorbed into α · G_bb(x).

This projection is orthogonal to μ and y because both M(x) and Y_SZ(x) conserve photon number ( M dx 0, Y dx 0), so there is no cross-talk.

Parameters:
  • x (array_like) – Dimensionless frequency grid.

  • delta_n (array_like) – Spectral distortion in occupation-number space.

Returns:

  • delta_n_stripped (ndarray of float64) – Number-conserving distortion ( Δn_stripped dx 0).

  • alpha (float) – Temperature-shift coefficient ΔT/T.

Convenience wrapper#

spectroxide.solver.run_single() is a thin wrapper around the analytic Green’s function that bundles single-burst and custom-heating calculations into a single dict-returning call. It is documented on the PDE-solver page for proximity with the other solver entry points; despite living there, it does not invoke the Rust PDE.