Units and conventions¶
Tengri carries no astropy.units-style runtime tagging. Every array is
a plain JAX array in a fixed, documented unit; conversions live as
pure functions in tengri.units.
This page lists the unit each layer expects, the conventions for metallicity / SFR / time, and the conversion helpers you’ll reach for most often.
The conventions, in one table¶
Quantity |
Unit |
Where it shows up |
|---|---|---|
Wavelength |
Å, vacuum |
|
Spectral flux density |
erg s⁻¹ cm⁻² Hz⁻¹ |
observed photometry / spectroscopy |
Spectral luminosity |
erg s⁻¹ Hz⁻¹ |
every |
Bolometric luminosity |
erg s⁻¹ (preferred) or |
AGN |
Time / age |
yr (internal), Myr / Gyr (user-facing) |
SFH age grids, PSD timescales |
SFR |
M_sun yr⁻¹ |
SFH outputs, |
Stellar mass |
M_sun |
mass normalisations |
Metallicity (SSP grid) |
|
DSPS grid axis |
Metallicity (user API) |
|
|
Magnitudes |
AB system |
photometry helpers default to AB |
Distance modulus |
mag |
|
Redshift |
dimensionless |
|
Vacuum wavelengths throughout — including emission lines (H_alpha = 6564.61 Å).
Never use air wavelengths. If you need them, convert at the boundary:
from tengri.units import vacuum_to_air
wave_air = vacuum_to_air(wave_vac) # Å -> Å
Where unit boundaries live¶
Unit translations happen at three places. Everywhere else the unit is fixed:
Parameters→ forward model. User-facing names (psd_tau_myr,agn_log_lbol,met_logzsol) are translated to internal units (years, erg/s,log10(Z)absolute) by theinternal_param_mapon each registered component. The user only sees the friendly unit; the model only sees the internal one.Forward model → observation.
SEDModel.predict_*returns flux in the unit declared by theObservation— F_ν cgs by default.Observation → user analysis. Use the conversions below to take F_ν cgs to Jy, AB mag, maggies, etc., for plotting or comparison with catalogue data.
Conversion helpers¶
All in tengri.units and JAX-native (JIT/grad/vmap-safe):
from tengri import units
# Spectral flux density
units.fnu_to_jy(fnu) # erg/s/cm²/Hz -> Jansky
units.fnu_to_ujy(fnu) # ... -> microjansky
units.fnu_to_njy(fnu) # ... -> nanojansky
units.fnu_to_maggies(fnu) # ... -> SDSS maggies
units.jy_to_fnu(jy) # inverse
units.fnu_to_flambda(fnu, wave) # F_ν -> F_λ (erg/s/cm²/Å)
# AB / Vega magnitudes
units.fnu_to_ab_mag(fnu)
units.ab_mag_to_fnu(mag_ab)
units.ab_to_vega(mag_ab, band) # band name from filter registry
units.vega_to_ab(mag_vega, band)
# L_ν ↔ F_ν at a given luminosity distance
units.lnu_to_fnu(lnu, d_lum_mpc, redshift)
units.fnu_to_lnu(fnu, d_lum_mpc, redshift)
# Absolute / apparent / surface brightness
units.absolute_to_apparent(M_abs, dm)
units.apparent_to_absolute(m_app, dm)
units.distance_modulus_from_dl_mpc(d_lum_mpc)
# Wavelength media
units.air_to_vacuum(wave_air)
units.vacuum_to_air(wave_vac)
# Energy
units.lsun_to_erg_per_s(lsun)
units.erg_per_s_to_lsun(ergs)
# Optical depth ↔ attenuation
units.tau_to_attenuation(tau) # = exp(-tau)
units.attenuation_to_tau(att)
The full list (about 35 helpers) is tengri.units.__all__ —
from tengri import units; help(units) shows it.
Why no astropy.units¶
Tengri is JAX-native and pre-1.0 research code. Wrapping every array in
an astropy.units.Quantity would (a) break JIT, since Quantity is
not a JAX type, (b) double the memory of every internal array, and
(c) introduce subtle conversion edge cases at every vmap boundary.
The convention here — fixed unit per layer, conversion helpers at the
boundary — has been stable since v0.1 and matches what working
SED-fitting codes (Bagpipes, Prospector, FSPS) actually do under the
hood. If you need to interoperate with astropy.units at the user
layer, convert your inputs to plain arrays in tengri’s units before
the fit and tag the outputs after.
Common gotchas¶
agn_log_lbolis alwayslog10(L_bol / L_sun)at the API level. The AGN component converts to erg/s internally; user code should never multiply by 3.828e33 itself.PSD timescale is Myr as
psd_tau_myrat the API level, years aspsd_tau_yrinternally. The internal-param map handles the1e6factor.Metallicity offset.
met_logzsolislog10(Z/Z_sun)(user) but the SSP grid islog10(Z)absolute. The translation addsLOG10_ZSUN = -1.848, defined intengri.utils.physics_constants. Do not reproduce this constant by hand.Emission lines are vacuum throughout.
H_alpha = 6564.61 Å, not 6562.8 Å (which is air).All SED components return
erg/s/Hz(standardised 2026-04-08). If you’re porting an external component, normalise to this unit before returning.Per-band photometry units.
predict_photometryreturns one F_ν value per filter band, in cgs. The filter integral cancels the per-Hz-per-Å distinction; the output is mean F_ν over the bandpass.
See also¶
docs/dev/NAMING_CONTRACT.md— parameter naming rules including unit suffixes (_myr,_gyr,_kms) for user-facing parameters.tengri.utils.physics_constants— the canonical source forLOG10_ZSUN,L_SUN, etc.tengri.cosmology— Planck18 distance / age helpers for redshift conversions.