def get_EOFs(var1, num=3, scaling=2): lat = var1.getAxis(1) lon = var1.getAxis(2) var = MV.array(var1 - np.mean(var1, axis=0)) var.setAxis(1, lat) var.setAxis(2, lon) solver = Eof(var, weights='area') eofs = solver.eofs(neofs=num, eofscaling=scaling) pc = solver.pcs(npcs=num, pcscaling=scaling) vari = solver.varianceFraction(num) eigv = solver.eigenvalues(num) return eofs, pc, vari, eigv
end_year = 2000 start_time = cdtime.comptime(start_year) end_time = cdtime.comptime(end_year) # Load variable --- d = f('sst',time=(start_time,end_time),longitude=(0,360),latitude=(-90,90)) # Provide proper variable name # Reomove annual cycle --- d_anom = cdutil.ANNUALCYCLE.departures(d) # EOF (take only first variance mode...) --- solver = Eof(d_anom, weights='area') eof = solver.eofsAsCovariance(neofs=1) pc = solver.pcs(npcs=1, pcscaling=1) # pcscaling=1: scaled to unit variance # (divided by the square-root of their eigenvalue) frac = solver.varianceFraction() # Sign control if needed --- eof = eof * -1 pc = pc * -1 #=========================================================================================================== # Plot #----------------------------------------------------------------------------------------------------------- # Create canvas --- canvas = vcs.init(geometry=(900,800)) canvas.open() template = canvas.createtemplate() # Turn off no-needed information -- prevent overlap
def eof_analysis_get_variance_mode( mode, timeseries, eofn, eofn_max=None, debug=False, EofScaling=False, save_multiple_eofs=False, ): """ NOTE: Proceed EOF analysis Input - mode (string): mode of variability is needed for arbitrary sign control, which is characteristics of EOF analysis - timeseries (cdms2 variable): time varying 2d array, so 3d array (time, lat, lon) - eofn (integer): Target eofs to be return - eofn_max (integer): number of eofs to diagnose (1~N) Output 1) When 'save_multiple_eofs = False' - eof_Nth: eof pattern (map) for given eofs as eofn - pc_Nth: corresponding principle component time series - frac_Nth: cdms2 array but for 1 single number which is float. Preserve cdms2 array type for netCDF recording. fraction of explained variance - reverse_sign_Nth: bool - solver 2) When 'save_multiple_eofs = True' - eof_list: list of eof patterns (map) for given eofs as eofn - pc_list: list of corresponding principle component time series - frac_list: list of cdms2 array but for 1 single number which is float. Preserve cdms2 array type for netCDF recording. fraction of explained variance - reverse_sign_list: list of bool - solver """ if debug: print("Lib-EOF: timeseries.shape:", timeseries.shape) debug_print("Lib-EOF: solver", debug) if eofn_max is None: eofn_max = eofn save_multiple_eofs = False # EOF (take only first variance mode...) --- solver = Eof(timeseries, weights="area") debug_print("Lib-EOF: eof", debug) # pcscaling=1 by default, return normalized EOFs eof = solver.eofsAsCovariance(neofs=eofn_max, pcscaling=1) debug_print("Lib-EOF: pc", debug) if EofScaling: # pcscaling=1: scaled to unit variance # (i.e., divided by the square-root of their eigenvalue) pc = solver.pcs(npcs=eofn_max, pcscaling=1) else: pc = solver.pcs(npcs=eofn_max) # pcscaling=0 by default # fraction of explained variance frac = solver.varianceFraction() debug_print("Lib-EOF: frac", debug) # For each EOFs... eof_list = [] pc_list = [] frac_list = [] reverse_sign_list = [] for n in range(0, eofn_max): eof_Nth = eof[n] pc_Nth = pc[:, n] frac_Nth = cdms2.createVariable(frac[n]) # Arbitrary sign control, attempt to make all plots have the same sign reverse_sign = arbitrary_checking(mode, eof_Nth) if reverse_sign: eof_Nth = MV2.multiply(eof_Nth, -1.0) pc_Nth = MV2.multiply(pc_Nth, -1.0) # time axis pc_Nth.setAxis(0, timeseries.getTime()) # Supplement NetCDF attributes frac_Nth.units = "ratio" pc_Nth.comment = "".join( [ "Non-scaled time series for principal component of ", str(eofn), "th variance mode", ] ) # append to lists for returning eof_list.append(eof_Nth) pc_list.append(pc_Nth) frac_list.append(frac_Nth) reverse_sign_list.append(reverse_sign) # return results if save_multiple_eofs: return eof_list, pc_list, frac_list, reverse_sign_list, solver else: # Remove unnecessary dimensions (make sure only taking requested eofs) eof_Nth = eof_list[eofn - 1] pc_Nth = pc_list[eofn - 1] frac_Nth = frac_list[eofn - 1] reverse_sign_Nth = reverse_sign_list[eofn - 1] return eof_Nth, pc_Nth, frac_Nth, reverse_sign_Nth, solver
def NatureRevisions_Figure5(D): aerosol_start = cdtime.comptime(1950,1,1) aerosol_stop = cdtime.comptime(1975,12,31) aerosolsolver=Eof(D.ALL.mma(time=(aerosol_start,aerosol_stop)),weights='area') fac=da.get_orientation(aerosolsolver) plt.subplot(221) m=b.landplot(fac*aerosolsolver.eofs()[0],vmin=-.1,vmax=.1) m.fillcontinents(color="gray",zorder=0) varex= str(int(100*np.round(aerosolsolver.varianceFraction()[0],2))) plt.title("(a)")#: 1950-1975 historical fingerprint ("+varex+"% of variance explained)",fontsize=8) m.drawcoastlines(color='gray') plt.ylim(-60,90) plt.colorbar(orientation='horizontal',label='EOF loading') plt.subplot(222) Plotting.time_plot(fac*aerosolsolver.pcs()[:,0],color=cm.Greys(.8),lw=1) plt.title("(b)")#: Associated PC",fontsize=8) plt.ylabel("Temporal amplitude") plt.subplot(223) target_obs,cru_proj,dai_proj=pdsi_time_series(D,aerosol_start,aerosol_stop,aerosols=True) plt.legend(fontsize=6) plt.title("(c)")#: Projections on fingerprint",fontsize=8) plt.subplot(224) # target_obs = D.ALL.get_tree_ring_projection(solver = aerosolsolver)(time=(aerosol_start,aerosol_stop)) L=len(target_obs) modslopes,noiseterm = D.ALL.sn_at_time(aerosol_start,L,overlapping=True,solver=aerosolsolver) ns=np.std(noiseterm) signal = float(cmip5.get_linear_trends(target_obs)) plt.hist(modslopes/ns,20,normed=True,color=get_dataset_color("h85"),alpha=.5) lab = str(aerosol_start.year)+"-"+str(aerosol_stop.year) da.fit_normals_to_data(modslopes/ns,color=get_dataset_color("h85"),lw=1,label="H85") plt.hist(noiseterm/ns,20,normed=True,color=get_dataset_color("tree_noise"),alpha=.5) da.fit_normals_to_data(noiseterm/ns,color=get_dataset_color("tree_noise"),lw=1,label="Pre-1850 tree rings") percentiles=[] plt.axvline(signal/ns,color=get_dataset_color("tree"),lw=1,label=lab+" GDA trend") noise_percentile=stats.percentileofscore(noiseterm.tolist(),signal) h85_percentile=stats.percentileofscore(modslopes.tolist(),signal) percentiles += [noise_percentile,h85_percentile] daitrend = cmip5.get_linear_trends(dai_proj) print "DAI slope is "+str(daitrend) daisignal = daitrend/ns plt.axvline(daisignal,color=get_dataset_color("dai"),lw=1,label="Dai") print "DAI signal/noise is "+str(daisignal) crutrend = cmip5.get_linear_trends(cru_proj) print "CRU slope is "+str(crutrend) crusignal = crutrend/ns plt.axvline(crusignal,color=get_dataset_color("cru"),lw=1,label="CRU") print "CRU signal/noise is "+str(crusignal) plt.legend(loc=0,fontsize=8) plt.xlabel("S/N") plt.ylabel("Normalized Frequency") plt.title("(d)")#: Detection and Attribution Results",fontsize=8) fig=plt.gcf() for ax in fig.axes: plt.setp(ax.xaxis.get_label(),fontsize=6) plt.setp(ax.yaxis.get_label(),fontsize=6) plt.setp(ax.get_xticklabels(),fontsize=6) plt.setp(ax.get_yticklabels(),fontsize=6) ax=fig.axes[0] ax.set_title("(a)",fontsize=6) ax=fig.axes[2] ax.set_title("(b)",fontsize=6) ax=fig.axes[3] ax.set_title("(c)",fontsize=6) ax=fig.axes[4] ax.set_title("(d)",fontsize=6) leg=ax.legend(fontsize=6,ncol=1,loc=2) leg.set_frame_on(False) cax=fig.axes[1] ticklabels=["-0.1","","-0.05","","0","","0.05","","0.1"] cax.set_xticklabels(ticklabels) plt.setp(cax.xaxis.get_ticklabels(),fontsize=6) plt.setp(cax.xaxis.get_label(),fontsize=6)