Multi-gas absorption LUT — CH, CO, HO¶
This notebook exercises the multi-gas orchestration layer in plumax.hapi_lut.multi. Two patterns are covered:
Separate-per-gas LUTs — one NetCDF per species, each on its own natural spectral range. Used when downstream tools want the widest possible window for each gas individually.
Combined LUT — a single NetCDF with one cross-section variable per gas on the shared spectral range. Used when several gases are retrieved jointly within the same instrument band (e.g. CH + HO interference correction in a TROPOMI SWIR fit).
The math is identical to the single-gas case from CH4 absorption cross-section LUT; here we just loop over GasConfig entries.
import warnings
from pathlib import Path
warnings.filterwarnings("ignore")
import matplotlib.pyplot as plt
import numpy as np
import xarray as xr
from plumax.hapi_lut import (
ATMOSPHERIC_GASES,
GasConfig,
LUTGridConfig,
create_combined_lut,
create_multi_gas_luts,
)
# Generated data lives in a per-user cache, outside the repository.
DATA_ROOT = Path.home() / ".cache" / "plumax"
CACHE_DIR = DATA_ROOT / "hitran"
LUT_DIR = DATA_ROOT / "hapi_lut"1. Separate-per-gas LUTs on a common small window¶
We narrow the three gases to a shared 500-cm⁻¹ methane window (4000–4500 cm⁻¹) for runtime — the registry defaults would have HO fetch 21 000 cm⁻¹ of lines, which is overkill for a tutorial.
def narrow(gas: GasConfig, nu_min: float, nu_max: float) -> GasConfig:
"""Return a copy of ``gas`` with the spectral range restricted."""
return GasConfig(
name=gas.name,
molecule_id=gas.molecule_id,
isotopologue_id=gas.isotopologue_id,
nu_min=nu_min,
nu_max=nu_max,
description=gas.description,
)
NU_MIN, NU_MAX = 4000.0, 4500.0
gas_configs = {
name: narrow(ATMOSPHERIC_GASES[name], NU_MIN, NU_MAX)
for name in ["CH4", "CO2", "H2O"]
}
for g in gas_configs.values():
print(g)
grid = LUTGridConfig(
T_grid=np.array([220.0, 260.0, 300.0]),
P_grid=np.array([0.3, 0.6, 1.0]),
nu_step=0.05,
)GasConfig(CH4, M6, I1)
GasConfig(CO2, M2, I1)
GasConfig(H2O, M1, I1)
create_multi_gas_luts runs the fetch → compute → wrap → save pipeline from notebook 01 in a loop. Gases whose NetCDF already exists are skipped (pass force_recompute=True to override).
Note: we monkey-patch the registry with the narrowed configs below since create_multi_gas_luts looks up names in ATMOSPHERIC_GASES. In production code you’d subclass or rebuild the registry.
# Temporarily swap the registry entries — simpler than forking the whole orchestration for a demo.
_original = {k: ATMOSPHERIC_GASES[k] for k in gas_configs}
ATMOSPHERIC_GASES.update(gas_configs)
try:
lut_files = create_multi_gas_luts(
list(gas_configs),
grid_config=grid,
cache_dir=CACHE_DIR,
output_dir=LUT_DIR,
force_recompute=True,
)
finally:
ATMOSPHERIC_GASES.update(_original)
for name, path in lut_files.items():
size_mb = path.stat().st_size / 1e6
print(f" {name}: {path.name} ({size_mb:.2f} MB)")HAPI version: 1.3.0.0
To get the most up-to-date version please check http://hitran.org/hapi
ATTENTION: Python versions of partition sums from TIPS-2021 are now available in HAPI code
MIT license: Copyright 2021 HITRAN team, see more at http://hitran.org.
If you use HAPI in your research or software development,
please cite it using the following reference:
R.V. Kochanov, I.E. Gordon, L.S. Rothman, P. Wcislo, C. Hill, J.S. Wilzewski,
HITRAN Application Programming Interface (HAPI): A comprehensive approach
to working with spectroscopic data, J. Quant. Spectrosc. Radiat. Transfer 177, 15-30 (2016)
DOI: 10.1016/j.jqsrt.2016.03.005
ATTENTION: This is the core version of the HITRAN Application Programming Interface.
For more efficient implementation of the absorption coefficient routine,
as well as for new profiles, parameters and other functional,
please consider using HAPI2 extension library.
HAPI2 package is available at http://github.com/hitranonline/hapi2
Using /root/.cache/plumax/hitran
CH4
Lines parsed: 39817
Data is fetched from http://hitran.org
BEGIN DOWNLOAD: CH4
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
Header written to /root/.cache/plumax/hitran/CH4.header
END DOWNLOAD
Lines parsed: 39817
PROCESSED
Using /root/.cache/plumax/hitran
CH4
Lines parsed: 39817
{'air': 0.999998, 'self': 2e-06}
14.517897 seconds elapsed for abscoef; nlines = 39817
{'air': 0.999998, 'self': 2e-06}
14.354403 seconds elapsed for abscoef; nlines = 39817
{'air': 0.999998, 'self': 2e-06}
14.067736 seconds elapsed for abscoef; nlines = 39817
{'air': 0.999998, 'self': 2e-06}
13.839799 seconds elapsed for abscoef; nlines = 39817
{'air': 0.999998, 'self': 2e-06}
14.510198 seconds elapsed for abscoef; nlines = 39817
{'air': 0.999998, 'self': 2e-06}
14.240977 seconds elapsed for abscoef; nlines = 39817
{'air': 0.999998, 'self': 2e-06}
14.504378 seconds elapsed for abscoef; nlines = 39817
{'air': 0.999998, 'self': 2e-06}
14.498769 seconds elapsed for abscoef; nlines = 39817
{'air': 0.999998, 'self': 2e-06}
14.577606 seconds elapsed for abscoef; nlines = 39817
Using /root/.cache/plumax/hitran
CH4
Lines parsed: 39817
Data is fetched from http://hitran.org
BEGIN DOWNLOAD: CO2
65536 bytes written to /root/.cache/plumax/hitran/CO2.data
65536 bytes written to /root/.cache/plumax/hitran/CO2.data
65536 bytes written to /root/.cache/plumax/hitran/CO2.data
65536 bytes written to /root/.cache/plumax/hitran/CO2.data
65536 bytes written to /root/.cache/plumax/hitran/CO2.data
Header written to /root/.cache/plumax/hitran/CO2.header
END DOWNLOAD
Lines parsed: 1652
PROCESSED
Using /root/.cache/plumax/hitran
CH4
Lines parsed: 39817
CO2
Lines parsed: 1652
{'air': 0.9996, 'self': 0.0004}
0.696691 seconds elapsed for abscoef; nlines = 1652
{'air': 0.9996, 'self': 0.0004}
0.592834 seconds elapsed for abscoef; nlines = 1652
{'air': 0.9996, 'self': 0.0004}
0.471782 seconds elapsed for abscoef; nlines = 1652
{'air': 0.9996, 'self': 0.0004}
0.673076 seconds elapsed for abscoef; nlines = 1652
{'air': 0.9996, 'self': 0.0004}
0.647662 seconds elapsed for abscoef; nlines = 1652
{'air': 0.9996, 'self': 0.0004}
0.472540 seconds elapsed for abscoef; nlines = 1652
{'air': 0.9996, 'self': 0.0004}
0.650782 seconds elapsed for abscoef; nlines = 1652
{'air': 0.9996, 'self': 0.0004}
0.688041 seconds elapsed for abscoef; nlines = 1652
{'air': 0.9996, 'self': 0.0004}
0.499448 seconds elapsed for abscoef; nlines = 1652
Using /root/.cache/plumax/hitran
CH4
Lines parsed: 39817
CO2
Lines parsed: 1652
Data is fetched from http://hitran.org
BEGIN DOWNLOAD: H2O
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
Header written to /root/.cache/plumax/hitran/H2O.header
END DOWNLOAD
Lines parsed: 4100
PROCESSED
Using /root/.cache/plumax/hitran
CH4
Lines parsed: 39817
H2O
Lines parsed: 4100
CO2
Lines parsed: 1652
{'air': 0.99, 'self': 0.01}
1.780204 seconds elapsed for abscoef; nlines = 4100
{'air': 0.99, 'self': 0.01}
1.680048 seconds elapsed for abscoef; nlines = 4100
{'air': 0.99, 'self': 0.01}
1.486082 seconds elapsed for abscoef; nlines = 4100
{'air': 0.99, 'self': 0.01}
1.711456 seconds elapsed for abscoef; nlines = 4100
{'air': 0.99, 'self': 0.01}
1.660397 seconds elapsed for abscoef; nlines = 4100
{'air': 0.99, 'self': 0.01}
1.631283 seconds elapsed for abscoef; nlines = 4100
{'air': 0.99, 'self': 0.01}
1.636269 seconds elapsed for abscoef; nlines = 4100
{'air': 0.99, 'self': 0.01}
1.693258 seconds elapsed for abscoef; nlines = 4100
{'air': 0.99, 'self': 0.01}
1.719812 seconds elapsed for abscoef; nlines = 4100
CH4: ch4_absorption_lut.nc (0.47 MB)
CO2: co2_absorption_lut.nc (0.44 MB)
H2O: h2o_absorption_lut.nc (0.48 MB)
1a. Overlay the three gases on the same axis¶
At K, atm, the three cross-sections have dramatically different magnitudes and structures. Water vapour dominates between the CH and CO band heads — this is exactly why operational SWIR retrievals co-retrieve HO as a nuisance parameter.
fig, ax = plt.subplots(1, 1, figsize=(11, 4))
colors = {"CH4": "C0", "CO2": "C3", "H2O": "C2"}
for name, path in lut_files.items():
with xr.open_dataset(path) as ds:
sigma = ds["absorption_cross_section"].sel(temperature=260.0, pressure=0.6)
ax.plot(
ds["wavenumber"], sigma, lw=0.5, color=colors[name], label=name, alpha=0.8
)
ax.set_yscale("log")
ax.set_ylim(1e-30, 1e-18)
ax.set_xlabel(r"Wavenumber $\nu$ [cm$^{-1}$]")
ax.set_ylabel(r"$\sigma$ [cm$^2$/molecule]")
ax.set_title(
r"Three-gas cross-sections at $T=260$ K, $p=0.6$ atm (4000–4500 cm$^{-1}$)"
)
ax.legend()
ax.grid(alpha=0.3)
plt.tight_layout()
plt.show()
2. Combined LUT — single file, one variable per gas¶
create_combined_lut collapses the above into one NetCDF with variables CH4_cross_section, CO2_cross_section, H2O_cross_section on a shared (wavenumber, temperature, pressure) grid. The shared wavenumber axis is the intersection of the per-gas ranges — in our case the full 4000–4500 cm⁻¹ window since we narrowed all three gases to it.
ATMOSPHERIC_GASES.update(gas_configs)
try:
combined_path = create_combined_lut(
list(gas_configs),
grid_config=grid,
cache_dir=CACHE_DIR,
output_dir=LUT_DIR,
filename="swir_combined_lut.nc",
)
finally:
ATMOSPHERIC_GASES.update(_original)
with xr.open_dataset(combined_path) as combined:
print(combined)Using /root/.cache/plumax/hitran
CH4
Lines parsed: 39817
H2O
Lines parsed: 4100
CO2
Lines parsed: 1652
Data is fetched from http://hitran.org
BEGIN DOWNLOAD: CH4
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
65536 bytes written to /root/.cache/plumax/hitran/CH4.data
Header written to /root/.cache/plumax/hitran/CH4.header
END DOWNLOAD
Lines parsed: 39817
PROCESSED
Using /root/.cache/plumax/hitran
CH4
Lines parsed: 39817
H2O
Lines parsed: 4100
CO2
Lines parsed: 1652
{'air': 0.999998, 'self': 2e-06}
14.614377 seconds elapsed for abscoef; nlines = 39817
{'air': 0.999998, 'self': 2e-06}
14.561487 seconds elapsed for abscoef; nlines = 39817
{'air': 0.999998, 'self': 2e-06}
14.552822 seconds elapsed for abscoef; nlines = 39817
{'air': 0.999998, 'self': 2e-06}
14.875161 seconds elapsed for abscoef; nlines = 39817
{'air': 0.999998, 'self': 2e-06}
14.197351 seconds elapsed for abscoef; nlines = 39817
{'air': 0.999998, 'self': 2e-06}
14.752668 seconds elapsed for abscoef; nlines = 39817
{'air': 0.999998, 'self': 2e-06}
14.621797 seconds elapsed for abscoef; nlines = 39817
{'air': 0.999998, 'self': 2e-06}
14.417776 seconds elapsed for abscoef; nlines = 39817
{'air': 0.999998, 'self': 2e-06}
14.496371 seconds elapsed for abscoef; nlines = 39817
Using /root/.cache/plumax/hitran
CH4
Lines parsed: 39817
H2O
Lines parsed: 4100
CO2
Lines parsed: 1652
Data is fetched from http://hitran.org
BEGIN DOWNLOAD: CO2
65536 bytes written to /root/.cache/plumax/hitran/CO2.data
65536 bytes written to /root/.cache/plumax/hitran/CO2.data
65536 bytes written to /root/.cache/plumax/hitran/CO2.data
65536 bytes written to /root/.cache/plumax/hitran/CO2.data
65536 bytes written to /root/.cache/plumax/hitran/CO2.data
Header written to /root/.cache/plumax/hitran/CO2.header
END DOWNLOAD
Lines parsed: 1652
PROCESSED
Using /root/.cache/plumax/hitran
CH4
Lines parsed: 39817
H2O
Lines parsed: 4100
CO2
Lines parsed: 1652
{'air': 0.9996, 'self': 0.0004}
0.729973 seconds elapsed for abscoef; nlines = 1652
{'air': 0.9996, 'self': 0.0004}
0.593299 seconds elapsed for abscoef; nlines = 1652
{'air': 0.9996, 'self': 0.0004}
0.494853 seconds elapsed for abscoef; nlines = 1652
{'air': 0.9996, 'self': 0.0004}
0.683780 seconds elapsed for abscoef; nlines = 1652
{'air': 0.9996, 'self': 0.0004}
0.680737 seconds elapsed for abscoef; nlines = 1652
{'air': 0.9996, 'self': 0.0004}
0.495262 seconds elapsed for abscoef; nlines = 1652
{'air': 0.9996, 'self': 0.0004}
0.747975 seconds elapsed for abscoef; nlines = 1652
{'air': 0.9996, 'self': 0.0004}
0.768098 seconds elapsed for abscoef; nlines = 1652
{'air': 0.9996, 'self': 0.0004}
0.531820 seconds elapsed for abscoef; nlines = 1652
Using /root/.cache/plumax/hitran
CH4
Lines parsed: 39817
H2O
Lines parsed: 4100
CO2
Lines parsed: 1652
Data is fetched from http://hitran.org
BEGIN DOWNLOAD: H2O
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
65536 bytes written to /root/.cache/plumax/hitran/H2O.data
Header written to /root/.cache/plumax/hitran/H2O.header
END DOWNLOAD
Lines parsed: 4100
PROCESSED
Using /root/.cache/plumax/hitran
CH4
Lines parsed: 39817
H2O
Lines parsed: 4100
CO2
Lines parsed: 1652
{'air': 0.99, 'self': 0.01}
1.728799 seconds elapsed for abscoef; nlines = 4100
{'air': 0.99, 'self': 0.01}
1.765727 seconds elapsed for abscoef; nlines = 4100
{'air': 0.99, 'self': 0.01}
1.626431 seconds elapsed for abscoef; nlines = 4100
{'air': 0.99, 'self': 0.01}
1.859660 seconds elapsed for abscoef; nlines = 4100
{'air': 0.99, 'self': 0.01}
1.752733 seconds elapsed for abscoef; nlines = 4100
{'air': 0.99, 'self': 0.01}
1.829859 seconds elapsed for abscoef; nlines = 4100
{'air': 0.99, 'self': 0.01}
1.862430 seconds elapsed for abscoef; nlines = 4100
{'air': 0.99, 'self': 0.01}
1.700506 seconds elapsed for abscoef; nlines = 4100
{'air': 0.99, 'self': 0.01}
1.746088 seconds elapsed for abscoef; nlines = 4100
<xarray.Dataset> Size: 1MB
Dimensions: (wavenumber: 10000, temperature: 3, pressure: 3)
Coordinates:
* wavenumber (wavenumber) float64 80kB 4e+03 4e+03 ... 4.5e+03 4.5e+03
wavelength (wavenumber) float64 80kB ...
* temperature (temperature) float64 24B 220.0 260.0 300.0
* pressure (pressure) float64 24B 0.3 0.6 1.0
Data variables:
CH4_cross_section (wavenumber, temperature, pressure) float32 360kB ...
CO2_cross_section (wavenumber, temperature, pressure) float32 360kB ...
H2O_cross_section (wavenumber, temperature, pressure) float32 360kB ...
Attributes:
title: Combined Atmospheric Absorption LUT
gases: CH4, CO2, H2O
line_shape: Voigt profile
conventions: CF-1.8
2a. Effective opacity by gas¶
A useful diagnostic: weight each cross-section by a typical column density of the gas () to see which gas actually dominates the optical depth at a representative atmospheric state.
We use Loschmidt’s number at the surface ( molecules/cm³) scaled to K, atm, and the dry-air VMRs from our config.
from plumax.hapi_lut.beers import number_density
N_total = number_density(p_atm=0.6, T_K=260.0)
vmrs = {"CH4": 2e-6, "CO2": 400e-6, "H2O": 1e-2}
fig, ax = plt.subplots(1, 1, figsize=(11, 4))
with xr.open_dataset(combined_path) as combined:
for name, vmr in vmrs.items():
sigma = combined[f"{name}_cross_section"].sel(temperature=260.0, pressure=0.6)
alpha = sigma * (N_total * vmr) # [1/cm]
ax.plot(
combined["wavenumber"],
alpha,
lw=0.5,
color=colors[name],
label=f"{name} (VMR = {vmr:.0e})",
alpha=0.85,
)
ax.set_yscale("log")
ax.set_ylim(1e-12, 1e-3)
ax.set_xlabel(r"Wavenumber $\nu$ [cm$^{-1}$]")
ax.set_ylabel(r"$\alpha = \sigma \cdot N_{\mathrm{gas}}$ [1/cm]")
ax.set_title(r"Column-weighted absorption coefficient (T = 260 K, p = 0.6 atm)")
ax.legend()
ax.grid(alpha=0.3)
plt.tight_layout()
plt.show()
Reading the plot. Even though CH has 200× larger than CO at its peaks, CO’s 200× higher VMR closes most of the gap. HO’s ~10% VMR swamps both at many wavenumbers — any methane retrieval in this window has to simultaneously fit a water-vapour column to avoid biased .
This is the interference-corrected retrieval picture: the matched filter in Differential Beer-Lambert plume retrieval from the LUT deals only with CH for clarity, but the LUT infrastructure is already set up to handle the joint fit.
3. Summary¶
create_multi_gas_luts= one NetCDF per species, useful for independently-retrieved gases.create_combined_lut= one NetCDF, one variable per species, useful for joint fits in a shared band.Column-weighted shows which gas actually drives optical depth at representative VMRs — the right diagnostic for planning which species to include in a joint retrieval.