Exemplo n.º 1
0
def get_PDO(sst_Pacific):
    #%%
    from eofs.xarray import Eof
    #    PDO   = functions_pp.find_region(sst, region='PDO')[0]
    coslat = np.cos(np.deg2rad(sst_Pacific.coords['latitude'].values)).clip(
        0., 1.)
    area_weights = np.tile(coslat[..., np.newaxis],
                           (1, sst_Pacific.longitude.size))
    area_weights = area_weights / area_weights.mean()
    solver = Eof(sst_Pacific, area_weights)
    # 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.eofsAsCovariance(neofs=1).squeeze()
    PDO_warmblob = eof1.sel(latitude=slice(30, 40)).sel(
        longitude=slice(180, 200)).mean()  # flip sign oef pattern and ts
    assert ~np.isnan(
        PDO_warmblob), 'Could not verify sign of PDO, check lat lon axis'
    init_sign = np.sign(PDO_warmblob)
    if init_sign != -1.:
        adjust_sign = -1
    else:
        adjust_sign = 1
    eof1 *= adjust_sign
    return eof1, solver, adjust_sign
Exemplo n.º 2
0
    def _get_EOF_xarray(ds_EOF, neofs):
        from eofs.xarray import Eof

        coslat = np.cos(np.deg2rad(ds_EOF.coords['latitude'].values)).clip(0., 1.)
        area_weights = np.tile(coslat[..., np.newaxis],(1,ds_EOF.longitude.size))
        area_weights = area_weights / area_weights.mean()
        solver = Eof(ds_EOF, area_weights)
        eofs = solver.eofsAsCovariance(neofs=neofs).squeeze()
        return eofs, solver
Exemplo n.º 3
0
def EOF_SST_analysis(xa, weights, neofs=1, npcs=1, fn=None):
    """ Empirical Orthogonal Function of SST(t,x,y) field """
    assert type(xa) == xr.core.dataarray.DataArray
    assert type(weights) == xr.core.dataarray.DataArray
    assert 'time' in xa.dims
    assert np.shape(xa[0, :, :]) == np.shape(weights)

    # anomalies by removing time mean
    xa = xa - xa.mean(dim='time')
    # Retrieve the leading EOF, expressed as the covariance between the leading PC
    # time series and the input xa anomalies at each grid point.
    solver = Eof(xa, weights=weights)
    eofs = solver.eofsAsCovariance(neofs=neofs)
    pcs = solver.pcs(npcs=npcs, pcscaling=1)
    if fn != None:
        xr.merge([eofs, pcs]).to_netcdf(fn)
    return eofs, pcs
Exemplo n.º 4
0
    def EOF_SST_analysis(self, xa, weights, n=1, fn=None):
        """ Empirical Orthogonal Function analysis of SST(t,x,y) field; from `SST.py` """
        assert type(xa)==xr.core.dataarray.DataArray
        assert type(weights)==xr.core.dataarray.DataArray
        assert 'time' in xa.dims
        assert np.shape(xa[0,:,:])==np.shape(weights)

        # anomalies by removing time mean
        xa = xa - xa.mean(dim='time')
        # Retrieve the leading EOF, expressed as the covariance between the leading PC
        # time series and the input xa anomalies at each grid point.
        solver = Eof(xa, weights=weights)
        eofs = solver.eofsAsCovariance(neofs=n)
        pcs  = solver.pcs(npcs=n, pcscaling=1)
        eigs = solver.eigenvalues(neigs=n)
        varF = solver.varianceFraction(neigs=n)
        ds = xr.merge([eofs, pcs, eigs, varF])
        if fn!=None:  ds.to_netcdf(fn)
        return ds
Exemplo n.º 5
0
 def operate(self, vid: str,
             variable: xa.DataArray) -> Dict[str, xa.DataArray]:
     """
         Convenience method defined for this particular operation
     """
     opSpecs = self.request['operation']
     result_arrays: Dict[str, xa.DataArray] = {}
     for opSpec in opSpecs:
         opId = opSpec['name'].split(':')[1]
         opAxis = opSpec['axis']
         coslat = np.cos(np.deg2rad(variable.coords['latitude'].values))
         wgts = np.sqrt(coslat)[..., np.newaxis]
         solver = Eof(variable, weights=wgts)
         if opId == "correlation":
             result_arrays = solver.eofsAsCorrelation(neofs=1)
         elif opId == "covariance":
             result_arrays = solver.eofsAsCovariance(neofs=1)
         else:
             raise Exception(f"Unknown operation for EOF: '{opId}'")
     return result_arrays
Exemplo n.º 6
0
# Read geopotential height data using the xarray module. The file contains
# December-February averages of geopotential height at 500 hPa for the
# European/Atlantic domain (80W-40E, 20-90N).
filename = example_data_path('hgt_djf.nc')
z_djf = xr.open_dataset(filename)['z']

# Compute anomalies by removing the time-mean.
z_djf = z_djf - z_djf.mean(dim='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(z_djf.coords['latitude'].values)).clip(0., 1.)
wgts = np.sqrt(coslat)[..., np.newaxis]
solver = Eof(z_djf, weights=wgts)

# Retrieve the leading EOF, expressed as the covariance between the leading PC
# time series and the input SLP anomalies at each grid point.
eof1 = solver.eofsAsCovariance(neofs=1)

# Plot the leading EOF expressed as covariance in the European/Atlantic domain.
clevs = np.linspace(-75, 75, 11)
proj = ccrs.Orthographic(central_longitude=-20, central_latitude=60)
ax = plt.axes(projection=proj)
ax.coastlines()
ax.set_global()
eof1[0, 0].plot.contourf(ax=ax, levels=clevs, cmap=plt.cm.RdBu_r,
                         transform=ccrs.PlateCarree(), add_colorbar=False)
ax.set_title('EOF1 expressed as covariance', fontsize=16)
plt.show()
Exemplo n.º 7
0
            time-mean) will be removed prior to analysis. If *False*,
            the mean along the first axis will not be removed. Defaults
            to *True* (mean is removed).
            The covariance interpretation relies on the input data being
            anomaly data with a time-mean of 0. Therefore this option
            should usually be set to *True*. Setting this option to
            *True* has the useful side effect of propagating missing
            values along the time dimension, ensuring that a solution
            can be found even if missing values occur in different
            locations at different times.
'''
lambdas = solver.eigenvalues()
vf = solver.varianceFraction()
Nerror = solver.northTest(vfscaled=True)
pcs = solver.pcs()  #(time, mode)
eofs = solver.eofsAsCovariance()
'''
plt.figure()
plt.subplot(3,2,1)
pcs[:, 0].plot()#color='b', linewidth=2)
ax = plt.gca()
ax.axhline(0, color='k')
ax.set_xlabel('Year')
ax.set_ylabel('PC1 amplitude')
plt.grid()
plt.subplot(3,2,2)
pcs[:, 1].plot()
ax = plt.gca()
ax.axhline(0, color='k')
ax.set_xlabel('Year')
ax.set_ylabel('PC2 amplitude')
Exemplo n.º 8
0
def calcEOF(xrdata, data_var, w, wei=True):
    """
    input:
        xrdata: xarray Dataset
        data_var: string. Variable name to use on EOF.
        w: string. variable for using weights. E.g. latitude

        use as:
            solver, eof1, var1 = calcEOF(xrdata, 'data_var')
    """
    xrdata = xrdata - xrdata[data_var].mean(dim="time")

    # Testing if we can select data from level, lat and time
    try:
        xrdata = xrdata.sel(level=1000,
                            latitude=slice(90, 20),
                            time=slice("1979-01-01", "2000-12-31"))
        print(
            'Data selection OK on first try. Level, lat and time slice done.')
    except ValueError:
        try:
            print('valueError: Trying next')
            xrdata = xrdata.sel(level=1000,
                                lat=slice(90, 20),
                                time=slice("1979-01-01", "2000-12-31"))
            print(
                'Data selection OK on second try. Level, lat and time slice done.'
            )
        except ValueError:
            try:
                print('valueError: Trying next')
                xrdata = xrdata.sel(latitude=slice(90, 20),
                                    time=slice("1979-01-01", "2000-12-31"))
                print('Data selection OK on third try. No level cut')
            except ValueError:
                try:
                    print('valueError: Trying next')
                    xrdata = xrdata.sel(time=slice("1979-01-01", "2000-12-31"))
                    print('Data selection OK on fourth try. Only time slice.')
                except:
                    raise TypeError(' Data out of limits')

    xrdata = (xrdata.groupby('time.month') -
              xrdata[data_var].groupby('time.month').mean())
    #  To ensure equal area weighting for the covariance matrix,
    # the gridded data is weighted by the square root of the cosine of
    # latitude. - NOAA

    if wei == True:
        coslat = np.cos(np.deg2rad(xrdata.coords[w].values)).clip(0., 1.)
        # np.newaxis add a dimention to wgts. dont know what ... does
        # i think its like a transposed. It took all the objects on a list and
        # make a new list with lists inside (each list with only one object)
        # just an adjustment of format
        wgts = np.sqrt(coslat)[..., np.newaxis]
        # The EOF analysis is handled by a solver class, and the EOF solution
        # is computed when the solver class is created. Method calls are then used
        # to retrieve the quantities of interest from the solver class.
        # center = False do not remove mean from data
        # solver = Eof(m_anomalie.hgt, weights=wgts, center=False)
        """
        # solver.eofAsCovariance Returns the EOFs expressed as the covariance between each PC and the input

        # data set at each point in space. they are not actually the EOFs. They tell you how each point in space

        # varies like the given mode. The eofs method provides the raw EOFs (eigenvectors of the covariance

        # matrix) which are the spatial patterns the PCs are the coefficeints of.

        # “The covariance matrix is used for the EOF analysis.” - NOAA """

        solver = Eof(xrdata[data_var], weights=wgts)
    else:
        solver = Eof(xrdata[data_var])
    # solver = Eof(s_anomalie.hgt, weights=wgts, center=False)
    # Retrieve the leading EOF, expressed as the covariance between the leading PC
    # time series and the input SLP anomalies at each grid point.
    eof1 = solver.eofsAsCovariance(pcscaling=1)
    var1 = solver.varianceFraction().sel(mode=0)

    return solver, eof1, var1
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