# How to Select and Use Molecular and Atomic Databases (ExoMol, HITRAN, VALD) in ExoJAX

> Learn how to select and use molecular and atomic databases like ExoMol HITRAN and VALD in ExoJAX. Efficiently integrate spectroscopic line lists for advanced radiative transfer calculations.

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

---

**ExoJAX provides specialized database classes—`MdbExomol`, `MdbHitran`, `MdbHitemp`, `AdbVald`, and `AdbSepVald`—that download, filter, and convert spectroscopic line lists into JAX-compatible arrays for radiative transfer calculations.**

ExoJAX stores spectroscopic line-list data in database (MDB) objects that handle everything from file parsing to GPU memory management. Whether you are modeling high-temperature exoplanet atmospheres with ExoMol, Earth-like conditions with HITRAN, or stellar abundances with VALD atomic data, the library provides a unified interface to select and use molecular and atomic databases in ExoJAX.

## Database Class Overview

ExoJAX organizes spectroscopic data into three families of database classes, each located in specific submodules under `src/exojax/database/`.

### Molecular Databases

- **ExoMol**: Use `MdbExomol` from [`src/exojax/database/exomol/api.py`](https://github.com/hajimekawahara/exojax/blob/main/src/exojax/database/exomol/api.py) for high-temperature line lists optimized for exoplanets, brown dwarfs, and M-dwarfs.
- **HITRAN**: Use `MdbHitran` from [`src/exojax/database/hitran/api.py`](https://github.com/hajimekawahara/exojax/blob/main/src/exojax/database/hitran/api.py) for Earth-atmosphere and standard planetary spectra following the HITRAN schema.
- **HITEMP**: Use `MdbHitemp` from [`src/exojax/database/hitemp/api.py`](https://github.com/hajimekawahara/exojax/blob/main/src/exojax/database/hitemp/api.py) for hot-planet line lists; this class inherits from the common HITRAN base `MdbCommonHitempHitran` defined in [`src/exojax/database/_common/commonapi.py`](https://github.com/hajimekawahara/exojax/blob/main/src/exojax/database/_common/commonapi.py).

### Atomic Databases

- **VALD**: Use `AdbVald` from [`src/exojax/database/vald/api.py`](https://github.com/hajimekawahara/exojax/blob/main/src/exojax/database/vald/api.py) for combined atomic line lists (e.g., Fe I, Fe II). For species-separated views, use `AdbSepVald`, which reshapes the combined object into separate axes per atomic/ionic species.

All classes share a common constructor signature that controls data location, spectral range, line filtering, and memory layout.

## Instantiating Molecular Databases

Each molecular database class accepts parameters to define the **local data directory** (`path` or `molecule_path`), select a **wavenumber region** with `nurange=[νmin, νmax]` (in cm⁻¹), and apply a **line-strength cut** (`crit`) based on a typical temperature (`Ttyp`). You can also control **memory layout** with `gpu_transfer=True/False`, select the I/O **engine** (`"vaex"` or `"pytables"`), and choose whether to **automatically activate** the database (`activation=True`).

Under the hood, these classes inherit from a thin Radis wrapper (`*_DatabaseManager`) and the ExoJAX base `MdbCommonHitempHitran`. The base handles downloading missing files via `download_and_parse`, loading data into lazy-IO dataframes (Vaex or Pandas), and applying a *load mask* that enforces the wavenumber range, line-strength cut, and optional `elower_max`.

### ExoMol Example

```python
from exojax.database.exomol.api import MdbExomol

mdb_co = MdbExomol(
    path=".database/CO/12C-16O/Li2015",  # Unpacked ExoMol folder structure

    nurange=[2000.0, 2500.0],            # Wavenumber range in cm⁻¹

    crit=1e-30,                          # Keep only lines stronger than this

    Ttyp=1500.0,                         # Temperature for crit evaluation

    gpu_transfer=True,                   # Store arrays on GPU if available

)

print(mdb_co.dev_nu_lines.shape)   # JAX DeviceArray shape, e.g., (123456,)

print(mdb_co.logsij0[:5])           # First five log line strengths

```

### HITRAN Example

```python
from exojax.database.hitran.api import MdbHitran

mdb_co2 = MdbHitran(
    molecule_path=".database/CO2/CO2_2020",  # HITRAN-2020 folder

    nurange=[2200, 2400],
    crit=1e-28,
    Ttyp=296.0,          # Room temperature for line-strength cut

    gpu_transfer=False,  # Keep on host memory for small selections

)

# Activate later if you instantiated with activation=False

mdb_co2.activate(mdb_co2.df)

```

### HITEMP Example

```python
from exojax.database.hitemp.api import MdbHitemp

mdb_h2o = MdbHitemp(
    molecule_path=".database/H2O/1H2-16O/POKAZATEL",
    nurange=[1500, 2000],
    crit=1e-27,
    Ttyp=2000.0,
    gpu_transfer=True,
    engine="vaex",      # Faster lazy-IO for large files

)

# Create a snapshot for opacity calculators

h2o_snapshot = mdb_h2o.to_snapshot()

```

## Working with Atomic Line Lists (VALD)

The VALD workflow differs slightly because raw VALD "Long format" files are converted to HDF5 on first read via `read_ExAll`. After conversion, the same masking and JAX-array generation steps apply. The `AdbVald` class creates a combined view, while `AdbSepVald` provides a species-separated view exposing a separate axis for each atomic/ionic species—useful for line-by-line opacity calculations.

```python
from exojax.database.vald.api import AdbVald, AdbSepVald

# VALD "Extract All" output file

vald_path = "./vald/Fe_extracted_All.txt"

adb = AdbVald(
    path=vald_path,
    nurange=[5000.0, 6000.0],
    crit=1e-30,
    Irwin=False,        # Use Barklem & Collet (2016) partition functions

    gpu_transfer=True,
)

# Species-separated view (e.g., Fe I vs Fe II)

adb_sep = AdbSepVald(adb)
print("Number of species:", adb_sep.N_usp)
print("Shape (species, lines):", adb_sep.nu_lines.shape)

```

## Database Activation and Memory Management

**Activation** builds the JAX-compatible arrays and computes pressure-broadening coefficients. By default, `activation=True` converts NumPy arrays to JAX `jnp.array`s, computes natural and collisional broadening coefficients (`gamma_natural`, `gamma_air`, `gamma_self`), and stores them on the selected device according to `gpu_transfer`. If you instantiate with `activation=False`, call `activate()` manually and pass the dataframe:

```python
mdb.activate(mdb.df)

```

All database objects expose a minimal, JAX-friendly public API:

- `nu_lines` – line centre wavenumbers (NumPy)
- `dev_nu_lines` – same data as JAX `DeviceArray` (used by opacity modules)
- `logsij0` – log of the reference line strength (`Sij0`)
- `A`, `elower`, `jlower`, `jupper`, `gpp` – standard spectroscopic parameters
- `gamma_natural`, `gamma_air`, `gamma_self` – pressure-broadening coefficients

Because the classes implement `__eq__`, they can be safely compared in tests or cached. The `to_snapshot()` method returns a *data-only* DTO (`MDBSnapshot`) consisting solely of NumPy arrays—this is what opacity calculators like `OpaPremodit` expect, keeping the heavy database implementation decoupled from the radiative-transfer pipeline.

## Integrating with Opacity Calculators

Pass the database object (or its snapshot) directly to opacity calculators in `exojax.opacity`:

```python
from exojax.opacity.premodit.api import OpaPremodit
from exojax.rt.atmrt import ArtEmisPure

# Compute emission spectrum for CO using Premodit opacity

opa = OpaPremodit(mdb_co, nu_grid=mdb_co.nu_lines, gpu_transfer=True)
rt = ArtEmisPure(opa, T=[1500.0], P=[1e5])   # Simple isothermal atmosphere

flux = rt.calc_spectrum()

```

## Summary

- **Select the appropriate class** for your data source: `MdbExomol` for high-temperature molecular lines, `MdbHitran`/`MdbHitemp` for HITRAN-schema data, or `AdbVald`/`AdbSepVald` for atomic lines.
- **Filter at load time** using `nurange` for wavenumber limits and `crit`/`Ttyp` for line-strength cuts to minimize memory usage.
- **Control hardware placement** with `gpu_transfer` and I/O performance with `engine` (`"vaex"` recommended for large files).
- **Activate** the database to generate JAX arrays and broadening coefficients, or use `to_snapshot()` to create a lightweight DTO for opacity modules.
- **Import directly** from the specific submodule (e.g., `exojax.database.exomol.api`) rather than the deprecated shim in `exojax.database.api`.

## Frequently Asked Questions

### What is the difference between `MdbHitran` and `MdbHitemp`?

**`MdbHitran`** targets standard HITRAN line lists optimized for Earth atmospheric temperatures, while **`MdbHitemp`** handles high-temperature extensions (like HITEMP water) required for hot exoplanets. `MdbHitemp` inherits from `MdbCommonHitempHitran` and can use the `"vaex"` engine for efficient lazy loading of large files.

### How do I convert a VALD "Long format" file for use in ExoJAX?

ExoJAX automatically converts VALD "Extract All" text files to HDF5 format on first read via the internal `read_ExAll` method in [`src/exojax/database/vald/api.py`](https://github.com/hajimekawahara/exojax/blob/main/src/exojax/database/vald/api.py). Simply point `AdbVald` to the `.txt` file; the HDF5 cache will be created in the same directory for subsequent loads.

### Should I use `gpu_transfer=True` for small line selections?

For small spectral ranges or limited line counts, set **`gpu_transfer=False`** to keep arrays in host memory and avoid GPU allocation overhead. Enable `gpu_transfer=True` only when you need maximum performance for large opacity calculations or when integrating with GPU-bound radiative transfer solvers.

### What does the `crit` parameter actually filter?

The **`crit`** parameter defines a threshold for the line strength `Sij` evaluated at temperature **`Ttyp`**. Lines weaker than `crit` are excluded by the *load mask* during dataframe initialization, reducing memory footprint and computation time. This is applied alongside the `nurange` wavenumber window and optional `elower_max` energy limits.