Normalization

In this example, the time evolution of type normalization is demonstrated. A historic emission scenario is simulated with OpenAirClim.

Imports

If the openairclim package cannot be imported, make sure that you have installed openairclim properly (see User Guide → Installation).

import xarray as xr
import matplotlib.pyplot as plt
import openairclim as oac

xr.set_options(display_expand_attrs=False)
<xarray.core.options.set_options at 0x7fa7e781d7f0>

Input files

In order to be able to execute this example simulation, three types of input are required.

  • Configuration file norm.toml

  • Emission inventory ELK_aviation_2019_res5deg_flat.nc

  • Time evolution file for fuel normalization time_norm_historic_SSP.nc

Emission inventory

  • Source: DLR Project EmissionsLandKarte (ELK)

  • Resolution down-sampled to 5 deg resolution

  • Converted into format suitable for OpenAirClim. See also following scripts.

  • Inventory year: 2019

inv = xr.load_dataset("../input/ELK_aviation_2019_res5deg_flat.nc")
display(inv)
<xarray.Dataset> Size: 2MB
Dimensions:   (index: 50854)
Dimensions without coordinates: index
Data variables:
    fuel      (index) float32 203kB 1.493e+04 7.459e+03 ... 7.471e+03 1.676e+03
    CO2       (index) float32 203kB 4.716e+04 2.356e+04 ... 2.36e+04 5.294e+03
    H2O       (index) float32 203kB 1.847e+04 9.227e+03 ... 9.242e+03 2.073e+03
    NOx       (index) float32 203kB 161.7 77.61 146.9 ... 965.8 134.5 23.91
    distance  (index) float32 203kB 2.266e+03 1.188e+03 ... 1.225e+03 272.1
    lat       (index) float64 407kB -67.5 -67.5 -67.5 -67.5 ... 87.5 87.5 87.5
    lon       (index) float64 407kB -167.5 -167.5 -167.5 ... 177.5 177.5 177.5
    plev      (index) float32 203kB 315.4 301.5 288.1 ... 197.5 179.4 171.0
Attributes: (9)

Time evolution

  • Time evolution with normalization of fuel use

  • Time period: 1920 - 2019

evo = xr.load_dataset("../input/time_norm_historic_SSP.nc")
display(evo)

fig, ax = plt.subplots()
evo.fuel.plot(ax=ax)
ax.grid(True)
<xarray.Dataset> Size: 2kB
Dimensions:  (time: 100)
Coordinates:
  * time     (time) int64 800B 1920 1921 1922 1923 1924 ... 2016 2017 2018 2019
Data variables:
    fuel     (time) float64 800B 2.669 2.889 3.427 4.145 ... 264.7 274.1 283.5
Attributes: (5)
../../_images/norm_3_1.png

Simulation run

oac.run("norm.toml")
2026-10-16 10:43:03,955 INFO main:449 (run): 
-------------- OPENAIRCLIM MAIN RUN LOG --------------
oac version: 0.20.0
timestamp: 2026-10-16 10:43:03.954995
input file: norm.toml
user: runner
platform: Linux 6.17.0-1022-azure
oac_premium available: False

NOTE:
OpenAirClim is currently in development phase.
The computed output is not to be used for scientific
purposes until the release of our publication.
The NOx response surfaces using the tagging method
are not validated and can produce misleading results
(output species CH4, O3, PMO and SWV).
------------------------------------------------------
START OF LOG

2026-10-16 10:43:03,966 INFO read_netcdf:392 (open_netcdf_from_config): O3 RF response surface employing perturbation approach!
2026-10-16 10:43:03,973 INFO read_netcdf:392 (open_netcdf_from_config): CH4 response surface employing perturbation approach!
2026-10-16 10:43:03,973 INFO read_config:537 (check_config): Configuration file checked.
2026-10-16 10:43:03,974 INFO read_config:572 (create_output_dir): Create new output directory results
2026-10-16 10:43:03,984 WARNING read_netcdf:85 (_filter_inventories_to_time_range): Longitude values have been automatically updated to be between 0 and 360 degrees to match pre-calculated data.
2026-10-16 10:43:03,991 INFO read_netcdf:204 (open_inventories): Emission inventories openend, attribute sections and time constraints checked successfully.
2026-10-16 10:43:04,002 INFO read_netcdf:257 (_resolve_aircraft_list): No ac data variable found in the emission inventories. Reverting to 'DEFAULT' aircraft from config file.
2026-10-16 10:43:04,156 INFO read_netcdf:392 (open_netcdf_from_config): O3 RF response surface employing perturbation approach!
2026-10-16 10:43:04,252 INFO read_netcdf:392 (open_netcdf_from_config): CH4 response surface employing perturbation approach!
2026-10-16 10:43:05,783 WARNING calc_cont:867 (check_plev_range): Found 604 'plev' values outside the allowed range [70, 1000]. Observed plev values min=148.165, max=1013.25. Values were automatically clamped into the allowed range. Use results with caution.
2026-10-16 10:43:05,969 INFO main:529 (run): Execution time: 2.01423716545105 sec
2026-10-16 10:43:05,970 INFO main:530 (run): 

END OF LOG
------------------------------------------------------

Results

Time series

  • Emission sums

  • Concentrations

  • Radiative forcings

  • Temperature changes

results_ds = xr.load_dataset("results/norm.nc")
display(results_ds)
<xarray.Dataset> Size: 34kB
Dimensions:        (ac: 2, time: 100)
Coordinates:
  * ac             (ac) <U7 56B 'DEFAULT' 'TOTAL'
  * time           (time) int64 800B 1920 1921 1922 1923 ... 2016 2017 2018 2019
Data variables: (12/21)
    emis_CO2       (ac, time) float64 2kB 8.432 9.125 10.83 ... 865.9 895.6
    emis_distance  (ac, time) float64 2kB 5.849e+08 6.33e+08 ... 6.213e+10
    emis_H2O       (ac, time) float64 2kB 3.302 3.573 4.239 ... 339.1 350.7
    emis_NOx       (ac, time) float64 2kB 0.03702 0.04006 ... 3.802 3.932
    conc_CH4       (ac, time) float64 2kB 0.0 -0.01828 ... -32.74 -33.59
    conc_CO2       (ac, time) float64 2kB 0.001082 0.002194 ... 2.754 2.828
    ...             ...
    dT_CO2         (ac, time) float64 2kB 1.489e-06 4.343e-06 ... 0.02605
    dT_cont        (ac, time) float64 2kB 7.374e-06 1.454e-05 ... 0.006202
    dT_H2O         (ac, time) float64 2kB 3.515e-06 6.93e-06 ... 0.002956
    dT_O3          (ac, time) float64 2kB 3.588e-05 7.073e-05 ... 0.03017
    dT_PMO         (ac, time) float64 2kB 0.0 -2.7e-07 ... -0.003189 -0.003259
    dT_SWV         (ac, time) float64 2kB 0.0 0.0 0.0 ... -0.001437 -0.001482
Attributes: (9)
# Plot Radiative Forcing and Temperature Changes

ac = "TOTAL"
# O3, CH4, PMO and SWV are summed into one NOx term
nox_species = ["O3", "CH4", "PMO", "SWV"]
rf_nox = sum(results_ds[f"RF_{s}"].sel(ac=ac) for s in nox_species) * 1000
dt_nox = sum(results_ds[f"dT_{s}"].sel(ac=ac) for s in nox_species) * 1000

species = ["CO2", "H2O", "cont"]
colors = ["tab:gray", "tab:blue", "tab:cyan"]

fig, ax = plt.subplots(ncols=2, figsize=(10, 5))
ax[0].grid(True)
ax[1].grid(True)
for spec, color in zip(species, colors):
    rf = results_ds[f"RF_{spec}"].sel(ac=ac) * 1000
    dt = results_ds[f"dT_{spec}"].sel(ac=ac) * 1000
    rf.plot(ax=ax[0], color=color, label=spec)
    dt.plot(ax=ax[1], color=color, label=spec)
rf_nox.plot(ax=ax[0], color="tab:green", linestyle="--", label="NOx")
dt_nox.plot(ax=ax[1], color="tab:green", linestyle="--", label="NOx")
ax[0].set_ylabel("Radiative Forcing [mW/m²]")
ax[1].set_ylabel("Temperature Change [mK]")
ax[0].legend()
ax[1].legend()
<matplotlib.legend.Legend at 0x7fa7da7dd2b0>
../../_images/norm_6_1.png

Climate metrics

  • Absolute Global Temperature Potential (AGTP)

  • Absolute Global Warming Potential (AGWP)

  • Absolute Efficacy-weighted Global Warming Potential (AEGWP)

  • Average Temperature Response (ATR)

metrics_ds = xr.load_dataset("results/norm_metrics.nc")
display(metrics_ds)
<xarray.Dataset> Size: 288B
Dimensions:         (species: 8)
Coordinates:
  * species         (species) <U5 160B 'CH4' 'CO2' 'cont' ... 'SWV' 'total'
Data variables:
    AGTP_100_1920   (species) float32 32B -0.01169 0.02605 ... -0.001482 0.04896
    AGWP_100_1920   (species) float32 32B -0.5619 1.272 1.738 ... -0.05455 4.095
    AEGWP_100_1920  (species) float32 32B -0.5843 1.272 ... -0.05455 2.785
    ATR_100_1920    (species) float32 32B -0.003162 0.006835 ... 0.01569
Attributes: (9)