Spectroscopic line data

ArchNEMESIS includes a reference class to operate with spectroscopic line data from databases such as HITRAN. Specifically, the attributes of the LineData class include the information required to calculate the line-by-line cross sections at arbitrary pressures and temperatures (e.g., line strengths, broadening coefficiencts, partition functions, etc).

In this notebook, we provide some examples showing how archNEMESIS can be used to process the spectroscopic line data.

[1]:
import archnemesis as ans
import matplotlib.pyplot as plt
import numpy as np

1. Initialising the LineData class

In archNEMESIS, the functionality to process the spectroscopic line data is included in the LineData_0() class. This class has four main attributes that must be indicated when initialising the class:

  • ID: Radtran ID of the gas we want to process.

  • ISO: Radtran ID of the isotope we want to process.

  • LINE_DATABASE : String containing the path to the HDF5 file where the line data is stored.

  • PARTITION_FUNCTION_DATABASE : String containing the path to the HDF5 file where the partition function data is stored.

To perform calculations, archNEMESIS reads the line and partition function data from a HDF5 written with a custom format specific to this code. Generally, we aim to provide these files for standard databases such as HITRAN and store them in a public repository. For other line data sources, please contact the developers to help you create your own line data file readable by archNEMESIS.

The data files used in this notebook, corresponding to HITRAN24, can be downloaded following this link.

[2]:
# Inputs are RADTRAN ID numbers
gas_id = ans.enums.Gas.CO
iso_id = 0

# Create LineData_0 instance
LineData = ans.LineData_0(
    gas_id, iso_id,
    LINE_DATABASE="/home/alday/Documents/Projects/archnemesis-dist/archnemesis/database/offline/hitran24.h5",
    PARTITION_FUNCTION_DATABASE="/home/alday/Documents/Projects/archnemesis-dist/archnemesis/database/offline/hitran24_pf.h5")

2. Loading line data

Once the class has been initialised, it can be used to load the desired data into the class, so that we can perform calculations with it. The main function for reading the data is the fetch_linedata() method of the class.

When using this function, the method will load the required line data from the HDF5 file into the class and will store it in the LineData.line_data dictionary. This dictionary includes the following information:

  • line_data[“RT_GAS_DESC”] : Indicates the gasID and isoID corresponding to each of the transitions. For cases when iso_id > 0 this will always be the same for all transitions, but in the case that we selected iso_id = 0, this descriptor provides information about the isotope the transition corresponds to.

  • line_data[“NU”] : Wavenumber of each of the transitions (cm\(^{-1}\)).

  • line_data[“SW”] : Line strength of the transition (cm\(^{-1}\) / (molec cm\(^{-2}\))).

  • line_data[“A”] : Einstein A coeifficient (s\(^{-1}\)).

  • line_data[“GAMMA_AMB”] : Ambient gas broadening coefficient (cm\(^{-1}\) atm\(^{-1}\)).

  • line_data[“N_AMB”] : Temperature dependent exponent for “GAMMA_AMB”.

  • line_data[“DELTA_AMB”] : Ambient gas pressure induced line-shift (cm\(^{-1}\) atm\(^{-1}\)).

  • line_data[“GAMMA_SELF”] : Self-broadening coefficient (cm\(^{-1}\) atm\(^{-1}\)).

  • line_data[“ELOWER”] : Lower state energy (cm\(^{-1}\)).

In addition, while this is the information that is strictly required to compute the absorption cross sections, we may load more extra information about the transitions by using the keyword fetch_linedata(include_extra_info=True). This will create a similar dictionary stored in LineData.line_info, where the values of the dictionary are:

  • line_info[“GLOBAL_UPPER_QUANTA”] : Global upper state quanta numbers.

  • line_info[“GLOBAL_LOWER_QUANTA”] : Global lower state quanta numbers.

  • line_info[“LOCAL_UPPER_QUANTA”] : Local upper state quanta numbers.

  • line_info[“LOCAL_LOWER_QUANTA”] : Local lower state quanta numbers.

  • line_info[“GP”] : Upper state degeneracy.

  • line_info[“GPP”] : Lower state degeneracy.

A more detailed explanation of these parameters can be found in the HITRAN website.

Once the data is loaded, it can be easily explored by printing the values in the dictionary. Similarly, the LineData class includes a method to create some diagnostic plots.

[3]:
# Download line data for a specified spectral range
vmin = 1700.0
vmax = 2300.0
wave_unit = 0 #0 - Wavenumber (cm-1) ; 1 = Wavelength (um)
LineData.fetch_linedata(vmin, vmax, wave_unit=wave_unit, include_extra_info=True)
[4]:
#Printing some values
print("")
print("Content of line_data dictionary")
print(LineData.line_data["RT_GAS_DESC"].T)
print(LineData.line_data["SW"].T)
print("")
print("")

print("Content of line_info dictionary")
print(LineData.line_data["RT_GAS_DESC"].T)
print(LineData.line_info["LOCAL_LOWER_QUANTA"].T)
print("")

Content of line_data dictionary
[[5 5 5 ... 5 5 5]
 [1 1 1 ... 6 6 6]]
[2.56653426e-31 7.17453771e-31 1.96950082e-30 ... 1.48514851e-25
 7.01683072e-26 3.25677729e-26]


Content of line_info dictionary
[[5 5 5 ... 5 5 5]
 [1 1 1 ... 6 6 6]]
[b'     P 57      ' b'     P 56      ' b'     P 55      ' ...
 b'     R 44      ' b'     R 45      ' b'     R 46      ']

[5]:
# Create diagnotic plots
LineData.plot_linedata()
INFO :: plot_linedata :: LineData_0.py-1062 :: gas_desc=RadtranGasDescriptor(gas_id=<Gas.CO: 5>, iso_id=1) gas_linedata.shape=(279,)
INFO :: plot_linedata :: LineData_0.py-1062 :: gas_desc=RadtranGasDescriptor(gas_id=<Gas.CO: 5>, iso_id=2) gas_linedata.shape=(252,)
INFO :: plot_linedata :: LineData_0.py-1062 :: gas_desc=RadtranGasDescriptor(gas_id=<Gas.CO: 5>, iso_id=3) gas_linedata.shape=(238,)
INFO :: plot_linedata :: LineData_0.py-1062 :: gas_desc=RadtranGasDescriptor(gas_id=<Gas.CO: 5>, iso_id=4) gas_linedata.shape=(215,)
INFO :: plot_linedata :: LineData_0.py-1062 :: gas_desc=RadtranGasDescriptor(gas_id=<Gas.CO: 5>, iso_id=5) gas_linedata.shape=(169,)
INFO :: plot_linedata :: LineData_0.py-1062 :: gas_desc=RadtranGasDescriptor(gas_id=<Gas.CO: 5>, iso_id=6) gas_linedata.shape=(158,)
../../_images/examples_linedata_linedata_7_1.png

3. Calculate the absorption cross sections

Apart from allowing the investigation of the line data, the LineData class includes some functionality to calculate the absorption cross following the formalism indicated in the HITRAN website.

The main method to perform these calculations is LineData.calculate_monochromatic_absorption(). This has several inputs that are important to specify:

  • waves : Array of wavenumbers (cm\(^{-1}\)) or wavelengths (\(\mu\)) at which to calculate the absorption coefficient.

  • temp : Ambient temperature (K).

  • press : Ambient pressure (atm).

  • amb_frac : Fraction of ambient pressure (1.0 = complete foreign broadening ; 0.0 = complete self broadening)

  • wave_unit : Unit of the spectral array (0 = wavenumber in cm\(^{-1}\); 1 = wavelength in \(\mu\)m). Default = 0.

  • lineshape_fn : This needs to point to one of the lineshapes stored in archnemesis.Data.lineshapes. Default = Data.lineshapes.voigt (Voigt profile).

  • line_calculation_wavenumber_window : Wavenumber window around a line where the contribution from that line is considered (cm\(^{-1}\)). Default = 25 cm\(^{-1}\).

  • line_strength_cutoff : Strength below which a line is ignored. Default = 10\(^{-32}\).

  • isotopic_abundances : If not None, use these abundances for each isotopologue instead of the default terrestrial ones.

It must be noted that, following NEMESIS conventions, the absorption coefficient calculated here must be multiplied by a factor of 10\(^{-20}\) to express it in cm\(^{2}\).

[6]:
wave_unit = 0     #0 - Wavenumber (cm-1) ; 1 = Wavelength (um)
waves = np.arange(2050,2055,0.0001)  #Wavenumber array

amb_frac = 1.0   #Fraction of ambient pressure (1.0 = complete foreign broadening ; 0.0 = complete self broadening)

temp1 = 200.      #Temperature (K)
press1 = 0.1      #Pressure (atm)
k1 = LineData.calculate_monochromatic_absorption(waves,temp1,press1,amb_frac,wave_unit=wave_unit)

temp2 = 200.      #Temperature (K)
press2 = 1.0      #Pressure (atm)
k2 = LineData.calculate_monochromatic_absorption(waves,temp2,press2,amb_frac,wave_unit=wave_unit)
INFO :: fetch_partition_function :: LineData_0.py-568 :: Retrieved partition function data from database /home/alday/Documents/Projects/archnemesis-dist/archnemesis/database/offline/hitran24_pf.h5
INFO :: calculate_monochromatic_spectrum :: LineData_0.py-774 :: Computing line contributions.  STARTING at 2026-06-02T17:50:34.515337
INFO :: calculate_monochromatic_spectrum :: LineData_0.py-774 :: Computing line contributions.  FINISHED at 2026-06-02T17:50:34.815013
INFO :: fetch_partition_function :: LineData_0.py-559 :: Partition function data already loaded
INFO :: calculate_monochromatic_spectrum :: LineData_0.py-774 :: Computing line contributions.  STARTING at 2026-06-02T17:50:34.834334
INFO :: calculate_monochromatic_spectrum :: LineData_0.py-774 :: Computing line contributions.  FINISHED at 2026-06-02T17:50:35.142963
[7]:
fig,ax1 = plt.subplots(1,1,figsize=(8,3))
ax1.plot(waves,k1*1.0e-20,label=f"T = {temp1} K ; P = {press1} atm")
ax1.plot(waves,k2*1.0e-20,label=f"T = {temp2} K ; P = {press2} atm")
ax1.set_yscale("log")
ax1.legend()
ax1.set_xlabel("Wavenumber (cm$^{-1}$)")
ax1.set_ylabel("Absorption cross section (cm$^2$)")
plt.tight_layout()

../../_images/examples_linedata_linedata_10_0.png
[ ]: