Пример #1
0
def raster_mask_values(
    raster: Union[gdal.Dataset, str, list],
    values_to_mask: list,
    out_path: Union[list, str, None] = None,
    include_original_nodata: bool = True,
    dst_nodata: Union[float, int, str, list, None] = "infer",
    in_place: bool = False,
    overwrite: bool = True,
    opened: bool = False,
    prefix: str = "",
    postfix: str = "_nodata_masked",
    creation_options: list = [],
) -> Union[list, gdal.Dataset, str]:
    """Mask a raster with a list of values.

    Args:
        raster (path | raster | list): The raster(s) to retrieve nodata values from.

        values_to_mask (list): The list of values to mask in the raster(s)

    **kwargs:
        include_original_nodata: (bool): If True, the nodata value of the raster(s) will be
        included in the values to mask.

        dst_nodata (float, int, str, None): The target nodata value. If 'infer' the nodata
        value is set based on the input datatype. A list of nodata values can be based matching
        the amount of input rasters. If multiple nodata values should be set, use raster_mask_values.

        out_path (path | list | None): The destination of the changed rasters. If out_paths
        are specified, in_place is automatically set to False. The path can be a folder.

        in_place (bool): Should the rasters be changed in_place or copied?

        prefix (str): Prefix to add the the output if a folder is specified in out_path.

        postfix (str): Postfix to add the the output if a folder is specified in out_path.

    Returns:
        Returns the rasters with nodata removed. If in_place is True a reference to the
        changed orignal is returned, otherwise a copied memory raster or the path to the
        generated raster is outputted.
    """
    type_check(raster, [list, str, gdal.Dataset], "raster")
    type_check(values_to_mask, [list], "values_to_mask")
    type_check(out_path, [list, str], "out_path", allow_none=True)
    type_check(include_original_nodata, [bool], "include_original_nodata")
    type_check(dst_nodata, [float, int, str, list],
               "dst_nodata",
               allow_none=True)
    type_check(in_place, [bool], "in_place")
    type_check(overwrite, [bool], "overwrite")
    type_check(prefix, [str], "prefix")
    type_check(postfix, [str], "postfix")
    type_check(opened, [bool], "opened")
    type_check(creation_options, [list], "creation_options")

    rasters_metadata = []
    internal_in_place = in_place if out_path is None else False
    internal_dst_nodata = None

    for value in values_to_mask:
        if not isinstance(value, (int, float)):
            raise ValueError("Values in values_to_mask must be ints or floats")

    if isinstance(dst_nodata, str) and dst_nodata != "infer":
        raise ValueError(f"Invalid dst_nodata value. {dst_nodata}")

    if isinstance(dst_nodata, list):
        if not isinstance(raster, list) or len(dst_nodata) != len(raster):
            raise ValueError(
                "If dst_nodata is a list, raster must also be a list of equal length."
            )

        for value in dst_nodata:
            if isinstance(value, (float, int, str, None)):
                raise ValueError("Invalid type in dst_nodata list.")

            if isinstance(value, str) and value != "infer":
                raise ValueError(
                    "If dst_nodata is a string it must be 'infer'")

    raster_list, out_names = ready_io_raster(raster, out_path, overwrite,
                                             prefix, postfix)

    output_rasters = []

    for index, internal_raster in enumerate(raster_list):

        raster_metadata = None
        if len(rasters_metadata) == 0:
            raster_metadata = raster_to_metadata(internal_raster)
            rasters_metadata.append(raster_metadata)
        else:
            raster_metadata = rasters_metadata[index]

        if dst_nodata == "infer":
            internal_dst_nodata = gdal_nodata_value_from_type(
                raster_metadata["dtype_gdal_raw"])
        elif isinstance(dst_nodata, list):
            internal_dst_nodata = dst_nodata[index]
        else:
            internal_dst_nodata = dst_nodata

        mask_values = list(values_to_mask)
        if include_original_nodata:
            if raster_metadata["nodata_value"] is not None:
                mask_values.append(raster_metadata["nodata_value"])

        arr = raster_to_array(internal_raster, filled=True)

        mask = None
        for index, mask_value in enumerate(mask_values):
            if index == 0:
                mask = arr == mask_value
            else:
                mask = mask | arr == mask_value

        arr = np.ma.masked_array(arr,
                                 mask=mask,
                                 fill_value=internal_dst_nodata)

        if internal_in_place:
            for band in range(raster_metadata["bands"]):
                raster_band = internal_raster.GetRasterBand(band + 1)
                raster_band.WriteArray(arr[:, :, band])
                raster_band = None
        else:
            out_name = out_names[index]
            remove_if_overwrite(out_name, overwrite)

            output_rasters.append(
                array_to_raster(arr, internal_raster, out_path=out_name))

    if isinstance(raster, list):
        return output_rasters

    return output_rasters[0]
Пример #2
0
def calc_proximity(
    input_rasters,
    target_value=1,
    out_path=None,
    max_dist=1000,
    add_border=False,
    weighted=False,
    invert=False,
    return_array=False,
    postfix="_proximity",
    uuid=False,
    overwrite=True,
    skip_existing=False,
):
    """
    Calculate the proximity of input_raster to values
    """
    raster_list, path_list = ready_io_raster(input_rasters,
                                             out_path,
                                             overwrite,
                                             postfix=postfix,
                                             uuid=uuid)

    output = []
    for index, input_raster in enumerate(raster_list):
        out_path = path_list[index]

        if skip_existing and os.path.exists(out_path):
            output.append(out_path)
            continue

        in_arr = raster_to_array(input_raster, filled=True)
        bin_arr = (in_arr != target_value).astype("uint8")
        bin_raster = array_to_raster(bin_arr, reference=input_raster)

        in_raster = open_raster(bin_raster)
        in_raster_path = bin_raster

        if add_border:
            border_size = 1
            border_raster = add_border_to_raster(
                in_raster,
                border_size=border_size,
                border_value=0,
                overwrite=True,
            )

            in_raster = open_raster(border_raster)

            gdal.Unlink(in_raster_path)
            in_raster_path = border_raster

        src_band = in_raster.GetRasterBand(1)

        driver_name = "GTiff" if out_path is None else path_to_driver_raster(
            out_path)
        if driver_name is None:
            raise ValueError(f"Unable to parse filetype from path: {out_path}")

        driver = gdal.GetDriverByName(driver_name)
        if driver is None:
            raise ValueError(
                f"Error while creating driver from extension: {out_path}")

        mem_path = f"/vsimem/raster_proximity_tmp_{uuid4().int}.tif"

        dest_raster = driver.Create(
            mem_path,
            in_raster.RasterXSize,
            in_raster.RasterYSize,
            1,
            gdal.GetDataTypeByName("Float32"),
        )

        dest_raster.SetGeoTransform(in_raster.GetGeoTransform())
        dest_raster.SetProjection(in_raster.GetProjectionRef())
        dst_band = dest_raster.GetRasterBand(1)

        gdal.ComputeProximity(
            src_band,
            dst_band,
            [
                f"VALUES='1'",
                "DISTUNITS=GEO",
                f"MAXDIST={max_dist}",
            ],
        )

        dst_arr = dst_band.ReadAsArray()
        gdal.Unlink(mem_path)
        gdal.Unlink(in_raster_path)

        dst_arr = np.where(dst_arr > max_dist, max_dist, dst_arr)

        if invert:
            dst_arr = max_dist - dst_arr

        if weighted:
            dst_arr = dst_arr / max_dist

        if add_border:
            dst_arr = dst_arr[border_size:-border_size,
                              border_size:-border_size]

        src_band = None
        dst_band = None
        in_raster = None
        dest_raster = None

        if return_array:
            output.append(dst_arr)
        else:
            array_to_raster(dst_arr, reference=input_raster, out_path=out_path)
            output.append(out_path)

        dst_arr = None

    if isinstance(input_rasters, list):
        return output

    return output[0]
Пример #3
0
def raster_set_nodata(
    raster: Union[List[Union[gdal.Dataset, str]], gdal.Dataset, str],
    dst_nodata: Union[float, int, str, list, None],
    out_path: Union[list, str, None] = None,
    overwrite: bool = True,
    in_place: bool = False,
    prefix: str = "",
    postfix: str = "_nodata_set",
    opened: bool = False,
    creation_options: list = [],
) -> Union[list, gdal.Dataset, str]:
    """Sets all the nodata from a raster or a list of rasters.

    Args:
        raster (path | raster | list): The raster(s) to retrieve nodata values from.

        dst_nodata (float, int, str, None): The target nodata value. If 'infer' the nodata
        value is set based on the input datatype. A list of nodata values can be based matching
        the amount of input rasters. If multiple nodata values should be set, use raster_mask_values.

    **kwargs:
        out_path (path | list | None): The destination of the changed rasters. If out_paths
        are specified, in_place is automatically set to False. The path can be a folder.

        in_place (bool): Should the rasters be changed in_place or copied?

        prefix (str): Prefix to add the the output if a folder is specified in out_path.

        postfix (str): Postfix to add the the output if a folder is specified in out_path.

    Returns:
        Returns the rasters with nodata set. If in_place is True a reference to the
        changed orignal is returned, otherwise a copied memory raster or the path to the
        generated raster is outputted.
    """
    type_check(raster, [list, str, gdal.Dataset], "raster")
    type_check(dst_nodata, [float, int, str, list],
               "dst_nodata",
               allow_none=True)
    type_check(out_path, [list, str], "out_path", allow_none=True)
    type_check(overwrite, [bool], "overwrite")
    type_check(prefix, [str], "prefix")
    type_check(postfix, [str], "postfix")
    type_check(opened, [bool], "opened")
    type_check(creation_options, [list], "creation_options")

    rasters, out_names = ready_io_raster(raster, out_path, overwrite, prefix,
                                         postfix)

    rasters_metadata: List[Metadata_raster] = []
    internal_dst_nodata = None

    if isinstance(dst_nodata, str) and dst_nodata != "infer":
        raise ValueError(f"Invalid dst_nodata value. {dst_nodata}")

    if isinstance(dst_nodata, list):
        if not isinstance(raster, list) or len(dst_nodata) != len(raster):
            raise ValueError(
                "If dst_nodata is a list, raster must also be a list of equal length."
            )

        for value in dst_nodata:
            if isinstance(value, (float, int, str, None)):
                raise ValueError("Invalid type in dst_nodata list.")

            if isinstance(value, str) and value != "infer":
                raise ValueError(
                    "If dst_nodata is a string it must be 'infer'")

    output_rasters = []

    for index, internal_raster in enumerate(rasters):

        raster_metadata = None
        if len(rasters_metadata) == 0:
            raster_metadata = raster_to_metadata(internal_raster)

            if not isinstance(raster_metadata, dict):
                raise Exception("Metadata is in the wrong format.")

            rasters_metadata.append(raster_metadata)
        else:
            raster_metadata = rasters_metadata[index]

        if dst_nodata == "infer":
            internal_dst_nodata = gdal_nodata_value_from_type(
                raster_metadata["dtype_gdal_raw"])
        elif isinstance(dst_nodata, list):
            internal_dst_nodata = dst_nodata[index]
        else:
            internal_dst_nodata = dst_nodata

        if in_place:
            for band in range(raster_metadata["bands"]):
                raster_band = internal_raster.GetRasterBand(band + 1)
                raster_band.SetNodataValue(internal_dst_nodata)
                raster_band = None
        else:
            if out_path is None:
                raster_mem = raster_to_memory(internal_raster)
                raster_mem_ref = raster_to_reference(raster_mem)
            else:
                remove_if_overwrite(out_names[index], overwrite)
                raster_mem = raster_to_disk(internal_raster, out_names[index])
                raster_mem_ref = raster_to_reference(raster_mem)

            for band in range(raster_metadata["bands"]):
                raster_band = raster_mem_ref.GetRasterBand(band + 1)
                raster_band.SetNodataValue(internal_dst_nodata)

    if isinstance(raster, list):
        return output_rasters

    return output_rasters[0]
Пример #4
0
def reproject_raster(
    raster: Union[List[Union[gdal.Dataset, str]], str, gdal.Dataset],
    projection: Union[int, str, gdal.Dataset, ogr.DataSource,
                      osr.SpatialReference],
    out_path: Union[List[str], str, None] = None,
    resample_alg: str = "nearest",
    copy_if_already_correct: bool = True,
    overwrite: bool = True,
    creation_options: list = [],
    dst_nodata: Union[str, int, float] = "infer",
    prefix: str = "",
    postfix: str = "_reprojected",
) -> Union[List[Union[gdal.Dataset, str]], gdal.Dataset, str]:
    """Reproject a raster(s) to a target coordinate reference system.

    Args:
        raster(s) (list, path | raster): The raster(s) to reproject.

        projection (str | int | vector | raster): The projection is infered from
        the input. The input can be: WKT proj, EPSG proj, Proj, osr proj, or read
        from a vector or raster datasource either from path or in-memory.

    **kwargs:
        out_path (list, path | None): The destination to save to. If None then
        the output is an in-memory raster.

        resample_alg (str): The algorithm to resample the raster. The following
        are available:
            'nearest', 'bilinear', 'cubic', 'cubicSpline', 'lanczos', 'average',
            'mode', 'max', 'min', 'median', 'q1', 'q3', 'sum', 'rms'.

        overwite (bool): Is it possible to overwrite the out_path if it exists.

        creation_options (list): A list of options for the GDAL creation. Only
        used if an outpath is specified. Defaults are:
            "TILED=YES"
            "NUM_THREADS=ALL_CPUS"
            "BIGG_TIF=YES"
            "COMPRESS=LZW"

        dst_nodata (str | int | float): If dst_nodata is 'infer' the destination nodata
        is the src_nodata if one exists, otherwise it's automatically chosen based
        on the datatype. If an int or a float is given, it is used as the output nodata.

    Returns:
        An in-memory raster. If an out_path is given the output is a string containing
        the path to the newly created raster.
    """
    type_check(raster, [list, str, gdal.Dataset], "raster")
    type_check(
        projection,
        [int, str, gdal.Dataset, ogr.DataSource, osr.SpatialReference],
        "projection",
    )
    type_check(out_path, [list, str], "out_path", allow_none=True)
    type_check(resample_alg, [str], "resample_alg")
    type_check(overwrite, [bool], "overwrite")
    type_check(creation_options, [list], "creation_options")
    type_check(dst_nodata, [str, int, float], "dst_nodata")
    type_check(prefix, [str], "prefix")
    type_check(postfix, [str], "postfix")

    raster_list, path_list = ready_io_raster(raster, out_path, overwrite,
                                             prefix, postfix)

    output = []
    for index, in_raster in enumerate(raster_list):
        output.append(
            internal_reproject_raster(
                in_raster,
                projection,
                out_path=path_list[index],
                resample_alg=resample_alg,
                copy_if_already_correct=copy_if_already_correct,
                overwrite=overwrite,
                creation_options=creation_options,
                dst_nodata=dst_nodata,
                prefix=prefix,
                postfix=postfix,
            ))

    if isinstance(raster, list):
        return output

    return output[0]
Пример #5
0
def internal_reproject_raster(
    raster: Union[str, gdal.Dataset],
    projection: Union[int, str, gdal.Dataset, ogr.DataSource,
                      osr.SpatialReference],
    out_path: Optional[str] = None,
    resample_alg: str = "nearest",
    copy_if_already_correct: bool = True,
    overwrite: bool = True,
    creation_options: list = [],
    dst_nodata: Union[str, int, float] = "infer",
    prefix: str = "",
    postfix: str = "_reprojected",
) -> str:
    """OBS: Internal. Single output.

    Reproject a raster(s) to a target coordinate reference system.
    """
    type_check(raster, [str, gdal.Dataset], "raster")
    type_check(
        projection,
        [int, str, gdal.Dataset, ogr.DataSource, osr.SpatialReference],
        "projection",
    )
    type_check(out_path, [str], "out_path", allow_none=True)
    type_check(resample_alg, [str], "resample_alg")
    type_check(copy_if_already_correct, [bool], "copy_if_already_correct")
    type_check(overwrite, [bool], "overwrite")
    type_check(creation_options, [list], "creation_options")
    type_check(dst_nodata, [str, int, float], "dst_nodata")
    type_check(prefix, [str], "prefix")
    type_check(postfix, [str], "postfix")

    raster_list, path_list = ready_io_raster(raster, out_path, overwrite,
                                             prefix, postfix)
    out_name = path_list[0]
    ref = open_raster(raster_list[0])
    metadata = raster_to_metadata(ref)

    out_creation_options = default_options(creation_options)
    out_format = path_to_driver_raster(out_name)

    original_projection = parse_projection(ref)
    target_projection = parse_projection(projection)

    if not isinstance(original_projection, osr.SpatialReference):
        raise Exception("Error while parsing input projection.")

    if not isinstance(target_projection, osr.SpatialReference):
        raise Exception("Error while parsing target projection.")

    if original_projection.IsSame(target_projection):
        if not copy_if_already_correct:
            return get_raster_path(ref)

    src_nodata = metadata["nodata_value"]
    out_nodata = None
    if src_nodata is not None:
        out_nodata = src_nodata
    else:
        if dst_nodata == "infer":
            out_nodata = gdal_nodata_value_from_type(
                metadata["datatype_gdal_raw"])
        elif isinstance(dst_nodata, str):
            raise TypeError(f"dst_nodata is in a wrong format: {dst_nodata}")
        else:
            out_nodata = dst_nodata

    remove_if_overwrite(out_path, overwrite)

    reprojected = gdal.Warp(
        out_name,
        ref,
        format=out_format,
        srcSRS=original_projection,
        dstSRS=target_projection,
        resampleAlg=translate_resample_method(resample_alg),
        creationOptions=out_creation_options,
        srcNodata=metadata["nodata_value"],
        dstNodata=out_nodata,
        multithread=True,
    )

    if reprojected is None:
        raise Exception(f"Error while reprojecting raster: {raster}")

    return out_name
Пример #6
0
def warp_raster(
    raster: Union[List[Union[gdal.Dataset, str]], str, gdal.Dataset],
    out_path: Optional[Union[List[str], str]] = None,
    projection: Optional[Union[int, str, gdal.Dataset, ogr.DataSource,
                               osr.SpatialReference]] = None,
    clip_geom: Optional[Union[str, ogr.DataSource]] = None,
    target_size: Optional[Union[Tuple[Number], Number]] = None,
    target_in_pixels: bool = False,
    resample_alg: str = "nearest",
    crop_to_geom: bool = True,
    all_touch: bool = True,
    adjust_bbox: bool = True,
    overwrite: bool = True,
    creation_options: Union[list, None] = None,
    src_nodata: Union[str, int, float] = "infer",
    dst_nodata: Union[str, int, float] = "infer",
    layer_to_clip: int = 0,
    prefix: str = "",
    postfix: str = "_resampled",
) -> Union[List[str], str]:
    """Warps a raster into a target raster

    Please be aware that all_touch does not work if target_size is set.
    If all_touch is required while resampling. Do it in two steps:
    resample -> warp or resample -> clip.
    """
    type_check(raster, [list, str, gdal.Dataset], "raster")
    type_check(out_path, [list, str], "out_path", allow_none=True)
    type_check(
        projection,
        [int, str, gdal.Dataset, ogr.DataSource, osr.SpatialReference],
        "projection",
        allow_none=True,
    )
    type_check(clip_geom, [str, ogr.DataSource], "clip_geom", allow_none=True)
    type_check(
        target_size,
        [tuple, int, float, str, gdal.Dataset],
        "target_size",
        allow_none=True,
    )
    type_check(target_in_pixels, [bool], "target_in_pixels")
    type_check(resample_alg, [str], "resample_alg")
    type_check(crop_to_geom, [bool], "crop_to_geom")
    type_check(all_touch, [bool], "all_touch")
    type_check(adjust_bbox, [bool], "adjust_bbox")
    type_check(overwrite, [bool], "overwrite")
    type_check(creation_options, [list, None], "creation_options")
    type_check(src_nodata, [str, int, float], "src_nodata")
    type_check(dst_nodata, [str, int, float], "dst_nodata")
    type_check(layer_to_clip, [int], "layer_to_clip")
    type_check(prefix, [str], "prefix")
    type_check(postfix, [str], "postfix")

    if creation_options is None:
        creation_options = []

    raster_list, path_list = ready_io_raster(raster, out_path, overwrite,
                                             prefix, postfix)

    output = []
    for index, in_raster in enumerate(raster_list):
        output.append(
            _warp_raster(
                in_raster,
                out_path=path_list[index],
                projection=projection,
                clip_geom=clip_geom,
                target_size=target_size,
                target_in_pixels=target_in_pixels,
                resample_alg=resample_alg,
                crop_to_geom=crop_to_geom,
                all_touch=all_touch,
                adjust_bbox=adjust_bbox,
                overwrite=overwrite,
                creation_options=creation_options,
                src_nodata=src_nodata,
                dst_nodata=dst_nodata,
                layer_to_clip=layer_to_clip,
                prefix=prefix,
                postfix=postfix,
            ))

    if isinstance(raster, list):
        return output

    return output[0]
Пример #7
0
def _warp_raster(
    raster: Union[str, gdal.Dataset],
    out_path: Optional[str] = None,
    projection: Optional[Union[int, str, gdal.Dataset, ogr.DataSource,
                               osr.SpatialReference]] = None,
    clip_geom: Optional[Union[str, ogr.DataSource]] = None,
    target_size: Optional[Union[Tuple[Number], Number]] = None,
    target_in_pixels: bool = False,
    resample_alg: str = "nearest",
    crop_to_geom: bool = True,
    all_touch: bool = True,
    adjust_bbox: bool = True,
    overwrite: bool = True,
    creation_options: Union[list, None] = None,
    src_nodata: Union[str, int, float] = "infer",
    dst_nodata: Union[str, int, float] = "infer",
    layer_to_clip: int = 0,
    prefix: str = "",
    postfix: str = "_resampled",
) -> str:
    """WARNING: INTERNAL. DO NOT USE."""
    raster_list, path_list = ready_io_raster(raster, out_path, overwrite,
                                             prefix, postfix)

    origin = open_raster(raster_list[0])
    out_name = path_list[0]
    raster_metadata = raster_to_metadata(origin, create_geometry=True)

    # options
    warp_options = []
    if all_touch:
        warp_options.append("CUTLINE_ALL_TOUCHED=TRUE")
    else:
        warp_options.append("CUTLINE_ALL_TOUCHED=FALSE")

    origin_projection: osr.SpatialReference = raster_metadata["projection_osr"]
    origin_extent: ogr.Geometry = raster_metadata["extent_geom_latlng"]

    target_projection = origin_projection
    if projection is not None:
        target_projection = parse_projection(projection)

    if clip_geom is not None:
        if is_raster(clip_geom):
            opened_raster = open_raster(clip_geom)
            clip_metadata_raster = raster_to_metadata(opened_raster,
                                                      create_geometry=True)
            clip_ds = clip_metadata_raster["extent_datasource"]
            clip_metadata = internal_vector_to_metadata(clip_ds,
                                                        create_geometry=True)
        elif is_vector(clip_geom):
            clip_ds = open_vector(clip_geom)
            clip_metadata = internal_vector_to_metadata(clip_ds,
                                                        create_geometry=True)
        else:
            if file_exists(clip_geom):
                raise ValueError(f"Unable to parse clip geometry: {clip_geom}")
            else:
                raise ValueError(f"Unable to find clip geometry {clip_geom}")

        if layer_to_clip > (clip_metadata["layer_count"] - 1):
            raise ValueError("Requested an unable layer_to_clip.")

        clip_projection = clip_metadata["projection_osr"]
        clip_extent = clip_metadata["extent_geom_latlng"]

        # Fast check: Does the extent of the two inputs overlap?
        if not origin_extent.Intersects(clip_extent):
            raise Exception("Clipping geometry did not intersect raster.")

        # Check if projections match, otherwise reproject target geom.
        if not target_projection.IsSame(clip_projection):
            clip_metadata["extent"] = reproject_extent(
                clip_metadata["extent"],
                clip_projection,
                target_projection,
            )

        # The extent needs to be reprojected to the target.
        # this ensures that adjust_bbox works.
        x_min_og, y_max_og, x_max_og, y_min_og = reproject_extent(
            raster_metadata["extent"],
            origin_projection,
            target_projection,
        )
        output_bounds = (x_min_og, y_min_og, x_max_og, y_max_og
                         )  # gdal_warp format

        if crop_to_geom:

            if adjust_bbox:
                output_bounds = align_bbox(
                    raster_metadata["extent"],
                    clip_metadata["extent"],
                    raster_metadata["pixel_width"],
                    raster_metadata["pixel_height"],
                    warp_format=True,
                )

            else:
                x_min_og, y_max_og, x_max_og, y_min_og = clip_metadata[
                    "extent"]
                output_bounds = (
                    x_min_og,
                    y_min_og,
                    x_max_og,
                    y_max_og,
                )  # gdal_warp format

        if clip_metadata["layer_count"] > 1:
            clip_ds = vector_to_memory(
                clip_ds,
                memory_path=f"clip_geom_{uuid4().int}.gpkg",
                layer_to_extract=layer_to_clip,
            )
        elif not isinstance(clip_ds, str):
            clip_ds = vector_to_memory(
                clip_ds,
                memory_path=f"clip_geom_{uuid4().int}.gpkg",
            )

        if clip_ds is None:
            raise ValueError(f"Unable to parse input clip geom: {clip_geom}")

    x_res, y_res, x_pixels, y_pixels = raster_size_from_list(
        target_size, target_in_pixels)

    out_format = path_to_driver_raster(out_name)
    out_creation_options = default_options(creation_options)

    # nodata
    out_nodata = None
    if src_nodata is not None:
        out_nodata = raster_metadata["nodata_value"]
    else:
        if dst_nodata == "infer":
            out_nodata = gdal_nodata_value_from_type(
                raster_metadata["datatype_gdal_raw"])
        else:
            out_nodata = dst_nodata

    # Removes file if it exists and overwrite is True.
    remove_if_overwrite(out_path, overwrite)

    warped = gdal.Warp(
        out_name,
        origin,
        xRes=x_res,
        yRes=y_res,
        width=x_pixels,
        height=y_pixels,
        cutlineDSName=clip_ds,
        outputBounds=output_bounds,
        format=out_format,
        srcSRS=origin_projection,
        dstSRS=target_projection,
        resampleAlg=translate_resample_method(resample_alg),
        creationOptions=out_creation_options,
        warpOptions=warp_options,
        srcNodata=src_nodata,
        dstNodata=out_nodata,
        targetAlignedPixels=False,
        cropToCutline=False,
        multithread=True,
    )

    if warped is None:
        raise Exception(f"Error while warping raster: {raster}")

    return out_name
Пример #8
0
def internal_resample_raster(
    raster: Union[str, gdal.Dataset],
    target_size: Union[tuple, int, float, str, gdal.Dataset],
    target_in_pixels: bool = False,
    out_path: Optional[str] = None,
    resample_alg: str = "nearest",
    overwrite: bool = True,
    creation_options: list = [],
    dtype=None,
    dst_nodata: Union[str, int, float] = "infer",
    prefix: str = "",
    postfix: str = "_resampled",
    add_uuid: bool = False,
) -> str:
    """OBS: Internal. Single output.

    Reprojects a raster given a target projection. Beware if your input is in
    latitude and longitude, you'll need to specify the target_size in degrees as well.
    """
    type_check(raster, [str, gdal.Dataset], "raster")
    type_check(target_size, [tuple, int, float, str, gdal.Dataset],
               "target_size")
    type_check(target_in_pixels, [bool], "target_in_pixels")
    type_check(out_path, [list, str], "out_path", allow_none=True)
    type_check(resample_alg, [str], "resample_alg")
    type_check(overwrite, [bool], "overwrite")
    type_check(creation_options, [list], "creation_options")
    type_check(dst_nodata, [str, int, float], "dst_nodata")
    type_check(prefix, [str], "prefix")
    type_check(postfix, [str], "postfix")

    raster_list, path_list = ready_io_raster(
        raster,
        out_path,
        overwrite=overwrite,
        prefix=prefix,
        postfix=postfix,
        uuid=add_uuid,
    )

    ref = open_raster(raster_list[0])
    metadata = raster_to_metadata(ref)
    out_name = path_list[0]

    x_res, y_res, x_pixels, y_pixels = raster_size_from_list(
        target_size, target_in_pixels)

    out_creation_options = default_options(creation_options)
    out_format = path_to_driver_raster(out_name)

    src_nodata = metadata["nodata_value"]
    out_nodata = None
    if src_nodata is not None:
        out_nodata = src_nodata
    else:
        if dst_nodata == "infer":
            out_nodata = gdal_nodata_value_from_type(
                metadata["datatype_gdal_raw"])
        elif isinstance(dst_nodata, str):
            raise TypeError(f"dst_nodata is in a wrong format: {dst_nodata}")
        else:
            out_nodata = dst_nodata

    remove_if_overwrite(out_path, overwrite)

    resampled = gdal.Warp(
        out_name,
        ref,
        width=x_pixels,
        height=y_pixels,
        xRes=x_res,
        yRes=y_res,
        format=out_format,
        outputType=translate_datatypes(dtype),
        resampleAlg=translate_resample_method(resample_alg),
        creationOptions=out_creation_options,
        srcNodata=metadata["nodata_value"],
        dstNodata=out_nodata,
        multithread=True,
    )

    if resampled is None:
        raise Exception(f"Error while resampling raster: {out_name}")

    return out_name
Пример #9
0
def resample_raster(
    raster: Union[List[Union[str, gdal.Dataset]], str, gdal.Dataset],
    target_size: Union[tuple, int, float, str, gdal.Dataset],
    target_in_pixels: bool = False,
    out_path: Optional[Union[list, str]] = None,
    resample_alg: str = "nearest",
    overwrite: bool = True,
    creation_options: list = [],
    dtype=None,
    dst_nodata: Union[str, int, float] = "infer",
    prefix: str = "",
    postfix: str = "_resampled",
) -> Union[List[str], str]:
    """Reprojects a raster given a target projection. Beware if your input is in
        latitude and longitude, you'll need to specify the target_size in degrees as well.

    Args:
        raster (list, path | raster): The raster to reproject.

        target_size (str | int | vector | raster): The target resolution of the
        raster. In the same unit as the projection of the raster.
        It's better to reproject to a projected coordinate system for resampling.
        If a raster is the target_size the function will read the pixel size from
        that raster.

    **kwargs:
        out_path (path | None): The destination to save to. If None then
        the output is an in-memory raster.

        resample_alg (str): The algorithm to resample the raster. The following
        are available:
            'nearest', 'bilinear', 'cubic', 'cubicSpline', 'lanczos', 'average',
            'mode', 'max', 'min', 'median', 'q1', 'q3', 'sum', 'rms'.

        overwite (bool): Is it possible to overwrite the out_path if it exists.

        creation_options (list): A list of options for the GDAL creation. Only
        used if an outpath is specified. Defaults are:
            "TILED=YES"
            "NUM_THREADS=ALL_CPUS"
            "BIGG_TIF=YES"
            "COMPRESS=LZW"

        dst_nodata (str | int | float): If dst_nodata is 'infer' the destination nodata
        is the src_nodata if one exists, otherwise it's automatically chosen based
        on the datatype. If an int or a float is given, it is used as the output nodata.

    Returns:
        An in-memory raster. If an out_path is given the output is a string containing
        the path to the newly created raster.
    """
    type_check(raster, [list, str, gdal.Dataset], "raster")
    type_check(target_size, [tuple, int, float, str, gdal.Dataset],
               "target_size")
    type_check(target_in_pixels, [bool], "target_in_pixels")
    type_check(out_path, [list, str], "out_path", allow_none=True)
    type_check(resample_alg, [str], "resample_alg")
    type_check(overwrite, [bool], "overwrite")
    type_check(creation_options, [list], "creation_options")
    type_check(dst_nodata, [str, int, float], "dst_nodata")
    type_check(prefix, [str], "prefix")
    type_check(postfix, [str], "postfix")

    raster_list, path_list = ready_io_raster(raster, out_path, overwrite,
                                             prefix, postfix)

    resampled_rasters = []
    for index, in_raster in enumerate(raster_list):
        resampled_rasters.append(
            internal_resample_raster(
                in_raster,
                target_size,
                target_in_pixels=target_in_pixels,
                out_path=path_list[index],
                resample_alg=resample_alg,
                overwrite=overwrite,
                creation_options=creation_options,
                dtype=dtype,
                dst_nodata=dst_nodata,
                prefix=prefix,
                postfix=postfix,
            ))

    if isinstance(raster, list):
        return resampled_rasters

    return resampled_rasters[0]
Пример #10
0
def align_rasters(
    rasters: List[Union[str, gdal.Dataset]],
    out_path: Optional[Union[List[str], str]] = None,
    master: Optional[Union[gdal.Dataset, str]] = None,
    postfix: str = "_aligned",
    bounding_box: Union[str, gdal.Dataset, ogr.DataSource, list,
                        tuple] = "intersection",
    resample_alg: str = "nearest",
    target_size: Optional[Union[tuple, list, int, float, str,
                                gdal.Dataset]] = None,
    target_in_pixels: bool = False,
    projection: Optional[Union[int, str, gdal.Dataset, ogr.DataSource,
                               osr.SpatialReference]] = None,
    overwrite: bool = True,
    creation_options: list = [],
    src_nodata: Optional[Union[str, int, float]] = "infer",
    dst_nodata: Optional[Union[str, int, float]] = "infer",
    prefix: str = "",
    ram=8000,
    skip_existing=False,
) -> List[str]:
    type_check(rasters, [list], "rasters")
    type_check(out_path, [list, str], "out_path", allow_none=True)
    type_check(master, [list, str], "master", allow_none=True)
    type_check(bounding_box, [str, gdal.Dataset, ogr.DataSource, list, tuple],
               "bounding_box")
    type_check(resample_alg, [str], "resample_alg")
    type_check(
        target_size,
        [tuple, list, int, float, str, gdal.Dataset],
        "target_size",
        allow_none=True,
    )
    type_check(
        target_in_pixels,
        [int, str, gdal.Dataset, ogr.DataSource, osr.SpatialReference],
        "target_in_pixels",
        allow_none=True,
    )
    type_check(overwrite, [bool], "overwrite")
    type_check(creation_options, [list], "creation_options")
    type_check(src_nodata, [str, int, float], "src_nodata", allow_none=True)
    type_check(dst_nodata, [str, int, float], "dst_nodata", allow_none=True)
    type_check(prefix, [str], "prefix")
    type_check(postfix, [str], "postfix")

    raster_list, path_list = ready_io_raster(
        rasters,
        out_path,
        overwrite=overwrite,
        prefix=prefix,
        postfix=postfix,
        uuid=False,
    )

    x_pixels = None
    y_pixels = None
    x_res = None
    y_res = None
    target_projection = None
    target_bounds = None

    reprojected_rasters: List[str] = []

    # Read the metadata for each raster.
    # Catalogue the used projections, to choose the most common one if necessary.
    used_projections: List[dict] = []
    metadata: List[str] = []

    for raster in rasters:
        meta = raster_to_metadata(raster)
        metadata.append(meta)
        used_projections.append(meta["projection"])

    # If there is a master layer, copy information from that layer.
    if master is not None:
        master_metadata = raster_to_metadata(master)

        target_projection = master_metadata["projection_osr"]
        x_min, y_max, x_max, y_min = master_metadata["extent"]

        # Set the target values.
        target_bounds = (x_min, y_min, x_max, y_max)
        x_res = master_metadata["pixel_width"]
        y_res = master_metadata["pixel_height"]
        x_pixels = master_metadata["width"]
        y_pixels = master_metadata["height"]
        target_size = (x_res, y_res)

        target_in_pixels = False

    # We allow overwrite of parameters specifically set.
    # Handle projection
    if projection is not None:
        target_projection = parse_projection(projection)

    # If no projection is specified, other from master or parameters. The most common one is chosen.
    elif target_projection is None:

        # Sort and count the projections
        projection_counter: dict = {}
        for proj in used_projections:
            if proj in projection_counter:
                projection_counter[proj] += 1
            else:
                projection_counter[proj] = 1

        # Choose most common projection
        most_common_projection = sorted(projection_counter,
                                        key=projection_counter.get,
                                        reverse=True)

        target_projection = parse_projection(most_common_projection[0])

    if target_size is not None:

        # If a raster is input, use it's pixel size as target values.
        if isinstance(target_size, (gdal.Dataset, str)):
            if isinstance(target_size, str) and not is_raster(target_size):
                raise ValueError(
                    f"Unable to parse the raster used for target_size: {target_size}"
                )

            # Reprojection is necessary to ensure the correct pixel_size
            reprojected_target_size = internal_reproject_raster(
                target_size, target_projection)
            target_size_raster = raster_to_metadata(reprojected_target_size)

            # Set the target values.
            x_res = target_size_raster["width"]
            y_res = target_size_raster["height"]
        else:
            # If a list, tuple, int or float is passed. Turn them into target values.
            x_res, y_res, x_pixels, y_pixels = raster_size_from_list(
                target_size, target_in_pixels)

    # If nothing has been specified, we will infer the pixel_size based on the median of all input rasters.
    elif x_res is None and y_res is None and x_pixels is None and y_pixels is None:

        # Ready numpy arrays for insertion
        x_res_arr = np.empty(len(raster_list), dtype="float32")
        y_res_arr = np.empty(len(raster_list), dtype="float32")

        for index, raster in enumerate(raster_list):
            # It is necessary to reproject each raster, as pixel height and width might be different after projection.
            reprojected = internal_reproject_raster(raster, target_projection)
            target_size_raster = raster_to_metadata(reprojected)

            # Add the pixel sizes to the numpy arrays
            x_res_arr[index] = target_size_raster["pixel_width"]
            y_res_arr[index] = target_size_raster["pixel_height"]

            # Keep track of the reprojected arrays so we only reproject rasters once.
            reprojected_rasters.append(reprojected)

        # Use the median values of pixel sizes as target values.
        x_res = np.median(x_res_arr)
        y_res = np.median(y_res_arr)

    if target_bounds is None:

        # If a bounding box is supplied, simply use that one. It must be in the target projection.
        if isinstance(bounding_box, (list, tuple)):
            if len(bounding_box) != 4:
                raise ValueError(
                    "bounding_box as a list/tuple must have 4 values.")
            target_bounds = bounding_box

        # If the bounding box is a raster. Take the extent and reproject it to the target projection.
        elif is_raster(bounding_box):
            reprojected_bbox_raster = raster_to_metadata(
                internal_reproject_raster(bounding_box, target_projection))

            x_min, y_max, x_max, y_min = reprojected_bbox_raster["extent"]

            # add to target values.
            target_bounds = (x_min, y_min, x_max, y_max)

        # If the bounding box is a raster. Take the extent and reproject it to the target projection.
        elif is_vector(bounding_box):
            reprojected_bbox_vector = internal_vector_to_metadata(
                internal_reproject_vector(bounding_box, target_projection))

            x_min, y_max, x_max, y_min = reprojected_bbox_vector["extent"]

            # add to target values.
            target_bounds = (x_min, y_min, x_max, y_max)

        # If the bounding box is a string, we either take the union or the intersection of all the
        # bounding boxes of the input rasters.
        elif isinstance(bounding_box, str):
            if bounding_box == "intersection" or bounding_box == "union":
                extents = []

                # If the rasters have not been reprojected, reproject them now.
                if len(reprojected_rasters) != len(raster_list):
                    reprojected_rasters = []

                    for raster in raster_list:
                        raster_metadata = raster_to_metadata(raster)

                        if raster_metadata["projection_osr"].IsSame(
                                target_projection):
                            reprojected_rasters.append(raster)
                        else:
                            reprojected = internal_reproject_raster(
                                raster, target_projection)
                            reprojected_rasters.append(reprojected)

                # Add the extents of the reprojected rasters to the extents list.
                for reprojected_raster in reprojected_rasters:
                    reprojected_raster_metadata = dict(
                        raster_to_metadata(reprojected_raster))
                    extents.append(reprojected_raster_metadata["extent"])

                # Placeholder values
                x_min, y_max, x_max, y_min = extents[0]

                # Loop the extents. Narrowing if intersection, expanding if union.
                for index, extent in enumerate(extents):
                    if index == 0:
                        continue

                    if bounding_box == "intersection":
                        if extent[0] > x_min:
                            x_min = extent[0]
                        if extent[1] < y_max:
                            y_max = extent[1]
                        if extent[2] < x_max:
                            x_max = extent[2]
                        if extent[3] > y_min:
                            y_min = extent[3]

                    elif bounding_box == "union":
                        if extent[0] < x_min:
                            x_min = extent[0]
                        if extent[1] > y_max:
                            y_max = extent[1]
                        if extent[2] > x_max:
                            x_max = extent[2]
                        if extent[3] < y_min:
                            y_min = extent[3]

                # Add to target values.
                target_bounds = (x_min, y_min, x_max, y_max)

            else:
                raise ValueError(
                    f"Unable to parse or infer target_bounds: {target_bounds}")
        else:
            raise ValueError(
                f"Unable to parse or infer target_bounds: {target_bounds}")
    """ 
        If the rasters have not been reprojected, we reproject them now.
        The reprojection is necessary as warp has to be a two step process
        in order to align the rasters properly. This might not be necessary
        in a future version of gdal.
    """
    if len(reprojected_rasters) != len(raster_list):
        reprojected_rasters = []

        for raster in raster_list:
            raster_metadata = raster_to_metadata(raster)

            # If the raster is already the correct projection, simply append the raster.
            if raster_metadata["projection_osr"].IsSame(target_projection):
                reprojected_rasters.append(raster)
            else:
                reprojected = internal_reproject_raster(
                    raster, target_projection)
                reprojected_rasters.append(reprojected)

    # If any of the target values are still undefined. Throw an error!
    if target_projection is None or target_bounds is None:
        raise Exception(
            "Error while preparing the target projection or bounds.")

    if x_res is None and y_res is None and x_pixels is None and y_pixels is None:
        raise Exception("Error while preparing the target pixel size.")

    # This is the list of rasters to return. If output is not memory, it's a list of paths.
    return_list: List[str] = []
    for index, raster in enumerate(reprojected_rasters):
        raster_metadata = raster_to_metadata(raster)

        out_name = path_list[index]
        out_format = path_to_driver_raster(out_name)

        if skip_existing and os.path.exists(out_name):
            return_list.append(out_name)
            continue

        # Handle nodata.
        out_src_nodata = None
        out_dst_nodata = None
        if src_nodata == "infer":
            out_src_nodata = raster_metadata["nodata_value"]

            if out_src_nodata is None:
                out_src_nodata = gdal_nodata_value_from_type(
                    raster_metadata["datatype_gdal_raw"])

        elif src_nodata == None:
            out_src_nodata = None
        elif not isinstance(src_nodata, str):
            out_src_nodata = src_nodata

        if dst_nodata == "infer":
            out_dst_nodata = out_src_nodata
        elif dst_nodata == False or dst_nodata == None:
            out_dst_nodata = None
        elif src_nodata == None:
            out_dst_nodata = None
        elif not isinstance(dst_nodata, str):
            out_dst_nodata = dst_nodata

        # Removes file if it exists and overwrite is True.
        remove_if_overwrite(out_name, overwrite)

        # Hand over to gdal.Warp to do the heavy lifting!
        warped = gdal.Warp(
            out_name,
            raster,
            xRes=x_res,
            yRes=y_res,
            width=x_pixels,
            height=y_pixels,
            dstSRS=target_projection,
            outputBounds=target_bounds,
            format=out_format,
            resampleAlg=translate_resample_method(resample_alg),
            creationOptions=default_options(creation_options),
            srcNodata=out_src_nodata,
            dstNodata=out_dst_nodata,
            targetAlignedPixels=False,
            cropToCutline=False,
            multithread=True,
            warpMemoryLimit=ram,
        )

        if warped == None:
            raise Exception("Error while warping rasters.")

        return_list.append(out_name)

    if not rasters_are_aligned(return_list, same_extent=True):
        raise Exception("Error while aligning rasters. Output is not aligned")

    return return_list
Пример #11
0
def _clip_raster(
    raster: Union[str, gdal.Dataset],
    clip_geom: Union[str, ogr.DataSource, gdal.Dataset],
    out_path: Optional[str] = None,
    resample_alg: str = "nearest",
    crop_to_geom: bool = True,
    adjust_bbox: bool = True,
    all_touch: bool = True,
    overwrite: bool = True,
    creation_options: list = [],
    dst_nodata: Union[str, int, float] = "infer",
    layer_to_clip: int = 0,
    prefix: str = "",
    postfix: str = "_clipped",
    verbose: int = 1,
    uuid: bool = False,
    ram: int = 8000,
) -> str:
    """OBS: Internal. Single output.

    Clips a raster(s) using a vector geometry or the extents of
    a raster.
    """
    type_check(raster, [str, gdal.Dataset], "raster")
    type_check(clip_geom, [str, ogr.DataSource, gdal.Dataset], "clip_geom")
    type_check(out_path, [str], "out_path", allow_none=True)
    type_check(resample_alg, [str], "resample_alg")
    type_check(crop_to_geom, [bool], "crop_to_geom")
    type_check(adjust_bbox, [bool], "adjust_bbox")
    type_check(all_touch, [bool], "all_touch")
    type_check(dst_nodata, [str, int, float], "dst_nodata")
    type_check(layer_to_clip, [int], "layer_to_clip")
    type_check(overwrite, [bool], "overwrite")
    type_check(creation_options, [list], "creation_options")
    type_check(prefix, [str], "prefix")
    type_check(postfix, [str], "postfix")
    type_check(verbose, [int], "verbose")
    type_check(uuid, [bool], "uuid")

    _, path_list = ready_io_raster(raster,
                                   out_path,
                                   overwrite=overwrite,
                                   prefix=prefix,
                                   postfix=postfix,
                                   uuid=uuid)

    if out_path is not None:
        if "vsimem" not in out_path:
            if not os.path.isdir(os.path.split(os.path.normpath(out_path))[0]):
                raise ValueError(
                    f"out_path folder does not exists: {out_path}")

    # Input is a vector.
    if is_vector(clip_geom):
        clip_ds = open_vector(clip_geom)

        clip_metadata = internal_vector_to_metadata(
            clip_ds, process_layer=layer_to_clip)

        if clip_metadata["layer_count"] > 1:
            clip_ds = internal_vector_to_memory(clip_ds,
                                                layer_to_extract=layer_to_clip)

        if isinstance(clip_ds, ogr.DataSource):
            clip_ds = clip_ds.GetName()

    # Input is a raster (use extent)
    elif is_raster(clip_geom):
        clip_metadata = raster_to_metadata(clip_geom, create_geometry=True)
        clip_metadata["layer_count"] = 1
        clip_ds = clip_metadata["extent_datasource"].GetName()
    else:
        if file_exists(clip_geom):
            raise ValueError(f"Unable to parse clip geometry: {clip_geom}")
        else:
            raise ValueError(f"Unable to locate clip geometry {clip_geom}")

    if layer_to_clip > (clip_metadata["layer_count"] - 1):
        raise ValueError("Requested an unable layer_to_clip.")

    if clip_ds is None:
        raise ValueError(f"Unable to parse input clip geom: {clip_geom}")

    clip_projection = clip_metadata["projection_osr"]
    clip_extent = clip_metadata["extent"]

    # options
    warp_options = []
    if all_touch:
        warp_options.append("CUTLINE_ALL_TOUCHED=TRUE")
    else:
        warp_options.append("CUTLINE_ALL_TOUCHED=FALSE")

    origin_layer = open_raster(raster)

    raster_metadata = raster_to_metadata(raster)
    origin_projection = raster_metadata["projection_osr"]
    origin_extent = raster_metadata["extent"]

    # Check if projections match, otherwise reproject target geom.
    if not origin_projection.IsSame(clip_projection):
        clip_metadata["extent"] = reproject_extent(
            clip_metadata["extent"],
            clip_projection,
            origin_projection,
        )

    # Fast check: Does the extent of the two inputs overlap?
    if not gdal_bbox_intersects(origin_extent, clip_extent):
        raise Exception("Geometries did not intersect.")

    output_bounds = raster_metadata["extent_gdal_warp"]

    if crop_to_geom:

        if adjust_bbox:
            output_bounds = align_bbox(
                raster_metadata["extent"],
                clip_metadata["extent"],
                raster_metadata["pixel_width"],
                raster_metadata["pixel_height"],
                warp_format=True,
            )

        else:
            output_bounds = clip_metadata["extent_gdal_warp"]

    # formats
    out_name = path_list[0]
    out_format = path_to_driver_raster(out_name)
    out_creation_options = default_options(creation_options)

    # nodata
    src_nodata = raster_metadata["nodata_value"]
    out_nodata = None
    if src_nodata is not None:
        out_nodata = src_nodata
    else:
        if dst_nodata == "infer":
            out_nodata = gdal_nodata_value_from_type(
                raster_metadata["datatype_gdal_raw"])
        elif dst_nodata is None:
            out_nodata = None
        elif isinstance(dst_nodata, (int, float)):
            out_nodata = dst_nodata
        else:
            raise ValueError(f"Unable to parse nodata_value: {dst_nodata}")

    # Removes file if it exists and overwrite is True.
    remove_if_overwrite(out_path, overwrite)

    if verbose == 0:
        gdal.PushErrorHandler("CPLQuietErrorHandler")

    clipped = gdal.Warp(
        out_name,
        origin_layer,
        format=out_format,
        resampleAlg=translate_resample_method(resample_alg),
        targetAlignedPixels=False,
        outputBounds=output_bounds,
        xRes=raster_metadata["pixel_width"],
        yRes=raster_metadata["pixel_height"],
        cutlineDSName=clip_ds,
        cropToCutline=
        False,  # GDAL does this incorrectly when targetAlignedPixels is True.
        creationOptions=out_creation_options,
        warpMemoryLimit=ram,
        warpOptions=warp_options,
        srcNodata=raster_metadata["nodata_value"],
        dstNodata=out_nodata,
        multithread=True,
    )

    if verbose == 0:
        gdal.PopErrorHandler()

    if clipped is None:
        raise Exception("Error while clipping raster.")

    return out_name
Пример #12
0
def clip_raster(
    raster: Union[List[Union[str, gdal.Dataset]], str, gdal.Dataset],
    clip_geom: Union[str, ogr.DataSource, gdal.Dataset],
    out_path: Union[List[str], str, None] = None,
    resample_alg: str = "nearest",
    crop_to_geom: bool = True,
    adjust_bbox: bool = True,
    all_touch: bool = True,
    prefix: str = "",
    postfix: str = "_clipped",
    overwrite: bool = True,
    creation_options: list = [],
    dst_nodata: Union[str, int, float] = "infer",
    layer_to_clip: int = 0,
    verbose: int = 1,
    uuid: bool = False,
    ram: int = 8000,
) -> Union[list, gdal.Dataset, str]:
    """Clips a raster(s) using a vector geometry or the extents of
        a raster.

    Args:
        raster(s) (list, path | raster): The raster(s) to clip.

        clip_geom (path | vector | raster): The geometry to use to clip
        the raster

    **kwargs:
        out_path (list, path | None): The destination to save to. If None then
        the output is an in-memory raster.

        resample_alg (str): The algorithm to resample the raster. The following
        are available:
            'nearest', 'bilinear', 'cubic', 'cubicSpline', 'lanczos', 'average',
            'mode', 'max', 'min', 'median', 'q1', 'q3', 'sum', 'rms'.

        crop_to_geom (bool): Should the extent of the raster be clipped
        to the extent of the clipping geometry.

        all_touch (bool): Should all the pixels touched by the clipped
        geometry be included or only those which centre lie within the
        geometry.

        overwite (bool): Is it possible to overwrite the out_path if it exists.

        creation_options (list): A list of options for the GDAL creation. Only
        used if an outpath is specified. Defaults are:
            "TILED=YES"
            "NUM_THREADS=ALL_CPUS"
            "BIGG_TIF=YES"
            "COMPRESS=LZW"

        dst_nodata (str | int | float): If dst_nodata is 'infer' the destination nodata
        is the src_nodata if one exists, otherwise it's automatically chosen based
        on the datatype. If an int or a float is given, it is used as the output nodata.

        layer_to_clip (int): The layer in the input vector to use for clipping.

    Returns:
        An in-memory raster. If an out_path is given the output is a string containing
        the path to the newly created raster.
    """
    type_check(raster, [list, str, gdal.Dataset], "raster")
    type_check(clip_geom, [str, ogr.DataSource, gdal.Dataset], "clip_geom")
    type_check(out_path, [list, str], "out_path", allow_none=True)
    type_check(resample_alg, [str], "resample_alg")
    type_check(crop_to_geom, [bool], "crop_to_geom")
    type_check(adjust_bbox, [bool], "adjust_bbox")
    type_check(all_touch, [bool], "all_touch")
    type_check(dst_nodata, [str, int, float], "dst_nodata")
    type_check(layer_to_clip, [int], "layer_to_clip")
    type_check(overwrite, [bool], "overwrite")
    type_check(creation_options, [list], "creation_options")
    type_check(prefix, [str], "prefix")
    type_check(postfix, [str], "postfix")
    type_check(verbose, [int], "verbose")
    type_check(uuid, [bool], "uuid")

    raster_list, path_list = ready_io_raster(
        raster,
        out_path,
        overwrite=overwrite,
        prefix=prefix,
        postfix=postfix,
        uuid=uuid,
    )

    output = []
    for index, in_raster in enumerate(raster_list):
        output.append(
            _clip_raster(
                in_raster,
                clip_geom,
                out_path=path_list[index],
                resample_alg=resample_alg,
                crop_to_geom=crop_to_geom,
                adjust_bbox=adjust_bbox,
                all_touch=all_touch,
                dst_nodata=dst_nodata,
                layer_to_clip=layer_to_clip,
                overwrite=overwrite,
                creation_options=creation_options,
                prefix=prefix,
                postfix=postfix,
                verbose=verbose,
                ram=ram,
            ))

    if isinstance(raster, list):
        return output

    return output[0]