def load_dataset( self, first_date: np.datetime64, last_date: np.datetime64) -> pyinterp.backends.xarray.Grid3D: """Loads the 3D cube describing the SSH in time and space.""" if first_date < self.ts["date"][0] or last_date > self.ts["date"][-1]: raise IndexError( f"period [{first_date}, {last_date}] is out of range: " f"[{self.ts['date'][0]}, {self.ts['date'][-1]}]") first_date -= self.dt last_date += self.dt selected = self.ts["path"][:] ds = xr.open_mfdataset(selected, concat_dim="time", combine="nested", decode_times=False) ds = ds.sel(depth=0) x_axis = pyinterp.Axis(ds.variables["lon"][:], is_circle=True) y_axis = pyinterp.Axis(ds.variables["lat"][:]) hours = (ds.variables['time'][:].data * 3600000000).astype('timedelta64[us]') time = np.datetime64('2000') + hours z_axis = pyinterp.TemporalAxis(time) var = ds.surf_el[:].T return pyinterp.Grid3D(x_axis, y_axis, z_axis, var)
def test_bicubic(): grid = pyinterp.backends.xarray.Grid2D(xr.load_dataset(GRID).mss) lon = np.arange(-180, 180, 1) + 1 / 3.0 lat = np.arange(-90, 90, 1) + 1 / 3.0 x, y = np.meshgrid(lon, lat, indexing="ij") z = grid.bicubic(collections.OrderedDict(lon=x.flatten(), lat=y.flatten())) assert isinstance(z, np.ndarray) for fitting_model in [ 'linear', 'bicubic', 'polynomial', 'c_spline', 'c_spline_periodic', 'akima', 'akima_periodic', 'steffen' ]: other = grid.bicubic(collections.OrderedDict(lon=x.flatten(), lat=y.flatten()), fitting_model=fitting_model) assert (z - other).mean() != 0 with pytest.raises(ValueError): grid.bicubic(collections.OrderedDict(lon=x.flatten(), lat=y.flatten()), bounds_error=True) with pytest.raises(ValueError): grid.bicubic(collections.OrderedDict(lon=x.flatten(), lat=y.flatten()), bounds_error=True, boundary="sym") x_axis = pyinterp.Axis(np.linspace(-180, 179, 360), is_circle=True) y_axis = pyinterp.Axis(np.linspace(-90, 90, 181), is_circle=False) z_axis = pyinterp.Axis(np.linspace(0, 10, 10), is_circle=False) matrix, _ = np.meshgrid(x_axis[:], y_axis[:]) grid = pyinterp.Grid2D(x_axis, y_axis, matrix.T) assert isinstance(grid, pyinterp.Grid2D) with pytest.raises(ValueError): pyinterp.bicubic(grid, x.flatten(), y.flatten(), fitting_model='_') with pytest.raises(ValueError): pyinterp.bicubic(grid, x.flatten(), y.flatten(), boundary='_') grid = pyinterp.Grid2D(x_axis.flip(inplace=False), y_axis, matrix.T) with pytest.raises(ValueError): pyinterp.bicubic(grid, x.flatten(), y.flatten()) grid = pyinterp.Grid2D(x_axis, y_axis.flip(), matrix.T) with pytest.raises(ValueError): pyinterp.bicubic(grid, x.flatten(), y.flatten()) matrix, _, _ = np.meshgrid(x_axis[:], y_axis[:], z_axis[:]) grid = pyinterp.Grid3D(x_axis, y_axis, z_axis, matrix.transpose(1, 0, 2)) with pytest.raises(ValueError): pyinterp.bicubic(grid, x.flatten(), y.flatten()) grid = pyinterp.backends.xarray.RegularGridInterpolator( xr.load_dataset(GRID).mss) assert grid.ndim == 2 assert isinstance(grid.grid, pyinterp.backends.xarray.Grid2D) z = grid(collections.OrderedDict(lon=x.flatten(), lat=y.flatten()), method="bicubic", bicubic_kwargs=dict(nx=3, ny=3)) assert isinstance(z, np.ndarray)
def bfn_grid_dataset(list_of_file, var2add, var2sub, lon_min=0., lon_max=360., lat_min=-90, lat_max=90., time_min='1900-10-01', time_max='2100-01-01', is_circle=True): ds = xr.open_mfdataset(list_of_file, concat_dim ='time', combine='nested', parallel=True) ds = ds.sel(time=slice(time_min, time_max)) ds = ds.where((ds["lon"]%360. >= lon_min) & (ds["lon"]%360. <= lon_max), drop=True) ds = ds.where((ds["lat"] >= lat_min) & (ds["lat"] <= lat_max), drop=True) x_axis = pyinterp.Axis(ds["lon"][:]%360., is_circle=is_circle) y_axis = pyinterp.Axis(ds["lat"][:]) z_axis = pyinterp.TemporalAxis(ds["time"][:]) for variable_name in var2add: try: var += ds[variable_name][:] except UnboundLocalError: var = ds[variable_name][:] for variable_name in var2sub: try: var -= ds[variable_name][:] except UnboundLocalError: var = ds[variable_name][:] # MB clean boundary for file OSE_GULFSTREAM_FPGENN.nc #var.values[:, 0:3, :] = np.nan #var.values[:, :, 0:3] = np.nan # ds['time'] = (ds['time'] - np.datetime64('1950-01-01T00:00:00Z')) / np.timedelta64(1, 'D') var = var.transpose('lon', 'lat', 'time') # The undefined values must be set to nan. try: var[var.mask] = float("nan") except AttributeError: pass grid = pyinterp.Grid3D(x_axis, y_axis, z_axis, var.data) del ds return x_axis, y_axis, z_axis, grid
def dymost_grid_dataset(list_of_file, var2add, var2sub, lon_min=0., lon_max=360., lat_min=-90, lat_max=90., time_min='1900-10-01', time_max='2100-01-01', is_circle=True): ds = xr.open_mfdataset(list_of_file, concat_dim ='time', combine='nested', parallel=True) ds = ds.sel(time=slice(time_min, time_max)) ds = ds.where((ds["lon"] >= lon_min) & (ds["lon"] <= lon_max), drop=True) ds = ds.where((ds["lat"] >= lat_min) & (ds["lat"] <= lat_max), drop=True) # print(ds) x_axis = pyinterp.Axis(ds["lon"][0, :], is_circle=is_circle) y_axis = pyinterp.Axis(ds["lat"][:, 0]) z_axis = pyinterp.TemporalAxis(ds["time"][:]) for variable_name in var2add: try: var += ds[variable_name][:] #ds['Ha'][:] except UnboundLocalError: var = ds[variable_name][:] for variable_name in var2sub: try: var -= ds[variable_name][:] except UnboundLocalError: var = ds[variable_name][:] var = var.transpose('x', 'y', 'time') # The undefined values must be set to nan. try: var[var.mask] = float("nan") except AttributeError: pass grid = pyinterp.Grid3D(x_axis, y_axis, z_axis, var.data) del ds return x_axis, y_axis, z_axis, grid
def duacs_grid_dataset(list_of_file, variable_name='Grid_0001', lon_min=0., lon_max=360., lat_min=-90, lat_max=90., time_min='1900-10-01', time_max='2100-01-01', is_circle=True): def preprocess_duacs_maps(ds): vtime = ds[variable_name].attrs['Date_CNES_JD'] ds.coords['time'] = np.datetime64(netCDF4.num2date(vtime, units='days since 1950-01-01')) if ds[variable_name].units == 'cm': ds[variable_name] = ds[variable_name] / 100. ds[variable_name].attrs = {'units': 'm'} return ds ds = xr.open_mfdataset(list_of_file, concat_dim ='time', combine='nested', parallel=True, preprocess=preprocess_duacs_maps) ds = ds.sel(time=slice(time_min, time_max)) ds = ds.where((ds["NbLongitudes"] >= lon_min) & (ds["NbLongitudes"] <= lon_max), drop=True) ds = ds.where((ds["NbLatitudes"] >= lat_min) & (ds["NbLatitudes"] <= lat_max), drop=True) x_axis = pyinterp.Axis(ds["NbLongitudes"][:], is_circle=is_circle) y_axis = pyinterp.Axis(ds["NbLatitudes"][:]) z_axis = pyinterp.TemporalAxis(ds["time"][:]) var = ds[variable_name][:].transpose('NbLongitudes', 'NbLatitudes', 'time') # The undefined values must be set to nan. try: var[var.mask] = float("nan") except AttributeError: pass grid = pyinterp.Grid3D(x_axis, y_axis, z_axis, var.data) del ds return x_axis, y_axis, z_axis, grid
def read_l4_dataset(list_of_file, lon_min=0., lon_max=360., lat_min=-90, lat_max=90., time_min='1900-10-01', time_max='2100-01-01', is_circle=True): ds = xr.open_mfdataset(list_of_file, concat_dim='time', combine='nested', parallel=True) ds = ds.sel(time=slice(time_min, time_max), drop=True) ds = ds.where( (ds["lon"] % 360. >= lon_min) & (ds["lon"] % 360. <= lon_max), drop=True) ds = ds.where((ds["lat"] >= lat_min) & (ds["lat"] <= lat_max), drop=True) x_axis = pyinterp.Axis(ds["lon"][:] % 360., is_circle=is_circle) y_axis = pyinterp.Axis(ds["lat"][:]) z_axis = pyinterp.TemporalAxis(ds["time"][:]) var = ds['ssh'][:] var = var.transpose('lon', 'lat', 'time') # The undefined values must be set to nan. try: var[var.mask] = float("nan") except AttributeError: pass grid = pyinterp.Grid3D(x_axis, y_axis, z_axis, var.data) del ds return x_axis, y_axis, z_axis, grid
def oi_regrid(ds_source, ds_target): logging.info(' Regridding...') # Define source grid x_source_axis = pyinterp.Axis(ds_source["lon"][:], is_circle=False) y_source_axis = pyinterp.Axis(ds_source["lat"][:]) z_source_axis = pyinterp.TemporalAxis(ds_source["time"][:]) ssh_source = ds_source["gssh"][:].T grid_source = pyinterp.Grid3D(x_source_axis, y_source_axis, z_source_axis, ssh_source.data) # Define target grid mx_target, my_target, mz_target = numpy.meshgrid( ds_target['lon'].values, ds_target['lat'].values, z_source_axis.safe_cast(ds_target['time'].values), indexing="ij") # Spatio-temporal Interpolation ssh_interp = pyinterp.trivariate(grid_source, mx_target.flatten(), my_target.flatten(), mz_target.flatten(), bounds_error=True).reshape( mx_target.shape).T # Save to dataset ds_ssh_interp = xr.Dataset( {'sossheig': (('time', 'lat', 'lon'), ssh_interp)}, coords={ 'time': ds_target['time'].values, 'lon': ds_target['lon'].values, 'lat': ds_target['lat'].values, }) return ds_ssh_interp
def load_dataset( self, first_date: np.datetime64, last_date: np.datetime64) -> pyinterp.backends.xarray.Grid3D: """Loads the 3D cube describing the SSH in time and space.""" if first_date < self.ts["date"][0] or last_date > self.ts["date"][-1]: raise IndexError( f"period [{first_date}, {last_date}] is out of range: " f"[{self.ts['date'][0]}, {self.ts['date'][-1]}]") first_date -= self.dt last_date += self.dt selected = self.ts["path"][(self.ts["date"] >= first_date) & (self.ts["date"] < last_date)] ds = xr.open_mfdataset(selected, concat_dim="time", combine="nested", decode_times=True) x_axis = pyinterp.Axis(ds.variables["longitude"][:], is_circle=True) y_axis = pyinterp.Axis(ds.variables["latitude"][:]) z_axis = pyinterp.TemporalAxis(ds.time) var = ds.wlv[:].T return pyinterp.Grid3D(x_axis, y_axis, z_axis, var)
def interpolate(self, lon: np.ndarray, lat: np.ndarray, dates: np.ndarray) -> np.ndarray: """Interpolate the SSH to the required coordinates.""" ds = self._select_ds( dates.min(), # type: ignore dates.max()) # type: ignore assert np.all(np.diff(ds.ocean_time.values) == self._dt) assert np.all(np.diff(ds.lon_rho.values, axis=0) < 1e-10) assert np.all(np.diff(ds.lat_rho.values, axis=1) < 1e-10) t_axis = pyinterp.TemporalAxis(ds.ocean_time.values) grid3d = pyinterp.Grid3D( pyinterp.Axis(ds.lon_rho.values[0, :], is_circle=True), pyinterp.Axis(ds.lat_rho.values[:, 0]), t_axis, ds[self.ssh].values.T) ssh = pyinterp.trivariate(grid3d, lon.ravel(), lat.ravel(), t_axis.safe_cast(dates.ravel()), num_threads=1).reshape(lon.shape) return ssh
# tensor data so that it is properly stored in memory for pyinterp. #%% # * The shape of the tensor must be (len(x_axis), len(y_axis), len(t_axis)) tcw = tcw.T #%% # * The undefined values must be set to nan. tcw[tcw.mask] = float("nan") #%% # Now we can build the object handling the regular 3-dimensional grid. # # .. note:: # Grid data are not copied, the Grid3D class just keeps a reference on the # handled array. Axis data are copied for non-uniform axes, and only examined # for regular axes. grid_3d = pyinterp.Grid3D(x_axis, y_axis, t_axis, tcw) grid_3d #%% # xarray backend # ############## # # The construction of these objects manipulating the :py:class:`regular grids # <pyinterp.backends.xarray.RegularGridInterpolator>` can be done more easily # using the `xarray <http://xarray.pydata.org/>`_ library and `CF # <https://cfconventions.org/>`_ convention usually found in NetCDF files. interpolator = pyinterp.backends.xarray.RegularGridInterpolator( xarray.open_dataset(TCW).tcw) interpolator.grid