Beispiel #1
0
    async def point(self, lon: float, lat: float, **kwargs: Any) -> List:
        """point"""
        coords = [lon, lat]
        if self.epsg != 4326:
            coords = [
                pt[0]
                for pt in transform_coords(
                    WGS84, CRS.from_epsg(self.epsg), [coords[0]], [coords[1]]
                )
            ]
        ifd = self.ifds[0]
        geotransform = self.geotransform()
        invgt = ~geotransform

        # Transform request point to pixel coordinates relative to geotransform
        image_x, image_y = invgt * coords
        xtile = math.floor((image_x + 1e-6) / ifd.TileWidth.value)
        ytile = math.floor((image_y + 1e-6) / ifd.TileHeight.value)
        tile = await self.get_tile(xtile, ytile, 0)

        # Calculate index of pixel relative to the tile
        xindex = int(image_x % ifd.TileWidth.value)
        yindex = int(image_y % ifd.TileHeight.value)

        return tile[:, xindex, yindex].tolist()
Beispiel #2
0
def calculate_pixel_area(transform, width, height):
    """Calculates an approximate pixel area based on finding the UTM zone that
    contains the center latitude / longitude of the window.

    Parameters
    ----------
    transform : Affine object
    width : int
        number of pixels in window
    height : int
        number of pixels in window

    Returns
    -------
    area of a pixel (in meters)
    """

    src_crs = "EPSG:4326"

    cell_x = transform.a
    cell_y = abs(transform.e)

    xmin = transform.c
    xmax = transform.c + ((width + 0) * cell_x)
    center_x = ((xmax - xmin) / 2) + xmin

    ymax = transform.f if transform.e < 0 else transform.f + cell_y * (height +
                                                                       0)
    ymin = transform.f if transform.e > 0 else transform.f + transform.e * (
        height + 0)
    center_y = ((ymax - ymin) / 2) + ymin

    ### to use UTM
    # UTM zones start numbered at 1 at -180 degrees, in 6 degree bands
    zone = int(round((center_x - -180) / 6.0)) + 1
    dst_crs = "+proj=utm +zone={} +ellps=GRS80 +datum=NAD83 +units=m +no_defs".format(
        zone)

    ### to use a custom Albers
    # inset = (ymax - ymin) / 6.0
    # lat1 = ymin + inset
    # lat2 = ymax - inset
    # dst_crs = "+proj=aea +lat_1={:.1f} +lat_2={:.1f} +lat_0={:.1f} +lon_0={:.1f} +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs".format(
    #     lat1, lat2, center_y, center_x
    # )

    xs = [center_x, center_x + cell_x]
    ys = [center_y, center_y + cell_y]
    (x1, x2), (y1, y2) = transform_coords(src_crs, dst_crs, xs, ys)
    area = abs(x1 - x2) * abs(y1 - y2)

    return area
Beispiel #3
0
 async def point(
     self,
     coords: Tuple[float, float],
     coords_crs: CRS = WGS84,
 ) -> np.ndarray:
     if coords_crs != self.cog.epsg:
         coords = [
             pt[0] for pt in transform_coords(coords_crs,
                                              CRS.from_epsg(self.cog.epsg),
                                              [coords[0]], [coords[1]])
         ]
     arr = await self.cog.point(*coords)
     return arr
Beispiel #4
0
def point(
    src_dst: Union[DatasetReader, DatasetWriter, WarpedVRT],
    coordinates: Tuple[float, float],
    indexes: Optional[Union[Sequence[int], int]] = None,
    coord_crs: CRS = constants.WGS84_CRS,
    masked: bool = True,
    nodata: Optional[Union[float, int, str]] = None,
    unscale: bool = False,
    resampling_method: Resampling = "nearest",
    vrt_options: Optional[Dict] = None,
) -> List:
    """
    Read point value

    Attributes
    ----------
        src_dst : rasterio.io.DatasetReader
            rasterio.io.DatasetReader object
        coordinates : tuple
            (X, Y) coordinates.
        indexes : list of ints or a single int, optional
            Band indexes
        coord_crs : rasterio.crs.CRS, optional
            (X, Y) coordinate system. Default is WGS84/EPSG:4326.
        nodata: int or float, optional
        unscale, bool, optional
            If True, apply scale and offset to the data.
            Default is set to False.
        masked : bool
            Whether to mask samples that fall outside the extent of the dataset.
            Default is set to True.
        vrt_options: dict, optional
            These will be passed to the rasterio.warp.WarpedVRT class.

    Returns
    -------
        point : list
            List of pixel values per bands indexes.

    """
    if isinstance(indexes, int):
        indexes = (indexes,)

    lon, lat = transform_coords(
        coord_crs, src_dst.crs, [coordinates[0]], [coordinates[1]]
    )
    if not (
        (src_dst.bounds[0] < lon[0] < src_dst.bounds[2])
        and (src_dst.bounds[1] < lat[0] < src_dst.bounds[3])
    ):
        raise PointOutsideBounds("Point is outside dataset bounds")

    indexes = indexes if indexes is not None else src_dst.indexes

    vrt_params: Dict[str, Any] = {
        "add_alpha": True,
        "resampling": Resampling[resampling_method],
    }
    nodata = nodata if nodata is not None else src_dst.nodata
    if nodata is not None:
        vrt_params.update({"nodata": nodata, "add_alpha": False, "src_nodata": nodata})

    if has_alpha_band(src_dst):
        vrt_params.update({"add_alpha": False})

    if vrt_options:
        vrt_params.update(vrt_options)

    with WarpedVRT(src_dst, **vrt_params) as vrt_dst:
        point_values = list(
            vrt_dst.sample([(lon[0], lat[0])], indexes=indexes, masked=masked)
        )[0]
        if unscale:
            point_values = point_values.astype("float32", casting="unsafe")
            numpy.multiply(
                point_values, vrt_dst.scales[0], out=point_values, casting="unsafe"
            )
            numpy.add(
                point_values, vrt_dst.offsets[0], out=point_values, casting="unsafe"
            )

    return point_values.tolist()
Beispiel #5
0
def point(
    src_dst: Union[DatasetReader, DatasetWriter, WarpedVRT],
    coordinates: Tuple[float, float],
    indexes: Optional[Union[Sequence[int], int]] = None,
    coord_crs: CRS = constants.WGS84_CRS,
    masked: bool = True,
    nodata: Optional[Union[float, int, str]] = None,
    unscale: bool = False,
    resampling_method: Resampling = "nearest",
    vrt_options: Optional[Dict] = None,
    post_process: Optional[Callable[[numpy.ndarray, numpy.ndarray],
                                    Tuple[numpy.ndarray,
                                          numpy.ndarray]]] = None,
) -> List:
    """Read a pixel value for a point.

    Args:
        src_dst (rasterio.io.DatasetReader or rasterio.io.DatasetWriter or rasterio.vrt.WarpedVRT): Rasterio dataset.
        coordinates (tuple): Coordinates in form of (X, Y).
        indexes (sequence of int or int, optional): Band indexes.
        coord_crs (rasterio.crs.CRS, optional): Coordinate Reference System of the input coords. Defaults to `epsg:4326`.
        masked (bool): Mask samples that fall outside the extent of the dataset. Defaults to `True`.
        nodata (int or float, optional): Overwrite dataset internal nodata value.
        unscale (bool, optional): Apply 'scales' and 'offsets' on output data value. Defaults to `False`.
        resampling_method (rasterio.enums.Resampling, optional): Rasterio's resampling algorithm. Defaults to `nearest`.
        vrt_options (dict, optional): Options to be passed to the rasterio.warp.WarpedVRT class.
        post_process (callable, optional): Function to apply on output data and mask values.

    Returns:
        list: Pixel value per band indexes.

    """
    if isinstance(indexes, int):
        indexes = (indexes, )

    lon, lat = transform_coords(coord_crs, src_dst.crs, [coordinates[0]],
                                [coordinates[1]])
    if not ((src_dst.bounds[0] < lon[0] < src_dst.bounds[2]) and
            (src_dst.bounds[1] < lat[0] < src_dst.bounds[3])):
        raise PointOutsideBounds("Point is outside dataset bounds")

    indexes = indexes if indexes is not None else src_dst.indexes

    vrt_params: Dict[str, Any] = {
        "add_alpha": True,
        "resampling": Resampling[resampling_method],
    }
    nodata = nodata if nodata is not None else src_dst.nodata
    if nodata is not None:
        vrt_params.update({
            "nodata": nodata,
            "add_alpha": False,
            "src_nodata": nodata
        })

    if has_alpha_band(src_dst):
        vrt_params.update({"add_alpha": False})

    if vrt_options:
        vrt_params.update(vrt_options)

    with WarpedVRT(src_dst, **vrt_params) as vrt_dst:
        values = list(
            vrt_dst.sample([(lon[0], lat[0])], indexes=indexes,
                           masked=masked))[0]
        point_values = values.data
        mask = values.mask * 255 if masked else numpy.zeros(point_values.shape)

        if unscale:
            point_values = point_values.astype("float32", casting="unsafe")
            numpy.multiply(point_values,
                           vrt_dst.scales[0],
                           out=point_values,
                           casting="unsafe")
            numpy.add(point_values,
                      vrt_dst.offsets[0],
                      out=point_values,
                      casting="unsafe")

    if post_process:
        point_values, _ = post_process(point_values, mask)

    return point_values.tolist()