# -*- coding: utf-8 -*-
"""
Standardised graphics generating functions for displaying resuls from the model
validation analysis.
:Dependencies [External]: matplotlib, cartopy
:Dependencies [Internal]: waveval.TimeFuncs
"""
# ----------------------------------------------------------------------------
# IMPORTS
# ----------------------------------------------------------------------------
# Standard Python Dependencies
# Non-Standard Python Dependencies
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import matplotlib.cm as cm
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER
# Local Module Dependencies
from waveval.TimeFuncs import dateStr, datetime, stdTimeFmt, np
# Other Dependencies
# ----------------------------------------------------------------------------
# GLOBAL VARIABLES
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# CLASS DEFINITIONS
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# FUNCTION DEFINITIONS
# ----------------------------------------------------------------------------
[docs]def plot_time_series(t_mod, v_mod, t_obs, v_obs,
obsVar, obsPlatform, modVar, modfname,
year, month,
xlims=None, ylims=None):
"""
Overlaid plot of model and observed time series of specified parameter.
"""
i_b = 'INSITU_GLO_WAVE'
obsDates = [datetime.strptime(dstr, stdTimeFmt) for dstr in dateStr(t_obs)]
modDates = [datetime.strptime(dstr, stdTimeFmt) for dstr in dateStr(t_mod)]
figHnd = plt.figure(figsize=(10,5)) # create first figure
label = obsPlatform+' | year: '+str(year)+' | month: '+str(month)
plt.plot(obsDates, v_obs, 'bo-', linewidth=1, markersize=3, label=label)
label= 'RSCD file: '+modfname
plt.plot(modDates, v_mod, 'ro--', linewidth=1, markersize=3, label=label)
plt.legend()
plt.grid(True)
plt.title('Buoy source: '+i_b,fontsize=12)
plt.xlabel('Time (dates)',fontsize=10)
plt.ylabel(obsVar+' / '+modVar+' [m]',fontsize=10)
plt.tight_layout()
#figHnd.show()
return figHnd
[docs]def plot_correlation(obs, model, obsVar, obsPlatform, modVar, modfname,
year, month, metrics):
figHnd = plt.figure(figsize=(6,6)) # create first figure
sc = plt.scatter(model, obs, s=3)
#plt.colorbar(sc)
if max(obs) > max(model):
max_plot_val = max(obs)
else:
max_plot_val = max(model)
plt.plot([0, max_plot_val+1], [0, max_plot_val+1], color='k', label='1:1')
plt.legend(loc='upper right')
plt.title(obsVar+' vs '+modVar, fontsize=12)
plt.xlabel(modfname, fontsize=10)
plt.ylabel('Buoy: '+obsPlatform, fontsize=10)
ax = plt.gca()
plt.text(0.05,0.9,
'Corr. : '+str(round(metrics['R'], 3))+\
' RMSE : '+str(round(metrics['RMSE'], 3))+' [m]'+\
' NRMSE : '+str(round(metrics['NRMSE'], 3))+' [%]'+\
'\nSI : '+str(round(metrics['SI'], 3))+\
' NMB : '+str(round(metrics['NMB'], 3))+' [%]',\
bbox=dict(fc=(1, 1, 1)), fontsize=10,
transform=ax.transAxes)
plt.grid(True)
plt.tight_layout()
#figHnd.show()
return figHnd
[docs]def plot_close(figHnd):
plt.close(figHnd)
return
[docs]def Regional_Weighted(lat: list, lon: list, wght: list, plot_area: list,
clims: list,
plotTitle: str, outpath: str, outname: str,
saveplot: bool):
"""
Regional map of parameters at specific locations colourised by a
wieghting factor.
"""
# plot_area = [-15, 15, 35, 70]
lon_div = [plot_area[0],
plot_area[0]+5,
plot_area[0]+10,
0,
plot_area[1]-10,
plot_area[1]-5,
plot_area[1]]
lat_div = [plot_area[2],
plot_area[2]+5,
plot_area[2]+10,
plot_area[2]+15,
plot_area[3]-15,
plot_area[3]-10,
plot_area[3]-5,
plot_area[3]]
#fig = plt.figure(figsize=(11, 10))
fig = plt.figure(figsize=(9, 10))
cm = plt.cm.get_cmap('YlOrRd')
ax = plt.axes(projection=ccrs.PlateCarree())
ax.add_feature(cfeature.LAND,color='grey',alpha=0.7)
ax.add_feature(cfeature.OCEAN,color='grey',alpha=0.15)
ax.coastlines(resolution='10m') # Options are 110, 50m, or 10m
sc = plt.scatter(lon, lat, c=wght, transform=ccrs.PlateCarree(),
s=80,alpha=0.8, cmap=cm, zorder = 3)
if clims[0] is not None:
plt.clim(clims[0],clims[1])
#plt.colorbar(sc, fraction=0.05, aspect=30, pad=0.1, shrink=0.95)
plt.colorbar(sc, fraction=0.05, aspect=30, pad=0.1, shrink=0.80)
ax.set_extent(plot_area)
gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
linewidth=1, color='gray', alpha=0.8)
gl.xlabel_style = {'size': 12,'color': 'gray'}#, 'weight': 'bold'}
gl.ylabel_style = {'size': 12,'color': 'gray'}#, 'weight': 'bold'}
gl.xlocator = mticker.FixedLocator(lon_div)
gl.ylocator = mticker.FixedLocator(lat_div)
gl.xformatter = LONGITUDE_FORMATTER
gl.yformatter = LATITUDE_FORMATTER
plt.title(plotTitle)
plt.tight_layout(pad=5)
if saveplot:
fig.savefig(outpath+'/'+outname+'.png')
return
[docs]def Regional(lat: list, lon: list,
plot_area: list, lat_div: list, lon_div: list,
outpath: str, outname: str,
saveplot: bool):
"""
Regional map of specific locations.
"""
# plot_area = [-15, 15, 35, 70]
'''
lon_div = [plot_area[0],
plot_area[0]+5,
plot_area[0]+10,
0,
plot_area[1]-10,
plot_area[1]-5,
plot_area[1]]
lat_div = [plot_area[2],
plot_area[2]+5,
plot_area[2]+10,
plot_area[2]+15,
plot_area[3]-15,
plot_area[3]-10,
plot_area[3]-5,
plot_area[3]]
'''
fig = plt.figure(figsize=(9.5, 10))
cm = plt.cm.get_cmap('YlOrRd')
ax = plt.axes(projection=ccrs.PlateCarree())
ax.add_feature(cfeature.LAND,color='grey',alpha=0.7)
ax.add_feature(cfeature.OCEAN,color='grey',alpha=0.15)
ax.coastlines(resolution='10m') # Options are 110, 50m, or 10m
sc = plt.scatter(lon, lat, c='c', transform=ccrs.PlateCarree(),
s=20,alpha=0.8, cmap=cm,zorder = 3)
ax.set_extent(plot_area)
gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
linewidth=1, color='gray', alpha=0.8)
gl.xlabel_style = {'size': 12,'color': 'gray'}#, 'weight': 'bold'}
gl.ylabel_style = {'size': 12,'color': 'gray'}#, 'weight': 'bold'}
gl.xlocator = mticker.FixedLocator(lon_div)
gl.ylocator = mticker.FixedLocator(lat_div)
gl.xformatter = LONGITUDE_FORMATTER
gl.yformatter = LATITUDE_FORMATTER
plt.tight_layout(pad=5)
if saveplot:
fig.savefig(outpath+'/'+outname+'.png')
return
[docs]def plot_1d_spec(freq, spec1D, titleStr:str=None,
outpath:str='./', outname:str='spec_1d', saveplot:bool=False):
"""
Plot of a 1-D wave frequency spectrum
"""
fhnd = plt.figure(figsize=(10,5))
plt.plot(freq,spec1D,'k')
plt.grid()
plt.xlabel('Frequency [Hz]')
plt.ylabel('S(f) [$m^2 s$]')
plt.title(titleStr)
if saveplot:
fhnd.savefig(outpath+'/'+outname+'.png')
return
[docs]def plot_2d_spec(freq, ntheta, spec2D, fmax:float=0.25, cmax:float=2.0, titleStr:str=None):
"""
Plot of a 2-D wave frequency spectrum
"""
ifrq = np.where(freq <= fmax)[0]
f = freq[ifrq]
nfreq = len(f)
sp = spec2D[ifrq,:]
sp = 100.0 * sp / np.nansum(sp)
sp = np.append(sp,sp[:,0].reshape(nfreq,1),1)
theta = np.linspace(0.0,360.0,ntheta+1)
r, t = np.meshgrid(f, np.radians(theta))
clevels = np.arange(0.1*cmax/2.0,cmax,0.05*cmax/2.0)
fig, ax = plt.subplots(subplot_kw=dict(projection='polar'), figsize=(10,10))
ax.contourf(t, r, sp.transpose(), clevels, cmap=cm.twilight)
clevels = np.arange(0.1*cmax/2.0,cmax,0.05*cmax/2.0)
ax.contour(t, r, sp.transpose(), clevels, colors=['k'], linewidths=0.2)
if titleStr is not None:
plt.title(titleStr)
return fig