-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #851 from PCMDI/741_ljw_cloud
Cloud feedback metric
- Loading branch information
Showing
28 changed files
with
108,775 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
# Cloud Feedback Metrics | ||
|
||
The clould feedback metrics implemented to PMP is originally from [`assessed-cloud-fbks`](https://github.com/mzelinka/assessed-cloud-fbks)[![DOI](https://zenodo.org/badge/353136800.svg)](https://zenodo.org/badge/latestdoi/353136800), developed by [@mzelinka](https://mzelinka.github.io/) at LLNL. This code performs the analysis of [Zelinka et al. (2022)](https://agupubs.onlinelibrary.wiley.com/doi/full/10.1029/2021JD035198). It computes GCM cloud feedback components and compares them to the expert-assessed values from [Sherwood et al. (2020)](https://agupubs.onlinelibrary.wiley.com/doi/full/10.1029/2019RG000678). | ||
|
||
## Instructions | ||
To use, please consider follow these steps: | ||
|
||
#### 1. Install PMP | ||
Install PMP via conda following [these instructions](http://pcmdi.github.io/pcmdi_metrics/install.html). For example: | ||
``` | ||
conda create -n [YOUR_CONDA_ENVIRONMENT] -c conda-forge pcmdi_metrics | ||
``` | ||
|
||
#### 2. Activate PMP installed conda environment | ||
Activate your environment (if PMP installed env is differnt than your current one): | ||
``` | ||
conda activate [YOUR_CONDA_ENVIRONMENT] | ||
``` | ||
|
||
#### 3. Clone PMP repo to your local | ||
Clone PMP repo to your local for pre-calculated data: | ||
``` | ||
git clone https://github.com/PCMDI/pcmdi_metrics | ||
``` | ||
|
||
Once completed, go to `pcmdi_metrics/pcmdi_metrics/cloud_feedback` directory | ||
``` | ||
cd [YOUR LOCAL CLONED PMP REPOSITORY] | ||
cd pcmdi_metrics/pcmdi_metrics/cloud_feedback | ||
``` | ||
|
||
#### 4. Edit parameter files | ||
In [`param/my_param.py`](param/my_param.py), update the "User Input" section so it points to your model's amip and amip-p4K files. | ||
```python | ||
|
||
# User Input: | ||
# ================================================================================================ | ||
model = "GFDL-CM4" | ||
variant = "r1i1p1f1" | ||
|
||
input_files_json = "./param/input_files.json" | ||
|
||
# Flag to compute ECS | ||
# True: compute ECS using abrupt-4xCO2 run | ||
# False: do not compute, instead rely on ECS value present in the json file (if it exists) | ||
# get_ecs = True | ||
get_ecs = False | ||
|
||
# Output directory path (directory will be generated if it does not exist yet.) | ||
xml_path = "./xmls/" | ||
figure_path = "./figures/" | ||
output_path = "./output" | ||
output_json_filename = "_".join(["cloud_feedback", model, variant]) + ".json" | ||
# ================================================================================================ | ||
``` | ||
|
||
You will need to update [`param/input_files.json`](param/input_files.json) file as well to provide data path for your input files. | ||
|
||
#### 5. Run the code and inspect the generated output files | ||
Run calculation: | ||
``` | ||
python cloud_feedback_driver.py -p param/my_param.py | ||
``` | ||
|
||
Once code is completed, check `output` directory (`output_path` from the above parameter file) for JSON and `figures` directory (`figure_path` from the above parameter file) for figures and text tables. | ||
|
||
|
||
## References | ||
- Zelinka et al. (2022): [Evaluating climate models’ cloud feedbacks against expert judgement](https://agupubs.onlinelibrary.wiley.com/doi/full/10.1029/2021JD035198), <em>J. Geophys. Res.</em>, 127, e2021JD035198, doi:10.1029/2021JD035198. | ||
|
||
- Sherwood et al. (2020): [A combined assessment of Earth’s climate sensitivity](https://agupubs.onlinelibrary.wiley.com/doi/abs/10.1029/2019RG000678), <em>Rev. Geophys.</em>, 58, e2019RG000678, doi:10.1029/2019RG000678. |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
#!/usr/bin/env python | ||
|
||
import json | ||
import os | ||
from collections import OrderedDict | ||
|
||
import pcmdi_metrics.cloud_feedback.lib.cld_fbks_ecs_assessment_v3 as dataviz | ||
from pcmdi_metrics.cloud_feedback.lib import ( | ||
AddParserArgument, | ||
CloudRadKernel, | ||
cloud_feedback_metrics_to_json, | ||
compute_ECS, | ||
organize_ecs_jsons, | ||
organize_err_jsons, | ||
organize_fbk_jsons, | ||
) | ||
|
||
# collect user input | ||
param = AddParserArgument() | ||
|
||
model = param.model | ||
institution = param.institution | ||
variant = param.variant | ||
grid_label = param.grid_label | ||
version = param.version | ||
input_files_json = param.input_files_json | ||
path = param.path | ||
xml_path = param.xml_path | ||
data_path = param.data_path | ||
figure_path = param.figure_path | ||
output_path = param.output_path | ||
output_json_filename = param.output_json_filename | ||
get_ecs = param.get_ecs | ||
debug = param.debug | ||
|
||
cmec = False | ||
if hasattr(param, "cmec"): | ||
cmec = param.cmec # Generate CMEC compliant json | ||
print("CMEC:" + str(cmec)) | ||
|
||
print("model:", model) | ||
print("institution:", institution) | ||
print("variant:", variant) | ||
print("grid_label:", grid_label) | ||
print("version:", version) | ||
print("path:", path) | ||
print("input_files_json:", input_files_json) | ||
print("xml_path:", xml_path) | ||
print("figure_path:", figure_path) | ||
print("output_path:", output_path) | ||
print("output_json_filename:", output_json_filename) | ||
print("get_ecs:", get_ecs) | ||
print("debug:", debug) | ||
|
||
if get_ecs: | ||
exps = ["amip", "amip-p4K", "piControl", "abrupt-4xCO2"] | ||
else: | ||
exps = ["amip", "amip-p4K"] | ||
|
||
# generate xmls pointing to the cmorized netcdf files | ||
os.makedirs(xml_path, exist_ok=True) | ||
|
||
filenames = dict() | ||
|
||
if input_files_json is not None: | ||
with open(input_files_json) as f: | ||
ncfiles = json.load(f) | ||
else: | ||
print('Warning: input files were not explicitly given. They will be searched from ', path) | ||
|
||
for exp in exps: | ||
filenames[exp] = dict() | ||
if exp == "amip-p4K": | ||
activity = "CFMIP" | ||
else: | ||
activity = "CMIP" | ||
if "amip" in exp: | ||
fields = [ | ||
"tas", | ||
"rsdscs", | ||
"rsuscs", | ||
"wap", | ||
"clisccp", | ||
] # necessary for cloud feedback calcs | ||
else: | ||
fields = ["tas", "rlut", "rsut", "rsdt"] # needed for ECS calc | ||
for field in fields: | ||
if field == "clisccp": | ||
table = "CFmon" | ||
else: | ||
table = "Amon" | ||
|
||
if input_files_json is None: # PCMDI internal setup | ||
searchstring = os.path.join( | ||
path, | ||
activity, | ||
institution, | ||
model, | ||
exp, | ||
variant, | ||
table, | ||
field, | ||
grid_label, | ||
version, | ||
"*.nc", | ||
) | ||
else: | ||
searchstring = os.path.join( | ||
ncfiles[exp][field]["path"], ncfiles[exp][field]["file"] | ||
) | ||
xmlname = os.path.join(xml_path, ".".join([exp, model, variant, field, "xml"])) | ||
os.system("cdscan -x " + xmlname + " " + searchstring) | ||
filenames[exp][field] = xmlname | ||
|
||
if debug: | ||
with open(os.path.join(output_path, "filenames.json"), "w") as f: | ||
json.dump(filenames, f, sort_keys=True, indent=4) | ||
|
||
# calculate all feedback components and Klein et al (2013) error metrics: | ||
fbk_dict, obsc_fbk_dict, err_dict = CloudRadKernel(filenames) | ||
|
||
print("calc done") | ||
|
||
# add this model's results to the pre-existing json file containing other models' results: | ||
updated_fbk_dict, updated_obsc_fbk_dict = organize_fbk_jsons( | ||
fbk_dict, obsc_fbk_dict, model, variant, datadir=data_path | ||
) | ||
updated_err_dict = organize_err_jsons(err_dict, model, variant, datadir=data_path) | ||
|
||
ecs = None | ||
if get_ecs: | ||
# calculate ECS and add it to the pre-existing json file containing other models' results: | ||
ecs = compute_ECS(filenames) | ||
print("calc ECS done") | ||
print("ecs: ", ecs) | ||
updated_ecs_dict = organize_ecs_jsons(ecs, model, variant, datadir=data_path) | ||
|
||
os.makedirs(output_path, exist_ok=True) | ||
if debug: | ||
with open(os.path.join(output_path, "fbk_dict.json"), "w") as f: | ||
json.dump(fbk_dict, f, sort_keys=True, indent=4) | ||
with open(os.path.join(output_path, "err_dict.json"), "w") as f: | ||
json.dump(err_dict, f, sort_keys=True, indent=4) | ||
with open(os.path.join(output_path, "updated_err_dict.json"), "w") as f: | ||
json.dump(updated_err_dict, f, sort_keys=True, indent=4) | ||
with open(os.path.join(output_path, "updated_fbk_dict.json"), "w") as f: | ||
json.dump(updated_fbk_dict, f, sort_keys=True, indent=4) | ||
with open(os.path.join(output_path, "updated_ecs_dict.json"), "w") as f: | ||
json.dump(updated_ecs_dict, f, sort_keys=True, indent=4) | ||
|
||
# generate plots and extract metrics from the plotting routines | ||
os.makedirs(figure_path, exist_ok=True) | ||
climo_cld_rmse, cld_fbk_rmse, assessed_cld_fbk, ecs = dataviz.make_all_figs( | ||
updated_fbk_dict, | ||
updated_obsc_fbk_dict, | ||
updated_err_dict, | ||
updated_ecs_dict, | ||
model, | ||
figdir=figure_path, | ||
datadir=data_path, | ||
debug=debug, | ||
) | ||
print("get metrics done") | ||
|
||
# save final metrics and accompanying important statistics in JSON format | ||
print("-- Metric result --") | ||
print("model:", model) | ||
print("variant:", variant) | ||
print("clim_cloud_rmse:", climo_cld_rmse) | ||
print("cloud_feedback_rmse:", cld_fbk_rmse) | ||
print("assessed_cloud_feedback:", assessed_cld_fbk) | ||
print("ecs:", ecs) | ||
|
||
output_dict = OrderedDict() | ||
output_dict["RESULTS"] = OrderedDict() | ||
output_dict["RESULTS"][model] = OrderedDict() | ||
output_dict["RESULTS"][model][variant] = OrderedDict() | ||
output_dict["RESULTS"][model][variant]["assessed_cloud_feedback"] = OrderedDict() | ||
output_dict["RESULTS"][model][variant]["assessed_cloud_feedback"]["high_cloud_altitude"] = assessed_cld_fbk[0] | ||
output_dict["RESULTS"][model][variant]["assessed_cloud_feedback"]["tropical_marine_low_cloud"] = assessed_cld_fbk[1] | ||
output_dict["RESULTS"][model][variant]["assessed_cloud_feedback"]["tropical_anvil_cloud_area"] = assessed_cld_fbk[2] | ||
output_dict["RESULTS"][model][variant]["assessed_cloud_feedback"]["land_cloud_amount"] = assessed_cld_fbk[3] | ||
output_dict["RESULTS"][model][variant]["assessed_cloud_feedback"]["middle_latitude_marine_low_cloud_amount"] = assessed_cld_fbk[4] | ||
output_dict["RESULTS"][model][variant]["assessed_cloud_feedback"]["high_latitude_low_cloud_optical_depth"] = assessed_cld_fbk[5] | ||
output_dict["RESULTS"][model][variant]["assessed_cloud_feedback"]["implied_unassessed"] = assessed_cld_fbk[6] | ||
output_dict["RESULTS"][model][variant]["assessed_cloud_feedback"]["sum_of_assessed"] = assessed_cld_fbk[7] | ||
output_dict["RESULTS"][model][variant]["assessed_cloud_feedback"]["total_cloud_feedback"] = assessed_cld_fbk[8] | ||
output_dict["RESULTS"][model][variant]["clim_cloud_rmse"] = climo_cld_rmse | ||
output_dict["RESULTS"][model][variant]["cloud_feedback_rmse"] = cld_fbk_rmse | ||
output_dict["RESULTS"][model][variant]["equilibrium_climate_sensitivity"] = ecs | ||
|
||
|
||
cloud_feedback_metrics_to_json( | ||
output_path, output_json_filename, output_dict, cmec_flag=cmec | ||
) | ||
|
||
print("Done!") |
Binary file added
BIN
+57 MB
pcmdi_metrics/cloud_feedback/data/AC_clisccp_ISCCP_HGG_198301-200812.nc
Binary file not shown.
Binary file added
BIN
+122 KB
pcmdi_metrics/cloud_feedback/data/AC_clisccp_wap_ISCCP_HGG_198301-200812.nc
Binary file not shown.
Binary file not shown.
Oops, something went wrong.