def test_dimensions_missing_params(): """dst_width and dst_height must be specified together""" with pytest.raises(ValueError): calculate_default_transform( 'epsg:4326', 'epsg:3857', width=1, height=1, gcps=[1], resolution=1, dst_width=1, dst_height=None) with pytest.raises(ValueError): calculate_default_transform( 'epsg:4326', 'epsg:3857', width=1, height=1, gcps=[1], resolution=1, dst_width=None, dst_height=1)
def reproject(fin, fout, logger, crs='EPSG:4326'): """ Reproject file using GCPs into a known projection """ ''' # TODO - combine cogify with warping if possible envs = { "driver": "GTiff", "interleave": "pixel", "tiled": True, "blockxsize": 512, "blockysize": 512, "compress": "DEFLATE", } ''' logger.debug('Reprojecting to %s: %s into %s' % (crs, fin, fout)) with rasterio.open(fin) as src: if src.crs: transform, width, height = calculate_default_transform( src.crs, crs, src.width, src.height, *src.bounds, ) else: # use GCPs transform, width, height = calculate_default_transform( src.crs, crs, src.width, src.height, gcps=src.gcps[0], ) kwargs = src.meta.copy() kwargs.update({ 'crs': crs, 'transform': transform, 'width': width, 'height': height }) with rasterio.open(fout, '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=crs, resampling=Resampling.nearest)
def create_image_source(origin_uri, source_uri, image_folder, order, tile_dim): with rasterio.drivers(): with rasterio.open(source_uri) as src: shape = src.shape res = src.res bounds = src.bounds (ll_transform, ll_cols, ll_rows) = calculate_default_transform( src.crs, "EPSG:4326", src.shape[0], src.shape[1], src.bounds.left, src.bounds.bottom, src.bounds.right, src.bounds.top, ) w, n = ll_transform.xoff, ll_transform.yoff e, s = ll_transform * (ll_cols, ll_rows) ll_bounds = [w, s, e, n] (wm_transform, _, _) = calculate_default_transform( src.crs, "EPSG:3857", src.shape[0], src.shape[1], src.bounds.left, src.bounds.bottom, src.bounds.right, src.bounds.top, ) resolution = max(abs(wm_transform[0]), abs(wm_transform[4])) zoom = get_zoom(resolution, tile_dim) min_tile = mercantile.tile(ll_bounds[0], ll_bounds[3], zoom) max_tile = mercantile.tile(ll_bounds[2], ll_bounds[1], zoom) return ImageSource( origin_uri=origin_uri, source_uri=source_uri, src_bounds=src.bounds, src_shape=src.shape, src_crs=src.crs, zoom=zoom, ll_bounds=ll_bounds, tile_bounds=[min_tile.x, min_tile.y, max_tile.x, max_tile.y], image_folder=image_folder, order=order, )
def test_target_aligned_pixels(): """Issue 853 has been resolved""" with rasterio.open('tests/data/world.rgb.tif') as src: source = src.read(1) profile = src.profile.copy() dst_crs = {'init': 'epsg:3857'} with rasterio.Env(CHECK_WITH_INVERT_PROJ=False): # Calculate the ideal dimensions and transformation in the new crs dst_affine, dst_width, dst_height = calculate_default_transform( src.crs, dst_crs, src.width, src.height, *src.bounds) dst_affine, dst_width, dst_height = aligned_target(dst_affine, dst_width, dst_height, 100000.0) profile['height'] = dst_height profile['width'] = dst_width out = np.empty(shape=(dst_height, dst_width), dtype=np.uint8) reproject( source, out, src_transform=src.transform, src_crs=src.crs, dst_transform=dst_affine, dst_crs=dst_crs, resampling=Resampling.nearest) # Check that there is no black borders assert out[:, 0].all() assert out[:, -1].all() assert out[0, :].all() assert out[-1, :].all()
def test_resample_no_invert_proj(method): """Nearest and bilinear should produce valid results with CHECK_WITH_INVERT_PROJ = False """ if not supported_resampling(method): pytest.skip() with rasterio.Env(CHECK_WITH_INVERT_PROJ=False): with rasterio.open('tests/data/world.rgb.tif') as src: source = src.read(1) profile = src.profile.copy() dst_crs = {'init': 'EPSG:32619'} # Calculate the ideal dimensions and transformation in the new crs dst_affine, dst_width, dst_height = calculate_default_transform( src.crs, dst_crs, src.width, src.height, *src.bounds) profile['height'] = dst_height profile['width'] = dst_width out = np.empty(shape=(dst_height, dst_width), dtype=np.uint8) # see #614, some resamplin methods succeed but produce blank images out = np.empty(src.shape, dtype=np.uint8) reproject( source, out, src_transform=src.transform, src_crs=src.crs, dst_transform=dst_affine, dst_crs=dst_crs, resampling=method) assert out.mean() > 0
def test_rasterio_vrt_with_transform_and_size(self): # Test open_rasterio() support of WarpedVRT with transform, width and # height (issue #2864) with create_tmp_geotiff() as (tmp_file, expected): with rasterio.open(tmp_file) as src: # Estimate the transform, width and height # for a change of resolution # tmp_file initial res is (1000,2000) (default values) trans, w, h = calculate_default_transform(src.crs, src.crs, src.width, src.height, resolution=500, *src.bounds) with rasterio.vrt.WarpedVRT(src, transform=trans, width=w, height=h) as vrt: expected_shape = (vrt.width, vrt.height) expected_res = vrt.res expected_transform = vrt.transform with xr.open_rasterio(vrt) as rds: actual_shape = (rds.sizes["x"], rds.sizes["y"]) actual_res = rds.res actual_transform = Affine(*rds.transform) assert actual_res == expected_res assert actual_shape == expected_shape assert actual_transform == expected_transform
def reproject_multiband(self, file_name, dst_crs): with Env(CHECK_WITH_INVERT_PROJ=True): with rasopen(self.temp_file) as src: profile = src.profile dst_affine, dst_width, dst_height = calculate_default_transform( src.crs, dst_crs, src.width, src.height, *src.bounds) profile.update({ 'crs': dst_crs, 'transform': dst_affine, 'width': dst_width, 'height': dst_height }) with rasopen(file_name, 'w', **profile) as dst: for i in range(1, src.count + 1): src_array = src.read(i) dst_array = empty((dst_height, dst_width), dtype=uint8) reproject(src_array, src_crs=src.crs, src_transform=src.transform, destination=dst_array, dst_transform=dst_affine, dst_crs=dst_crs, resampling=Resampling.nearest, num_threads=2) dst.write(dst_array, i)
def reproject_like(this, reproject_this): dst = MemoryFile() d_transform, d_width, d_height = calculate_default_transform( reproject_this.crs, this.crs, reproject_this.width, reproject_this.height, *reproject_this.bounds) dst_profile = reproject_this.profile.copy() dst_profile.update({ "driver": "GTiff", "crs": this.crs, "transform": d_transform, "width": d_width, "height": d_height, }) # with rio.open(dst, 'w', **dst_profile) as dst_file: reproject(source=reproject_this.read(1), destination=rio.band(dst_file, 1), src_transform=reproject_this.transform, src_crs=reproject_this.crs, dst_transform=d_transform, dst_crs=this.crs, resampling=Resampling.bilinear) dst.seek(0) return dst.open()
def reproject_et(inpath, outpath, new_crs): """ reprojects created reprojected output image from input inputted image :param inpath: String, file path of input image to be reprojected :param outpath: String, file path of output image to be created :param new_crs: String, Projection system to be reprojected to """ dst_crs = new_crs # CRS for web Mercator with rasterio.open(inpath) 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(outpath, '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 mosaicraster(rasters, date, proj): filename = date + '_mosaic.tif' # read in rasters raster_objs = [] for raster in rasters: src = rasterio.open(raster, driver='JP2OpenJPEG') raster_objs.append(src) # reproject to a common projection for raster in raster_objs: transform, width, height = calculate_default_transform( raster.crs, proj, raster.width, raster.height, *raster.bounds) reproj = np.zeros((width, height), raster.dtypes[0]) reproj, reproj_transform = reproject( source=rasterio.band(raster, 1), #source destination=reproj, #destination src_transform=raster.transform, src_crs=raster.crs, dst_transform=transform, dst_crs=proj, resampling=Resampling.nearest, drtype=raster.dtypes[0]) # write a temporary file for making a mosaic raster_reproj = rasterio.open(raster.name[:-4] + 'temp.jp2', 'w+', driver='JP2OpenJPEG', width=width, height=height, count=1, crs=proj, transform=transform, dtype=raster.dtypes[0]) raster_reproj.write(reproj, 1) raster_objs[raster_objs.index(raster)] = raster_reproj # merge rasters and save file mosaic, out_trans = merge(raster_objs) out_meta = raster_objs[0].meta out_meta.update({ "driver": "GTiff", "height": mosaic.shape[1], "width": mosaic.shape[2], "transform": out_trans }) with rasterio.open(filename, 'w', **out_meta) as dest: dest.write(mosaic) # close all open files and delete temps for raster in raster_objs: raster.close() # if 'temp' in raster.name: # os.remove(raster.name) return (filename)
def test_calculate_default_transform_dimensions(): with rasterio.open("tests/data/RGB.byte.tif") as src: dst_width, dst_height = (113, 103) target_transform = Affine( 0.02108612597535966, 0.0, -78.95864996545055, 0.0, -0.0192823863230055, 25.550873767433984, ) dst_transform, width, height = calculate_default_transform( src.crs, CRS.from_epsg(4326), src.width, src.height, *src.bounds, dst_width=dst_width, dst_height=dst_height ) assert dst_transform.almost_equals(target_transform) assert width == dst_width assert height == dst_height
def convert_tif_to_wgs84(input, output): '''convert from input to output to wgs84 CRS''' print(f'convert| {input}\n\t->{output}') dst_crs = 'EPSG:4326' with rio_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 rio_open(output, 'w', **kwargs) as dst: for i in range(1, src.count + 1): reproject( source=band(src, i), destination=band(dst, i), src_transform=src.transform, src_crs=src.crs, dst_transform=transform, dst_crs=dst_crs, resampling=Resampling.nearest)
def test_resample_default_invert_proj(method): """Nearest and bilinear should produce valid results with the default Env """ with rasterio.open('tests/data/world.rgb.tif') as src: source = src.read(1) profile = src.profile.copy() dst_crs = {'init': 'EPSG:32619'} # Calculate the ideal dimensions and transformation in the new crs dst_affine, dst_width, dst_height = calculate_default_transform( src.crs, dst_crs, src.width, src.height, *src.bounds) profile['height'] = dst_height profile['width'] = dst_width out = np.empty(shape=(dst_height, dst_width), dtype=np.uint8) out = np.empty(src.shape, dtype=np.uint8) reproject(source, out, src_transform=src.transform, src_crs=src.crs, dst_transform=dst_affine, dst_crs=dst_crs, resampling=method) assert out.mean() > 0
def reproject_to_geographic( image: xr.DataArray ) -> xr.DataArray: with rasterio.Env(): src_shape = image.shape src_transform = image.transform src_crs = CRS( {'init': image.crs.split("=")[1].upper() } ) source: np.ndarray = image.data xaxis: np.ndarray = image.coords[image.dims[1]].data yaxis: np.ndarray = image.coords[image.dims[0]].data dst_shape = src_shape dst_crs = CRS( {'init': 'EPSG:4326'} ) dst_transform = calculate_default_transform(src_crs, dst_crs, dst_shape[1], dst_shape[0], left=src_transform[2], bottom=src_transform[5] + src_transform[3] * dst_shape[1] + src_transform[4] * dst_shape[0], right=src_transform[2] + src_transform[0] * dst_shape[1] + src_transform[1] * dst_shape[0], top=src_transform[5])[0] destination = np.zeros(dst_shape, np.uint8) reproject( source, destination, src_transform=src_transform, src_crs=src_crs, dst_transform=dst_transform, dst_crs=dst_crs, resampling=Resampling.nearest) (lons, lats) = transform( Proj(**src_crs), Proj(**dst_crs), xaxis, yaxis ) result = xr.DataArray(destination, dims=['lat', 'lon'], coords=dict(lat=np.array(lats), lon=np.array(lons) )) result.attrs['transform'] = dst_transform result.attrs['crs'] = dst_crs return result
def reproject2(src, data, resolution, resampling): meta = src.meta.copy() if not src.crs.is_valid: crs = src.crs.from_string(u'epsg:4326') else: crs = src.crs newaff, width, \ height = rwarp.calculate_default_transform(crs, crs, src.width, src.height, *src.bounds, resolution=resolution) out = ma.empty((src.count, int(height), int(width)), dtype=meta['dtype']) newarr = np.empty((int(height), int(width)), dtype=meta['dtype']) meta.update({'transform': newaff, 'width': int(width), 'height': int(height), 'nodata': src.nodata}) for idx in range(data.shape[0]): rwarp.reproject(source = data[idx], destination = newarr, src_transform = src.transform, dst_transform = newaff, src_crs = src.crs, dst_crs = crs, src_nodata = src.nodatavals[idx], dst_nodata = src.nodatavals[idx], resampling = resampling) out[idx] = ma.masked_values(newarr, src.nodatavals[idx]) return meta, out
def get_transform(r1, r2): # Get the geo transform using r1 resolution but r2 bounds dst = rasterio.open(r1) src = rasterio.open(r2) #src_bounds = np.around(src.bounds, decimals=3) affine, width, height = rwarp.calculate_default_transform( src.crs, dst.crs, src.width, src.height, *src.bounds, resolution=dst.res) ul = affine * (0.5, 0.5) lr = affine * (width - 0.5, height - 0.5) lats = np.linspace(ul[1], lr[1], height) lons = np.linspace(ul[0], lr[0], width) cratio = np.prod(dst.res) / np.prod(src.res) #cratio = 1.0 static = rasterio.open(utils.luh2_static('carea')) carea = static.read(1, window=static.window(*src.bounds)) rcs = (np.sin(np.radians(lats + dst.res[0] / 2.0)) - np.sin(np.radians(lats - dst.res[0] / 2.0))) * \ (dst.res[0] * np.pi/180) * earth_radius() ** 2 / 1e6 #carea *= rcs.reshape(carea.shape[0], 1) return affine, lats, lons, dst.res, cratio # / carea
def _reproject(input_data, input_type, input_crs, target_crs, dest_path, resampling_method='bicubic'): input_crs = _check_crs(input_crs) target_crs = _check_crs(target_crs) if input_type == 'vector': output = input_data.to_crs(target_crs) if dest_path is not None: output.to_file(dest_path, driver='GeoJSON') elif input_type == 'raster': if isinstance(input_data, rasterio.DatasetReader): transform, width, height = calculate_default_transform( input_crs.to_wkt("WKT1_GDAL"), target_crs.to_wkt("WKT1_GDAL"), input_data.width, input_data.height, *input_data.bounds ) kwargs = input_data.meta.copy() kwargs.update({'crs': target_crs.to_wkt("WKT1_GDAL"), 'transform': transform, 'width': width, 'height': height}) if dest_path is not None: with rasterio.open(dest_path, 'w', **kwargs) as dst: for band_idx in range(1, input_data.count + 1): rasterio.warp.reproject( source=rasterio.band(input_data, band_idx), destination=rasterio.band(dst, band_idx), src_transform=input_data.transform, src_crs=input_data.crs, dst_transform=transform, dst_crs=target_crs.to_wkt("WKT1_GDAL"), resampling=getattr(Resampling, resampling_method) ) output = rasterio.open(dest_path) input_data.close() else: output = np.zeros(shape=(height, width, input_data.count)) for band_idx in range(1, input_data.count + 1): rasterio.warp.reproject( source=rasterio.band(input_data, band_idx), destination=output[:, :, band_idx-1], src_transform=input_data.transform, src_crs=input_data.crs, dst_transform=transform, dst_crs=target_crs, resampling=getattr(Resampling, resampling_method) ) elif isinstance(input_data, gdal.Dataset): if dest_path is not None: gdal.Warp(dest_path, input_data, dstSRS='EPSG:' + str(target_crs.to_epsg())) output = gdal.Open(dest_path) else: raise ValueError('An output path must be provided for ' 'reprojecting GDAL datasets.') return output
def warp(fileinname, fileoutname, dst_crs='EPSG:4326'): import numpy as np from rasterio.warp import calculate_default_transform, reproject, Resampling with rasterio.open(fileinname) 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(fileoutname, '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) print('Done.') return
def test_calculate_default_transform_dimensions(): with rasterio.open("tests/data/RGB.byte.tif") as src: dst_width, dst_height = (113, 103) target_transform = Affine( 0.02108612597535966, 0.0, -78.95864996545055, 0.0, -0.0192823863230055, 25.550873767433984, ) dst_transform, width, height = calculate_default_transform( src.crs, {"init": "epsg:4326"}, src.width, src.height, *src.bounds, dst_width=dst_width, dst_height=dst_height ) assert dst_transform.almost_equals(target_transform) assert width == dst_width assert height == dst_height
def reproject_raster(memfile: MemoryFile, dst_crs: str, src_crs: str = WGS84) -> MemoryFile: """Reproject raster with CRS src_crs to new CRS dst_crs.""" print(f'Reprojecting raster from {src_crs} to {dst_crs}.') with memfile.open() as src: print(f'Source raster has shape {src.shape}.') transform, width, height = calculate_default_transform( src_crs, dst_crs, src.width, src.height, *src.bounds) kwargs = src.profile.copy() kwargs.update({ 'crs': dst_crs, 'transform': transform, 'width': width, 'height': height }) dst_memfile = MemoryFile() with dst_memfile.open(**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.bilinear) print(f'Reprojected raster has shape {dst.shape}.') return dst_memfile
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 test_resample_default_invert_proj(method): """Nearest and bilinear should produce valid results with the default Env """ with rasterio.open("tests/data/world.rgb.tif") as src: source = src.read(1) profile = src.profile.copy() dst_crs = {"init": "epsg:32619"} # Calculate the ideal dimensions and transformation in the new crs dst_affine, dst_width, dst_height = calculate_default_transform( src.crs, dst_crs, src.width, src.height, *src.bounds ) profile["height"] = dst_height profile["width"] = dst_width out = np.empty(shape=(dst_height, dst_width), dtype=np.uint8) out = np.empty(src.shape, dtype=np.uint8) reproject( source, out, src_transform=src.transform, src_crs=src.crs, dst_transform=dst_affine, dst_crs=dst_crs, resampling=method, ) assert out.mean() > 0
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 reproject_et(inpath, outpath, new_crs, platform): dst_crs = new_crs if platform == 1: driv = 'JP2OpenJPEG' if platform == 0: driv = 'Gtiff' print(driv) with rio.open(inpath, driver=driv) as src: transform, width, height = calculate_default_transform( src.crs, dst_crs, src.width, src.height, *src.bounds) kwargs = src.meta.copy() kwargs.update({ 'driver': 'Gtiff', 'crs': dst_crs, 'transform': transform, 'width': width, 'height': height }) with rio.open(outpath, 'w', **kwargs) as dst: for i in range(1, src.count + 1): reproject(source=rio.band(src, i), destination=rio.band(dst, i), src_transform=src.transform, src_crs=src.crs, dst_transform=transform, dst_crs=dst_crs, resampling=Resampling.nearest)
def _get_zooms(self): """Calculate raster min/max zoom level.""" def _zoom_for_pixelsize(pixel_size, max_z=24): """Get zoom level corresponding to a pixel resolution.""" for z in range(max_z): matrix = self.tms.matrix(z) if pixel_size > self.tms._resolution(matrix): return max(0, z - 1) # We don't want to scale up return max_z - 1 dst_affine, w, h = calculate_default_transform( self.dataset.crs, self.tms.crs, self.dataset.width, self.dataset.height, *self.dataset.bounds, ) resolution = max(abs(dst_affine[0]), abs(dst_affine[4])) max_zoom = _zoom_for_pixelsize(resolution) matrix = self.tms.tileMatrix[0] ovr_resolution = (resolution * max(h, w) / max(matrix.tileWidth, matrix.tileHeight)) min_zoom = _zoom_for_pixelsize(ovr_resolution) self.minzoom = self.minzoom or min_zoom self.maxzoom = self.maxzoom or max_zoom return
def reproject_to_utm(viirs_path: str, epsg_code: str, write_directory: str) -> None: """ This function reprojects a VIIRS raster from native-WGS84 to a UTM CRS e.g UTM 32N :param viirs_path: path to VIIRS image :param epsg_code: EPSG coordinate system code :param write_directory: Directory to save reprojected raster to :return: Void """ with rio.open(viirs_path, "r") as source: transform, width, height, = calculate_default_transform( source.crs, epsg_code, source.width, source.height, *source.bounds) raster_metadata = source.meta.copy() raster_metadata.update({ "crs": epsg_code, "transform": transform, "width": width, "height": height }) utils.write_raster_reprojection( path_to_write= f"{write_directory}{viirs_path.split('/')[-1].split('.tif')[0]}_utm.tif", epsg_code=epsg_code, metadata=raster_metadata, source=source, ) source.close() return
def reproject_dtm(path_in,path_out,src_crs,dst_crs): with rasterio.open(path_in) 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(path_out, '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) dst.close() print("reprojected dtm geotif saved as",path_out)
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_vrt_transform(src, bounds, bounds_crs='epsg:3857'): """Calculate VRT transform. Attributes ---------- src : rasterio.io.DatasetReader Rasterio io.DatasetReader object bounds : list Bounds (left, bottom, right, top) bounds_crs : str Coordinate reference system string (default "epsg:3857") Returns ------- vrt_transform: Affine Output affine transformation matrix vrt_width, vrt_height: int Output dimensions """ dst_transform, _, _ = calculate_default_transform(src.crs, bounds_crs, src.width, src.height, *src.bounds) w, s, e, n = bounds vrt_width = math.ceil((e - w) / dst_transform.a) vrt_height = math.ceil((s - n) / dst_transform.e) vrt_transform = transform.from_bounds(w, s, e, n, vrt_width, vrt_height) return vrt_transform, vrt_width, vrt_height
def reproject_raster_by_epsg(input_f, output_f, epsg): ''' Reproject a geotiff raster from one epsg to another Args: input_f: Input path to a geotiff output_f: Output location of a reprojected geotiff epsg: Valid projection reference number ''' dst_crs = 'EPSG:{}'.format(epsg) with rasterio.open(input_f) 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_f, '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.bilinear)
def reprojectedRaster(rasterFn,ref_vectorFn): dst_crs=gpd.read_file(ref_vectorFn).crs print(dst_crs) #{'init': 'epsg:4326'} dst_raster_projected=os.path.join(dataFp_1,r"svf_dstRasterProjected_b.tif") a_T = datetime.datetime.now() # dst_crs='EPSG:4326' with rasterio.open(rasterFn) 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, # 'compress': "LZW", 'dtype':rasterio.float32, }) # print(src.count) with rasterio.open(dst_raster_projected, '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 ) b_T = datetime.datetime.now() print("reprojected time span:", b_T-a_T)
def get_max_zoom(src_dst, lat=0.0, tilesize=256): """ Calculate raster max zoom level. Parameters ---------- src: rasterio.io.DatasetReader Rasterio io.DatasetReader object lat: float, optional Center latitude of the dataset. This is only needed in case you want to apply latitude correction factor to ensure consitent maximum zoom level (default: 0.0). tilesize: int, optional Mercator tile size (default: 256). Returns ------- max_zoom: int Max zoom level. """ dst_affine, w, h = calculate_default_transform(src_dst.crs, "epsg:3857", src_dst.width, src_dst.height, *src_dst.bounds) native_resolution = max(abs(dst_affine[0]), abs(dst_affine[4])) # Correction factor for web-mercator projection latitude distortion latitude_correction_factor = math.cos(math.radians(lat)) corrected_resolution = native_resolution * latitude_correction_factor max_zoom = zoom_for_pixelsize(corrected_resolution, tilesize=tilesize) return max_zoom
def reproject_array_to_file(array, profile, dst_crs, save_file): import rasterio from rasterio.io import MemoryFile from rasterio.warp import calculate_default_transform, reproject, Resampling with MemoryFile() as memfile: with memfile.open(**profile) as src: src.write(array) with memfile.open() 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(save_file, '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) return True
def convert(self, source_file_path: str, dest_file_path: str, espg = 4236 ): dst_crs = f'EPSG:{espg}' with rasterio.open( source_file_path ) as src: print( f"PROFILE: {src.profile}" ) src_crs = ''.join(src.crs.wkt.split()) print(f" ---> CRS: {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(dest_file_path, '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 reproject_task(self, girderFile, name, dstCrs, resampleMethod): tempName = getTempFileName(name) dstCrs = str(dstCrs) with rasterio.open(girderFile) as src: affine, width, height = calculate_default_transform( src.crs, dstCrs, src.width, src.height, *src.bounds) kwargs = src.meta.copy() kwargs.update({ 'crs': dstCrs, 'transform': affine, 'affine': affine, 'width': width, 'height': height }) with rasterio.open(tempName, 'w', **kwargs) as dest: for i in range(1, src.count + 1): reproject(source=rasterio.band(src, i), destination=rasterio.band(dest, i), src_transform=affine, src_crs=src.crs, dst_transform=affine, dst_crs=dstCrs, resampling=getattr(Resampling, resampleMethod)) return tempName
def reproject(self, dst_crs, interpolation='nearest'): """ Change coordinate system (projection) of the band. It returns a new BandSample and does not alter the current object 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 interpolation: interpolation type as in rasterio, `nearest`, `bilinear`, `cubic`, `lanzsos` or others Returns: BandSample: a new instance with changed CRS. """ if dst_crs == 'utm': dst_crs = get_utm_zone(self.crs, self.transform, (self.height, self.width)) dst_transform, dst_width, dst_height = calculate_default_transform( self.crs, dst_crs, self.width, self.height, *self.bounds) new_raster = np.empty(shape=(1, dst_height, dst_width), dtype=self.dtype) reproject(self._raster, new_raster, src_transform=self.transform, dst_transform=dst_transform, src_crs=self.crs, dst_crs=dst_crs, resampling=getattr(Resampling, interpolation)) return BandSample(self.name, new_raster, dst_crs, dst_transform, self.nodata)
def project_raster(src_raster, dst_raster, dst_crs, resampling=1, resolution=None, num_threads=2): """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' resampling : int (see rasterio source code: https://github.com/mapbox/rasterio/blob/master/rasterio/enums.py) nearest = 0 bilinear = 1 cubic = 2 cubic_spline = 3 lanczos = 4 average = 5 mode = 6 gauss = 7 max = 8 min = 9 med = 10 q1 = 11 q3 = 12 resolution : tuple of floats (len 2) cell size of the output raster (x resolution, y resolution) """ rasterio = import_rasterio() # check for rasterio from rasterio.warp import calculate_default_transform, reproject with rasterio.open(src_raster) as src: affine, width, height = calculate_default_transform( src.crs, dst_crs, src.width, src.height, *src.bounds, resolution=resolution) 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, num_threads=num_threads)
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 test_gcps_calculate_transform(): src_gcps = [ GroundControlPoint(row=0, col=0, x=156113, y=2818720, z=0), GroundControlPoint(row=0, col=800, x=338353, y=2785790, z=0), GroundControlPoint(row=800, col=800, x=297939, y=2618518, z=0), GroundControlPoint(row=800, col=0, x=115698, y=2651448, z=0)] _, width, height = calculate_default_transform( 'epsg:3857', 'epsg:4326', width=800, height=800, gcps=src_gcps) assert width == 1087 assert height == 895
def test_calculate_default_transform(): target_transform = Affine( 0.0028535715391804096, 0.0, -78.95864996545055, 0.0, -0.0028535715391804096, 25.550873767433984) with rasterio.open('tests/data/RGB.byte.tif') as src: wgs84_crs = {'init': 'EPSG:4326'} dst_transform, width, height = calculate_default_transform( src.crs, wgs84_crs, src.width, src.height, *src.bounds) assert dst_transform.almost_equals(target_transform) assert width == 835 assert height == 696
def __init__(self, left, bottom, right, top, width, height, src_crs, dst_crs): self.width = width self.height = height src_res = float(right - left) / float(width) self.src_transform = Affine(src_res, 0, left, 0, -src_res, top) self.src_crs = src_crs self.dst_crs = dst_crs dt, dw, dh = calculate_default_transform( src_crs, dst_crs, width, height, left, bottom, right, top ) self.dst_transform = dt self.dst_width = dw self.dst_height = dh
def __compute_transform(self, in_raster, new_crs): affine, width, height = calculate_default_transform( in_raster.crs, new_crs, in_raster.width, in_raster.height, *in_raster.bounds ) kwargs = in_raster.meta.copy() kwargs.update({ 'driver':'GTiff', 'crs': new_crs, 'transform': affine, 'affine': affine, 'width': width, 'height': height }) return affine, height, width, kwargs
def test_calculate_default_transform(): target_transform = Affine( 0.0028956983577810586, 0.0, -78.95864996545055, 0.0, -0.0028956983577810586, 25.550873767433984 ) with rasterio.drivers(): with rasterio.open('tests/data/RGB.byte.tif') as src: l, b, r, t = src.bounds wgs84_crs = {'init': 'EPSG:4326'} dst_transform, width, height = calculate_default_transform( l, b, r, t, src.width, src.height, src.crs, wgs84_crs) assert dst_transform.almost_equals(target_transform) assert width == 824 assert height == 686
def test_calculate_default_transform_single_resolution(): with rasterio.open('tests/data/RGB.byte.tif') as src: target_resolution = 0.1 target_transform = Affine( target_resolution, 0.0, -78.95864996545055, 0.0, -target_resolution, 25.550873767433984 ) dst_transform, width, height = calculate_default_transform( src.crs, {'init': 'EPSG:4326'}, src.width, src.height, *src.bounds, resolution=target_resolution ) assert dst_transform.almost_equals(target_transform) assert width == 24 assert height == 20
def get_zoom(input, dst_crs="EPSG:3857"): input = input.replace("s3://", "/vsicurl/http://s3.amazonaws.com/") with rasterio.drivers(): with rasterio.open(input) as src: # Compute the geographic bounding box of the dataset. (west, east), (south, north) = transform( src.crs, "EPSG:4326", src.bounds[::2], src.bounds[1::2]) affine, _, _ = calculate_default_transform(src.crs, dst_crs, src.width, src.height, *src.bounds, resolution=None) # grab the lowest resolution dimension resolution = max(abs(affine[0]), abs(affine[4])) return int(round(math.log((2 * math.pi * 6378137) / (resolution * CHUNK_SIZE)) / math.log(2)))
def to_srs(self, srs, resolution=None, src_nodata=None, dst_nodata=None, resampling=Resampling.nearest): affine, width, height = calculate_default_transform(self.crs, srs, self.shape[1], self.shape[0], *self.bounds, resolution=resolution) if dst_nodata is None: dst_nodata = self.fill_value destination = RectifiedGrid(np.zeros([height, width], self.dtype), srs, affine, fill_value=dst_nodata) return self.to_srs_like(destination, src_nodata, dst_nodata, resampling)
def test_resample_no_invert_proj(method): """Nearest and bilinear should produce valid results with CHECK_WITH_INVERT_PROJ = False """ if method in ( Resampling.bilinear, Resampling.cubic, Resampling.cubic_spline, Resampling.lanczos, ): pytest.xfail( reason="Some resampling methods succeed but produce blank images. " "See https://github.com/mapbox/rasterio/issues/614" ) with rasterio.Env(CHECK_WITH_INVERT_PROJ=False): with rasterio.open("tests/data/world.rgb.tif") as src: source = src.read(1) profile = src.profile.copy() dst_crs = {"init": "epsg:32619"} # Calculate the ideal dimensions and transformation in the new crs dst_affine, dst_width, dst_height = calculate_default_transform( src.crs, dst_crs, src.width, src.height, *src.bounds ) profile["height"] = dst_height profile["width"] = dst_width out = np.empty(shape=(dst_height, dst_width), dtype=np.uint8) # see #614, some resampling methods succeed but produce blank images out = np.empty(src.shape, dtype=np.uint8) reproject( source, out, src_transform=src.transform, src_crs=src.crs, dst_transform=dst_affine, dst_crs=dst_crs, resampling=method, ) assert out.mean() > 0
def test_calculate_default_transform_multiple_resolutions(): with rasterio.drivers(): with rasterio.open('tests/data/RGB.byte.tif') as src: l, b, r, t = src.bounds target_resolution = (0.2, 0.1) target_transform = Affine( target_resolution[0], 0.0, -78.95864996545055, 0.0, -target_resolution[1], 25.550873767433984 ) dst_transform, width, height = calculate_default_transform( l, b, r, t, src.width, src.height, src.crs, {'init': 'EPSG:4326'}, resolution=target_resolution ) assert dst_transform.almost_equals(target_transform) assert width == 12 assert height == 20
def test_project(): data = np.array([[0,0,1,0,0], [0,0,1,0,0], [1,1,1,1,1], [0,0,1,0,0], [0,0,1,0,0]],dtype=np.int32) geodict = {'xmin':50,'xmax':50.4,'ymin':50,'ymax':50.4,'dx':0.1,'dy':0.1,'nx':5,'ny':5} gd = GeoDict(geodict) grid = GDALGrid(data,gd) projstr = "+proj=utm +zone=40 +north +ellps=WGS84 +datum=WGS84 +units=m +no_defs " newgrid = grid.project(projstr,method='nearest') try: tdir = tempfile.mkdtemp() outfile = os.path.join(tdir,'output.bil') grid.save(outfile) with rasterio.open(outfile) as src: aff = src.transform data = src.read(1) src_crs = CRS().from_string(GeoDict.DEFAULT_PROJ4).to_dict() dst_crs = CRS().from_string(projstr).to_dict() nrows,ncols = data.shape left = aff.xoff top = aff.yoff right,bottom = aff * (ncols-1, nrows-1) dst_transform,width,height = calculate_default_transform(src_crs,dst_crs, ncols,nrows, left,bottom, right,top) destination = np.zeros((height,width)) reproject(data, destination, src_transform=aff, src_crs=src_crs, dst_transform=dst_transform, dst_crs=dst_crs, src_nodata=src.nodata, dst_nodata=np.nan, resampling=Resampling.nearest) x = 1 except: pass finally: shutil.rmtree(tdir)
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 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 test_calculate_default_transform_multiple_resolutions(): with rasterio.open("tests/data/RGB.byte.tif") as src: target_resolution = (0.2, 0.1) target_transform = Affine( target_resolution[0], 0.0, -78.95864996545055, 0.0, -target_resolution[1], 25.550873767433984, ) dst_transform, width, height = calculate_default_transform( src.crs, {"init": "epsg:4326"}, src.width, src.height, *src.bounds, resolution=target_resolution ) assert dst_transform.almost_equals(target_transform) assert width == 12 assert height == 20
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 warp(ctx, files, output, driver, like, dst_crs, dimensions, src_bounds, x_dst_bounds, bounds, res, resampling, src_nodata, dst_nodata, threads, check_invert_proj, force_overwrite, creation_options): """ 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 ignored. \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 ignored. 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 """ verbosity = (ctx.obj and ctx.obj.get('verbosity')) or 1 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 with rasterio.Env(CPL_DEBUG=verbosity > 2, CHECK_WITH_INVERT_PROJ=check_invert_proj): with rasterio.open(files[0]) as src: l, b, r, t = src.bounds out_kwargs = src.meta.copy() out_kwargs['driver'] = driver # Sort out the bounds options. src_bounds = bounds or src_bounds dst_bounds = x_dst_bounds if src_bounds and dst_bounds: raise click.BadParameter( "Source 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.affine 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) else: try: dst_transform, dst_width, dst_height = calculate_default_transform( src.crs, dst_crs, src.width, src.height, *src.bounds, resolution=res) 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.affine.a, -src.affine.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.affine 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, 'affine': dst_transform, 'width': dst_width, 'height': dst_height }) out_kwargs.update(**creation_options) with rasterio.open(output, '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, src_nodata=src_nodata, dst_transform=out_kwargs['transform'], dst_crs=out_kwargs['crs'], dst_nodata=dst_nodata, resampling=resampling, num_threads=threads)
def test_gcps_bounds_exclusivity(): """gcps and bounds parameters are mutually exclusive""" with pytest.raises(ValueError): calculate_default_transform( 'epsg:4326', 'epsg:3857', width=1, height=1, left=1.0, gcps=[1])
def reproject_tif(src_tif_path_remote, src_tif_path, data_name, dst_crs): """Reproject tif to a destination CRS Reprojects a GeoTiff to a new CRS using rasterio, saving the reprojected GeoTiff to a new temporary location. Args: src_tif_path_remote (string): remote path of the tiff src_tif_path (string): local directory of unprocessed GeoTif data_name (string): string used to prefix new GeoTiffs to keep them somewhat identifiable dst_crs (string): New coordinate reference system to reproject GeoTiff. Currently only supports strings of the format `EPSG:XXXX` NOTE: The `compress` and `optimize_size` options in the `reproject` function for `rasterio` are necessary to get around a limitation of `gdal_warp` where the reprojected GeoTiff is not compressed. There is a performance penalty in some cases, but has so far been unoticeable for the expected workload in Azavea Data Hub. Nevertheless, the performance penalty is likely insignifcant compared to the additional bandwidth/time spent moving files to/from s3 due to not compressing them. See https://trac.osgeo.org/gdal/wiki/UserDocs/GdalWarp#GeoTIFFoutput-coCOMPRESSisbroken for more information """ regex = r"""3IMERG\.(\d\d\d\d)(\d\d)(\d\d)""" regex2 = r"""(\d\d\d\d)\.(\d\d)\.(\d\d)""" filename = os.path.basename(src_tif_path_remote) # Get the date m = re.search(regex, filename) if not m: m = re.search(regex2, filename) if not m: raise Exception("NO TIME in %s" % src_tif_path_remote) basename = "3IMERG.%s%s%s" % (m.group(1), m.group(2), m.group(3)) prefix = '-'.join(filter(lambda x: x, [data_name, basename])) _, dst_tif_path = tempfile.mkstemp(prefix=prefix, suffix=".tif") with rasterio.open(src_tif_path) as src: ## HACKED IN CODE ## We need to clip the tiles so that they can fit inside the EPSG:3857 world bounds ## We'll do so by first clipping the bounds, and then computin the transform xmin, ymin, xmax, ymax = (-180.0, -85.06, 180.0, 85.06) cell_width = (src.bounds.right - src.bounds.left) / src.width cell_height = (src.bounds.top - src.bounds.bottom) / src.height clipped_width = (xmax - xmin) / cell_width clipped_height = (ymax - ymin) / cell_height affine, width, height = calculate_default_transform( src.crs, dst_crs, clipped_width, clipped_height, xmin, ymin, xmax, ymax) kwargs = src.meta.copy() kwargs.update({ 'crs': dst_crs, 'transform': affine, 'affine': affine, 'width': width, 'height': height, 'compress': 'deflate' }) with rasterio.open(dst_tif_path, 'w', **kwargs) as dst: dst.update_tags(**src.tags()) 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, optimize_size='yes' # necessary to keep size small, performance penalty ) return dst_tif_path
def test_issue1131(): """Confirm that we don't run out of memory""" transform, w, h = calculate_default_transform(CRS.from_epsg(4326), CRS.from_epsg(3857), 455880, 454450, 13.0460235139, 42.6925552354, 13.2511695428, 42.8970561511) assert (w, h) == (381595, 518398)
def test_resolution_dimensions_exclusivity(): """resolution and dimensions parameters are mutually exclusive""" with pytest.raises(ValueError): calculate_default_transform( 'epsg:4326', 'epsg:3857', width=1, height=1, gcps=[1], resolution=1, dst_width=1, dst_height=1)
def test_one_of_gcps_bounds(): """at least one of gcps or bounds parameters must be provided""" with pytest.raises(ValueError): calculate_default_transform( 'epsg:4326', 'epsg:3857', width=1, height=1)