Skip to content

Commit 7d29489

Browse files
author
drewmresnick
committed
changing diagnostics code to start incorporating envt vars; change file name
1 parent 5247949 commit 7d29489

File tree

1 file changed

+217
-0
lines changed

1 file changed

+217
-0
lines changed
+217
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
#Load libraries
2+
import os
3+
import xarray as xr
4+
import numpy as np
5+
import pandas as pd
6+
#import eccodes
7+
from sklearn.cluster import KMeans
8+
from sklearn.decomposition import PCA
9+
import cartopy.crs as ccrs
10+
from cartopy import feature
11+
import matplotlib.pyplot as plt
12+
from matplotlib.colors import LinearSegmentedColormap
13+
# key PyWR functions are imported here
14+
from PyWR import *
15+
16+
17+
#The data used in this diagnostic was downloaded from the IRI:
18+
#https://iridl.ldeo.columbia.edu/?Set-Language=en
19+
#If data of a similar nature is desired, refer to the prep_data.py file for instructions on how to download anomaly data from the http server
20+
21+
22+
#HOW WOULD THE DATA FILE BE INPUT IN THIS NAME FORMAT
23+
hgt_input_path = "{DATADIR}/day/{CASENAME}.{hgt_var}.day.nc".format(**os.environ)
24+
t2m_input_path = "{DATADIR}/day/{CASENAME}.{t2m_var}.day.nc".format(**os.environ)
25+
pr_input_path = "{DATADIR}/day/{CASENAME}.{pr_var}.day.nc".format(**os.environ)
26+
27+
#Trying to write the open_ds using environment variables here for a single variable; the other variables are kept as original code for now
28+
29+
reanalysis = xr.open_dataset(hgt_input_path, decode_cf = True, decode_times = True).stack(time=['T'], grid=['Y', 'X'])
30+
#reanalysis = xr.open_dataset('WUS/data/hgt_NNRP_rean.nc', decode_cf = True, decode_times = True).stack(time=['T'], grid=['Y', 'X'])
31+
32+
#old code still retained
33+
rainfall = xr.open_dataset('WUS/data/rainfall_cpc.nc', decode_cf = True, decode_times = True).stack(time=['T'], grid=['Y', 'X'])
34+
t2m = xr.open_dataset('WUS/data/t2m_cpc.nc', decode_cf = True, decode_times = True).stack(time=['T'], grid=['Y', 'X'])
35+
uwnd = xr.open_dataset('WUS/data/u_NNRP_rean.nc', decode_cf = True, decode_times = True).stack(time=['T'], grid=['Y', 'X'])
36+
vwnd = xr.open_dataset('WUS/data/v_NNRP_rean.nc', decode_cf = True, decode_times = True).stack(time=['T'], grid=['Y', 'X'])
37+
38+
39+
#get rid of dummy pressure coordinate
40+
reanalysis=reanalysis.isel(P=0)
41+
uwnd=uwnd.isel(P=0)
42+
vwnd=vwnd.isel(P=0)
43+
44+
45+
#viewing the data
46+
print(reanalysis)
47+
print(rainfall)
48+
print(t2m)
49+
print(vwnd)
50+
print(uwnd)
51+
52+
53+
#DIMENSION REDUCTION: choose a percentage of variance explained that we will require
54+
n_eof = get_number_eof(X=reanalysis['adif'].values, var_to_explain=0.9, plot=True)
55+
56+
#project the data onto the leading EOFs to get the principal component time series
57+
#We will retain the PCA model for use later. The reanalysis_pc variable is now indexed [time, EOF]
58+
pca_model = PCA(n_components=n_eof).fit(reanalysis['adif'].values)
59+
reanalysis_pc = pca_model.transform(reanalysis['adif'].values)
60+
61+
62+
#REANALYSIS WEATHER TYPING: perform the clustering. We will manually specify the number of clusters we want to create and the number of simulations we want to run
63+
ncluster = 6 # use 6 WTs
64+
n_sim = 50 # typically 25-50 -- try 25 for quick preliminary computation only
65+
66+
centroids, wtypes = loop_kmeans(X=reanalysis_pc, n_cluster=ncluster, n_sim=n_sim)
67+
class_idx, best_part = get_classifiability_index(centroids)
68+
print('The classifiability index is {}'.format(class_idx))
69+
70+
71+
#Now that we have identified a suitable partition, we can use it to keep only the corresponding centroid and set of weather type labels. Use centroids to define KMeans object
72+
best_fit = KMeans(n_clusters=ncluster, init=centroids[best_part, :, :], n_init=1, max_iter=1).fit(reanalysis_pc)
73+
74+
# start with reanalysis
75+
reanalysis_composite = reanalysis.copy()
76+
model_clust = best_fit.fit_predict(reanalysis_pc) # get centroids
77+
weather_types = xr.DataArray(
78+
model_clust,
79+
coords = {'time': reanalysis_composite['time']},
80+
dims='time'
81+
)
82+
reanalysis_composite['WT'] = weather_types
83+
reanalysis_composite = reanalysis_composite.groupby('WT').mean(dim='time').unstack('grid')['adif']
84+
reanalysis_composite['M'] = 0
85+
86+
wt_anomalies = [] # initialize empty list
87+
wt_anomalies.append(reanalysis_composite)
88+
89+
wt_anomalies = xr.concat(wt_anomalies, dim='M') # join together
90+
wt_anomalies['WT'] = wt_anomalies['WT'] + 1 # start from 1
91+
92+
93+
#FIGURE: prepare a figure with rainfall and temperature composites
94+
#Hashed out options for adding wind arrows, and additional plot labels
95+
96+
X, Y = np.meshgrid(reanalysis['adif'].X, reanalysis['adif'].Y)
97+
map_proj = ccrs.PlateCarree() #ccrs.Orthographic(-110, 10)
98+
data_proj = ccrs.PlateCarree()
99+
wt_unique = np.unique(wt_anomalies['WT'])
100+
figsize = (14, 8)
101+
102+
#WT proportions
103+
wt=weather_types.to_dataframe(name='WT')
104+
wt=wt+1
105+
#wt.to_netcdf('data/t2m_cpc.nc', format="NETCDF4")
106+
wt_counts = wt.groupby('WT').size().div(wt['WT'].size)
107+
wt_counts
108+
109+
xmin,xmax = reanalysis['X'].min(), reanalysis['X'].max()
110+
ymin,ymax = reanalysis['Y'].min(), reanalysis['Y'].max()
111+
112+
# Set up the Figure
113+
plt.rcParams.update({'font.size': 12})
114+
fig, axes = plt.subplots(
115+
nrows=3, ncols=len(wt_unique), subplot_kw={'projection': map_proj},
116+
figsize=figsize, sharex=True, sharey=True
117+
)
118+
119+
# Loop through
120+
for i,w in enumerate(wt_unique):
121+
def selector(ds):
122+
times = wt.loc[wt['WT'] == w].index
123+
ds = ds.sel(time = np.in1d(ds.unstack('time')['T'], times))
124+
ds = ds.mean(dim = 'time')
125+
return(ds)
126+
127+
# Top row: geopotential height anomalies
128+
ax = axes[0, i]
129+
ax.set_title('WT {}: {:.1%} of days'.format(w, wt_counts.values[i]))
130+
C0 = selector(reanalysis['adif']).unstack('grid').plot.contourf(
131+
transform = data_proj,
132+
ax=ax,
133+
cmap='PuOr',
134+
extend="both",
135+
levels=np.linspace(-2e2, 2e2, 21),
136+
add_colorbar=False,
137+
add_labels=False
138+
)
139+
ax.coastlines()
140+
ax.add_feature(feature.BORDERS)
141+
#ax.set_extent([-95, -65, -12, 12])
142+
143+
# # add wind arrows
144+
# U = selector(uwnd).adif.values
145+
# V = selector(vwnd).adif.values
146+
# magnitude = np.sqrt(U**2 + V**2)
147+
# strongest = magnitude > np.percentile(magnitude, 50)
148+
# Q = ax.quiver(
149+
# X[strongest], Y[strongest], U[strongest], V[strongest],
150+
# transform=data_proj,
151+
# width=0.001, scale=0.8,units='xy'
152+
# )
153+
154+
# Middle row: rainfall anomalies
155+
ax = axes[1, i]
156+
C1 = selector(rainfall['adif']).unstack('grid').plot.contourf(
157+
transform = data_proj,
158+
ax=ax,
159+
cmap = 'BrBG',
160+
extend="both",
161+
levels=np.linspace(-2, 2, 13),
162+
add_colorbar=False,
163+
add_labels=False
164+
)
165+
ax.coastlines()
166+
ax.add_feature(feature.BORDERS)
167+
#ax.set_extent([-95, -75, -9, 5])
168+
169+
# Bottom row: tepmperature anomalies
170+
ax = axes[2, i]
171+
C2 = selector(t2m['asum']).unstack('grid').plot.contourf(
172+
transform = data_proj,
173+
ax=ax,
174+
cmap = 'RdBu_r',
175+
extend="both",
176+
levels=np.linspace(-2, 2, 13),
177+
add_colorbar=False,
178+
add_labels=False
179+
)
180+
ax.coastlines()
181+
ax.add_feature(feature.BORDERS)
182+
#ax.set_extent([-95, -70, -9, 5])
183+
ax.tick_params(colors='b')
184+
185+
# # Add Colorbar
186+
plt.tight_layout()
187+
fig.subplots_adjust(right=0.94)
188+
cax0 = fig.add_axes([0.97, 0.65, 0.0075, 0.3])
189+
cax1 = fig.add_axes([0.97, 0.33, 0.0075, 0.3])
190+
cax2 = fig.add_axes([0.97, 0.01, 0.0075, 0.3])
191+
cbar0 = fig.colorbar(C0, cax = cax0)
192+
cbar0.formatter.set_powerlimits((4, 4))
193+
cbar0.update_ticks()
194+
cbar0.set_label(r'$zg_{500}$ anomaly [$m^2$/$s^2$]', rotation=270)
195+
cbar0.ax.get_yaxis().labelpad = 20
196+
cbar1 = fig.colorbar(C1, cax=cax1)
197+
cbar1.set_label('Precip. anomaly [mm/d]', rotation=270)
198+
cbar1.ax.get_yaxis().labelpad = 20
199+
cbar2 = fig.colorbar(C2, cax=cax2)
200+
cbar2.set_label('T2m anomaly [$^o$C]', rotation=270)
201+
cbar2.ax.get_yaxis().labelpad = 20
202+
203+
# Format these axes
204+
205+
206+
#Add plot labels
207+
# letters = string.ascii_lowercase
208+
# for i, ax in enumerate(axes.flat):
209+
# label = '({})'.format(letters[i])
210+
# t = ax.text(0.05, 0.9, label, fontsize=11, transform=ax.transAxes)
211+
# t.set_bbox(dict(facecolor='white', edgecolor='gray'))
212+
213+
# Add a quiver key
214+
#k = plt.quiverkey(Q, 0.9, 0.7, 1, '1 m/s', labelpos='E', coordinates='figure')
215+
216+
fig.savefig('figs/wt_composite.pdf', bbox_inches='tight') #this needs to be changed to appropriate folder in framework
217+
plt.show()

0 commit comments

Comments
 (0)