Exemplo n.º 1
0
    def get_coordinates(self):
        """{get_coordinates}

        The default implementation tries to find the lat/lon coordinates based on dataset.affine.
        It cannot determine the alt or time dimensions, so child classes may
        have to overload this method.
        """

        # check to see if the coordinates are rotated used affine
        affine = self.dataset.transform

        if self.crs is not None:
            crs = self.crs
        elif isinstance(self.dataset.crs,
                        rasterio.crs.CRS) and "init" in self.dataset.crs:
            crs = self.dataset.crs["init"].upper()
        elif isinstance(self.dataset.crs, dict) and "init" in self.dataset.crs:
            crs = self.dataset.crs["init"].upper()
        else:
            try:
                crs = pyproj.CRS(self.dataset.crs).to_wkt()
            except pyproj.exceptions.CRSError:
                raise RuntimeError("Unexpected rasterio crs '%s'" %
                                   self.dataset.crs)

        return Coordinates.from_geotransform(affine.to_gdal(),
                                             self.dataset.shape, crs)
Exemplo n.º 2
0
    def get_data_overviews(self, coordinates, coordinates_index):
        # Figure out how much coarser the request is than the actual data
        reduction_factor = np.inf
        for c in ["lat", "lon"]:
            crd = coordinates[c]
            if crd.size == 1:
                reduction_factor = 0
                break
            if isinstance(crd, UniformCoordinates1d):
                min_delta = crd.step
            elif isinstance(crd, ArrayCoordinates1d) and crd.is_monotonic:
                min_delta = crd.deltas.min()
            else:
                raise NotImplementedError(
                    "The Rasterio node with prefer_overviews=True currently does not support request coordinates type {}"
                    .format(coordinates))
            reduction_factor = min(
                reduction_factor,
                np.abs(min_delta / self.coordinates[c].step
                       )  # self.coordinates is always uniform
            )
        # Find the overview that's closest to this reduction factor
        if (reduction_factor < 2) or (len(
                self.overviews) == 0):  # Then we shouldn't use an overview
            overview = 1
            overview_level = None
        else:
            diffs = reduction_factor - np.array(self.overviews)
            if self.prefer_overviews_closest:
                diffs = np.abs(diffs)
            else:
                diffs[diffs < 0] = np.inf
            overview_level = np.argmin(diffs)
            overview = self.overviews[np.argmin(diffs)]

        # Now read the data
        inds = coordinates_index
        if overview_level is None:
            dataset = self.dataset
        else:
            dataset = self.open_dataset(self.source, overview_level)
        try:
            # read data within coordinates_index window at the resolution of the overview
            # Rasterio will then automatically pull from the overview
            window = (
                ((inds[0].min() // overview),
                 int(np.ceil(inds[0].max() / overview) + 1)),
                ((inds[1].min() // overview),
                 int(np.ceil(inds[1].max() / overview) + 1)),
            )
            slc = (slice(window[0][0], window[0][1],
                         1), slice(window[1][0], window[1][1], 1))
            new_coords = Coordinates.from_geotransform(
                dataset.transform.to_gdal(),
                dataset.shape,
                crs=self.coordinates.crs)
            new_coords = new_coords[slc]
            missing_coords = self.coordinates.drop(["lat", "lon"])
            new_coords = merge_dims([new_coords, missing_coords])
            new_coords = new_coords.transpose(*self.coordinates.dims)
            coordinates_shape = new_coords.shape[:2]

            # The following lines are *nearly* copied/pasted from get_data
            if self.outputs is not None:  # read all the bands
                raster_data = dataset.read(out_shape=(len(self.outputs), ) +
                                           coordinates_shape,
                                           window=window)
                raster_data = np.moveaxis(raster_data, 0, 2)
            else:  # read the requested band
                raster_data = dataset.read(self.band,
                                           out_shape=coordinates_shape,
                                           window=window)

            # set raster data to output array
            data = self.create_output_array(new_coords)
            data.data.ravel()[:] = raster_data.ravel()
        except Exception as e:
            _logger.error(
                "Error occurred when reading overview with Rasterio: {}".
                format(e))

        if overview_level is not None:
            dataset.close()

        return data