Discovering the Menu¶
Tengri keeps its physics in registries — every SFH family, dust law, AGN model, filter, and inference backend lives behind a name. This notebook walks through the API for asking what’s there: list_*(), describe(), search(), doctor(). Pure introspection, no fitting, runs in a couple of seconds.
Why bother? Because the alternative — reading the source — is slower and you’ll miss models registered by plugins or recent commits. tengri.summary() reads the live registry; if someone adds a new AGN model with @register_agn_model, the count updates here too.
Global overview¶
Start with a bird’s-eye view of everything in tengri.
[1]:
import numpy as np
import tengri
# The one-liner summary: counts of every menu.
tengri.summary()
tengri — what's available:
7 physics components tengri.list_components()
12 AGN models tengri.list_agn_models()
21 dust attenuation laws tengri.list_dust_laws()
7 dust emission templates tengri.list_dust_emission_models()
34 SFH models tengri.list_sfh_models()
4 nebular backends tengri.list_nebular_backends()
242 photometric filters tengri.list_filters()
8 plotting helpers tengri.list_plots()
6 primary inference methods tengri.list_inference_methods(tier='primary')
19 total inference methods tengri.list_inference_methods()
Look up any name: tengri.describe('skirtor')
Curated cheatsheet for new users: tengri.help()
``tengri.summary()`` is what you run first after import tengri. It prints live counts from every registry — add a new model via @register_agn_model and this number updates automatically.
The full cheatsheet¶
``tengri.help()`` is a 5-section narrative. Read it once to see the entire surface area of the library.
[2]:
tengri.help()
tengri — differentiable galaxy SED fitting in JAX
────────────────────────────────────────────────────────────────────
1. See what's available
────────────────────────────────────────────────────────────────────
tengri.summary() one-line counts of every menu
tengri.list_agn_models() 12 AGN models
tengri.list_dust_laws() 21 attenuation curves (UV/optical)
tengri.list_dust_emission_models() 7 IR emission templates
tengri.list_sfh_models() 34 SFH variants
tengri.list_nebular_backends() 4 nebular backends
tengri.list_inference_methods(tier="primary") 6 primary methods
tengri.list_filters() 242 filter curves
tengri.describe("skirtor") full metadata for any name
tengri.search("torus") cross-menu fuzzy search
tengri.doctor() env / install / SSP health check
tengri.help("dust") topical cheatsheet for one menu
────────────────────────────────────────────────────────────────────
2. Learn the design — interactive tutorials
────────────────────────────────────────────────────────────────────
tengri.tutorial() list every available recipe
tengri.tutorial("philosophy") layered architecture + IFT framework
tengri.tutorial("key_classes") Parameters / SEDModel / Fitter / Posterior
tengri.tutorial("use_cases") common patterns (catalog / hierarchical / mock)
tengri.tutorial("first_fit") end-to-end mock-recovery recipe
tengri.tutorial("register_a_model", run=True) register a new alternative
tengri.tutorial("custom_likelihood") Student-t / calibration / Protocol
tengri.tutorial("swap_inference") same model, NUTS → geoVI → MCMC
tengri.tutorial("diagnostics") ESS / R-hat / convergence checking
tengri.explain(tengri.SEDModel) architectural role of any class
tengri.examples() list every runnable example script
────────────────────────────────────────────────────────────────────
3. Build a fit
────────────────────────────────────────────────────────────────────
obs = tengri.Observation(photometry=tengri.Photometry.from_names([...]))
parameters = tengri.Parameters(...) # priors + fixed values
model = tengri.SEDModel(parameters, ssp_data, observation=obs)
fitter = tengri.Fitter(model, data, noise)
posterior = fitter.run("map") # or "nuts", "vi", …
posterior.summary() # median ± 68% CI per param
Pick the right kwargs:
tengri.suggest_parameters(mean_sfh_type="dpl", agn_model="skirtor")
────────────────────────────────────────────────────────────────────
4. Contribute a new physics alternative
────────────────────────────────────────────────────────────────────
Copy examples/contrib/example_new_agn_torus.py. It registers a new
AGN torus model with metadata (citation, status), then exercises the
introspection API end-to-end. See CONTRIBUTING.md for the 5-step recipe.
────────────────────────────────────────────────────────────────────
5. Cite the components used
────────────────────────────────────────────────────────────────────
tengri.cite_components(model_or_posterior) live walk of every component used
tengri.print_components_bibtex(spec) BibTeX-only output
tengri.print_citations(model) formal Bibliography report
tengri.help('citations') full citation cheatsheet
``tengri.help(“dust”)`` narrows to one topic — dust attenuation + emission in this case. Try other topics too: "agn", "sfh", "nebular", "components", "inference", "filters", "plot", "citations".
[3]:
tengri.help("dust")
tengri.help('dust') — dust attenuation + emission: 28 available
name kind status citation short_doc use
──────────── ──────────────── ──────────── ───────────────────────────────────────────────── ────────────────────────────────────────────────────── ──────────────────────────────────────────
calzetti dust_attenuation production Calzetti et al. 2000 (ApJ 533, 682) Calzetti et al. starburst attenuation (R_V=4.05) Parameters(..., dust_law="calzetti")
cardelli dust_attenuation production Cardelli et al. 1989 (ApJ 345, 245) MW extinction Cardelli et al. MW extinction (parameterized R_V) Parameters(..., dust_law="cardelli")
conroy2010 dust_attenuation production Conroy et al. 2010 (ApJ 708, 58) Conroy+10 mixed MW + power-law (FSPS default) Parameters(..., dust_law="conroy2010")
d03_mwrv31 dust_attenuation production Draine 2003 (ARA&A 41, 241) Draine 2003 MW R_V=3.1 grain model attenuation Parameters(..., dust_law="d03_mwrv31")
hd23_mwrv31 dust_attenuation production Hensley & Draine 2023 (ApJ 948, 55) Hensley & Draine 2023 astrodust+PAH grain model Parameters(..., dust_law="hd23_mwrv31")
kriek_conroy dust_attenuation production Kriek & Conroy 2013 (ApJL 775, L16) Kriek & Conroy modified Calzetti + bump + slope Parameters(..., dust_law="kriek_conroy")
leitherer02 dust_attenuation production Leitherer et al. 2002 (ApJS 140, 303) Leitherer et al. UV starburst attenuation Parameters(..., dust_law="leitherer02")
li08 dust_attenuation production Li et al. 2008 (ApJ 685, 1046) Li et al. analytical flexible attenuation curve Parameters(..., dust_law="li08")
lmc dust_attenuation production Pei 1992 (ApJ 395, 130) LMC LMC extinction (Pei 1992, weak bump) Parameters(..., dust_law="lmc")
narayanan_z dust_attenuation production Narayanan et al. 2018 (ApJ 869, 70) Narayanan et al. z-dependent attenuation (SIMBA) Parameters(..., dust_law="narayanan_z")
noll09 dust_attenuation production Noll et al. 2009 (A&A 507, 1793) Noll et al. modified Calzetti + L02 + bump + slope Parameters(..., dust_law="noll09")
power_law dust_attenuation production Charlot & Fall 2000 (ApJ 539, 718) Generic power-law attenuation Parameters(..., dust_law="power_law")
prevot_smc dust_attenuation production Prevot et al. 1984 (A&A 132, 389) Prevot et al. SMC extinction for AGN Parameters(..., dust_law="prevot_smc")
salim dust_attenuation production Salim et al. 2018 (ApJ 859, 11) Salim et al. modified Calzetti (DSPS default) Parameters(..., dust_law="salim")
salim_sbl18 dust_attenuation production Salim et al. 2018 (ApJ 859, 11) Salim, Boquien & Lee modified Calzetti + L02 Parameters(..., dust_law="salim_sbl18")
smc dust_attenuation production Pei 1992 (ApJ 395, 130) SMC Bar SMC extinction (Pei 1992, no 2175 bump) Parameters(..., dust_law="smc")
tea dust_attenuation production Haskell et al. 2024 (arXiv:2401.11007) TEA empirical attenuation from NIHAO-SKIRT simulations Parameters(..., dust_law="tea")
vw07_bc dust_attenuation production Wild et al. 2007 (MNRAS 381, 543) Wild+07 birth cloud (n=-1.3, steep UV) Parameters(..., dust_law="vw07_bc")
vw07_diff dust_attenuation production Wild et al. 2007 (MNRAS 381, 543) Wild+07 diffuse ISM (n=-0.7, standard) Parameters(..., dust_law="vw07_diff")
wd01_mwrv31 dust_attenuation production Weingartner & Draine 2001 (ApJ 548, 296) WD01 MW R_V=3.1 grain model attenuation Parameters(..., dust_law="wd01_mwrv31")
wd01_smcbar dust_attenuation production Weingartner & Draine 2001 (ApJ 548, 296) WD01 SMC Bar grain model attenuation Parameters(..., dust_law="wd01_smcbar")
astrodust dust_emission experimental Hensley & Draine 2023 (ApJ 948, 55) Astrodust + PAH unified grain model Parameters(..., dust_emission="astrodust")
bosa dust_emission experimental Boquien et al. 2019 (CIGALE BOSA grids) BOSA dust SED templates Parameters(..., dust_emission="bosa")
dale2014 dust_emission production Dale et al. 2014 (ApJ 784, 83) SFR-driven empirical IR template family (alpha_sf) Parameters(..., dust_emission="dale2014")
dl07 dust_emission production Draine & Li 2007 (ApJ 657, 810) Diffuse + PAH grain mixture, Umin/Umax/qpah Parameters(..., dust_emission="dl07")
dl14 dust_emission production Draine et al. 2014 (ApJ 780, 172) Updated DL with extended PAH and silicate features Parameters(..., dust_emission="dl14")
mbb dust_emission production Casey 2012 (MNRAS 425, 3094) Single-temperature modified blackbody (analytic) Parameters(..., dust_emission="mbb")
themis dust_emission experimental Jones et al. 2017 (A&A 602, A46) THEMIS amorphous-carbon grain model Parameters(..., dust_emission="themis")
[28 results — mixed]
API discovery surface¶
Tengri exposes more discovery helpers beyond the menus above.
4.1. Filter suggestion by redshift¶
[22]:
# Suggest a bandset for a low-redshift galaxy (z=0.05) and a high-z target (z=2.5).
low_z_filters = tengri.filters.suggest(redshift=0.05, coverage="visible_to_nir")
print(f"Suggested filters for z=0.05:\n {low_z_filters}\n")
high_z_filters = tengri.filters.suggest(redshift=2.5, coverage="visible_to_nir")
print(f"Suggested filters for z=2.5:\n {high_z_filters}\n")
Suggested filters for z=0.05:
['megacam_u', 'lsst_u', 'megacam_u2', 'suprime_ib427', 'hst_f435w', 'xmm_b', 'uvot_b', 'johnson_b', 'suprime_b', 'suprime_ib464', 'sdss_g', 'des_g', 'suprime_g', 'megacam_g', 'lsst_g', 'hsc_g', 'suprime_ib484', 'megacam_g2', 'ps1_g', 'suprime_ib505', 'suprime_ib527', 'xmm_v', 'uvot_v', 'suprime_v', 'johnson_v', 'suprime_ib574', 'hst_f606w', 'sdss_r', 'ps1_r', 'hsc_r', 'lsst_r', 'suprime_ib624', 'megacam_r2', 'suprime_r', 'roman_f062', 'megacam_r', 'des_r', 'cousins_r', 'suprime_rc', 'suprime_na656', 'suprime_ib679', 'johnson_r', 'jwst_f070w', 'nircam25_f070w', 'suprime_ib709', 'suprime_nb711', 'euclid_vis', 'suprime_ib738', 'sdss_i', 'lsst_i', 'ps1_i', 'megacam_i3', 'suprime_i', 'suprime_ib767', 'megacam_i2', 'megacam_i', 'hst_f775w', 'hsc_i', 'des_i', 'cousins_i', 'suprime_ic', 'hst_f814w', 'suprime_nb816', 'suprime_ib827', 'ps1_z', 'lsst_z', 'roman_f087', 'johnson_i', 'vista_z', 'megacam_z2', 'ukidss_z', 'hsc_z', 'sdss_z', 'megacam_z', 'niriss_f090w', 'suprime_z', 'jwst_f090w', 'nircam25_f090w', 'hst_f850lp', 'suprime_nb921', 'des_z', 'ps1_y', 'lsst_y', 'hsc_y', 'des_y', 'suprime_y', 'vista_y', 'ukidss_y', 'hst_f105w', 'roman_f106', 'euclid_y', 'niriss_f115w', 'nircam25_f115w', 'jwst_f115w', '2mass_j', 'johnson_j', 'ukidss_j', 'hst_f125w', 'vista_j', 'roman_f129', 'euclid_j', 'hst_f140w', 'niriss_f140m', 'jwst_f140m', 'nircam25_f140m', 'niriss_f150w', 'jwst_f150w', 'nircam25_f150w', 'hst_f160w', 'roman_f158', 'niriss_f158m', 'nircam25_f162m', 'jwst_f162m', 'ukidss_h', 'nircam25_f164n', 'jwst_f164n', 'vista_h', '2mass_h', 'jwst_f150w2', 'nircam25_f150w2', 'euclid_h', 'roman_f184', 'jwst_f182m', 'nircam25_f182m', 'jwst_f187n', 'nircam25_f187n', 'niriss_f200w', 'nircam25_f200w', 'jwst_f200w', 'jwst_f210m', 'nircam25_f210m', 'nircam25_f212n', 'jwst_f212n', 'roman_f213', 'vista_ks', '2mass_ks', 'ukidss_k', 'nirspec_g235h', 'akari_n2', 'nirspec_g235m', 'nircam25_f250m', 'jwst_f250m']
Suggested filters for z=2.5:
['2mass_j', 'johnson_j', 'ukidss_j', 'hst_f125w', 'vista_j', 'roman_f129', 'euclid_j', 'hst_f140w', 'niriss_f140m', 'jwst_f140m', 'nircam25_f140m', 'niriss_f150w', 'jwst_f150w', 'nircam25_f150w', 'hst_f160w', 'roman_f158', 'niriss_f158m', 'nircam25_f162m', 'jwst_f162m', 'ukidss_h', 'nircam25_f164n', 'jwst_f164n', 'vista_h', '2mass_h', 'jwst_f150w2', 'nircam25_f150w2', 'euclid_h', 'roman_f184', 'jwst_f182m', 'nircam25_f182m', 'jwst_f187n', 'nircam25_f187n', 'niriss_f200w', 'nircam25_f200w', 'jwst_f200w', 'jwst_f210m', 'nircam25_f210m', 'nircam25_f212n', 'jwst_f212n', 'roman_f213', 'vista_ks', '2mass_ks', 'ukidss_k', 'nirspec_g235h', 'akari_n2', 'nirspec_g235m', 'nircam25_f250m', 'jwst_f250m', 'jwst_f277w', 'niriss_f277w', 'nircam25_f277w', 'jwst_f300m', 'nircam25_f300m', 'nirspec_prism', 'nircam25_f323n', 'jwst_f323n', 'jwst_f322w2', 'akari_n3', 'nircam25_f322w2', 'jwst_f335m', 'nircam25_f335m', 'wise_w1', 'irac_36', 'nircam25_f356w', 'jwst_f356w', 'niriss_f356w', 'nircam25_f360m', 'jwst_f360m', 'niriss_f380m', 'nirspec_g395h', 'nirspec_g395m', 'jwst_f405n', 'nircam25_f405n', 'jwst_f410m', 'nircam25_f410m', 'jwst_f430m', 'nircam25_f430m', 'niriss_f430m', 'nircam25_f444w', 'jwst_f444w', 'niriss_f444w', 'akari_n4', 'irac_45', 'nircam25_f460m', 'jwst_f460m', 'wise_w2', 'nircam25_f466n', 'jwst_f466n', 'jwst_f470n', 'nircam25_f470n', 'nircam25_f480m', 'niriss_f480m', 'jwst_f480m', 'miri_f560w', 'irac_58', 'akari_s7', 'miri_f770w', 'irac_80']
4.2. Filter properties and metadata¶
[23]:
# Inspect a single filter in detail.
info = tengri.filters.filter_info("jwst_f200w")
print(f"Filter info for {info['name']}:")
print(f" Facility: {info['facility']}")
print(f" λ_eff: {info['lambda_eff_str']}")
print(f" FWHM: {info['fwhm_str']}\n")
Filter info for jwst_f200w:
Facility: JWST/NIRCam
λ_eff: 1.99 μm
FWHM: 4700 Å
Compute effective wavelength and FWHM for any filter.
[24]:
# Load a few filters and compute their properties
test_filters = ["sdss_u", "sdss_g", "2mass_j"]
for fname in test_filters:
fc = tengri.filters.load_filter(fname)
wave_np, trans_np = (np.asarray(fc.wave), np.asarray(fc.trans))
lam_eff = tengri.filters.compute_effective_wavelength(wave_np, trans_np)
fwhm = tengri.filters.compute_fwhm(wave_np, trans_np)
print(f"{fname:15s} λ_eff={lam_eff:8.1f} Å FWHM={fwhm:7.1f} Å")
sdss_u λ_eff= 3561.8 Å FWHM= 575.0 Å
sdss_g λ_eff= 4718.9 Å FWHM= 1250.0 Å
2mass_j λ_eff= 12410.5 Å FWHM= 2140.0 Å
4.3. Introspection API¶
[25]:
# List available example scripts
try:
tengri.examples()
except NotImplementedError:
print("❋ api preview — examples() not yet implemented\n")
tengri runnable example scripts (133 total):
examples/advanced/plot_fisher_degeneracy.py Age-Dust-Metallicity Degeneracy: Fisher Analysis
examples/advanced/plot_gradient_sensitivity.py Gradient Sensitivity Heatmap
examples/advanced/plot_hierarchical.py Hierarchical PSD Inference
examples/advanced/plot_joint_fit.py Joint Photometry + Spectroscopy Fit
examples/advanced/plot_orchestrator_demo.py Component orchestrator end-to-end
examples/advanced/plot_radio_xray.py Panchromatic SED: UV to Radio
examples/agn/plot_agn_alpha_ox_lbol_2d.py X-ray Corona: Spectral Index vs Bolometric Luminosity 2D Sweep
examples/agn/plot_agn_cos_inc_sweep.py SKIRTOR Torus: Viewing Angle Sweep
examples/agn/plot_agn_hierarchy.py AGN SEDModel Hierarchy
examples/agn/plot_agn_log_lbol_sweep.py QSOgen Disc Continuum: Bolometric Luminosity
examples/agn/plot_agn_oa_sweep.py SKIRTOR Torus: Opening Angle Sweep
examples/agn/plot_agn_polar_dust_temp_sweep.py Polar Dust: Temperature Sweep in AGN Torus
examples/agn/plot_agn_qsogen_ebv_sweep.py QSOgen Dust Reddening: Intrinsic AGN Obscuration
examples/agn/plot_agn_qsogen_emline_sweep.py QSOgen Emission Line Scaling: Rest-UV to Optical SED
examples/agn/plot_agn_skirtor_p_sweep.py SKIRTOR Torus: Radial Dust Power-Law Sweep
examples/agn/plot_agn_tau_skirtor_sweep.py SKIRTOR Torus: Optical Depth Sweep
examples/agn/plot_agn_templates.py AGN SED Templates
examples/agn/plot_agn_type12.py Type 1 vs Type 2 AGN: Geometric Unification
examples/agn/plot_nlr_blr_lines.py Narrow and Broad Line Region Emission
examples/agn/plot_polar_dust.py Polar Dust in AGN: IR Bump from Polar Dust Torus
examples/agn/plot_qsogen_spectrum.py QSOgen Empirical Quasar Template
examples/agn/plot_relagn_spin.py RELAGN Spin Sweep
examples/agn/plot_skirtor_variants.py SKIRTOR Clumpy Torus: Inclination and Optical Depth
examples/agn/plot_torus_comparison.py Torus Models Comparison: Nenkova vs Silva04
examples/contrib/example_fit_real_csv.py Worked example: fit a real galaxy from a CSV of measured fluxes.
examples/contrib/example_new_agn_torus.py Worked example: contributing a new AGN torus model to tengri.
examples/dust/plot_attenuation_law_compare.py Attenuation Law Comparison
examples/dust/plot_dust_T_sweep.py Modified Blackbody Dust Temperature
examples/dust/plot_dust_curves.py Dust Attenuation Curves
examples/dust/plot_dust_emission_models.py Dust Emission Models: Overview
examples/dust/plot_dust_geometry_sweep.py Dust Geometry: Screen vs Mixed vs Clumpy
examples/dust/plot_dust_qpah_umin_grid.py Dust IR SED: q_PAH × U_min Grid
examples/dust/plot_dust_slope_sweep.py Attenuation Curve Slope (δ)
examples/dust/plot_qpah_sweep.py PAH Mass Fraction (q_PAH)
examples/dust/plot_tau_bc_sweep.py Birth Cloud Optical Depth (τ_BC)
examples/dust/plot_tau_diff_sweep.py Diffuse ISM Optical Depth (τ_diff)
examples/dust/plot_two_component.py Two-Component Dust SEDModel
examples/dust/plot_umin_sweep.py Draine & Li Minimum Radiation Field (U_min)
examples/dust/plot_uv_bump_sweep.py UV Bump Strength (dust_bump_strength)
examples/igm/plot_dla_absorption.py Damped Lyman-Alpha (DLA) Absorption
examples/igm/plot_igm_model_comparison.py IGM Transmission Model Comparison
examples/igm/plot_igm_redshift.py IGM Transmission vs Redshift
examples/igm/plot_igm_z_evolution.py IGM Absorption Evolution with Redshift
examples/inference/plot_convergence.py Convergence Diagnostics
examples/inference/plot_corner.py Corner Plot with Truth Overlay
examples/inference/plot_hierarchical_convergence.py Population PSD Recovery: 1/√N Convergence
examples/inference/plot_method_comparison.py MAP vs geoVI Posterior Comparison
examples/inference/plot_population_scaling.py Population VI scaling: time, memory, and convergence
examples/inference/plot_prior_posterior_compare.py Prior vs Posterior: Parameter Constraints from Inference
examples/metallicity/plot_alpha_fe_sweep.py α/Fe Enhancement (met_alpha_fe)
examples/metallicity/plot_logzsol_panchromatic.py Metallicity Sweep: Panchromatic SED
examples/metallicity/plot_logzsol_sweep.py Stellar Metallicity (log Z/Z_⊙)
examples/metallicity/plot_metallicity_age_grid.py Stellar Continuum: Metallicity × Age Grid
examples/metallicity/plot_zh_evolution_compare.py Chemical Evolution: Model Comparison
examples/multiwavelength/plot_fir_radio_correlation.py FIR–Radio Correlation
examples/multiwavelength/plot_panchromatic_agn.py Panchromatic AGN Host SED
examples/multiwavelength/plot_panchromatic_agn_fraction.py AGN Contribution to Composite SEDs
examples/multiwavelength/plot_panchromatic_dust_balance.py Dust Energy Balance: UV Attenuation ↔ IR Emission
examples/multiwavelength/plot_panchromatic_galaxy.py Panchromatic Star-Forming Galaxy
examples/multiwavelength/plot_panchromatic_redshift_sweep.py Panchromatic SED: Redshift Evolution
examples/nebular/plot_bpt_cue_flexibility.py BPT with Cue: Every Knob, One Panel Each
examples/nebular/plot_bpt_cue_grid.py BPT Diagrams with Cue: 2D Grid in (log U, log Z_gas)
examples/nebular/plot_bpt_diagnostics.py BPT Diagnostics: Star Formation, Shocks, and AGN
examples/nebular/plot_dig_frac_sweep.py Diffuse Ionized Gas Fraction (f_DIG)
examples/nebular/plot_fesc_sweep.py Ionizing Photon Escape Fraction (f_esc)
examples/nebular/plot_line_sigma_sweep.py Emission Line Width (σ in km/s)
examples/nebular/plot_logu_sweep.py Ionization Parameter (logU)
examples/nebular/plot_logz_gas_sweep.py Gas Metallicity (log Z/Zsun)
examples/nebular/plot_neb_age_dependence.py Nebular Emission: Dependence on Stellar Population Age
examples/nebular/plot_neb_backend_compare.py Nebular Backends: BakedIn vs CloudyGrid vs Cue
examples/nebular/plot_neb_bpt_logu_grid.py BPT Diagram: Ionization Parameter Sequence
examples/nebular/plot_neb_density_sweep.py Nebular Gas Density: Metallicity Variation
examples/nebular/plot_nebular_backends.py Nebular Emission Backends
examples/nebular/plot_shock_emission.py Nebular Shock Emission (MAPPINGS V)
examples/photometry/plot_filter_curves.py SDSS Filter Transmission Curves
examples/photometry/plot_filter_set_comparison.py Filter Set Comparison
examples/photometry/plot_photometric_fit.py Photometric SED Fit
examples/photometry/plot_redshift_filter_grid.py Filter Sampling Across Redshift
examples/photometry/plot_snr_sweep.py S/N Ratio Parameter Sweep
examples/quickstart/plot_first_fit.py First Photometric Fit
examples/quickstart/plot_sed_components.py SED Components
examples/radio/plot_alpha_sf_sweep.py Radio Spectral Index (α_sf)
examples/radio/plot_q_ir_sweep.py FIR-Radio Correlation (q_IR)
examples/radio/plot_radio_lir_relation.py FIR-Radio Correlation: L_IR Luminosity Sweep
examples/radio/plot_radio_loudness_sweep.py AGN Radio Loudness (R)
examples/recipes/__init__.py Recipes: Bite-sized "how to do X" examples for common tasks.
examples/recipes/plot_recipe_compare_priors.py Prior Sensitivity: Gaussian vs Uniform
examples/recipes/plot_recipe_custom_filter.py Register and Use Custom Filters
examples/recipes/plot_recipe_load_real_csv.py Load and Fit Real CSV Photometry
examples/recipes/plot_recipe_save_load_posterior.py Save and Load a Posterior
examples/recipes/plot_recipe_specific_redshift.py Fix Redshift to a Known Value
examples/sfh/plot_bursty_recovery.py SFH Recovery Across Four Burstiness Regimes
examples/sfh/plot_chemical_evolution.py Chemical Evolution: Metallicity History Models
examples/sfh/plot_dexp_tau_sweep.py Delayed-τ SFH: Star Formation Timescale
examples/sfh/plot_dpl_alpha_beta_grid.py Double Power-Law SFH: 2D Parameter Grid (α × β)
examples/sfh/plot_dpl_alpha_sweep.py Double Power-Law SFH: Rising Slope α
examples/sfh/plot_dpl_beta_sweep.py Double Power-Law SFH: Falling Slope β
examples/sfh/plot_lnorm_peak_sweep.py Log-Normal SFH: Peak Lookback Time
examples/sfh/plot_parametric_sfh.py Parametric SFH Models
examples/sfh/plot_psd_alternatives.py Alternative PSD Models
examples/sfh/plot_psd_burstiness.py PSD Parameter Space and Burstiness
examples/sfh/plot_psd_sigma_sweep.py Stochastic SFH: Burstiness Amplitude σ
examples/sfh/plot_psd_tau_sweep.py Stochastic SFH: Burstiness Timescale τ
examples/sfh/plot_sfh_double_burst.py SFH with Double Bursts: Old and Recent Star Formation
examples/sfh/plot_sfh_quenching_compare.py SFH Quenching Scenarios: Constant, Exponential, Sharp, and Burst+Decay
examples/sfh/plot_stochastic_sfh.py Stochastic SFH from GP Correlated Fields
examples/sfh/plot_wrong_model_trap.py The Wrong-SEDModel Trap: Parametric Bias in Derived Quantities
examples/spectroscopy/plot_resolution_sweep.py Instrumental Resolution Sweep
examples/spectroscopy/plot_spectral_features.py Key Spectral Features as Age and Metallicity Probes
examples/spectroscopy/plot_spectrum_fit.py Spectroscopic SED Fit
examples/spectroscopy/plot_velocity_dispersion_sweep.py Stellar Velocity Dispersion Sweep
examples/sps/plot_ssp_age_sweep.py Stellar Population Aging: SSP at Solar Metallicity
examples/sps/plot_ssp_grid.py SSP Grid Visualization: Age and Metallicity
examples/sps/plot_ssp_imf_compare.py IMF Comparison: Mass-to-Light Ratio
examples/sps/plot_ssp_metallicity_sweep.py Stellar Metallicity Effects on SED
examples/usecases/__init__.py
examples/usecases/plot_usecase_age_dust_degeneracy.py Age-Dust-Metallicity Degeneracy with UV Break
examples/usecases/plot_usecase_emission_line_pcc.py Emission Line Ratio Correlation Matrix for Nebular Diagnostics
examples/usecases/plot_usecase_jwst_color_color.py JWST NIRCam Color-Color Diagram for High-z Classification
examples/usecases/plot_usecase_mass_completeness.py Stellar Mass Completeness in Photometric Surveys
examples/usecases/plot_usecase_sfr_indicator_compare.py SFR Indicator Comparison: UV, Hα, FIR, Bolometric
examples/usecases/plot_usecase_uvj_diagram.py UVJ Diagram: Star-Forming vs Passive Galaxy Population
examples/workflows/__init__.py Workflow examples demonstrating real-world scientific use cases.
examples/workflows/plot_workflow_bpt_classification.py Workflow: BPT Emission-Line Classification
examples/workflows/plot_workflow_dust_mc_resampling.py Workflow: Dust Attenuation Uncertainty via Posterior Resampling
examples/workflows/plot_workflow_high_z_lbg.py Workflow: High-z Lyman-Break Galaxy
examples/workflows/plot_workflow_method_comparison.py Workflow: Inference Method Comparison
examples/workflows/plot_workflow_post_starburst.py Workflow: Post-Starburst (E+A) Galaxy Diagnosis
examples/xray/plot_E_cut_sweep.py High-Energy Cutoff Variation
examples/xray/plot_alpha_ox_sweep.py X-ray Normalisation via UV-to-X-ray Slope
examples/xray/plot_xray_agn.py AGN X-ray Emission and Corona
examples/xray/plot_xray_gamma_sweep.py X-ray Spectral Index Variation
examples/xray/plot_xray_sf.py X-ray Binary Population from Star Formation
Run any of them with:
cd /Users/suchethacooray/Projects/tengri
.venv/bin/python <path>
Explain the role of major classes.
[26]:
# Show architectural role of SEDModel and Posterior
try:
tengri.explain(tengri.SEDModel)
except NotImplementedError:
print("❋ api preview — explain() not yet implemented\n")
SEDModel
────────
FORWARD MODEL (layer 2)
Wires Parameters + SSP + Observation into one JIT-compiled function:
predict_photometry(params) → flux array.
Tutorial: tengri.tutorial('key_classes')
Print the fun easter egg.
[27]:
tengri.print_logo()
████████
████████████████
██████ ██████
███████ ███████
██████ ██████
██████ ██████
██████ █████████████████ ██████
██████ ██████ ███████ ██████
█████ █████ █████ █████
████ ████ ██████████ ████ ████
████ ████ ████████ ████████ ████ ████
███ ███ ████ ████ █████ ████ ███
███ ███ ████ ██████████████ ████ ███ ███
███ ███ ███ █████ █████ ███ ███ ███
███ ███ ██ ████ ████████ ████ ███ ███ ███
███ ██ ██ ███ ██████ █████ ████ ███ ███ ███
███ ██ █ ███ ████ ██████ ███ ███ ███ ███ ███
███ ████ ███ ███ ███ ████ ███ ███ ███ ███
███ ███ ███ ███ ███ ███ ███ ███ ███ ███
███ ███ ███ ███ ███ ███ ███ ███ ███ ███
███ ███ ███ ███ ████ ███ ████ ███ █ ██ ███
███ ███ ███ ███ ████ ████ ████ ███ ██ ██ ███
███ ███ ███ ███ ███████████ ███ ██ ██ ███
███ ██ ███ ████ ████ █████ ██ ███ ███
███ ███ ███ ███████ ████████ ███ ███ ███
███ ███ ████ ██████████ ████ ███ ███
███ ████ ██████ █████ ███ ███
███ ████ ████████████████ ███ ███
█████ ████ ████ █████
█████ ██████ █████ █████
███████ █████████ █████████ ███████
██████ ████████████ ██████
██████ ██████
██████ ██████
███████ ███████
██████ ██████
██████████████
██████████
4.4. Parameter suggestion¶
[28]:
# Ask tengri to suggest default parameters for a given configuration
try:
suggested = tengri.suggest_parameters(
mean_sfh_type="dpl",
dust_law_bc="calzetti",
dust_emission="dale2014",
)
print("Suggested parameter set:")
print(suggested)
except (NotImplementedError, TypeError):
print("❋ api preview — suggest_parameters() under development\n")
Parameters configuration: mean_sfh_type='dpl', dust_emission='dale2014'
→ 30 parameters. Pass any subset as kwargs to tengri.Parameters().
Suggested parameter set:
name default description
──────────────────── ────────────────── ────────────────────────────────────────────────────────────────────────────────
dust_Rv Fixed(3.1) Total-to-selective extinction R_V (Cardelli)
dust_T Fixed(35.0) Dust temperature (K) for greybody/Casey emission
dust_T_cold Fixed(20.0) Cold ISM grain temperature (K) — used by the two-temperature emission model (...
dust_T_warm Fixed(45.0) Warm birth-cloud grain temperature (K) — used by two-temp emission model (30-...
dust_alpha_dale Fixed(2.0) Dale et al. 2014 alpha parameter (0.0625-4.0)
dust_alpha_dl14 Fixed(2.0) DL14 power-law slope of radiation field distribution (1.0-3.0)
dust_alpha_mir Fixed(2.0) Mid-IR power-law slope for Casey 2012 emission
dust_beta_ir Fixed(1.6) IR emissivity index for greybody/Casey emission
dust_bump_strength Fixed(0.0) UV bump strength at 2175A (Kriek & Conroy 2013)
dust_delta Fixed(0.0) Attenuation curve slope modification
dust_eta_balance Fixed(1.0) Energy balance relaxation: L_IR = eta * L_absorbed. eta=1.0 = strict energy b...
dust_f_obscuration Fixed(0.0) Fraction of unobscured sightlines (Lower 2022)
dust_gamma_dl Fixed(0.01) Draine & Li 2007 PDR fraction (0-1)
dust_log_ssfr Fixed(-10.0) log10(sSFR/yr^-1) for BOSA template selection (Boquien & Salim 2021)
dust_qhac Fixed(0.17) THEMIS small hydrocarbon grain fraction (Jones+2017, 0-15%)
dust_qpah Fixed(2.5) Draine & Li PAH mass fraction (%, 0.47-4.58 for DL07, 0.47-7.32 for DL14)
dust_slope Fixed(-0.7) Dust power-law index
dust_tau_bc Uniform(0.0, 4.0) Birth cloud optical depth
dust_tau_diff Uniform(0.0, 3.0) Diffuse ISM optical depth
dust_umin Fixed(1.0) Draine & Li minimum radiation field (0.1-25 for DL07, 0.1-50 for DL14)
met_alpha_fe Fixed(0.0) Alpha-element enhancement [alpha/Fe] (dex). Applied uniformly to all ages unl...
met_logzsol Uniform(-2.0, 0.2) log10(Z/Zsun)
noise_dof Fixed(0.0) Student-t degrees of freedom for outlier robustness (0=Gaussian)
noise_frac_cal Fixed(0.0) Fractional calibration noise floor (added in quadrature with obs noise)
redshift Fixed(0.1) Source redshift
sfh_dpl_alpha Uniform(0.1, 5.0) DPL falling slope
sfh_dpl_beta Uniform(0.1, 3.0) DPL rising slope
sfh_dpl_log_peak_sfr Uniform(-1.0, 3.0) log10 peak SFR
sfh_dpl_tau_gyr Uniform(0.1, 12.0) DPL turnover time (Gyr)
sigma_v_kms Fixed(0.0) Stellar velocity dispersion sigma_v [km/s] — added in quadrature to the instr...
[30 results — parameter]
4.5. Bibliography registry¶
[29]:
# Cite a single author/model by key
try:
tengri.cite("calzetti")
except (KeyError, TypeError):
print("❋ No direct cite('calzetti') in this version; see cite_components()\n")
❋ No direct cite('calzetti') in this version; see cite_components()
4.6. List all registries at once¶
[30]:
all_tables = tengri.list_all()
total = sum(len(table) for table in all_tables.values())
print(f"Total catalog size: {total} entries")
for kind, table in all_tables.items():
print(f" {kind:25s}: {len(table):3d}")
if len(table) > 0:
print(f" {table[0] if isinstance(table[0], dict) else table[0].name}")
print()
Total catalog size: 354 entries
components : 7
{'name': 'stellar', 'kind': 'component', 'status': 'production', 'module': 'tengri.components.stellar.component', 'short_doc': 'SSP integration over SFH (DSPS), metallicity history, mass remaining', 'use': 'tengri.stellar (see list_stellar_models / list_stellar_laws for alternatives)'}
inference_methods : 19
{'name': 'map', 'kind': 'inference_method', 'tier': 'primary', 'short_doc': 'Adam MAP optimization', 'requires': ['optax'], 'use': 'fitter.run("map")'}
agn_models : 12
{'name': 'adaf', 'kind': 'agn_model', 'status': 'production', 'citation': 'Mahadevan 1997 (ApJ 477, 585)', 'short_doc': 'ADAF + truncated disc + simple torus (low-luminosity)', 'use': 'Parameters(..., agn_model="adaf")', 'params': ['agn_log_lbol', 'agn_frac', 'agn_log_mbh', 'agn_log_ledd', 'agn_r_tr', 'agn_adaf_beta', 'agn_adaf_delta', 'agn_cos_inc', 'agn_torus_frac', 'agn_T_torus', 'agn_ebv_disc'], 'param_details': [{'name': 'agn_log_lbol', 'default': 'Fixed(10.0)', 'description': 'AGN bolometric luminosity log10(L_bol / Lsun) — direct parametric mode'}, {'name': 'agn_frac', 'default': 'Fixed(0.0)', 'description': 'AGN luminosity fraction (L_AGN / L_stellar_bol)'}, {'name': 'agn_log_mbh', 'default': 'Fixed(7.0)', 'description': 'AGN black hole mass log10(M_BH/Msun)'}, {'name': 'agn_log_ledd', 'default': 'Fixed(-1.0)', 'description': 'AGN Eddington ratio log10(L/L_Edd)'}, {'name': 'agn_cos_inc', 'default': 'Fixed(0.5)', 'description': 'Cosine of inclination (0=edge-on, 1=face-on)'}, {'name': 'agn_torus_frac', 'default': 'Fixed(0.5)', 'description': 'AGN torus covering factor (fraction of L_bol re-emitted by torus)'}, {'name': 'agn_T_torus', 'default': 'Fixed(1000.0)', 'description': 'AGN torus temperature (K)'}]}
dust_laws : 21
{'name': 'calzetti', 'kind': 'dust_attenuation', 'status': 'production', 'citation': 'Calzetti et al. 2000 (ApJ 533, 682)', 'short_doc': 'Calzetti et al. starburst attenuation (R_V=4.05)', 'use': 'Parameters(..., dust_law="calzetti")'}
dust_emission_models : 7
{'name': 'astrodust', 'status': 'experimental', 'citation': 'Hensley & Draine 2023 (ApJ 948, 55)', 'short_doc': 'Astrodust + PAH unified grain model', 'use': 'Parameters(..., dust_emission="astrodust")', 'kind': 'dust_emission'}
sfh_models : 34
{'name': 'buat08', 'kind': 'sfh_model', 'status': 'production', 'citation': 'Buat et al. 2008', 'short_doc': 'Velocity-parameterized SFH (Buat et al.)', 'use': 'Parameters(..., mean_sfh_type="buat08")', 'params': ['sfh_buat08_velocity_km_s'], 'param_details': [{'name': 'sfh_buat08_velocity_km_s', 'default': 'Uniform(80.0, 360.0)', 'description': 'Rotational velocity (km/s), range [40, 360]'}]}
nebular_backends : 4
{'name': 'baked_in', 'kind': 'nebular_backend', 'status': 'production', 'citation': 'DSPS / FSPS SSP-internal', 'short_doc': 'Emission baked into SSP grid; zero free params', 'use': 'Parameters(..., nebular_backend="baked_in")'}
filters : 242
{'name': '2MASS_2MASS_H', 'kind': 'filter', 'survey': '2MASS', 'instrument': '2MASS', 'band': 'H', 'use': 'Photometry.from_names(["2MASS_2MASS_H"])'}
plots : 8
{'name': 'plot_sed_fit', 'kind': 'plot', 'status': 'production', 'short_doc': 'Plot observed photometry/spectrum + posterior SED + uncertainty band', 'use': 'tengri.plot.plot_sed_fit(...)'}
4.7. Filter operators reference¶
The .filter() method supports several operators for fine-grained queries.
[31]:
# Example: exact match
exact = tengri.list_filters().filter(instrument="MIRI").names()[:3]
print(f"Exact match (instrument='MIRI'): {exact}\n")
# Example: contains
contains = (
tengri.list_filters()
.filter(band__contains="F150")
.names()[:3]
)
print(f"Contains (band__contains='F150'): {contains}\n")
# Example: startswith
startswith = (
tengri.list_filters()
.filter(survey__startswith="JWST")
.names()[:3]
)
print(f"Startswith (survey__startswith='JWST'): {startswith}\n")
# Example: in tuple (multiple values)
in_tuple = (
tengri.list_filters()
.filter(instrument__in=("NIRCam", "MIRI"))
.names()[:3]
)
print(f"In tuple (instrument__in=...): {in_tuple}\n")
Exact match (instrument='MIRI'): ['JWST_MIRI_F1000W', 'JWST_MIRI_F1065C', 'JWST_MIRI_F1130W']
Contains (band__contains='F150'): ['JWST_MIRI_F1500W', 'JWST_NIRCam2025_F150W', 'JWST_NIRCam2025_F150W2']
Startswith (survey__startswith='JWST'): ['JWST_MIRI_F1000W', 'JWST_MIRI_F1065C', 'JWST_MIRI_F1130W']
In tuple (instrument__in=...): ['JWST_MIRI_F1000W', 'JWST_MIRI_F1065C', 'JWST_MIRI_F1130W']
Single-entry lookup¶
Use ``describe()`` to get full metadata for any name — model, method, component, or filter.
[32]:
tengri.describe("calzetti")
[32]:
| name | calzetti |
|---|---|
| kind | dust_attenuation |
| status | production |
| citation | Calzetti et al. 2000 (ApJ 533, 682) |
| short_doc | Calzetti et al. starburst attenuation (R_V=4.05) |
| use | Parameters(..., dust_law="calzetti") |
Describe an AGN model.
[33]:
tengri.describe("skirtor")
[33]:
| name | skirtor |
|---|---|
| kind | agn_model |
| status | production |
| citation | Stalevski et al. 2012 (MNRAS 420, 2756); Stalevski et al. 2016 (MNRAS 458, 2288) |
| short_doc | Power-law disc + SKIRTOR clumpy torus |
| use | Parameters(..., agn_model="skirtor") |
| params | agn_log_lbol agn_frac agn_tau_skirtor agn_p_skirtor agn_q_skirtor agn_oa_skirtor agn_cos_inc agn_torus_frac agn_ebv_disc |
| param_details | [{'name': 'agn_log_lbol', 'default': 'Fixed(10.0)', 'description': 'AGN bolometric luminosity log10(L_bol / Lsun) — direct parametric mode'}, {'name': 'agn_frac', 'default': 'Fixed(0.0)', 'description': 'AGN luminosity fraction (L_AGN / L_stellar_bol)'}, {'name': 'agn_tau_skirtor', 'default': 'Fixed(7.0)', 'description': 'SKIRTOR 9.7 um optical depth (3-11)'}, {'name': 'agn_p_skirtor', 'default': 'Fixed(1.0)', 'description': 'SKIRTOR radial density power-law gradient (0-1.5)'}, {'name': 'agn_q_skirtor', 'default': 'Fixed(1.0)', 'description': 'SKIRTOR polar density power-law gradient (0-1.5)'}, {'name': 'agn_oa_skirtor', 'default': 'Fixed(40.0)', 'description': 'SKIRTOR torus half-opening angle [degrees] (20-60)'}, {'name': 'agn_cos_inc', 'default': 'Fixed(0.5)', 'description': 'Cosine of inclination (0=edge-on, 1=face-on)'}, {'name': 'agn_torus_frac', 'default': 'Fixed(0.5)', 'description': 'AGN torus covering factor (fraction of L_bol re-emitted by torus)'}] |
Describe an inference method.
[34]:
tengri.describe("mcmc_nuts")
[34]:
| name | mcmc_nuts |
|---|---|
| kind | inference_method |
| tier | primary |
| short_doc | No-U-Turn Sampler |
| requires | blackjax |
| use | fitter.run("mcmc_nuts") |
Describe a dust emission template.
[35]:
tengri.describe("dale2014")
[35]:
| name | dale2014 |
|---|---|
| status | production |
| citation | Dale et al. 2014 (ApJ 784, 83) |
| short_doc | SFR-driven empirical IR template family (alpha_sf) |
| use | Parameters(..., dust_emission="dale2014") |
| kind | dust_emission |
Environment health¶
``doctor()`` checks whether your install is healthy: Python version, JAX configuration, SSP data files, GPU availability.
[39]:
tengri.doctor()
████████
████████████████
██████ ██████
███████ ███████
██████ ██████
██████ ██████
██████ █████████████████ ██████
██████ ██████ ███████ ██████
█████ █████ █████ █████
████ ████ ██████████ ████ ████
████ ████ ████████ ████████ ████ ████
███ ███ ████ ████ █████ ████ ███
███ ███ ████ ██████████████ ████ ███ ███
███ ███ ███ █████ █████ ███ ███ ███
███ ███ ██ ████ ████████ ████ ███ ███ ███
███ ██ ██ ███ ██████ █████ ████ ███ ███ ███
███ ██ █ ███ ████ ██████ ███ ███ ███ ███ ███
███ ████ ███ ███ ███ ████ ███ ███ ███ ███
███ ███ ███ ███ ███ ███ ███ ███ ███ ███
███ ███ ███ ███ ███ ███ ███ ███ ███ ███
███ ███ ███ ███ ████ ███ ████ ███ █ ██ ███
███ ███ ███ ███ ████ ████ ████ ███ ██ ██ ███
███ ███ ███ ███ ███████████ ███ ██ ██ ███
███ ██ ███ ████ ████ █████ ██ ███ ███
███ ███ ███ ███████ ████████ ███ ███ ███
███ ███ ████ ██████████ ████ ███ ███
███ ████ ██████ █████ ███ ███
███ ████ ████████████████ ███ ███
█████ ████ ████ █████
█████ ██████ █████ █████
███████ █████████ █████████ ███████
██████ ████████████ ██████
██████ ██████
██████ ██████
███████ ███████
██████ ██████
██████████████
██████████
============================================================
tengri Environment Health Check
============================================================
Python: 3.12.2
Platform: Darwin 25.4.0
tengri: 0.1.0
JAX: 0.9.1
JAX backend: cpu
JAX x64 (float64): OK
XLA cache: /Users/suchethacooray/.cache/tengri_jax_cache (writable)
SSP Data:
WARNING: No SSP data found in common locations.
Check TENGRI_DATA env var or download SSP grids.
============================================================
For issues, see: https://github.com/suchethac/tengri
============================================================
[39]:
' ████████\n ████████████████\n ██████ ██████\n ███████ ███████\n ██████ ██████\n ██████ ██████\n ██████ █████████████████ ██████\n ██████ ██████ ███████ ██████\n █████ █████ █████ █████\n ████ ████ ██████████ ████ ████\n████ ████ ████████ ████████ ████ ████\n███ ███ ████ ████ █████ ████ ███\n███ ███ ████ ██████████████ ████ ███ ███\n███ ███ ███ █████ █████ ███ ███ ███\n███ ███ ██ ████ ████████ ████ ███ ███ ███\n███ ██ ██ ███ ██████ █████ ████ ███ ███ ███\n███ ██ █ ███ ████ ██████ ███ ███ ███ ███ ███\n███ ████ ███ ███ ███ ████ ███ ███ ███ ███\n███ ███ ███ ███ ███ ███ ███ ███ ███ ███\n███ ███ ███ ███ ███ ███ ███ ███ ███ ███\n███ ███ ███ ███ ████ ███ ████ ███ █ ██ ███\n███ ███ ███ ███ ████ ████ ████ ███ ██ ██ ███\n███ ███ ███ ███ ███████████ ███ ██ ██ ███\n███ ██ ███ ████ ████ █████ ██ ███ ███\n███ ███ ███ ███████ ████████ ███ ███ ███\n███ ███ ████ ██████████ ████ ███ ███\n███ ████ ██████ █████ ███ ███\n ███ ████ ████████████████ ███ ███\n █████ ████ ████ █████\n █████ ██████ █████ █████\n ███████ █████████ █████████ ███████\n ██████ ████████████ ██████\n ██████ ██████\n ██████ ██████\n ███████ ███████\n ██████ ██████\n ██████████████\n ██████████ \n\n============================================================\ntengri Environment Health Check\n============================================================\n\nPython: 3.12.2\nPlatform: Darwin 25.4.0\ntengri: 0.1.0\n\nJAX: 0.9.1\nJAX backend: cpu\nJAX x64 (float64): OK\nXLA cache: /Users/suchethacooray/.cache/tengri_jax_cache (writable)\n\nSSP Data:\n WARNING: No SSP data found in common locations.\n Check TENGRI_DATA env var or download SSP grids.\n\n============================================================\nFor issues, see: https://github.com/suchethac/tengri\n============================================================'
Photometric filter coverage¶
Build a multi-wavelength filter set and visualize their transmission curves. Color by effective wavelength to reveal the spectral coverage, and annotate the Balmer break at z=0.1.
[40]:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import Normalize
from matplotlib.cm import ScalarMappable
# Set publication-style defaults
tengri.plot.setup_style()
# 1. Discover filters via the chained API — use available registry names
# Build a representative set: SDSS optical + 2MASS near-IR
sdss_names = ["sdss_u", "sdss_g", "sdss_r", "sdss_i", "sdss_z"]
ir_names = ["2mass_j", "2mass_h", "2mass_ks"]
all_filter_names = sdss_names + ir_names
print(f"Loading filters: {all_filter_names}\n")
# 2. Load each filter and collect metadata
filters_data = []
for name in all_filter_names:
try:
fc = tengri.filters.load_filter(name)
wave_np, trans_np = np.asarray(fc.wave), np.asarray(fc.trans)
lam_eff = tengri.filters.compute_effective_wavelength(wave_np, trans_np)
filters_data.append({
'name': name,
'wave': wave_np,
'trans': trans_np,
'lam_eff': lam_eff
})
except KeyError as e:
print(f"warn: Skipping {name}: {e}")
print(f"Loaded {len(filters_data)} filters\n")
# 3. Create the figure with a shared wavelength axis
fig, ax = plt.subplots(figsize=(12, 6))
# Color map: effective wavelength → perceptual color
lam_effs = np.array([f['lam_eff'] for f in filters_data])
norm = Normalize(vmin=lam_effs.min(), vmax=lam_effs.max())
cmap = plt.get_cmap("viridis")
# Plot each filter's transmission curve
for fdata in filters_data:
color = cmap(norm(fdata['lam_eff']))
ax.plot(fdata['wave'] / 1e4, fdata['trans'], linewidth=2.0, color=color,
label=fdata['name'].upper())
# 4. Annotate the Balmer break for a nearby galaxy (z=0.1)
# Balmer edge: 3647 Å (rest) → 4012 Å (z=0.1)
z = 0.1
balmer_obs = 3647 * (1 + z) / 1e4
ax.axvline(balmer_obs, color="red", linestyle="--", alpha=0.5, linewidth=1.5)
ax.text(balmer_obs, 0.95, f"Balmer break (z={z})", rotation=90, va="top", ha="right",
fontsize=10, color="red", alpha=0.8, fontweight="bold")
# 5. Labels and formatting
ax.set_xlabel("Wavelength (μm)", fontsize=12)
ax.set_ylabel("Transmission (normalized)", fontsize=12)
ax.set_title("Multi-Wavelength Filter Coverage: SDSS + 2MASS", fontsize=13, fontweight="bold")
ax.set_xlim(0.3, 2.5)
ax.set_ylim(0, 1.05)
ax.grid(True, alpha=0.3, linestyle=":")
ax.legend(fontsize=10, frameon=False, loc="upper right", ncol=2)
# 6. Add colorbar for effective wavelength
sm = ScalarMappable(cmap=cmap, norm=norm)
sm.set_array([])
cbar = plt.colorbar(sm, ax=ax, label="λ_eff (Å)", pad=0.02)
cbar.ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f"{x/1e3:.1f}k"))
plt.tight_layout()
import os
os.makedirs("figures", exist_ok=True)
plt.savefig("figures/03_filter_coverage.png", dpi=200, bbox_inches="tight")
print("\nSaved hero figure to figures/03_filter_coverage.png")
plt.show()
Loading filters: ['sdss_u', 'sdss_g', 'sdss_r', 'sdss_i', 'sdss_z', '2mass_j', '2mass_h', '2mass_ks']
Loaded 8 filters
✓ Saved hero figure to figures/03_filter_coverage.png
What this figure shows. SDSS optical bands (3000–10000 Å) combined with 2MASS near-IR filters. The Balmer break near 4000 Å (rest-frame) is a strong stellar mass tracer. These eight filters give you good wavelength coverage for constraining age, dust, and metallicity in local galaxies.
From discovery API to Observation¶
Demonstrate the full workflow — from introspection to building an Observation ready for a model.
Note: list_filters().names() returns SVO-style long names (e.g. "SLOAN_SDSS_g"), but Photometry.from_names() also accepts shorthand aliases (e.g. "sdss_g"). Both work.
[41]:
# 1. Discover filters via the registry
sdss_filters = tengri.list_filters(survey="SDSS")
print(f"Found {len(sdss_filters)} SDSS filters\n")
print(sdss_filters)
Found 5 SDSS filters
name survey instrument band
──────────── ────── ────────── ────
SLOAN_SDSS_g SLOAN SDSS g
SLOAN_SDSS_i SLOAN SDSS i
SLOAN_SDSS_r SLOAN SDSS r
SLOAN_SDSS_u SLOAN SDSS u
SLOAN_SDSS_z SLOAN SDSS z
[5 results — filter]
Use: tengri.describe('SLOAN_SDSS_g') → Photometry.from_names(["SLOAN_SDSS_g"])
Manually build a working filter set using shorthand names (what
Photometry.from_names()expects).
[42]:
# Use shorthand names for photometry
filter_names = [
"sdss_u", "sdss_g", "sdss_r", "sdss_i", "sdss_z",
"2mass_j", "2mass_h", "2mass_ks",
]
print(f"Filter shorthand names:\n {filter_names}\n")
# 3. Create Photometry from discovered filters
from tengri import Observation, Photometry
photometry = Photometry.from_names(filter_names)
print(f"Loaded {photometry.n_filters} filters from shorthand names")
print(f" Filter names: {photometry.names}\n")
# 4. Bundle into an Observation (the object SEDModel expects)
obs = Observation(photometry=photometry)
print(f"Observation ready with {obs.photometry.n_filters} photometric bands")
Filter shorthand names:
['sdss_u', 'sdss_g', 'sdss_r', 'sdss_i', 'sdss_z', '2mass_j', '2mass_h', '2mass_ks']
Loaded 8 filters from shorthand names
Filter names: ('sdss_u', 'sdss_g', 'sdss_r', 'sdss_i', 'sdss_z', '2mass_j', '2mass_h', '2mass_ks')
✓ Observation ready with 8 photometric bands
That entire workflow — from list_filters() all the way to an Observation you can pass to SEDModel() — is three method calls. Discovery and model building are tightly coupled, not separate.
CLI mirror¶
The same introspection functions are available from the command line:
python -m tengri summary
python -m tengri doctor
python -m tengri search torus
python -m tengri describe skirtor
python -m tengri list agn
Run in a terminal when you want quick answers without opening a notebook.
Next steps¶
You now know how to discover what tengri offers. Next, build your first model:
Notebook 04: Building models — construct a
Parameters,SEDModel, andFitterfrom the components you just explored.Notebook 05: Joint photometry + spectroscopy — break the age–dust degeneracy with spectral data.
Notebook 14: Stochastic SFH — add bursty star formation via the GP.
Every name you discovered here becomes a kwarg to Parameters():
spec = tengri.Parameters(
mean_sfh_type="dpl", # from list_sfh_models()
dust_law_bc="calzetti", # from list_dust_laws()
dust_emission="dale2014", # from list_dust_emission_models()
agn_model="skirtor", # from list_agn_models()
nebular_backend="cue", # from list_nebular_backends()
)
Happy exploring!