# ExoJAX Utility Functions for Spectral Modeling: A Complete Guide

> Explore ExoJAX utility functions for spectral modeling. Discover helpers for grids, photometry, opacity, and data validation in radiative transfer.

- Repository: [Hajime Kawahara/exojax](https://github.com/hajimekawahara/exojax)
- Tags: how-to-guide
- Published: 2026-03-03

---

**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`](https://github.com/hajimekawahara/exojax/blob/main/src/exojax/utils/grids.py) and [`src/exojax/utils/spectral_bands.py`](https://github.com/hajimekawahara/exojax/blob/main/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

```python
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`](https://github.com/hajimekawahara/exojax/blob/main/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

```python
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`](https://github.com/hajimekawahara/exojax/blob/main/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.

```python
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`](https://github.com/hajimekawahara/exojax/blob/main/src/exojax/utils/interp.py)) – Performs bilinear interpolation on arbitrary 2-D grids using JAX-compatible operations
- **`is_sorted`** ([`src/exojax/utils/checkarray.py`](https://github.com/hajimekawahara/exojax/blob/main/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**:

- **`progbar`** ([`src/exojax/utils/progbar.py`](https://github.com/hajimekawahara/exojax/blob/main/src/exojax/utils/progbar.py)) – Lightweight text-based progress indicator for long-running loops
- **URL constants** ([`src/exojax/utils/url.py`](https://github.com/hajimekawahara/exojax/blob/main/src/exojax/utils/url.py)) – Centralized endpoints for external databases including `url_svo_filter`, `url_ExoMol`, `url_HITEMP`, and `url_HITRAN`
- **Physical constants** ([`src/exojax/utils/constants.py`](https://github.com/hajimekawahara/exojax/blob/main/src/exojax/utils/constants.py)) – Atomic masses, planetary radii, and unit conversion factors
- **`jaxstatus`** ([`src/exojax/utils/jaxstatus.py`](https://github.com/hajimekawahara/exojax/blob/main/src/exojax/utils/jaxstatus.py)) – Exposes JAX configuration flags (x64 mode, platform detection) for debugging

## Summary

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

- **Grid construction** via `wavenumber_grid` and conversion utilities in [`grids.py`](https://github.com/hajimekawahara/exojax/blob/main/grids.py)
- **Photometric calibration** with SVO filter downloads and magnitude calculations in [`photometry.py`](https://github.com/hajimekawahara/exojax/blob/main/photometry.py)
- **Opacity analysis** through `pressure_at_given_opacity` in [`opautils.py`](https://github.com/hajimekawahara/exojax/blob/main/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`](https://github.com/hajimekawahara/exojax/blob/main/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`](https://github.com/hajimekawahara/exojax/blob/main/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`](https://github.com/hajimekawahara/exojax/blob/main/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.