def data_arrays_resampling_demo(): """init demo data arrays (2d) and meta data for resampling""" data_arrays = list() # demo pop: data_arrays.append(np.array([[0, 1, 2], [3, 4, 5]], dtype='float32')) data_arrays.append(np.array([[0, 1, 2], [3, 4, 5]], dtype='float32')) # array([[0, 1, 2], # [3, 4, 5]]) # demo nightlight: data_arrays.append( np.array([[2, 10, 0, 0, 0, 0], [10, 2, 10, 0, 0, 0], [0, 0, 0, 0, 1, 1], [1, 0, 0, 0, 1, 1]], dtype='float32')) # array([[ 2., 10., 0., 0., 0., 0.], # [10., 2., 10., 0., 0., 0.], # [ 0., 0., 0., 0., 1., 1.], # [ 1., 0., 0., 0., 1., 1.]], dtype=float32)] meta_list = [ { 'driver': 'GTiff', 'dtype': 'float32', 'nodata': -3.4028230607370965e+38, 'width': 3, 'height': 2, 'count': 1, 'crs': CRS.from_epsg(4326), #'crs': CRS.from_epsg(4326), 'transform': Affine(1, 0.0, -10, 0.0, -1, 40), }, { 'driver': 'GTiff', 'dtype': 'float32', 'nodata': -3.4028230607370965e+38, 'width': 3, 'height': 2, 'count': 1, 'crs': CRS.from_epsg(4326), #'crs': CRS.from_epsg(4326), 'transform': Affine(1, 0.0, -10, 0.0, -1, 41), # shifted by 1 degree latitude to the north }, { 'driver': 'GTiff', 'dtype': 'float32', 'nodata': None, 'width': 6, 'height': 4, 'count': 1, 'crs': CRS.from_epsg(4326), # 'crs': CRS.from_epsg(32662), 'transform': Affine(.5, 0.0, -10, 0.0, -.5, 40), # higher resolution } ] return data_arrays, meta_list
def resample_raster_dataset(raster, scale): t = raster.transform # rescale the metadata transform = Affine(t.a / scale, t.b, t.c, t.d, t.e / scale, t.f) height = int(raster.height * scale) width = int(raster.width * scale) profile = raster.profile profile.update(transform=transform, driver='GTiff', height=height, width=width) data = raster.read( # Note changed order of indexes, arrays are band, row, col order not row, col, band out_shape=(raster.count, height, width), resampling=Resampling.bilinear, ) with MemoryFile() as memfile: with memfile.open(**profile) as dataset: # Open as DatasetWriter dataset.write(data) with memfile.open() as dataset: # Reopen as DatasetReader return data, dataset
def ShapeToArray(inputgeodf, cellsize, valfield=None, fillval=0): """Transform vector data into numpy arrays. Locations that vector data presents are valued to 1, otherwise 0. :param GeoDataFrame inputgeodf: input GeoDataFrame :param int cellsize: cell size used to transform the vector data :param string valfield: the field contains values for each cell in the output array :param int fillval: fill value for all areas not covered by the input geometries :return: numpy array, affine object, and extent of the original vector data """ extent = inputgeodf.total_bounds outshape = (int(round((extent[3] - extent[1]) / cellsize)), int(round((extent[2] - extent[0]) / cellsize))) trans = Affine(cellsize, 0, extent[0], 0, -cellsize, extent[3]) if valfield is None: arr = features.rasterize(inputgeodf[inputgeodf.geometry.name], out_shape=outshape, fill=fillval, transform=trans) else: arr = features.rasterize(tuple( zip(inputgeodf[inputgeodf.geometry.name], inputgeodf[valfield])), out_shape=outshape, fill=fillval, transform=trans) return arr, trans, extent
def _yield_downsampled_raster(raster): # https://gis.stackexchange.com/questions/329434/creating-an-in-memory-rasterio-dataset-from-numpy-array/329439#329439 max_n = np.product(MAX_LOAD_SHAPE) n = raster.height * raster.width scale = 1.0 if n > max_n: scale = max_n / n if scale == 1.0: yield raster return t = raster.transform # rescale the metadata transform = Affine(t.a / scale, t.b, t.c, t.d, t.e / scale, t.f) height = int(raster.height * scale) width = int(raster.width * scale) profile = raster.profile profile.update(transform=transform, height=height, width=width) data = raster.read( out_shape=(raster.count, height, width), resampling=Resampling.bilinear, ) with MemoryFile() as memfile: with memfile.open(**profile) as dataset: dataset.write(data) del data with memfile.open() as dataset: # Reopen as DatasetReader yield dataset # Note yield not return
def append(self, centr): """ Append raster or points. Raster needs to have the same resolution """ if self.meta and centr.meta: LOGGER.debug('Appending raster') if centr.meta['crs'] != self.meta['crs']: LOGGER.error('Different CRS not accepted.') raise ValueError if self.meta['transform'][0] != centr.meta['transform'][0] or \ self.meta['transform'][4] != centr.meta['transform'][4]: LOGGER.error('Different raster resolutions.') raise ValueError left = min(self.total_bounds[0], centr.total_bounds[0]) bottom = min(self.total_bounds[1], centr.total_bounds[1]) right = max(self.total_bounds[2], centr.total_bounds[2]) top = max(self.total_bounds[3], centr.total_bounds[3]) crs = self.meta['crs'] width = (right - left) / self.meta['transform'][0] height = (bottom - top) / self.meta['transform'][4] self.meta = {'dtype':'float32', 'width':width, 'height':height, 'crs':crs, 'transform':Affine(self.meta['transform'][0], \ 0.0, left, 0.0, self.meta['transform'][4], top)} else: LOGGER.debug('Appending points') if not equal_crs(centr.geometry.crs, self.geometry.crs): LOGGER.error('Different CRS not accepted.') raise ValueError lat = np.append(self.lat, centr.lat) lon = np.append(self.lon, centr.lon) crs = self.geometry.crs self.__init__() self.set_lat_lon(lat, lon, crs)
def test_file_writer(): test_data = np.zeros((3, 256, 256), dtype=np.uint8) test_opts = { 'driver': 'PNG', 'dtype': 'uint8', 'height': 512, 'width': 512, 'count': 3, 'crs': 'EPSG:3857' } test_affine = Affine(1, 0, 0, 0, -1, 0) test_bytearray = _encode_as_png(test_data, test_opts, test_affine) assert len(test_bytearray) == 842 test_complex_data = test_data.copy() test_complex_data[0] += (np.random.rand(256, 256) * 255).astype(np.uint8) test_complex_data[1] += 10 test_bytearray_complex = _encode_as_png(test_complex_data, test_opts, test_affine) assert len(test_bytearray) < len(test_bytearray_complex)
def resample(self, dst_res=None, dst_shape=None, interpolation='nearest'): transform = self.transform if dst_res is None else Affine( dst_res[1], self.transform.b, self.transform.c, self.transform.d, -dst_res[0], self.transform.f) if dst_res is not None and dst_shape is None: target_height = int(self.height * self.res[0] / dst_res[0]) target_width = int(self.width * self.res[1] / dst_res[1]) elif dst_shape is not None: target_height = dst_shape[1] target_width = dst_shape[2] else: target_height = self.height target_width = self.width new_raster = np.empty(shape=(1, target_height, target_width), dtype=self.dtype) reproject(self._raster, new_raster, src_transform=self.transform, dst_transform=transform, src_crs=self.crs, dst_crs=self.crs, resampling=getattr(Resampling, interpolation)) return BandSample(self._name, new_raster, self.crs, transform, self.nodata)
class Img(object): def __enter__(self): return self def __exit__(self, type, value, tb): pass @staticmethod def read_masks(band: int = 0, window: Optional[Window] = None) -> np.ndarray: return np.array([[0, 0, 0], [0, 1, 0], [0, 0, 0]]) @staticmethod def block_windows(idx: int): for i in range(0, 2): yield (0, i), Window(i, 0, 1, 1) profile: Dict[str, Any] = { "transform": Affine(0, 2, 0, 0, -2, 0), "width": 3, "height": 3, "crs": CRS.from_epsg(4326), "blockxsize": 16, "blockysize": 16, "dtype": np.dtype("uint"), } bounds: box = box(1, 1, 0, 0)
def sample(self, y, x, height, width, **kwargs): """ Read sample of of band to memory with specified: x, y - pixel coordinates of left top corner width, height - spatial dimension of sample in pixels Return: `Sample` object """ coord_x = self.transform.c + x * self.transform.a coord_y = self.transform.f + y * self.transform.e dst_crs = self.crs dst_name = os.path.basename(self.name) dst_nodata = self.nodata if self.nodata is not None else 0 dst_transform = Affine(self.transform.a, self.transform.b, coord_x, self.transform.d, self.transform.e, coord_y) dst_raster = self._band.read(window=((y, y + height), (x, x + width)), boundless=True, fill_value=dst_nodata) sample = BandSample(dst_name, dst_raster, dst_crs, dst_transform, dst_nodata) return sample
def get_transform(xul, yul, dx, dy=None, rotation=0.): """Returns an affine.Affine instance that can be used to locate raster grids in space. See https://www.perrygeo.com/python-affine-transforms.html https://rasterio.readthedocs.io/en/stable/topics/migrating-to-v1.html Parameters ---------- xul : float x-coorindate of upper left corner of raster grid yul : float y-coorindate of upper left corner of raster grid dx : float cell spacing in the x-direction dy : float cell spacing in the y-direction rotation : rotation of the raster grid in degrees, clockwise Returns ------- affine.Affine instance """ if not rasterio: raise ModuleNotFoundError( 'This function requires rasterio. Please conda install rasterio.') if dy is None: dy = -dx return Affine(dx, 0., xul, 0., dy, yul) * \ Affine.rotation(rotation)
def makeTesting(output, size, windowsize, bands): kwargs = { 'count': bands, 'crs': { 'init': u'epsg:3857' }, 'dtype': 'uint8', 'driver': u'GTiff', 'transform': Affine(4.595839562240513, 0.0, -13550756.3744, 0.0, -4.595839562240513, 6315533.02503), 'height': size, 'width': size, 'compress': 'lzw', 'blockxsize': windowsize, 'blockysize': windowsize, 'tiled': True } randArr = np.array([(np.random.rand(size, size) * 255).astype(np.uint8) for i in range(bands)]) with rasterio.open(output, 'w', **kwargs) as dst: dst.write(randArr)
def sample(self, y, x, height, width, **kwargs): """ Read sample of the Band to memory. The sample is defined by its size and position in the raster, without respect to the georeference. In case if the sample coordinates spread out of the image boundaries, the image is padded with nodata value. Args: x: pixel horizontal coordinate of left top corner of the sample y: pixel vertical coordinate of left top corner of the sample width: spatial dimension of sample in pixels height: spatial dimension of sample in pixels Returns: a new :obj:`BandSample` containing the specified spatial subset of the band """ coord_x = self.transform.c + x * self.transform.a coord_y = self.transform.f + y * self.transform.e dst_crs = self.crs dst_name = os.path.basename(self.name) dst_nodata = self.nodata if self.nodata is not None else 0 dst_transform = Affine(self.transform.a, self.transform.b, coord_x, self.transform.d, self.transform.e, coord_y) dst_raster = self._band.read(window=((y, y + height), (x, x + width)), boundless=True, fill_value=dst_nodata) sample = BandSample(dst_name, dst_raster, dst_crs, dst_transform, dst_nodata) return sample
def set_raster_from_pix_bounds(self, xf_lat, xo_lon, d_lat, d_lon, n_lat, n_lon, crs=DEF_CRS): """ Set raster metadata (meta attribute) from pixel border data Parameters: xf_lat (float): upper latitude (top) xo_lon (float): left longitude d_lat (float): latitude step d_lon (float): longitude step n_lat (int): number of latitude points n_lon (int): number of longitude points crs (dict() or rasterio.crs.CRS, optional): CRS. Default: DEF_CRS """ self.__init__() self.meta = { 'dtype': 'float32', 'width': n_lon, 'height': n_lat, 'crs': crs, 'transform': Affine(d_lon, 0.0, xo_lon, 0.0, d_lat, xf_lat) }
def read_hdf5(self, file_data): """Read centroids attributes from hdf5. Parameters: file_data (str or h5): if string, path to read data. if h5 object, the datasets will be read from there """ if isinstance(file_data, str): LOGGER.info('Reading %s', file_data) data = h5py.File(file_data, 'r') else: data = file_data self.clear() crs = DEF_CRS if data.get('crs'): crs = ast.literal_eval(data.get('crs')[0]) if data.get('lat') and data.get('lat').size: self.set_lat_lon(np.array(data.get('lat')), np.array(data.get('lon')), crs) elif data.get('latitude') and data.get('latitude').size: self.set_lat_lon(np.array(data.get('latitude')), np.array(data.get('longitude')), crs) else: centr_meta = data.get('meta') self.meta['crs'] = crs for key, value in centr_meta.items(): if key != 'transform': self.meta[key] = value[0] else: self.meta[key] = Affine(*value) for centr_name in data.keys(): if centr_name not in ('crs', 'lat', 'lon', 'meta'): setattr(self, centr_name, np.array(data.get(centr_name))) if isinstance(file_data, str): data.close()
def setUp(self): self.arr = np.array([[4, 4, 3, 2], [4, 4, 1, 1], [1, 4, 0, 2]], dtype='uint8').reshape(3, 4, 1) self.masked_filled = np.array( [[4, 4, 0, 0], [4, 4, 0, 0], [0, 4, 0, 0]], dtype='uint8').reshape(3, 4, 1) self.arr4ch = np.array([[[4, 4, 3, 2], [4, 4, 1, 1], [1, 4, 0, 2]], [[4, 4, 3, 2], [4, 4, 1, 1], [1, 4, 0, 2]]], dtype='uint8') self.masked_filled4ch = np.array( [[[4, 4, 0, 0], [4, 4, 0, 0], [0, 4, 0, 0]], [[4, 4, 0, 0], [4, 4, 0, 0], [0, 4, 0, 0]]], dtype='uint8') self.meta = { 'driver': 'GTiff', 'dtype': 'uint8', 'nodata': None, 'width': 4, 'height': 3, 'count': 1, 'crs': CRS.from_epsg(32737), 'transform': Affine(10.0, 0.0, 199980.0, 0.0, -10.0, 9300040.0) }
def rio_resample(srcpath, outpath, res_factor = 15): with rio.open(srcpath) as src: arr = src.read() newarr = np.empty(shape=(arr.shape[0], int(arr.shape[1] * res_factor), int(arr.shape[2] * res_factor))) # adjust the new affine transform to the 150% smaller cell size aff = src.transform newaff = Affine(aff.a / res_factor, aff.b, aff.c, aff.d, aff.e /res_factor, aff.f) kwargs = src.meta.copy() #kwargs['transform'] = newaff #kwargs['affine'] = newaff kwargs.update({ 'crs': src.crs, 'transform': newaff, 'affine': newaff, 'width': int(arr.shape[2] * res_factor), 'height': int(arr.shape[1] * res_factor) }) with rio.open(outpath, 'w', **kwargs) as dst: reproject( arr, newarr, src_transform = aff, dst_transform = newaff, src_crs = src.crs, dst_crs = src.crs, resample = Resampling.bilinear) dst.write(newarr[0].astype(rio.float32), indexes=1)
def __mask_to_polygons(mask): """[summary] Args: mask ([type]): [description] Returns: [type]: [description] """ # XXX: maybe this should be merged with __mask_to_polys() defined above import numpy as np from rasterio import features, Affine from shapely import geometry all_polygons = [] for shape, value in features.shapes(mask.astype(np.int16), mask=(mask > 0), transform=Affine(1.0, 0, 0, 0, 1.0, 0)): all_polygons.append(geometry.shape(shape)) all_polygons = geometry.MultiPolygon(all_polygons) if not all_polygons.is_valid: all_polygons = all_polygons.buffer(0) # Sometimes buffer() converts a simple Multipolygon to just a Polygon, # need to keep it a Multi throughout if all_polygons.type == 'Polygon': all_polygons = geometry.MultiPolygon([all_polygons]) return all_polygons
def increase_resolution(raster_file_path: str, factor_increase: int): """ References: * mapbox.github.io/rasterio/topics/resampling.html#use-decimated-reads :param raster_file_path: :param factor_increase: :return: """ # this method need a integer factor resolution res = int(factor_increase) # alias with rasterio.open(raster_file_path) as src: image = src.read() image_new = np.empty( shape=( image.shape[0], # same number of bands round(image.shape[1] * res), # n times resolution round(image.shape[2] * res)), # n times resolution dtype=image.dtype) image = src.read(out=image_new).copy() meta = dict(src.profile) aff = copy(meta['affine']) meta['transform'] = Affine(aff.a / res, aff.b, aff.c, aff.d, aff.e / res, aff.f) meta['affine'] = meta['transform'] meta['width'] *= res meta['height'] *= res with rasterio.open(raster_file_path, "w", **meta) as dst: dst.write(image)
def rescale_transform(src_transform, src_width, src_height, scale): """Calculate the transform corresponding to a pixel size multiplied by a given scale factor. Parameters ---------- src_transform : Affine Source affine transform. src_width : int Source raster width. src_height : int Source raster height. scale : float Scale factor (e.g. 0.5 to reduce pixel size by half). Returns ------- dst_transform : Affine New affine transform. dst_width : int New raster width. dst_height : int New raster height. """ dst_transform = Affine(src_transform.a * scale, src_transform.b, src_transform.c, src_transform.d, src_transform.e * scale, src_transform.f) dst_width = int(src_width / scale) dst_height = int(src_height / scale) return dst_transform, dst_width, dst_height
def resample_meta(solar_zenith, solar_azimuth,meta_name, index): """ Resamples Solar Zenith and solar azimuth angle from 5x5 km to 10 m Grid (nearest neighbor) and writes into GeoTIFF Parameters ---------- solar_zenith: np.array float64 data in 5km x 5 km grid solar_azimuth: np.array float64 data in 5 km x 5 km grid meta_name: str Name of .xml file containing metadata index: int number of current tile (just used for naming convention) Returns ------- None """ reference_tile = glob.glob(os.path.join(meta_name[:-10],'IMG_DATA','*_B02.jp2'))[0] # Open 10 m resolution tile to read size and dimension of final tile: with rasterio.open(reference_tile) as src: out_meta = src.meta.copy() newarr = src.read() newarr = np.squeeze(newarr) newarr = newarr.astype(float) new_transform = src.transform old_transform = Affine(new_transform.a * 500, new_transform.b, new_transform.c, new_transform.d, new_transform.e * 500, new_transform.f) out_meta['dtype'] = 'float64' out_meta['driver'] = "GTiff" angles = [solar_zenith, solar_azimuth] angles_str = ["solar_zenith.tif", "solar_azimuth.tif"] id = 0 if not os.path.exists(os.path.join(cfg.PATHS['working_dir'], 'cache', str(cfg.PARAMS['date'][0]), 'meta')): os.makedirs(os.path.join(cfg.PATHS['working_dir'], 'cache', str(cfg.PARAMS['date'][0]), 'meta')) for angle in angles: with rasterio.open(os.path.join(cfg.PATHS['working_dir'], 'cache', str(cfg.PARAMS['date'][0]), 'meta', str(index)+angles_str[id]), "w", **out_meta) \ as dest: reproject( source=angle, destination=newarr, src_transform=old_transform, dst_transform=src.transform, src_crs=src.crs, dst_crs=src.crs, resampling=Resampling.nearest) dest.write(newarr, indexes=1) id = id + 1
def test_transform_raster_pass(self): meta, inten_ras = read_raster(HAZ_DEMO_FL, transform=Affine(0.009000000000000341, 0.0, -69.33714959699981, 0.0, -0.009000000000000341, 10.42822096697894), height=500, width=501) left = meta['transform'].xoff top = meta['transform'].yoff bottom = top + meta['transform'][4] * meta['height'] right = left + meta['transform'][0] * meta['width'] self.assertAlmostEqual(left, -69.33714959699981) self.assertAlmostEqual(bottom, 5.928220966978939) self.assertAlmostEqual(right, -64.82814959699981) self.assertAlmostEqual(top, 10.42822096697894) self.assertEqual(meta['width'], 501) self.assertEqual(meta['height'], 500) self.assertEqual(meta['crs'].to_epsg(), 4326) self.assertEqual(inten_ras.shape, (1, 500 * 501)) meta, inten_all = read_raster(HAZ_DEMO_FL, window=Window(0, 0, 501, 500)) self.assertTrue(np.array_equal(inten_all, inten_ras))
def make_affine(height, width, ul, lr): """ Create an affine for a tile of a given size """ xCell = (ul[0] - lr[0]) / width yCell = (ul[1] - lr[1]) / height return Affine(-xCell, 0.0, ul[0], 0.0, -yCell, ul[1])
def makehappytiff(dst_path, seams_path): kwargs = { 'blockxsize': 256, 'blockysize': 256, 'compress': 'lzw', 'count': 4, 'crs': { 'init': u'epsg:3857' }, 'driver': u'GTiff', 'dtype': 'uint8', 'height': 1065, 'nodata': None, 'tiled': True, 'transform': Affine(4.595839562240513, 0.0, -13550756.3744, 0.0, -4.595839562240513, 6315533.02503), 'width': 1065 } imsize = 1065 testdata = [(np.random.rand(imsize, imsize) * 255).astype(np.uint8) for i in range(4)] for i in range(4): testdata[i][0:100, :] = 0 testdata[i][:, 900:] = 0 with rio.open(dst_path, 'w', **kwargs) as dst: for i, arr in enumerate(testdata, 1): dst.write(arr, i) if seams_path: frto = np.sort(np.random.rand(2) * imsize).astype(int) rInds = np.arange(frto[0], frto[1], (frto[1] - frto[0]) / float(imsize)).astype(int) inds = np.arange(imsize) for i in range(4): testdata[i][rInds, inds] = 0 testdata[i][rInds - 1, inds] = 0 testdata[i][rInds + 1, inds] = 0 testdata[i][inds, rInds] = 0 testdata[i][inds, rInds - 1] = 0 testdata[i][inds, rInds + 1] = 0 with rio.open(seams_path, 'w', **kwargs) as dst: for i, arr in enumerate(testdata, 1): dst.write(arr, i)
def rowcol_to_latlon(row, col, res=250): row = np.asarray(row) if type(row) is list else row col = np.asarray(col) if type(col) is list else col x, y = xy(Affine(*albers_conus_transform(res)), row, col) p1 = Proj(CRS.from_wkt(albers_conus_crs())) p2 = Proj(proj='latlong', datum='WGS84') lon, lat = transform(p1, p2, x, y) return lat, lon
def test_bounds_from_transform(): transform = Affine(300, 0, 101985, 0, -300, 2826915) width, height = 791, 718 bounds = utils.bounds_from_transform(transform, width, height) assert bounds.left == 101985 assert bounds.bottom == 2611515 assert bounds.right == 339285 assert bounds.top == 2826915
def reproj_ras(size, epsg, data_folder, extens, fname, method): print("get glob for BVI") file_search = os.path.join(data_folder, extens) rasters = glob.glob(file_search, recursive=True) for data in rasters: grid = data[(len(data_folder) + 1):(len(data_folder) + 3)] # print(grid) print("resampling {0}".format(grid)) src = rasterio.open(data) arr = src.read() newarr = np.empty( shape=( arr.shape[0], # same number of bands round(arr.shape[1] * size), # round(arr.shape[2] * size)), dtype="float32") # adjust the new affine transform to the 150% smaller cell size aff = src.transform newaff = Affine(aff.a / size, aff.b, aff.c, aff.d, aff.e / size, aff.f) if method == "Q3": reproject(arr, newarr, src_transform=aff, dst_transform=newaff, src_crs=src.crs, dst_crs=src.crs, resampling=Resampling.q3) else: reproject(arr, newarr, src_transform=aff, dst_transform=newaff, src_crs=src.crs, dst_crs=src.crs, resampling=Resampling.average) out_meta = src.meta.copy() out_meta.update({ "driver": "GTiff", "height": newarr.shape[1], "width": newarr.shape[2], "transform": newaff, "crs": CRS.from_epsg(epsg), "compress": "lzw", "dtype": "float32" }) re_out_ras = os.path.join(data_folder, grid, grid + "_" + fname) print(re_out_ras) with rasterio.open(re_out_ras, "w", **out_meta) as dest: dest.write(newarr)
def makeAffine(bounds, width): xD = bounds[2] - bounds[0] yD = bounds[3] - bounds[1] cS = xD / float(width - 2) height = int(yD / cS) + 1 return Affine(cS, 0.00, bounds[0] - cS, 0.00, -cS, bounds[3] + cS), height + 1
def resample_raster(infile, outfile, gridx, gridy, driver='GTiff', null = -999): """ A function for resampling a raster onto a regular grid with the same crs :param infile: input raster path :param outfile: output raster path :param gridx: numpy array of grid x coordinates :param gridy: numpy array of grid y coordinates :param driver: rasterio driver :param null: value to be replaced by null in the grid """ # Open src = rasterio.open(infile) # Extract data as an array arr = src.read()[0] # Get the affine aff = src.transform # Define the affine for the kriged dataset newaff = Affine(gridx[1] - gridx[0], 0, np.min(gridx), 0, gridy[1] - gridy[0], np.max(gridy)) # Create new array with the grid # coordinates from the kriging newarr = np.empty(shape=(gridy.shape[0], gridx.shape[0])) # Reproject reproject( arr, newarr, src_transform=aff, dst_transform=newaff, src_crs=src.crs, dst_crs=src.crs, resampling=Resampling.bilinear) src.close() # Do some post processing newarr[np.abs(newarr - null) < 0.0001] = np.nan src.close() # Create a new dataset new_dataset = rasterio.open(outfile, 'w', driver=driver, height=newarr.shape[0], width=newarr.shape[1], count=1, dtype=newarr.dtype, crs=src.crs, transform=newaff) new_dataset.write(newarr, 1) new_dataset.close()
def resample_band(dataset: rio.io.DatasetReader, target_resolution: float, resampling_method: Resampling, resampler: str) -> dict: """Resample a Band (2D NDArray) :param dataset: Input dataset :param target_resolution: Resolution of the output dataset: what you want to resample to :param resampling_method: Which method to use for resampling (only applicable to rasterio!) :param resampler: Which resampling function to use (e.g. Rasterio vs SciPy zoom) :return: Dictionary containing resampled data ("data") and the resampled profile ("profile") """ # Calculate scale factor scaling = int(dataset.res[0]) / float(target_resolution) # Calculate profile and transfor elements profile = copy.deepcopy(dataset.profile) trans = copy.deepcopy(dataset.transform) transform = Affine(trans.a / scaling, trans.b, trans.c, trans.d, trans.e / scaling, trans.f) height = copy.deepcopy(dataset.height) * scaling width = copy.deepcopy(dataset.width) * scaling profile.update( res=(float(target_resolution), float(target_resolution)), transform=transform, height=height, width=width ) # Resample data to target resolution if resampler is "rasterio": print("[INFO] Using Rasterio resampler...") resampled = dataset.read( out_shape=( dataset.count, int(height), int(width) ), resampling=resampling_method ) else: print("[INFO] Using scipy zoom resampler...") print("[WARNING] Zoom resampler does not honor resampling methods! Use the Rasterio resampler for this!") raw_read = dataset.read() resampled = np.array(list(map( lambda layer: zoom(layer, scaling, order=0, mode='nearest'), raw_read ))) # Create output dictionary output = { "data": resampled, "profile": profile } return output
def __init__(self, name, raster, crs, transform, nodata=0): super().__init__() self._name = name self._raster = band_shape_guard(raster) self._nodata = nodata self._transform = Affine( *transform) if not isinstance(transform, Affine) else transform self._crs = CRS(init=crs) if not isinstance(crs, CRS) else crs