def test_warp_from_to_file(tmpdir): """File to file""" tiffname = str(tmpdir.join('foo.tif')) with rasterio.open('rasterio/tests/data/RGB.byte.tif') as src: dst_transform = [-8789636.708, 300.0, 0.0, 2943560.235, 0.0, -300.0] dst_crs = dict( proj='merc', a=6378137, b=6378137, lat_ts=0.0, lon_0=0.0, x_0=0.0, y_0=0, k=1.0, units='m', nadgrids='@null', wktext=True, no_defs=True) kwargs = src.meta.copy() kwargs.update( transform=dst_transform, crs=dst_crs) with rasterio.open(tiffname, 'w', **kwargs) as dst: for i in (1, 2, 3): reproject(rasterio.band(src, i), rasterio.band(dst, i))
def test_warp_from_to_file_multi(tmpdir): """File to file""" tiffname = str(tmpdir.join('foo.tif')) with rasterio.open('tests/data/RGB.byte.tif') as src: dst_crs = dict( proj='merc', a=6378137, b=6378137, lat_ts=0.0, lon_0=0.0, x_0=0.0, y_0=0, k=1.0, units='m', nadgrids='@null', wktext=True, no_defs=True) kwargs = src.meta.copy() kwargs.update( transform=DST_TRANSFORM, crs=dst_crs) with rasterio.open(tiffname, 'w', **kwargs) as dst: for i in (1, 2, 3): reproject( rasterio.band(src, i), rasterio.band(dst, i), num_threads=2)
def reproject_dataset(geotiff_path): """Project a GeoTIFF to the WGS84 coordinate reference system. See https://mapbox.github.io/rasterio/topics/reproject.html""" # We want to project the GeoTIFF coordinate reference system (crs) # to WGS84 (e.g. into the familiar Lat/Lon pairs). WGS84 is analogous # to EPSG:4326 dst_crs = 'EPSG:4326' with rasterio.open(geotiff_path) as src: transform, width, height = rasterio.warp.calculate_default_transform( src.crs, dst_crs, src.width, src.height, *src.bounds) kwargs = src.meta.copy() kwargs.update({ 'crs': dst_crs, 'transform': transform, 'width': width, 'height': height }) satellite_img_name = get_file_name(geotiff_path) out_file_name = "{}_wgs84.tif".format(satellite_img_name) out_path = os.path.join(WGS84_DIR, out_file_name) with rasterio.open(out_path, 'w', **kwargs) as dst: for i in range(1, src.count + 1): rasterio.warp.reproject( source=rasterio.band(src, i), destination=rasterio.band(dst, i), src_transform=src.transform, src_crs=src.crs, dst_transform=transform, dst_crs=dst_crs, resampling=rasterio.warp.Resampling.nearest) return rasterio.open(out_path), out_path
def warp_tif(combined_tif_path, warped_tif_path, dst_crs={ 'init': 'EPSG:3857' }): logger.info('Warping tif to web mercator: %s', combined_tif_path) with rasterio.open(combined_tif_path) as src: meta = src.meta new_meta = meta.copy() transform, width, height = calculate_default_transform( src.crs, dst_crs, src.width, src.height, *src.bounds) new_meta.update({ 'crs': dst_crs, 'transform': transform, 'width': width, 'height': height, 'nodata': -28762 }) with rasterio.open( warped_tif_path, 'w', compress='DEFLATE', tiled=True, **new_meta) as dst: for i in range(1, src.count): reproject( source=rasterio.band(src, i), destination=rasterio.band(dst, i), src_transform=src.transform, src_crs=src.crs, dst_transform=transform, dst_crs=dst_crs, resampling=Resampling.nearest, src_nodata=-28762 )
def get_bands(inputs, d, i=None): """Get a rasterio.Band object from calc's inputs""" path = inputs[d] if d in dict(inputs) else inputs[int(d)-1][1] if i: return rasterio.band(rasterio.open(path), i) else: src = rasterio.open(path) return [rasterio.band(src, i) for i in src.indexes]
def reproject(self, destination_file, source_file=None, resampling=RESAMPLING.nearest, **kwargs): """ Reprojects the pixels of a source raster map to a destination raster, with a different reference coordinate system and Affine transform. It uses `Rasterio <https://github.com/mapbox/rasterio/blob/master/docs/reproject.rst>`_ calculate_default_transform() to calculate parameters such as the resolution (if not provided), and the destination transform and dimensions. param string source_file: Full path to the source file containing a raster map param string destination_file: Full path to the destination file containing a raster map :param int resampling: Resampling method to use. Can be one of the following: ``Resampling.nearest``, ``Resampling.bilinear``, \ ``Resampling.cubic``, ``Resampling.cubic_spline``, ``Resampling.lanczos``, ``Resampling.average``, ``Resampling.mode``. :param dict kwargs: Optional additional arguments passed to the method, to parametrize the reprojection. \ For example: :attr:`dst_crs` for the target coordinate reference system, :attr:`resolution` for the target resolution, \ in units of target coordinate reference system. """ if not source_file: if not self.file_path: raise AttributeError("Please provide a source_file to load the data from.") else: source_file = self.file_path with rasterio.open(source_file) as src: affine, width, height = calculate_default_transform(src_crs=src.crs, dst_crs=kwargs.get('dst_crs', src.crs), width=kwargs.get('width', src.width), height=kwargs.get('height', src.height), left=kwargs.get('left', src.bounds.left), bottom=kwargs.get('bottom', src.bounds.bottom), right=kwargs.get('right', src.bounds.right), top=kwargs.get('top', src.bounds.top), resolution=kwargs.get('resolution', src.res) ) logger.info("Calculated default transformation:") logger.info("Affine:\n{0} \n width={1}, height={2}".format(affine, width, height)) kwargs = src.meta.copy() kwargs.update({'transform': affine, 'affine': affine, 'width': width, 'height': height }) with rasterio.open(destination_file, 'w', **kwargs) as dst: for i in range(1, src.count + 1): rasterio.warp.reproject(source=rasterio.band(src, i), destination=rasterio.band(dst, i), src_transform=src.affine, src_crs=src.crs, dst_transform=affine, dst_crs=kwargs.get('dst_crs', src.crs), resampling=resampling ) logger.info("Reprojected data in %s " % destination_file)
def __reproject(self, in_raster, out_raster, affine, new_crs): for k in range(1, in_raster.count + 1): reproject( source=rasterio.band(in_raster, k), destination=rasterio.band(out_raster, k), src_transform=affine, src_crs=in_raster.crs, dst_transform=affine, dst_crs=new_crs, resampling=RESAMPLING.nearest) return out_raster
def test_reproject_no_init_nodata_tofile(tmpdir): """Test that nodata is not being initialized.""" params = default_reproject_params() tiffname = str(tmpdir.join('foo.tif')) source1 = np.zeros((params.width, params.height), dtype=np.uint8) source2 = source1.copy() # fill both sources w/ arbitrary values rows, cols = source1.shape source1[:rows // 2, :cols // 2] = 200 source2[rows // 2:, cols // 2:] = 100 kwargs = { 'count': 1, 'width': params.width, 'height': params.height, 'dtype': np.uint8, 'driver': 'GTiff', 'crs': params.dst_crs, 'transform': params.dst_transform } with rasterio.open(tiffname, 'w', **kwargs) as dst: reproject( source1, rasterio.band(dst, 1), src_transform=params.src_transform, src_crs=params.src_crs, src_nodata=0.0, dst_transform=params.dst_transform, dst_crs=params.dst_crs, dst_nodata=0.0 ) reproject( source2, rasterio.band(dst, 1), src_transform=params.src_transform, src_crs=params.src_crs, src_nodata=0.0, dst_transform=params.dst_transform, dst_crs=params.dst_crs, dst_nodata=0.0, init_dest_nodata=False ) # 200s should remain along with 100s with rasterio.open(tiffname) as src: data = src.read() assert data.max() == 200
def test_reproject_no_init_nodata_tofile(tmpdir): """Test that nodata is not being initialized.""" params = default_reproject_params() tiffname = str(tmpdir.join("foo.tif")) source1 = np.zeros((params.width, params.height), dtype=np.uint8) source2 = source1.copy() # fill both sources w/ arbitrary values rows, cols = source1.shape source1[:rows // 2, :cols // 2] = 200 source2[rows // 2:, cols // 2:] = 100 kwargs = { "count": 1, "width": params.width, "height": params.height, "dtype": np.uint8, "driver": "GTiff", "crs": params.dst_crs, "transform": params.dst_transform, } with rasterio.open(tiffname, "w", **kwargs) as dst: reproject( source1, rasterio.band(dst, 1), src_transform=params.src_transform, src_crs=params.src_crs, src_nodata=0.0, dst_transform=params.dst_transform, dst_crs=params.dst_crs, dst_nodata=0.0, ) reproject( source2, rasterio.band(dst, 1), src_transform=params.src_transform, src_crs=params.src_crs, src_nodata=0.0, dst_transform=params.dst_transform, dst_crs=params.dst_crs, dst_nodata=0.0, init_dest_nodata=False, ) # 200s should remain along with 100s with rasterio.open(tiffname) as src: data = src.read() assert data.max() == 200
def test_band(): with rasterio.open('tests/data/RGB.byte.tif') as src: b = rasterio.band(src, 1) assert b.ds == src assert b.bidx == 1 assert b.dtype in src.dtypes assert b.shape == src.shape
def test_warp_from_file(): """File to ndarray""" with rasterio.open('rasterio/tests/data/RGB.byte.tif') as src: dst_transform = [-8789636.708, 300.0, 0.0, 2943560.235, 0.0, -300.0] dst_crs = dict( proj='merc', a=6378137, b=6378137, lat_ts=0.0, lon_0=0.0, x_0=0.0, y_0=0, k=1.0, units='m', nadgrids='@null', wktext=True, no_defs=True) destin = numpy.empty(src.shape, dtype=numpy.uint8) reproject( rasterio.band(src, 1), destin, dst_transform=dst_transform, dst_crs=dst_crs) assert destin.any() try: import matplotlib.pyplot as plt plt.imshow(destin) plt.gray() plt.savefig('test_warp_from_filereproject.png') except: pass
def process_tile(tile): """Process a single MBTiles tile.""" global base_kwds, src # Get the bounds of the tile. ulx, uly = mercantile.xy(*mercantile.ul(tile.x, tile.y, tile.z)) lrx, lry = mercantile.xy(*mercantile.ul(tile.x + 1, tile.y + 1, tile.z)) kwds = base_kwds.copy() kwds["transform"] = from_bounds(ulx, lry, lrx, uly, 256, 256) with rasterio.open("/vsimem/tileimg", "w", **kwds) as tmp: # Reproject the src dataset into image tile. for bidx in tmp.indexes: reproject(rasterio.band(src, bidx), rasterio.band(tmp, bidx)) # Get contents of the virtual file. contents = bytearray(virtual_file_to_buffer("/vsimem/tileimg")) return tile, contents
def test_shapes_band_shortcut(): """Access to shapes of labeled features""" with rasterio.drivers(): with rasterio.open('rasterio/tests/data/shade.tif') as src: shapes = ftrz.shapes(rasterio.band(src, 1)) shape, val = next(shapes) assert shape['type'] == 'Polygon' assert len(shape['coordinates']) == 1 assert val == 255
def process_chunk(tile, input, creation_options, resampling): """Process a single tile.""" from rasterio.warp import RESAMPLING input = input.replace("s3://", "/vsicurl/http://s3.amazonaws.com/") print("Chunking initial image for", tile) # Get the bounds of the tile. ulx, uly = mercantile.xy( *mercantile.ul(tile.x, tile.y, tile.z)) lrx, lry = mercantile.xy( *mercantile.ul(tile.x + 1, tile.y + 1, tile.z)) tmp_path = "/vsimem/tile" with rasterio.drivers(): with rasterio.open(input, "r") as src: meta = src.meta.copy() meta.update(creation_options) meta["height"] = CHUNK_SIZE meta["width"] = CHUNK_SIZE meta["transform"] = from_bounds(ulx, lry, lrx, uly, CHUNK_SIZE, CHUNK_SIZE) # write to a tmp file to allow GDAL to handle the transform with rasterio.open(tmp_path, "w", **meta) as tmp: # Reproject the src dataset into image tile. for bidx in src.indexes: reproject( source=rasterio.band(src, bidx), destination=rasterio.band(tmp, bidx), resampling=getattr(RESAMPLING, resampling), num_threads=multiprocessing.cpu_count(), ) # check for chunks containing only NODATA data = tmp.read(masked=True) if data.mask.all(): return # TODO hard-coded for the first band return (tile, data[0])
def test_shapes_band_shortcut(): """Test rasterio bands as input to shapes""" with rasterio.drivers(): with rasterio.open('tests/data/shade.tif') as src: shapes = ftrz.shapes(rasterio.band(src, 1)) shape, val = next(shapes) assert shape['type'] == 'Polygon' assert len(shape['coordinates']) == 1 assert val == 255
def test_shapes_band(pixelated_image, pixelated_image_file): """Shapes from a band should match shapes from an array.""" truth = list(shapes(pixelated_image)) with rasterio.open(pixelated_image_file) as src: band = rasterio.band(src, 1) assert truth == list(shapes(band)) # Mask band should function, but will mask out some results assert truth[0] == list(shapes(band, mask=band))[0]
def process_chunk_task(task): """ Chunks the image into tile_dim x tile_dim tiles, and saves them to the target folder (s3 or local) Returns the extent of the output raster. """ creation_options = { "driver": "GTiff", "crs": "EPSG:3857", "tiled": True, "compress": "deflate", "predictor": 2, # 3 for floats, 2 otherwise "sparse_ok": True } with rasterio.open(task.source_uri, "r") as src: meta = src.meta.copy() meta.update(creation_options) meta.update(task.target_meta) cols = meta["width"] rows = meta["height"] tmp_path = "/vsimem/" + get_filename(task.target) with rasterio.open(tmp_path, "w", **meta) as tmp: # Reproject the src dataset into image tile. warped = [] for bidx in src.indexes: source = rasterio.band(src, bidx) warped.append(numpy.zeros((cols, rows), dtype=meta['dtype'])) warp.reproject( source=source, src_nodata=0, destination=warped[bidx - 1], dst_transform=meta["transform"], dst_crs=meta["crs"], # resampling=RESAMPLING.bilinear ) # check for chunks containing only zero values if not any(map(lambda b: b.any(), warped)): return False # write out our warped data to the vsimem raster for bidx in src.indexes: tmp.write_band(bidx, warped[bidx - 1]) contents = bytearray(virtual_file_to_buffer(tmp_path)) write_bytes_to_target(task.target, contents) return True
def project_raster(src_raster, dst_raster, dst_crs): """Reproject a raster from one coordinate system to another using Rasterio code from: https://github.com/mapbox/rasterio/blob/master/docs/reproject.rst Parameters ---------- src_raster : str Filename of source raster. dst_raster : str Filename of reprojected (destination) raster. dst_crs : str Coordinate system of reprojected raster. Examples: 'EPSG:26715' """ try: import rasterio from rasterio.warp import calculate_default_transform, reproject, RESAMPLING except: print('This function requires rasterio.') with rasterio.open(src_raster) as src: affine, width, height = calculate_default_transform( src.crs, dst_crs, src.width, src.height, *src.bounds) kwargs = src.meta.copy() kwargs.update({ 'crs': dst_crs, 'transform': affine, 'affine': affine, 'width': width, 'height': height }) with rasterio.open(dst_raster, 'w', **kwargs) as dst: for i in range(1, src.count + 1): reproject( source=rasterio.band(src, i), destination=rasterio.band(dst, i), src_transform=src.affine, src_crs=src.crs, dst_transform=affine, dst_crs=dst_crs, resampling=RESAMPLING.nearest)
def project2wgs(gtiff, output): with rio.Env(): with rio.open(gtiff) as src: out_kwargs = src.meta.copy() out_kwargs['driver'] = 'GTiff' print(out_kwargs) res = (0.01, 0.01) dst_crs = crs.from_string('+units=m +init=epsg:4326') #dst_width, dst_height = src.width, src.height xmin, ymin, xmax, ymax = [-127.8294048826629989,5.1830409679864857, -59.0561278820333229,49.9999999955067977] dst_transform = Affine(res[0], 0, xmin, 0, -res[1], ymax) dst_width = max(int(ceil((xmax - xmin) / res[0])), 1) dst_height = max(int(ceil((ymax - ymin) / res[1])), 1) print(dst_transform) out_kwargs.update({ 'crs': dst_crs, 'transform': dst_transform, 'affine': dst_transform, 'width': dst_width, 'height': dst_height }) print(out_kwargs) with rio.open(output, 'w', **out_kwargs) as dst: reproject( source=rio.band(src, 1), destination=rio.band(dst, 1), src_transform=src.affine, src_crs=src.crs, src_nodata=src.nodata, dst_transform=out_kwargs['transform'], dst_crs=out_kwargs['crs'], dst_nodata=src.nodata, resampling=0, num_threads=2)
def run(input_file, out_file, dst_crs): try: print("Starting proccess...") createOutFolder(out_file) with rasterio.open(input_file) as src: affine, width, height = calculate_default_transform( src.crs, dst_crs, src.width, src.height,*src.bounds) kwargs = src.meta.copy() kwargs.update({ 'crs': dst_crs, 'transform': affine, 'affine': affine, 'width': width, 'height': height, 'compress': 'lzw', 'nodata': 0 }) with rasterio.open(out_file, 'w', **kwargs) as dst: reproject( source=rasterio.band(src, 1), destination=rasterio.band(dst, 1), src_transform=src.affine, src_crs=src.crs, dst_transform=affine, dst_crs=dst_crs, resampling=RESAMPLING.nearest) for i in dst.indexes: band_dst = dst.read(i) / 100 dst.write_band(i, band_dst) print("Successfully finished proccess!") except Exception as error: print("Error creating out folder: {}".format(error))
def ConvertRaster2LatLong(InputRasterFile,OutputRasterFile): """ Convert a raster to lat long WGS1984 EPSG:4326 coordinates for global plotting MDH """ # import modules import rasterio from rasterio.warp import reproject, calculate_default_transform as cdt, Resampling # read the source raster with rasterio.open(InputRasterFile) as src: #get input coordinate system Input_CRS = src.crs # define the output coordinate system Output_CRS = {'init': "epsg:4326"} # set up the transform Affine, Width, Height = cdt(Input_CRS,Output_CRS,src.width,src.height,*src.bounds) kwargs = src.meta.copy() kwargs.update({ 'crs': Output_CRS, 'transform': Affine, 'affine': Affine, 'width': Width, 'height': Height }) with rasterio.open(OutputRasterFile, 'w', **kwargs) as dst: for i in range(1, src.count+1): reproject( source=rasterio.band(src, i), destination=rasterio.band(dst, i), src_transform=src.affine, src_crs=src.crs, dst_transform=Affine, dst_crs=Output_CRS, resampling=Resampling.bilinear)
def test_issue1056(): """Warp sucessfully from RGB's upper bands to an array""" with rasterio.open('tests/data/RGB.byte.tif') as src: dst_crs = {'init': 'EPSG:3857'} out = np.zeros(src.shape, dtype=np.uint8) reproject( rasterio.band(src, 2), out, src_transform=src.transform, src_crs=src.crs, dst_transform=DST_TRANSFORM, dst_crs=dst_crs, resampling=Resampling.nearest)
def test_sieve_band(pixelated_image, pixelated_image_file): """Sieving a band from a raster file should match sieve of array.""" truth = sieve(pixelated_image, 9) with rasterio.open(pixelated_image_file) as src: band = rasterio.band(src, 1) assert np.array_equal(truth, sieve(band, 9)) # Mask band should also work but will be a no-op assert np.array_equal( pixelated_image, sieve(band, 9, mask=band) )
def test_warp_from_to_file(tmpdir): """File to file.""" tiffname = str(tmpdir.join("foo.tif")) with rasterio.open("tests/data/RGB.byte.tif") as src: dst_crs = dict( proj="merc", a=6378137, b=6378137, lat_ts=0.0, lon_0=0.0, x_0=0.0, y_0=0, k=1.0, units="m", nadgrids="@null", wktext=True, no_defs=True, ) kwargs = src.meta.copy() kwargs.update(transform=DST_TRANSFORM, crs=dst_crs) with rasterio.open(tiffname, "w", **kwargs) as dst: for i in (1, 2, 3): reproject(rasterio.band(src, i), rasterio.band(dst, i))
def test_issue1401(): """The warp_mem_limit keyword argument is in effect""" with rasterio.open('tests/data/RGB.byte.tif') as src: dst_crs = {'init': 'EPSG:3857'} out = np.zeros(src.shape, dtype=np.uint8) reproject( rasterio.band(src, 2), out, src_transform=src.transform, src_crs=src.crs, dst_transform=DST_TRANSFORM, dst_crs=dst_crs, resampling=Resampling.nearest, warp_mem_limit=4000)
def test_warp_from_to_file_multi(tmpdir): """File to file""" tiffname = str(tmpdir.join("foo.tif")) with rasterio.open("tests/data/RGB.byte.tif") as src: dst_transform = affine.Affine.from_gdal(-8789636.708, 300.0, 0.0, 2943560.235, 0.0, -300.0) dst_crs = dict( proj="merc", a=6378137, b=6378137, lat_ts=0.0, lon_0=0.0, x_0=0.0, y_0=0, k=1.0, units="m", nadgrids="@null", wktext=True, no_defs=True, ) kwargs = src.meta.copy() kwargs.update(transform=dst_transform, crs=dst_crs) with rasterio.open(tiffname, "w", **kwargs) as dst: for i in (1, 2, 3): reproject(rasterio.band(src, i), rasterio.band(dst, i), num_threads=2)
def warp_image(infile, outfile, dst_crs="EPSG:3857", dst_driver='GTiff'): """ Use rasterio to warp an image from one projection to another :param infile: Origina raster image :param outfile: Warped raster image :param dst_crs: Output projection :param dst_driver: Output filetype driver :return: None """ with rasterio.drivers(CPL_DEBUG=False): with rasterio.open(infile) as src: res = None dst_transform, dst_width, dst_height = calculate_default_transform( src.crs, dst_crs, src.width, src.height, *src.bounds, resolution=res) out_kwargs = src.meta.copy() out_kwargs.update({ 'crs': dst_crs, 'transform': dst_transform, 'affine': dst_transform, 'width': dst_width, 'height': dst_height, 'driver': dst_driver }) with rasterio.open(outfile, 'w', **out_kwargs) as dst: for i in range(1, src.count + 1): reproject( source=rasterio.band(src, i), destination=rasterio.band(dst, i), src_transform=src.affine, src_crs=src.crs, dst_transform=out_kwargs['transform'], dst_crs=out_kwargs['crs'], resampling=RESAMPLING.nearest, num_threads=1)
def test_band(rgb_image, band_idx): band = core.Band(rgb_image, bidx=band_idx) with rasterio.open(rgb_image) as src: # Assert the properties are the same props = [(p, v) for p, v in inspect.getmembers(src, lambda x: not callable(x)) if not p.startswith('_')] for prop, value in props: assert getattr(band.src, prop) == value filter_ = (lambda x: not callable(x) and not isinstance(x, rasterio._io.RasterReader)) props = [(p, v) for p, v in inspect.getmembers(rasterio.band(src, band_idx), filter_) if not p.startswith('_')] for prop, value in props: assert getattr(band.band, prop) == value
def test_reproject_dst_alpha(path_rgb_msk_byte_tif): """Materialization of external mask succeeds""" with rasterio.open(path_rgb_msk_byte_tif) as src: nrows, ncols = src.shape dst_arr = np.zeros((src.count + 1, nrows, ncols), dtype=np.uint8) reproject( rasterio.band(src, src.indexes), dst_arr, src_transform=src.transform, src_crs=src.crs, dst_transform=DST_TRANSFORM, dst_crs={'init': 'EPSG:3857'}, dst_alpha=4) assert dst_arr[3].any()
def test_reproject_dst_alpha(path_rgb_msk_byte_tif): """Materialization of external mask succeeds""" with rasterio.open(path_rgb_msk_byte_tif) as src: nrows, ncols = src.shape dst_arr = np.zeros((src.count + 1, nrows, ncols), dtype=np.uint8) reproject( rasterio.band(src, src.indexes), dst_arr, src_transform=src.transform, src_crs=src.crs, dst_transform=DST_TRANSFORM, dst_crs={"init": "EPSG:3857"}, dst_alpha=4, ) assert dst_arr[3].any()
def test_warp_from_file(): """File to ndarray.""" with rasterio.open('tests/data/RGB.byte.tif') as src: dst_crs = dict(proj='merc', a=6378137, b=6378137, lat_ts=0.0, lon_0=0.0, x_0=0.0, y_0=0, k=1.0, units='m', nadgrids='@null', wktext=True, no_defs=True) destin = np.empty(src.shape, dtype=np.uint8) reproject(rasterio.band(src, 1), destin, dst_transform=DST_TRANSFORM, dst_crs=dst_crs) assert destin.any()
def _tile_worker(tile): """ For each tile, and given an open rasterio src, plus a`global_args` dictionary with attributes of `base_val`, `interval`, and a `writer_func`, warp a continous single band raster to a 512 x 512 mercator tile, then encode this tile into RGB. Parameters ----------- tile: list [x, y, z] indices of tile Returns -------- tile, buffer tuple with the input tile, and a bytearray with the data encoded into the format created in the `writer_func` """ x, y, z = tile bounds = [ c for i in (mercantile.xy(*mercantile.ul(x, y + 1, z)), mercantile.xy(*mercantile.ul(x + 1, y, z))) for c in i ] toaffine = transform.from_bounds(*bounds + [512, 512]) out = np.empty((512, 512), dtype=src.meta['dtype']) reproject(rasterio.band(src, 1), out, dst_transform=toaffine, dst_crs="init='epsg:3857'", resampling=RESAMPLING.bilinear) out = data_to_rgb(out, global_args['base_val'], global_args['interval']) return tile, global_args['writer_func'](out, global_args['kwargs'].copy(), toaffine)
def test_warp_from_file(): """File to ndarray.""" with rasterio.open("tests/data/RGB.byte.tif") as src: dst_crs = dict( proj="merc", a=6378137, b=6378137, lat_ts=0.0, lon_0=0.0, x_0=0.0, y_0=0, k=1.0, units="m", nadgrids="@null", wktext=True, no_defs=True, ) destin = np.empty(src.shape, dtype=np.uint8) reproject( rasterio.band(src, 1), destin, dst_transform=DST_TRANSFORM, dst_crs=dst_crs ) assert destin.any()
def test_issue1350(): """Warp bands other than 1 or All""" with rasterio.open('tests/data/RGB.byte.tif') as src: dst_crs = {'init': 'EPSG:3857'} reprojected = [] for dtype, idx in zip(src.dtypes, src.indexes): out = np.zeros((1,) + src.shape, dtype=dtype) reproject( rasterio.band(src, idx), out, resampling=Resampling.nearest, dst_transform=DST_TRANSFORM, dst_crs=dst_crs) reprojected.append(out) for i in range(1, len(reprojected)): assert not (reprojected[0] == reprojected[i]).all()
def open(self) -> Iterator[GeoRasterReader]: """Context manager which returns a :class:`BandDataSource`""" try: _LOG.debug("opening %s", self.filename) with rasterio.open(self.filename) as src: override = False transform = src.transform if transform.is_identity: override = True transform = self.get_transform(src.shape) try: crs = geometry.CRS(_rasterio_crs_wkt(src)) except ValueError: override = True crs = self.get_crs() # The [1.0a1-1.0a8] releases of rasterio had a bug that means it # cannot read multiband data into a numpy array during reprojection # We override it here to force the reading and reprojection into separate steps # TODO: Remove when we no longer care about those versions of rasterio bandnumber = self.get_bandnumber(src) band = rasterio.band(src, bandnumber) nodata = src.nodatavals[band.bidx - 1] if src.nodatavals[ band.bidx - 1] is not None else self.nodata nodata = num2numpy(nodata, band.dtype) if override: yield OverrideBandDataSource(band, nodata=nodata, crs=crs, transform=transform) else: yield BandDataSource(band, nodata=nodata) except Exception as e: _LOG.error("Error opening source dataset: %s", self.filename) raise e
def open(self): """Context manager which returns a :class:`BandDataSource`""" try: _LOG.debug("opening %s", self.filename) with rasterio.open(self.filename) as src: override = False transform = _rasterio_transform(src) if transform.is_identity: override = True transform = self.get_transform(src.shape) try: crs = geometry.CRS(_rasterio_crs_wkt(src)) except ValueError: override = True crs = self.get_crs() # The 1.0 onwards release of rasterio has a bug that means it # cannot read multiband data into a numpy array during reprojection # We override it here to force the reading and reprojection into separate steps # TODO: Remove when rasterio bug fixed bandnumber = self.get_bandnumber(src) if bandnumber > 1 and str(rasterio.__version__) >= '1.0': override = True band = rasterio.band(src, bandnumber) nodata = numpy.dtype(band.dtype).type(src.nodatavals[0] if src.nodatavals[0] is not None else self.nodata) if override: yield OverrideBandDataSource(band, nodata=nodata, crs=crs, transform=transform) else: yield BandDataSource(band, nodata=nodata) except Exception as e: _LOG.error("Error opening source dataset: %s", self.filename) raise e
def transform_raster_to_metre_projection(country_geotiff_uri: str, destination_epsg: str, reprojected_geotiff_uri: str): """ Mosaicked(or single tile) SRTM files are projected in WGS84 degrees. To be able to calculate slope, we need the raster in a local projection in metres :param country_geotiff_uri: the geotiff raster for the country :param destination_epsg: the target projection as string "EPSG:#####" :param reprojected_geotiff_uri: the raster for the country in the new projection """ with rasterio.open(country_geotiff_uri) as src: dst_transform, dst_width, dst_height = \ warp.calculate_default_transform(src.crs, destination_epsg, src.width, src.height, *src.bounds) src_data = src.read(1) src_meta = src.meta src_crs = src.crs src_transform = src.transform dst_meta = src_meta.copy() dst_meta.update(crs=destination_epsg) dst_meta.update(transform=dst_transform) dst_meta.update(width=dst_width) dst_meta.update(height=dst_height) dst_meta.update(compress='lzw') with rasterio.open(reprojected_geotiff_uri, 'w', **dst_meta) as dst: warp.reproject(source=src_data, destination=rasterio.band(dst, 1), src_transform=src_transform, src_crs=src_crs, dst_transform=dst_transform, dst_crs=destination_epsg, resampling=warp.Resampling.nearest)
def scatter(raster_path1, raster_path2, band1=1, band2=1, buckets=100): print "here2" with rasterio.open(raster_path1) as ds1: with rasterio.open(raster_path2) as ds2: print "here1" b = rasterio.band(ds1, band1) print b array1 = ds1.read(band1) band1 = ds1.read_band(band1) meta1 = ds1.meta rows = meta1['height'] cols = meta1['width'] min1 = band1.min() max1 = band1.max() array2 = ds2.read(band2) band2 = ds2.read_band(band2) min2 = band2.min() max2 = band2.max() step1 = (max1 - min1) / buckets step2 = (max2 - min2) / buckets print len(array1), len(array1[0]), len(array2),len(array1[0]) print rows, cols, min1, min2 matrix = couple_data(array1, array2, min1, min2, max1, max2, rows, cols) print "end" return matrix, min1, min2, max1, max2, step1, step2
def reproject2wgs84(src_path, dst_path): dataset = rasterio.open(src_path) dataread = dataset.read() dataread = dataread.astype('uint8') dst_crs = 'EPSG:4326' transform, width, height = calculate_default_transform( dataset.crs, dst_crs, dataset.width, dataset.height, *dataset.bounds) kwargs = dataset.profile.copy() kwargs.update({ 'crs': dst_crs, 'transform': transform, 'width': width, 'height': height, 'dtype': rasterio.uint8, }) with rasterio.open(dst_path, 'w', **kwargs) as dst: for i in range(1, dataset.count + 1): reproject(source=dataread[i - 1], destination=rasterio.band(dst, i), src_transform=dataset.transform, src_crs=dataset.crs, dst_transform=transform, dst_crs=dst_crs, resampling=Resampling.nearest)
def crop_geotiff_to_glacier(gdir, img_list, dim_name, dim_label, var_name, time_stamp, file_group): """ A function that reads Tiles in .tif format from folder for different dates and processes them to the size of the each glacier. The output is then stored in the sentinel.nc file with the dimensions of all 12 Sentinel bands with the current time stamp Structure of the function: - Reading Data from imgfolder - Cropping Data to glacier outline - Reprojecting Raster of Glacier to local grid - Resampling all bands to 10 Meter resolution - Writing local raster of all bands to multi-temporal netCDF file xxxx.nc Parameters: ----------- gdir: :py:class:`crampon.GlacierDirectory` A GlacierDirectory instance. img_list: os.listdir(img_path) list with paths of all tiles (need to have same resolution and projection) to be processed into netCDF dim_name: str dimension name for variables: e.g. height, bands, angles dim_label: list of str name of e.g. each band or each angle ['solar_azimuth','solar_zenith'], range(len(list(range(1,len(b_sub)+1)) var_name: str Name of variable: e.g. 'img_values', 'height', 'angles' time_stamp: int date in format yyyymmdd (no datetime.datetime!) file_group: str filepath in cfg.PATH, e.g. 'sentinel', 'solar_angles' Returns: -------- None """ glacier = gpd.read_file(gdir.get_filepath('outlines')) # iterate over all bands b_sub = [] band_index = 0 for band in img_list: with rasterio.open(band) as src: # Read crs from first Tile of list: if band == img_list[0]: local_crs = glacier.crs src_crs = src.crs list_conts = os.listdir(cfg.PATHS['dem_dir'])[0] # Problem with Swiss CRS, set crs manually for DEM if band == os.path.join(cfg.PATHS['dem_dir'], list_conts): src_crs = CRS.to_proj4(src.crs) # Convert outline to projection of tile (src_crs) to crop it out glacier = glacier.to_crs(src_crs) glacier.to_file( driver='ESRI Shapefile', filename=gdir.get_filepath('outlines_proj_tile')) with fiona.open(gdir.get_filepath('outlines_proj_tile'), "r") \ as glacier_reprojected: # Read local geometry features = [ feature["geometry"] for feature in glacier_reprojected ] # --- 1. Open file: CROP file to glacier outline try: out_image, out_transform = rasterio.mask.mask(src, features, crop=True) except ValueError: # Glacier not located in tile return out_meta = src.meta.copy() out_meta.update({ "driver": "GTiff", "height": out_image.shape[1], "width": out_image.shape[2], "transform": out_transform }) with rasterio.open(gdir.get_filepath('cropped_cache'),'w', **out_meta) \ as src1: src1.write(out_image) # --- 2. REPROJECT to local grid: we want to project out_image with # out_meta to local_crs of glacier # Calculate Transform dst_transform, width, height = calculate_default_transform( src_crs, local_crs, out_image.shape[1], out_image.shape[2], *src1.bounds) out_meta.update({ 'crs': local_crs, 'transform': dst_transform, 'width': width, 'height': height }) with rasterio.open(gdir.get_filepath('cropped_cache'), 'w', **out_meta) as src1: reproject(source=out_image, destination=rasterio.band(src1, 1), src_transform=src1.transform, src_crs=src_crs, dst_transform=dst_transform, dst_crs=local_crs, resampling=Resampling.nearest) # Write to geotiff in cache src1.write(out_image) # Open with xarray into DataArray band_array = xarray.open_rasterio(gdir.get_filepath('cropped_cache')) band_array = band_array.squeeze('band').drop('band') try: band_array = band_array.assign_coords(band=dim_label[band_index]) except IndexError: return band_array = band_array.expand_dims('band') # write all bands into list b_sub: b_sub.append(band_array) band_index = band_index + 1 # Merge all bands to write into netcdf file! all_bands = xr.concat(b_sub, dim=dim_name) # all_bands[dim_name] = dim_label all_bands.name = var_name all_bands = all_bands.assign_coords(time=time_stamp) all_bands = all_bands.expand_dims('time') all_bands_attrs = all_bands.attrs # check if netcdf file for this glacier already exists, create if not, append if exists if not os.path.isfile(gdir.get_filepath(file_group)): all_bands = all_bands.to_dataset(name=var_name) all_bands.attrs = all_bands_attrs all_bands.attrs['pyproj_srs'] = rasterio.crs.CRS.to_proj4(src1.crs) all_bands.to_netcdf(gdir.get_filepath(file_group), 'w', unlimited_dims={'time': True}) all_bands.close() else: # Open existing file existing = xr.open_dataset(gdir.get_filepath(file_group)) # Convert all_bands from DataArray to Dataset all_bands = all_bands.to_dataset(name=var_name) if not all_bands.time.values in existing.time.values: try: appended = xr.concat([existing, all_bands], dim='time') except MemoryError: print("Memory Error on", gdir, ". Skipping this entry") return existing.close() appended.attrs = all_bands_attrs appended.attrs['pyproj_srs'] = rasterio.crs.CRS.to_proj4(src1.crs) #Write to file appended.to_netcdf(gdir.get_filepath(file_group), 'w', unlimited_dims={'time': True}) appended.close() # shutil.move(gdir.get_filepath("sentinel_temp"), gd-ir.get_filepath(file_group)) # Remove cropped_cache.tif file: os.remove(gdir.get_filepath('cropped_cache')) os.remove(gdir.get_filepath('outlines_proj_tile'))
def crop_dem_to_glacier(gdir): """ Crop 10 Meter resolution Geotiff of DEM to glacier extent Reads DEM of entinre Area of interest , crops to individual glacier, changes projection to local crs and saves into netCDF file for current date Parameters: ----------- gdir: py:class:'crampon.GlavierDirectory' A GlacierDirectoryInstance Returns: -------- None """ print("Crop DEM to glacier") img_path = cfg.PATHS['dem_dir'] img_list = os.listdir(img_path) img_list = [os.path.join(img_path, band) for band in img_list] dim_name = "band" dim_label = ['height_in_m'] var_name = 'height_in_m' time_stamp = 20180101 file_group = 'dem_ts' # check if cropped dem for glacier already exists: if os.path.isfile(os.path.join(gdir.get_filepath('dem_ts'))): # exit function, no need to read again return # for first time: # Project DEM to same crs as sentinel tiles: # get crs from sentinel tile: # TODO: something wrong with this, currently the DEM needs to have # the same projection as the sentinel images # with rasterio.open(os.path.join(os.path.join(os.path.join( # cfg.PATHS['working_dir'], # 'cache', str(cfg.PARAMS['date'][0]), # 'mosaic')), os.listdir(os.path.join(os.path.join( # cfg.PATHS['working_dir'], # 'cache', str(cfg.PARAMS['date'][0]), # 'mosaic')))[1])) as sentinel: # dst_crs = sentinel.crs dst_crs = 'EPSG:32632' for band in img_list: with rasterio.open(band) as src: if dst_crs == src.crs: # DEM is already reprojected crop_geotiff_to_glacier(gdir, img_list, dim_name, dim_label, var_name, time_stamp, file_group) else: # reproject # TODO: something is not right with reprojection... print(src.crs) src_crs = CRS.to_proj4(src.crs) transform, width, height = calculate_default_transform( src_crs, dst_crs, src.width, src.height, *src.bounds) kwargs = src.meta.copy() kwargs.update({ 'crs': dst_crs, 'transform': transform, 'width': width, 'height': height }) with rasterio.open(band, 'w', **kwargs) as dst: for i in range(1, src.count + 1): # safe reprojected file: reproject(source=rasterio.band(src, i), destination=rasterio.band(dst, i), src_transform=src.transform, src_crs=src_crs, dst_transform=transform, dst_crs=dst_crs, resampling=Resampling.nearest) print(dst.meta) crop_geotiff_to_glacier(gdir, img_list, dim_name, dim_label, var_name, time_stamp, file_group)
def warp(ctx, files, output, driver, like, dst_crs, dimensions, src_bounds, dst_bounds, res, resampling, src_nodata, dst_nodata, threads, check_invert_proj, force_overwrite, creation_options, target_aligned_pixels): """ Warp a raster dataset. If a template raster is provided using the --like option, the coordinate reference system, affine transform, and dimensions of that raster will be used for the output. In this case --dst-crs, --bounds, --res, and --dimensions options are not applicable and an exception will be raised. \b $ rio warp input.tif output.tif --like template.tif The output coordinate reference system may be either a PROJ.4 or EPSG:nnnn string, \b --dst-crs EPSG:4326 --dst-crs '+proj=longlat +ellps=WGS84 +datum=WGS84' or a JSON text-encoded PROJ.4 object. \b --dst-crs '{"proj": "utm", "zone": 18, ...}' If --dimensions are provided, --res and --bounds are not applicable and an exception will be raised. Resolution is calculated based on the relationship between the raster bounds in the target coordinate system and the dimensions, and may produce rectangular rather than square pixels. \b $ rio warp input.tif output.tif --dimensions 100 200 \\ > --dst-crs EPSG:4326 If --bounds are provided, --res is required if --dst-crs is provided (defaults to source raster resolution otherwise). \b $ rio warp input.tif output.tif \\ > --bounds -78 22 -76 24 --res 0.1 --dst-crs EPSG:4326 """ output, files = resolve_inout(files=files, output=output, force_overwrite=force_overwrite) resampling = Resampling[resampling] # get integer code for method if not len(res): # Click sets this as an empty tuple if not provided res = None else: # Expand one value to two if needed res = (res[0], res[0]) if len(res) == 1 else res if target_aligned_pixels: if not res: raise click.BadParameter( '--target-aligned-pixels requires a specified resolution') if src_bounds or dst_bounds: raise click.BadParameter( '--target-aligned-pixels cannot be used with ' '--src-bounds or --dst-bounds') # Check invalid parameter combinations if like: invalid_combos = (dimensions, dst_bounds, dst_crs, res) if any(p for p in invalid_combos if p is not None): raise click.BadParameter( "--like cannot be used with any of --dimensions, --bounds, " "--dst-crs, or --res") elif dimensions: invalid_combos = (dst_bounds, res) if any(p for p in invalid_combos if p is not None): raise click.BadParameter( "--dimensions cannot be used with --bounds or --res") with ctx.obj['env']: setenv(CHECK_WITH_INVERT_PROJ=check_invert_proj) with rasterio.open(files[0]) as src: l, b, r, t = src.bounds out_kwargs = src.profile.copy() out_kwargs['driver'] = driver # Sort out the bounds options. if src_bounds and dst_bounds: raise click.BadParameter( "--src-bounds and destination --bounds may not be " "specified simultaneously.") if like: with rasterio.open(like) as template_ds: dst_crs = template_ds.crs dst_transform = template_ds.transform dst_height = template_ds.height dst_width = template_ds.width elif dst_crs is not None: try: dst_crs = CRS.from_string(dst_crs) except ValueError as err: raise click.BadParameter(str(err), param='dst_crs', param_hint='dst_crs') if dimensions: # Calculate resolution appropriate for dimensions # in target. dst_width, dst_height = dimensions try: xmin, ymin, xmax, ymax = transform_bounds( src.crs, dst_crs, *src.bounds) except CRSError as err: raise click.BadParameter(str(err), param='dst_crs', param_hint='dst_crs') dst_transform = Affine( (xmax - xmin) / float(dst_width), 0, xmin, 0, (ymin - ymax) / float(dst_height), ymax) elif src_bounds or dst_bounds: if not res: raise click.BadParameter( "Required when using --bounds.", param='res', param_hint='res') if src_bounds: try: xmin, ymin, xmax, ymax = transform_bounds( src.crs, dst_crs, *src_bounds) except CRSError as err: raise click.BadParameter(str(err), param='dst_crs', param_hint='dst_crs') else: xmin, ymin, xmax, ymax = dst_bounds dst_transform = Affine(res[0], 0, xmin, 0, -res[1], ymax) dst_width = max(int(ceil((xmax - xmin) / res[0])), 1) dst_height = max(int(ceil((ymax - ymin) / res[1])), 1) elif target_aligned_pixels: try: xmin, ymin, xmax, ymax = transform_bounds( src.crs, dst_crs, *src.bounds) except CRSError as err: raise click.BadParameter(str(err), param='dst_crs', param_hint='dst_crs') xmin = floor(xmin / res[0]) * res[0] xmax = ceil(xmax / res[0]) * res[0] ymin = floor(ymin / res[1]) * res[1] ymax = ceil(ymax / res[1]) * res[1] dst_transform = Affine(res[0], 0, xmin, 0, -res[1], ymax) dst_width = max(int(ceil((xmax - xmin) / res[0])), 1) dst_height = max(int(ceil((ymax - ymin) / res[1])), 1) else: try: if src.transform.is_identity and src.gcps: src_crs = src.gcps[1] kwargs = {'gcps': src.gcps[0]} else: src_crs = src.crs kwargs = src.bounds._asdict() dst_transform, dst_width, dst_height = calcdt( src_crs, dst_crs, src.width, src.height, resolution=res, **kwargs) except CRSError as err: raise click.BadParameter(str(err), param='dst_crs', param_hint='dst_crs') elif dimensions: # Same projection, different dimensions, calculate resolution. dst_crs = src.crs dst_width, dst_height = dimensions dst_transform = Affine((r - l) / float(dst_width), 0, l, 0, (b - t) / float(dst_height), t) elif src_bounds or dst_bounds: # Same projection, different dimensions and possibly # different resolution. if not res: res = (src.transform.a, -src.transform.e) dst_crs = src.crs xmin, ymin, xmax, ymax = (src_bounds or dst_bounds) dst_transform = Affine(res[0], 0, xmin, 0, -res[1], ymax) dst_width = max(int(ceil((xmax - xmin) / res[0])), 1) dst_height = max(int(ceil((ymax - ymin) / res[1])), 1) elif res: # Same projection, different resolution. dst_crs = src.crs dst_transform = Affine(res[0], 0, l, 0, -res[1], t) dst_width = max(int(ceil((r - l) / res[0])), 1) dst_height = max(int(ceil((t - b) / res[1])), 1) else: dst_crs = src.crs dst_transform = src.transform dst_width = src.width dst_height = src.height # If src_nodata is not None, update the dst metadata NODATA # value to src_nodata (will be overridden by dst_nodata if it is not None if src_nodata is not None: # Update the dst nodata value out_kwargs.update({'nodata': src_nodata}) # Validate a manually set destination NODATA value # against the input datatype. if dst_nodata is not None: if src_nodata is None and src.meta['nodata'] is None: raise click.BadParameter( "--src-nodata must be provided because dst-nodata is not None" ) else: # Update the dst nodata value out_kwargs.update({'nodata': dst_nodata}) # When the bounds option is misused, extreme values of # destination width and height may result. if (dst_width < 0 or dst_height < 0 or dst_width > MAX_OUTPUT_WIDTH or dst_height > MAX_OUTPUT_HEIGHT): raise click.BadParameter( "Invalid output dimensions: {0}.".format( (dst_width, dst_height))) out_kwargs.update({ 'crs': dst_crs, 'transform': dst_transform, 'width': dst_width, 'height': dst_height }) # Adjust block size if necessary. if ('blockxsize' in out_kwargs and dst_width < out_kwargs['blockxsize']): del out_kwargs['blockxsize'] if ('blockysize' in out_kwargs and dst_height < out_kwargs['blockysize']): del out_kwargs['blockysize'] out_kwargs.update(**creation_options) with rasterio.open(output, 'w', **out_kwargs) as dst: reproject(source=rasterio.band(src, list(range(1, src.count + 1))), destination=rasterio.band( dst, list(range(1, src.count + 1))), src_transform=src.transform, src_crs=src.crs, src_nodata=src_nodata, dst_transform=out_kwargs['transform'], dst_crs=out_kwargs['crs'], dst_nodata=dst_nodata, resampling=resampling, num_threads=threads)
'crs': dst_crs, 'transform': dst_transform, 'width': width, 'height': height }) with rasterio.open('reprojected_and_cropped_scene_file.tif', 'w', **kwargs) as dst: ############################################################# #### #### Issues: combining projecting and cropping in one open comman (when first cropping then reprojecting it has problems to open the .tif of the clipped image. #### Otherwise not sure wichinput parameters for reproject fct, especially for source = out_image?? #### #### ############################################################# reproject(source=out_image, destination=rasterio.band(dst, 1), src_transform=out_transform, src_crs=src.crs, dst_transform=dst_transform, dst_crs=dst_crs, resampling=Resampling.nearest) print('New CRS of Scene file;', dst.crs) ##### Write reprojected and cropped image to .tif file dst.write(out_image) ##### Plot results: # img = mpimg.imread('reprojected_and_cropped_scene_file.tif') # imgplot = plt.imshow(img) # plt.show() # # #
def reproject_s2(pth: str, date: str, lat: float, lng: float, dst_crs: str): """Reproject GTiff to target CRS EPSG:3005 - BC Albers - output tif and plot EPSG:4326 - KML generation Parameters ---------- pth : str Path to source GTiff to be reprojected date : str Date selected in format YYYY.MM.DD lat : float Target latitude lng : float Target longitude dst_crs : str Desired CRS to reproject to Returns ------- str Path to output GTiff """ logger.info(f'[sentinel2.reproject_s2] REPROJECTING S2 TO {dst_crs}') base = os.path.split(pth)[0] if dst_crs == 'EPSG:4326': out_pth = os.path.join(base, f'{date}_EPSG4326.tif') res = 0.000285245221099300378 # Value from QGIS reprojection inspection elif dst_crs == 'EPSG:3153': out_pth = os.path.join(base, f'{date}_EPSG3153.tif') res = 20.00754121032614563 # Value from QGIS reprojection inspection else: logger.warning('[sentinel2.reproject_s2] Invalid CRS') return None if os.path.exists(out_pth): os.remove(out_pth) logger.debug( f'[sentinel2.reproject_s2] Removing residual file: {out_pth}') with rio.open(pth, 'r') as src: transform, width, height = calculate_default_transform(src.crs, dst_crs, src.width, src.height, *src.bounds, resolution=res) kwargs = src.meta.copy() # Update meta information to desired CRS kwargs.update({ 'driver': 'GTiff', 'crs': dst_crs, 'transform': transform, 'width': width, 'height': height, 'dtype': rio.uint16, 'nodata': nodata_val }) # Write reprojected granule into GTiff format with rio.open(out_pth, 'w', **kwargs) as dst: reproject(source=rio.band(src, 1), destination=rio.band(dst, 1), src_transform=src.transform, src_crs=src.crs, dst_transform=transform, dst_crs=dst_crs, resampling=Resampling.nearest, dst_nodata=nodata_val) if dst_crs == 'EPSG:3153': mv_pth = os.path.join(const.SENTINEL_OUTPUT, date, f'lat{lat}_lng{lng}', os.path.split(out_pth)[-1]) try: os.makedirs(os.path.split(mv_pth)[0]) except: pass shutil.copy(out_pth, mv_pth) return out_pth
def _arith(self, function, other=None): """General method for performing arithmetic operations on RasterLayer objects Parameters ---------- function : function Custom function that takes either one or two arrays, and returns a single array following a pre-defined calculation. other : pyspatialml.RasterLayer (optional, default None) If not specified, then a `function` should be provided that performs a calculation using only the selected RasterLayer. If `other` is specified, then a `function` should be supplied that takes to ndarrays as arguments and performs a calculation using both layers, i.e. layer1 - layer2. Returns ------- pyspatialml.RasterLayer Returns a single RasterLayer containing the calculated result. """ _, tfile = _file_path_tempfile(None) driver = self.driver # determine dtype of result based on calc on single pixel if other is not None: arr1 = self.read(masked=True, window=Window(0, 0, 1, 1)) try: arr2 = other.read(masked=True, window=Window(0, 0, 1, 1)) except AttributeError: arr2 = other test = function(arr1, arr2) dtype = test.dtype else: dtype = self.dtype nodata = _get_nodata(dtype) # open output file with updated metadata meta = self.meta meta.update(driver=driver, count=1, dtype=dtype, nodata=nodata) with rasterio.open(tfile.name, "w", **meta) as dst: # define windows windows = [window for ij, window in dst.block_windows()] # generator gets raster arrays for each window self_gen = (self.read(window=w, masked=True) for w in windows) if isinstance(other, RasterLayer): other_gen = (other.read(window=w, masked=True) for w in windows) else: other_gen = (other for w in windows) for window, arr1, arr2 in zip(windows, self_gen, other_gen): if other is not None: result = function(arr1, arr2) else: result = function(arr1) result = np.ma.filled(result, fill_value=nodata) dst.write(result.astype(dtype), window=window, indexes=1) # create RasterLayer from result src = rasterio.open(tfile.name) band = rasterio.band(src, 1) layer = pyspatialml.RasterLayer(band) # overwrite close attribute with close method from temporaryfilewrapper layer.close = tfile.close return layer
def snap_raster_to_other(raster_path, ex_path, out_path, src_crs=None): '''Resample a raster to match the size and extent of another raster. args : raster_path - raster to alter. ex_path - raster to use as template out_path - path of output raster. ''' #collect template data with rasterio.open(ex_path) as ex: dst_res = (ex.transform[0], ex.transform[4] * -1) dst_crs = ex.crs height = ex.height width = ex.width dst_transform = ex.transform bounds = ex.bounds crs = ex.crs if src_crs: with rasterio.open(raster_path, 'r') as src: data = src.read() meta = src.meta meta.update({'crs': src_crs}) with rasterio.open(raster_path, 'w+', **meta) as dst: dst.write(data) src = rasterio.open(raster_path) #if extents dont match, mask the raster to bounding box of the example. if src.bounds != bounds: src.close() mask_raster(raster_path, [box(*bounds)], out_path, crs) src = rasterio.open(out_path) # make the out array dst_data = np.zeros((1, height, width)) try: rasterio.warp.reproject( rasterio.band(src, 1), destination=dst_data, dst_resolution=dst_res, dst_crs=dst_crs, src_crs=src.crs, dst_transform=dst_transform, ) out_meta = src.meta.copy() finally: src.close() assert width == dst_data.shape[-1] assert height == dst_data.shape[-2] out_meta.update({ 'transform': dst_transform, 'width': dst_data.shape[-1], 'height': dst_data.shape[-2], }) with rasterio.open(out_path, 'w+', **out_meta) as dst: dst.write(dst_data.astype(out_meta['dtype'])) assert rasterio.open(out_path).read(1).shape == rasterio.open( ex_path).read(1).shape
dst_dataset = os.path.join(path_myd_processed, '03mask_SouthKorea_MYD13A2', str(yr), f'm_{os.path.basename(src_dataset)[2:]}') matlab.check_make_dir(os.path.dirname(dst_dataset)) with rio.open(src_dataset) as src: kwargs = src.meta.copy() kwargs['transform'] = masksrc.transform temp_dataset = os.path.join(os.path.dirname(dst_dataset), 'temp.tif') resolution = 1.02308446206551E-02 dst_crs = masksrc.crs with rio.open(temp_dataset, 'w+', **kwargs) as temp_dst: for i in range(1, src.count + 1): reproject( source=rio.band(src, i), destination=rio.band(temp_dst, i), src_transform=src.transform, src_crs=src.crs, src_nodata=-9999, dst_transform=masksrc.transform, dst_crs=dst_crs, dst_nodata=-9999, dst_resolution=resolution, ) out_img, out_transform = mask(dataset=temp_dst, shapes=shapes, crop=True) with rio.open(temp_dataset) as temp_dst: out_meta = temp_dst.meta.copy() out_meta.update({
def reproject_raster(input_raster_name, reprojection, blocksize=None, reprojected_raster_name=None): if blocksize is not None: if isinstance(blocksize, int): pass elif isinstance(blocksize, str): blocksize = int(blocksize) elif isinstance(blocksize, float): blocksize = int(blocksize) else: raise TypeError("Pass integer for blocksize") else: blocksize = 256 assert input_raster_name.endswith('.tif'), "input raster needs to be a tif" reprojection = rasterio.crs.CRS.from_string(reprojection) with rasterio.open(input_raster_name) as src: # Check projection if src.crs.to_string() != reprojection: if src.crs.to_string().startswith('EPSG'): epsg = src.crs.to_epsg() proj_crs = CRS.from_epsg(epsg) rio_crs = rasterio.crs.CRS.from_user_input( proj_crs).to_string() else: rio_crs = src.crs.to_string() print(f"{input_raster_name} not projected") print(f"Reprojecting from {rio_crs} to {reprojection}") transform, width, height = calculate_default_transform( src.crs, reprojection, src.width, src.height, *src.bounds) kwargs = src.meta.copy() kwargs.update({ 'crs': reprojection, 'transform': transform, 'width': width, 'height': height, 'compress': 'lzw' }) if reprojected_raster_name is None: reprojected_raster_name = input_raster_name assert reprojected_raster_name.endswith( '.tif'), "output raster needs to be a tif" with rasterio.open(reprojected_raster_name, 'w', **kwargs, tiled=True, blockxsize=blocksize, blockysize=blocksize, BIGTIFF='YES') as dst: reproject(source=rasterio.band(src, 1), destination=rasterio.band(dst, 1), src_transform=src.transform, src_crs=rio_crs, dst_transform=transform, dst_crs=reprojection.to_string(), resampling=Resampling.nearest) del dst del src
def reproject(self, dst_crs, dst_res=None, fp=None, interpolation='nearest'): """ Change coordinate system (projection) of the band. It does not alter the existing file, and creates a new file either in the specified location or a temporary file. The band ground sampling distance is not changed, however the resolution may change due to the new coordinate system It is based on `rasterio.warp.reproject <https://rasterio.readthedocs.io/en/latest/api/rasterio.warp.html#rasterio.warp.reproject>`_, see for more variants of interpolation. Args: dst_crs: new CRS, may be in any form acceptable by rasterio, for example as EPSG code, string, CRS object; if dst_crs == `utm`, the appropriate UTM zone is used according to the center of the image fp (str): a filename for the new resampled band. If none, a temporary file is created interpolation: interpolation type as in rasterio, `nearest`, `bilinear`, `cubic`, `lanzsos` or others dst_res (Tuple[float, float]): new resoluton, georeferenced pixel size for the new band Returns: a new reprojected and resampled Band """ if dst_crs == 'utm': dst_crs = get_utm_zone(self.crs, self.transform, (self.height, self.width)) else: dst_crs = dst_crs if isinstance(dst_crs, CRS) else CRS.from_user_input(dst_crs) # Old rasterio compatibility: a separate check for validity if not dst_crs.is_valid: raise rasterio.errors.CRSError('Invalid CRS {} given'.format(dst_crs)) # get temporary filepath if such is not provided tmp_file = False if fp is not None else True if fp is None: fp = '{tmp}/reprojected_{crs}/{directory}/{name}.tif'.format( tmp=TMP_DIR, crs=dst_crs, directory=random_name(), name=self.name) os.makedirs(os.path.dirname(fp), exist_ok=True) # calculate params of new reprojected Band transform, width, height = calculate_default_transform( self.crs, dst_crs, self.width, self.height, resolution=dst_res,*self.bounds) kwargs = self.meta.copy() kwargs.update({ 'crs': dst_crs, 'transform': transform, 'width': width, 'height': height }) # reproject with rasterio.open(fp, 'w', **kwargs) as dst: reproject( source=rasterio.band(self._band, 1), destination=rasterio.band(dst, 1), src_transform=self.transform, src_crs=self.crs, dst_transform=transform, dst_crs=dst_crs, resampling=getattr(Resampling, interpolation)) # new band band = Band(fp) band._tmp_file = tmp_file # file will be automatically removed when `Band` instance will be deleted return band
with rasterio.open(path) as src: profile = src.profile.copy() transform, width, height = rasterio.warp.calculate_default_transform( src.crs, dst_crs, src.width, src.height, *src.bounds) profile.update({ 'crs': {'init': 'EPSG:3857'}, 'transform': transform, 'width': width, 'height': height }) with rasterio.open('C:/data/new_tif', 'w', **profile) as dst: rasterio.warp.reproject( source=rasterio.band(src, 1), destination=rasterio.band(dst, 1), src_transform=transform, src_crs=source_crs, dst_transform=transform, dst_crs={'init': 'EPSG:3857'}, resampling=rasterio.warp.Resampling.bilinear) source_crs = ccrs.LambertConformal(central_longitude=-95,central_latitude=38.936454, cutoff=20) ax = plt.subplot(projection = ccrs.LambertConformal(central_longitude=-95,central_latitude=38.936454, cutoff=20)) ax.add_feature(shape_michigan['MI'], facecolor='none', edgecolor='yellow', linewidth=0.5) def main(): fig = plt.figure() ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())
def define_glacier_region(gdir, entity=None): """ Very first task: define the glacier's local grid. Defines the local projection (Transverse Mercator), centered on the glacier. There is some options to set the resolution of the local grid. It can be adapted depending on the size of the glacier with:: dx (m) = d1 * AREA (km) + d2 ; clipped to dmax or be set to a fixed value. See ``params.cfg`` for setting these options. Default values of the adapted mode lead to a resolution of 50 m for Hintereisferner, which is approx. 8 km2 large. After defining the grid, the topography and the outlines of the glacier are transformed into the local projection. The default interpolation for the topography is `cubic`. Parameters ---------- gdir : :py:class:`oggm.GlacierDirectory` where to write the data entity : geopandas GeoSeries the glacier geometry to process """ # choose a spatial resolution with respect to the glacier area dxmethod = cfg.PARAMS['grid_dx_method'] area = gdir.rgi_area_km2 if dxmethod == 'linear': dx = np.rint(cfg.PARAMS['d1'] * area + cfg.PARAMS['d2']) elif dxmethod == 'square': dx = np.rint(cfg.PARAMS['d1'] * np.sqrt(area) + cfg.PARAMS['d2']) elif dxmethod == 'fixed': dx = np.rint(cfg.PARAMS['fixed_dx']) else: raise ValueError('grid_dx_method not supported: {}'.format(dxmethod)) # Additional trick for varying dx if dxmethod in ['linear', 'square']: dx = np.clip(dx, cfg.PARAMS['d2'], cfg.PARAMS['dmax']) log.debug('%s: area %.2f km, dx=%.1f', gdir.rgi_id, area, dx) # Make a local glacier map proj_params = dict(name='tmerc', lat_0=0., lon_0=gdir.cenlon, k=0.9996, x_0=0, y_0=0, datum='WGS84') proj4_str = "+proj={name} +lat_0={lat_0} +lon_0={lon_0} +k={k} " \ "+x_0={x_0} +y_0={y_0} +datum={datum}".format(**proj_params) proj_in = pyproj.Proj("+init=EPSG:4326", preserve_units=True) proj_out = pyproj.Proj(proj4_str, preserve_units=True) project = partial(pyproj.transform, proj_in, proj_out) # transform geometry to map geometry = shapely.ops.transform(project, entity['geometry']) geometry = _check_geometry(geometry) xx, yy = geometry.exterior.xy # Corners, incl. a buffer of N pix ulx = np.min(xx) - cfg.PARAMS['border'] * dx lrx = np.max(xx) + cfg.PARAMS['border'] * dx uly = np.max(yy) + cfg.PARAMS['border'] * dx lry = np.min(yy) - cfg.PARAMS['border'] * dx # n pixels nx = np.int((lrx - ulx) / dx) ny = np.int((uly - lry) / dx) # Back to lon, lat for DEM download/preparation tmp_grid = salem.Grid(proj=proj_out, nxny=(nx, ny), x0y0=(ulx, uly), dxdy=(dx, -dx), pixel_ref='corner') minlon, maxlon, minlat, maxlat = tmp_grid.extent_in_crs(crs=salem.wgs84) # save transformed geometry to disk entity = entity.copy() entity['geometry'] = geometry # Avoid fiona bug: https://github.com/Toblerity/Fiona/issues/365 for k, s in entity.iteritems(): if type(s) in [np.int32, np.int64]: entity[k] = int(s) towrite = gpd.GeoDataFrame(entity).T towrite.crs = proj4_str # Delete the source before writing if 'DEM_SOURCE' in towrite: del towrite['DEM_SOURCE'] towrite.to_file(gdir.get_filepath('outlines')) # Also transform the intersects if necessary gdf = cfg.PARAMS['intersects_gdf'] gdf = gdf.loc[(gdf.RGIId_1 == gdir.rgi_id) | (gdf.RGIId_2 == gdir.rgi_id)] if len(gdf) > 0: gdf = salem.transform_geopandas(gdf, to_crs=proj_out) if hasattr(gdf.crs, 'srs'): # salem uses pyproj gdf.crs = gdf.crs.srs gdf.to_file(gdir.get_filepath('intersects')) # Open DEM source = entity.DEM_SOURCE if hasattr(entity, 'DEM_SOURCE') else None dem_list, dem_source = get_topo_file((minlon, maxlon), (minlat, maxlat), rgi_region=gdir.rgi_region, source=source) log.debug('%s: DEM source: %s', gdir.rgi_id, dem_source) # A glacier area can cover more than one tile: if len(dem_list) == 1: dem_dss = [rasterio.open(dem_list[0])] # if one tile, just open it dem_data = rasterio.band(dem_dss[0], 1) src_transform = dem_dss[0].transform else: dem_dss = [rasterio.open(s) for s in dem_list] # list of rasters dem_data, src_transform = merge_tool(dem_dss) # merged rasters # Use Grid properties to create a transform (see rasterio cookbook) dst_transform = rasterio.transform.from_origin( ulx, uly, dx, dx # sign change (2nd dx) is done by rasterio.transform ) # Set up profile for writing output profile = dem_dss[0].profile profile.update({ 'crs': proj4_str, 'transform': dst_transform, 'width': nx, 'height': ny }) # Could be extended so that the cfg file takes all Resampling.* methods if cfg.PARAMS['topo_interp'] == 'bilinear': resampling = Resampling.bilinear elif cfg.PARAMS['topo_interp'] == 'cubic': resampling = Resampling.cubic else: raise ValueError('{} interpolation not understood'.format( cfg.PARAMS['topo_interp'])) dem_reproj = gdir.get_filepath('dem') with rasterio.open(dem_reproj, 'w', **profile) as dest: dst_array = np.empty((ny, nx), dtype=dem_dss[0].dtypes[0]) reproject( # Source parameters source=dem_data, src_crs=dem_dss[0].crs, src_transform=src_transform, # Destination parameters destination=dst_array, dst_transform=dst_transform, dst_crs=proj4_str, # Configuration resampling=resampling) dest.write(dst_array, 1) for dem_ds in dem_dss: dem_ds.close() # Glacier grid x0y0 = (ulx + dx / 2, uly - dx / 2) # To pixel center coordinates glacier_grid = salem.Grid(proj=proj_out, nxny=(nx, ny), dxdy=(dx, -dx), x0y0=x0y0) glacier_grid.to_json(gdir.get_filepath('glacier_grid')) gdir.write_pickle(dem_source, 'dem_source') # Looks in the database if the glacier has divides. gdf = cfg.PARAMS['divides_gdf'] if gdir.rgi_id in gdf.index.values: divdf = [g for g in gdf.loc[gdir.rgi_id].geometry] # Reproject the shape def proj(lon, lat): return salem.transform_proj(salem.wgs84, gdir.grid.proj, lon, lat) divdf = [shapely.ops.transform(proj, g) for g in divdf] # Keep only the ones large enough log.debug('%s: divide candidates: %d', gdir.rgi_id, len(divdf)) divdf = [g for g in divdf if (g.area >= (25 * dx**2))] log.debug('%s: number of divides: %d', gdir.rgi_id, len(divdf)) # Write the directories and the files for i, g in enumerate(divdf): _dir = os.path.join(gdir.dir, 'divide_{0:0=2d}'.format(i + 1)) if not os.path.exists(_dir): os.makedirs(_dir) # File entity['geometry'] = g towrite = gpd.GeoDataFrame(entity).T towrite.crs = proj4_str towrite.to_file(os.path.join(_dir, cfg.BASENAMES['outlines'])) else: # Make a single directory and link the files log.debug('%s: number of divides: %d', gdir.rgi_id, 1) _dir = os.path.join(gdir.dir, 'divide_01') if not os.path.exists(_dir): os.makedirs(_dir) linkname = os.path.join(_dir, cfg.BASENAMES['outlines']) sourcename = gdir.get_filepath('outlines') for ending in ['.cpg', '.dbf', '.shp', '.shx', '.prj']: _s = sourcename.replace('.shp', ending) _l = linkname.replace('.shp', ending) if os.path.exists(_s): try: # we are on UNIX os.link(_s, _l) except AttributeError: # we are on windows copyfile(_s, _l)
def define_nonrgi_glacier_region(gdir: NonRGIGlacierDirectory): """ Very first task: define the glacier's local grid. Defines the local projection (Transverse Mercator), centered on the glacier. The resolution of the local grid is dx. After defining the grid, the topography is transformed into the local projection. The default interpolation for the topography is `cubic`. Parameters ---------- gdir : :py:class:`oggm.NonRGIGlacierDirectory` where to write the data dx : float grid spacing """ xx, yy = gdir.extent_ll dx = gdir.case.dx # Make a local glacier map proj_params = dict(name='tmerc', lat_0=0., lon_0=gdir.cenlon, k=0.9996, x_0=0, y_0=0, datum='WGS84') proj4_str = "+proj={name} +lat_0={lat_0} +lon_0={lon_0} +k={k} " \ "+x_0={x_0} +y_0={y_0} +datum={datum}".format(**proj_params) # proj_in = pyproj.Proj("+init=EPSG:4326", preserve_units=True) proj_out = pyproj.Proj(proj4_str, preserve_units=True) merc_xx, merc_yy = salem.transform_proj(salem.wgs84, proj_out, xx, yy) # Corners, incl. a buffer of N pix ulx = np.min(merc_xx) lrx = np.max(merc_xx) uly = np.max(merc_yy) lry = np.min(merc_yy) # n pixels nx = np.int((lrx - ulx) / dx) ny = np.int((uly - lry) / dx) # Back to lon, lat for DEM download/preparation tmp_grid = salem.Grid(proj=proj_out, nxny=(nx, ny), x0y0=(ulx, uly), dxdy=(dx, -dx), pixel_ref='corner') minlon, maxlon, minlat, maxlat = tmp_grid.extent_in_crs(crs=salem.wgs84) dem_list, dem_source = get_topo_file((minlon, maxlon), (minlat, maxlat), rgi_region=None, rgi_subregion=None, source='DEM3') log.debug('(%s) DEM source: %s', gdir.name, dem_source) # A glacier area can cover more than one tile: if len(dem_list) == 1: dem_dss = [rasterio.open(dem_list[0])] # if one tile, just open it dem_data = rasterio.band(dem_dss[0], 1) if LooseVersion(rasterio.__version__) >= LooseVersion('1.0'): src_transform = dem_dss[0].transform else: src_transform = dem_dss[0].affine else: dem_dss = [rasterio.open(s) for s in dem_list] # list of rasters dem_data, src_transform = merge_tool(dem_dss) # merged rasters # Use Grid properties to create a transform (see rasterio cookbook) dst_transform = rasterio.transform.from_origin( ulx, uly, dx, dx # sign change (2nd dx) is done by rasterio.transform ) # Set up profile for writing output profile = dem_dss[0].profile profile.update({ 'crs': proj4_str, 'transform': dst_transform, 'width': nx, 'height': ny }) # Could be extended so that the cfg file takes all Resampling.* methods if cfg.PARAMS['topo_interp'] == 'bilinear': resampling = Resampling.bilinear elif cfg.PARAMS['topo_interp'] == 'cubic': resampling = Resampling.cubic else: raise ValueError('{} interpolation not understood'.format( cfg.PARAMS['topo_interp'])) dem_reproj = gdir.get_filepath('dem') with rasterio.open(dem_reproj, 'w', **profile) as dest: dst_array = np.empty((ny, nx), dtype=dem_dss[0].dtypes[0]) reproject( # Source parameters source=dem_data, src_crs=dem_dss[0].crs, src_transform=src_transform, # Destination parameters destination=dst_array, dst_transform=dst_transform, dst_crs=proj4_str, # Configuration resampling=resampling) # TODO: ugly if gdir.case.name == 'Borden Peninsula': print('Anti icepatch used') dst_array[32, 27] = gdir.case.ela_h - 5 dst_array[:2, -4:] = gdir.case.ela_h - 5 if gdir.case.name == 'Borden Peninsula HR': print('Anti icepatch HR used') dst_array[-21:-16, 32:38] = gdir.case.ela_h - 5 dst_array[-8:-2, 88:98] = gdir.case.ela_h - 5 dst_array[:-109, 120:] = gdir.case.ela_h - 5 dest.write(dst_array, 1) for dem_ds in dem_dss: dem_ds.close() # Glacier grid x0y0 = (ulx + dx / 2, uly - dx / 2) # To pixel center coordinates glacier_grid = salem.Grid(proj=proj_out, nxny=(nx, ny), dxdy=(dx, -dx), x0y0=x0y0) glacier_grid.to_json(gdir.get_filepath('glacier_grid')) # Write DEM source info source_txt = DEM_SOURCE_INFO.get(dem_source, dem_source) with open(gdir.get_filepath('dem_source'), 'w') as fw: fw.write(source_txt)
def process_pci_dataset(src, outfile, dst_crs='EPSG:4326', resolution=None, resample_method=Resampling.nearest): """Simpely process sentinel 2 PCI image(line strech and apply gamma value) then projected to WGS 1984. Args: src (rasterio dataset): Input rasterio dataset. outfile (str): Result file (TIFF format). dst_crs : Target coordinate reference system. resolution (:tuple: x resolution, y resolution or float, optional): Target resolution, in units of target coordinate reference system. resample_method: Resampling method to use. One of the following: Resampling.nearest, Resampling.bilinear, Resampling.cubic, Resampling.cubic_spline, Resampling.lanczos, Resampling.average, Resampling.mode, Resampling.max (GDAL >= 2.2), Resampling.min (GDAL >= 2.2), Resampling.med (GDAL >= 2.2), Resampling.q1 (GDAL >= 2.2), Resampling.q3 (GDAL >= 2.2), """ # calculate_default_transform if resolution is not None: transform, width, height = calculate_default_transform( src.crs, dst_crs, src.width, src.height, resolution=resolution, *src.bounds) else: transform, width, height = calculate_default_transform( src.crs, dst_crs, src.width, src.height, *src.bounds) kwargs = src.meta.copy() kwargs.update({ 'driver': 'GTIFF', 'nodata': 0, 'crs': dst_crs, 'transform': transform, 'width': width, 'height': height }) # reproject data with rasterio.open(outfile, 'w', **kwargs) as dst: for i in range(1, src.count + 1): # strech image data # green band if i == 2: source = gamma(bytscl(src.read(i), maxValue=155), 1.4) # other band else: source = gamma(bytscl(src.read(i), maxValue=160), 1.3) reproject(source=source, destination=rasterio.band(dst, i), src_transform=src.transform, src_crs=src.crs, dst_transform=transform, dst_crs=dst_crs, resampling=resample_method)
def extract_esalc(esa_lc='H:/C3S-LC-L4-LCCS-Map-300m-P1Y-2018-v2.1.data/lccs_class.img', source_crs='EPSG:4326', region='Arctic_a60', outpath='C:/Users/Pascal/Desktop/GEUS_2019/masks/github/', target_crs='EPSG:4326', clean_temp_files=False, to_SICEMask=False, binary_mask=False): ''' INPUTS: esa_lc: path of ESA Land Classes .img file [string] source_crs: CRS of ESA Land Classes, default to 4326 [string] region: region to clip [string] outpath: folder where to store outputs [string] target_crs: Output CRS [string] to_SICEMask: set to True to have a SICE useable mask as output [boolean] binary_mask: set to True to have a SICE useable binary mask (land/ocean) if False, mask contains the 22 ESALC [boolean] OUTPUTS: if to_SICEMASK set to True: {outpath}/{region}.tif: binary or ESALC (depending on binary_mask option) SICE useable mask for the selected region [.tif] if to_SICEMASK set to False: {outpath}/esalc__clipped_{region}.tif: clipped ESALC for the selected region [.tif] {outpath}/esalc_clipped_{region}_{target_crs}.tif: clipped and reprojected in {target_crs} ESALC for the selected region [.tif] ''' import rasterio from shapely.geometry import box import geopandas as gpd from fiona.crs import from_epsg from rasterio.mask import mask from rasterio.warp import calculate_default_transform, reproject, Resampling import os from IPython import get_ipython #clear all variables to enable file deletion get_ipython().magic('reset -sf') #initialize output names target_crs_name=target_crs.split(':')[1] out_tif=outpath+'esalc_clipped_'+region+'.tif' out_tif_3413=outpath+'esalc_clipped_'+target_crs_name+'_'+region+'.tif' SICEmask_tif=outpath+region+'.tif' #Delete outputs if already exists if os.path.exists(out_tif)==True: print('WARNING: Clipped ESA LC already exists...') print('Deleting clipped ESA LC...') os.remove(out_tif) if os.path.exists(out_tif_3413)==True: print('WARNING: Reprojected and clipped ESA LC already exists...') print('Deleting reprojected and clipped ESA LC...') os.remove(out_tif_3413) if os.path.exists(SICEmask_tif)==True: print('WARNING: SICE mask already exists...') print('Deleting SICE mask...') data = rasterio.open(esa_lc) if source_crs=='EPSG:4326': if region=='Greenland': minx, miny = -80.35, 56.33 maxx, maxy = -3.17, 84.17 bbox = box(minx, miny, maxx, maxy) elif region=='Iceland': minx, miny = -24.93, 63.18 maxx, maxy = -12.8, 66.6 bbox = box(minx, miny, maxx, maxy) elif region=='Svalbard': minx, miny = 7.65, 76.18 maxx, maxy = 37.3, 80.84 bbox = box(minx, miny, maxx, maxy) elif region=='NovayaZemlya': minx, miny = 47.64, 70.4 maxx, maxy = 70.96, 77.22 bbox = box(minx, miny, maxx, maxy) elif region=='FransJosefLand': minx, miny = 40.88, 79.85 maxx, maxy = 71.66, 81.93 bbox = box(minx, miny, maxx, maxy) elif region=='SevernayaZemlya': minx, miny = 82.77, 78.00 maxx, maxy = 112.26, 83.11 bbox = box(minx, miny, maxx, maxy) elif region=='JanMayen': minx, miny = -9.47, 70.77 maxx, maxy = -7.45, 71.21 bbox = box(minx, miny, maxx, maxy) elif region=='NorthernArcticCanada': minx, miny = -128.27, 73.78 maxx, maxy = -57.69, 83.24 bbox = box(minx, miny, maxx, maxy) elif region=='SouthernArcticCanada': minx, miny = -92.23, 61.19 maxx, maxy = -60.96, 74.43 bbox = box(minx, miny, maxx, maxy) elif region=='Norway': minx, miny = 4.49, 59.44 maxx, maxy = 9.08, 62.12 bbox = box(minx, miny, maxx, maxy) elif region=='Beaufort': minx, miny = -148.87, 68.28 maxx, maxy = -122.28, 75.39 bbox = box(minx, miny, maxx, maxy) elif region=='AntarcticPeninsula': minx, miny = -78.23, -74.76 maxx, maxy = -49.23, -57.98 bbox = box(minx, miny, maxx, maxy) elif region=='AlaskaYukon': minx, miny = -158.07, 54.96 maxx, maxy = -127.22, 64.42 bbox = box(minx, miny, maxx, maxy) elif region=='Russia': minx, miny = 25, 48 maxx, maxy = 188, 80 bbox = box(minx, miny, maxx, maxy) elif region=='Arctic_a60': minx, miny = -180, 60 maxx, maxy = 180, 90 bbox = box(minx, miny, maxx, maxy) else: print('Wrong region name or not implemented') return elif source_crs=='EPSG:3413': if region=='Iceland': minx, miny = 825968.82, -2422134.15 maxx, maxy = 1405420.90, -2377180.81 bbox = box(minx, miny, maxx, maxy) elif region=='Svalbard': minx, miny = 7.65, 76.18 maxx, maxy = 37.3, 80.84 bbox = box(minx, miny, maxx, maxy) elif region=='Novaya Zemlya': minx, miny = 47.64, 70.4 maxx, maxy = 70.96, 77.22 bbox = box(minx, miny, maxx, maxy) else: print('Wrong region name or not implemented') return #insert the bbox into a GeoDataFrame if source_crs=='EPSG:4326': geo = gpd.GeoDataFrame({'geometry': bbox}, index=[0], crs=from_epsg(4326)) elif source_crs=='EPSG:3413': geo = gpd.GeoDataFrame({'geometry': bbox}, index=[0], crs=from_epsg(3413)) #reproject to the raster crs (safer) geo = geo.to_crs(crs=data.crs.data) #coordinates of the geometry so that rasterio handles it def getFeatures(gdf): """Function to parse features from GeoDataFrame in such a manner that rasterio wants them""" import json return [json.loads(gdf.to_json())['features'][0]['geometry']] print('Creating mask...') coords = getFeatures(geo) #clip source image using coords print('Clipping input...') out_img, out_transform = mask(dataset=data, shapes=coords, crop=True) # Copy the metadata out_meta = data.meta.copy() out_meta.update({"driver": "GTiff", "height": out_img.shape[1], "width": out_img.shape[2], "transform": out_transform, "crs": data.crs}) print('Saving output...') with rasterio.open(out_tif, "w",compress='deflate', **out_meta) as dest: dest.write(out_img) if source_crs != target_crs: print('Reprojecting output...') dst_crs = target_crs with rasterio.open(out_tif) as src: transform, width, height = calculate_default_transform(src.crs, dst_crs, src.width, src.height, *src.bounds) kwargs = src.meta.copy() kwargs.update({'crs': dst_crs,'transform': transform, 'width': width,'height': height}) with rasterio.open(out_tif_3413, 'w', compress='deflate', **kwargs) as dst: reproject(source=rasterio.band(src, 1),destination=rasterio.band(dst, 1), src_transform=src.transform, src_crs=src.crs, dst_transform=transform, dst_crs=dst_crs, resampling=Resampling.nearest) if to_SICEMask==True: ''' ESA LC: 210: ocean 0: out of footprint 60-90(10)/100-150(10)/122/180/200-220(10): land SICE MASK: 255: ocean 2: land ''' print('Converting output to SICE mask...') esalc_tp=rasterio.open(out_tif_3413) esalc=esalc_tp.read(1) if binary_mask==True: if region!='BeaufortSea': mask_esalc=esalc.copy() mask_esalc[(mask_esalc!=210) & (mask_esalc!=0)]=2 mask_esalc[mask_esalc!=2]=255 else: mask_esalc=esalc.copy() mask_esalc[(mask_esalc==210) & (mask_esalc!=0)]=2 mask_esalc[mask_esalc!=2]=255 elif binary_mask==False: if region!='BeaufortSea': mask_esalc=esalc.copy() mask_esalc[mask_esalc==210]=255 mask_esalc[mask_esalc==0]=255 else: print('BeaufortSea mask could only be binary (covers ocean only)') mask_esalc=esalc.copy() mask_esalc[(mask_esalc==210) & (mask_esalc!=0)]=2 mask_esalc[mask_esalc!=2]=255 print('Saving SICE mask...') profile = esalc_tp.profile profile.update(nodata=255) with rasterio.open(SICEmask_tif, 'w', **profile) as dst: dst.write(mask_esalc, 1) return out_tif, out_tif_3413, clean_temp_files,to_SICEMask
def _get_bands(inputs, sources, d, i=None): """Get a rasterio.Band object from calc's inputs""" idx = d if d in dict(inputs) else int(d) - 1 src = sources[idx] return (rasterio.band(src, i) if i else [rasterio.band(src, j) for j in src.indexes])
def warp_like( input, output, like, format=None, co={}, resampling=warp.Resampling.nearest ): """Warp a raster to lie on top op of an existing dataset. This function is meant to be similar to the ``rio warp --like`` CLI, and uses code from the implementation. Once https://github.com/mapbox/rasterio/issues/784 is resolved this function may no longer be required. For further information see https://mapbox.github.io/rasterio/cli.html#warp and https://mapbox.github.io/rasterio/topics/reproject.html Parameters ---------- input : str Path to the input raster. output : str Path to the output raster. like : str or rasterio.DatasetReader The raster whose affine transform, size, and crs are used. format : str, optional The GDAL raster driver code of the output, see http://www.gdal.org/formats_list.html By default, use the same format as the input. co : dict, optional Creation options for creating the output. resampling : Resampling enum, optional Default value is ``rasterio.warp.Resampling.nearest``. For other values see https://mapbox.github.io/rasterio/topics/resampling.html?highlight=resampling#resampling-methods Example ------- >>> warp_like('input.map', 'output.tif', 'like.tif', format='GTiff', co={'COMPRESS':'DEFLATE'}, resampling=warp.Resampling.med) """ dst_crs, dst_transform, dst_height, dst_width = _like(like) with rasterio.open(input) as src: out_kwargs = src.profile.copy() out_kwargs.update( { "crs": dst_crs, "transform": dst_transform, "width": dst_width, "height": dst_height, } ) # else the format is equal to the input format if format is not None: out_kwargs["driver"] = format # Adjust block size if necessary. if "blockxsize" in out_kwargs and dst_width < out_kwargs["blockxsize"]: del out_kwargs["blockxsize"] if "blockysize" in out_kwargs and dst_height < out_kwargs["blockysize"]: del out_kwargs["blockysize"] out_kwargs.update(co) with rasterio.open(output, "w", **out_kwargs) as dst: warp.reproject( source=rasterio.band(src, list(range(1, src.count + 1))), destination=rasterio.band(dst, list(range(1, src.count + 1))), src_transform=src.transform, src_crs=src.crs, src_nodata=src.nodata, dst_transform=out_kwargs["transform"], dst_crs=out_kwargs["crs"], dst_nodata=dst.nodata, resampling=resampling, )
def reproject_and_save_tile(gs_tuple, pixel_size=10): tile_name = gs_tuple[-1].split('_')[-2] tile_folder_base = '/Volumes/Conlon Backup 2TB/sentinel_imagery/reprojected_tiles' tile_folder = os.path.join(tile_folder_base, tile_name) if not os.path.exists(tile_folder): os.mkdir(tile_folder) print('Downloading Tile: {}'.format(gs_tuple[-1])) valid_bands = ['B02', 'B03', 'B04', 'B08'] cmd_string = '/Users/terenceconlon/anaconda3/envs/gis/bin/gsutil ls -r ' + gs_tuple[ -1] + '/GRANULE' image_list_output = subprocess.Popen(cmd_string, shell=True, stdout=subprocess.PIPE) image_list_clean = [ j.decode('utf-8') for j in image_list_output.stdout.readlines() ] image_list_output.kill() jp2_list = sorted( [j.replace('\n', '') for j in image_list_clean if '.jp2' in j]) jp2_band_list = sorted( [i for i in jp2_list if i.split('_')[-1][0:3] in valid_bands]) jp2_single_image = [ j.replace('\n', '') for j in image_list_clean if valid_bands[0] + '.jp2' in j ][0] cloud_cover_gml = [ j.replace('\n', '') for j in image_list_clean if 'CLOUDS' in j ][0] year = jp2_single_image.split('_')[-2][0:4] month = jp2_single_image.split('_')[-2][4:6] day = jp2_single_image.split('_')[-2][6:8] dir_folder, cloud_folder = create_dirs(tile_folder_base, tile_name, year, month, valid_bands) cloud_path = os.path.join( cloud_folder, 'cloud_cover_polygons_{}_{}_{}.shp'.format(year, month, day)) tile_template = '/Volumes/Conlon Backup 2TB/sentinel_imagery/tile_template_tifs/' \ 'pixel_{}m/template_{}.tif'.format(pixel_size, tile_name) with rasterio.open(tile_template, 'r') as band_dest: metadata = band_dest.meta.copy() for file in jp2_band_list: band = file.split('_')[-1][0:3] band_folder = os.path.join(dir_folder, band) previously_saved_images = glob.glob(band_folder + '/*.tif') save_file_str = '{}_{}_{}_{}.tif'.format(year, month, day, band) save_file = os.path.join(band_folder, save_file_str) save_new_file = True print(save_file) if os.path.exists(save_file): with rasterio.open(save_file, 'r', driver='GTiff') as saved_img: print(np.max(saved_img.read())) if np.max(saved_img.read()) > 0: save_new_file = False print(save_new_file) if save_new_file: with rasterio.open( file, 'r', driver='JP2OpenJPEG', ) as band_src: print('before reproject: {}'.format(file)) with rasterio.open(save_file, 'w', **metadata) as dest_jp2: reproject(source=rasterio.band(band_src, 1), destination=rasterio.band(dest_jp2, 1), resampling=Resampling.nearest) print('after reproject') cloud_file = os.path.join(tile_folder, cloud_path) if not os.path.exists(cloud_file): with fiona.open(cloud_cover_gml, 'r') as src_cc: with fiona.open(cloud_file, 'w', crs=src_cc.crs, driver='ESRI Shapefile', schema=src_cc.schema) as output: for f in src_cc: output.write(f)
resolution=resolution) kwargs = src.meta.copy() kwargs.update({ 'crs': dst_crs, 'transform': transform, 'width': width, 'height': height, 'nodata':-9999, 'compress':'LZW', }) with rio.open(dst_dataset02, 'w', **kwargs) as dst02: for i in range(1, src.count+1): reproject( source=rio.band(src, i), destination=rio.band(dst02, i), src_transform=src.transform, src_crs=src.crs, src_nodata=-9999, dst_transform=transform, dst_crs=dst_crs, dst_nodata=-9999, dst_resolution=resolution, resampling=Resampling.nearest, ) with rio.open(dst_dataset02) as dst02: out_img, out_transform = mask(dataset=dst02, shapes=shapes, crop=True) out_meta = dst02.meta.copy() out_meta.update({"height": out_img.shape[1], "width": out_img.shape[2],
import numpy as np import rasterio from rasterio.warp import calculate_default_transform, reproject, Resampling import sys dst_crs = 'EPSG:32606' input_ = sys.argv[1] output = sys.argv[2] with rasterio.open(input_) as src: transform, width, height = calculate_default_transform( src.crs, dst_crs, src.width, src.height, *src.bounds) kwargs = src.meta.copy() kwargs.update({ 'crs': dst_crs, 'transform': transform, 'width': width, 'height': height }) with rasterio.open(output, 'w', **kwargs) as dst: for i in range(1, src.count + 1): reproject(source=rasterio.band(src, i), destination=rasterio.band(dst, i), src_transform=src.transform, src_crs=src.crs, dst_transform=transform, dst_crs=dst_crs, resampling=Resampling.nearest)
def align_rasters(rasters, template, outputdir, method="Resampling.nearest"): """Aligns a list of rasters (paths to files) to a template raster. The rasters to that are to be realigned are assumed to represent single band raster files. Nodata values are also reclassified to the template raster's nodata values Args ---- rasters : list, str List containing file paths to multiple rasters that are to be realigned. template : str File path to raster that is to be used as a template to transform the other rasters to. outputdir : str Directory to output the realigned rasters. This should not be the existing directory unless it is desired that the existing rasters to be realigned should be overwritten. method : str Resampling method to use. One of the following: Resampling.average, Resampling.bilinear, Resampling.cubic, Resampling.cubic_spline, Resampling.gauss, Resampling.lanczos, Resampling.max, Resampling.med, Resampling.min, Resampling.mode, Resampling.nearest, Resampling.q1, Resampling.q3 """ # check resampling methods methods = dir(rasterio.enums.Resampling) methods = [i for i in methods if i.startswith('__') is False] methods = ['Resampling.' + i for i in methods] if method not in methods: raise ValueError('Invalid resampling method: ' + method + os.linesep + 'Valid methods are: ' + str(methods)) # open raster to be used as the template and create numpy array template = rasterio.open(template) kwargs = template.meta.copy() for raster in rasters: output = os.path.join(outputdir, os.path.basename(raster)) with rasterio.open(raster) as src: with rasterio.open(output, 'w', **kwargs) as dst: reproject(source=rasterio.band(src, 1), destination=rasterio.band(dst, 1), dst_transform=template.transform, dst_nodata=template.nodata, dst_crs=template.nodata) template.close() return ()