7. Precipitation Variability Across Timescales
This notebook demonstrates how to use the precipitation variability metrics driver and calc_ratio script to obtain the precipitation variability metric.
Our metric is based on the simulated-to-observed ratio of spectral power because the spectral power is substantially sensitive to the processing choices for power spectra analysis (e.g., window length, overlap length, and windowing function). By using the ratio, the metric is not greatly affected by the different processing choices, helping the robustness of analysis results.
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 as demonstrated in the download notebook.
The following cell reads in the choices you made during the download data step:
[1]:
from user_choices import demo_data_directory, demo_output_directory
Basic Use
Help
Use the --help
flag for assistance with the precip variability driver:
[2]:
%%bash
variability_across_timescales_PS_driver.py --help
usage: variability_across_timescales_PS_driver.py [-h]
[--parameters PARAMETERS]
[--diags OTHER_PARAMETERS [OTHER_PARAMETERS ...]]
[--mip MIP] [--exp EXP]
[--mod MOD] [--var VAR]
[--frq FRQ]
[--modpath MODPATH]
[--results_dir RESULTS_DIR]
[--case_id CASE_ID]
[--prd PRD [PRD ...]]
[--fac FAC]
[--nperseg NPERSEG]
[--noverlap NOVERLAP]
[--ref REF] [--res RES]
[--regions_specs REGIONS_SPECS]
[--cmec] [--no_cmec]
[--region_file REGION_FILE]
[--feature FEATURE]
[--attr ATTR]
options:
-h, --help show this help message and exit
--parameters PARAMETERS, -p PARAMETERS
--diags OTHER_PARAMETERS [OTHER_PARAMETERS ...], -d OTHER_PARAMETERS [OTHER_PARAMETERS ...]
Path to other user-defined parameter file. (default:
None)
--mip MIP cmip5, cmip6 or other mip (default: None)
--exp EXP amip, cmip or others (default: None)
--mod MOD model (default: None)
--var VAR pr or other variable (default: None)
--frq FRQ day, 3hr or other frequency (default: None)
--modpath MODPATH data directory path (default: None)
--results_dir RESULTS_DIR
results directory path (default: None)
--case_id CASE_ID case_id with date (default: None)
--prd PRD [PRD ...] start- and end-year for analysis (e.g., 1985 2004)
(default: None)
--fac FAC factor to make unit of [mm/day] (default: None)
--nperseg NPERSEG length of segment in power spectra (default: None)
--noverlap NOVERLAP length of overlap between segments in power spectra
(default: None)
--ref REF reference data path (default: None)
--res RES Horizontal resolution [degree] for interpolation (lon,
lat) (default: 2)
--regions_specs REGIONS_SPECS
Provide a single custom region (default: None)
--cmec Use to save CMEC format metrics JSON (default: False)
--no_cmec Do not save CMEC format metrics JSON (default: False)
--region_file REGION_FILE
File containing vector region of interest. (default:
None)
--feature FEATURE Feature in vectorized region. (default: None)
--attr ATTR Attribute containing feature in vectorized region.
(default: None)
[WARNING] yaksa: 10 leaked handle pool objects
Parameter file
Settings can be specified in a parameter file or on the command line. The basic case demonstrated here uses a parameter file, which is printed below.
Note that this driver should only be used to run one model or dataset at a time.
The mod
variable can either be set to a particular file name, as shown here, or to a model name (i.e. “GISS-E2-H”).
[3]:
# print parameter file
with open("basic_precip_variability_param.py") as f:
print(f.read())
mip = "cmip5"
exp = "historical"
mod = "pr_day_GISS-E2-H_historical_r6i1p1_*.nc"
var = "pr"
frq = "day"
modpath = 'demo_data_tmp/CMIP5_demo_timeseries/historical/atmos/day/pr/'
results_dir = 'demo_output_tmp/precip_variability/GISS-E2-H/'
prd = [2000,2005] # analysis period
fac = 86400 # factor to make unit of [mm/day]
# length of segment in power spectra (~10 years)
# shortened to 2 years for demo purposes
nperseg = 2 * 365
# length of overlap between segments in power spectra (~5 years)
# shortened to 1 year for demo purposes
noverlap = 1 * 365
# flag for cmec formatted JSON
cmec = False
Running the driver
-p
flag, similar to other PMP metrics. The basic command is:variability_across_timescales_PS_driver.py -p parameter_file_name.py
The next cell uses the command line syntax to execute the driver as a subprocess.
[4]:
%%bash
variability_across_timescales_PS_driver.py -p basic_precip_variability_param.py
INFO::2024-09-18 15:56::pcmdi_metrics:: Results saved to a json file: /home/ordonez4/git/pcmdi_metrics/doc/jupyter/Demo/demo_output_tmp/precip_variability/GISS-E2-H/PS_pr.day_regrid.180x90_area.freq.mean_GISS-E2-H.r6i1p1.json
2024-09-18 15:56:49,164 [INFO]: base.py(write:422) >> Results saved to a json file: /home/ordonez4/git/pcmdi_metrics/doc/jupyter/Demo/demo_output_tmp/precip_variability/GISS-E2-H/PS_pr.day_regrid.180x90_area.freq.mean_GISS-E2-H.r6i1p1.json
2024-09-18 15:56:49,164 [INFO]: base.py(write:422) >> Results saved to a json file: /home/ordonez4/git/pcmdi_metrics/doc/jupyter/Demo/demo_output_tmp/precip_variability/GISS-E2-H/PS_pr.day_regrid.180x90_area.freq.mean_GISS-E2-H.r6i1p1.json
demo_data_tmp/CMIP5_demo_timeseries/historical/atmos/day/pr/
pr_day_GISS-E2-H_historical_r6i1p1_*.nc
[2000, 2005]
730 365
2
demo_output_tmp/precip_variability/GISS-E2-H/
demo_output_tmp/precip_variability/GISS-E2-H/
demo_output_tmp/precip_variability/GISS-E2-H/
['demo_data_tmp/CMIP5_demo_timeseries/historical/atmos/day/pr/pr_day_GISS-E2-H_historical_r6i1p1_20000101-20051231.nc']
GISS-E2-H.r6i1p1
['demo_data_tmp/CMIP5_demo_timeseries/historical/atmos/day/pr/pr_day_GISS-E2-H_historical_r6i1p1_20000101-20051231.nc']
GISS-E2-H.r6i1p1 365_day
2000 2005
Complete regridding from (2190, 90, 144) to (2190, 90, 180)
Complete calculating climatology and anomaly for calendar of 365_day
Complete power spectra (segment: 730 nps: 5.0 )
Complete domain and frequency average of spectral power
Complete power spectra (segment: 730 nps: 5.0 )
Complete domain and frequency average of spectral power
[WARNING] yaksa: 10 leaked handle pool objects
Results
Running the precipitation variability driver produces three output files, found in the demo output directory:
[5]:
!ls {demo_output_directory + "/precip_variability/GISS-E2-H"}
PS_pr.day_regrid.180x90_area.freq.mean_GISS-E2-H.r6i1p1.json
PS_pr.day_regrid.180x90_GISS-E2-H.r6i1p1.nc
PS_pr.day_regrid.180x90_GISS-E2-H.r6i1p1_unforced.nc
The next cell displays the metrics from the JSON file.
[6]:
import json
import os
output_path = os.path.join(demo_output_directory,"precip_variability/GISS-E2-H/PS_pr.day_regrid.180x90_area.freq.mean_GISS-E2-H.r6i1p1.json")
with open(output_path) as f:
metric = json.load(f)["RESULTS"]
print(json.dumps(metric, indent=2))
{
"GISS-E2-H.r6i1p1": {
"forced": {
"Land_30N50N": {
"annual": 1.153948602189096,
"semi-annual": 0.3675381067314767
},
"Land_30S30N": {
"annual": 6.8509958100746555,
"semi-annual": 1.1945015595812805
},
"Land_50S30S": {
"annual": 0.8090939740005696,
"semi-annual": 0.34297346148163804
},
"Land_50S50N": {
"annual": 4.793570167683052,
"semi-annual": 0.8971106124805638
},
"Ocean_30N50N": {
"annual": 1.450126151318265,
"semi-annual": 0.3738726067518909
},
"Ocean_30S30N": {
"annual": 4.561426422605001,
"semi-annual": 1.5069884231014545
},
"Ocean_50S30S": {
"annual": 0.5890515819402276,
"semi-annual": 0.19150748548003316
},
"Ocean_50S50N": {
"annual": 3.3050864193776026,
"semi-annual": 1.0780758057454556
},
"Total_30N50N": {
"annual": 1.3110986682307972,
"semi-annual": 0.3708991551953958
},
"Total_30S30N": {
"annual": 5.155704413930364,
"semi-annual": 1.4258796929688142
},
"Total_50S30S": {
"annual": 0.6055533541116551,
"semi-annual": 0.20286646501255923
},
"Total_50S50N": {
"annual": 3.6979701926949535,
"semi-annual": 1.030310226813203
}
},
"unforced": {
"Land_30N50N": {
"interannual": 0.11025112312631524,
"seasonal-annual": 0.1502570664470804,
"sub-seasonal": 0.13618888930844514,
"synoptic": 0.06327297649960462
},
"Land_30S30N": {
"interannual": 0.31535297942347246,
"seasonal-annual": 0.31179854291318526,
"sub-seasonal": 0.2477967897126997,
"synoptic": 0.076484979080103
},
"Land_50S30S": {
"interannual": 0.16178541870984994,
"seasonal-annual": 0.21589364787265297,
"sub-seasonal": 0.1847557860658534,
"synoptic": 0.07524240453524904
},
"Land_50S50N": {
"interannual": 0.24443780233759468,
"seasonal-annual": 0.25718039033896883,
"sub-seasonal": 0.2102202999468355,
"synoptic": 0.07234360585017287
},
"Ocean_30N50N": {
"interannual": 0.13265625643216272,
"seasonal-annual": 0.1758330640897642,
"sub-seasonal": 0.15435681112427357,
"synoptic": 0.0981749977902816
},
"Ocean_30S30N": {
"interannual": 0.6539803811119562,
"seasonal-annual": 0.6385364543707663,
"sub-seasonal": 0.43424291163472306,
"synoptic": 0.11428977945404156
},
"Ocean_50S30S": {
"interannual": 0.09747609150424397,
"seasonal-annual": 0.13244482423836793,
"sub-seasonal": 0.11915711328928573,
"synoptic": 0.06874014945078849
},
"Ocean_50S50N": {
"interannual": 0.467278699215871,
"seasonal-annual": 0.4701741107777076,
"sub-seasonal": 0.33044759093021675,
"synoptic": 0.10233245216785025
},
"Total_30N50N": {
"interannual": 0.12213915511604374,
"seasonal-annual": 0.1638275404092277,
"sub-seasonal": 0.14582868179640485,
"synoptic": 0.08179178377228893
},
"Total_30S30N": {
"interannual": 0.5660866430211011,
"seasonal-annual": 0.5537287386607875,
"sub-seasonal": 0.38584917112064354,
"synoptic": 0.10447720904161961
},
"Total_50S30S": {
"interannual": 0.10229887976839695,
"seasonal-annual": 0.13870295233219931,
"sub-seasonal": 0.12407659422553256,
"synoptic": 0.06922777699836948
},
"Total_50S50N": {
"interannual": 0.4084600708535113,
"seasonal-annual": 0.4139546346334961,
"sub-seasonal": 0.29871371960574444,
"synoptic": 0.09441692664589409
}
}
}
}
Command line usage with Obs data
To calculate the precipitation variability spectral power ratio, we also need results for a reference dataset. This example shows how to call the variability_across_timescales_PS_driver
using a combination of the parameter file and command line arguments with daily observational data. The command line arguments will overwrite values that are in the parameter file.
The modpath
and results_dir
values are set first in a separate cell to easily combine the demo_data_directory
and demo_output_directory
variables with other strings. The new variables are then passed to the shell command in the second cell.
[7]:
modpath = demo_data_directory + '/obs4MIPs_PCMDI_daily/NASA-JPL/GPCP-1-3/day/pr/gn/latest/'
results_dir = demo_output_directory + '/precip_variability/GPCP-1-3/'
[8]:
%%bash -s "$modpath" "$results_dir"
variability_across_timescales_PS_driver.py -p basic_precip_variability_param.py \
--mip 'obs' \
--mod 'pr_day_GPCP-1-3_PCMDI_gn_19961002-20170101.nc' \
--modpath $1 \
--results_dir $2 \
--prd 1997 2016
INFO::2024-09-18 16:08::pcmdi_metrics:: Results saved to a json file: /home/ordonez4/git/pcmdi_metrics/doc/jupyter/Demo/demo_output_tmp/precip_variability/GPCP-1-3/PS_pr.day_regrid.180x90_area.freq.mean_GPCP-1-3.json
2024-09-18 16:08:28,962 [INFO]: base.py(write:422) >> Results saved to a json file: /home/ordonez4/git/pcmdi_metrics/doc/jupyter/Demo/demo_output_tmp/precip_variability/GPCP-1-3/PS_pr.day_regrid.180x90_area.freq.mean_GPCP-1-3.json
2024-09-18 16:08:28,962 [INFO]: base.py(write:422) >> Results saved to a json file: /home/ordonez4/git/pcmdi_metrics/doc/jupyter/Demo/demo_output_tmp/precip_variability/GPCP-1-3/PS_pr.day_regrid.180x90_area.freq.mean_GPCP-1-3.json
demo_data_tmp/obs4MIPs_PCMDI_daily/NASA-JPL/GPCP-1-3/day/pr/gn/latest/
pr_day_GPCP-1-3_PCMDI_gn_19961002-20170101.nc
[1997, 2016]
730 365
2
demo_output_tmp/precip_variability/GPCP-1-3/
demo_output_tmp/precip_variability/GPCP-1-3/
demo_output_tmp/precip_variability/GPCP-1-3/
['demo_data_tmp/obs4MIPs_PCMDI_daily/NASA-JPL/GPCP-1-3/day/pr/gn/latest/pr_day_GPCP-1-3_PCMDI_gn_19961002-20170101.nc']
GPCP-1-3
['demo_data_tmp/obs4MIPs_PCMDI_daily/NASA-JPL/GPCP-1-3/day/pr/gn/latest/pr_day_GPCP-1-3_PCMDI_gn_19961002-20170101.nc']
GPCP-1-3 gregorian
1997 2016
Complete regridding from (7305, 180, 360) to (7305, 90, 180)
Complete calculating climatology and anomaly for calendar of gregorian
Complete power spectra (segment: 730 nps: 19.0 )
Complete domain and frequency average of spectral power
Complete power spectra (segment: 730 nps: 19.0 )
Complete domain and frequency average of spectral power
[WARNING] yaksa: 10 leaked handle pool objects
Precipitation Variability Metric
The precipitation variability metric can be generated after model and observational spectral averages are made.
ref
: path to obs results JSONmodpath
: directory containing model results JSONS (not CMEC formatted JSONs)results_dir
: directory for calc_ratio.py resultsThis script can be accessed via the PMP repo, which is how it is run here. It does not come with the PMP conda installation.
[9]:
%%bash -s "$demo_output_directory"
python ../../../pcmdi_metrics/precip_variability/scripts_pcmdi/calc_ratio.py \
--ref $1/precip_variability/GPCP-1-3/PS_pr.day_regrid.180x90_area.freq.mean_GPCP-1-3.json \
--modpath $1/precip_variability/GISS-E2-H/ \
--results_dir $1/precip_variability/ratio/
reference: demo_output_tmp/precip_variability/GPCP-1-3/PS_pr.day_regrid.180x90_area.freq.mean_GPCP-1-3.json
modpath: demo_output_tmp/precip_variability/GISS-E2-H/
outdir: demo_output_tmp/precip_variability/ratio/
['demo_output_tmp/precip_variability/GISS-E2-H/PS_pr.day_regrid.180x90_area.freq.mean_GISS-E2-H.r6i1p1.json']
Complete GISS-E2-H.r6i1p1
Complete all
[WARNING] yaksa: 10 leaked handle pool objects
This outputs one JSON file in the results_dir
folder. The results in this file are shown below.
[10]:
output_path = os.path.join(demo_output_directory,"precip_variability/ratio/PS_pr.day_regrid.180x90_area.freq.mean_GISS-E2-H.r6i1p1.json")
with open(output_path) as f:
metric = json.load(f)["RESULTS"]
print(json.dumps(metric, indent=2))
{
"GISS-E2-H.r6i1p1": {
"forced": {
"Land_30N50N": {
"annual": 1.6279984575673894,
"semi-annual": 1.867057373601494
},
"Land_30S30N": {
"annual": 1.3338114720532706,
"semi-annual": 1.333350181560781
},
"Land_50S30S": {
"annual": 1.164227264547647,
"semi-annual": 1.9246852085563568
},
"Land_50S50N": {
"annual": 1.3503132388688357,
"semi-annual": 1.391749566706111
},
"Ocean_30N50N": {
"annual": 1.0524861972773814,
"semi-annual": 0.8517712548298377
},
"Ocean_30S30N": {
"annual": 1.499118828822202,
"semi-annual": 1.8222593026548162
},
"Ocean_50S30S": {
"annual": 1.4363958284724372,
"semi-annual": 1.0484119422307991
},
"Ocean_50S50N": {
"annual": 1.4625476582104198,
"semi-annual": 1.6902905191733497
},
"Total_30N50N": {
"annual": 1.2324909366302752,
"semi-annual": 1.1401718517572574
},
"Total_30S30N": {
"annual": 1.4376639123073875,
"semi-annual": 1.6876985330852605
},
"Total_50S30S": {
"annual": 1.4035190474483104,
"semi-annual": 1.1126375229893537
},
"Total_50S50N": {
"annual": 1.4221050736833434,
"semi-annual": 1.6108754775087752
}
},
"unforced": {
"Land_30N50N": {
"interannual": 1.3879961062215058,
"seasonal-annual": 1.4543733420466998,
"sub-seasonal": 1.2722446114532955,
"synoptic": 0.9550314725762122
},
"Land_30S30N": {
"interannual": 1.568479703495435,
"seasonal-annual": 1.3855140760562272,
"sub-seasonal": 1.0320215218679585,
"synoptic": 0.6344408069821
},
"Land_50S30S": {
"interannual": 1.273480429665751,
"seasonal-annual": 1.4835739537712782,
"sub-seasonal": 1.1166071488025653,
"synoptic": 0.6682326701057775
},
"Land_50S50N": {
"interannual": 1.5292151952175095,
"seasonal-annual": 1.4013209418868053,
"sub-seasonal": 1.076210914944252,
"synoptic": 0.6996958985943696
},
"Ocean_30N50N": {
"interannual": 0.7043783826080335,
"seasonal-annual": 0.6455934192259553,
"sub-seasonal": 0.6137724411737419,
"synoptic": 0.6863874501625437
},
"Ocean_30S30N": {
"interannual": 1.250341415643576,
"seasonal-annual": 1.5516779450827425,
"sub-seasonal": 1.1798960241814673,
"synoptic": 1.0953812575228667
},
"Ocean_50S30S": {
"interannual": 0.8539632674914027,
"seasonal-annual": 0.8423603608480983,
"sub-seasonal": 0.7618579649944118,
"synoptic": 0.6782173179198747
},
"Ocean_50S50N": {
"interannual": 1.192306567530281,
"seasonal-annual": 1.388569073500126,
"sub-seasonal": 1.075457264771947,
"synoptic": 0.9428927883322024
},
"Total_30N50N": {
"interannual": 0.8901421815356266,
"seasonal-annual": 0.8488114296330028,
"sub-seasonal": 0.7938998372292919,
"synoptic": 0.764474619537189
},
"Total_30S30N": {
"interannual": 1.2881197802160176,
"seasonal-annual": 1.5249482736415583,
"sub-seasonal": 1.1523720464576683,
"synoptic": 0.96250506817075
},
"Total_50S30S": {
"interannual": 0.8886847211435605,
"seasonal-annual": 0.8871164946123411,
"sub-seasonal": 0.7898809941461293,
"synoptic": 0.6773923219536804
},
"Total_50S50N": {
"interannual": 1.235295139394142,
"seasonal-annual": 1.390644261053773,
"sub-seasonal": 1.0755971788907195,
"synoptic": 0.8809660578685686
}
}
}
}
Regional metrics
The precipitation variability metrics have a set of default regions. However, users can instead define a single spatial region to compute metrics over. There are two ways to do this.
Use the
regions_specs
parameter to define a latitude/longitude box. Parameter file example:
regions_specs={"CONUS": {"domain": {"latitude": (24.7, 49.4), "longitude": (235.22, 293.08)}}}
Use a shapefile to define a region. Users must provide the path to the shapefile along with the attribute/feature pair that defines the region. Parameter file example:
region_file="CONUS.shp" # Shapefile path
attr="NAME" # An attribute in the shapefile
feature="CONUS" # A unique feature name that can be
# found under the "attr" attribute
Both options can be used at the same time. In that case, the area defined by regions_specs is applied first and can be used to trim down very large, high resolution datasets. Then the metrics are computed for the area defined by the shapefile region.
Region example
First, we generate a simple shapefile for use in this demo. The shapefile contains one feature, a box that defines the CONUS region.
[13]:
from shapely import Polygon
import geopandas as gpd
import pandas as pd
# Define region box
coords = ((233.,22.),(233.,50.),(294.,50.),(294.,22))
# Add to pandas dataframe, then convert to geopandas dataframe
df = pd.DataFrame({"Region": ["CONUS"], "Coords": [Polygon(coords)]})
gdf = gpd.GeoDataFrame(df, geometry="Coords", crs="EPSG:4326")
# Create the output location
if not os.path.exists(demo_output_directory+"/shp"):
os.mkdir(demo_output_directory+"/shp")
gdf.to_file(demo_output_directory+'/shp/CONUS.shp')
Add the information for this shapefile to the variability_across_timescales_PS_driver.py run command.
[14]:
%%bash -s "$demo_output_directory"
variability_across_timescales_PS_driver.py -p basic_precip_variability_param.py \
--region_file $1/shp/CONUS.shp \
--attr 'Region' \
--feature 'CONUS' \
--results_dir $1/precip_variability/region_ex
/home/ordonez4/miniconda3/envs/pmp_dev/lib/python3.10/site-packages/pcmdi_metrics/precip_variability/lib/lib_variability_across_timescales.py:313: RuntimeWarning: Mean of empty slice
clim = np.nanmean(dseg, axis=0)
INFO::2024-09-18 16:11::pcmdi_metrics:: Results saved to a json file: /home/ordonez4/git/pcmdi_metrics/doc/jupyter/Demo/demo_output_tmp/precip_variability/region_ex/PS_pr.day_regrid.180x90_area.freq.mean_GISS-E2-H.r6i1p1.json
2024-09-18 16:11:40,113 [INFO]: base.py(write:422) >> Results saved to a json file: /home/ordonez4/git/pcmdi_metrics/doc/jupyter/Demo/demo_output_tmp/precip_variability/region_ex/PS_pr.day_regrid.180x90_area.freq.mean_GISS-E2-H.r6i1p1.json
2024-09-18 16:11:40,113 [INFO]: base.py(write:422) >> Results saved to a json file: /home/ordonez4/git/pcmdi_metrics/doc/jupyter/Demo/demo_output_tmp/precip_variability/region_ex/PS_pr.day_regrid.180x90_area.freq.mean_GISS-E2-H.r6i1p1.json
demo_data_tmp/CMIP5_demo_timeseries/historical/atmos/day/pr/
pr_day_GISS-E2-H_historical_r6i1p1_*.nc
[2000, 2005]
730 365
2
demo_output_tmp/precip_variability/region_ex
demo_output_tmp/precip_variability/region_ex
demo_output_tmp/precip_variability/region_ex
['demo_data_tmp/CMIP5_demo_timeseries/historical/atmos/day/pr/pr_day_GISS-E2-H_historical_r6i1p1_20000101-20051231.nc']
GISS-E2-H.r6i1p1
['demo_data_tmp/CMIP5_demo_timeseries/historical/atmos/day/pr/pr_day_GISS-E2-H_historical_r6i1p1_20000101-20051231.nc']
GISS-E2-H.r6i1p1 365_day
2000 2005
Complete regridding from (2190, 90, 144) to (2190, 90, 180)
Cropping from shapefile
Reading region from file.
Complete calculating climatology and anomaly for calendar of 365_day
Complete power spectra (segment: 730 nps: 5.0 )
Complete domain and frequency average of spectral power
Complete power spectra (segment: 730 nps: 5.0 )
Complete domain and frequency average of spectral power
[WARNING] yaksa: 10 leaked handle pool objects
The metrics output will look different than the default example. Metrics will only be produced for a single region that we defined in this shapefile.
[15]:
output_path = os.path.join(demo_output_directory,"precip_variability/region_ex/PS_pr.day_regrid.180x90_area.freq.mean_GISS-E2-H.r6i1p1.json")
with open(output_path) as f:
metric = json.load(f)["RESULTS"]
print(json.dumps(metric, indent=2))
{
"GISS-E2-H.r6i1p1": {
"forced": {
"CONUS": {
"annual": 1.2011870574080201,
"semi-annual": 0.380975826207154
}
},
"unforced": {
"CONUS": {
"interannual": 0.1521909521737256,
"seasonal-annual": 0.20428410514869913,
"sub-seasonal": 0.20652699240276465,
"synoptic": 0.10360220715481439
}
}
}
}