Esempio n. 1
0
    def from_slice_out_res(self, slice_=None):
        assert self.out_res in ["10", "30", "20", "60"
                                ], "output resolution must be 10, 20, 30 or 60"

        if slice_ is None:
            slice_ = self.slice
        if slice_ is None:
            slice_ = (slice(None), slice(None))

        shape = (self.dimsByRes[self.out_res][0],
                 self.dimsByRes[self.out_res][1])
        slice_norm = []
        for i, s in enumerate(slice_):
            start = 0 if s.start is None else s.start
            end = shape[i] if s.stop is None else s.stop
            slice_norm.append(slice(start, end))
        slice_ = tuple(slice_norm)

        # Assert slice fits the dims
        misc.assert_valid_slice(
            slice_,
            (self.dimsByRes[self.out_res][0], self.dimsByRes[self.out_res][1]))

        bbox = windows.bounds(windows.Window.from_slices(*slice_),
                              self.transform_dict[self.out_res][0])

        return bbox, slice_
Esempio n. 2
0
def _resize_crs_probav(img, src_crs, transform_landsat, resolution_step):
    assert (len(img.shape) == 3
            ), "Prepared to work with 3d arrays in HWC format {}".format(
                img.shape)
    assert not np.any(
        np.ma.getmask(img)), "masked array not supported. fill before calling!"

    window_landsat = (slice(0, img.shape[0]), slice(0, img.shape[1]))
    bbox = windows.bounds(window_landsat, transform_landsat)
    transform, width, height = warp.calculate_default_transform(
        src_crs, {"init": "epsg:4326"},
        img.shape[1],
        img.shape[0],
        left=bbox[0],
        bottom=bbox[1],
        right=bbox[2],
        top=bbox[3],
        resolution=resolution_step)

    img = np.ma.filled(img, fill_value=-1)
    out_array = np.ndarray((img.shape[2], height, width), dtype=img.dtype)

    warp.reproject(np.transpose(img, axes=(2, 0, 1)),
                   out_array,
                   src_crs=src_crs,
                   dst_crs={"init": "epsg:4326"},
                   src_transform=transform_landsat,
                   dst_transform=transform,
                   resampling=warp.Resampling.lanczos,
                   dst_nodata=-1,
                   src_nodata=-1)

    out_array = np.transpose(out_array, (1, 2, 0))

    return out_array, transform
Esempio n. 3
0
    def _compute_image_stats_chunked(dataset: 'DatasetReader') -> Optional[Dict[str, Any]]:
        """Compute statistics for the given rasterio dataset by looping over chunks."""
        from rasterio import features, warp, windows
        from shapely import geometry

        total_count = valid_data_count = 0
        tdigest = TDigest()
        sstats = SummaryStats()
        convex_hull = geometry.Polygon()

        block_windows = [w for _, w in dataset.block_windows(1)]

        for w in block_windows:
            with warnings.catch_warnings():
                warnings.filterwarnings('ignore', message='invalid value encountered.*')
                block_data = dataset.read(1, window=w, masked=True)

            # handle NaNs for float rasters
            block_data = np.ma.masked_invalid(block_data, copy=False)

            total_count += int(block_data.size)
            valid_data = block_data.compressed()

            if valid_data.size == 0:
                continue

            valid_data_count += int(valid_data.size)

            if np.any(block_data.mask):
                hull_candidates = RasterDriver._hull_candidate_mask(~block_data.mask)
                hull_shapes = [geometry.shape(s) for s, _ in features.shapes(
                    np.ones(hull_candidates.shape, 'uint8'),
                    mask=hull_candidates,
                    transform=windows.transform(w, dataset.transform)
                )]
            else:
                w, s, e, n = windows.bounds(w, dataset.transform)
                hull_shapes = [geometry.Polygon([(w, s), (e, s), (e, n), (w, n)])]
            convex_hull = geometry.MultiPolygon([convex_hull, *hull_shapes]).convex_hull

            tdigest.update(valid_data)
            sstats.update(valid_data)

        if sstats.count() == 0:
            return None

        convex_hull_wgs = warp.transform_geom(
            dataset.crs, 'epsg:4326', geometry.mapping(convex_hull)
        )

        return {
            'valid_percentage': valid_data_count / total_count * 100,
            'range': (sstats.min(), sstats.max()),
            'mean': sstats.mean(),
            'stdev': sstats.std(),
            'percentiles': tdigest.quantile(np.arange(0.01, 1, 0.01)),
            'convex_hull': convex_hull_wgs
        }
Esempio n. 4
0
 def _calc_transform(self):
     bbox = windows.bounds(self.window, self.transform_window)
     transform, width, height = warp.calculate_default_transform(
         self.src.crs, {"init": "epsg:4326"},
         self.window.width,
         self.window.height,
         left=bbox[0],
         bottom=bbox[1],
         right=bbox[2],
         top=bbox[3],
         resolution=self.resolution)
     return transform, width, height
Esempio n. 5
0
def crop(pixel_collection, data_format, offsets):
    data, (bounds, data_crs), _ = pixel_collection
    left, bottom, right, top = offsets

    if _isimage(data_format):
        width, height, _ = data.shape
        t = transform.from_bounds(*bounds, width=width, height=height)

        data = data[top:height - bottom, left:width - right, :]

        cropped_window = windows.Window(left, top, width, height)
        cropped_bounds = windows.bounds(cropped_window, t)

        return PixelCollection(data, Bounds(cropped_bounds, data_crs))

    _, height, width = data.shape
    t = transform.from_bounds(*bounds, width=width, height=height)

    data = data[:, top:height - bottom, left:width - right]

    cropped_window = windows.Window(left, top, width, height)
    cropped_bounds = windows.bounds(cropped_window, t)

    return PixelCollection(data, Bounds(cropped_bounds, data_crs))
Esempio n. 6
0
    def window_bounds(self, window):
        """Get the bounds of a window

        Parameters
        ----------
        window: tuple
            Dataset window tuple

        Returns
        -------
        bounds : tuple
            x_min, y_min, x_max, y_max for the given window
        """

        transform = guard_transform(self.transform)
        return windows.bounds(window, transform)
def build_window(in_src, in_xy_ul, in_chip_size, in_chip_stride):

    out_window = windows.Window(col_off=in_xy_ul[0],
                                row_off=in_xy_ul[1],
                                width=in_chip_size,
                                height=in_chip_size)

    out_win_transform = windows.transform(out_window, in_src.transform)

    col_id = in_xy_ul[1] // in_chip_stride
    row_id = in_xy_ul[0] // in_chip_stride
    out_win_id = f'{col_id}_{row_id}'

    out_win_bounds = windows.bounds(out_window, out_win_transform)

    return out_window, out_win_transform, out_win_bounds, out_win_id
Esempio n. 8
0
    def window_bounds(self, window):
        """Get the bounds of a window

        Parameters
        ----------
        window: tuple
            Dataset window tuple

        Returns
        -------
        bounds : tuple
            x_min, y_min, x_max, y_max for the given window
        """

        transform = guard_transform(self.transform)
        return windows.bounds(window, transform)
Esempio n. 9
0
    def _read_window(self, vrt: WarpedVRT, dst_window: Window) -> MaskedArray:
        """Read window of input raster."""
        dst_bounds: Bounds = bounds(dst_window, self.dst[self.default_format].transform)
        window = vrt.window(*dst_bounds)

        src_bounds = transform_bounds(
            self.dst[self.default_format].crs, self.src.crs, *dst_bounds
        )

        LOGGER.debug(
            f"Read {dst_window} for Tile {self.tile_id} - this corresponds to bounds {src_bounds} in source"
        )

        shape = (
            len(self.layer.input_bands),
            int(round(dst_window.height)),
            int(round(dst_window.width)),
        )

        try:

            return vrt.read(
                window=window,
                out_shape=shape,
                masked=True,
            )
        except rasterio.RasterioIOError as e:
            if "Access window out of range" in str(e) and (
                shape[1] == 1 or shape[2] == 1
            ):
                LOGGER.warning(
                    f"Access window out of range while reading {dst_window} for Tile {self.tile_id}. "
                    "This is most likely due to subpixel misalignment. "
                    "Returning empty array instead."
                )
                return np.ma.array(
                    data=np.zeros(shape=shape), mask=np.ones(shape=shape)
                )

            else:
                LOGGER.warning(
                    f"RasterioIO error while reading {dst_window} for Tile {self.tile_id}. "
                    "Will make attempt to retry."
                )
                raise
Esempio n. 10
0
    def _reproject_dst_window(self, dst_window: Window) -> Window:
        """Reproject window into same projection as source raster."""

        dst_bounds: Bounds = bounds(
            window=dst_window,
            transform=self.dst[self.default_format].transform,
            height=self.grid.blockysize,
            width=self.grid.blockxsize,
        )
        src_bounds: Bounds = transform_bounds(
            self.dst[self.default_format].crs, self.src.crs, *dst_bounds
        )

        src_window: Window = from_bounds(*src_bounds, transform=self.src.transform)
        LOGGER.debug(
            f"Source window for {dst_window} of tile {self.tile_id} is {src_window}"
        )
        return src_window
Esempio n. 11
0
def test_window_bounds_function():
    with rasterio.open('tests/data/RGB.byte.tif') as src:
        rows = src.height
        cols = src.width
        assert bounds(((0, rows), (0, cols)), src.transform) == src.bounds
Esempio n. 12
0
def pixel_to_geo(datafile: DataFile, window: PixelWindow) -> GeoWindow:
    """Return the geo BoundingBox corresponding to the pixel window on the datafile"""
    return rasterio.coords.BoundingBox(
        *windows.bounds(window, datafile.transform))
Esempio n. 13
0
 def _get_gpdf_from_window(self, window: Window, transform) -> GeoDataFrame:
     """Returns a GeoDataFrame of the bounds of the given window"""
     return self._get_gpdf_from_bounds(bounds(window, transform))
Esempio n. 14
0
def test_window_bounds_function(path_rgb_byte_tif):
    with rasterio.open(path_rgb_byte_tif) as src:
        rows = src.height
        cols = src.width
        assert bounds(((0, rows), (0, cols)), src.transform) == src.bounds
Esempio n. 15
0
def test_window_bounds_function(path_rgb_byte_tif):
    with rasterio.open(path_rgb_byte_tif) as src:
        rows = src.height
        cols = src.width
        assert bounds(((0, rows), (0, cols)), src.transform) == src.bounds
Esempio n. 16
0
    def _get_raster_tile(self, path: str, *,
                         upsampling_method: str,
                         downsampling_method: str,
                         bounds: Tuple[float, float, float, float] = None,
                         tile_size: Tuple[int, int] = (256, 256),
                         preserve_values: bool = False) -> np.ma.MaskedArray:
        """Load a raster dataset from a file through rasterio.

        Heavily inspired by mapbox/rio-tiler
        """
        import rasterio
        from rasterio import transform, windows, warp
        from rasterio.vrt import WarpedVRT
        from affine import Affine

        dst_bounds: Tuple[float, float, float, float]

        if preserve_values:
            upsampling_enum = downsampling_enum = self._get_resampling_enum('nearest')
        else:
            upsampling_enum = self._get_resampling_enum(upsampling_method)
            downsampling_enum = self._get_resampling_enum(downsampling_method)

        with contextlib.ExitStack() as es:
            es.enter_context(rasterio.Env(**self._RIO_ENV_KEYS))
            try:
                with trace('open_dataset'):
                    src = es.enter_context(rasterio.open(path))
            except OSError:
                raise IOError('error while reading file {}'.format(path))

            # compute suggested resolution and bounds in target CRS
            dst_transform, _, _ = self._calculate_default_transform(
                src.crs, self._TARGET_CRS, src.width, src.height, *src.bounds
            )
            dst_res = (abs(dst_transform.a), abs(dst_transform.e))
            dst_bounds = warp.transform_bounds(src.crs, self._TARGET_CRS, *src.bounds)

            if bounds is None:
                bounds = dst_bounds

            # pad tile bounds to prevent interpolation artefacts
            num_pad_pixels = 2

            # compute tile VRT shape and transform
            dst_width = max(1, round((bounds[2] - bounds[0]) / dst_res[0]))
            dst_height = max(1, round((bounds[3] - bounds[1]) / dst_res[1]))
            vrt_transform = (
                transform.from_bounds(*bounds, width=dst_width, height=dst_height)
                * Affine.translation(-num_pad_pixels, -num_pad_pixels)
            )
            vrt_height, vrt_width = dst_height + 2 * num_pad_pixels, dst_width + 2 * num_pad_pixels

            # remove padding in output
            out_window = windows.Window(
                col_off=num_pad_pixels, row_off=num_pad_pixels, width=dst_width, height=dst_height
            )

            # construct VRT
            vrt = es.enter_context(
                WarpedVRT(
                    src, crs=self._TARGET_CRS, resampling=upsampling_enum, add_alpha=True,
                    transform=vrt_transform, width=vrt_width, height=vrt_height
                )
            )

            # prevent loads of very sparse data
            out_window_bounds = windows.bounds(out_window, vrt_transform)
            cover_ratio = (
                (dst_bounds[2] - dst_bounds[0]) / (out_window_bounds[2] - out_window_bounds[0])
                * (dst_bounds[3] - dst_bounds[1]) / (out_window_bounds[3] - out_window_bounds[1])
            )

            if cover_ratio < 0.01:
                raise exceptions.TileOutOfBoundsError('dataset covers less than 1% of tile')

            # determine whether we are upsampling or downsampling
            pixel_ratio = min(out_window.width / tile_size[1], out_window.height / tile_size[0])
            if pixel_ratio < 1:
                resampling_enum = upsampling_enum
            else:
                resampling_enum = downsampling_enum

            # read data
            with warnings.catch_warnings(), trace('read_from_vrt'):
                warnings.filterwarnings('ignore', message='invalid value encountered.*')
                tile_data = vrt.read(
                    1, resampling=resampling_enum, window=out_window, out_shape=tile_size
                )
                # read alpha mask
                mask_idx = src.count + 1
                mask = vrt.read(mask_idx, window=out_window, out_shape=tile_size) == 0
                if src.nodata is not None:
                    mask |= tile_data == src.nodata

        return np.ma.masked_array(tile_data, mask=mask)
Esempio n. 17
0
def test_window_bounds_function():
    with rasterio.open('tests/data/RGB.byte.tif') as src:
        rows = src.height
        cols = src.width
        assert bounds(((0, rows), (0, cols)), src.transform) == src.bounds