diff --git a/esmvaltool/diag_scripts/fire/diagnostic_run_confire.py b/esmvaltool/diag_scripts/fire/diagnostic_run_confire.py index e24590f1c7..a270641c0d 100644 --- a/esmvaltool/diag_scripts/fire/diagnostic_run_confire.py +++ b/esmvaltool/diag_scripts/fire/diagnostic_run_confire.py @@ -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. @@ -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 = "" @@ -612,6 +614,7 @@ def _read_all_data_from_netcdf( make_flat=True, return_time_points=True, return_extent=True, + verbose=False, **kw, ) @@ -622,6 +625,7 @@ def _read_all_data_from_netcdf( make_flat=True, time_points=time_points, extent=extent, + verbose=False, **kw, ) @@ -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) diff --git a/esmvaltool/diag_scripts/fire/fire_diagnostic.py b/esmvaltool/diag_scripts/fire/fire_diagnostic.py index 7e4fc5110a..79724f0331 100644 --- a/esmvaltool/diag_scripts/fire/fire_diagnostic.py +++ b/esmvaltool/diag_scripts/fire/fire_diagnostic.py @@ -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 + vpd_tavg-h2m-hxy-u_mon_glb_g999_MPI-ESM1-2-LR_historical_r1i1p1f2_... Parameters ---------- @@ -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) @@ -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") @@ -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) @@ -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" @@ -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( diff --git a/esmvaltool/recipes/ref/recipe_ref_fire_cmip7.yml b/esmvaltool/recipes/ref/recipe_ref_fire_cmip7.yml new file mode 100644 index 0000000000..bd5102ec66 --- /dev/null +++ b/esmvaltool/recipes/ref/recipe_ref_fire_cmip7.yml @@ -0,0 +1,85 @@ +# 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 + + 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: 2013, end_year: 2014, + 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']