Skip to content

Grids and Filters

Atmosphere grids

from sed_model import load_grid

grid = load_grid("/path/to/Kurucz2003all/")

load_grid() expects an SED_Tools-built directory containing flux_cube.bin. A co-located lookup_table.csv can be checked separately with sed_model.grid.validate_lookup_table(grid); it is not read at load time.

Binary format of flux_cube.bin

Section Contents
Header 4 × int32 → (n_teff, n_logg, n_meta, n_lambda)
Axes n_teff + n_logg + n_meta + n_lambda float64 values, written consecutively with no padding
Payload n_teff × n_logg × n_meta × n_lambda float64 values stored in (W, M, L, T) order on disk, loaded into (T, L, M, W) in memory

This matches the layout written by SED_Tools and read by the MESA colors module (colors_utils.f90 :: load_flux_cube). The loader validates the header dimensions and raises ValueError on truncated axis or payload data.

The AtmosphereGrid object

load_grid returns an immutable AtmosphereGrid exposing:

Attribute / method Description
teff_grid, logg_grid, meta_grid grid axes (K, dex, dex)
wavelengths wavelength grid in Å
flux surface flux cube, shape (n_T, n_L, n_M, n_W), erg/s/cm²/Å
teff_bounds, logg_bounds, meta_bounds (min, max) per axis
in_bounds(teff, logg, meta) True if the point lies within all three axes
clamp(teff, logg, meta) the point clipped to the grid boundary
nearest_grid_distance(teff, logg, meta) Euclidean distance in normalised parameter space from the nearest tabulated model (empty nodes excluded) — the Interp_rad diagnostic of the MESA colors module
cell_has_empty_nodes(teff, logg, meta, stencil=False) True if the cell containing the point touches a node with no model; stencil=True also checks the nodes the Hermite derivatives read (see Forward Model)

Filters

from sed_model import load_filters, load_filters_from_instrument_dir

filters = load_filters([
    "/path/to/filters/Generic/Johnson/B.dat",
    "/path/to/filters/Generic/Johnson/V.dat",
])

filters = load_filters_from_instrument_dir(
    "/path/to/filters/Generic/Johnson",
    vega_sed_path="/path/to/stellar_models/vega_flam.csv",  # optional
)

Filter files are two-column (wavelength Å, transmission 0–1); # comments are skipped, and both whitespace-separated and CSV files (with or without a header row) are handled. Wavelengths are sorted ascending if needed.

load_filters_from_instrument_dir looks for an index file whose name matches the directory's last component (e.g. Johnson/Johnson) listing one .dat filename per line — the structure the MESA colors module expects. If no index file exists, every .dat in the directory is loaded.

Zero-points

Each Filter carries precomputed zero-points using the same integrals as MESA colors/private/synthetic.f90 (photon counting, as MESA does; an energy-counting curve tagged DetectorType=energy on the column row is converted to T/λ first, see below). The photon-counting forms are:

System Definition
Vega \( F_{zp} = \int F_{\rm Vega}(\lambda)\, T(\lambda)\, \lambda\, d\lambda \;/\; \int T(\lambda)\, \lambda\, d\lambda \)
AB same integral with \( F_{\rm AB}(\lambda) = 3.631 \times 10^{-20} \, c / \lambda^2 \) erg/s/cm²/Å
ST \( F_{zp} = 3.63 \times 10^{-9} \) erg/s/cm²/Å (flat \( F_\lambda \); the constant cancels in the integral but it is computed explicitly for consistency with the Fortran implementation)

The Vega zero-point requires a Vega reference SED (CSV: wavelength Å, flux erg/s/cm²/Å) passed via vega_sed_path; without it, vega_zero_point is -1.0 and requesting the Vega system raises ValueError. Query a zero-point with filt.zero_point("Vega"), "AB", or "ST".

Trapezoid vs Simpson

The Python zero-point integrals use the trapezoid rule (valid for non-uniform wavelength grids); the Fortran runtime uses adaptive Simpson for the in-band flux. The difference is negligible for the dense wavelength grids produced by SED_Tools, and is folded into the tolerances of the forward test suite.

Detector type

SED_Tools tags every filter file with the response convention of its curve, as a ;-separated field after the second comma of the column-name row:

Wavelength,Transmission,FilterID=GAIA/GAIA3.G;DetectorType=photon;WavelengthUnit=Angstrom

load_filters reads DetectorType (photon or energy, case-insensitive). A photon-counting curve (CCD detectors, e.g. Gaia) is used as is. An energy-counting curve TE (e.g. the classical Bessell UBVRI curves) is converted to its photon-counting equivalent TE/λ (Bessell & Murphy 2012, eq. A9), rescaled to keep its peak, so that the λ-weighted integrals above reduce to ∫F TE / ∫TE. This matches the MESA colors module.

  • Filter.detector_type is the tag the file carried ('photon' or 'energy'). For 'energy' filters Filter.transmission holds the converted curve, not the file's values.
  • A missing tag means photon counting; an unrecognised value does too, with a warning.
  • Only the column-name row is read. Leading # DetectorType: comment lines, as written by SED_Tools 0.3.0, are ignored.
  • WavelengthUnit is the unit of the file's own wavelength column (SED_Tools writes Angstrom for its own products). Known units are converted to Angstrom; an unknown unit raises ValueError. Files without the tag are read as Angstrom.