jwspecabund — chemical abundances

jwspecabund turns a FitResult (from jwspecfit) or an MCMCResult (from jwspecmcmc) into element abundances: 12 + log(O/H), log(N/O), log(C/O), log(S/O), log(Ne/O), log(Ar/O), with electron temperatures, densities, and dust attenuation.

Basic usage

import jwspecabund

abund = jwspecabund.compute_abundances(result, z=6.0)
print(abund.summary())

Pipeline

compute_abundances runs five stages in order:

1 — Dust correction

A_V is derived from the multi-Balmer decrement. By default the anchor is Hβ (using Hγ/Hβ, Hδ/Hβ, H9/Hβ, H10/Hβ), but you can anchor on Hα — useful at moderate redshift where Hα is the highest-SNR Balmer line:

abund = jwspecabund.compute_abundances(
    result, z=2.5,
    balmer_anchor="Ha",    # or "HBETA" (default)
    dust_law="salim",       # or "cardelli"
)

A per-line A_V is computed against the anchor, then an inverse-variance weighted mean is returned. You can also supply Av= directly to skip the derivation entirely, or dust_correct=False to turn dust off.

All line fluxes are then corrected at each line’s own rest wavelength — the correction is fully wavelength-dependent.

Note

A_V is held constant across MCMC draws by default. When the input is an MCMCResult, the single A_V derived above is applied once to every posterior draw (the Balmer-propagated A_V error is reported on the result but not marginalised into the abundance posteriors). To marginalise over A_V instead — each draw dust-corrected with its own A_V sample — opt in by passing Av_err=<value> explicitly (and optionally Av_prior="gaussian" or "uniform").

2 — Electron density

Three-zone density from whatever ratios are available:

Zone

Diagnostic

Fallback

Low-ionisation

[S II] 6718/6732

[O II] 3726/3729, else 300 cm⁻³

Mid-ionisation

C III] 1907/1909

High-ionisation

N IV] 1483/1486

mid-zone, else low-zone

Each zone can be forced manually:

abund = jwspecabund.compute_abundances(
    result, z=6.0,
    ne_low_override=500.0,
    ne_mid_override=2.0e4,
    ne_high_override=1.0e5,
)

3 — Method selection

Method

Triggered when

What it does

"direct"

[O III] 4363 detected (SNR ≥ snr_auroral)

T_e from [O III] 4363 / (5007 + 4959); ionic abundances via PyNEB

"direct" (UV)

4363 absent, O III] 1666 detected

T_e from 1666 / (5007 + 4959); larger 7.5 eV gap → more sensitive

"strong_line"

No auroral line available

Sanders+25 simultaneous polynomial across O3, O2, R23, O32

"forward"

Requested explicitly

Cullen+25 Bayesian forward model, sampling T_e, n_e, log U, ionic abundances

4 — Ionic and total abundances

For the direct method, PyNEB computes O⁺/H⁺, O²⁺/H⁺, N⁺/H⁺, C⁺/H⁺, C²⁺/H⁺, Ne²⁺/H⁺, S⁺/H⁺, S²⁺/H⁺, Ar²⁺/H⁺, Ar³⁺/H⁺. ICFs convert ionic to total:

  • N/O — Martinez+25 (multiple tiers auto-selected, override via icf_tier=)

  • C/O — Garnett+97

  • S/O, Ne/O, Ar/O — Izotov+06

5 — T_e-T_e relation

When only the high-ionisation T_e is measured, the low-ionisation T_e comes from:

  • "desi" (default) — DESI DR2 calibration

  • "classical" — Garnett 1992

Result fields

Field

Description

OH, OH_err

12 + log(O/H) and uncertainty

NO, CO, SO, NeO, ArO (+_err)

Element ratios

Te_high, Te_low (+_err)

Electron temperatures (K)

ne, ne_low, ne_mid, ne_high

Electron densities (cm⁻³)

Av, Av_err

Dust attenuation

logU, logU_err

Ionisation parameter

ionic

Dict of ionic abundance ratios

icf_method, NO_icf_name

ICF scheme and tier used for N/O

OH_posterior, NO_posterior

Full posterior arrays (MC / MCMC)

method

"direct" / "strong_line" / "forward"

Lyα escape fraction

When Lyα is present, the intrinsic flux is predicted from the dust-corrected Balmer lines via Case B, and the escape fraction f_esc = F_obs(Lyα) / F_int(Lyα) is returned with MC propagation of A_V uncertainty:

print(abund.lya_f_esc)       # median
print(abund.lya_f_esc_err)   # (lo, hi)

See Chemical Abundance Methodology for the full derivation.