def test_get_sample_from_bil_info(self): """Test bilinear interpolation as a whole.""" import dask.array as da from xarray import DataArray from pyresample.bilinear.xarr import XArrayResamplerBilinear resampler = XArrayResamplerBilinear(self.source_def, self.target_def, self.radius) resampler.get_bil_info() # Sample from data1 res = resampler.get_sample_from_bil_info(self.data1) res = res.compute() # Check couple of values self.assertEqual(res.values[1, 1], 1.) self.assertTrue(np.isnan(res.values[0, 3])) # Check that the values haven't gone down or up a lot self.assertAlmostEqual(np.nanmin(res.values), 1.) self.assertAlmostEqual(np.nanmax(res.values), 1.) # Check that dimensions are the same self.assertEqual(res.dims, self.data1.dims) # Sample from data1, custom fill value res = resampler.get_sample_from_bil_info(self.data1, fill_value=-1.0) res = res.compute() self.assertEqual(np.nanmin(res.values), -1.) # Sample from integer data res = resampler.get_sample_from_bil_info(self.data1.astype(np.uint8), fill_value=None) res = res.compute() # Five values should be filled with zeros, which is the # default fill_value for integer data self.assertEqual(np.sum(res == 0), 6) # Output coordinates should have been set self.assertTrue(isinstance(resampler._out_coords, dict)) self.assertTrue( np.all(resampler._out_coords['x'] == resampler.out_coords_x)) self.assertTrue( np.all(resampler._out_coords['y'] == resampler.out_coords_y)) # 3D data data = da.moveaxis(da.dstack((self.data1, self.data1)), -1, 0) data = DataArray(data, dims=('bands', 'y', 'x')) res = resampler.get_sample_from_bil_info(data) assert res.shape == (2, ) + self.target_def.shape assert res.dims == data.dims
def test_get_sample_from_bil_info(self): """Test bilinear interpolation as a whole.""" from pyresample.bilinear.xarr import XArrayResamplerBilinear resampler = XArrayResamplerBilinear(self.source_def, self.target_def, self.radius) _ = resampler.get_bil_info() # Sample from data1 res = resampler.get_sample_from_bil_info(self.data1) res = res.compute() # Check couple of values self.assertEqual(res.values[1, 1], 1.) self.assertTrue(np.isnan(res.values[0, 3])) # Check that the values haven't gone down or up a lot self.assertAlmostEqual(np.nanmin(res.values), 1.) self.assertAlmostEqual(np.nanmax(res.values), 1.) # Check that dimensions are the same self.assertEqual(res.dims, self.data1.dims) # Sample from data1, custom fill value res = resampler.get_sample_from_bil_info(self.data1, fill_value=-1.0) res = res.compute() self.assertEqual(np.nanmin(res.values), -1.) # Sample from integer data res = resampler.get_sample_from_bil_info(self.data1.astype(np.uint8), fill_value=None) res = res.compute() # Five values should be filled with zeros, which is the # default fill_value for integer data self.assertEqual(np.sum(res == 0), 6)
def test_slice_data(self): """Test slicing the data.""" import dask.array as da from xarray import DataArray from pyresample.bilinear.xarr import XArrayResamplerBilinear resampler = XArrayResamplerBilinear(self.source_def, self.target_def, self.radius) resampler.get_bil_info() # Too many dimensions data = DataArray(da.ones((1, 3) + self.source_def.shape)) with self.assertRaises(ValueError): _ = resampler._slice_data(data, np.nan) # 2D data data = DataArray(da.ones(self.source_def.shape)) p_1, p_2, p_3, p_4 = resampler._slice_data(data, np.nan) self.assertEqual(p_1.shape, resampler.bilinear_s.shape) self.assertTrue(p_1.shape == p_2.shape == p_3.shape == p_4.shape) self.assertTrue( np.all(p_1 == 1.0) and np.all(p_2 == 1.0) and np.all(p_3 == 1.0) and np.all(p_4 == 1.0)) # 2D data with masking resampler.mask_slices[:, :] = True p_1, p_2, p_3, p_4 = resampler._slice_data(data, np.nan) self.assertTrue( np.all(np.isnan(p_1)) and np.all(np.isnan(p_2)) and np.all(np.isnan(p_3)) and np.all(np.isnan(p_4))) # 3D data data = DataArray(da.ones((3, ) + self.source_def.shape)) resampler.mask_slices[:, :] = False p_1, p_2, p_3, p_4 = resampler._slice_data(data, np.nan) self.assertEqual(p_1.shape, (3, ) + resampler.bilinear_s.shape) self.assertTrue(p_1.shape == p_2.shape == p_3.shape == p_4.shape) # 3D data with masking resampler.mask_slices[:, :] = True p_1, p_2, p_3, p_4 = resampler._slice_data(data, np.nan) self.assertTrue( np.all(np.isnan(p_1)) and np.all(np.isnan(p_2)) and np.all(np.isnan(p_3)) and np.all(np.isnan(p_4)))
class BilinearResampler(BaseResampler): """Resample using bilinear.""" def __init__(self, source_geo_def, target_geo_def): super(BilinearResampler, self).__init__(source_geo_def, target_geo_def) self.resampler = None def precompute(self, mask=None, radius_of_influence=50000, epsilon=0, reduce_data=True, nprocs=1, cache_dir=False, **kwargs): """Create bilinear coefficients and store them for later use. Note: The `mask` keyword should be provided if geolocation may be valid where data points are invalid. This defaults to the `mask` attribute of the `data` numpy masked array passed to the `resample` method. """ del kwargs if self.resampler is None: kwargs = dict(source_geo_def=self.source_geo_def, target_geo_def=self.target_geo_def, radius_of_influence=radius_of_influence, neighbours=32, epsilon=epsilon, reduce_data=reduce_data) self.resampler = XArrayResamplerBilinear(**kwargs) try: self.load_bil_info(cache_dir, **kwargs) LOG.debug("Loaded bilinear parameters") except IOError: LOG.debug("Computing bilinear parameters") self.resampler.get_bil_info() self.save_bil_info(cache_dir, **kwargs) def load_bil_info(self, cache_dir, **kwargs): if cache_dir: filename = self._create_cache_filename(cache_dir, prefix='resample_lut_bil_', **kwargs) cache = np.load(filename) for elt in ['bilinear_s', 'bilinear_t', 'valid_input_index', 'index_array']: if isinstance(cache[elt], tuple): setattr(self.resampler, elt, cache[elt][0]) else: setattr(self.resampler, elt, cache[elt]) cache.close() else: raise IOError def save_bil_info(self, cache_dir, **kwargs): if cache_dir: filename = self._create_cache_filename(cache_dir, prefix='resample_lut_bil_', **kwargs) LOG.info('Saving kd_tree neighbour info to %s', filename) cache = {'bilinear_s': self.resampler.bilinear_s, 'bilinear_t': self.resampler.bilinear_t, 'valid_input_index': self.resampler.valid_input_index, 'index_array': self.resampler.index_array} np.savez(filename, **cache) def compute(self, data, fill_value=None, **kwargs): """Resample the given data using bilinear interpolation""" del kwargs if fill_value is None: fill_value = data.attrs.get('_FillValue') target_shape = self.target_geo_def.shape res = self.resampler.get_sample_from_bil_info(data, fill_value=fill_value, output_shape=target_shape) return res
class BilinearResampler(BaseResampler): """Resample using bilinear.""" def __init__(self, source_geo_def, target_geo_def): """Init BilinearResampler.""" super(BilinearResampler, self).__init__(source_geo_def, target_geo_def) self.resampler = None def precompute(self, mask=None, radius_of_influence=50000, epsilon=0, reduce_data=True, cache_dir=False, **kwargs): """Create bilinear coefficients and store them for later use. Note: The `mask` keyword should be provided if geolocation may be valid where data points are invalid. This defaults to the `mask` attribute of the `data` numpy masked array passed to the `resample` method. """ del kwargs if self.resampler is None: kwargs = dict(source_geo_def=self.source_geo_def, target_geo_def=self.target_geo_def, radius_of_influence=radius_of_influence, neighbours=32, epsilon=epsilon, reduce_data=reduce_data) self.resampler = XArrayResamplerBilinear(**kwargs) try: self.load_bil_info(cache_dir, **kwargs) LOG.debug("Loaded bilinear parameters") except IOError: LOG.debug("Computing bilinear parameters") self.resampler.get_bil_info() self.save_bil_info(cache_dir, **kwargs) def load_bil_info(self, cache_dir, **kwargs): """Load bilinear resampling info from cache directory.""" if cache_dir: filename = self._create_cache_filename(cache_dir, prefix='bil_lut-', **kwargs) for val in BIL_COORDINATES.keys(): try: cache = da.from_zarr(filename, val) if val == 'valid_input_index': # valid input index array needs to be boolean cache = cache.astype(np.bool) # Compute the cache arrays cache = cache.compute() except ValueError: raise IOError setattr(self.resampler, val, cache) else: raise IOError def save_bil_info(self, cache_dir, **kwargs): """Save bilinear resampling info to cache directory.""" if cache_dir: filename = self._create_cache_filename(cache_dir, prefix='bil_lut-', **kwargs) LOG.info('Saving BIL neighbour info to %s', filename) zarr_out = xr.Dataset() for idx_name, coord in BIL_COORDINATES.items(): var = getattr(self.resampler, idx_name) if isinstance(var, np.ndarray): var = da.from_array(var, chunks=CHUNK_SIZE) var = var.rechunk(CHUNK_SIZE) zarr_out[idx_name] = (coord, var) zarr_out.to_zarr(filename) def compute(self, data, fill_value=None, **kwargs): """Resample the given data using bilinear interpolation.""" del kwargs if fill_value is None: fill_value = data.attrs.get('_FillValue') target_shape = self.target_geo_def.shape res = self.resampler.get_sample_from_bil_info(data, fill_value=fill_value, output_shape=target_shape) return update_resampled_coords(data, res, self.target_geo_def)
def test_get_bil_info(self): """Test calculation of bilinear info.""" from pyresample.bilinear.xarr import XArrayResamplerBilinear def _check_ts(t__, s__, nans): for i, _ in enumerate(t__): # Just check the exact value for one pixel if i == 5: self.assertAlmostEqual(t__[i], 0.730659147133, 5) self.assertAlmostEqual(s__[i], 0.310314173004, 5) # These pixels are outside the area elif i in nans: self.assertTrue(np.isnan(t__[i])) self.assertTrue(np.isnan(s__[i])) # All the others should have values between 0.0 and 1.0 else: self.assertTrue(t__[i] >= 0.0) self.assertTrue(s__[i] >= 0.0) self.assertTrue(t__[i] <= 1.0) self.assertTrue(s__[i] <= 1.0) # Data reduction enabled (default) resampler = XArrayResamplerBilinear(self.source_def, self.target_def, self.radius, reduce_data=True) (t__, s__, slices, mask_slices, out_coords) = resampler.get_bil_info() _check_ts(t__.compute(), s__.compute(), [3, 10, 12, 13, 14, 15]) # Nothing should be masked based on coordinates self.assertTrue(np.all(~mask_slices)) # Four values per output location self.assertEqual(mask_slices.shape, (self.target_def.size, 4)) # self.slices_{x,y} are used in self.slices dict so they # should be the same (object) self.assertTrue(isinstance(slices, dict)) self.assertTrue(resampler.slices['x'] is resampler.slices_x) self.assertTrue(np.all(resampler.slices['x'] == slices['x'])) self.assertTrue(resampler.slices['y'] is resampler.slices_y) self.assertTrue(np.all(resampler.slices['y'] == slices['y'])) # self.slices_{x,y} are used in self.slices dict so they # should be the same (object) self.assertTrue(isinstance(out_coords, dict)) self.assertTrue(resampler.out_coords['x'] is resampler.out_coords_x) self.assertTrue(np.all(resampler.out_coords['x'] == out_coords['x'])) self.assertTrue(resampler.out_coords['y'] is resampler.out_coords_y) self.assertTrue(np.all(resampler.out_coords['y'] == out_coords['y'])) # Also some other attributes should have been set self.assertTrue(t__ is resampler.bilinear_t) self.assertTrue(s__ is resampler.bilinear_s) self.assertIsNotNone(resampler.valid_output_index) self.assertIsNotNone(resampler.index_array) self.assertIsNotNone(resampler.valid_input_index) # Data reduction disabled resampler = XArrayResamplerBilinear(self.source_def, self.target_def, self.radius, reduce_data=False) (t__, s__, slices, mask_slices, out_coords) = resampler.get_bil_info() _check_ts(t__.compute(), s__.compute(), [10, 12, 13, 14, 15])
def test_get_bil_info(self): """Test calculation of bilinear info.""" from pyresample.bilinear.xarr import XArrayResamplerBilinear def _check_ts(t__, s__, nans): for i, _ in enumerate(t__): # Just check the exact value for one pixel if i == 5: self.assertAlmostEqual(t__[i], 0.730659147133, 5) self.assertAlmostEqual(s__[i], 0.310314173004, 5) # These pixels are outside the area elif i in nans: self.assertTrue(np.isnan(t__[i])) self.assertTrue(np.isnan(s__[i])) # All the others should have values between 0.0 and 1.0 else: self.assertTrue(t__[i] >= 0.0) self.assertTrue(s__[i] >= 0.0) self.assertTrue(t__[i] <= 1.0) self.assertTrue(s__[i] <= 1.0) # Data reduction enabled (default) resampler = XArrayResamplerBilinear(self.source_def, self.target_def, self.radius, reduce_data=True) resampler.get_bil_info() t__ = resampler.bilinear_t s__ = resampler.bilinear_s mask_slices = resampler.mask_slices _check_ts(t__, s__, [3, 10, 12, 13, 14, 15]) # Nothing should be masked based on coordinates self.assertTrue(np.all(~mask_slices)) # Four values per output location self.assertEqual(mask_slices.shape, (self.target_def.size, 4)) # Also some other attributes should have been set self.assertTrue(t__ is resampler.bilinear_t) self.assertTrue(s__ is resampler.bilinear_s) self.assertIsNotNone(resampler._index_array) self.assertIsNotNone(resampler._valid_input_index) self.assertIsNotNone(resampler.out_coords_x) self.assertIsNotNone(resampler.out_coords_y) self.assertTrue( np.allclose(resampler.out_coords_x, [-1070912.72, -470912.72, 129087.28, 729087.28])) self.assertTrue( np.allclose(resampler.out_coords_y, [1190031.36, 590031.36, -9968.64, -609968.64])) # Data reduction disabled resampler = XArrayResamplerBilinear(self.source_def, self.target_def, self.radius, reduce_data=False) resampler.get_bil_info() t__ = resampler.bilinear_t s__ = resampler.bilinear_s mask_slices = resampler.mask_slices _check_ts(t__, s__, [10, 12, 13, 14, 15]) # Target area and source data do not overlap resampler = XArrayResamplerBilinear(self.source_def, self.target_def_outside, self.radius, reduce_data=False) resampler.get_bil_info() self.assertEqual(resampler.bilinear_t.shape, (self.target_def_outside.size, )) self.assertEqual(resampler.bilinear_s.shape, (self.target_def_outside.size, )) self.assertEqual(resampler.slices_x.shape, (self.target_def_outside.size, 4)) self.assertEqual(resampler.slices_y.shape, (self.target_def_outside.size, 4)) self.assertEqual(resampler.out_coords_x.shape, (self.target_def_outside.shape[1], )) self.assertEqual(resampler.out_coords_y.shape, (self.target_def_outside.shape[0], )) self.assertEqual(resampler.mask_slices.shape, (self.target_def_outside.size, 4))