wkt = src_ds.GetProjection() if wkt != '': dst_ds.SetProjection(wkt) dst_ds.SetGeoTransform(src_ds.GetGeoTransform()) dstband = dst_ds.GetRasterBand(1) CopyBand(srcband, dstband) else: dstband = srcband # ============================================================================= # Invoke algorithm. # ============================================================================= if quiet_flag: prog_func = None else: prog_func = gdal.TermProgress result = gdal.FillNodata(dstband, maskband, max_distance, smoothing_iterations, options, callback=prog_func) src_ds = None dst_ds = None mask_ds = None
def warp_ds(ds, src_crs, new_cell_size=None, dst_crs=None, var_name='rain', xname='longitude', yname='latitude', tname='time', resampling_alg=gdal.GRA_CubicSpline): from tqdm import tqdm # todo: not sure what happens if the order of co-ordinates in the source xarray # does not match the order expected here (time, latitude, longitude) x_size, y_size = ds.dims[xname], ds.dims[yname] if not new_cell_size: new_cell_size = (x_size, y_size) if not dst_crs: dst_crs = src_crs time_size = ds.dims[tname] ds_src_transform = get_transform(ds, x_coords=xname, y_coords=yname) west, south, east, north = array_bounds(height=y_size, width=x_size, transform=ds_src_transform) src_ds = create_mem_src(x_size, y_size, ds_src_transform, src_crs) dst_transform, dst_width, dst_height = calculate_default_transform( src_crs=src_crs, dst_crs=dst_crs, width=x_size, height=y_size, left=west, bottom=south, right=east, top=north, resolution=(new_cell_size, new_cell_size)) out_bounds = array_bounds(height=dst_height, width=dst_width, transform=dst_transform) wrapopts = gdal.WarpOptions(xRes=new_cell_size, yRes=new_cell_size, srcSRS=src_crs.to_wkt(), dstSRS=dst_crs.to_wkt(), outputBounds=out_bounds, resampleAlg=resampling_alg, dstNodata=np.nan) new_xs, new_ys = return_coords(dst_transform, dst_width, dst_height) time_values = times = ds.indexes[tname] warped_data = np.zeros((time_size, dst_height, dst_width)) for ti, tvalue in tqdm(list(enumerate(ds.indexes[tname]))): data = ds[var_name][ti, ...].values.copy() src_ds.GetRasterBand(1).WriteArray(data) tb = src_ds.GetRasterBand(1) gdal.FillNodata(tb, maskBand=None, maxSearchDist=6, smoothingIterations=0) _ = tb.ReadAsArray() warp_ras = gdal.Warp(r"/vsimem/wrap_singletimestamp.tiff", src_ds, options=wrapopts) warped_slice = warp_ras.GetRasterBand(1).ReadAsArray().copy() if warped_slice.shape != (dst_height, dst_width): raise ValueError(warped_slice.shape, (dst_height, dst_width)) warped_data[ti, ...] = warped_slice del warp_ras warped_ds = xr.DataArray(warped_data, coords=[times, new_ys, new_xs], dims=[tname, yname, xname]) return warped_ds
def fill_nodata(input_path, mask_path, output_path, max_distance=0, smoothing_iterations=0, options=[], driver="HFA", desired_nodata=-9999, quiet=False): """ This function mimicks the gdal_fillnodata.py script because it's heavily based on it. Basically I just added more logging to fit it into this project. """ logger.info('input: {0}'.format(input_path)) logger.info('mask: {0}'.format(mask_path)) logger.info('output: {0}'.format(output_path)) # Open the MHHW tile as read-only and get the driver GDAL is using to access the data input_fh = gdal.Open(input_path, gdal.GA_ReadOnly) input_driver = input_fh.GetDriver() # Open the mask tile as read-only and get the driver GDAL is using to access the data mask_fh = gdal.Open(mask_path, gdal.GA_ReadOnly) mask_driver = mask_fh.GetDriver() mask_band = mask_fh.GetRasterBand(1) # Get the raster band # Pull Metadata associated with the LIDAR tile so we can create the output raster later geotransform = input_fh.GetGeoTransform() projection = input_fh.GetProjection() cols = input_fh.RasterXSize # Get the number of columns rows = input_fh.RasterYSize # Get the number of rows logger.info(" cols: {0}".format(cols)) logger.info(" rows: {0}".format(rows)) input_data = input_fh.GetRasterBand(1) # Get the raster band original_nodata = input_data.GetNoDataValue( ) # Get the NoData value so we can set our mask logger.info(" original nodata value: {0}".format(original_nodata)) # Create a copy of the data using in the input tile as an example. logger.info(" Creating new raster...") output_driver = gdal.GetDriverByName(driver) # Setup the output driver output_fh = output_driver.Create(output_path, cols, rows, 1, gdal.GDT_CFloat32) output_fh.SetGeoTransform(geotransform) output_fh.SetProjection(projection) output_band = output_fh.GetRasterBand(1) output_band.SetNoDataValue(9) logger.info(" done.") logger.info(" copying band to destination file...") gm_gdal.CopyBand(input_data, output_band) logger.info(" done.") # Suppress progress report if we ask for quiet behavior if quiet: prog_func = None else: prog_func = gdal.TermProgress logger.info(" Running FillNodata()...") result = gdal.FillNodata(output_band, mask_band, max_distance, smoothing_iterations, options, callback=prog_func) logger.info(" done.") # Compute Statistics before closing out the dataset logger.info(" Computing stats...") try: output_band.ComputeStatistics(False) except RuntimeError: logger.warn(" Cannot compute statistics.") logger.info(" done.") logger.info(" cleanning up band...") output_band = None logger.info(" done.") logger.info(" Building blocks...") output_fh.BuildOverviews(overviewlist=[2, 4, 8, 16, 32, 64, 128]) logger.info(" done.") logger.info(" Flushing the cache...") output_fh.FlushCache() logger.info(" done.") logger.info(" closing mask bands and all file handlers...") output_fh = None mask_band = None input_fh = None logger.info(" done.") return result