Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

updated_processings_v20231204 #77

Open
wants to merge 38 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
2623a7a
obs2obs updated
yyplanton Mar 10, 2021
80df737
corrections: this version ran all metrics on my laptop
yyplanton Apr 9, 2021
8ec586a
obs_interpreter added in this version (possibility to interpret obs a…
yyplanton Apr 12, 2021
06386b2
bias lhf, lwr, shf, swr, thf added to the metric list
yyplanton Apr 13, 2021
39e12ba
updated metrics
yyplanton May 14, 2021
4c8b943
pr, lhf, lwr, shf, ssh, swr, taux, tauy, thf for bias, seasonal cycle…
yyplanton May 20, 2021
af5d47e
new teleconnections metrics
yyplanton Jun 11, 2021
255c801
driver for new plot template and CDAT lib
yyplanton Jun 11, 2021
7af26be
possibility to compute telecon during common era (1982-2014), extende…
yyplanton Jun 11, 2021
caa1934
corrected telecon metrics
yyplanton Jun 15, 2021
2684c8a
corrected telecon metrics
yyplanton Jun 15, 2021
fed1793
corrected telecon metrics
yyplanton Jun 15, 2021
d647689
corrected telecon metrics
yyplanton Jun 15, 2021
c6abfeb
corrected telecon metrics
yyplanton Jun 15, 2021
8168605
telecon metrics corrections (significance mask) and plot functions
yyplanton Jun 18, 2021
542efe7
the obs and model masks are no longer put together after regrid if th…
yyplanton Jun 22, 2021
2bbfecb
telecon metrics corrections (significance mask) and plot functions
yyplanton Jul 23, 2021
ac6c682
ave_ts_box and nstar for ENSO internal variability paper
yyplanton Mar 30, 2022
4641991
ave_ts_box mv is float now
yyplanton Mar 30, 2022
d69b572
nstar and stat_box created to be run with any variable and any region
yyplanton Sep 8, 2022
3f2ee49
removes stat_box_ave_pr_global from ENSO_IV metrics collection
yyplanton Sep 8, 2022
481dd3f
sst anomalies time series saved in NetCDF when EnsoAmpl is computed
yyplanton Sep 20, 2022
649fac5
typo fix
lee1043 Sep 20, 2022
e0cd86d
sst anomalies time series saved in NetCDF when EnsoAmpl is computed
yyplanton Jan 1, 2023
ca95aba
added metric collection 'ENSO_eq_stats'
yyplanton Jan 1, 2023
4d263f5
N3 SST mean, skewness, variance added to metric collection 'ENSO_eq_s…
yyplanton Jan 3, 2023
4a215ca
EnsoCollectionsLib.py
yyplanton Jan 12, 2023
14dbc70
EnsoCollectionsLib.py
yyplanton Jan 17, 2023
8506ae7
EnsoMetricsLib.py
yyplanton Jan 18, 2023
6f13614
EnsoCollectionsLib.py
yyplanton Jan 23, 2023
12d4de1
add dev.yml for dependencies
lee1043 Dec 4, 2023
4f9e5a8
keep only metric 'stat_box'
Dec 5, 2023
f256f7b
add nc-time-axis as one of dependency
lee1043 Dec 6, 2023
949453f
remove pmp driver related codes as they were fully migrated to the PMP
lee1043 Dec 6, 2023
8234999
xcdat functions separated from the rest of the code
Dec 8, 2023
806c759
@yyplanton and @lee1043 are working on this, in progress
lee1043 Dec 8, 2023
0a08c78
xcdat functions separated from the rest of the code
Nov 29, 2024
65a96df
processors update
yyplanton Dec 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .idea/ENSO_metrics.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 7 additions & 3 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions conda-env/dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Conda pcmdi_metrics development environment
name: enso_metrics_dev
channels:
- conda-forge
- defaults
dependencies:
# ==================
# Base
# ==================
# NOTE: If versions are updated, also `additional_dependencies` list for mypy in `.pre-commit-config.yaml`
- python=3.10.10
- pip=23.1.2
- numpy=1.23.5
- cartopy=0.22.0
- matplotlib=3.7.1
- cdat_info=8.2.1
- cdms2=3.1.5
- genutil=8.2.1
- cdutil=8.2.1
- seaborn=0.12.2
- xcdat=0.6.1
- setuptools=67.7.2
- regionmask=0.9.0
- nc-time-axis=1.4.1

prefix: /opt/miniconda3/envs/enso_metrics_dev
2 changes: 1 addition & 1 deletion conda/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ about:
home: http://github.com/eguil/Enso_metrics
license: 'CCLRC'
license_file: LICENSE
summary: "Library to compute ENSO metrics"
summary: "Library to compute ENSO recipes"

extra:
recipe-maintainers:
Expand Down
2,791 changes: 2,791 additions & 0 deletions enso_metrics/EnsoCollectionsLib.py

Large diffs are not rendered by default.

193 changes: 193 additions & 0 deletions enso_metrics/EnsoComputeMetricsLib.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
# -*- coding:UTF-8 -*-
# ---------------------------------------------------------------------------------------------------------------------#
# Functions to compute collections or recipes
# ---------------------------------------------------------------------------------------------------------------------#


# ---------------------------------------------------#
# Import packages
# ---------------------------------------------------#
# basic python package
from copy import deepcopy
from inspect import getmembers, isfunction
from typing import Union

# local functions
from enso_metrics import recipes
# ---------------------------------------------------#


# ---------------------------------------------------------------------------------------------------------------------#
# Functions
# ---------------------------------------------------------------------------------------------------------------------#
all_recipe = dict((k[0], k[1]) for k in getmembers(recipes, isfunction))


def compute_metric(
metric: str,
metric_param: dict,
project: str,
model: str,
experiment: str,
member: str,
dict_mod: dict[
str, dict[
str, Union[int, float, str, list[str], None, dict[
str, Union[int, float, None]]]]],
dict_obs: dict[
str, dict[
str, dict[
str, Union[int, float, str, list[str], None, dict[
str, Union[int, float, None]]]]]],
**kwargs):
#
# -- compute model and observations one after the others
#
# put model and obs in a single dictionary
dict_a = {model: dict_mod}
dict_a.update(dict_obs)
# loop on datasets
for dat, dic in dict_a.items():
if metric not in list(all_recipe.keys()):
continue
# update metric_param
metric_p = deepcopy(metric_param)
metric_p["time_bounds"] = metric_param["time_bounds_mod"] if dat == model else metric_param["time_bounds_obs"]
diagnostic = all_recipe[metric](
dic, dataset=modelName, debug=debug, netcdf=netcdf, netcdf_name=netcdf_name,
metname=tmp_metric, **keyarg)
else:
diagnostic1 = None
list_strings = ["ERROR" + EnsoErrorsWarnings.message_formating(INSPECTstack()) + ": metric",
str().ljust(5) + "unknown metric name: " + str(metric)]
EnsoErrorsWarnings.my_error(list_strings)
#
# observations diag
#
diag_obs = dict()
keyarg["time_bounds"] = keyarg["time_bounds_obs"]
for ii in range(len(obsNameVar1)):
# sets observations
keyarg["project_interpreter_var1"] = \
"CMIP" if obs_interpreter == "CMIP" else deepcopy(obsInterpreter1[ii])
if metric in list(dict_oneVar.keys()):
output_name = deepcopy(obsNameVar1[ii])
if output_name != modelName:
print("\033[94m" + str().ljust(5) + "ComputeMetric: oneVarmetric = " + str(output_name) +
"\033[0m")
diag_obs[output_name] = dict_oneVar[metric](
obsFile1[ii], obsVarName1[ii], obsFileArea1[ii], obsAreaName1[ii], obsFileLandmask1[ii],
obsLandmaskName1[ii], regionVar1, dataset=output_name, debug=debug, netcdf=netcdf,
netcdf_name=netcdf_name, metname=tmp_metric, **keyarg)
del output_name
elif metric in list(dict_twoVar.keys()):
for jj in range(len(obsNameVar2)):
output_name = deepcopy(obsNameVar1[ii]) + "_" + deepcopy(obsNameVar2[jj])
keyarg["project_interpreter_var2"] = \
"CMIP" if obs_interpreter == "CMIP" else deepcopy(obsInterpreter2[jj])
# if obsNameVar1[ii] == "Tropflux":
# if ("AVISO" in obsNameVar2[jj] and obsNameVar1[ii] == "Tropflux") or \
# obsNameVar2[jj] == obsNameVar1[ii]:
if output_name != modelName:
print("\033[94m" + str().ljust(5) + "ComputeMetric: twoVarmetric = " + str(output_name) +
"\033[0m")
diag_obs[output_name] = dict_twoVar[metric](
obsFile1[ii], obsVarName1[ii], obsFileArea1[ii], obsAreaName1[ii], obsFileLandmask1[ii],
obsLandmaskName1[ii], regionVar1, obsFile2[jj], obsVarName2[jj], obsFileArea2[jj],
obsAreaName2[jj], obsFileLandmask2[jj], obsLandmaskName2[jj], regionVar2,
dataset=output_name, debug=debug, netcdf=netcdf, netcdf_name=netcdf_name,
metname=tmp_metric, **keyarg)
del output_name
del keyarg["project_interpreter_var2"]
del keyarg["project_interpreter_var1"]
for obs in list(diag_obs.keys()):
# computes the metric
metric_val, metric_err, description_metric = math_metric_computation(
diagnostic1["value"], diagnostic1["value_error"], obs=diag_obs[obs]["value"],
obs_err=diag_obs[obs]["value_error"], keyword=keyarg["metric_computation"])
dict_metric_val[obs] = {"value": metric_val, "value_error": metric_err}
# puts metric / diagnostic values in its proper dictionary
dict_diagnostic[obs] = {"value": diag_obs[obs]["value"], "value_error": diag_obs[obs]["value_error"]}
if "nonlinearity" in list(diag_obs[obs].keys()):
dict_diagnostic[obs]["nonlinearity"] = diag_obs[obs]["nonlinearity"]
dict_diagnostic[obs]["nonlinearity_error"] = diag_obs[obs]["nonlinearity_error"]
if "dive_down_diag" in list(diag_obs[obs].keys()):
dict_dive_down[obs] = diag_obs[obs]["dive_down_diag"]["value"]
for elt in list(diag_obs[obs]["dive_down_diag"].keys()):
if elt not in ["value"]:
try:
dict_dive_down_metadata[obs]
except:
dict_dive_down_metadata[obs] = {elt: diag_obs[obs]["dive_down_diag"][elt]}
else:
dict_dive_down_metadata[obs][elt] = diag_obs[obs]["dive_down_diag"][elt]
# puts diagnostic metadata in its proper dictionary
dict_diagnostic_metadata[obs] = {
"name": obs, "nyears": diag_obs[obs]["nyears"], "time_period": diag_obs[obs]["time_period"],
}
if "events_model" in list(diag_obs[obs].keys()):
dict_diagnostic_metadata[obs]["events"] = diag_obs[obs]["events"]
if "keyerror" in list(diag_obs[obs].keys()):
dict_diagnostic_metadata[obs]["keyerror"] = diag_obs[obs]["keyerror"]
if keyarg["metric_computation"] in ["ratio", "relative_difference"]:
units = diagnostic1["units"] + " / " + diagnostic1["units"]
elif keyarg["metric_computation"] in ["abs_relative_difference"]:
units = "%"
else:
units = diagnostic1["units"]
try: del keyarg["time_bounds"]
except: pass
# finishes to fill the diagnostic dictionary
list_keys = ["method", "name", "ref", "time_frequency", "units"]
for key in list_keys:
if key == "method":
dict_diagnostic_metadata[key] = diagnostic1["method"]
dict_dive_down_metadata[key] = diagnostic1["method"]
try:
diagnostic1["nonlinearity"]
except:
pass
else:
dict_diagnostic_metadata["method_nonlinearity"] = diagnostic1["method_nonlinearity"]
else:
dict_diagnostic_metadata[key] = diagnostic1[key]
dict_dive_down_metadata[key] = diagnostic1[key]
# creates the output dictionaries
dict_metrics = {"metric": dict_metric_val, "diagnostic": dict_diagnostic}
datasets = modelName + "; "
for ii in range(len(obsNameVar1)):
if isinstance(obsVarName1[ii], list):
datasets = datasets + obsNameVar1[ii] + "'s "
for jj in range(len(obsVarName1[ii])):
datasets += obsVarName1[ii][jj]
if jj != len(obsVarName1[ii]) - 1:
datasets += " & "
else:
datasets = datasets + obsNameVar1[ii] + "'s " + obsVarName1[ii]
if ii != len(obsNameVar1) - 1:
datasets = datasets + "; "
if len(obsNameVar2) > 0:
datasets = datasets + "; "
for ii in range(len(obsNameVar2)):
if isinstance(obsVarName2[ii], list):
datasets = datasets + obsNameVar2[ii] + "'s "
for jj in range(len(obsVarName2[ii])):
datasets += obsVarName2[ii][jj]
if jj != len(obsVarName2[ii]) - 1:
datasets += " & "
else:
datasets = datasets + obsNameVar2[ii] + "'s " + obsVarName2[ii]
if ii != len(obsNameVar2) - 1:
datasets = datasets + "; "
if multimetric is True:
tmp = {"name": metric, "method": description_metric, "datasets": datasets}
for key in lkeys:
tmp[key + "__units"] = diagnostic1[key + "__units"]
dict_metadata = {"metric": tmp, "diagnostic": dict_diagnostic_metadata}
else:
dict_metadata = {
"metric": {"name": metric, "method": description_metric, "datasets": datasets, "units": units},
"diagnostic": dict_diagnostic_metadata,
}
return dict_metrics, dict_metadata, dict_dive_down, dict_dive_down_metadata
# ---------------------------------------------------------------------------------------------------------------------#
Loading