Skip to content
3 changes: 3 additions & 0 deletions doc/sphinx/source/recipes/recipe_ref_fire.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ The ConFire model relies on a variety of observational datasets (see references)
* ESA CCI Biomass
* ISIMIP3a GSWP3-W5E5 dataset

For the CMIP7 version of the recipe, the time period is chosen to overlap
with reliable burned area observations, namely GFED5.

Note: If custom ConFire run files are to be used for the diagnostic,
they need to be present inside the auxiliary directory defined in the
user configuration file `config_user.yml`.
Expand Down
14 changes: 11 additions & 3 deletions esmvaltool/diag_scripts/fire/diagnostic_run_confire.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ def _read_variable_from_netcdf(
make_flat: bool = False,
return_time_points: bool = False,
return_extent: bool = False,
verbose: bool = True,
) -> iris.cube.Cube:
"""Read data from a netCDF file.

Expand Down Expand Up @@ -446,8 +447,9 @@ def _read_variable_from_netcdf(
if make_flat, a numpy vector of the target variable, otherwise
returns iris cube.
"""
logger.info("Opening:")
logger.info(filename)
if verbose:
logger.info("Opening:")
logger.info(filename)

if filename[0] == "~" or filename[0] == "/" or filename[0] == ".":
directory = ""
Expand Down Expand Up @@ -612,6 +614,7 @@ def _read_all_data_from_netcdf(
make_flat=True,
return_time_points=True,
return_extent=True,
verbose=False,
**kw,
)

Expand All @@ -622,6 +625,7 @@ def _read_all_data_from_netcdf(
make_flat=True,
time_points=time_points,
extent=extent,
verbose=False,
**kw,
)

Expand Down Expand Up @@ -899,7 +903,11 @@ def _get_parameters(config: dict) -> tuple:
directory=nc_dir,
)
# Load a sample cube (used for inserting data)
eg_cube = _read_variable_from_netcdf(nc_files[0], directory=nc_dir)
eg_cube = _read_variable_from_netcdf(
nc_files[0],
directory=nc_dir,
verbose=False,
)
# **Extract Model Parameters**
logger.info("Loading ConFire model parameters...")
params, params_names = _select_post_param(param_file_trace)
Expand Down
57 changes: 38 additions & 19 deletions esmvaltool/diag_scripts/fire/fire_diagnostic.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,17 @@ def setup_basename_file(
) -> str:
"""Generate the file basename for a newly computed variable.

the filename of an ancestor variable is used as template.

Example: If the ancestor filename is
CMIP6_MPI-ESM1-2-LR_Amon_historical-ssp370_r1i1p1f1_pr_gn_2010-2020.nc
then the returned basename will have the following structure
CMIP6_MPI-ESM1-2-LR_{table}_historical-ssp370_r1i1p1f1_{var}_gn_2010-2020.
The filename of an ancestor variable is used as template.

Example:
- If the ancestor filename is
CMIP6_MPI-ESM1-2-LR_Amon_historical-ssp370_r1i1p1f1_tas_gn_...
then the returned basename will have the following structure
CMIP6_MPI-ESM1-2-LR_{table}_historical-ssp370_r1i1p1f1_{var}_gn_...
- For CMIP7 data, for an ancestor filename
tas_tavg-h2m-hxy-u_mon_glb_g999_MPI-ESM1-2-LR_historical_r1i1p1f2_...
then the returned basename will have the following structure
{var}_tavg-h2m-hxy-u_mon_glb_g999_MPI-ESM1-2-LR_historical_r1i1p1f2_...

Parameters
----------
Expand All @@ -66,11 +71,18 @@ def setup_basename_file(
basename : str
Basename for the file in which the processed variable will be saved.
"""
# Recover only the filename without path and type then split elements
file = Path(filename).stem.split("_")
# Fill in variable and table
file[2] = table
file[-3] = var
# CMIP6-like case for filename convention
if table == "Amon":
# Recover only the filename without path and type then split elements
file = Path(filename).stem.split("_")
# Fill in variable and table
file[2] = table
file[-3] = var
else:
# Recover only the filename without path and type then split elements
file = Path(filename).stem.split("_")
# Fill in variable
file[0] = var
return "_".join(file)


Expand Down Expand Up @@ -279,7 +291,19 @@ def compute_vpd(
vpd.attributes["ancestors"] = provenance["ancestors"]
debug_vpd = f"vapor_pressure_deficit iris cube {vpd}"
logger.debug(debug_vpd)
basename = setup_basename_file(provenance["ancestors"][0], "vpd", "Amon")
# Differentiate filename structure for CMIP6/CMIP7 data
if "tavg-h2m-hxy" in provenance["ancestors"][0]:
basename = setup_basename_file(
provenance["ancestors"][0],
"vpd",
"atmos",
)
else:
basename = setup_basename_file(
provenance["ancestors"][0],
"vpd",
"Amon",
)
msg = f"Saving vapor_pressure_deficit in {cfg['work_dir']}/{basename}"
logger.info(msg)
filename = get_diagnostic_filename(basename, cfg, extension="nc")
Expand Down Expand Up @@ -310,12 +334,7 @@ def main(cfg: dict) -> None:
# - user-defined path to files
# - download files from a Zenodo archive
# - defaults to the path to files from ESMValTool
if "confire_param" in cfg:
if "zenodo" not in cfg["confire_param"]:
cfg["param_confire"] = (
Path(cfg["auxiliary_data_dir"]) / cfg["confire_param"]
)
else:
if "confire_param" not in cfg:
cfg["confire_param"] = "https://zenodo.org/records/14917245"
cfg["confire_param_dir"] = get_parameter_directory(cfg)

Expand All @@ -340,7 +359,6 @@ def main(cfg: dict) -> None:

vars_file = {}
for i, attributes in enumerate(group):
logger.info("Variable %s", attributes["short_name"])
# Fallback for CMIP7 data for tasmax
short_name_key = (
"tasmax"
Expand All @@ -350,6 +368,7 @@ def main(cfg: dict) -> None:
else attributes["short_name"]
)
vars_file[short_name_key] = attributes
logger.info("Variable %s", short_name_key)
# Save model information for output plot name
if i == 0:
plot_file_info = "_".join(
Expand Down
86 changes: 86 additions & 0 deletions esmvaltool/recipes/ref/recipe_ref_fire_cmip7.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# ESMValTool
---
documentation:
description: |
Recipe that plots diagnostics regarding climate drivers for fire.
The diagnostic uses code for the ConFire model from the following GitHub repository:
https://github.com/douglask3/Bayesian_fire_models/tree/AR7_REF
The timerange is chosen to overlap with reliable burned area observations.

title: Climate drivers for fire.

authors:
- lenhardt_julien
- kelley_douglas

maintainer:
- lenhardt_julien

datasets:
- {dataset: DUMMY-MODEL, institute: MOHC, project: CMIP7, activity: CMIP,
ensemble: r1i1p1f2, exp: historical, start_year: 2002, end_year: 2021,
region: glb, grid: g999, frequency: mon}

preprocessors:

preproc: &preproc
regrid:
target_grid: 2.5x2.5
scheme: nearest
mask_landsea:
mask_out: "sea"
preproc_fraction:
<<: *preproc
convert_units:
units: 1

diagnostics:

fire_evaluation:
description: Climate drivers for fire
variables:
#Precipitation
pr:
mip: atmos
branding_suffix: tavg-u-hxy-u
preprocessor: preproc
# Maximum surface temperature
tasmax:
short_name: tas
mip: atmos
branding_suffix: tmaxavg-h2m-hxy-u
preprocessor: preproc
# Tree cover percentage
treeFrac:
mip: land
branding_suffix: tavg-u-hxy-u
preprocessor: preproc_fraction
# Vegetation cover percentage
vegFrac:
mip: land
branding_suffix: tavg-u-hxy-u
preprocessor: preproc_fraction
# Vegetation carbon mass
cVeg:
mip: land
branding_suffix: tavg-u-hxy-lnd
preprocessor: preproc
# To compute the vapor pressure deficit (vpd)
# Surface temperature
tas:
mip: atmos
branding_suffix: tavg-h2m-hxy-u
preprocessor: preproc
# Near-surface relative humidity
hurs:
mip: atmos
branding_suffix: tavg-h2m-hxy-u
preprocessor: preproc

scripts:
fire_evaluation:
script: fire/fire_diagnostic.py
# confire_param: https://zenodo.org/records/14917245
confire_param: /home/b/b381312/esmvaltool/auxiliary_data/ConFire_parameter_files/
# IMPORTANT = the order of the variables should fit the configuration files of the ConFire model run
var_order: ['pr', 'tasmax', 'treeFrac', 'vegFrac', 'vpd', 'cVeg']