diff --git a/graphics.py b/graphics.py index 85ef48eca512f3ef8852086102a637957aaa9122..aaefb23353f8a8ab3dcf6ce107aa9394019fc8b6 100644 --- a/graphics.py +++ b/graphics.py @@ -3,7 +3,7 @@ import numpy as np from matplotlib import pyplot as p import matplotlib.colors as colors -from ENDA import experiment +from ENDA import compute_distances, gaspari_cohn is_sorted = lambda a: np.all(a[:-1] <= a[1:]) @@ -344,6 +344,7 @@ def plot_CBL_identifiability(cbl,sigma_o,ax=None): C = deltap.T D = ( (sigma2_p/sigma2_yb)**0.5 ).T E = ( innov*sigma2_yb/(sigma2_yb+sigma_o**2) ).T + F = innov.T # For plotting contours = np.linspace(cbl.nr.theta_0,cbl.nr.theta_0+cbl.nr.gamma*zmax,ncont) @@ -370,7 +371,8 @@ def plot_CBL_identifiability(cbl,sigma_o,ax=None): elif type(ax) is list and len(ax)==2: - c0 = ax[0].pcolormesh(times/3600.,zobs,D,cmap=new_cmap) + #c0 = ax[0].pcolormesh(times/3600.,zobs,D,cmap=new_cmap) # For old version of Fig 8 + c0 = ax[0].pcolormesh(times/3600.,zobs,B,norm=colors.CenteredNorm(),cmap='RdBu_r') ax[0].contour(times/3600.,zobs,theta.mean(axis=2).T, contours, colors='black', @@ -378,7 +380,8 @@ def plot_CBL_identifiability(cbl,sigma_o,ax=None): linewidths=0.75) ax[0].set_ylim([0,zmax]) - c1 = ax[1].pcolormesh(times/3600.,zobs,E,norm=colors.CenteredNorm(),cmap='RdBu_r') + #c1 = ax[1].pcolormesh(times/3600.,zobs,E,norm=colors.CenteredNorm(),cmap='RdBu_r') # For old version of Fig 8 + c1 = ax[1].pcolormesh(times/3600.,zobs,C,norm=colors.CenteredNorm(),cmap='RdBu_r') ax[1].contour(times/3600.,zobs,theta.mean(axis=2).T, contours, colors='black', @@ -484,13 +487,20 @@ def plot_free_ensemble(cbl,show='spread',ax=None,cmap='viridis'): elif show=='mean': bkgd = theta.mean(axis=0) contour_color = 'white' - if show=='cov': + elif show=='cov': cov = np.zeros((nz,ntimes))+np.nan for ii in range(nz): for jj in range(ntimes): cov[ii,jj] = np.cov(param,theta[:,ii,jj])[0,1] bkgd = cov contour_color = 'black' + elif show=='corr': + corr = np.zeros((nz,ntimes))+np.nan + for ii in range(nz): + for jj in range(ntimes): + corr[ii,jj] = np.corrcoef(param,theta[:,ii,jj])[0,1] + bkgd = corr + contour_color = 'black' # Plot zmax = 2000 @@ -498,7 +508,7 @@ def plot_free_ensemble(cbl,show='spread',ax=None,cmap='viridis'): if ax is not None: # Make plots - c = ax.pcolormesh(times/3600.,zt,bkgd,cmap=cmap) + c = ax.pcolormesh(times/3600.,zt,bkgd,cmap=cmap,norm=colors.CenteredNorm()) ax.contour(times/3600.,zt,theta.mean(axis=0), np.linspace(cbl.theta_0,cbl.theta_0+cbl.gamma*zmax,ncont), colors=contour_color, @@ -507,7 +517,7 @@ def plot_free_ensemble(cbl,show='spread',ax=None,cmap='viridis'): ax.set_ylim([0,zmax]) return ax,c -def plot_diagnostics(exp,show='errors',axes=None,label='',linecolor='blue'): +def plot_diagnostics(exp,show='errors',axes=None,label='',linecolor='blue',zmax=None): # See if the experiment is an OSSE if (not hasattr(exp.da,'truths')): @@ -517,9 +527,11 @@ def plot_diagnostics(exp,show='errors',axes=None,label='',linecolor='blue'): # Get the data sigma_o = exp.dg.varo**0.5 + sigma_d = exp.dg.sigma_ominb armsd = exp.dg.aRMSD_t brmsd = exp.dg.bRMSD_t - bsprd = exp.dg.bSprd_t + #bsprd = exp.dg.bSprd_t + bsprd = exp.dg.varb_ta**0.5 if truth_exists: armse = exp.dg.aRMSE_t brmse = exp.dg.bRMSE_t @@ -537,15 +549,20 @@ def plot_diagnostics(exp,show='errors',axes=None,label='',linecolor='blue'): elif exp.da.obs_coordinates.ndim == 2: z = np.sort(exp.da.obs_coordinates[0,:]) + if zmax is None: + idx = np.arange(z.size) + else: + idx = (z<zmax) + if axes is not None and len(axes)==4: # Plot errors (wrt to true state) only if true state exists if show=='errors' and truth_exists: - axes[0].plot(armse,z,label=label,color=linecolor)#,color=linecolors[i]) - axes[1].plot(brmse,z,color=linecolor) - axes[2].plot(brmse-armse,z,color=linecolor) - axes[3].plot(np.sqrt(bsprd**2+sigma_o**2)/brmse,z,color=linecolor) + axes[0].plot(armse[idx],z[idx],label=label,color=linecolor)#,color=linecolors[i]) + axes[1].plot(brmse[idx],z[idx],color=linecolor) + axes[2].plot(brmse[idx]-armse[idx],z[idx],color=linecolor) + axes[3].plot(np.sqrt(bsprd[idx]**2+sigma_o[idx]**2)/brmse[idx],z[idx],color=linecolor) elif show=='deviations': @@ -553,10 +570,10 @@ def plot_diagnostics(exp,show='errors',axes=None,label='',linecolor='blue'): mean_bias_a_i1 = exp.dg.omina.mean(axis=0) mean_bias_b_i1 = exp.dg.ominb.mean(axis=0) # Plots - axes[0].plot(armsd,z,label=label,color=linecolor) - axes[1].plot(brmsd,z,color=linecolor) - axes[2].plot(brmsd-armsd,z,color=linecolor) - axes[3].plot(np.sqrt(bsprd**2+sigma_o**2)/brmsd,z,color=linecolor) + axes[0].plot(armsd[idx],z[idx],label=label,color=linecolor) + axes[1].plot(brmsd[idx],z[idx],color=linecolor) + axes[2].plot(brmsd[idx]-armsd[idx],z[idx],color=linecolor) + axes[3].plot(np.sqrt(bsprd[idx]**2+sigma_o[idx]**2)/brmsd[idx],z,color=linecolor) return axes @@ -593,7 +610,7 @@ def plot_linearity(cbl,ax=None): return ax -def plot_B_matrix(exp,timeid=-1): +def plot_B_matrix(exp,timeid=-1,localize=True): # Read the background state for the requested analysis time xx = exp.da.backgrounds[timeid] @@ -612,17 +629,30 @@ def plot_B_matrix(exp,timeid=-1): Pb = np.matmul(X.T,X)/(nens-1) v = np.abs(Pb[:-1,:-1]).max() + # Compute localized covariance matrix + xcoords = exp.nr.zt + dist = compute_distances(xcoords,xcoords) + loc = np.ones((nvar,nvar)) + loc[:(nvar-1),:(nvar-1)] = gaspari_cohn(dist,cutoff=800) + # Plot - fig = p.figure(0) - fig.set_size_inches(4,3) - sp1 = fig.add_subplot(1,1,1) - c = sp1.pcolormesh(range(nvar),range(nvar),Pb,vmin=-v,vmax=v,cmap='RdBu_r',shading='nearest') + fig, [sp1,sp2] = p.subplots(1,2,constrained_layout=True) + fig.set_size_inches(6,3) + # + c1 = sp1.pcolormesh(range(nvar),range(nvar),Pb,vmin=-v,vmax=v,cmap='RdBu_r',shading='nearest') sp1.set_aspect('equal','box') sp1.set_xlim(-0.5,nvar-0.5) sp1.set_ylim(-0.5,nvar-0.5) - sp1.set_title('$1/(N-1)\cdot X^TX$, $t=%4.2f$ h'%(tt/3600)) - p.colorbar(c) - fig.tight_layout() + sp1.set_title('a) $P^b$, $t=%4.2f$ h'%(tt/3600)) + # + c2 = sp2.pcolormesh(range(nvar),range(nvar),loc*Pb,vmin=-v,vmax=v,cmap='RdBu_r',shading='nearest') + sp2.set_aspect('equal','box') + sp2.set_xlim(-0.5,nvar-0.5) + sp2.set_ylim(-0.5,nvar-0.5) + sp2.set_title('b) Localized $P^b$, $t=%4.2f$ h'%(tt/3600)) + # + p.colorbar(c1,orientation='horizontal') + p.colorbar(c2,orientation='horizontal') fig.savefig('Covariance_matrix_%05u_s.png'%tt,format='png',dpi=150) p.close(fig) @@ -636,18 +666,21 @@ def plot_desroziers(dgs,filename='desroziers_diagnostics.png',labels=None,logsca fig.set_size_inches(4,3) ax = fig.add_subplot(1,1,1) - for i,dg in zip( range(len(dgs)) , dgs ): + colors = p.rcParams['axes.prop_cycle'].by_key()['color'][:len(dgs)] + for i,dg,color in zip( range(len(dgs)) , dgs , colors): if labels is not None: # Two formulations of the same thing; they give the same numbers! #ax1.scatter( dg.dobdob_ta-dg.mean_ominb**2 , dg.varo+dg.varb_ta , s=5, label = labels[i]) - ax.scatter( dg.sigma_ominb**2 , dg.varo+dg.varb_ta , s=5, label = labels[i]) + ax.scatter( np.mean(dg.sigma_ominb**2) , np.mean(dg.varo+dg.varb_ta) , s=13, label = labels[i],zorder=10, c=color, edgecolors='black') + ax.scatter( dg.sigma_ominb**2 , dg.varo+dg.varb_ta , s=5, alpha = 0.3, c=color, linewidths=0) else: # Two formulations of the same thing; they give the same numbers! #ax1.scatter( dg.dobdob_ta-dg.mean_ominb**2 , dg.varo+dg.varb_ta , s=5) - ax.scatter( dg.sigma_ominb**2 , dg.varo+dg.varb_ta , s=5) # + ax.scatter( np.mean(dg.sigma_ominb**2) , np.mean(dg.varo+dg.varb_ta) , s=13, zorder = 10) + ax.scatter( dg.sigma_ominb**2 , dg.varo+dg.varb_ta , s=5, alpha = 0.3) # #ax.set_title("Consistency of innovations",fontsize=8) - ax.set_xlabel(r'${\langle}\sigma_d^2{\rangle}_t$') # '${\langle}d_{ob}^2{\rangle}_t$' - ax.set_ylabel(r'$\sigma_o^2+{\langle}\sigma_b^2{\rangle}_t$') + ax.set_xlabel(r'${\langle}\sigma_d^2{\rangle}$ (K)') # '${\langle}d_{ob}^2{\rangle}_t$' + ax.set_ylabel(r'$\sigma_{y_o}^2+{\langle}\sigma_{y_b}^2{\rangle}$ (K)') if labels is not None: ax.legend(frameon=False, fontsize=6, ncol=2) @@ -685,21 +718,24 @@ def plot_overview(exp,label,filename,show_spread=False,show_transformed_paramete ax2.set_title(r'c) Exp. %s, $\delta\overline{p}\prime\prime$'%label) ax2.set_xlabel('Time (h)') ax2.set_ylabel('Height (m)') - ax3 = plot_CBL_PE(exp,None,ax=ax3,show_spread=show_spread,show_transformed_parameter=show_transformed_parameter,show_true_parameter=show_true_parameter) - if show_transformed_parameter: - ax3.set_title(r'd) Exp. %s, evolution of $p\prime\prime$'%label) - else: - ax3.set_title(r'd) Exp. %s, evolution of $p$'%label) - ax3.set_yticks(np.arange(5+1)) - ax3.set_xlabel('Time (h)') ax0.set_xlim([0,maxtime/3600]) ax1.set_xlim([0,maxtime/3600]) ax2.set_xlim([0,maxtime/3600]) - ax3.set_xlim([0,maxtime/3600]) ax0.set_xticks(np.arange((maxtime+1)/3600)) ax1.set_xticks(np.arange((maxtime+1)/3600)) ax2.set_xticks(np.arange((maxtime+1)/3600)) - ax3.set_xticks(np.arange((maxtime+1)/3600)) + ax3 = plot_CBL_PE(exp,None,ax=ax3,show_spread=show_spread,show_transformed_parameter=show_transformed_parameter,show_true_parameter=show_true_parameter) + if ax3 is None: + pass + else: + if show_transformed_parameter: + ax3.set_title(r'd) Exp. %s, evolution of $p\prime\prime$'%label) + else: + ax3.set_title(r'd) Exp. %s, evolution of $p$'%label) + ax3.set_yticks(np.arange(5+1)) + ax3.set_xlabel('Time (h)') + ax3.set_xlim([0,maxtime/3600]) + ax3.set_xticks(np.arange((maxtime+1)/3600)) p.colorbar(c0,orientation='horizontal') p.colorbar(c1,orientation='horizontal') p.colorbar(c2,orientation='horizontal')