fill_lat_lng_nodata.py
def fill_by_convolution(
        base_raster_path, convolve_radius, target_filled_raster_path):
    """Clip and fill.

    Clip the base raster data to the bounding box then fill any noodata
    holes with a weighted distance convolution.

    Args:
        base_raster_path (str): path to base raster
        convolve_radius (float): maximum convolution distance kernel in
            projected units of base.
        target_filled_raster_path (str): raster created by convolution fill,
            if holes are too far from valid pixels resulting fill will be
            nonsensical, perhaps NaN.

    Return:
        None
    """
    try:
        LOGGER.info(f'filling {base_raster_path}')
        # create working directory in the same directory as the target with
        # the same name as the target file so it can't be duplicated
        # easier to spot for debugging too
        working_dir = os.path.join(
            os.path.dirname(target_filled_raster_path),
            os.path.basename(os.path.splitext(target_filled_raster_path)[0]))
        try:
            os.makedirs(working_dir)
        except OSError:
            pass

        basename = os.path.basename(target_filled_raster_path)
        base_raster_info = pygeoprocessing.get_raster_info(base_raster_path)

        # this ensures a minimum of 3 pixels in case the pixel size is too
        # chunky
        n = max(3, int(convolve_radius / base_raster_info['pixel_size'][0]))
        base = numpy.zeros((n, n))
        base[n//2, n//2] = 1
        kernel_array = scipy.ndimage.filters.gaussian_filter(base, n/3)
        kernel_raster_path = os.path.join(working_dir, f'kernel_{basename}')
        geotransform = base_raster_info['geotransform']
        pygeoprocessing.numpy_array_to_raster(
            kernel_array, None, base_raster_info['pixel_size'],
            (geotransform[0], geotransform[3]),
            base_raster_info['projection_wkt'], kernel_raster_path)

        # scrub input raster
        sanitized_base_raster_path = os.path.join(
            working_dir, f'sanitized_{basename}')
        sanitize_raster(base_raster_path, sanitized_base_raster_path)

        # mask valid
        valid_raster_path = os.path.join(
            working_dir, f'sanitized_{basename}')
        pygeoprocessing.raster_calculator(
            [(base_raster_path, 1), (base_raster_info['nodata'][0], 'raw')],
            _mask_valid_op, valid_raster_path, gdal.GDT_Byte, None)
        mask_kernel_raster_path = os.path.join(
            working_dir, f'mask_kernel_{basename}')
        geotransform = base_raster_info['geotransform']
        mask_kernel_array = numpy.copy(kernel_array)
        mask_kernel_array[:] = 1
        pygeoprocessing.numpy_array_to_raster(
            mask_kernel_array, None, base_raster_info['pixel_size'],
            (geotransform[0], geotransform[3]),
            base_raster_info['projection_wkt'], mask_kernel_raster_path)
        coverage_raster_path = os.path.join(
            working_dir, f'coverage_{basename}')
        pygeoprocessing.convolve_2d(
            (valid_raster_path, 1), (mask_kernel_raster_path, 1),
            coverage_raster_path,
            mask_nodata=False,
            target_nodata=-1,
            target_datatype=gdal.GDT_Byte,
            working_dir=working_dir)

        # this raster will be filled with the entire convolution
        backfill_raster_path = os.path.join(
            working_dir, f'backfill_{basename}')
        base_nodata = base_raster_info['nodata'][0]
        if base_nodata is None:
            target_datatype = gdal.GDT_Float64
        else:
            target_datatype = base_raster_info['datatype']
        LOGGER.info(
            f'create backfill from {sanitized_base_raster_path} to '
            f'{backfill_raster_path}')
        pygeoprocessing.convolve_2d(
            (sanitized_base_raster_path, 1), (kernel_raster_path, 1),
            backfill_raster_path, ignore_nodata_and_edges=True,
            mask_nodata=False, normalize_kernel=True,
            target_nodata=base_nodata,
            target_datatype=target_datatype,
            working_dir=working_dir)

        LOGGER.info(
            f'fill nodata of {base_raster_path} to {backfill_raster_path}')
        pygeoprocessing.raster_calculator(
            [(base_raster_path, 1),
             (backfill_raster_path, 1), (coverage_raster_path, 1),
             (base_nodata, 'raw')], _fill_nodata_op,
            target_filled_raster_path,
            base_raster_info['datatype'], base_nodata)
        shutil.rmtree(working_dir)
    except Exception:
        LOGGER.exception(
            f'error on fill by convolution {target_filled_raster_path}')
        raise
Clip and fill.

    Clip the base raster data to the bounding box then fill any noodata
    holes with a weighted distance convolution.

    Args:
        base_raster_path (str): path to base raster
        convolve_radius (float): maximum convolution distance kernel in
            projected units of base.
        target_filled_raster_path (str): raster created by convolution fill,
            if holes are too far from valid pixels resulting fill will be
            nonsensical, perhaps NaN.

    Return:
        None
    
Clip and fill.
Clip the base raster data to the bounding box then fill any noodata
holes with a weighted distance convolution.
Clip and fill . Clip the base raster data to the bounding box then fill any noodata holes with a weighted distance convolution .
def fill_by_convolution(
        base_raster_path, convolve_radius, target_filled_raster_path):
    try:
        LOGGER.info(f'filling {base_raster_path}')
        working_dir = os.path.join(
            os.path.dirname(target_filled_raster_path),
            os.path.basename(os.path.splitext(target_filled_raster_path)[0]))
        try:
            os.makedirs(working_dir)
        except OSError:
            pass
        basename = os.path.basename(target_filled_raster_path)
        base_raster_info = pygeoprocessing.get_raster_info(base_raster_path)
        n = max(3, int(convolve_radius / base_raster_info['pixel_size'][0]))
        base = numpy.zeros((n, n))
        base[n//2, n//2] = 1
        kernel_array = scipy.ndimage.filters.gaussian_filter(base, n/3)
        kernel_raster_path = os.path.join(working_dir, f'kernel_{basename}')
        geotransform = base_raster_info['geotransform']
        pygeoprocessing.numpy_array_to_raster(
            kernel_array, None, base_raster_info['pixel_size'],
            (geotransform[0], geotransform[3]),
            base_raster_info['projection_wkt'], kernel_raster_path)
        sanitized_base_raster_path = os.path.join(
            working_dir, f'sanitized_{basename}')
        sanitize_raster(base_raster_path, sanitized_base_raster_path)
        valid_raster_path = os.path.join(
            working_dir, f'sanitized_{basename}')
        pygeoprocessing.raster_calculator(
            [(base_raster_path, 1), (base_raster_info['nodata'][0], 'raw')],
            _mask_valid_op, valid_raster_path, gdal.GDT_Byte, None)
        mask_kernel_raster_path = os.path.join(
            working_dir, f'mask_kernel_{basename}')
        geotransform = base_raster_info['geotransform']
        mask_kernel_array = numpy.copy(kernel_array)
        mask_kernel_array[:] = 1
        pygeoprocessing.numpy_array_to_raster(
            mask_kernel_array, None, base_raster_info['pixel_size'],
            (geotransform[0], geotransform[3]),
            base_raster_info['projection_wkt'], mask_kernel_raster_path)
        coverage_raster_path = os.path.join(
            working_dir, f'coverage_{basename}')
        pygeoprocessing.convolve_2d(
            (valid_raster_path, 1), (mask_kernel_raster_path, 1),
            coverage_raster_path,
            mask_nodata=False,
            target_nodata=-1,
            target_datatype=gdal.GDT_Byte,
            working_dir=working_dir)
        backfill_raster_path = os.path.join(
            working_dir, f'backfill_{basename}')
        base_nodata = base_raster_info['nodata'][0]
        if base_nodata is None:
            target_datatype = gdal.GDT_Float64
        else:
            target_datatype = base_raster_info['datatype']
        LOGGER.info(
            f'create backfill from {sanitized_base_raster_path} to '
            f'{backfill_raster_path}')
        pygeoprocessing.convolve_2d(
            (sanitized_base_raster_path, 1), (kernel_raster_path, 1),
            backfill_raster_path, ignore_nodata_and_edges=True,
            mask_nodata=False, normalize_kernel=True,
            target_nodata=base_nodata,
            target_datatype=target_datatype,
            working_dir=working_dir)
        LOGGER.info(
            f'fill nodata of {base_raster_path} to {backfill_raster_path}')
        pygeoprocessing.raster_calculator(
            [(base_raster_path, 1),
             (backfill_raster_path, 1), (coverage_raster_path, 1),
             (base_nodata, 'raw')], _fill_nodata_op,
            target_filled_raster_path,
            base_raster_info['datatype'], base_nodata)
        shutil.rmtree(working_dir)
    except Exception:
        LOGGER.exception(
            f'error on fill by convolution {target_filled_raster_path}')
        raise
def fill_by_convolution ( base_raster_path , convolve_radius , target_filled_raster_path ) : try : LOGGER . info ( f'filling {base_raster_path}' ) working_dir = os . path . join ( os . path . dirname ( target_filled_raster_path ) , os . path . basename ( os . path . splitext ( target_filled_raster_path ) [ 0 ] ) ) try : os . makedirs ( working_dir ) except OSError : pass basename = os . path . basename ( target_filled_raster_path ) base_raster_info = pygeoprocessing . get_raster_info ( base_raster_path ) n = max ( 3 , int ( convolve_radius / base_raster_info [ 'pixel_size' ] [ 0 ] ) ) base = numpy . zeros ( ( n , n ) ) base [ n // 2 , n // 2 ] = 1 kernel_array = scipy . ndimage . filters . gaussian_filter ( base , n / 3 ) kernel_raster_path = os . path . join ( working_dir , f'kernel_{basename}' ) geotransform = base_raster_info [ 'geotransform' ] pygeoprocessing . numpy_array_to_raster ( kernel_array , None , base_raster_info [ 'pixel_size' ] , ( geotransform [ 0 ] , geotransform [ 3 ] ) , base_raster_info [ 'projection_wkt' ] , kernel_raster_path ) sanitized_base_raster_path = os . path . join ( working_dir , f'sanitized_{basename}' ) sanitize_raster ( base_raster_path , sanitized_base_raster_path ) valid_raster_path = os . path . join ( working_dir , f'sanitized_{basename}' ) pygeoprocessing . raster_calculator ( [ ( base_raster_path , 1 ) , ( base_raster_info [ 'nodata' ] [ 0 ] , 'raw' ) ] , _mask_valid_op , valid_raster_path , gdal . GDT_Byte , None ) mask_kernel_raster_path = os . path . join ( working_dir , f'mask_kernel_{basename}' ) geotransform = base_raster_info [ 'geotransform' ] mask_kernel_array = numpy . copy ( kernel_array ) mask_kernel_array [ : ] = 1 pygeoprocessing . numpy_array_to_raster ( mask_kernel_array , None , base_raster_info [ 'pixel_size' ] , ( geotransform [ 0 ] , geotransform [ 3 ] ) , base_raster_info [ 'projection_wkt' ] , mask_kernel_raster_path ) coverage_raster_path = os . path . join ( working_dir , f'coverage_{basename}' ) pygeoprocessing . convolve_2d ( ( valid_raster_path , 1 ) , ( mask_kernel_raster_path , 1 ) , coverage_raster_path , mask_nodata = False , target_nodata = - 1 , target_datatype = gdal . GDT_Byte , working_dir = working_dir ) backfill_raster_path = os . path . join ( working_dir , f'backfill_{basename}' ) base_nodata = base_raster_info [ 'nodata' ] [ 0 ] if base_nodata is None : target_datatype = gdal . GDT_Float64 else : target_datatype = base_raster_info [ 'datatype' ] LOGGER . info ( f'create backfill from {sanitized_base_raster_path} to ' f'{backfill_raster_path}' ) pygeoprocessing . convolve_2d ( ( sanitized_base_raster_path , 1 ) , ( kernel_raster_path , 1 ) , backfill_raster_path , ignore_nodata_and_edges = True , mask_nodata = False , normalize_kernel = True , target_nodata = base_nodata , target_datatype = target_datatype , working_dir = working_dir ) LOGGER . info ( f'fill nodata of {base_raster_path} to {backfill_raster_path}' ) pygeoprocessing . raster_calculator ( [ ( base_raster_path , 1 ) , ( backfill_raster_path , 1 ) , ( coverage_raster_path , 1 ) , ( base_nodata , 'raw' ) ] , _fill_nodata_op , target_filled_raster_path , base_raster_info [ 'datatype' ] , base_nodata ) shutil . rmtree ( working_dir ) except Exception : LOGGER . exception ( f'error on fill by convolution {target_filled_raster_path}' ) raise
Clip and fill.
Clip and fill .
"""Clip and fill.

    Clip the base raster data to the bounding box then fill any noodata
    holes with a weighted distance convolution.

    Args:
        base_raster_path (str): path to base raster
        convolve_radius (float): maximum convolution distance kernel in
            projected units of base.
        target_filled_raster_path (str): raster created by convolution fill,
            if holes are too far from valid pixels resulting fill will be
            nonsensical, perhaps NaN.

    Return:
        None
    """ # create working directory in the same directory as the target with # the same name as the target file so it can't be duplicated # easier to spot for debugging too # this ensures a minimum of 3 pixels in case the pixel size is too # chunky # scrub input raster # mask valid # this raster will be filled with the entire convolution
base_raster_path
path to base raster
path to base raster
convolve_radius
maximum convolution distance kernel in
projected units of base.
maximum convolution distance kernel in projected units of base .
target_filled_raster_path
raster created by convolution fill,
if holes are too far from valid pixels resulting fill will be
nonsensical, perhaps NaN.
raster created by convolution fill if holes are too far from valid pixels resulting fill will be nonsensical perhaps NaN .