1B. Mean Climate Driver

This notebook introduces new users to the PCDMI mean climate driver.

This notebook should be run in an environment with python, jupyterlab, pcmdi metrics package, and cdat installed. It is expected that you have downloaded the sample data and prepared input parameter files as demonstrated in the 0. Prepare Demos notebook.

To see which datasets are the default and which are alternates, check out pcmdi_metrics/doc/obs_info_dictionary.json.

The following cell reads in the choices you made during the download data step:

[1]:
# To open and display one of the graphics
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from matplotlib import rcParams

import os

%matplotlib inline
[2]:
from user_choices import demo_data_directory, demo_output_directory

When you chec user_choices.py in the current directory, you will see:

This is where you will be downloading the sample_data: demo_data_directory = "demo_data"

and this line is where your output will be stored: demo_output_directory = "demo_output"

Download reference datasets

[3]:
# Lets get the file containing the data needed for this demo
import requests
r = requests.get("https://pcmdi.llnl.gov/pss/pmpdata/PMP_obs4MIPsClims_v20250228.txt")
with open("data_files.txt","wb") as f:
    f.write(r.content)
[4]:
# Let's download the files
from pcmdi_metrics.io.base import download_sample_data_files
try:
    download_sample_data_files("data_files.txt", demo_data_directory)
    print("All files downloaded")
except Exception:
    print("Download failed")
Downloading: 'PMP_obs4MIPsClims/pr/gr/v20250211/pr_mon_GPCP-Monthly-3-2_RSS_gr_198301-200412_AC_v20250211_interp_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/pr/gr/v20250211/pr_mon_GPCP-Monthly-3-2_RSS_gr_198301-200412_AC_v20250211_interp_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/psl/gr/v20250224/psl_mon_ERA-5_PCMDI_gr_198101-200412_AC_v20250224_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/psl/gr/v20250224/psl_mon_ERA-5_PCMDI_gr_198101-200412_AC_v20250224_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/rldscs/gr/v20250213/rldscs_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/rldscs/gr/v20250213/rldscs_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/rlds/gr/v20250213/rlds_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/rlds/gr/v20250213/rlds_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/rltcre/gr/v20250213/rltcre_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/rltcre/gr/v20250213/rltcre_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/rlus/gr/v20250213/rlus_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/rlus/gr/v20250213/rlus_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/rlutcs/gr/v20250213/rlutcs_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/rlutcs/gr/v20250213/rlutcs_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/rlut/gr/v20250213/rlut_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/rlut/gr/v20250213/rlut_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/rsdscs/gr/v20250213/rsdscs_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/rsdscs/gr/v20250213/rsdscs_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/rsds/gr/v20250213/rsds_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/rsds/gr/v20250213/rsds_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/rsdt/gr/v20250213/rsdt_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/rsdt/gr/v20250213/rsdt_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/rstcre/gr/v20250213/rstcre_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/rstcre/gr/v20250213/rstcre_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/rsuscs/gr/v20250213/rsuscs_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/rsuscs/gr/v20250213/rsuscs_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/rsus/gr/v20250213/rsus_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/rsus/gr/v20250213/rsus_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/rsutcs/gr/v20250213/rsutcs_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/rsutcs/gr/v20250213/rsutcs_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/rsut/gr/v20250213/rsut_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/rsut/gr/v20250213/rsut_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/rt/gr/v20250213/rt_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/rt/gr/v20250213/rt_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/ta/gr/v20250224/ta_mon_ERA-5_PCMDI_gr_198101-200412_AC_v20250224_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/ta/gr/v20250224/ta_mon_ERA-5_PCMDI_gr_198101-200412_AC_v20250224_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/tas/gr/v20250224/tas_mon_ERA-5_PCMDI_gr_198101-200412_AC_v20250224_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/tas/gr/v20250224/tas_mon_ERA-5_PCMDI_gr_198101-200412_AC_v20250224_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/ts/gr/v20250224/ts_mon_ERA-5_PCMDI_gr_198101-200412_AC_v20250224_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/ts/gr/v20250224/ts_mon_ERA-5_PCMDI_gr_198101-200412_AC_v20250224_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/ua/gr/v20250224/ua_mon_ERA-5_PCMDI_gr_198101-200412_AC_v20250224_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/ua/gr/v20250224/ua_mon_ERA-5_PCMDI_gr_198101-200412_AC_v20250224_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/uas/gr/v20250224/uas_mon_ERA-5_PCMDI_gr_198101-200412_AC_v20250224_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/uas/gr/v20250224/uas_mon_ERA-5_PCMDI_gr_198101-200412_AC_v20250224_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/va/gr/v20250225/va_mon_ERA-5_PCMDI_gr_198101-200412_AC_v20250225_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/va/gr/v20250225/va_mon_ERA-5_PCMDI_gr_198101-200412_AC_v20250225_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/vas/gr/v20250225/vas_mon_ERA-5_PCMDI_gr_198101-200412_AC_v20250225_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/vas/gr/v20250225/vas_mon_ERA-5_PCMDI_gr_198101-200412_AC_v20250225_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/zg/gr/v20250225/zg_mon_ERA-5_PCMDI_gr_198101-200412_AC_v20250225_2.5x2.5.nc' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/zg/gr/v20250225/zg_mon_ERA-5_PCMDI_gr_198101-200412_AC_v20250225_2.5x2.5.nc
Downloading: 'PMP_obs4MIPsClims/PMP_obs4MIPsClims_catalogue_byVar_v20250305.json' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/PMP_obs4MIPsClims_catalogue_byVar_v20250305.json
Downloading: 'PMP_obs4MIPsClims/Usingcatalogue-sample.py' from 'https://pcmdiweb.llnl.gov/pss/pmpdata/' in: demo_data/PMP_obs4MIPsClims/Usingcatalogue-sample.py
All files downloaded

Basic use

The PCMDI Median Driver is driven via parameter files reflecting your study and environment. The parameter file for this demo is shown here:

[5]:
with open("basic_param.py") as f:
    print(f.read())
import os

#
#  OPTIONS ARE SET BY USER IN THIS FILE AS INDICATED BELOW BY:
#
#

# RUN IDENTIFICATION
# DEFINES A SUBDIRECTORY TO METRICS OUTPUT RESULTS SO MULTIPLE CASES CAN
# BE COMPARED
case_id = 'basicTest'

# LIST OF MODEL VERSIONS TO BE TESTED - WHICH ARE EXPECTED TO BE PART OF
# CLIMATOLOGY FILENAME
test_data_set = ['ACCESS1-0', 'CanCM4']


# VARIABLES TO USE
vars = ['pr']


# Observations to use at the moment "default" or "alternate"
reference_data_set = ['all']
#ext = '.nc'

# INTERPOLATION OPTIONS
target_grid = '2.5x2.5'  # OPTIONS: '2.5x2.5' or an actual cdms2 grid object
regrid_tool = 'regrid2'  # 'regrid2' # OPTIONS: 'regrid2','esmf'
# OPTIONS: 'linear','conservative', only if tool is esmf
regrid_method = 'linear'
regrid_tool_ocn = 'esmf'    # OPTIONS: "regrid2","esmf"
# OPTIONS: 'linear','conservative', only if tool is esmf
regrid_method_ocn = 'linear'

# Templates for climatology files
# %(param) will subsitute param with values in this file
filename_template = "cmip5.historical.%(model_version).r1i1p1.mon.%(variable).198101-200512.AC.v20200426.nc"

# filename template for landsea masks ('sftlf')
sftlf_filename_template = "sftlf_%(model_version).nc"
generate_sftlf = True # if land surface type mask cannot be found, generate one

# Region
regions = {
    "pr": ["Global"],
    "rlut": ["Global"]
}

# ROOT PATH FOR MODELS CLIMATOLOGIES
test_data_path = 'demo_data/CMIP5_demo_clims/'
# ROOT PATH FOR OBSERVATIONS
# Note that atm/mo/%(variable)/ac will be added to this
reference_data_path = 'demo_data/PMP_obs4MIPsClims'
custom_observations = 'demo_data/PMP_obs4MIPsClims/PMP_obs4MIPsClims_catalogue_byVar_v20250305.json'

# DIRECTORY WHERE TO PUT RESULTS
metrics_output_path = os.path.join(
    'demo_output',
    "%(case_id)")

To run the mean climate driver, use the following command in the terminal. This will generate a metrics file based on the models, observations, and other criteria in basic_param.py

mean_climate_driver.py -p basic_param.py

In the next cell, bash cell magic is used to run this command as a subprocess:

[6]:
%%bash
mean_climate_driver.py -p basic_param.py
--- prepare mean climate metrics calculation ---
case_id: basicTest
test_data_set: ['ACCESS1-0', 'CanCM4']
realization:
vars: ['pr']
varname_in_test_data: None
reference_data_set: ['all']
target_grid: 2.5x2.5
regrid_tool: regrid2
regrid_tool_ocn: esmf
save_test_clims: False
test_clims_interpolated_output: None
filename_template: cmip5.historical.%(model_version).r1i1p1.mon.%(variable).198101-200512.AC.v20200426.nc
sftlf_filename_template: sftlf_%(model_version).nc
generate_sftlf: True
regions_specs: {'global': {}, 'NHEX': {'domain': {'latitude': (30.0, 90)}}, 'SHEX': {'domain': {'latitude': (-90.0, -30)}}, 'TROPICS': {'domain': {'latitude': (-30.0, 30)}}, '90S50S': {'domain': {'latitude': (-90.0, -50)}}, '50S20S': {'domain': {'latitude': (-50.0, -20)}}, '20S20N': {'domain': {'latitude': (-20.0, 20)}}, '20N50N': {'domain': {'latitude': (20.0, 50)}}, '50N90N': {'domain': {'latitude': (50.0, 90)}}, 'CONUS': {'domain': {'latitude': (24.7, 49.4), 'longitude': (-124.78, -66.92)}}, 'land': {'value': 100}, 'land_NHEX': {'value': 100, 'domain': {'latitude': (30.0, 90)}}, 'land_SHEX': {'value': 100, 'domain': {'latitude': (-90.0, -30)}}, 'land_TROPICS': {'value': 100, 'domain': {'latitude': (-30.0, 30)}}, 'land_CONUS': {'value': 100, 'domain': {'latitude': (24.7, 49.4), 'longitude': (-124.78, -66.92)}}, 'ocean': {'value': 0}, 'ocean_NHEX': {'value': 0, 'domain': {'latitude': (30.0, 90)}}, 'ocean_SHEX': {'value': 0, 'domain': {'latitude': (-90.0, -30)}}, 'ocean_TROPICS': {'value': 0, 'domain': {'latitude': (30.0, 30)}}, 'ocean_50S50N': {'value': 0.0, 'domain': {'latitude': (-50.0, 50)}}, 'ocean_50S20S': {'value': 0.0, 'domain': {'latitude': (-50.0, -20)}}, 'ocean_20S20N': {'value': 0.0, 'domain': {'latitude': (-20.0, 20)}}, 'ocean_20N50N': {'value': 0.0, 'domain': {'latitude': (20.0, 50)}}, 'NAM': {'domain': {'latitude': (20.0, 90), 'longitude': (-180, 180)}}, 'NAO': {'domain': {'latitude': (20.0, 80), 'longitude': (-90, 40)}}, 'EA': {'domain': {'latitude': (20.0, 80), 'longitude': (-90, 40)}}, 'SCA': {'domain': {'latitude': (20.0, 80), 'longitude': (-90, 40)}}, 'SAM': {'domain': {'latitude': (-20.0, -90), 'longitude': (0, 360)}}, 'PSA1': {'domain': {'latitude': (-20.0, -90), 'longitude': (0, 360)}}, 'PSA2': {'domain': {'latitude': (-20.0, -90), 'longitude': (0, 360)}}, 'PNA': {'domain': {'latitude': (20.0, 85), 'longitude': (120, 240)}}, 'NPO': {'domain': {'latitude': (20.0, 85), 'longitude': (120, 240)}}, 'PDO': {'domain': {'latitude': (20.0, 70), 'longitude': (110, 260)}}, 'NPGO': {'domain': {'latitude': (20.0, 70), 'longitude': (110, 260)}}, 'AMO': {'domain': {'latitude': (0.0, 70), 'longitude': (-80, 0)}}, 'AllMW': {'domain': {'latitude': (-40.0, 45.0), 'longitude': (0.0, 360.0)}}, 'AllM': {'domain': {'latitude': (-45.0, 45.0), 'longitude': (0.0, 360.0)}}, 'NAMM': {'domain': {'latitude': (0.0, 45.0), 'longitude': (210.0, 310.0)}}, 'SAMM': {'domain': {'latitude': (-45.0, 0.0), 'longitude': (240.0, 330.0)}}, 'NAFM': {'domain': {'latitude': (0.0, 45.0), 'longitude': (-50.0, 60.0)}}, 'SAFM': {'domain': {'latitude': (-45.0, 0.0), 'longitude': (0.0, 90.0)}}, 'ASM': {'domain': {'latitude': (0.0, 45.0), 'longitude': (60.0, 180.0)}}, 'AUSM': {'domain': {'latitude': (-45.0, 0.0), 'longitude': (90.0, 160.0)}}, 'AIR': {'domain': {'latitude': (7.0, 25.0), 'longitude': (65.0, 85.0)}}, 'AUS': {'domain': {'latitude': (-20.0, -10.0), 'longitude': (120.0, 150.0)}}, 'Sahel': {'domain': {'latitude': (13.0, 18.0), 'longitude': (-10.0, 10.0)}}, 'GoG': {'domain': {'latitude': (0.0, 5.0), 'longitude': (-10.0, 10.0)}}, 'NAmo': {'domain': {'latitude': (20.0, 37.0), 'longitude': (-112.0, -103.0)}}, 'SAmo': {'domain': {'latitude': (-20.0, 2.5), 'longitude': (-65.0, -40.0)}}}
regions: {'pr': ['Global'], 'rlut': ['Global']}
test_data_path: demo_data/CMIP5_demo_clims/
reference_data_path: demo_data/PMP_obs4MIPsClims
custom_observations: demo_data/PMP_obs4MIPsClims/PMP_obs4MIPsClims_catalogue_byVar_v20250305.json
metrics_output_path: demo_output/basicTest
diagnostics_output_path: demo_output/basicTest
debug: False
--- start mean climate metrics calculation ---
varname: pr
level: None
reference_data_set (all):  ['default']
No 'default' reference found, using the only available reference: GPCP-Monthly-3-2 for variable 'pr'
obs_dict (for variable): pr
{'GPCP-Monthly-3-2': {'filename': 'pr_mon_GPCP-Monthly-3-2_RSS_gr_198301-200412_AC_v20250211_interp_2.5x2.5.nc',
                      'template': 'pr/gr/v20250211/pr_mon_GPCP-Monthly-3-2_RSS_gr_198301-200412_AC_v20250211_interp_2.5x2.5.nc'},
 'default': 'GPCP-Monthly-3-2'}
obs_dict (for variable) keys: dict_keys(['GPCP-Monthly-3-2', 'default'])
ref: default
ref_data_full_path: demo_data/PMP_obs4MIPsClims/pr/gr/v20250211/pr_mon_GPCP-Monthly-3-2_RSS_gr_198301-200412_AC_v20250211_interp_2.5x2.5.nc
2025-08-04 12:36:40,980 [WARNING]: dataset.py(open_dataset:120) >> "No time coordinates were found in this dataset to decode. If time coordinates were expected to exist, make sure they are detectable by setting the CF 'axis' or 'standard_name' attribute (e.g., ds['time'].attrs['axis'] = 'T' or ds['time'].attrs['standard_name'] = 'time'). Afterwards, try decoding again with `xcdat.decode_time`."
2025-08-04 12:36:40,980 [WARNING]: dataset.py(open_dataset:120) >> "No time coordinates were found in this dataset to decode. If time coordinates were expected to exist, make sure they are detectable by setting the CF 'axis' or 'standard_name' attribute (e.g., ds['time'].attrs['axis'] = 'T' or ds['time'].attrs['standard_name'] = 'time'). Afterwards, try decoding again with `xcdat.decode_time`."
Adjust units for pr
pr units adjusted to [mm d-1] from [kg m-2 s-1] by 86400 multiplied
units: mm/day
ref_data load_and_regrid done
=================================
model, runs, find_all_realizations: ACCESS1-0 [''] False
-----------------------
model, run: ACCESS1-0
test_data (model in this case) full_path: demo_data/CMIP5_demo_clims/cmip5.historical.ACCESS1-0.r1i1p1.mon.pr.198101-200512.AC.v20200426.nc
2025-08-04 12:36:41,222 [WARNING]: dataset.py(_is_decodable:549) >> 'time' does not have a 'units' attribute set so it could not be decoded. Try setting the 'units' attribute (`ds.{coords.name}.attrs['units']`) and try decoding again.
2025-08-04 12:36:41,222 [WARNING]: dataset.py(_is_decodable:549) >> 'time' does not have a 'units' attribute set so it could not be decoded. Try setting the 'units' attribute (`ds.{coords.name}.attrs['units']`) and try decoding again.
Adjust units for pr
pr units adjusted to [mm d-1] from [kg m-2 s-1] by 86400 multiplied
units: mm/day
load and regrid done
region: Global
plot map done
plot map done
plot map done
plot map done
plot map done
compute metrics start
var: pr
metrics-CALCULATE ANNUAL CYCLE SPACE-TIME RMS, CORRELATIONS and STD
metrics, rms_xyt
metrics, rms_xyt: 1.7995509408249972
metrics, stdObs_xyt
metrics, stdObs_xyt: 2.515774881304398
metrics, std_xyt
metrics, std_xyt: 3.1305194374804888
metrics-CALCULATE ANNUAL MEANS
metrics-CALCULATE ANNUAL MEAN BIAS
metrics-CALCULATE ANNUAL MEAN BIAS, bias_xy: 0.25922717938795004
metrics-CALCULATE MSE
metrics-CALCULATE MSE, mae_xy: 0.72142914491151
metrics-CALCULATE MEAN RMS
metrics-CALCULATE MEAN RMS: rms_xy, rmsc_xy:  1.1919949785767163 1.1634660710217004
metrics-CALCULATE MEAN CORR
metrics-CALCULATE MEAN CORR: cor_xy: 0.883562458809904
metrics-CALCULATE ANNUAL OBS AND MOD STD
metrics-CALCULATE ANNUAL OBS AND MOD MEAN
metrics-CALCULATE ANNUAL MEANS
metrics-CALCULATE ANNUAL AND ZONAL MEAN RMS
metrics-CALCULATE ANNUAL MEAN DEVIATION FROM ZONAL MEAN RMS
metrics-CALCULATE ANNUAL MEAN DEVIATION FROM ZONAL MEAN STD
INFO::2025-08-04 12:37::pcmdi_metrics:: Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/basicTest/pr/pr_ACCESS1-0__2.5x2.5_regrid2_metrics_default_basicTest.json
2025-08-04 12:37:01,692 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/basicTest/pr/pr_ACCESS1-0__2.5x2.5_regrid2_metrics_default_basicTest.json
2025-08-04 12:37:01,692 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/basicTest/pr/pr_ACCESS1-0__2.5x2.5_regrid2_metrics_default_basicTest.json
=================================
model, runs, find_all_realizations: CanCM4 [''] False
-----------------------
model, run: CanCM4
test_data (model in this case) full_path: demo_data/CMIP5_demo_clims/cmip5.historical.CanCM4.r1i1p1.mon.pr.198101-200512.AC.v20200426.nc
2025-08-04 12:37:01,699 [WARNING]: dataset.py(_is_decodable:549) >> 'time' does not have a 'units' attribute set so it could not be decoded. Try setting the 'units' attribute (`ds.{coords.name}.attrs['units']`) and try decoding again.
2025-08-04 12:37:01,699 [WARNING]: dataset.py(_is_decodable:549) >> 'time' does not have a 'units' attribute set so it could not be decoded. Try setting the 'units' attribute (`ds.{coords.name}.attrs['units']`) and try decoding again.
Adjust units for pr
pr units adjusted to [mm d-1] from [kg m-2 s-1] by 86400 multiplied
units: mm/day
load and regrid done
region: Global
plot map done
plot map done
plot map done
plot map done
plot map done
compute metrics start
var: pr
metrics-CALCULATE ANNUAL CYCLE SPACE-TIME RMS, CORRELATIONS and STD
metrics, rms_xyt
metrics, rms_xyt: 1.6937110851537234
metrics, stdObs_xyt
metrics, stdObs_xyt: 2.515774881304398
metrics, std_xyt
metrics, std_xyt: 2.7462907772599525
metrics-CALCULATE ANNUAL MEANS
metrics-CALCULATE ANNUAL MEAN BIAS
metrics-CALCULATE ANNUAL MEAN BIAS, bias_xy: -0.053533741934399505
metrics-CALCULATE MSE
metrics-CALCULATE MSE, mae_xy: 0.7740939928776985
metrics-CALCULATE MEAN RMS
metrics-CALCULATE MEAN RMS: rms_xy, rmsc_xy:  1.21206440023263 1.2108815998212985
metrics-CALCULATE MEAN CORR
metrics-CALCULATE MEAN CORR: cor_xy: 0.8345736267748058
metrics-CALCULATE ANNUAL OBS AND MOD STD
metrics-CALCULATE ANNUAL OBS AND MOD MEAN
metrics-CALCULATE ANNUAL MEANS
metrics-CALCULATE ANNUAL AND ZONAL MEAN RMS
metrics-CALCULATE ANNUAL MEAN DEVIATION FROM ZONAL MEAN RMS
metrics-CALCULATE ANNUAL MEAN DEVIATION FROM ZONAL MEAN STD
INFO::2025-08-04 12:37::pcmdi_metrics:: Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/basicTest/pr/pr_CanCM4__2.5x2.5_regrid2_metrics_default_basicTest.json
2025-08-04 12:37:21,896 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/basicTest/pr/pr_CanCM4__2.5x2.5_regrid2_metrics_default_basicTest.json
2025-08-04 12:37:21,896 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/basicTest/pr/pr_CanCM4__2.5x2.5_regrid2_metrics_default_basicTest.json
INFO::2025-08-04 12:37::pcmdi_metrics:: Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/basicTest/pr_2.5x2.5_regrid2_metrics_basicTest.json
2025-08-04 12:37:21,898 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/basicTest/pr_2.5x2.5_regrid2_metrics_basicTest.json
2025-08-04 12:37:21,898 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/basicTest/pr_2.5x2.5_regrid2_metrics_basicTest.json
pmp mean clim driver completed
[7]:
# figure size in inches optional
rcParams['figure.figsize'] = 12, 10

# path to images
image_path_djf = os.path.join(demo_output_directory,"basicTest/pr/pr_ACCESS1-0__interpolated_regrid2_Global_DJF_basicTest.png")
image_path_jja = os.path.join(demo_output_directory,"basicTest/pr/pr_ACCESS1-0__interpolated_regrid2_Global_JJA_basicTest.png")

# display images
fig, ax = plt.subplots(1,2); ax[0].axis('off'); ax[1].axis('off')
ax[0].imshow(mpimg.imread(image_path_djf))
ax[1].imshow(mpimg.imread(image_path_jja))
[7]:
<matplotlib.image.AxesImage at 0x1afe8bd00>
../_images/examples_Demo_1b_mean_climate_12_1.png

Running the mean climate driver produces an output json file in the demo output directory. The metrics are stored in the “RESULTS” object of the json, viewed here:

[8]:
import json
import os
output_path = os.path.join(demo_output_directory,"basicTest/pr_2.5x2.5_regrid2_metrics_basicTest.json")
with open(output_path) as f:
    metric = json.load(f)["RESULTS"]
print(json.dumps(metric, indent=2))
{
  "ACCESS1-0": {
    "default": {
      "source": "GPCP-Monthly-3-2",
      "": {
        "InputClimatologyFileName": "cmip5.historical.ACCESS1-0.r1i1p1.mon.pr.198101-200512.AC.v20200426.nc",
        "Global": {
          "bias_xy": {
            "ann": "2.59227e-01",
            "djf": "2.58572e-01",
            "mam": "2.84891e-01",
            "jja": "2.79024e-01",
            "son": "2.15130e-01",
            "CalendarMonths": [
              "2.44339e-01",
              "2.72209e-01",
              "2.42156e-01",
              "2.92509e-01",
              "3.17260e-01",
              "2.96571e-01",
              "2.94654e-01",
              "2.46352e-01",
              "1.93360e-01",
              "2.18105e-01",
              "2.34022e-01",
              "2.59189e-01"
            ]
          },
          "cor_xy": {
            "ann": "8.83562e-01",
            "djf": "8.69386e-01",
            "mam": "8.36063e-01",
            "jja": "8.45822e-01",
            "son": "8.50875e-01",
            "CalendarMonths": [
              "8.49486e-01",
              "8.50622e-01",
              "8.28531e-01",
              "8.19663e-01",
              "7.94971e-01",
              "7.79469e-01",
              "8.20938e-01",
              "8.27655e-01",
              "8.37839e-01",
              "8.27425e-01",
              "8.10679e-01",
              "8.21431e-01"
            ]
          },
          "mae_xy": {
            "ann": "7.21429e-01",
            "djf": "8.76524e-01",
            "mam": "8.96475e-01",
            "jja": "9.63492e-01",
            "son": "8.64213e-01",
            "CalendarMonths": [
              "9.44617e-01",
              "9.49359e-01",
              "9.55736e-01",
              "9.94040e-01",
              "9.98548e-01",
              "1.08393e+00",
              "1.07853e+00",
              "1.06215e+00",
              "9.72518e-01",
              "9.53854e-01",
              "1.03373e+00",
              "1.03675e+00"
            ]
          },
          "mean-obs_xy": {
            "ann": "2.81023e+00",
            "djf": "2.78965e+00",
            "mam": "2.78562e+00",
            "jja": "2.85401e+00",
            "son": "2.81134e+00",
            "CalendarMonths": [
              "2.79955e+00",
              "2.76952e+00",
              "2.79466e+00",
              "2.76949e+00",
              "2.79376e+00",
              "2.86752e+00",
              "2.85269e+00",
              "2.84178e+00",
              "2.82533e+00",
              "2.79685e+00",
              "2.81137e+00",
              "2.80023e+00"
            ]
          },
          "mean_xy": {
            "ann": "3.06946e+00",
            "djf": "3.04822e+00",
            "mam": "3.07051e+00",
            "jja": "3.13304e+00",
            "son": "3.02647e+00",
            "CalendarMonths": [
              "3.04389e+00",
              "3.04173e+00",
              "3.03681e+00",
              "3.06200e+00",
              "3.11103e+00",
              "3.16410e+00",
              "3.14734e+00",
              "3.08813e+00",
              "3.01869e+00",
              "3.01496e+00",
              "3.04539e+00",
              "3.05942e+00"
            ]
          },
          "rms_devzm": {
            "ann": "9.87552e-01"
          },
          "rms_xy": {
            "ann": "1.19199e+00",
            "djf": "1.60098e+00",
            "mam": "1.53329e+00",
            "jja": "1.64962e+00",
            "son": "1.53270e+00",
            "CalendarMonths": [
              "1.78966e+00",
              "1.70639e+00",
              "1.71990e+00",
              "1.66363e+00",
              "1.77204e+00",
              "1.97998e+00",
              "1.91334e+00",
              "1.83395e+00",
              "1.67583e+00",
              "1.69501e+00",
              "1.86946e+00",
              "1.97542e+00"
            ]
          },
          "rms_xyt": {
            "ann": "1.79955e+00"
          },
          "rms_y": {
            "ann": "6.67527e-01"
          },
          "rmsc_xy": {
            "ann": "1.16347e+00",
            "djf": "1.57996e+00",
            "mam": "1.50659e+00",
            "jja": "1.62585e+00",
            "son": "1.51753e+00",
            "CalendarMonths": [
              "1.77290e+00",
              "1.68454e+00",
              "1.70277e+00",
              "1.63771e+00",
              "1.74341e+00",
              "1.95764e+00",
              "1.89052e+00",
              "1.81732e+00",
              "1.66463e+00",
              "1.68092e+00",
              "1.85475e+00",
              "1.95834e+00"
            ]
          },
          "std-obs_xy": {
            "ann": "2.00595e+00",
            "djf": "2.46391e+00",
            "mam": "2.13342e+00",
            "jja": "2.63913e+00",
            "son": "2.31686e+00",
            "CalendarMonths": [
              "2.59576e+00",
              "2.51661e+00",
              "2.34084e+00",
              "2.22530e+00",
              "2.33491e+00",
              "2.70020e+00",
              "2.75700e+00",
              "2.73490e+00",
              "2.52093e+00",
              "2.40951e+00",
              "2.45659e+00",
              "2.53315e+00"
            ]
          },
          "std-obs_xy_devzm": {
            "ann": "1.64066e+00"
          },
          "std-obs_xyt": {
            "ann": "2.51577e+00"
          },
          "std_xy": {
            "ann": "2.45879e+00",
            "djf": "3.14906e+00",
            "mam": "2.73226e+00",
            "jja": "3.04541e+00",
            "son": "2.87762e+00",
            "CalendarMonths": [
              "3.33089e+00",
              "3.18322e+00",
              "3.02637e+00",
              "2.85215e+00",
              "2.87261e+00",
              "3.09019e+00",
              "3.31006e+00",
              "3.23652e+00",
              "3.04863e+00",
              "2.99097e+00",
              "3.16256e+00",
              "3.40294e+00"
            ]
          },
          "std_xy_devzm": {
            "ann": "1.92436e+00"
          },
          "std_xyt": {
            "ann": "3.13052e+00"
          }
        }
      }
    },
    "units": "mm/day"
  },
  "CanCM4": {
    "default": {
      "source": "GPCP-Monthly-3-2",
      "": {
        "InputClimatologyFileName": "cmip5.historical.CanCM4.r1i1p1.mon.pr.198101-200512.AC.v20200426.nc",
        "Global": {
          "bias_xy": {
            "ann": "-5.35337e-02",
            "djf": "-3.12924e-02",
            "mam": "-4.00471e-02",
            "jja": "-2.75896e-02",
            "son": "-1.14628e-01",
            "CalendarMonths": [
              "-3.09921e-02",
              "-2.56221e-02",
              "-6.93328e-02",
              "-4.20869e-02",
              "-1.03619e-02",
              "-1.92844e-02",
              "-1.17036e-02",
              "-5.12684e-02",
              "-1.12487e-01",
              "-1.27240e-01",
              "-1.04563e-01",
              "-3.74621e-02"
            ]
          },
          "cor_xy": {
            "ann": "8.34574e-01",
            "djf": "8.28211e-01",
            "mam": "7.91875e-01",
            "jja": "8.35520e-01",
            "son": "8.05279e-01",
            "CalendarMonths": [
              "8.13470e-01",
              "8.00002e-01",
              "7.97410e-01",
              "7.65652e-01",
              "7.65074e-01",
              "7.87125e-01",
              "8.22792e-01",
              "8.31350e-01",
              "8.07272e-01",
              "7.82998e-01",
              "7.76582e-01",
              "7.93378e-01"
            ]
          },
          "mae_xy": {
            "ann": "7.74094e-01",
            "djf": "9.13198e-01",
            "mam": "8.98531e-01",
            "jja": "9.14631e-01",
            "son": "9.76242e-01",
            "CalendarMonths": [
              "9.77430e-01",
              "9.67317e-01",
              "9.51678e-01",
              "9.90494e-01",
              "1.01565e+00",
              "1.03355e+00",
              "9.83975e-01",
              "9.78783e-01",
              "1.03162e+00",
              "1.04585e+00",
              "1.07235e+00",
              "1.06165e+00"
            ]
          },
          "mean-obs_xy": {
            "ann": "2.81023e+00",
            "djf": "2.78965e+00",
            "mam": "2.78562e+00",
            "jja": "2.85401e+00",
            "son": "2.81134e+00",
            "CalendarMonths": [
              "2.79955e+00",
              "2.76952e+00",
              "2.79466e+00",
              "2.76949e+00",
              "2.79376e+00",
              "2.86752e+00",
              "2.85269e+00",
              "2.84178e+00",
              "2.82533e+00",
              "2.79685e+00",
              "2.81137e+00",
              "2.80023e+00"
            ]
          },
          "mean_xy": {
            "ann": "2.75670e+00",
            "djf": "2.75836e+00",
            "mam": "2.74557e+00",
            "jja": "2.82642e+00",
            "son": "2.69671e+00",
            "CalendarMonths": [
              "2.76856e+00",
              "2.74390e+00",
              "2.72532e+00",
              "2.72740e+00",
              "2.78340e+00",
              "2.84824e+00",
              "2.84099e+00",
              "2.79051e+00",
              "2.71285e+00",
              "2.66961e+00",
              "2.70681e+00",
              "2.76277e+00"
            ]
          },
          "rms_devzm": {
            "ann": "1.12714e+00"
          },
          "rms_xy": {
            "ann": "1.21206e+00",
            "djf": "1.53966e+00",
            "mam": "1.46098e+00",
            "jja": "1.53450e+00",
            "son": "1.56981e+00",
            "CalendarMonths": [
              "1.69802e+00",
              "1.70946e+00",
              "1.61918e+00",
              "1.64185e+00",
              "1.67901e+00",
              "1.77292e+00",
              "1.66288e+00",
              "1.62590e+00",
              "1.67291e+00",
              "1.71732e+00",
              "1.75899e+00",
              "1.76610e+00"
            ]
          },
          "rms_xyt": {
            "ann": "1.69371e+00"
          },
          "rms_y": {
            "ann": "4.45698e-01"
          },
          "rmsc_xy": {
            "ann": "1.21088e+00",
            "djf": "1.53935e+00",
            "mam": "1.46043e+00",
            "jja": "1.53426e+00",
            "son": "1.56562e+00",
            "CalendarMonths": [
              "1.69773e+00",
              "1.70927e+00",
              "1.61770e+00",
              "1.64131e+00",
              "1.67898e+00",
              "1.77281e+00",
              "1.66283e+00",
              "1.62509e+00",
              "1.66912e+00",
              "1.71260e+00",
              "1.75588e+00",
              "1.76570e+00"
            ]
          },
          "std-obs_xy": {
            "ann": "2.00595e+00",
            "djf": "2.46391e+00",
            "mam": "2.13342e+00",
            "jja": "2.63913e+00",
            "son": "2.31686e+00",
            "CalendarMonths": [
              "2.59576e+00",
              "2.51661e+00",
              "2.34084e+00",
              "2.22530e+00",
              "2.33491e+00",
              "2.70020e+00",
              "2.75700e+00",
              "2.73490e+00",
              "2.52093e+00",
              "2.40951e+00",
              "2.45659e+00",
              "2.53315e+00"
            ]
          },
          "std-obs_xy_devzm": {
            "ann": "1.64066e+00"
          },
          "std-obs_xyt": {
            "ann": "2.51577e+00"
          },
          "std_xy": {
            "ann": "2.16914e+00",
            "djf": "2.72103e+00",
            "mam": "2.34929e+00",
            "jja": "2.70621e+00",
            "son": "2.61686e+00",
            "CalendarMonths": [
              "2.88815e+00",
              "2.81431e+00",
              "2.65505e+00",
              "2.50686e+00",
              "2.53359e+00",
              "2.73293e+00",
              "2.82501e+00",
              "2.84879e+00",
              "2.79165e+00",
              "2.71530e+00",
              "2.73706e+00",
              "2.86993e+00"
            ]
          },
          "std_xy_devzm": {
            "ann": "1.68427e+00"
          },
          "std_xyt": {
            "ann": "2.74629e+00"
          }
        }
      }
    },
    "units": "mm/day"
  }
}

Customizing parameters in the mean climate driver

It is possible to override the parameter file from the command line. Use mean_climate_driver.py --help to see all the flag options.

This next cell demonstrates how to change ‘case_id’ and ‘regrid_tool’ on the command line. Changing the ‘case_id’ is helpful because these results will be stored in a folder with that name, separate from other runs.

Both the model data sets and observations are regridded to a 2.5 by 2.5 degree grid before producing statistics. Interpolation of the different grid is conducted by creating a target grid and regridding it.

The two regrid tools available are ‘regrid2’ and ‘xesmf’. ‘regrid2’ is recommended, but ‘xesmf’ must be used with non-rectangular grids. See regrid function for more details.

[9]:
# for conda
"""
import sys
!conda install --yes --prefix {sys.prefix} -c conda-forge xesmf
"""
[9]:
'\nimport sys\n!conda install --yes --prefix {sys.prefix} -c conda-forge xesmf\n'

OR delete the triple quotations on lines 2&5 from this cell to install with pip:

[10]:
# for pip
"""
import sys
!{sys.executable} -m pip install git+https://github.com/pangeo-data/xesmf.git
"""
[10]:
'\nimport sys\n!{sys.executable} -m pip install git+https://github.com/pangeo-data/xesmf.git\n'
[11]:
%%bash
mean_climate_driver.py  -p basic_param.py --case_id 'Ex2' --regrid_tool 'xesmf'
--- prepare mean climate metrics calculation ---
case_id: Ex2
test_data_set: ['ACCESS1-0', 'CanCM4']
realization:
vars: ['pr']
varname_in_test_data: None
reference_data_set: ['all']
target_grid: 2.5x2.5
regrid_tool: xesmf
regrid_tool_ocn: esmf
save_test_clims: False
test_clims_interpolated_output: None
filename_template: cmip5.historical.%(model_version).r1i1p1.mon.%(variable).198101-200512.AC.v20200426.nc
sftlf_filename_template: sftlf_%(model_version).nc
generate_sftlf: True
regions_specs: {'global': {}, 'NHEX': {'domain': {'latitude': (30.0, 90)}}, 'SHEX': {'domain': {'latitude': (-90.0, -30)}}, 'TROPICS': {'domain': {'latitude': (-30.0, 30)}}, '90S50S': {'domain': {'latitude': (-90.0, -50)}}, '50S20S': {'domain': {'latitude': (-50.0, -20)}}, '20S20N': {'domain': {'latitude': (-20.0, 20)}}, '20N50N': {'domain': {'latitude': (20.0, 50)}}, '50N90N': {'domain': {'latitude': (50.0, 90)}}, 'CONUS': {'domain': {'latitude': (24.7, 49.4), 'longitude': (-124.78, -66.92)}}, 'land': {'value': 100}, 'land_NHEX': {'value': 100, 'domain': {'latitude': (30.0, 90)}}, 'land_SHEX': {'value': 100, 'domain': {'latitude': (-90.0, -30)}}, 'land_TROPICS': {'value': 100, 'domain': {'latitude': (-30.0, 30)}}, 'land_CONUS': {'value': 100, 'domain': {'latitude': (24.7, 49.4), 'longitude': (-124.78, -66.92)}}, 'ocean': {'value': 0}, 'ocean_NHEX': {'value': 0, 'domain': {'latitude': (30.0, 90)}}, 'ocean_SHEX': {'value': 0, 'domain': {'latitude': (-90.0, -30)}}, 'ocean_TROPICS': {'value': 0, 'domain': {'latitude': (30.0, 30)}}, 'ocean_50S50N': {'value': 0.0, 'domain': {'latitude': (-50.0, 50)}}, 'ocean_50S20S': {'value': 0.0, 'domain': {'latitude': (-50.0, -20)}}, 'ocean_20S20N': {'value': 0.0, 'domain': {'latitude': (-20.0, 20)}}, 'ocean_20N50N': {'value': 0.0, 'domain': {'latitude': (20.0, 50)}}, 'NAM': {'domain': {'latitude': (20.0, 90), 'longitude': (-180, 180)}}, 'NAO': {'domain': {'latitude': (20.0, 80), 'longitude': (-90, 40)}}, 'EA': {'domain': {'latitude': (20.0, 80), 'longitude': (-90, 40)}}, 'SCA': {'domain': {'latitude': (20.0, 80), 'longitude': (-90, 40)}}, 'SAM': {'domain': {'latitude': (-20.0, -90), 'longitude': (0, 360)}}, 'PSA1': {'domain': {'latitude': (-20.0, -90), 'longitude': (0, 360)}}, 'PSA2': {'domain': {'latitude': (-20.0, -90), 'longitude': (0, 360)}}, 'PNA': {'domain': {'latitude': (20.0, 85), 'longitude': (120, 240)}}, 'NPO': {'domain': {'latitude': (20.0, 85), 'longitude': (120, 240)}}, 'PDO': {'domain': {'latitude': (20.0, 70), 'longitude': (110, 260)}}, 'NPGO': {'domain': {'latitude': (20.0, 70), 'longitude': (110, 260)}}, 'AMO': {'domain': {'latitude': (0.0, 70), 'longitude': (-80, 0)}}, 'AllMW': {'domain': {'latitude': (-40.0, 45.0), 'longitude': (0.0, 360.0)}}, 'AllM': {'domain': {'latitude': (-45.0, 45.0), 'longitude': (0.0, 360.0)}}, 'NAMM': {'domain': {'latitude': (0.0, 45.0), 'longitude': (210.0, 310.0)}}, 'SAMM': {'domain': {'latitude': (-45.0, 0.0), 'longitude': (240.0, 330.0)}}, 'NAFM': {'domain': {'latitude': (0.0, 45.0), 'longitude': (-50.0, 60.0)}}, 'SAFM': {'domain': {'latitude': (-45.0, 0.0), 'longitude': (0.0, 90.0)}}, 'ASM': {'domain': {'latitude': (0.0, 45.0), 'longitude': (60.0, 180.0)}}, 'AUSM': {'domain': {'latitude': (-45.0, 0.0), 'longitude': (90.0, 160.0)}}, 'AIR': {'domain': {'latitude': (7.0, 25.0), 'longitude': (65.0, 85.0)}}, 'AUS': {'domain': {'latitude': (-20.0, -10.0), 'longitude': (120.0, 150.0)}}, 'Sahel': {'domain': {'latitude': (13.0, 18.0), 'longitude': (-10.0, 10.0)}}, 'GoG': {'domain': {'latitude': (0.0, 5.0), 'longitude': (-10.0, 10.0)}}, 'NAmo': {'domain': {'latitude': (20.0, 37.0), 'longitude': (-112.0, -103.0)}}, 'SAmo': {'domain': {'latitude': (-20.0, 2.5), 'longitude': (-65.0, -40.0)}}}
regions: {'pr': ['Global'], 'rlut': ['Global']}
test_data_path: demo_data/CMIP5_demo_clims/
reference_data_path: demo_data/PMP_obs4MIPsClims
custom_observations: demo_data/PMP_obs4MIPsClims/PMP_obs4MIPsClims_catalogue_byVar_v20250305.json
metrics_output_path: demo_output/Ex2
diagnostics_output_path: demo_output/Ex2
debug: False
--- start mean climate metrics calculation ---
varname: pr
level: None
reference_data_set (all):  ['default']
No 'default' reference found, using the only available reference: GPCP-Monthly-3-2 for variable 'pr'
obs_dict (for variable): pr
{'GPCP-Monthly-3-2': {'filename': 'pr_mon_GPCP-Monthly-3-2_RSS_gr_198301-200412_AC_v20250211_interp_2.5x2.5.nc',
                      'template': 'pr/gr/v20250211/pr_mon_GPCP-Monthly-3-2_RSS_gr_198301-200412_AC_v20250211_interp_2.5x2.5.nc'},
 'default': 'GPCP-Monthly-3-2'}
obs_dict (for variable) keys: dict_keys(['GPCP-Monthly-3-2', 'default'])
ref: default
ref_data_full_path: demo_data/PMP_obs4MIPsClims/pr/gr/v20250211/pr_mon_GPCP-Monthly-3-2_RSS_gr_198301-200412_AC_v20250211_interp_2.5x2.5.nc
2025-08-04 12:37:29,554 [WARNING]: dataset.py(open_dataset:120) >> "No time coordinates were found in this dataset to decode. If time coordinates were expected to exist, make sure they are detectable by setting the CF 'axis' or 'standard_name' attribute (e.g., ds['time'].attrs['axis'] = 'T' or ds['time'].attrs['standard_name'] = 'time'). Afterwards, try decoding again with `xcdat.decode_time`."
2025-08-04 12:37:29,554 [WARNING]: dataset.py(open_dataset:120) >> "No time coordinates were found in this dataset to decode. If time coordinates were expected to exist, make sure they are detectable by setting the CF 'axis' or 'standard_name' attribute (e.g., ds['time'].attrs['axis'] = 'T' or ds['time'].attrs['standard_name'] = 'time'). Afterwards, try decoding again with `xcdat.decode_time`."
Adjust units for pr
pr units adjusted to [mm d-1] from [kg m-2 s-1] by 86400 multiplied
units: mm/day
ref_data load_and_regrid done
=================================
model, runs, find_all_realizations: ACCESS1-0 [''] False
-----------------------
model, run: ACCESS1-0
test_data (model in this case) full_path: demo_data/CMIP5_demo_clims/cmip5.historical.ACCESS1-0.r1i1p1.mon.pr.198101-200512.AC.v20200426.nc
2025-08-04 12:37:29,957 [WARNING]: dataset.py(_is_decodable:549) >> 'time' does not have a 'units' attribute set so it could not be decoded. Try setting the 'units' attribute (`ds.{coords.name}.attrs['units']`) and try decoding again.
2025-08-04 12:37:29,957 [WARNING]: dataset.py(_is_decodable:549) >> 'time' does not have a 'units' attribute set so it could not be decoded. Try setting the 'units' attribute (`ds.{coords.name}.attrs['units']`) and try decoding again.
Adjust units for pr
pr units adjusted to [mm d-1] from [kg m-2 s-1] by 86400 multiplied
units: mm/day
load and regrid done
region: Global
plot map done
plot map done
plot map done
plot map done
plot map done
compute metrics start
var: pr
metrics-CALCULATE ANNUAL CYCLE SPACE-TIME RMS, CORRELATIONS and STD
metrics, rms_xyt
metrics, rms_xyt: 1.9344141720039378
metrics, stdObs_xyt
metrics, stdObs_xyt: 2.51577488130445
metrics, std_xyt
metrics, std_xyt: 3.248008596279206
metrics-CALCULATE ANNUAL MEANS
metrics-CALCULATE ANNUAL MEAN BIAS
metrics-CALCULATE ANNUAL MEAN BIAS, bias_xy: 0.26074034921825784
metrics-CALCULATE MSE
metrics-CALCULATE MSE, mae_xy: 0.7564724405551871
metrics-CALCULATE MEAN RMS
metrics-CALCULATE MEAN RMS: rms_xy, rmsc_xy:  1.2838852664089677 1.25715932150558
metrics-CALCULATE MEAN CORR
metrics-CALCULATE MEAN CORR: cor_xy: 0.872553827583345
metrics-CALCULATE ANNUAL OBS AND MOD STD
metrics-CALCULATE ANNUAL OBS AND MOD MEAN
metrics-CALCULATE ANNUAL MEANS
metrics-CALCULATE ANNUAL AND ZONAL MEAN RMS
metrics-CALCULATE ANNUAL MEAN DEVIATION FROM ZONAL MEAN RMS
metrics-CALCULATE ANNUAL MEAN DEVIATION FROM ZONAL MEAN STD
INFO::2025-08-04 12:37::pcmdi_metrics:: Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex2/pr/pr_ACCESS1-0__2.5x2.5_xesmf_metrics_default_Ex2.json
2025-08-04 12:37:52,006 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex2/pr/pr_ACCESS1-0__2.5x2.5_xesmf_metrics_default_Ex2.json
2025-08-04 12:37:52,006 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex2/pr/pr_ACCESS1-0__2.5x2.5_xesmf_metrics_default_Ex2.json
=================================
model, runs, find_all_realizations: CanCM4 [''] False
-----------------------
model, run: CanCM4
test_data (model in this case) full_path: demo_data/CMIP5_demo_clims/cmip5.historical.CanCM4.r1i1p1.mon.pr.198101-200512.AC.v20200426.nc
2025-08-04 12:37:52,013 [WARNING]: dataset.py(_is_decodable:549) >> 'time' does not have a 'units' attribute set so it could not be decoded. Try setting the 'units' attribute (`ds.{coords.name}.attrs['units']`) and try decoding again.
2025-08-04 12:37:52,013 [WARNING]: dataset.py(_is_decodable:549) >> 'time' does not have a 'units' attribute set so it could not be decoded. Try setting the 'units' attribute (`ds.{coords.name}.attrs['units']`) and try decoding again.
Adjust units for pr
pr units adjusted to [mm d-1] from [kg m-2 s-1] by 86400 multiplied
units: mm/day
load and regrid done
region: Global
plot map done
plot map done
plot map done
plot map done
plot map done
compute metrics start
var: pr
metrics-CALCULATE ANNUAL CYCLE SPACE-TIME RMS, CORRELATIONS and STD
metrics, rms_xyt
metrics, rms_xyt: 1.683077506468278
metrics, stdObs_xyt
metrics, stdObs_xyt: 2.51577488130445
metrics, std_xyt
metrics, std_xyt: 2.733759999283311
metrics-CALCULATE ANNUAL MEANS
metrics-CALCULATE ANNUAL MEAN BIAS
metrics-CALCULATE ANNUAL MEAN BIAS, bias_xy: -0.058910717845545676
metrics-CALCULATE MSE
metrics-CALCULATE MSE, mae_xy: 0.7726931289903871
metrics-CALCULATE MEAN RMS
metrics-CALCULATE MEAN RMS: rms_xy, rmsc_xy:  1.2070583943853663 1.2056687503112526
metrics-CALCULATE MEAN CORR
metrics-CALCULATE MEAN CORR: cor_xy: 0.8354938765188585
metrics-CALCULATE ANNUAL OBS AND MOD STD
metrics-CALCULATE ANNUAL OBS AND MOD MEAN
metrics-CALCULATE ANNUAL MEANS
metrics-CALCULATE ANNUAL AND ZONAL MEAN RMS
metrics-CALCULATE ANNUAL MEAN DEVIATION FROM ZONAL MEAN RMS
metrics-CALCULATE ANNUAL MEAN DEVIATION FROM ZONAL MEAN STD
INFO::2025-08-04 12:38::pcmdi_metrics:: Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex2/pr/pr_CanCM4__2.5x2.5_xesmf_metrics_default_Ex2.json
2025-08-04 12:38:11,982 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex2/pr/pr_CanCM4__2.5x2.5_xesmf_metrics_default_Ex2.json
2025-08-04 12:38:11,982 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex2/pr/pr_CanCM4__2.5x2.5_xesmf_metrics_default_Ex2.json
INFO::2025-08-04 12:38::pcmdi_metrics:: Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex2/pr_2.5x2.5_xesmf_metrics_Ex2.json
2025-08-04 12:38:11,984 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex2/pr_2.5x2.5_xesmf_metrics_Ex2.json
2025-08-04 12:38:11,984 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex2/pr_2.5x2.5_xesmf_metrics_Ex2.json
pmp mean clim driver completed

Specifying the model

It is easy to change the models or variables in the analysis. Whatever variables you choose must be present in both your model files and obervations. This example shows how to specify a variable while running only the ACCESS1-0 model.

[12]:
%%bash
mean_climate_driver.py -p basic_param.py --case_id 'Ex3' --test_data_set 'ACCESS1-0' --vars "rlut"
--- prepare mean climate metrics calculation ---
case_id: Ex3
test_data_set: ['ACCESS1-0']
realization:
vars: ['rlut']
varname_in_test_data: None
reference_data_set: ['all']
target_grid: 2.5x2.5
regrid_tool: regrid2
regrid_tool_ocn: esmf
save_test_clims: False
test_clims_interpolated_output: None
filename_template: cmip5.historical.%(model_version).r1i1p1.mon.%(variable).198101-200512.AC.v20200426.nc
sftlf_filename_template: sftlf_%(model_version).nc
generate_sftlf: True
regions_specs: {'global': {}, 'NHEX': {'domain': {'latitude': (30.0, 90)}}, 'SHEX': {'domain': {'latitude': (-90.0, -30)}}, 'TROPICS': {'domain': {'latitude': (-30.0, 30)}}, '90S50S': {'domain': {'latitude': (-90.0, -50)}}, '50S20S': {'domain': {'latitude': (-50.0, -20)}}, '20S20N': {'domain': {'latitude': (-20.0, 20)}}, '20N50N': {'domain': {'latitude': (20.0, 50)}}, '50N90N': {'domain': {'latitude': (50.0, 90)}}, 'CONUS': {'domain': {'latitude': (24.7, 49.4), 'longitude': (-124.78, -66.92)}}, 'land': {'value': 100}, 'land_NHEX': {'value': 100, 'domain': {'latitude': (30.0, 90)}}, 'land_SHEX': {'value': 100, 'domain': {'latitude': (-90.0, -30)}}, 'land_TROPICS': {'value': 100, 'domain': {'latitude': (-30.0, 30)}}, 'land_CONUS': {'value': 100, 'domain': {'latitude': (24.7, 49.4), 'longitude': (-124.78, -66.92)}}, 'ocean': {'value': 0}, 'ocean_NHEX': {'value': 0, 'domain': {'latitude': (30.0, 90)}}, 'ocean_SHEX': {'value': 0, 'domain': {'latitude': (-90.0, -30)}}, 'ocean_TROPICS': {'value': 0, 'domain': {'latitude': (30.0, 30)}}, 'ocean_50S50N': {'value': 0.0, 'domain': {'latitude': (-50.0, 50)}}, 'ocean_50S20S': {'value': 0.0, 'domain': {'latitude': (-50.0, -20)}}, 'ocean_20S20N': {'value': 0.0, 'domain': {'latitude': (-20.0, 20)}}, 'ocean_20N50N': {'value': 0.0, 'domain': {'latitude': (20.0, 50)}}, 'NAM': {'domain': {'latitude': (20.0, 90), 'longitude': (-180, 180)}}, 'NAO': {'domain': {'latitude': (20.0, 80), 'longitude': (-90, 40)}}, 'EA': {'domain': {'latitude': (20.0, 80), 'longitude': (-90, 40)}}, 'SCA': {'domain': {'latitude': (20.0, 80), 'longitude': (-90, 40)}}, 'SAM': {'domain': {'latitude': (-20.0, -90), 'longitude': (0, 360)}}, 'PSA1': {'domain': {'latitude': (-20.0, -90), 'longitude': (0, 360)}}, 'PSA2': {'domain': {'latitude': (-20.0, -90), 'longitude': (0, 360)}}, 'PNA': {'domain': {'latitude': (20.0, 85), 'longitude': (120, 240)}}, 'NPO': {'domain': {'latitude': (20.0, 85), 'longitude': (120, 240)}}, 'PDO': {'domain': {'latitude': (20.0, 70), 'longitude': (110, 260)}}, 'NPGO': {'domain': {'latitude': (20.0, 70), 'longitude': (110, 260)}}, 'AMO': {'domain': {'latitude': (0.0, 70), 'longitude': (-80, 0)}}, 'AllMW': {'domain': {'latitude': (-40.0, 45.0), 'longitude': (0.0, 360.0)}}, 'AllM': {'domain': {'latitude': (-45.0, 45.0), 'longitude': (0.0, 360.0)}}, 'NAMM': {'domain': {'latitude': (0.0, 45.0), 'longitude': (210.0, 310.0)}}, 'SAMM': {'domain': {'latitude': (-45.0, 0.0), 'longitude': (240.0, 330.0)}}, 'NAFM': {'domain': {'latitude': (0.0, 45.0), 'longitude': (-50.0, 60.0)}}, 'SAFM': {'domain': {'latitude': (-45.0, 0.0), 'longitude': (0.0, 90.0)}}, 'ASM': {'domain': {'latitude': (0.0, 45.0), 'longitude': (60.0, 180.0)}}, 'AUSM': {'domain': {'latitude': (-45.0, 0.0), 'longitude': (90.0, 160.0)}}, 'AIR': {'domain': {'latitude': (7.0, 25.0), 'longitude': (65.0, 85.0)}}, 'AUS': {'domain': {'latitude': (-20.0, -10.0), 'longitude': (120.0, 150.0)}}, 'Sahel': {'domain': {'latitude': (13.0, 18.0), 'longitude': (-10.0, 10.0)}}, 'GoG': {'domain': {'latitude': (0.0, 5.0), 'longitude': (-10.0, 10.0)}}, 'NAmo': {'domain': {'latitude': (20.0, 37.0), 'longitude': (-112.0, -103.0)}}, 'SAmo': {'domain': {'latitude': (-20.0, 2.5), 'longitude': (-65.0, -40.0)}}}
regions: {'pr': ['Global'], 'rlut': ['Global']}
test_data_path: demo_data/CMIP5_demo_clims/
reference_data_path: demo_data/PMP_obs4MIPsClims
custom_observations: demo_data/PMP_obs4MIPsClims/PMP_obs4MIPsClims_catalogue_byVar_v20250305.json
metrics_output_path: demo_output/Ex3
diagnostics_output_path: demo_output/Ex3
debug: False
--- start mean climate metrics calculation ---
varname: rlut
level: None
reference_data_set (all):  ['default']
No 'default' reference found, using the only available reference: CERES-EBAF-4-2 for variable 'rlut'
obs_dict (for variable): rlut
{'CERES-EBAF-4-2': {'filename': 'rlut_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc',
                    'template': 'rlut/gr/v20250213/rlut_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc'},
 'default': 'CERES-EBAF-4-2'}
obs_dict (for variable) keys: dict_keys(['CERES-EBAF-4-2', 'default'])
ref: default
ref_data_full_path: demo_data/PMP_obs4MIPsClims/rlut/gr/v20250213/rlut_mon_CERES-EBAF-4-2_RSS_gr_200101-200412_AC_v20250213_2.5x2.5.nc
2025-08-04 12:38:19,191 [WARNING]: dataset.py(open_dataset:120) >> "No time coordinates were found in this dataset to decode. If time coordinates were expected to exist, make sure they are detectable by setting the CF 'axis' or 'standard_name' attribute (e.g., ds['time'].attrs['axis'] = 'T' or ds['time'].attrs['standard_name'] = 'time'). Afterwards, try decoding again with `xcdat.decode_time`."
2025-08-04 12:38:19,191 [WARNING]: dataset.py(open_dataset:120) >> "No time coordinates were found in this dataset to decode. If time coordinates were expected to exist, make sure they are detectable by setting the CF 'axis' or 'standard_name' attribute (e.g., ds['time'].attrs['axis'] = 'T' or ds['time'].attrs['standard_name'] = 'time'). Afterwards, try decoding again with `xcdat.decode_time`."
'units'
units:
ref_data load_and_regrid done
=================================
model, runs, find_all_realizations: ACCESS1-0 [''] False
-----------------------
model, run: ACCESS1-0
test_data (model in this case) full_path: demo_data/CMIP5_demo_clims/cmip5.historical.ACCESS1-0.r1i1p1.mon.rlut.198101-200512.AC.v20200426.nc
2025-08-04 12:38:19,410 [WARNING]: dataset.py(_is_decodable:549) >> 'time' does not have a 'units' attribute set so it could not be decoded. Try setting the 'units' attribute (`ds.{coords.name}.attrs['units']`) and try decoding again.
2025-08-04 12:38:19,410 [WARNING]: dataset.py(_is_decodable:549) >> 'time' does not have a 'units' attribute set so it could not be decoded. Try setting the 'units' attribute (`ds.{coords.name}.attrs['units']`) and try decoding again.
'units'
units:
load and regrid done
region: Global
plot map done
plot map done
plot map done
plot map done
plot map done
compute metrics start
var: rlut
metrics-CALCULATE ANNUAL CYCLE SPACE-TIME RMS, CORRELATIONS and STD
metrics, rms_xyt
metrics, rms_xyt: 11.791448148672695
metrics, stdObs_xyt
metrics, stdObs_xyt: 33.71355661656618
metrics, std_xyt
metrics, std_xyt: 36.43801778367986
metrics-CALCULATE ANNUAL MEANS
metrics-CALCULATE ANNUAL MEAN BIAS
metrics-CALCULATE ANNUAL MEAN BIAS, bias_xy: 1.0915953538209389
metrics-CALCULATE MSE
metrics-CALCULATE MSE, mae_xy: 5.65309518968484
metrics-CALCULATE MEAN RMS
metrics-CALCULATE MEAN RMS: rms_xy, rmsc_xy:  7.933463164396582 7.858005940717656
metrics-CALCULATE MEAN CORR
metrics-CALCULATE MEAN CORR: cor_xy: 0.9700363580064795
metrics-CALCULATE ANNUAL OBS AND MOD STD
metrics-CALCULATE ANNUAL OBS AND MOD MEAN
metrics-CALCULATE ANNUAL MEANS
metrics-CALCULATE ANNUAL AND ZONAL MEAN RMS
metrics-CALCULATE ANNUAL MEAN DEVIATION FROM ZONAL MEAN RMS
metrics-CALCULATE ANNUAL MEAN DEVIATION FROM ZONAL MEAN STD
INFO::2025-08-04 12:38::pcmdi_metrics:: Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex3/rlut/rlut_ACCESS1-0__2.5x2.5_regrid2_metrics_default_Ex3.json
2025-08-04 12:38:35,376 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex3/rlut/rlut_ACCESS1-0__2.5x2.5_regrid2_metrics_default_Ex3.json
2025-08-04 12:38:35,376 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex3/rlut/rlut_ACCESS1-0__2.5x2.5_regrid2_metrics_default_Ex3.json
INFO::2025-08-04 12:38::pcmdi_metrics:: Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex3/rlut_2.5x2.5_regrid2_metrics_Ex3.json
2025-08-04 12:38:35,377 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex3/rlut_2.5x2.5_regrid2_metrics_Ex3.json
2025-08-04 12:38:35,377 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex3/rlut_2.5x2.5_regrid2_metrics_Ex3.json
pmp mean clim driver completed

Specifying the observation

This section demonstrates use of alternative reference dataset, which was downloaded from Demo 0. There are several sets of observations available in this alternative dataset. This case uses the ‘alternate1’ observations for zg with the flag reference_data_set. The test and observations path are specified with test_data_path and reference_data_path, respectively.

To see which datasets are the default and which are alternates, check out pcmdi_metrics/doc/obs_info_dictionary.json.

[13]:
# Download https://raw.githubusercontent.com/PCMDI/pcmdi_metrics/refs/heads/main/doc/obs_info_dictionary.json file
!wget https://raw.githubusercontent.com/PCMDI/pcmdi_metrics/refs/heads/main/doc/obs_info_dictionary.json
/bin/bash: wget: command not found
[14]:
!mean_climate_driver.py -p basic_param.py \
--case_id 'Ex3_2' \
--vars 'zg-500' \
--test_data_set 'ACCESS1-0' \
--custom_observations 'obs_info_dictionary.json' \
--reference_data_path {demo_data_directory}/obs4MIPs_PCMDI_clims \
--reference_data_set "alternate1"
--- prepare mean climate metrics calculation ---
case_id: Ex3_2
test_data_set: ['ACCESS1-0']
realization:
vars: ['zg-500']
varname_in_test_data: None
reference_data_set: ['alternate1']
target_grid: 2.5x2.5
regrid_tool: regrid2
regrid_tool_ocn: esmf
save_test_clims: False
test_clims_interpolated_output: None
filename_template: cmip5.historical.%(model_version).r1i1p1.mon.%(variable).198101-200512.AC.v20200426.nc
sftlf_filename_template: sftlf_%(model_version).nc
generate_sftlf: True
regions_specs: {'global': {}, 'NHEX': {'domain': {'latitude': (30.0, 90)}}, 'SHEX': {'domain': {'latitude': (-90.0, -30)}}, 'TROPICS': {'domain': {'latitude': (-30.0, 30)}}, '90S50S': {'domain': {'latitude': (-90.0, -50)}}, '50S20S': {'domain': {'latitude': (-50.0, -20)}}, '20S20N': {'domain': {'latitude': (-20.0, 20)}}, '20N50N': {'domain': {'latitude': (20.0, 50)}}, '50N90N': {'domain': {'latitude': (50.0, 90)}}, 'CONUS': {'domain': {'latitude': (24.7, 49.4), 'longitude': (-124.78, -66.92)}}, 'land': {'value': 100}, 'land_NHEX': {'value': 100, 'domain': {'latitude': (30.0, 90)}}, 'land_SHEX': {'value': 100, 'domain': {'latitude': (-90.0, -30)}}, 'land_TROPICS': {'value': 100, 'domain': {'latitude': (-30.0, 30)}}, 'land_CONUS': {'value': 100, 'domain': {'latitude': (24.7, 49.4), 'longitude': (-124.78, -66.92)}}, 'ocean': {'value': 0}, 'ocean_NHEX': {'value': 0, 'domain': {'latitude': (30.0, 90)}}, 'ocean_SHEX': {'value': 0, 'domain': {'latitude': (-90.0, -30)}}, 'ocean_TROPICS': {'value': 0, 'domain': {'latitude': (30.0, 30)}}, 'ocean_50S50N': {'value': 0.0, 'domain': {'latitude': (-50.0, 50)}}, 'ocean_50S20S': {'value': 0.0, 'domain': {'latitude': (-50.0, -20)}}, 'ocean_20S20N': {'value': 0.0, 'domain': {'latitude': (-20.0, 20)}}, 'ocean_20N50N': {'value': 0.0, 'domain': {'latitude': (20.0, 50)}}, 'NAM': {'domain': {'latitude': (20.0, 90), 'longitude': (-180, 180)}}, 'NAO': {'domain': {'latitude': (20.0, 80), 'longitude': (-90, 40)}}, 'EA': {'domain': {'latitude': (20.0, 80), 'longitude': (-90, 40)}}, 'SCA': {'domain': {'latitude': (20.0, 80), 'longitude': (-90, 40)}}, 'SAM': {'domain': {'latitude': (-20.0, -90), 'longitude': (0, 360)}}, 'PSA1': {'domain': {'latitude': (-20.0, -90), 'longitude': (0, 360)}}, 'PSA2': {'domain': {'latitude': (-20.0, -90), 'longitude': (0, 360)}}, 'PNA': {'domain': {'latitude': (20.0, 85), 'longitude': (120, 240)}}, 'NPO': {'domain': {'latitude': (20.0, 85), 'longitude': (120, 240)}}, 'PDO': {'domain': {'latitude': (20.0, 70), 'longitude': (110, 260)}}, 'NPGO': {'domain': {'latitude': (20.0, 70), 'longitude': (110, 260)}}, 'AMO': {'domain': {'latitude': (0.0, 70), 'longitude': (-80, 0)}}, 'AllMW': {'domain': {'latitude': (-40.0, 45.0), 'longitude': (0.0, 360.0)}}, 'AllM': {'domain': {'latitude': (-45.0, 45.0), 'longitude': (0.0, 360.0)}}, 'NAMM': {'domain': {'latitude': (0.0, 45.0), 'longitude': (210.0, 310.0)}}, 'SAMM': {'domain': {'latitude': (-45.0, 0.0), 'longitude': (240.0, 330.0)}}, 'NAFM': {'domain': {'latitude': (0.0, 45.0), 'longitude': (-50.0, 60.0)}}, 'SAFM': {'domain': {'latitude': (-45.0, 0.0), 'longitude': (0.0, 90.0)}}, 'ASM': {'domain': {'latitude': (0.0, 45.0), 'longitude': (60.0, 180.0)}}, 'AUSM': {'domain': {'latitude': (-45.0, 0.0), 'longitude': (90.0, 160.0)}}, 'AIR': {'domain': {'latitude': (7.0, 25.0), 'longitude': (65.0, 85.0)}}, 'AUS': {'domain': {'latitude': (-20.0, -10.0), 'longitude': (120.0, 150.0)}}, 'Sahel': {'domain': {'latitude': (13.0, 18.0), 'longitude': (-10.0, 10.0)}}, 'GoG': {'domain': {'latitude': (0.0, 5.0), 'longitude': (-10.0, 10.0)}}, 'NAmo': {'domain': {'latitude': (20.0, 37.0), 'longitude': (-112.0, -103.0)}}, 'SAmo': {'domain': {'latitude': (-20.0, 2.5), 'longitude': (-65.0, -40.0)}}}
regions: {'pr': ['Global'], 'rlut': ['Global']}
test_data_path: demo_data/CMIP5_demo_clims/
reference_data_path: demo_data/obs4MIPs_PCMDI_clims
custom_observations: obs_info_dictionary.json
metrics_output_path: demo_output/Ex3_2
diagnostics_output_path: demo_output/Ex3_2
debug: False
Traceback (most recent call last):
  File "/Users/lee1043/miniforge3/envs/pmp_devel_20250715/bin/mean_climate_driver.py", line 139, in <module>
    with open(obs_file_path) as fo:
FileNotFoundError: [Errno 2] No such file or directory: 'obs_info_dictionary.json'

Using custom regions

The predefined regions that can be set by the --regions flag can be found in default_regions.py. By default, the mean climate driver will run “global”, “NHEX”, “SHEX”, and “TROPICS”.

This example specifies customized additional regions for the analysis. Region can be named as “MyDomain”, “MyDomain_ocean” (for over ocean only) or “MyDomain_land” (for over land only). The driver will recognize “_ocean” or “_land” keywords to mask out land or ocean.

[15]:
%%bash
mean_climate_driver.py -p basic_param.py \
--case_id 'Ex4' --regions '{"pr": ["MyDomain_ocean"]}' \
--regions_specs "{'MyDomain_ocean': {'domain': {'latitude': (-20, 40), 'longitude':(90, 260)}}}"
--- prepare mean climate metrics calculation ---
case_id: Ex4
test_data_set: ['ACCESS1-0', 'CanCM4']
realization:
vars: ['pr']
varname_in_test_data: None
reference_data_set: ['all']
target_grid: 2.5x2.5
regrid_tool: regrid2
regrid_tool_ocn: esmf
save_test_clims: False
test_clims_interpolated_output: None
filename_template: cmip5.historical.%(model_version).r1i1p1.mon.%(variable).198101-200512.AC.v20200426.nc
sftlf_filename_template: sftlf_%(model_version).nc
generate_sftlf: True
regions_specs: {'MyDomain_ocean': {'domain': {'latitude': (-20, 40), 'longitude': (90, 260)}}}
regions: {'pr': ['MyDomain_ocean']}
test_data_path: demo_data/CMIP5_demo_clims/
reference_data_path: demo_data/PMP_obs4MIPsClims
custom_observations: demo_data/PMP_obs4MIPsClims/PMP_obs4MIPsClims_catalogue_byVar_v20250305.json
metrics_output_path: demo_output/Ex4
diagnostics_output_path: demo_output/Ex4
debug: False
--- start mean climate metrics calculation ---
varname: pr
level: None
reference_data_set (all):  ['default']
No 'default' reference found, using the only available reference: GPCP-Monthly-3-2 for variable 'pr'
obs_dict (for variable): pr
{'GPCP-Monthly-3-2': {'filename': 'pr_mon_GPCP-Monthly-3-2_RSS_gr_198301-200412_AC_v20250211_interp_2.5x2.5.nc',
                      'template': 'pr/gr/v20250211/pr_mon_GPCP-Monthly-3-2_RSS_gr_198301-200412_AC_v20250211_interp_2.5x2.5.nc'},
 'default': 'GPCP-Monthly-3-2'}
obs_dict (for variable) keys: dict_keys(['GPCP-Monthly-3-2', 'default'])
ref: default
ref_data_full_path: demo_data/PMP_obs4MIPsClims/pr/gr/v20250211/pr_mon_GPCP-Monthly-3-2_RSS_gr_198301-200412_AC_v20250211_interp_2.5x2.5.nc
2025-08-04 12:38:49,375 [WARNING]: dataset.py(open_dataset:120) >> "No time coordinates were found in this dataset to decode. If time coordinates were expected to exist, make sure they are detectable by setting the CF 'axis' or 'standard_name' attribute (e.g., ds['time'].attrs['axis'] = 'T' or ds['time'].attrs['standard_name'] = 'time'). Afterwards, try decoding again with `xcdat.decode_time`."
2025-08-04 12:38:49,375 [WARNING]: dataset.py(open_dataset:120) >> "No time coordinates were found in this dataset to decode. If time coordinates were expected to exist, make sure they are detectable by setting the CF 'axis' or 'standard_name' attribute (e.g., ds['time'].attrs['axis'] = 'T' or ds['time'].attrs['standard_name'] = 'time'). Afterwards, try decoding again with `xcdat.decode_time`."
Adjust units for pr
pr units adjusted to [mm d-1] from [kg m-2 s-1] by 86400 multiplied
units: mm/day
ref_data load_and_regrid done
=================================
model, runs, find_all_realizations: ACCESS1-0 [''] False
-----------------------
model, run: ACCESS1-0
test_data (model in this case) full_path: demo_data/CMIP5_demo_clims/cmip5.historical.ACCESS1-0.r1i1p1.mon.pr.198101-200512.AC.v20200426.nc
2025-08-04 12:38:49,597 [WARNING]: dataset.py(_is_decodable:549) >> 'time' does not have a 'units' attribute set so it could not be decoded. Try setting the 'units' attribute (`ds.{coords.name}.attrs['units']`) and try decoding again.
2025-08-04 12:38:49,597 [WARNING]: dataset.py(_is_decodable:549) >> 'time' does not have a 'units' attribute set so it could not be decoded. Try setting the 'units' attribute (`ds.{coords.name}.attrs['units']`) and try decoding again.
Adjust units for pr
pr units adjusted to [mm d-1] from [kg m-2 s-1] by 86400 multiplied
units: mm/day
load and regrid done
region: MyDomain_ocean
mask done
spatial subset done
plot map done
plot map done
plot map done
plot map done
plot map done
compute metrics start
var: pr
metrics-CALCULATE ANNUAL CYCLE SPACE-TIME RMS, CORRELATIONS and STD
metrics, rms_xyt
metrics, rms_xyt: 2.6861180300813765
metrics, stdObs_xyt
metrics, stdObs_xyt: 3.0943294252755345
metrics, std_xyt
metrics, std_xyt: 4.377531682374096
metrics-CALCULATE ANNUAL MEANS
metrics-CALCULATE ANNUAL MEAN BIAS
metrics-CALCULATE ANNUAL MEAN BIAS, bias_xy: 0.7067868940811111
metrics-CALCULATE MSE
metrics-CALCULATE MSE, mae_xy: 1.2139268993457806
metrics-CALCULATE MEAN RMS
metrics-CALCULATE MEAN RMS: rms_xy, rmsc_xy:  1.7797276074675437 1.6333654346585524
metrics-CALCULATE MEAN CORR
metrics-CALCULATE MEAN CORR: cor_xy: 0.8867825252530882
metrics-CALCULATE ANNUAL OBS AND MOD STD
metrics-CALCULATE ANNUAL OBS AND MOD MEAN
metrics-CALCULATE ANNUAL MEANS
metrics-CALCULATE ANNUAL AND ZONAL MEAN RMS
metrics-CALCULATE ANNUAL MEAN DEVIATION FROM ZONAL MEAN RMS
metrics-CALCULATE ANNUAL MEAN DEVIATION FROM ZONAL MEAN STD
INFO::2025-08-04 12:39::pcmdi_metrics:: Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex4/pr/pr_ACCESS1-0__2.5x2.5_regrid2_metrics_default_Ex4.json
2025-08-04 12:39:04,380 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex4/pr/pr_ACCESS1-0__2.5x2.5_regrid2_metrics_default_Ex4.json
2025-08-04 12:39:04,380 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex4/pr/pr_ACCESS1-0__2.5x2.5_regrid2_metrics_default_Ex4.json
=================================
model, runs, find_all_realizations: CanCM4 [''] False
-----------------------
model, run: CanCM4
test_data (model in this case) full_path: demo_data/CMIP5_demo_clims/cmip5.historical.CanCM4.r1i1p1.mon.pr.198101-200512.AC.v20200426.nc
2025-08-04 12:39:04,386 [WARNING]: dataset.py(_is_decodable:549) >> 'time' does not have a 'units' attribute set so it could not be decoded. Try setting the 'units' attribute (`ds.{coords.name}.attrs['units']`) and try decoding again.
2025-08-04 12:39:04,386 [WARNING]: dataset.py(_is_decodable:549) >> 'time' does not have a 'units' attribute set so it could not be decoded. Try setting the 'units' attribute (`ds.{coords.name}.attrs['units']`) and try decoding again.
Adjust units for pr
pr units adjusted to [mm d-1] from [kg m-2 s-1] by 86400 multiplied
units: mm/day
load and regrid done
region: MyDomain_ocean
mask done
spatial subset done
plot map done
plot map done
plot map done
plot map done
plot map done
compute metrics start
var: pr
metrics-CALCULATE ANNUAL CYCLE SPACE-TIME RMS, CORRELATIONS and STD
metrics, rms_xyt
metrics, rms_xyt: 2.2329921410578577
metrics, stdObs_xyt
metrics, stdObs_xyt: 3.0943294252755345
metrics, std_xyt
metrics, std_xyt: 3.7353502078628646
metrics-CALCULATE ANNUAL MEANS
metrics-CALCULATE ANNUAL MEAN BIAS
metrics-CALCULATE ANNUAL MEAN BIAS, bias_xy: 0.6094173427413772
metrics-CALCULATE MSE
metrics-CALCULATE MSE, mae_xy: 1.1156627939627723
metrics-CALCULATE MEAN RMS
metrics-CALCULATE MEAN RMS: rms_xy, rmsc_xy:  1.517734986814394 1.3900107886511264
metrics-CALCULATE MEAN CORR
metrics-CALCULATE MEAN CORR: cor_xy: 0.8764736221859271
metrics-CALCULATE ANNUAL OBS AND MOD STD
metrics-CALCULATE ANNUAL OBS AND MOD MEAN
metrics-CALCULATE ANNUAL MEANS
metrics-CALCULATE ANNUAL AND ZONAL MEAN RMS
metrics-CALCULATE ANNUAL MEAN DEVIATION FROM ZONAL MEAN RMS
metrics-CALCULATE ANNUAL MEAN DEVIATION FROM ZONAL MEAN STD
INFO::2025-08-04 12:39::pcmdi_metrics:: Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex4/pr/pr_CanCM4__2.5x2.5_regrid2_metrics_default_Ex4.json
2025-08-04 12:39:18,818 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex4/pr/pr_CanCM4__2.5x2.5_regrid2_metrics_default_Ex4.json
2025-08-04 12:39:18,818 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex4/pr/pr_CanCM4__2.5x2.5_regrid2_metrics_default_Ex4.json
INFO::2025-08-04 12:39::pcmdi_metrics:: Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex4/pr_2.5x2.5_regrid2_metrics_Ex4.json
2025-08-04 12:39:18,819 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex4/pr_2.5x2.5_regrid2_metrics_Ex4.json
2025-08-04 12:39:18,819 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex4/pr_2.5x2.5_regrid2_metrics_Ex4.json
pmp mean clim driver completed
[16]:
# path to images
image_path_djf = os.path.join(demo_output_directory,"Ex4/pr/pr_ACCESS1-0__interpolated_regrid2_MyDomain_ocean_DJF_Ex4.png")
image_path_jja = os.path.join(demo_output_directory,"Ex4/pr/pr_ACCESS1-0__interpolated_regrid2_MyDomain_ocean_JJA_Ex4.png")

# display images
fig, ax = plt.subplots(1,2); ax[0].axis('off'); ax[1].axis('off')
ax[0].imshow(mpimg.imread(image_path_djf))
ax[1].imshow(mpimg.imread(image_path_jja))
[16]:
<matplotlib.image.AxesImage at 0x1afdac4c0>
../_images/examples_Demo_1b_mean_climate_28_1.png

The region value None is another way of indicating “global”

Custom domain is controlled by the variable regions_specs in the parameter file or command line. For example, a custom region for Antarctica over land could be defined with regions_specs = {'ANT': {'value': 100, 'domain': {'latitude': (-90, -60)}}} in the parameter file. value indicate masking, 100: land only, 0: ocean only.

The command to use the custom region would look like --regions '{"rlut": ["ANT"]}' in the command line or regions = {"rlut": ["ANT"]} in the parameter file.

Land/sea masks

Land/Sea masking is required for some regions (e.g. “land”). This is controlled by variables sftlf_filename_template and generate_sftlf. The metrics package expects the land/sea mask files to be located with the model data under a fixed field variable (‘fx’) with a file name that follows the pattern in sftlf_filename_template. The example data does not come with a land/sea mask, so we set generate_sftlf to True in the basic parameter file to have the PMP generate a land/sea mask where 0 represents ocean and 100 represents land.

Extract vertical level and customize observations

This example shows how to extract a vertical level from a 4-D variable. The 500 hPa level of zg is specified by adding “_500” to zg.

There are several sets of observations available in the standard PCMDI set. This case uses the ‘alternate1’ observations for zg with the flag reference_data_set. The test and observations path are specified with test_data_path and reference_data_path, respectively.

To see which datasets are the default and which are alternates, check out pcmdi_metrics/doc/obs_info_dictionary.json.

[17]:
!mean_climate_driver.py -p basic_param.py \
--case_id 'Ex5' \
--vars 'zg_500' \
--test_data_set 'CanCM4' \
--custom_observations 'obs_info_dictionary.json' \
--reference_data_path {demo_data_directory}/obs4MIPs_PCMDI_clims \
--reference_data_set "alternate1"
--- prepare mean climate metrics calculation ---
case_id: Ex5
test_data_set: ['CanCM4']
realization:
vars: ['zg_500']
varname_in_test_data: None
reference_data_set: ['alternate1']
target_grid: 2.5x2.5
regrid_tool: regrid2
regrid_tool_ocn: esmf
save_test_clims: False
test_clims_interpolated_output: None
filename_template: cmip5.historical.%(model_version).r1i1p1.mon.%(variable).198101-200512.AC.v20200426.nc
sftlf_filename_template: sftlf_%(model_version).nc
generate_sftlf: True
regions_specs: {'global': {}, 'NHEX': {'domain': {'latitude': (30.0, 90)}}, 'SHEX': {'domain': {'latitude': (-90.0, -30)}}, 'TROPICS': {'domain': {'latitude': (-30.0, 30)}}, '90S50S': {'domain': {'latitude': (-90.0, -50)}}, '50S20S': {'domain': {'latitude': (-50.0, -20)}}, '20S20N': {'domain': {'latitude': (-20.0, 20)}}, '20N50N': {'domain': {'latitude': (20.0, 50)}}, '50N90N': {'domain': {'latitude': (50.0, 90)}}, 'CONUS': {'domain': {'latitude': (24.7, 49.4), 'longitude': (-124.78, -66.92)}}, 'land': {'value': 100}, 'land_NHEX': {'value': 100, 'domain': {'latitude': (30.0, 90)}}, 'land_SHEX': {'value': 100, 'domain': {'latitude': (-90.0, -30)}}, 'land_TROPICS': {'value': 100, 'domain': {'latitude': (-30.0, 30)}}, 'land_CONUS': {'value': 100, 'domain': {'latitude': (24.7, 49.4), 'longitude': (-124.78, -66.92)}}, 'ocean': {'value': 0}, 'ocean_NHEX': {'value': 0, 'domain': {'latitude': (30.0, 90)}}, 'ocean_SHEX': {'value': 0, 'domain': {'latitude': (-90.0, -30)}}, 'ocean_TROPICS': {'value': 0, 'domain': {'latitude': (30.0, 30)}}, 'ocean_50S50N': {'value': 0.0, 'domain': {'latitude': (-50.0, 50)}}, 'ocean_50S20S': {'value': 0.0, 'domain': {'latitude': (-50.0, -20)}}, 'ocean_20S20N': {'value': 0.0, 'domain': {'latitude': (-20.0, 20)}}, 'ocean_20N50N': {'value': 0.0, 'domain': {'latitude': (20.0, 50)}}, 'NAM': {'domain': {'latitude': (20.0, 90), 'longitude': (-180, 180)}}, 'NAO': {'domain': {'latitude': (20.0, 80), 'longitude': (-90, 40)}}, 'EA': {'domain': {'latitude': (20.0, 80), 'longitude': (-90, 40)}}, 'SCA': {'domain': {'latitude': (20.0, 80), 'longitude': (-90, 40)}}, 'SAM': {'domain': {'latitude': (-20.0, -90), 'longitude': (0, 360)}}, 'PSA1': {'domain': {'latitude': (-20.0, -90), 'longitude': (0, 360)}}, 'PSA2': {'domain': {'latitude': (-20.0, -90), 'longitude': (0, 360)}}, 'PNA': {'domain': {'latitude': (20.0, 85), 'longitude': (120, 240)}}, 'NPO': {'domain': {'latitude': (20.0, 85), 'longitude': (120, 240)}}, 'PDO': {'domain': {'latitude': (20.0, 70), 'longitude': (110, 260)}}, 'NPGO': {'domain': {'latitude': (20.0, 70), 'longitude': (110, 260)}}, 'AMO': {'domain': {'latitude': (0.0, 70), 'longitude': (-80, 0)}}, 'AllMW': {'domain': {'latitude': (-40.0, 45.0), 'longitude': (0.0, 360.0)}}, 'AllM': {'domain': {'latitude': (-45.0, 45.0), 'longitude': (0.0, 360.0)}}, 'NAMM': {'domain': {'latitude': (0.0, 45.0), 'longitude': (210.0, 310.0)}}, 'SAMM': {'domain': {'latitude': (-45.0, 0.0), 'longitude': (240.0, 330.0)}}, 'NAFM': {'domain': {'latitude': (0.0, 45.0), 'longitude': (-50.0, 60.0)}}, 'SAFM': {'domain': {'latitude': (-45.0, 0.0), 'longitude': (0.0, 90.0)}}, 'ASM': {'domain': {'latitude': (0.0, 45.0), 'longitude': (60.0, 180.0)}}, 'AUSM': {'domain': {'latitude': (-45.0, 0.0), 'longitude': (90.0, 160.0)}}, 'AIR': {'domain': {'latitude': (7.0, 25.0), 'longitude': (65.0, 85.0)}}, 'AUS': {'domain': {'latitude': (-20.0, -10.0), 'longitude': (120.0, 150.0)}}, 'Sahel': {'domain': {'latitude': (13.0, 18.0), 'longitude': (-10.0, 10.0)}}, 'GoG': {'domain': {'latitude': (0.0, 5.0), 'longitude': (-10.0, 10.0)}}, 'NAmo': {'domain': {'latitude': (20.0, 37.0), 'longitude': (-112.0, -103.0)}}, 'SAmo': {'domain': {'latitude': (-20.0, 2.5), 'longitude': (-65.0, -40.0)}}}
regions: {'pr': ['Global'], 'rlut': ['Global']}
test_data_path: demo_data/CMIP5_demo_clims/
reference_data_path: demo_data/obs4MIPs_PCMDI_clims
custom_observations: obs_info_dictionary.json
metrics_output_path: demo_output/Ex5
diagnostics_output_path: demo_output/Ex5
debug: False
Traceback (most recent call last):
  File "/Users/lee1043/miniforge3/envs/pmp_devel_20250715/bin/mean_climate_driver.py", line 139, in <module>
    with open(obs_file_path) as fo:
FileNotFoundError: [Errno 2] No such file or directory: 'obs_info_dictionary.json'

There are a couple of steps for using an observational dataset that isn’t included in obs_info_dict.json. The observational dataset mush be documented in a catalog json following the format used in obs_info_dict.json. Then set the variable custom_observations to the path for this catalog. The observation files need to be located under the path specified by reference_data_path

Adding notes and other options

This example adds a field to “user_notes” in the output json and saves the interpolated fields. Interpolated fields are saved at the same directory level as the parameter file.

[18]:
%%bash
mean_climate_driver.py -p basic_param.py \
--case_id 'Ex6' --user_notes 'Example note' --save_test_clims True
--- prepare mean climate metrics calculation ---
case_id: Ex6
test_data_set: ['ACCESS1-0', 'CanCM4']
realization:
vars: ['pr']
varname_in_test_data: None
reference_data_set: ['all']
target_grid: 2.5x2.5
regrid_tool: regrid2
regrid_tool_ocn: esmf
save_test_clims: True
test_clims_interpolated_output: None
filename_template: cmip5.historical.%(model_version).r1i1p1.mon.%(variable).198101-200512.AC.v20200426.nc
sftlf_filename_template: sftlf_%(model_version).nc
generate_sftlf: True
regions_specs: {'global': {}, 'NHEX': {'domain': {'latitude': (30.0, 90)}}, 'SHEX': {'domain': {'latitude': (-90.0, -30)}}, 'TROPICS': {'domain': {'latitude': (-30.0, 30)}}, '90S50S': {'domain': {'latitude': (-90.0, -50)}}, '50S20S': {'domain': {'latitude': (-50.0, -20)}}, '20S20N': {'domain': {'latitude': (-20.0, 20)}}, '20N50N': {'domain': {'latitude': (20.0, 50)}}, '50N90N': {'domain': {'latitude': (50.0, 90)}}, 'CONUS': {'domain': {'latitude': (24.7, 49.4), 'longitude': (-124.78, -66.92)}}, 'land': {'value': 100}, 'land_NHEX': {'value': 100, 'domain': {'latitude': (30.0, 90)}}, 'land_SHEX': {'value': 100, 'domain': {'latitude': (-90.0, -30)}}, 'land_TROPICS': {'value': 100, 'domain': {'latitude': (-30.0, 30)}}, 'land_CONUS': {'value': 100, 'domain': {'latitude': (24.7, 49.4), 'longitude': (-124.78, -66.92)}}, 'ocean': {'value': 0}, 'ocean_NHEX': {'value': 0, 'domain': {'latitude': (30.0, 90)}}, 'ocean_SHEX': {'value': 0, 'domain': {'latitude': (-90.0, -30)}}, 'ocean_TROPICS': {'value': 0, 'domain': {'latitude': (30.0, 30)}}, 'ocean_50S50N': {'value': 0.0, 'domain': {'latitude': (-50.0, 50)}}, 'ocean_50S20S': {'value': 0.0, 'domain': {'latitude': (-50.0, -20)}}, 'ocean_20S20N': {'value': 0.0, 'domain': {'latitude': (-20.0, 20)}}, 'ocean_20N50N': {'value': 0.0, 'domain': {'latitude': (20.0, 50)}}, 'NAM': {'domain': {'latitude': (20.0, 90), 'longitude': (-180, 180)}}, 'NAO': {'domain': {'latitude': (20.0, 80), 'longitude': (-90, 40)}}, 'EA': {'domain': {'latitude': (20.0, 80), 'longitude': (-90, 40)}}, 'SCA': {'domain': {'latitude': (20.0, 80), 'longitude': (-90, 40)}}, 'SAM': {'domain': {'latitude': (-20.0, -90), 'longitude': (0, 360)}}, 'PSA1': {'domain': {'latitude': (-20.0, -90), 'longitude': (0, 360)}}, 'PSA2': {'domain': {'latitude': (-20.0, -90), 'longitude': (0, 360)}}, 'PNA': {'domain': {'latitude': (20.0, 85), 'longitude': (120, 240)}}, 'NPO': {'domain': {'latitude': (20.0, 85), 'longitude': (120, 240)}}, 'PDO': {'domain': {'latitude': (20.0, 70), 'longitude': (110, 260)}}, 'NPGO': {'domain': {'latitude': (20.0, 70), 'longitude': (110, 260)}}, 'AMO': {'domain': {'latitude': (0.0, 70), 'longitude': (-80, 0)}}, 'AllMW': {'domain': {'latitude': (-40.0, 45.0), 'longitude': (0.0, 360.0)}}, 'AllM': {'domain': {'latitude': (-45.0, 45.0), 'longitude': (0.0, 360.0)}}, 'NAMM': {'domain': {'latitude': (0.0, 45.0), 'longitude': (210.0, 310.0)}}, 'SAMM': {'domain': {'latitude': (-45.0, 0.0), 'longitude': (240.0, 330.0)}}, 'NAFM': {'domain': {'latitude': (0.0, 45.0), 'longitude': (-50.0, 60.0)}}, 'SAFM': {'domain': {'latitude': (-45.0, 0.0), 'longitude': (0.0, 90.0)}}, 'ASM': {'domain': {'latitude': (0.0, 45.0), 'longitude': (60.0, 180.0)}}, 'AUSM': {'domain': {'latitude': (-45.0, 0.0), 'longitude': (90.0, 160.0)}}, 'AIR': {'domain': {'latitude': (7.0, 25.0), 'longitude': (65.0, 85.0)}}, 'AUS': {'domain': {'latitude': (-20.0, -10.0), 'longitude': (120.0, 150.0)}}, 'Sahel': {'domain': {'latitude': (13.0, 18.0), 'longitude': (-10.0, 10.0)}}, 'GoG': {'domain': {'latitude': (0.0, 5.0), 'longitude': (-10.0, 10.0)}}, 'NAmo': {'domain': {'latitude': (20.0, 37.0), 'longitude': (-112.0, -103.0)}}, 'SAmo': {'domain': {'latitude': (-20.0, 2.5), 'longitude': (-65.0, -40.0)}}}
regions: {'pr': ['Global'], 'rlut': ['Global']}
test_data_path: demo_data/CMIP5_demo_clims/
reference_data_path: demo_data/PMP_obs4MIPsClims
custom_observations: demo_data/PMP_obs4MIPsClims/PMP_obs4MIPsClims_catalogue_byVar_v20250305.json
metrics_output_path: demo_output/Ex6
diagnostics_output_path: demo_output/Ex6
debug: False
--- start mean climate metrics calculation ---
varname: pr
level: None
reference_data_set (all):  ['default']
No 'default' reference found, using the only available reference: GPCP-Monthly-3-2 for variable 'pr'
obs_dict (for variable): pr
{'GPCP-Monthly-3-2': {'filename': 'pr_mon_GPCP-Monthly-3-2_RSS_gr_198301-200412_AC_v20250211_interp_2.5x2.5.nc',
                      'template': 'pr/gr/v20250211/pr_mon_GPCP-Monthly-3-2_RSS_gr_198301-200412_AC_v20250211_interp_2.5x2.5.nc'},
 'default': 'GPCP-Monthly-3-2'}
obs_dict (for variable) keys: dict_keys(['GPCP-Monthly-3-2', 'default'])
ref: default
ref_data_full_path: demo_data/PMP_obs4MIPsClims/pr/gr/v20250211/pr_mon_GPCP-Monthly-3-2_RSS_gr_198301-200412_AC_v20250211_interp_2.5x2.5.nc
2025-08-04 12:39:33,146 [WARNING]: dataset.py(open_dataset:120) >> "No time coordinates were found in this dataset to decode. If time coordinates were expected to exist, make sure they are detectable by setting the CF 'axis' or 'standard_name' attribute (e.g., ds['time'].attrs['axis'] = 'T' or ds['time'].attrs['standard_name'] = 'time'). Afterwards, try decoding again with `xcdat.decode_time`."
2025-08-04 12:39:33,146 [WARNING]: dataset.py(open_dataset:120) >> "No time coordinates were found in this dataset to decode. If time coordinates were expected to exist, make sure they are detectable by setting the CF 'axis' or 'standard_name' attribute (e.g., ds['time'].attrs['axis'] = 'T' or ds['time'].attrs['standard_name'] = 'time'). Afterwards, try decoding again with `xcdat.decode_time`."
Adjust units for pr
pr units adjusted to [mm d-1] from [kg m-2 s-1] by 86400 multiplied
units: mm/day
ref_data load_and_regrid done
=================================
model, runs, find_all_realizations: ACCESS1-0 [''] False
-----------------------
model, run: ACCESS1-0
test_data (model in this case) full_path: demo_data/CMIP5_demo_clims/cmip5.historical.ACCESS1-0.r1i1p1.mon.pr.198101-200512.AC.v20200426.nc
2025-08-04 12:39:33,366 [WARNING]: dataset.py(_is_decodable:549) >> 'time' does not have a 'units' attribute set so it could not be decoded. Try setting the 'units' attribute (`ds.{coords.name}.attrs['units']`) and try decoding again.
2025-08-04 12:39:33,366 [WARNING]: dataset.py(_is_decodable:549) >> 'time' does not have a 'units' attribute set so it could not be decoded. Try setting the 'units' attribute (`ds.{coords.name}.attrs['units']`) and try decoding again.
Adjust units for pr
pr units adjusted to [mm d-1] from [kg m-2 s-1] by 86400 multiplied
units: mm/day
load and regrid done
region: Global
plot map done
plot map done
plot map done
plot map done
plot map done
compute metrics start
var: pr
metrics-CALCULATE ANNUAL CYCLE SPACE-TIME RMS, CORRELATIONS and STD
metrics, rms_xyt
metrics, rms_xyt: 1.7995509408249972
metrics, stdObs_xyt
metrics, stdObs_xyt: 2.515774881304398
metrics, std_xyt
metrics, std_xyt: 3.1305194374804888
metrics-CALCULATE ANNUAL MEANS
metrics-CALCULATE ANNUAL MEAN BIAS
metrics-CALCULATE ANNUAL MEAN BIAS, bias_xy: 0.25922717938795004
metrics-CALCULATE MSE
metrics-CALCULATE MSE, mae_xy: 0.72142914491151
metrics-CALCULATE MEAN RMS
metrics-CALCULATE MEAN RMS: rms_xy, rmsc_xy:  1.1919949785767163 1.1634660710217004
metrics-CALCULATE MEAN CORR
metrics-CALCULATE MEAN CORR: cor_xy: 0.883562458809904
metrics-CALCULATE ANNUAL OBS AND MOD STD
metrics-CALCULATE ANNUAL OBS AND MOD MEAN
metrics-CALCULATE ANNUAL MEANS
metrics-CALCULATE ANNUAL AND ZONAL MEAN RMS
metrics-CALCULATE ANNUAL MEAN DEVIATION FROM ZONAL MEAN RMS
metrics-CALCULATE ANNUAL MEAN DEVIATION FROM ZONAL MEAN STD
INFO::2025-08-04 12:39::pcmdi_metrics:: Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex6/pr/pr_ACCESS1-0__2.5x2.5_regrid2_metrics_default_Ex6.json
2025-08-04 12:39:54,241 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex6/pr/pr_ACCESS1-0__2.5x2.5_regrid2_metrics_default_Ex6.json
2025-08-04 12:39:54,241 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex6/pr/pr_ACCESS1-0__2.5x2.5_regrid2_metrics_default_Ex6.json
=================================
model, runs, find_all_realizations: CanCM4 [''] False
-----------------------
model, run: CanCM4
test_data (model in this case) full_path: demo_data/CMIP5_demo_clims/cmip5.historical.CanCM4.r1i1p1.mon.pr.198101-200512.AC.v20200426.nc
2025-08-04 12:39:54,248 [WARNING]: dataset.py(_is_decodable:549) >> 'time' does not have a 'units' attribute set so it could not be decoded. Try setting the 'units' attribute (`ds.{coords.name}.attrs['units']`) and try decoding again.
2025-08-04 12:39:54,248 [WARNING]: dataset.py(_is_decodable:549) >> 'time' does not have a 'units' attribute set so it could not be decoded. Try setting the 'units' attribute (`ds.{coords.name}.attrs['units']`) and try decoding again.
Adjust units for pr
pr units adjusted to [mm d-1] from [kg m-2 s-1] by 86400 multiplied
units: mm/day
load and regrid done
region: Global
plot map done
plot map done
plot map done
plot map done
plot map done
compute metrics start
var: pr
metrics-CALCULATE ANNUAL CYCLE SPACE-TIME RMS, CORRELATIONS and STD
metrics, rms_xyt
metrics, rms_xyt: 1.6937110851537234
metrics, stdObs_xyt
metrics, stdObs_xyt: 2.515774881304398
metrics, std_xyt
metrics, std_xyt: 2.7462907772599525
metrics-CALCULATE ANNUAL MEANS
metrics-CALCULATE ANNUAL MEAN BIAS
metrics-CALCULATE ANNUAL MEAN BIAS, bias_xy: -0.053533741934399505
metrics-CALCULATE MSE
metrics-CALCULATE MSE, mae_xy: 0.7740939928776985
metrics-CALCULATE MEAN RMS
metrics-CALCULATE MEAN RMS: rms_xy, rmsc_xy:  1.21206440023263 1.2108815998212985
metrics-CALCULATE MEAN CORR
metrics-CALCULATE MEAN CORR: cor_xy: 0.8345736267748058
metrics-CALCULATE ANNUAL OBS AND MOD STD
metrics-CALCULATE ANNUAL OBS AND MOD MEAN
metrics-CALCULATE ANNUAL MEANS
metrics-CALCULATE ANNUAL AND ZONAL MEAN RMS
metrics-CALCULATE ANNUAL MEAN DEVIATION FROM ZONAL MEAN RMS
metrics-CALCULATE ANNUAL MEAN DEVIATION FROM ZONAL MEAN STD
INFO::2025-08-04 12:40::pcmdi_metrics:: Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex6/pr/pr_CanCM4__2.5x2.5_regrid2_metrics_default_Ex6.json
2025-08-04 12:40:14,610 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex6/pr/pr_CanCM4__2.5x2.5_regrid2_metrics_default_Ex6.json
2025-08-04 12:40:14,610 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex6/pr/pr_CanCM4__2.5x2.5_regrid2_metrics_default_Ex6.json
INFO::2025-08-04 12:40::pcmdi_metrics:: Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex6/pr_2.5x2.5_regrid2_metrics_Ex6.json
2025-08-04 12:40:14,611 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex6/pr_2.5x2.5_regrid2_metrics_Ex6.json
2025-08-04 12:40:14,611 [INFO]: base.py(write:429) >> Results saved to a json file: /Users/lee1043/Documents/Research/git/pcmdi_metrics_20221013_pcmdi/pcmdi_metrics/doc/jupyter/Demo/demo_output/Ex6/pr_2.5x2.5_regrid2_metrics_Ex6.json
pmp mean clim driver completed

Some other flags to note:

  • --ext ‘.nc’ or ‘.xml’. NetCDF files should be post-processed annual climatologies

  • --filename_template Based on the format of your model files.

    • When the file name varies based on model, experiment, or another parameter, use %(parameter) as a placeholder (for example, CMIP5.historical.%(model_version)... in this demo’s parameter file)

  • --help or -h Help command for more information about all flags.

  • --custom_observations Path for observation catalogue JSON file.