def PDO(dat1, dat2): solver = Eof(dat1) pc1 = solver.pcs(npcs=1, pcscaling=1) sigs = solver.eigenvalues() eofs = solver.eofs() eof1 = eofs[0] # normalise sigs sigs1 = sigs / sigs.sum() # not used eof1 = solver.eofsAsCorrelation(neofs=1) # pcs=solver.pcs() # filter first pdf Nt = dat1.time.size fp = fft.fft(pc1[:, 0]) x = fft.fftfreq(Nt, 1 / 12.) # cycles per year # lowpass filter at 0.1 per year i = abs(x) <= .1 fp_fil = fp * i #plt.plot(x,abs(fp)) #plt.plot(x,abs(fp_fil)) pfil = fft.ifft(fp_fil) # pc1_fil = pc1[:, 0] * 0 + np.real(pfil) #plt.plot(pc1_fil) #print(pc1) print(pc1_fil) tmp = np.imag(pfil) print(tmp.max) # correlate with sst field astd, bstd, abstd, bhat = regresst(pc1_fil, dat2) r = abstd / (astd * bstd) slope = r * bstd return sigs1, eof1, slope, pc1, pc1_fil, x, fp_fil
def get_eofs(x): import numpy as np import xarray from eofs.xarray import Eof from matplotlib import pyplot as plt coslat = np.cos(np.deg2rad(x.lat)).clip(0., 1.) wgts = np.sqrt(coslat)[..., np.newaxis] from eddof import get_eddof DF = np.empty(np.shape(x[0, :, :])) for i in range(0, len(x.lat)): for j in range(0, len(x.lon)): DF[i, j] = get_eddof(x[:, i, j].values) edof = np.mean(DF) print(edof) solver = Eof(x, weights=wgst, ddof=edof) var = solver.varianceFraction() plt.figure(1) plt.bar(np.arange(0, len(var), 1), var * 100) plt.show() plt.close() n = input('Cuantos PC extraer: ') eof = solver.eofs(neofs=n, eofscaling=2) pc = solver.pcs(npcs=n, pcscaling=1) vf = var[:n] EOFs = [eof, pc, vf] return EOFs
def test_eof_values(shape, n_modes, weight, wrap): """Test values relative to Eof package""" data = example_da(shape, wrap=wrap) lat_dim = f"dim_{len(shape)-1}" xeof.core.LAT_NAME = lat_dim sensor_dims = [f"dim_{i}" for i in range(1, len(shape))] if weight == "none": weights = None elif weight == "sqrt_cos_lat": weights = np.cos(data[lat_dim] * np.pi / 180)**0.5 elif weight == "random": weights = data.isel(time=0).copy() weight = weights.compute() res = eof( data, sensor_dims=sensor_dims, sample_dim="time", weight=weight, n_modes=n_modes, norm_PCs=False, ) Eof_solver = Eof(data, weights=weights, center=False) ver_pcs = Eof_solver.pcs(pcscaling=0, npcs=n_modes) ver_eofs = Eof_solver.eofs(eofscaling=0, neofs=n_modes) ver_EV = Eof_solver.varianceFraction(neigs=n_modes) npt.assert_allclose(abs(res["pc"]), abs(ver_pcs)) npt.assert_allclose(abs(res["eof"]), abs(ver_eofs)) npt.assert_allclose(res["explained_var"], ver_EV)
def processInputCrossSection(self, request: TaskRequest, node: OpNode, inputDset: EDASDataset) -> EDASDataset: nModes = int(node.getParm("modes", 16)) center = bool(node.getParm("center", "false")) merged_input_data, info = self.get_input_array(inputDset) shapes = info['shapes'] slicers = info['slicers'] solver = Eof(merged_input_data, center=center) results = [] for iMode, eofs_result in enumerate(solver.eofs(neofs=nModes)): for iVar, eofs_data in enumerate( self.getResults(eofs_result, slicers, shapes)): input = inputDset.inputs[iVar] results.append( EDASArray("-".join(["eof-", str(iMode), input.name]), input.domId, eofs_data)) pcs_result = solver.pcs(npcs=nModes) pcs = EDASArray( "pcs[" + inputDset.id + "]", inputDset.inputs[0].domId, EDASArray.cleanupCoords(pcs_result, { "mode": "m", "pc": "m" }).transpose()) results.append(pcs) fracs = solver.varianceFraction(neigs=nModes) pves = [str(round(float(frac * 100.), 1)) + '%' for frac in fracs] for result in results: result["pves"] = str(pves) return EDASDataset.init(self.renameResults(results, node), inputDset.attrs)
def plot_pca_analysis(ds, fig_output_path, title=''): print(title) # var = "T" print('done load') nbpcs = 3 solver = Eof(ds.dropna(dim="time", how="all")) pcas = solver.pcs(npcs=nbpcs, pcscaling=1) eofs = solver.eofs(neofs=nbpcs, eofscaling=1) fig, axes = plt.subplots(5, 2, figsize=(20, 20)) fig.suptitle(title, fontsize=12) pcas.plot.line(ax=axes[0, 0], x='time') pcas.resample(time='M').mean('time').plot.line(ax=axes[1, 0], x='time') axes[1, 0].set_title('Monthly mean') pcas.resample(time='Y').mean('time').plot.line(ax=axes[2, 0], x='time') axes[2, 0].set_title('Annual mean') pcas.groupby('time.month').mean('time').plot.line(ax=axes[3, 0], x='month') axes[3, 0].set_title('By Month') pcas.groupby('time.hour').mean('time').plot.line(ax=axes[4, 0], x='hour') axes[4, 0].set_title('By Hour') for pc in range(nbpcs): # eofs.isel(mode=pc).plot(ax=axes[pc, 1]) eofs.to_dataframe().unstack().T.loc[:, pc].plot.bar(ax=axes[pc, 1]) solver.varianceFraction().isel(mode=slice(0, nbpcs)).plot(ax=axes[3, 1]) plt.tight_layout() plt.tight_layout() fig.suptitle(title) plt.savefig(fig_output_path + title + '.pdf', bbox_inches='tight')
ds_spring = ds_spring.sel(spring=idx) plt.scatter(ds_spring_sib2.min('time').to_dataframe(), ds_spring.min('time').to_dataframe()) ####################### # PCA Analysis ####################### nbpcs = 3 solver_sib2 = Eof(ds_spring_sib2.dropna(dim="time", how="all")) pcas_sib2 = solver_sib2.pcs(npcs=nbpcs, pcscaling=1) eofs_sib2 = solver_sib2.eofs(neofs=nbpcs, eofscaling=1) solver = Eof(ds_spring.dropna(dim="time", how="all")) pcas = solver.pcs(npcs=nbpcs, pcscaling=1) eofs = solver.eofs(neofs=nbpcs, eofscaling=1) fig, axes = plt.subplots(3, 4, figsize=(20, 20)) pcas.to_dataframe().unstack().plot(ax=axes[0,0]) pcas_sib2.to_dataframe().unstack().plot(ax=axes[0,1]) df_eofs = eofs.to_dataframe().unstack().T df_eofs_sib2 = eofs_sib2.to_dataframe().unstack().T df_eofs.index = df_eofs.index.levels[1] df_eofs_sib2.index = df_eofs_sib2.index.levels[1]
def reof(stack: xr.DataArray, variance_threshold: float = 0.727, n_modes: int = 4) -> xr.Dataset: """Function to perform rotated empirical othogonal function (eof) on a spatial timeseries args: stack (xr.DataArray): DataArray of spatial temporal values with coord order of (t,y,x) variance_threshold(float, optional): optional fall back value to select number of eof modes to use. Only used if n_modes is less than 1. default = 0.727 n_modes (int, optional): number of eof modes to use. default = 4 returns: xr.Dataset: rotated eof dataset with spatial modes, temporal modes, and mean values as variables """ # extract out some dimension shape information shape3d = stack.shape spatial_shape = shape3d[1:] shape2d = (shape3d[0],np.prod(spatial_shape)) # flatten the data from [t,y,x] to [t,...] da_flat = xr.DataArray( stack.values.reshape(shape2d), coords = [stack.time,np.arange(shape2d[1])], dims=['time','space'] ) #logger.debug(da_flat) ## find the temporal mean for each pixel center = da_flat.mean(dim='time') centered = da_flat - center # get an eof solver object # explicitly set center to false since data is already #solver = Eof(centered,center=False) solver = Eof(centered,center=False) # check if the n_modes keyword is set to a realistic value # if not get n_modes based on variance explained if n_modes < 0: n_modes = int((solver.varianceFraction().cumsum() < variance_threshold).sum()) # calculate to spatial eof values eof_components = solver.eofs(neofs=n_modes).transpose() # get the indices where the eof is valid data non_masked_idx = np.where(np.logical_not(np.isnan(eof_components[:,0])))[0] # create a "blank" array to set roated values to rotated = eof_components.values.copy() # # waiting for release of sklean version >= 0.24 # # until then have a placeholder function to do the rotation # fa = FactorAnalysis(n_components=n_modes, rotation="varimax") # rotated[non_masked_idx,:] = fa.fit_transform(eof_components[non_masked_idx,:]) # apply varimax rotation to eof components # placeholder function until sklearn version >= 0.24 rotated[non_masked_idx,:] = _ortho_rotation(eof_components[non_masked_idx,:]) # project the original time series data on the rotated eofs projected_pcs = np.dot(centered[:,non_masked_idx], rotated[non_masked_idx,:]) # reshape the rotated eofs to a 3d array of [y,x,c] spatial_rotated = rotated.reshape(spatial_shape+(n_modes,)) # structure the spatial and temporal reof components in a Dataset reof_ds = xr.Dataset( { "spatial_modes": (["lat","lon","mode"],spatial_rotated), "temporal_modes":(["time","mode"],projected_pcs), "center": (["lat","lon"],center.values.reshape(spatial_shape)) }, coords = { "lon":(["lon"],stack.lon), "lat":(["lat"],stack.lat), "time":stack.time, "mode": np.arange(n_modes)+1 } ) return reof_ds
# Load packages. import xarray as xr from eofs.xarray import Eof import datetime import os # Read preprocessed data. DATA_FILE = "/LFASGI/sandroal/data_sets/GIMMS/ppdata_ndvi.nc" DS = xr.open_dataset(DATA_FILE) # Create an EOF solver to do the EOF analysis. Memory intensive operation. solver = Eof(DS.ndvi) # Retrieve EOFs, principal component time series, fraction of explained # variance, and eigenvalues as xarray DataArray objects for all modes. EOFs = solver.eofs() PCs = solver.pcs() FRACs = solver.varianceFraction() EIGs = solver.eigenvalues() # Attributes for xarray DataSet objects. attrs = {} attrs["Description"] = "Empirical orthogonal functions to NDVI (GIMMS) " + \ "in its original temporal and spatial resolutions" attrs["Build"] = "By Alex Araujo" attrs["Date"] = datetime.datetime.now().strftime("%B %d, %Y; %Hh:%Mmin:%Ss") attrs["Source"] = os.path.abspath(__file__) # Set these attributes to results. Must transform from xarray DataArray to # DataSets before exporting results as netcdf files. DAs = [EOFs, PCs, FRACs, EIGs]
from eofs.xarray import Eof for ii in range(3, 8): if ii < 4: skipnum = 10 else: skipnum = 50 solver_across = Eof(dat['across track velocity'][:, ::skipnum, :].T[:, :, ii]) solver_along = Eof(dat['along track velocity'][:, ::skipnum, :].T[:, :, ii]) figure(figsize=(10, 5)) subplot(121) plot(squeeze(solver_across.eofs(neofs=1)), -dat.depth[::skipnum], label='mode 1: ' + str(int(solver_across.varianceFraction()[0].values * 100)) + '% of variance') plot(squeeze(solver_across.eofs()[1, :]), -dat.depth[::skipnum], label='mode 2: ' + str(int(solver_across.varianceFraction()[1].values * 100)) + '% of variance') ylabel('depth [m]') xlabel('along-stream velocity [m/s]') xlim([-1, 1]) legend(loc=(0.2, 1.01)) subplot(122) plot(squeeze(solver_along.eofs(neofs=1)),
if (valid.any()==True): sst_obs[:,la,lo] = signal.detrend(sst_obs[:,la,lo], axis=0, \ type='linear') elif (valid.all()==False): sst_obs[:,la,lo] = np.nan ''' # EOF for model coslat_mdl = np.cos(np.deg2rad(sst_mdl.coords['lat'].values)) wgts_mdl = np.sqrt(coslat_mdl)[..., np.newaxis] solver_mdl = Eof(sst_mdl, weights=wgts_mdl, center=True) lambdas_mdl=solver_mdl.eigenvalues() vf_mdl = solver_mdl.varianceFraction() Nerror_mdl = solver_mdl.northTest(vfscaled=True) pcs_mdl = solver_mdl.pcs() #(time, mode) eofs_mdl = solver_mdl.eofs() # EOF for obs coslat_obs = np.cos(np.deg2rad(sst_obs.coords['lat'].values)) wgts_obs = np.sqrt(coslat_obs)[..., np.newaxis] solver_obs = Eof(sst_obs, weights=wgts_obs, center=True) lambdas_obs=solver_obs.eigenvalues() vf_obs = solver_obs.varianceFraction() Nerror_obs = solver_obs.northTest(vfscaled=True) pcs_obs = solver_obs.pcs() #(time, mode) eofs_obs = solver_obs.eofs() ## plotting domain = [-55, 90, 10, 180] #[-55, -270, 10, -180] #[-55, 90, 10, 180]
def orthoModes(cls, data, nModes): # type: (np.ndarray, int) -> np.ndarray eof = Eof(data, None, False, False) result = eof.eofs(0, nModes) # type: np.ndarray result = result / (np.std(result) * math.sqrt(data.shape[1])) return result.transpose()
''' start5 = time.time() os.chdir("/home/ubuntu") lon = 180 lat = 90 dim = lon * lat months = 24 data = np.resize(x1, [dim, months]) solver = Eof(xr.DataArray(anomalies.data, dims=['time', 'lat', 'lon'])) pcs = solver.pcs(npcs=3, pcscaling=1) eofs = solver.eofs(neofs=5, eofscaling=1) variance_fractions = solver.varianceFraction() variance_fractions = solver.varianceFraction(neigs=3) print(variance_fractions) myFile1 = open('PC1.csv', 'w') with myFile1: writer = csv.writer(myFile1) writer.writerows(eofs[0, :, :].data) myFile2 = open('PC2.csv', 'w') with myFile2: writer = csv.writer(myFile2) writer.writerows(eofs[1, :, :].data)
def eof_orca_latlon_box(run, var, modes, lon_bnds, lat_bnds, pathfile, plot, time, eoftype): if (var == 'temp'): key = 'votemper' key1 = "votemper" elif (var == 'sal'): key = 'vosaline' key1 = "vosaline" elif (var == 'MLD'): key = 'somxl010' key1 = "somxl010" # read data ds = xr.open_dataset(pathfile) #ds["time_counter"] = ds['time_counter']+(np.datetime64('0002-01-01')-np.datetime64('0001-01-01')) if time == 'comparison': ds = ds.sel(time_counter=slice('1958-01-01', '2006-12-31')) # cut box for EOF at surface if var == 'MLD': data = ds[key].sel(lon=slice(lon_bnds[0], lon_bnds[1]), lat=slice(lat_bnds[0], lat_bnds[1])) #data = cut_latlon_box(ds[key][:,:,:],ds.lon,ds.lat, # lon_bnds,lat_bnds) else: data = ds[key][:, 0, :, :].sel(lon=slice(lon_bnds[0], lon_bnds[1]), lat=slice(lat_bnds[0], lat_bnds[1])) #data = cut_latlon_box(ds[key][:,0,:,:],ds.lon,ds.lat, # lon_bnds,lat_bnds) data = data.to_dataset() # detrend data data[key1] = (['time_counter', 'lat', 'lon'], signal.detrend(data[key].fillna(0), axis=0, type='linear')) #data=data.where(data!=0) # remove seasonal cycle and drop unnecessary coordinates if 'time_centered' in list(data.coords): data = deseason_month(data).drop('month').drop( 'time_centered') # somehow pca doesn't work otherwise else: data = deseason_month(data).drop( 'month') # somehow pca doesn't work otherwise # set 0 values back to nan data = data.where(data != 0) # EOF analysis #Square-root of cosine of latitude weights are applied before the computation of EOFs. coslat = np.cos(np.deg2rad(data['lat'].values)) coslat, _ = np.meshgrid(coslat, np.arange(0, len(data['lon']))) wgts = np.sqrt(coslat) solver = Eof(data[key], weights=wgts.transpose()) pcs = solver.pcs(npcs=modes, pcscaling=1) if eoftype == 'correlation': eof = solver.eofsAsCorrelation(neofs=modes) elif eoftype == 'covariance': eof = solver.eofsAsCovariance(neofs=modes) else: eof = solver.eofs(neofs=modes) varfr = solver.varianceFraction(neigs=4) print(varfr) #----------- Plotting -------------------- plt.close("all") if plot == 1: for i in np.arange(0, modes): fig = plt.figure(figsize=(8, 2)) ax1 = fig.add_axes([0.1, 0.1, 0.3, 0.9], projection=ccrs.PlateCarree()) # main axes ax1.set_extent( (lon_bnds[0], lon_bnds[1], lat_bnds[0], lat_bnds[1])) # discrete colormap cmap = plt.get_cmap('RdYlBu', len(np.arange(10, 30)) - 1) #inferno similar to cmo thermal eof[i, :, :].plot(ax=ax1, cbar_kwargs={'label': 'Correlation'}, transform=ccrs.PlateCarree(), x='lon', y='lat', add_colorbar=True, cmap=cmap) gl = map_stuff(ax1) gl.xlocator = mticker.FixedLocator([100, 110, 120]) gl.ylocator = mticker.FixedLocator(np.arange(-35, -10, 5)) plt.text(116, -24, str(np.round(varfr[i].values, decimals=2)), horizontalalignment='center', verticalalignment='center', transform=ccrs.PlateCarree(), fontsize=8) ax2 = fig.add_axes([0.5, 0.1, 0.55, 0.9]) # main axes plt.plot(pcs.time_counter, pcs[:, i].values, linewidth=0.1, color='k') anomaly(ax2, pcs.time_counter.values, pcs.values[:, i], [0, 0]) ax2.set_xlim( [pcs.time_counter[0].values, pcs.time_counter[-1].values]) plt.savefig(pathplots + 'eof_as' + eoftype + '_mode' + str(i) + '_' + time + '_' + run + '_' + var + '.png', dpi=300, bbox_inches='tight', pad_inches=0.1) plt.show() #---------------------------------------------- return pcs, eof, varfr
def eof_analyse(xarray_DataArray, neofs): solver = Eof(xarray_DataArray) eofs = solver.eofs(neofs) return eofs
covu = cov(umeana[ii, :]**2) covv = cov(vmeana[ii, :]**2) covuv = cov(umeana[ii, :] * vmeana[ii, :]) varmax = 0.5 * (covu + covv + sqrt((covu - covv)**2 + 4 * covuv**2)) varmax varmin = covu**2 + covv**2 - varmax varmin import xarray as xray uvmat = xray.concat((umeana, vmeana), dim='uv') from eofs.xarray import Eof solver = Eof(uvmat.isel(distance=ii).T) evec1x = solver.eofs(neofs=1)[0][0].values evec1y = solver.eofs(neofs=1)[0][1].values maxtheta_rad = arctan(evec1y / evec1x) maxtheta = arctan(evec1y / evec1x) * 180 / pi maxtheta eig1 = solver.eigenvalues()[0].values eig2 = solver.eigenvalues()[1].values maxvar = 2 * sqrt(5.991 * eig1) minvar = 2 * sqrt(5.991 * eig2) fig, ax = plt.subplots(subplot_kw={'aspect': 'equal'}) hist2d(umean[ii, :], vmean[ii, :], 30) colorbar() e = Ellipse(xy=hstack(
def LFCA(da, N=30, L=1/10, fs=12, order=3, landmask=None, monthly=True): """Perform LFCA (as per Wills et al, 2018, GRL) on a dataarray. Parameters ---------- da : xarray.DataArray Data to perform LFCA on (time x lat x lon) N : int Number of EOFs to retain L : float Cutoff frequency for lowpass filter (e.g. 1/10 for per decade) fs : float Sampling frequency (1/12 for monthly) order : int Order of the Butterworth filter landmask : xarray.DataArray or None If None, do not perform any masking If DataArray, indicates land locations monthly : bool If True, perform lowpass filtering for each month separately Returns ------- LFPs : numpy.ndarray 2D array of N spatial patterns (nlat*nlon x N) LFCs : numpy.ndarray 2D array of N time series (ntime x N) """ from eofs.xarray import Eof # remove empirical seasonal cycle da = da.groupby('time.month') - da.groupby('time.month').mean('time') ntime, nlat, nlon = da.shape if landmask is not None: # expand land mask to ntime lnd_mask = np.repeat(is_land.values[np.newaxis, :, :], ntime, axis=0) da = da.where(lnd_mask) coslat = np.cos(np.deg2rad(da['lat'].values)).clip(0., 1.) wgts = np.sqrt(coslat)[..., np.newaxis] solver = Eof(da, weights=wgts) eofs = solver.eofs(eofscaling=0) # normalized st L2 norm = 1 eigenvalues = solver.eigenvalues() # Low pass filter data if monthly: fs = 1 nyq = 0.5 * fs # Nyquist frequency low = L / nyq sos = butter(order, low, btype='low', output='sos') # Coefficients for Butterworth filter if monthly: X_tilde = np.empty((da.shape)) for kk in range(12): X_tilde[kk::12, :, :] = sosfiltfilt(sos, da.values[kk::12, :, :], padtype='even', axis=0) else: X_tilde = sosfiltfilt(sos, da.values, axis=0) a_k = eofs.values[:N, :, :].reshape((N, nlat*nlon)) sigma_k = np.sqrt(eigenvalues.values[:N]) if landmask is not None: lnd_mask_vec = is_land.values.flatten() else: lnd_mask_vec = np.ones((nlat*nlon,), dtype=bool) PC_tilde = np.empty((ntime, N)) for kk in range(N): PC_tilde[:, kk] = 1/sigma_k[kk]*np.dot(X_tilde.reshape((ntime, nlat*nlon))[:, lnd_mask_vec], a_k[kk, lnd_mask_vec]) R = np.dot(PC_tilde.T, PC_tilde)/(N - 1) R_eigvals, e_k = np.linalg.eig(R) # eigenvalues already sorted # eigenvalues are in columns u_k = np.dot((a_k.T)/sigma_k, e_k) LFPs = np.dot(sigma_k*(a_k.T), e_k) # Time series: LFCs = np.dot(da.values.reshape((ntime, nlat*nlon))[:, lnd_mask_vec], u_k[lnd_mask_vec, :]) return LFPs, LFCs
coslats = np.cos((np.pi / 180) * latts) coslats = coslats[:-1, :-1] areas = r**2 * coslats * dlats * dlons Q_s = Q_s[:, :-1, :-1] Qr = Qr[:, :-1, :-1] sst = sst[:, :-1, :-1] tendsst = tendsst[:, :-1, :-1] tot_area = np.sum(areas) weights = areas / tot_area #Calculate EOFs for SST, Qs and Qo. Should weight by area? solver = Eof(sst, weights=weights) sst_eof = solver.eofs(neofs=3, eofscaling=2) sst_eof_varfracs = solver.varianceFraction() solver = Eof(Qr, weights=weights) Qo_eof = solver.eofs(neofs=3, eofscaling=2) Qo_pc = solver.pcs(npcs=3, pcscaling=2) Qo_eof_varfracs = solver.varianceFraction() Qo_rec = solver.reconstructedField(5) Qo_rec_var = Qo_rec.var(dim='time') #get projection (pseudo-PCs) associated with Qo EOFs # Qo_eof_projsst = solver.projectField(sst, neofs=3)
# select data in 2019 and plot it ## ONLY DATA FOR THIS PLOT temperature = dataset['tg'] oneday = temperature.sel(time='2009-07-01') oneday.plot(robust=True) # output <matplotlib.collections.QuadMesh at ... > # XARRAY EXTENSIONS! # # simulation models with <xarray-simlab> # WRF Weather Forecasting Model functions (wrf-python) # EMPIRICAL ORTHOGONAL functiosn (eofs) # ... and MORE! @ Xarray site on FAQ "what other projects leverage xarray") # ^^^^^^^^check this out!!^^^^^^^^ from eofs.xarray import Eof monthly = PM25.resample(time='M').mean('time') solver = Eof(monthly) results = solver.eofs() results.plot(col='mode',col_wrap=3, robust=True) # output <xarray.plot.facetgrid.FacetGrid at ... > # RESOURCES .. ** # slides: http://bit.do/xarray_pyconuk # code: https://github.com/robintw/XArray_PyConUK2018 # Xarray dos: http://xarray.pydata.org/ # [email protected] @sciremotesense @robintw on Slack
# Read SST anomalies using the xarray module. The file contains November-March # averages of SST anomaly in the central and northern Pacific. filename = example_data_path('sst_ndjfm_anom.nc') sst = xr.open_dataset(filename)['sst'] sst -= sst.mean('time') # Create an EOF solver to do the EOF analysis. Square-root of cosine of # latitude weights are applied before the computation of EOFs. coslat = np.cos(np.deg2rad(sst.coords['latitude'].values)) wgts = np.sqrt(coslat)[..., np.newaxis] solver = Eof(sst, weights=wgts) # Retrieve the leading EOF, expressed as the correlation between the leading # PC time series and the input SST anomalies at each grid point, and the # leading PC time series itself. eof1 = solver.eofs(neofs=1) pc1 = solver.pcs(npcs=1, pcscaling=1) fig, axes = plt.subplots(1,2) plt.sca(axes[0]) eof1.sel(mode=0).plot.contourf(levels=np.arange(-0.15,0.16,0.03)) mapplot() plt.sca(axes[1]) pc1.sel(mode=0).plot() plt.suptitle('Results from eofs package') plt.tight_layout() # use pca analysis from sklearn n_samples = sst.shape[0] grid_shape = sst.shape[1:] n_grids = np.prod(grid_shape)