-
Notifications
You must be signed in to change notification settings - Fork 33
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
JJB tropical subseasonal diags - Wheeler and Kiladis #732
Merged
Merged
Changes from all commits
Commits
Show all changes
49 commits
Select commit
Hold shift + click to select a range
943030b
Initial commit of tropical subseasonal diagnostics
jjbenedict 88e5884
add stand alone driver to reproduce Jim's results
chengzhuzhang 58d0b5a
add plotting; clean up driver
chengzhuzhang f40d46a
add viwer
chengzhuzhang 4ac2e66
zoom in MJO;use diff ratio
chengzhuzhang 1166fd2
[Refactor]: Update `e3sm_diags_driver.run_diags` as `CoreParameter` m…
tomvothecoder 091d9ee
[Doc]: Add GitHub issues and pull request templates (#741)
tomvothecoder 336be9b
fix typo (#753)
chengzhuzhang 9cc56f3
Update DevOps configs (#755)
tomvothecoder 28ea590
Replace `parser.readfp()` with `parser.read_file()` for Python 3.12 s…
tomvothecoder 14a6b97
Add more aerosol metrics (#763)
mahf708 059c71c
Bump to 2.10.0 (#766)
tomvothecoder ecc5f2a
[Refactor]: Refactor integration tests and add `use_cfg` flag to `run…
tomvothecoder 04ffd97
Fix type conditional check and `UnboundLocalError` for `params_result…
tomvothecoder d1ed07f
Bump to 2.10.1rc1 (#771)
tomvothecoder 59a16e1
Port over `cdp_viewer.OutputViewer` and remove `cdp` dependency (#773)
tomvothecoder f575065
Fix default diagnostics attrs not being copied to parent CoreParamete…
tomvothecoder a12ac88
Bump to 2.10.1 (#780)
tomvothecoder 2cd644a
Fix `cosp_histogram_driver.py` not writing mean variables to netCDF (…
tomvothecoder 64ffabc
update zppy cfg for perlmutter (#783)
chengzhuzhang d951535
Update README.md
chengzhuzhang 29acef2
Support monthly average and variable name convention for EAMxx (#712)
chengzhuzhang 22fb716
Update intercomparison with cmip models workflow (#786)
chengzhuzhang 765210c
put everything together in source
chengzhuzhang 9768b79
fix formatting
chengzhuzhang 13c5be8
fix viewer
chengzhuzhang 29e9caa
support model vs model
chengzhuzhang 2f6cec2
fix format
chengzhuzhang 8b851e2
Fix for OLR
chengzhuzhang 2bdbd08
fix diff ratio
chengzhuzhang c693e8a
fix viewer
chengzhuzhang 06d3325
Merge branch 'main' into jjb_tropical_subseasonal_diags
chengzhuzhang 1664941
fix pre-commit problems; clean up
chengzhuzhang ca0ded4
Apply Tom's suggestions from code review
chengzhuzhang 0422f98
correct print out start end year for subset data
chengzhuzhang f0f7253
fix dispersion curves for antisymmetric
chengzhuzhang 31dc8cd
fix formatting
chengzhuzhang 0cc310c
fix importing zwf_functions
chengzhuzhang 913293f
address code review; clean up
chengzhuzhang 1921965
address code review; clean up
chengzhuzhang d1f4b94
Revert "address code review; clean up"
chengzhuzhang a8bcf9e
update README.md
chengzhuzhang 78d4fb8
update mp_partition with similar time subsetting
chengzhuzhang e334b15
updated original zwf_plot.py to allow dispersion curvers to cross zer…
jjbenedict 0db4fa0
update dispersion lines labels
chengzhuzhang d87c554
update contour map colorbars
chengzhuzhang 9fff78d
fix colarbar try2
chengzhuzhang a6f58d2
Merge branch 'main' into jjb_tropical_subseasonal_diags
chengzhuzhang 82f97fd
Merge branch 'main' into jjb_tropical_subseasonal_diags
chengzhuzhang File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
26 changes: 26 additions & 0 deletions
26
auxiliary_tools/tropical_subseasonal_diags/run_tropical_subseasonal.py
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,26 @@ | ||
import os | ||
from e3sm_diags.parameter.tropical_subseasonal_parameter import TropicalSubseasonalParameter | ||
from e3sm_diags.run import runner | ||
|
||
param = TropicalSubseasonalParameter() | ||
|
||
param.reference_data_path = '/global/cfs/cdirs/e3sm/e3sm_diags/obs_for_e3sm_diags/time-series' | ||
#param.reference_data_path = '/global/cfs/cdirs/e3sm/chengzhu/e3sm_diags_zppy_test_complete_run_output/v2.LR.historical_0101_20240130/post/atm/180x360_aave/ts/daily/15yr' | ||
param.test_data_path = '/global/cfs/cdirs/e3sm/chengzhu/e3sm_diags_zppy_test_complete_run_output/v2.LR.historical_0101_20240130/post/atm/180x360_aave/ts/daily/15yr' | ||
param.test_name = 'E3SMv2' | ||
prefix = '/Users/zhang40/Documents/repos/e3sm_diags/auxiliary_tools/tropical_subseasonal_diags/data1' | ||
prefix = '/global/cfs/cdirs/e3sm/www/chengzhu/tests/tropical_diags_subsetting' | ||
|
||
param.results_dir = os.path.join(prefix, 'tropical_variability_model_obs_refine') | ||
#param.run_type = "model_vs_model" | ||
#param.ref_name = 'E3SMv2' | ||
param.test_start_yr = '2000' | ||
param.test_end_yr = '2000' | ||
param.ref_start_yr = '2001' | ||
param.ref_end_yr = '2001' | ||
param.save_netcdf = True | ||
|
||
runner.sets_to_run = ['tropical_subseasonal'] | ||
runner.run_diags([param]) | ||
|
||
|
28 changes: 28 additions & 0 deletions
28
auxiliary_tools/tropical_subseasonal_diags/tropical_diags.cfg
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,28 @@ | ||
[#] | ||
sets = ["tropical_subseasonal"] | ||
case_id = "wavenumber-frequency" | ||
variables = ["PRECT"] | ||
ref_name = "IMERG_Daily" | ||
reference_name = "IMERG Daily" | ||
# (2001-2021)" | ||
regions = ["15S15N"] | ||
# | ||
|
||
[#] | ||
sets = ["tropical_subseasonal"] | ||
case_id = "wavenumber-frequency" | ||
variables = ["FLUT"] | ||
ref_name = "NOAA-OLR_Daily" | ||
reference_name = "NOAA OLR Daily" | ||
# (1979-2021)" | ||
regions = ["15S15N"] | ||
# | ||
# | ||
#[#] | ||
#sets = ["tropical_subseasonal"] | ||
#case_id = "wavenumber-frequency" | ||
#variables = ["U850"] | ||
#ref_name = "ERA5_Daily" | ||
#reference_name = "ERA5 Daily" | ||
## (1980-2022)" | ||
#regions = ["15S15N"] |
196 changes: 196 additions & 0 deletions
196
auxiliary_tools/tropical_subseasonal_diags/tropical_subseasonal_driver.py
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,196 @@ | ||
from __future__ import annotations | ||
|
||
import glob | ||
import json | ||
import os | ||
from typing import TYPE_CHECKING # , Optional | ||
|
||
import numpy as np | ||
import xarray as xr | ||
|
||
import e3sm_diags | ||
from e3sm_diags.driver import utils | ||
from e3sm_diags.logger import custom_logger | ||
from e3sm_diags.plot.cartopy.mp_partition_plot import plot | ||
import matplotlib.pyplot as plt | ||
from matplotlib.colors import ListedColormap, BoundaryNorm | ||
|
||
from tropical_subseasonal_plot import plot | ||
from tropical_subseasonal_viewer import create_viewer | ||
from zwf import zwf_functions as wf | ||
|
||
logger = custom_logger(__name__) | ||
|
||
# Script to compute and plot spectral powers of a subseasonal tropical field in | ||
# zonal wavenumber-frequency space. Both the plot files and files containing the | ||
# associated numerical data shown in the plots are created. | ||
|
||
# Authors: Jim Benedict and Brian Medeiros | ||
# Modified by Jill Zhang to integrate into E3SM Diags. | ||
|
||
def find_nearest(array, value): | ||
array = np.asarray(array) | ||
idx = (np.abs(array - value)).argmin() | ||
return idx,array[idx] | ||
"""Return index of [array] closest in value to [value] | ||
Example: | ||
array = [ 0.21069679 0.61290182 0.63425412 0.84635244 0.91599191 0.00213826 | ||
0.17104965 0.56874386 0.57319379 0.28719469] | ||
print(find_nearest(array, value=0.5)) | ||
# 0.568743859261 | ||
|
||
""" | ||
|
||
def wf_analysis(x, **kwargs): | ||
"""Return zonal wavenumber-frequency power spectra of x. The returned spectra are: | ||
spec_sym: Raw (non-normalized) power spectrum of the component of x that is symmetric about the equator. | ||
spec_asym: Raw (non-normalized) power spectrum of the component of x that is antisymmetric about the equator. | ||
nspec_sym: Normalized (by a smoothed red-noise background spectrum) power spectrum of the component of x that is symmetric about the equator. | ||
nspec_asym: Normalized (by a smoothed red-noise background spectrum) power spectrum of the component of x that is antisymmetric about the equator. | ||
|
||
The NCL version of 'wkSpaceTime' smooths the symmetric and antisymmetric components | ||
along the frequency dimension using a 1-2-1 filter once. | ||
|
||
""" | ||
# Get the "raw" spectral power | ||
# OPTIONAL kwargs: | ||
# segsize, noverlap, spd, latitude_bounds (tuple: (south, north)), dosymmetries, rmvLowFrq | ||
|
||
z2 = wf.spacetime_power(x, **kwargs) | ||
z2avg = z2.mean(dim='component') | ||
z2.loc[{'frequency':0}] = np.nan # get rid of spurious power at \nu = 0 (mean) | ||
|
||
# Following NCL's wkSpaceTime, apply one pass of a 1-2-1 filter along the frequency | ||
# domain to the raw (non-normalized) spectra/um. | ||
# Do not use 0 frequency when smoothing here. | ||
# Use weights that sum to 1 to ensure that smoothing is conservative. | ||
z2s = wf.smoothFrq121(z2,1) | ||
|
||
# The background is supposed to be derived from both symmetric & antisymmetric | ||
# Inputs to the background spectrum calculation should be z2avg | ||
background = wf.smoothBackground_wavefreq(z2avg) | ||
# separate components | ||
spec_sym = z2s[0,...] | ||
spec_asy = z2s[1,...] | ||
# normalize: Following NCL's wkSpaceTime, use lightly smoothed version of spectra/um | ||
# as numerator | ||
nspec_sym = spec_sym / background | ||
nspec_asy = spec_asy / background | ||
|
||
spec = xr.merge([spec_sym.rename('spec_raw_sym'), spec_asy.rename('spec_raw_asy'), nspec_sym.rename('spec_norm_sym'), nspec_asy.rename('spec_norm_asy'), background.rename('spec_background')], compat='override') | ||
spec_all = spec.drop('component') | ||
spec_all['spec_raw_sym'].attrs = {"component": "symmetric", "type": "raw"} | ||
spec_all['spec_raw_asy'].attrs = {"component": "antisymmetric", "type": "raw"} | ||
spec_all['spec_norm_sym'].attrs = {"component": "symmetric", "type": "normalized"} | ||
spec_all['spec_norm_asy'].attrs = {"component": "antisymmetric", "type": "normalized"} | ||
spec_all['spec_background'].attrs = {"component": "", "type": "background"} | ||
|
||
return spec_all | ||
|
||
|
||
def calculate_spectrum(path, variable): | ||
|
||
var = xr.open_mfdataset(glob.glob(f"{test_data_path}/{variable}_*.nc")).sel( | ||
lat=slice(-15, 15))[variable] | ||
|
||
# TODO: subset time | ||
|
||
# Unit conversion | ||
if var.name == "PRECT": | ||
if var.attrs["units"] == "m/s" or var.attrs["units"] == "m s{-1}": | ||
print("\nBEFORE unit conversion: Max/min of data: " + str(var.values.max()) + " " + str(var.values.min())) | ||
var.values = var.values * 1000. * 86400. # convert m/s to mm/d, do not alter metadata (yet) | ||
var.attrs["units"] = "mm/d" # adjust metadata to reflect change in units | ||
print("\nAFTER unit conversion: Max/min of data: " + str(var.values.max()) + " " + str(var.values.min())) | ||
if var.name == "precipAvg": | ||
if var.attrs["units"] == "mm/hr": | ||
print("\nBEFORE unit conversion: Max/min of data: " + str(var.values.max()) + " " + str(var.values.min())) | ||
var.values = data.values * 24. # convert mm/hr to mm/d, do not alter metadata (yet) | ||
var.attrs["units"] = "mm/d" # adjust metadata to reflect change in units | ||
print("\nAFTER unit conversion: Max/min of data: " + str(var.values.max()) + " " + str(var.values.min())) | ||
|
||
# Wavenumber Frequency Analysis | ||
spec_all = wf_analysis(var, **opt) | ||
#spec_all.to_netcdf(outDataDir + "/full_spec.nc") | ||
return spec_all | ||
|
||
# | ||
# Options ... right now these only go into wk.spacetime_power() | ||
# | ||
do_zooming = False # Set to True to also make plots to zoom into MJO spectral region, | ||
# in addition to the default (larger) spectral region | ||
latBound = (-15,15) # latitude bounds for analysis | ||
spd = 1 # SAMPLES PER DAY | ||
nDayWin = 96 # Wheeler-Kiladis [WK] temporal window length (days) | ||
nDaySkip = -60 # time (days) between temporal windows [segments] | ||
# negative means there will be overlapping temporal segments | ||
twoMonthOverlap = -1*nDaySkip | ||
|
||
vari = "PRECT" | ||
srcID = "model" | ||
outDataDir = "/global/cfs/cdirs/e3sm/www/chengzhu/tests/tropical_diags" | ||
outDataDir = "/Users/zhang40/Documents/repos/e3sm_diags/auxiliary_tools/tropical_subseasonal_diags/data" | ||
|
||
opt = {'segsize': nDayWin, | ||
'noverlap': twoMonthOverlap, | ||
'spd': spd, | ||
'latitude_bounds': latBound, | ||
'dosymmetries': True, | ||
'rmvLowFrq':True} | ||
|
||
|
||
#datapath = '/global/cfs/cdirs/e3sm/forsyth/E3SMv2/v2.LR.historical_0201/post/atm/180x360_aave/ts/daily/5yr' | ||
datapath = '/Users/zhang40/Documents/e3sm_diags_data/e3sm_diags_test_data/E3SM_v2_daily' | ||
|
||
from e3sm_diags.parameter.core_parameter import CoreParameter | ||
parameter = CoreParameter() | ||
|
||
test_data_path = '/Users/zhang40/Documents/e3sm_diags_data/e3sm_diags_test_data/E3SM_v2_daily' | ||
parameter.test_data_path = test_data_path | ||
parameter.test_timeseries_input = True | ||
parameter.test_start_yr = '2000' | ||
parameter.test_end_yr = '2014' | ||
parameter.ref_data_path = test_data_path | ||
parameter.ref_timeseries_input = True | ||
parameter.ref_start_yr = '2000' | ||
parameter.ref_end_yr = '2014' | ||
parameter.variables = ['PRECT'] | ||
season = "ANN" | ||
|
||
test_data = utils.dataset.Dataset(parameter, test=True) | ||
parameter.test_name_yrs = utils.general.get_name_and_yrs( | ||
parameter, test_data, season | ||
) | ||
|
||
ref_data = utils.dataset.Dataset(parameter, ref=True) | ||
parameter.ref_name_yrs = utils.general.get_name_and_yrs( | ||
parameter, ref_data, season | ||
) | ||
|
||
for variable in parameter.variables: | ||
#test = calculate_spectrum(parameter.test_data_path, variable) | ||
#test.to_netcdf("data/full_spec_test.nc") | ||
#ref = calculate_spectrum(parameter.ref_data_path, variable) | ||
#ref.to_netcdf("data/full_spec_ref.nc") | ||
# Below uses intermediate saved files for development | ||
test = xr.open_dataset("/Users/zhang40/Documents/repos/e3sm_diags/auxiliary_tools/tropical_subseasonal_diags/data/full_spec_ref.nc").load() | ||
ref = xr.open_dataset("/Users/zhang40/Documents/repos/e3sm_diags/auxiliary_tools/tropical_subseasonal_diags/data/full_spec_ref.nc").load() | ||
parameter.var_id = variable | ||
|
||
for diff_name in ["raw_sym", "raw_asy", "norm_sym", "norm_asy", "background"]: | ||
|
||
# Compute percentage difference | ||
diff = 100 * (test[f"spec_{diff_name}"]-ref[f"spec_{diff_name}"])/ref[f"spec_{diff_name}"] | ||
diff.name = f"spec_{diff_name}" | ||
diff.attrs.update(test[f"spec_{diff_name}"].attrs) | ||
parameter.spec_type = diff_name | ||
plot(parameter, test[f"spec_{diff_name}"], ref[f"spec_{diff_name}"], diff) | ||
if "norm" in diff_name: | ||
parameter.spec_type = f"{diff_name}_zoom" | ||
plot(parameter, test[f"spec_{diff_name}"], ref[f"spec_{diff_name}"], diff, do_zoom = True) | ||
|
||
|
||
|
||
display_name, url = create_viewer('.', parameter) | ||
print("Viewer Created: ", url) | ||
|
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest addressing
pre-commit
issues inzwf_functions
for long-term maintainability and readability rather than excluding them.It'll make debugging and updating (if needed) much easier in the future.