示例#1
0
def _calculate_load(lulc_raster_path, lucode_to_parameters, load_type,
                    target_load_raster):
    """Calculate load raster by mapping landcover and multiplying by area.

    Parameters:
        lulc_raster_path (string): path to integer landcover raster.
        lucode_to_parameters (dict): a mapping of landcover IDs to a
            dictionary indexed by the value of `load_{load_type}` that
            represents a per-area nutrient load.
        load_type (string): represent nutrient to map, either 'load_n' or
            'load_p'.
        target_load_raster (string): path to target raster that will have
            total load per pixel.

    Returns:
        None.

    """
    lulc_raster_info = pygeoprocessing.get_raster_info(lulc_raster_path)
    nodata_landuse = lulc_raster_info['nodata'][0]
    cell_area_ha = abs(numpy.prod(lulc_raster_info['pixel_size'])) * 0.0001

    def _map_load_op(lucode_array):
        """Convert unit load to total load & handle nodata."""
        result = numpy.empty(lucode_array.shape)
        result[:] = _TARGET_NODATA
        for lucode in numpy.unique(lucode_array):
            if lucode != nodata_landuse:
                result[lucode_array == lucode] = (
                    lucode_to_parameters[lucode][load_type] * cell_area_ha)
        return result

    pygeoprocessing.raster_calculator([(lulc_raster_path, 1)], _map_load_op,
                                      target_load_raster, gdal.GDT_Float32,
                                      _TARGET_NODATA)
示例#2
0
文件: globio.py 项目: dkav/invest
def _msa_calculation(msa_f_path, msa_lu_path, msa_i_path, msa_path,
                     msa_nodata):
    """Calculate the MSA which is the product of the sub MSAs.

    Args:
        msa_f_path (str): path to the msa_f raster.
        msa_lu_path (str): path to the msa_lu raster.
        msa_i_path (str): path to the msa_i raster.
        msa_path (str): path to the output MSA raster.
        msa_nodata (int/float): the output nodata value.

    Returns:
        Nothing
    """
    msa_f_nodata = pygeoprocessing.get_raster_info(msa_f_path)['nodata'][0]
    msa_lu_nodata = pygeoprocessing.get_raster_info(msa_lu_path)['nodata'][0]
    msa_i_nodata = pygeoprocessing.get_raster_info(msa_i_path)['nodata'][0]
    nodata_array = [msa_f_nodata, msa_lu_nodata, msa_i_nodata]

    def msa_op(msa_f, msa_lu, msa_i):
        """Calculate the MSA which is the product of the sub MSAs."""
        result = numpy.full_like(msa_f, msa_nodata, dtype=numpy.float32)
        valid_mask = numpy.ones(msa_f.shape, dtype=bool)
        for msa_array, nodata_val in zip([msa_f, msa_lu, msa_i], nodata_array):
            if nodata_val is not None:
                valid_mask &= ~numpy.isclose(msa_array, nodata_val)
        result[valid_mask] = (msa_f[valid_mask] * msa_lu[valid_mask] *
                              msa_i[valid_mask])
        return result

    pygeoprocessing.raster_calculator([(msa_f_path, 1), (msa_lu_path, 1),
                                       (msa_i_path, 1)], msa_op, msa_path,
                                      gdal.GDT_Float32, msa_nodata)
示例#3
0
def _sum_valuation_rasters(dem_path, valuation_filepaths, target_path):
    """Sum up all valuation rasters.

    Args:
        dem_path (string): A path to the DEM. Must perfectly overlap all of
            the rasters in ``valuation_filepaths``.
        valuation_filepaths (list of strings): A list of paths to individual
            valuation rasters. All rasters in this list must overlap
            perfectly.
        target_path (string): The path on disk where the output raster will be
            written. If a file exists at this path, it will be overwritten.

    Returns:
        ``None``

    """
    dem_nodata = pygeoprocessing.get_raster_info(dem_path)['nodata'][0]

    def _sum_rasters(dem, *valuation_rasters):
        valid_dem_pixels = ~utils.array_equals_nodata(dem, dem_nodata)
        raster_sum = numpy.empty(dem.shape, dtype=numpy.float64)
        raster_sum[:] = _VALUATION_NODATA
        raster_sum[valid_dem_pixels] = 0

        for valuation_matrix in valuation_rasters:
            valid_pixels = (
                ~utils.array_equals_nodata(valuation_matrix, _VALUATION_NODATA)
                & valid_dem_pixels)
            raster_sum[valid_pixels] += valuation_matrix[valid_pixels]
        return raster_sum

    pygeoprocessing.raster_calculator(
        [(dem_path, 1)] + [(path, 1) for path in valuation_filepaths],
        _sum_rasters, target_path, gdal.GDT_Float64, _VALUATION_NODATA,
        raster_driver_creation_tuple=FLOAT_GTIFF_CREATION_OPTIONS)
示例#4
0
def _calculate_si_raster(cn_path, stream_path, si_path):
    """Calculate the S factor of the quickflow equation [1].

    Parameters:
        cn_path (string): path to curve number raster
        stream_path (string): path to a stream raster (0, 1)
        si_path (string): path to output s_i raster

    Returns:
        None
    """
    si_nodata = -1
    cn_nodata = pygeoprocessing.get_raster_info(cn_path)['nodata'][0]

    def si_op(ci_factor, stream_mask):
        """Calculate si factor."""
        valid_mask = (ci_factor != cn_nodata) & (ci_factor > 0)
        si_array = numpy.empty(ci_factor.shape)
        si_array[:] = si_nodata
        # multiply by the stream mask != 1 so we get 0s on the stream and
        # unaffected results everywhere else
        si_array[valid_mask] = (
            (1000.0 / ci_factor[valid_mask] - 10) * (
                stream_mask[valid_mask] != 1))
        return si_array

    pygeoprocessing.raster_calculator(
        [(cn_path, 1), (stream_path, 1)], si_op, si_path, gdal.GDT_Float32,
        si_nodata)
示例#5
0
def raster_list_sum(raster_list,
                    input_nodata,
                    target_path,
                    target_nodata,
                    nodata_remove=False):
    """Calculate the sum per pixel across rasters in a list.

    Sum the rasters in `raster_list` element-wise, allowing nodata values
    in the rasters to propagate to the result or treating nodata as zero. If
    nodata is treated as zero, areas where all inputs are nodata will be nodata
    in the output.

    Parameters:
        raster_list (list): list of paths to rasters to sum
        input_nodata (float or int): nodata value in the input rasters
        target_path (string): path to location to store the result
        target_nodata (float or int): nodata value for the result raster
        nodata_remove (bool): if true, treat nodata values in input
            rasters as zero. If false, the sum in a pixel where any input
            raster is nodata is nodata.

    Side effects:
        modifies or creates the raster indicated by `target_path`

    Returns:
        None

    """
    def raster_sum_op(*raster_list):
        """Add the rasters in raster_list without removing nodata values."""
        invalid_mask = numpy.any(numpy.isclose(numpy.array(raster_list),
                                               input_nodata),
                                 axis=0)
        for r in raster_list:
            numpy.place(r, numpy.isclose(r, input_nodata), [0])
        sum_of_rasters = numpy.sum(raster_list, axis=0)
        sum_of_rasters[invalid_mask] = target_nodata
        return sum_of_rasters

    def raster_sum_op_nodata_remove(*raster_list):
        """Add the rasters in raster_list, treating nodata as zero."""
        invalid_mask = numpy.all(numpy.isclose(numpy.array(raster_list),
                                               input_nodata),
                                 axis=0)
        for r in raster_list:
            numpy.place(r, numpy.isclose(r, input_nodata), [0])
        sum_of_rasters = numpy.sum(raster_list, axis=0)
        sum_of_rasters[invalid_mask] = target_nodata
        return sum_of_rasters

    if nodata_remove:
        pygeoprocessing.raster_calculator([(path, 1) for path in raster_list],
                                          raster_sum_op_nodata_remove,
                                          target_path, gdal.GDT_Int16,
                                          target_nodata)

    else:
        pygeoprocessing.raster_calculator([(path, 1) for path in raster_list],
                                          raster_sum_op, target_path,
                                          gdal.GDT_Int16, target_nodata)
示例#6
0
def _convert_to_density(base_wgs84_raster_path,
                        target_wgs84_density_raster_path):
    """Convert base WGS84 raster path to a per density raster path."""
    base_raster_info = pygeoprocessing.get_raster_info(base_wgs84_raster_path)
    # xmin, ymin, xmax, ymax
    _, lat_min, _, lat_max = base_raster_info['bounding_box']
    _, n_rows = base_raster_info['raster_size']

    m2_area_col = _create_latitude_m2_area_column(lat_min, lat_max, n_rows)
    nodata = base_raster_info['nodata'][0]

    def _div_by_area_op(base_array, m2_area_array):
        result = numpy.empty(base_array.shape, dtype=base_array.dtype)
        if nodata is not None:
            valid_mask = ~numpy.isclose(base_array, nodata)
            result[:] = nodata
        else:
            valid_mask = numpy.ones(base_array.shape, dtype=bool)

        result[valid_mask] = (base_array[valid_mask] /
                              m2_area_array[valid_mask])
        return result

    pygeoprocessing.raster_calculator(
        [(base_wgs84_raster_path, 1), m2_area_col], _div_by_area_op,
        target_wgs84_density_raster_path, base_raster_info['datatype'], nodata)
示例#7
0
def _create_lulc_mask(lulc_raster_path, mask_codes, target_mask_raster_path):
    """Create a mask raster given an lulc and mask code."""
    numpy_mask_codes = numpy.array(mask_codes)
    pygeoprocessing.raster_calculator(
        [(lulc_raster_path, 1)],
        lambda array: numpy.isin(array, numpy_mask_codes),
        target_mask_raster_path, gdal.GDT_Byte, None)
示例#8
0
def reclassify_nodata(input_path, target_path):
    """Reclassify the nodata value of a raster to a default value.

    Convert all areas of nodata in the input raster to the default nodata
    value and convert the data type of the input raster to the default data
    type.
    
    Parameters:
        input_path (string): path to input raster that should be reclassified
        target_path (string): path to target raster with reclassified
    Side effects:
        creates a raster at the location indicated by `target_path`
    
    Returns:
        None
    """
    def reclassify_op(target_raster):
        reclassified_raster = numpy.copy(target_raster)
        reclassify_mask = numpy.isclose(target_raster, previous_nodata_value)
        reclassified_raster[reclassify_mask] = _TARGET_NODATA
        return reclassified_raster

    previous_nodata_value = pygeoprocessing.get_raster_info(
        input_path)['nodata'][0]
    pygeoprocessing.raster_calculator(
        [(input_path, 1)], reclassify_op, target_path, _TARGET_DATATYPE,
        _TARGET_NODATA)
示例#9
0
def _threshold_slope(slope_path, out_thresholded_slope_path):
    """Threshold the slope between 0.005 and 1.0.

    Parameters:
        slope_path (string): path to a raster of slope in percent
        out_thresholded_slope_path (string): path to output raster of
            thresholded slope between 0.005 and 1.0

    Returns:
        None
    """
    slope_nodata = pygeoprocessing.get_raster_info(slope_path)['nodata'][0]

    def threshold_slope(slope):
        """Convert slope to m/m and clamp at 0.005 and 1.0.

        As desribed in Cavalli et al., 2013.
        """
        valid_slope = slope != slope_nodata
        slope_m = slope[valid_slope] / 100.0
        slope_m[slope_m < 0.005] = 0.005
        slope_m[slope_m > 1.0] = 1.0
        result = numpy.empty(valid_slope.shape)
        result[:] = slope_nodata
        result[valid_slope] = slope_m
        return result

    pygeoprocessing.raster_calculator(
        [(slope_path, 1)], threshold_slope, out_thresholded_slope_path,
        gdal.GDT_Float32, slope_nodata)
def density_per_ha_to_total_per_pixel(base_value_per_ha_raster_path,
                                      mult_factor,
                                      target_total_per_pixel_raster_path):
    """Convert X/Ha in base to (total X)/pixel."""
    base_raster_info = pygeoprocessing.get_raster_info(
        base_value_per_ha_raster_path)

    base_srs = osr.SpatialReference()
    base_srs.ImportFromWkt(base_raster_info['projection_wkt'])
    if base_srs.IsProjected():
        # convert m^2 of pixel size to Ha
        pixel_conversion = numpy.array([[
            abs(base_raster_info['pixel_size'][0] *
                base_raster_info['pixel_size'][1])
        ]]) / 10000.0
    else:
        # create 1D array of pixel size vs. lat
        n_rows = base_raster_info['raster_size'][1]
        pixel_height = abs(base_raster_info['geotransform'][5])
        # the / 2 is to get in the center of the pixel
        miny = base_raster_info['bounding_box'][1] + pixel_height / 2
        maxy = base_raster_info['bounding_box'][3] - pixel_height / 2
        lat_vals = numpy.linspace(maxy, miny, n_rows)

        pixel_conversion = 1.0 / 10000.0 * numpy.array(
            [[area_of_pixel(pixel_height, lat_val)] for lat_val in lat_vals])

    pixel_conversion *= mult_factor

    nodata = base_raster_info['nodata'][0]
    pygeoprocessing.raster_calculator(
        [(base_value_per_ha_raster_path, 1), pixel_conversion,
         (nodata, 'raw')], mult_op, target_total_per_pixel_raster_path,
        gdal.GDT_Float32, nodata)
示例#11
0
def rescale_by_base(base_raster_path, new_raster_path, target_raster_path):
    """Target is new * base_max/new_max."""
    base_sum = _sum_raster(base_raster_path)
    new_sum = _sum_raster(new_raster_path)

    new_raster_info = pygeoprocessing.get_raster_info(new_raster_path)
    new_nodata = new_raster_info['nodata'][0]

    def _mult_op(new_array, scale):
        """Scale non-nodata by scale."""
        result = numpy.copy(new_array)
        if new_nodata is not None:
            result[~numpy.isfinite(result)] = new_nodata
            valid_mask = ~numpy.isclose(new_array, new_nodata)
        else:
            result[~numpy.isfinite(result)] = 0
            valid_mask = slice(-1)

        result[valid_mask] *= scale
        return result

    if new_sum == 0:
        scale = 1.0
    else:
        scale = base_sum / new_sum

    pygeoprocessing.raster_calculator([(new_raster_path, 1), (scale, 'raw')],
                                      _mult_op, target_raster_path,
                                      new_raster_info['datatype'],
                                      new_raster_info['nodata'][0])
def smooth_mask(base_mask_path, smooth_radius, target_smooth_mask_path):
    """Fill in gaps in base mask if there are neighbors.

    Args:
        base_mask_path (str): path to base raster, should be 0, 1 and nodata.
        smooth_radius (int): how far to smooth out at a max radius?
        target_smooth_mask_path (str): target smoothed file.

    Returns:
        None.

    """
    kernel_size = smooth_radius*2+1
    working_dir = tempfile.mkdtemp(
        dir=os.path.dirname(target_smooth_mask_path))
    kernel_path = os.path.join(working_dir, f'kernel_{kernel_size}.tif')
    make_neighborhood_hat_kernel(kernel_size, kernel_path)

    convolved_raster_path = os.path.join(working_dir, 'convolved_mask.tif')
    byte_nodata = 255
    pygeoprocessing.convolve_2d(
        (base_mask_path, 1), (kernel_path, 1), convolved_raster_path,
        ignore_nodata=False, working_dir=working_dir, mask_nodata=False,
        target_nodata=TARGET_NODATA)

    # set required proportion of coverage to turn on a pixel, lets make it a
    # quarter wedge.
    proportion_covered = 0.01
    threshold_val = proportion_covered * 3.14159 * (smooth_radius+1)**2
    pygeoprocessing.raster_calculator(
        [(convolved_raster_path, 1), (threshold_val, 'raw'),
         (TARGET_NODATA, 'raw'), (byte_nodata, 'raw'), ], threshold_op,
        target_smooth_mask_path, gdal.GDT_Byte, byte_nodata)
示例#13
0
def invert_raster_values(base_raster_path, target_raster_path):
    """Invert (1/x) the values in `base`.

    Parameters:
        base_raster_path (string): path to floating point raster.
        target_raster_path (string): path to created output raster whose
            values are 1/x of base.

    Returns:
        None.

    """
    base_nodata = pygeoprocessing.get_raster_info(
        base_raster_path)['nodata'][0]

    def _inverse_op(base_val):
        """Calculate inverse of S factor."""
        result = numpy.empty(base_val.shape, dtype=numpy.float32)
        result[:] = _TARGET_NODATA
        valid_mask = ~numpy.isclose(base_val, base_nodata)
        zero_mask = base_val == 0.0
        result[valid_mask & ~zero_mask] = (1.0 /
                                           base_val[valid_mask & ~zero_mask])
        result[zero_mask] = 0.0
        return result

    pygeoprocessing.raster_calculator(((base_raster_path, 1), ), _inverse_op,
                                      target_raster_path, gdal.GDT_Float32,
                                      _TARGET_NODATA)
示例#14
0
def _multiply_rasters(raster_path_list, target_nodata, target_result_path):
    """Multiply the rasters in `raster_path_list`.

    Parameters:
        raster_path_list (list): list of single band raster paths.
        target_nodata (float): desired target nodata value.
        target_result_path (string): path to float 32 target raster
            multiplied where all rasters are not nodata.

    Returns:
        None.

    """
    def _mult_op(*array_nodata_list):
        """Multiply non-nodata stacks."""
        result = numpy.empty(array_nodata_list[0].shape)
        result[:] = target_nodata
        valid_mask = ~numpy.isclose(array_nodata_list[0], array_nodata_list[1])
        for array, nodata in zip(*[iter(array_nodata_list[2:])] * 2):
            valid_mask &= ~numpy.isclose(array, nodata)
        result[valid_mask] = array_nodata_list[0][valid_mask]
        for array in array_nodata_list[2::2]:
            result[valid_mask] *= array[valid_mask]
        return result

    # make a list of (raster_path_band, nodata) tuples, then flatten it
    path_nodata_list = list(
        itertools.chain(*[((path, 1),
                           (pygeoprocessing.get_raster_info(path)['nodata'][0],
                            'raw')) for path in raster_path_list]))
    pygeoprocessing.raster_calculator(path_nodata_list, _mult_op,
                                      target_result_path, gdal.GDT_Float32,
                                      target_nodata)
示例#15
0
def calculate_mask_area(base_mask_raster_path):
    """Calculate area of mask==1."""
    base_raster_info = pygeoprocessing.get_raster_info(
        base_mask_raster_path)

    base_srs = osr.SpatialReference()
    base_srs.ImportFromWkt(base_raster_info['projection_wkt'])
    if base_srs.IsProjected():
        # convert m^2 of pixel size to Ha
        pixel_conversion = numpy.array([[
            abs(base_raster_info['pixel_size'][0] *
                base_raster_info['pixel_size'][1])]]) / 10000.0
    else:
        # create 1D array of pixel size vs. lat
        n_rows = base_raster_info['raster_size'][1]
        pixel_height = abs(base_raster_info['geotransform'][5])
        # the / 2 is to get in the center of the pixel
        miny = base_raster_info['bounding_box'][1] + pixel_height/2
        maxy = base_raster_info['bounding_box'][3] - pixel_height/2
        lat_vals = numpy.linspace(maxy, miny, n_rows)

        pixel_conversion = 1.0 / 10000.0 * numpy.array([
            [area_of_pixel(pixel_height, lat_val)] for lat_val in lat_vals])

    nodata = base_raster_info['nodata'][0]
    area_raster_path = 'tmp_area_mask.tif'
    pygeoprocessing.raster_calculator(
        [(base_mask_raster_path, 1), pixel_conversion], mask_op,
        area_raster_path, gdal.GDT_Float32, nodata)

    area_sum = 0.0
    for _, area_block in pygeoprocessing.iterblocks((area_raster_path, 1)):
        area_sum += numpy.sum(area_block)
    return area_sum
示例#16
0
def _calculate_d_up(
        w_bar_path, s_bar_path, flow_accumulation_path, out_d_up_path):
    """Calculate w_bar * s_bar * sqrt(flow accumulation * cell area)."""
    cell_area = pygeoprocessing.get_raster_info(
        w_bar_path)['mean_pixel_size'] ** 2
    flow_accumulation_nodata = pygeoprocessing.get_raster_info(
        flow_accumulation_path)['nodata'][0]

    def d_up_op(w_bar, s_bar, flow_accumulation):
        """Calculate the d_up index.

        w_bar * s_bar * sqrt(upstream area)

        """
        valid_mask = (
            (w_bar != _TARGET_NODATA) & (s_bar != _TARGET_NODATA) &
            (flow_accumulation != flow_accumulation_nodata))
        d_up_array = numpy.empty(valid_mask.shape)
        d_up_array[:] = _TARGET_NODATA
        d_up_array[valid_mask] = (
            w_bar[valid_mask] * s_bar[valid_mask] * numpy.sqrt(
                flow_accumulation[valid_mask] * cell_area))
        return d_up_array

    pygeoprocessing.raster_calculator(
        [(path, 1) for path in [
            w_bar_path, s_bar_path, flow_accumulation_path]], d_up_op,
        out_d_up_path, gdal.GDT_Float32, _TARGET_NODATA)
示例#17
0
def is_near(input_path, radius, distance_path, out_path):
    """Make binary raster of which pixels are within a radius of a '1' pixel.

    Args:
        input_path (str): path to a binary raster where '1' pixels are what
            we're measuring distance to, in this case roads/connected areas
        radius (float): distance in pixels which is considered "near".
            pixels this distance or less from a '1' pixel are marked '1' in
            the output. Distances are measured centerpoint to centerpoint.
        distance_path (str): path to write out the raster of distances
        out_path (str): path to write out the final thresholded raster.
            Pixels marked '1' are near to a '1' pixel in the input, pixels
            marked '0' are not.

    Returns:
        None
    """
    # Calculate the distance from each pixel to the nearest '1' pixel
    pygeoprocessing.distance_transform_edt(
        (input_path, 1),
        distance_path)

    def lte_threshold_op(array, threshold):
        """Binary array of elements less than or equal to the threshold."""
        # no need to mask nodata because distance_transform_edt doesn't
        # output any nodata pixels
        return array <= threshold

    # Threshold that to a binary array so '1' means it's within the radius
    pygeoprocessing.raster_calculator(
        [(distance_path, 1), (radius, 'raw')],
        lte_threshold_op,
        out_path,
        gdal.GDT_Byte,
        UINT8_NODATA)
示例#18
0
def _calculate_d_up_bare(
        s_bar_path, flow_accumulation_path, out_d_up_bare_path):
    """Calculate s_bar * sqrt(flow accumulation * cell area)."""
    cell_area = pygeoprocessing.get_raster_info(
        s_bar_path)['mean_pixel_size'] ** 2
    flow_accumulation_nodata = pygeoprocessing.get_raster_info(
        flow_accumulation_path)['nodata'][0]

    def d_up_op(s_bar, flow_accumulation):
        """Calculate the bare d_up index.

        s_bar * sqrt(upstream area)

        """
        valid_mask = (
            (flow_accumulation != flow_accumulation_nodata) &
            (s_bar != _TARGET_NODATA))
        d_up_array = numpy.empty(valid_mask.shape, dtype=numpy.float32)
        d_up_array[:] = _TARGET_NODATA
        d_up_array[valid_mask] = (
            numpy.sqrt(flow_accumulation[valid_mask] * cell_area) *
            s_bar[valid_mask])
        return d_up_array

    pygeoprocessing.raster_calculator(
        [(s_bar_path, 1), (flow_accumulation_path, 1)], d_up_op,
        out_d_up_bare_path, gdal.GDT_Float32, _TARGET_NODATA)
示例#19
0
def _calculate_vri(l_path, target_vri_path):
    """Calculate VRI as li_array / qb_sum.

    Parameters:
        l_path (str): path to L raster.
        target_vri_path (str): path to output Vri raster.

    Returns:
        None.

    """
    qb_sum = 0.0
    qb_valid_count = 0
    l_nodata = pygeoprocessing.get_raster_info(l_path)['nodata'][0]

    for _, block in pygeoprocessing.iterblocks((l_path, 1)):
        valid_mask = block != l_nodata
        qb_sum += numpy.sum(block[valid_mask])
        qb_valid_count += numpy.count_nonzero(valid_mask)
    li_nodata = pygeoprocessing.get_raster_info(l_path)['nodata'][0]

    def vri_op(li_array):
        """Calculate vri index [Eq 10]."""
        result = numpy.empty_like(li_array)
        result[:] = li_nodata
        if qb_sum > 0:
            valid_mask = li_array != li_nodata
            result[valid_mask] = li_array[valid_mask] / qb_sum
        return result

    pygeoprocessing.raster_calculator([(l_path, 1)], vri_op, target_vri_path,
                                      gdal.GDT_Float32, li_nodata)
def main(inundation_raster, target_raster):
    """Create boolean raster indicating which pixels are underwater.

    Parameters:
        inundation_raster (string): The path to an inundation raster with
            pixel values indicating the depth of inundation.
        target_raster (string): Where to write the output raster.

    Returns:
        ``None``

    """
    def mask_inundation(depth_under_water):
        """Create a boolean raster indicating whether rasters are underwater.

        Parameters:
            depth_under_water (ndarray): A float array with pixel values
                representing the depth of inundation at a pixel.  Large
                negative values are probably nodata.

        Returns:
            A numpy array with pixel values of 1 if a pixel is underwater,
            0 if above water.

        """
        out_matrix = numpy.empty(depth_under_water.shape, dtype=numpy.uint8)
        out_matrix[:] = 0
        out_matrix[depth_under_water > 0] = 1
        return out_matrix

    pygeoprocessing.raster_calculator([(inundation_raster, 1)],
                                      mask_inundation,
                                      target_raster,
                                      gdal.GDT_Byte,
                                      nodata_target=255)
def max_value_per_pixel(raster_list, target_path):
    """Identify, for each pixel, the maximum value across a list of rasters.

    The maximum value is calculated only for pixels with valid data across each
    raster in `raster_list`.  All rasters in `raster_list` must share nodata
    value.

    Args:
        raster_list (list): a list of paths to rasters containing the same
            quantity over the same area
        target_path (string): path where the result should be stored

    Side effects:
        creates a raster at `target_path` containing the maximum value for each
            pixel across the rasters in `raster_list`

    """
    def max_op(*raster_list):
        """Find the maximum value per pixel across rasters."""
        invalid_mask = numpy.any(numpy.isclose(numpy.array(raster_list),
                                               input_nodata),
                                 axis=0)
        max_val = numpy.amax(raster_list, axis=0)
        max_val[invalid_mask] = input_nodata
        return max_val

    input_nodata = pygeoprocessing.get_raster_info(raster_list[0])['nodata'][0]
    pygeoprocessing.raster_calculator([(path, 1) for path in raster_list],
                                      max_op, target_path, gdal.GDT_Float32,
                                      input_nodata)
def _diff_rasters(
        a_raster_path, b_raster_path, target_diff_raster_path):
    """Calculate a-b.

    Args:
        a_raster_path (str): raster A, same nodata and size as B
        b_raster_path (str): raster B
        target_diff_raster_path (str): result of A-B accounting for nodata.

    Returns:
        None
    """
    raster_info = pygeoprocessing.get_raster_info(a_raster_path)
    nodata = raster_info['nodata'][0]

    def _diff_op(a_array, b_array):
        """Return a-b and consider nodata."""
        result = numpy.copy(a_array)
        valid_mask = ~numpy.isclose(a_array, nodata)
        result[valid_mask] -= b_array[valid_mask]
        return result

    pygeoprocessing.raster_calculator(
        [(a_raster_path, 1), (b_raster_path, 1)], _diff_op,
        target_diff_raster_path, raster_info['datatype'], nodata)
示例#23
0
def _calculate_annual_qfi(qfm_path_list, target_qf_path):
    """Calculate annual quickflow.

    Parameters:
        qfm_path_list (list): list of monthly quickflow raster paths.
        target_qf_path (str): path to target annual quickflow raster.

    Returns:
        None.

    """
    qf_nodata = -1

    def qfi_sum_op(*qf_values):
        """Sum the monthly qfis."""
        qf_sum = numpy.zeros(qf_values[0].shape)
        valid_mask = qf_values[0] != qf_nodata
        valid_qf_sum = qf_sum[valid_mask]
        for index in range(len(qf_values)):
            valid_qf_sum += qf_values[index][valid_mask]
        qf_sum[:] = qf_nodata
        qf_sum[valid_mask] = valid_qf_sum
        return qf_sum

    pygeoprocessing.raster_calculator(
        [(path, 1) for path in qfm_path_list],
        qfi_sum_op, target_qf_path, gdal.GDT_Float32, qf_nodata)
def _calculate_new_forest(
        base_lulc_raster_path, future_lulc_raster_path,
        new_forest_mask_raster_path):
    """Calculate where there is new forest from base to future.

    Args:
        base_lulc_raster_path (str):
        future_lulc_raster_path (str):
        new_forest_mask_raster_path (str):

    Returns:
        None
    """
    FOREST_CODES = (50, 60, 61, 62, 70, 71, 72, 80, 81, 82, 90, 160, 170)

    def _mask_new_forest(base, future):
        """Remap values from ESA codes to basic MASK_TYPES."""
        result = numpy.empty(base.shape, dtype=numpy.uint8)
        base_forest = numpy.in1d(base, FOREST_CODES).reshape(result.shape)
        future_forest = numpy.in1d(future, FOREST_CODES).reshape(result.shape)
        result[:] = future_forest & ~base_forest
        return result

    pygeoprocessing.raster_calculator(
        [(base_lulc_raster_path, 1), (future_lulc_raster_path, 1)],
        _mask_new_forest, new_forest_mask_raster_path, gdal.GDT_Byte, None)
def mask_ranges(
        base_raster_path, mask_value_list, inverse, target_raster_path):
    """Mask all values in the given inclusive range to 1, the rest to 0.

    Args:
        base_raster_path (str): path to an integer raster
        mask_value_list (list): lits of integer codes to set output to 1 or 0
            if it is ccontained in the list.
        inverse (bool): if true the inverse of the `mask_value_list` is used
            so that values not in the list are set to 1 and those within are
            set to 0.
        target_raster_path (str): path to output mask, will contain 1 or 0
            whether the base had a pixel value contained in the
            `mask_value_list` while accounting for `inverse`.

    Returns:
        None.

    """
    base_nodata = pygeoprocessing.get_raster_info(
        base_raster_path)['nodata'][0]
    pygeoprocessing.raster_calculator(
        [(base_raster_path, 1), (base_nodata, 'raw'),
         (mask_value_list, 'raw'), (inverse, 'raw'),
         (MASK_NODATA, 'raw')], _mask_vals_op,
        target_raster_path, gdal.GDT_Byte, MASK_NODATA)
def mask_to_nodata(base_raster_path, mask_raster_path,
                   target_masked_base_raster_path):
    """Mask base to nodata where mask raster path is 1.

    Args:
        base_raster_path (str): arbitrary raster.
        mask_raster_path (str): path to mask raster containing 1 where mask
            is set.
        target_masked_base_raster_path (str): copy of base except where mask
            is 1, base is nodata.

    Returns:
        None.
    """
    base_info = pygeoprocessing.get_raster_info(base_raster_path)

    def mask_op(base_array, mask_array):
        result = numpy.copy(base_array)
        result[mask_array == 1] = base_info['nodata'][0]
        return result

    pygeoprocessing.raster_calculator([(base_raster_path, 1),
                                       (mask_raster_path, 1)], mask_op,
                                      target_masked_base_raster_path,
                                      base_info['datatype'],
                                      base_info['nodata'][0])
def mask_raster_by_array(raster_path_band,
                         mask_array,
                         target_raster_path,
                         invert=False):
    """Mask the given raster path/band by a set of integers.

    Parameters:
        raster_path_band (tuple): a raster path/band indicating the band to
            apply the mask operation.
        mask_array (list/numpy.ndarray): a sequence of integers that will be
            used to set a mask.
        target_raster_path (str): path to output raster which will have 1s
            where the original raster band had a value found in `mask_array`,
            0 if not found, and nodata if originally nodata.
        invert (bool): if true makes a mask of all values in raster band that
            are *not* in `mask_array`.

    Returns:
        None.

    """
    raster_info = pygeoprocessing.get_raster_info(raster_path_band[0])
    pygeoprocessing.raster_calculator([
        raster_path_band,
        (raster_info['nodata'][raster_path_band[1] - 1], 'raw'),
        (numpy.array(mask_array), 'raw'), (2, 'raw'), (invert, 'raw')
    ], _mask_raster_op, target_raster_path, gdal.GDT_Byte, 2)
def diff_valid(a_raster_path, b_raster_path, target_diff_raster_path):
    """Calculate a-b.

    Args:
        a_raster_path (str): path to arbitrary raster
        b_raster_path (str): path to raster that is the same size as a
        target_diff_raster_path (str): result of a-b where both a and b are
            not nodata.

    Returns:
        None.
    """
    a_info = pygeoprocessing.get_raster_info(a_raster_path)
    b_info = pygeoprocessing.get_raster_info(b_raster_path)

    def valid_diff_op(a_array, b_array):
        """Calc a-b."""
        result = numpy.empty_like(a_array)
        result[:] = a_info['nodata'][0]
        valid_mask = (~numpy.isclose(a_array, a_info['nodata'][0])
                      & ~numpy.isclose(b_array, b_info['nodata'][0]))
        result[valid_mask] = a_array[valid_mask] - b_array[valid_mask]
        return result

    pygeoprocessing.raster_calculator([(a_raster_path, 1), (b_raster_path, 1)],
                                      valid_diff_op, target_diff_raster_path,
                                      a_info['datatype'], a_info['nodata'][0])
示例#29
0
def reclassify_nodata(target_path, new_nodata_value):
    """Reclassify the nodata value of a raster to a new value.
    Convert all areas of nodata in the target raster to the new nodata
    value, which must be an integer.
    
    Parameters:
        target_path (string): path to target raster
        new_nodata_value (integer): new value to set as nodata
    Side effects:
        modifies the raster indicated by `target_path`
    
    Returns:
        None
    """
    def reclassify_op(target_raster):
        reclassified_raster = numpy.copy(target_raster)
        reclassify_mask = (target_raster == previous_nodata_value)
        reclassified_raster[reclassify_mask] = new_nodata_value
        return reclassified_raster

    fd, temp_path = tempfile.mkstemp()
    shutil.copyfile(target_path, temp_path)
    previous_raster_info = pygeoprocessing.get_raster_info(target_path)
    previous_nodata_value = previous_raster_info['nodata'][0]
    datatype = previous_raster_info['datatype']

    pygeoprocessing.raster_calculator([(temp_path, 1)], reclassify_op,
                                      target_path, datatype, new_nodata_value)

    # clean up
    os.close(fd)
    os.remove(temp_path)
示例#30
0
def _slope_proportion_and_threshold(slope_path, target_threshold_slope_path):
    """Rescale slope to proportion and threshold to between 0.005 and 1.0.

    Parameters:
        slope_path (string): a raster with slope values in percent.
        target_threshold_slope_path (string): generated raster with slope
            values as a proportion (100% is 1.0) and thresholded to values
            between 0.005 and 1.0.

    Returns:
        None.

    """
    slope_nodata = pygeoprocessing.get_raster_info(slope_path)['nodata'][0]

    def _slope_proportion_and_threshold_op(slope):
        """Rescale and threshold slope between 0.005 and 1.0."""
        valid_mask = slope != slope_nodata
        result = numpy.empty(valid_mask.shape, dtype=numpy.float32)
        result[:] = slope_nodata
        slope_fraction = slope[valid_mask] / 100
        slope_fraction[slope_fraction < 0.005] = 0.005
        slope_fraction[slope_fraction > 1.0] = 1.0
        result[valid_mask] = slope_fraction
        return result

    pygeoprocessing.raster_calculator([(slope_path, 1)],
                                      _slope_proportion_and_threshold_op,
                                      target_threshold_slope_path,
                                      gdal.GDT_Float32, slope_nodata)