ExoJAX Utility Functions for Spectral Modeling: A Complete Guide

ExoJAX ships a lightweight exojax.utils package that provides essential helper functions for constructing spectral grids, converting photometric magnitudes, analyzing opacity profiles, and validating array data in radiative transfer workflows.

The exojax.utils module in the hajimekawahara/exojax repository consolidates pure NumPy/JAX tools needed throughout the opacity and radiative-transfer pipelines. These utilities handle the "bookkeeping" of spectral modeling—from wavenumber grid generation to filter curve downloads—without pulling in heavy computational solvers, making them ideal for forward modeling, retrieval algorithms, and post-processing scripts.

Spectral Grid and Wavelength Handling

The grid utilities form the foundation of most ExoJAX workflows. Located in src/exojax/utils/grids.py and src/exojax/utils/spectral_bands.py, these functions generate evenly spaced wavenumber arrays, handle unit conversions, and validate grid properties.

Key functions include:

  • wavenumber_grid – Constructs log-spaced (ESLOG) or linear wavenumber grids with automatic resolution calculation
  • extended_wavenumber_grid – Generates extended grids for convolution padding
  • nu2wav and wav2nu – Convert between wavenumber (cm⁻¹) and wavelength (µm)
  • velocity_grid and delta_velocity_from_resolution – Build velocity grids for rigid-rotation convolution
  • grid_resolution – Estimates the spectral resolving power $R$
  • check_eslog_wavenumber_grid – Validates that a grid follows the expected evenly-spaced-log pattern
  • spectral_band_edges and spectral_bands – Generate band centers and edges for correlated-k distribution calculations
from exojax.utils.grids import wavenumber_grid

# Build a high-resolution grid from 1.0–2.5 µm (converted to cm⁻¹)

x0_cm = 1.0e4 / 2.5   # ν_max (cm⁻¹)

x1_cm = 1.0e4 / 1.0   # ν_min (cm⁻¹)

nu_grid, wav_grid, R = wavenumber_grid(
    x0_cm, x1_cm, N=4000,
    xsmode='premodit',
    wavelength_order='descending',
    unit='cm-1'
)
print(f"Resolution ≈ {R:.0f}, ν‑grid shape: {nu_grid.shape}")

Photometry and Filter Utilities

For comparing synthetic spectra against observed photometry, src/exojax/utils/photometry.py provides SVO filter service integration and magnitude calculations.

Core capabilities include:

  • download_filter_from_svo – Downloads filter transmission curves from the Spanish Virtual Observatory
  • download_zero_magnitude_flux_from_svo – Retrieves zero-point fluxes for magnitude calibration
  • apparent_magnitude – Converts a model spectrum to apparent magnitude through a given filter
  • apparent_magnitude_isothermal_sphere – Specialized version for isothermal sphere geometry
  • average_resolution – Computes the filter-averaged spectral resolution
import jax.numpy as jnp
from exojax.utils.photometry import (
    download_filter_from_svo,
    download_zero_magnitude_flux_from_svo,
    apparent_magnitude,
)

# Load 2MASS Ks filter from SVO

flt_id = "2MASS/2MASS.Ks"
nu_filt, tr_filt = download_filter_from_svo(flt_id)

# Get zero-point flux in consistent units

nu0, f0_nu = download_zero_magnitude_flux_from_svo(flt_id, unit="cm-1")

# Convert model flux (erg s⁻¹ cm⁻² (cm⁻¹)⁻¹) to magnitude

mag = apparent_magnitude(model_flux, nu_filt, tr_filt, f0_nu)
print(f"{flt_id} apparent magnitude = {mag:.3f}")

Opacity Diagnostics and Pressure Extraction

The src/exojax/utils/opautils.py module contains specialized tools for optical depth analysis. The primary function, pressure_at_given_opacity, extracts the pressure level where a specific optical depth (e.g., $\tau = 1$) is reached for each wavelength—critical for identifying photosphere depths.

import numpy as np
from exojax.utils.opautils import pressure_at_given_opacity

# dtau: differential optical depth per layer (N_layer × N_λ)

# Parr: pressure array in bar (ascending order)

Parr = np.logspace(-6, 2, dtau.shape[0])

# Find τ=1 pressure for each wavelength

p_tau1 = pressure_at_given_opacity(dtau, Parr, tauextracted=1.0)

# Locate photosphere at specific wavenumber

idx = np.argmin(np.abs(nu_grid - 1500.0))
print(f"τ=1 pressure at 1500 cm⁻¹ ≈ {p_tau1[idx]:.2e} bar")

Interpolation and Array Validation

For data preprocessing and safety checks, ExoJAX provides robust interpolation and validation helpers:

  • interp2d_bilinear (src/exojax/utils/interp.py) – Performs bilinear interpolation on arbitrary 2-D grids using JAX-compatible operations
  • is_sorted (src/exojax/utils/checkarray.py) – Detects whether an array is in ascending or descending order
  • is_outside_range – Tests if values lie outside specified bounds, useful for input validation

These functions include safeguards against common array handling errors that could propagate through radiative transfer calculations.

Supporting Utilities and Constants

Several additional modules provide infrastructure and reference data:

Summary

The exojax.utils package provides a comprehensive toolkit for spectral modeling workflows:

  • Grid construction via wavenumber_grid and conversion utilities in grids.py
  • Photometric calibration with SVO filter downloads and magnitude calculations in photometry.py
  • Opacity analysis through pressure_at_given_opacity in opautils.py
  • Data validation using is_sorted and interpolation helpers
  • Infrastructure support including progress bars, URL constants, and JAX status checks

These functions are deliberately lightweight, well-tested (see tests/unittests/utils), and JAX-compatible, ensuring they integrate seamlessly into both research scripts and production retrieval pipelines.

Frequently Asked Questions

How do I create a wavenumber grid compatible with ExoJAX's opacity calculators?

Use wavenumber_grid from src/exojax/utils/grids.py. Specify the spectral range in cm⁻¹, the number of points, and the cross-section mode (e.g., xsmode='premodit'). The function returns the wavenumber grid, wavelength grid, and estimated resolving power $R$, automatically handling the log-spacing required for high-resolution spectroscopy.

Can ExoJAX convert synthetic spectra to photometric magnitudes for comparison with observations?

Yes. The src/exojax/utils/photometry.py module provides download_filter_from_svo to retrieve transmission curves from the SVO Filter Profile Service, download_zero_magnitude_flux_from_svo for calibration, and apparent_magnitude to integrate your model spectrum through the filter. These handle the proper normalization and unit conversions required for accurate magnitude calculations.

How do I determine the atmospheric pressure level corresponding to the observed photosphere?

Use pressure_at_given_opacity in src/exojax/utils/opautils.py. Pass the differential optical depth array (dtau) and pressure array (Parr), specifying the target optical depth (default $\tau = 1$). The function returns an array of pressure values representing the $\tau = 1$ surface for each wavelength, which defines the photosphere depth in transmission or emission spectra.

Are these utility functions dependent on JAX, or can they be used with standard NumPy?

Most utilities are JAX-agnostic and work with standard NumPy arrays, though they return JAX-compatible arrays when JAX is available. Functions like wavenumber_grid and pressure_at_given_opacity use pure NumPy operations by default, while interp2d_bilinear is specifically designed for JAX's functional programming patterns. The jaxstatus utility helps verify your JAX configuration when needed.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →