Exemplo n.º 1
0
def test_set_options__global():
    assert get_option(EXPORT_GRID_MAPPING)
    try:
        set_options(export_grid_mapping=False)
        assert not get_option(EXPORT_GRID_MAPPING)
    finally:
        set_options(export_grid_mapping=True)
    assert get_option(EXPORT_GRID_MAPPING)
Exemplo n.º 2
0
    def interpolate_na(self, method="nearest"):
        """
        This method uses `scipy.interpolate.griddata` to interpolate missing data.

        .. warning:: scipy is an optional dependency.

        .. warning:: Interpolates variables that have dimensions 'x'/'y'. Others are appended as is.

        Parameters
        ----------
        method: {‘linear’, ‘nearest’, ‘cubic’}, optional
            The method to use for interpolation in `scipy.interpolate.griddata`.

        Returns
        -------
        :obj:`xarray.DataArray`:
             The interpolated object.
        """
        interpolated_dataset = xarray.Dataset(attrs=self._obj.attrs)
        for var in self.vars:
            try:
                x_dim, y_dim = _get_spatial_dims(self._obj, var)
                interpolated_dataset[var] = (
                    self._obj[var].rio.set_spatial_dims(
                        x_dim=x_dim, y_dim=y_dim,
                        inplace=True).rio.interpolate_na(method=method))
            except MissingSpatialDimensionError:
                if len(self._obj[var].dims) >= 2 and not get_option(
                        SKIP_MISSING_SPATIAL_DIMS):
                    raise
                interpolated_dataset[var] = self._obj[var].copy()
        return interpolated_dataset.rio.set_spatial_dims(x_dim=self.x_dim,
                                                         y_dim=self.y_dim,
                                                         inplace=True)
Exemplo n.º 3
0
    def clip_box(self,
                 minx,
                 miny,
                 maxx,
                 maxy,
                 auto_expand=False,
                 auto_expand_limit=3):
        """Clip the :class:`xarray.Dataset` by a bounding box in dimensions 'x'/'y'.

        .. warning:: Clips variables that have dimensions 'x'/'y'. Others are appended as is.

        Parameters
        ----------
        minx: float
            Minimum bound for x coordinate.
        miny: float
            Minimum bound for y coordinate.
        maxx: float
            Maximum bound for x coordinate.
        maxy: float
            Maximum bound for y coordinate.
        auto_expand: bool
            If True, it will expand clip search if only 1D raster found with clip.
        auto_expand_limit: int
            maximum number of times the clip will be retried before raising
            an exception.

        Returns
        -------
        :obj:`Dataset`:
            The clipped object.
        """
        clipped_dataset = xarray.Dataset(attrs=self._obj.attrs)
        for var in self.vars:
            try:
                x_dim, y_dim = _get_spatial_dims(self._obj, var)
                clipped_dataset[var] = (self._obj[var].rio.set_spatial_dims(
                    x_dim=x_dim, y_dim=y_dim, inplace=True).rio.clip_box(
                        minx,
                        miny,
                        maxx,
                        maxy,
                        auto_expand=auto_expand,
                        auto_expand_limit=auto_expand_limit,
                    ))
            except MissingSpatialDimensionError:
                if len(self._obj[var].dims) >= 2 and not get_option(
                        SKIP_MISSING_SPATIAL_DIMS):
                    raise
                clipped_dataset[var] = self._obj[var].copy()
        return clipped_dataset.rio.set_spatial_dims(x_dim=self.x_dim,
                                                    y_dim=self.y_dim,
                                                    inplace=True)
Exemplo n.º 4
0
    def reproject_match(self,
                        match_data_array,
                        resampling=Resampling.nearest,
                        **reproject_kwargs):
        """
        Reproject a Dataset object to match the resolution, projection,
        and region of another DataArray.

        .. note:: Only 2D/3D arrays with dimensions 'x'/'y' are currently supported.
            Others are appended as is.
            Requires either a grid mapping variable with 'spatial_ref' or
            a 'crs' attribute to be set containing a valid CRS.
            If using a WKT (e.g. from spatiareference.org), make sure it is an OGC WKT.

        .. versionadded:: 0.9 reproject_kwargs

        Parameters
        ----------
        match_data_array: :obj:`xarray.DataArray` | :obj:`xarray.Dataset`
            Dataset with the target resolution and projection.
        resampling: rasterio.enums.Resampling, optional
            See :func:`rasterio.warp.reproject` for more details.
        **reproject_kwargs:
            Other options to pass to :meth:`rioxarray.raster_dataset.RasterDataset.reproject`

        Returns
        --------
        :obj:`xarray.Dataset`:
            Contains the data from the src_data_array,
            reprojected to match match_data_array.
        """
        resampled_dataset = xarray.Dataset(attrs=self._obj.attrs)
        for var in self.vars:
            try:
                x_dim, y_dim = _get_spatial_dims(self._obj, var)
                resampled_dataset[var] = (self._obj[var].rio.set_spatial_dims(
                    x_dim=x_dim, y_dim=y_dim,
                    inplace=True).rio.reproject_match(match_data_array,
                                                      resampling=resampling,
                                                      **reproject_kwargs))
            except MissingSpatialDimensionError:
                if len(self._obj[var].dims) >= 2 and not get_option(
                        SKIP_MISSING_SPATIAL_DIMS):
                    raise
                resampled_dataset[var] = self._obj[var].copy()
        return resampled_dataset.rio.set_spatial_dims(x_dim=self.x_dim,
                                                      y_dim=self.y_dim,
                                                      inplace=True)
Exemplo n.º 5
0
    def pad_box(self, minx, miny, maxx, maxy):
        """Pad the :class:`xarray.Dataset` to a bounding box.

        .. warning:: Only works if all variables in the dataset have the
                     same coordinates.

        .. warning:: Pads variables that have dimensions 'x'/'y'. Others are appended as is.

        Parameters
        ----------
        minx: float
            Minimum bound for x coordinate.
        miny: float
            Minimum bound for y coordinate.
        maxx: float
            Maximum bound for x coordinate.
        maxy: float
            Maximum bound for y coordinate.

        Returns
        -------
        :obj:`xarray.Dataset`:
            The padded object.
        """
        padded_dataset = xarray.Dataset(attrs=self._obj.attrs)
        for var in self.vars:
            try:
                x_dim, y_dim = _get_spatial_dims(self._obj, var)
                padded_dataset[var] = (self._obj[var].rio.set_spatial_dims(
                    x_dim=x_dim, y_dim=y_dim,
                    inplace=True).rio.pad_box(minx, miny, maxx, maxy))
            except MissingSpatialDimensionError:
                if len(self._obj[var].dims) >= 2 and not get_option(
                        SKIP_MISSING_SPATIAL_DIMS):
                    raise
                padded_dataset[var] = self._obj[var].copy()
        return padded_dataset.rio.set_spatial_dims(x_dim=self.x_dim,
                                                   y_dim=self.y_dim,
                                                   inplace=True)
Exemplo n.º 6
0
    def write_crs(self, input_crs=None, grid_mapping_name=None, inplace=False):
        """
        Write the CRS to the dataset in a CF compliant manner.

        Parameters
        ----------
        input_crs: object
            Anything accepted by `rasterio.crs.CRS.from_user_input`.
        grid_mapping_name: str, optional
            Name of the grid_mapping coordinate to store the CRS information in.
            Default is the grid_mapping name of the dataset.
        inplace: bool, optional
            If True, it will write to the existing dataset. Default is False.

        Returns
        -------
        :obj:`xarray.Dataset` | :obj:`xarray.DataArray`:
            Modified dataset with CF compliant CRS information.

        Examples
        --------
        Write the CRS of the current `xarray` object:

        >>> raster.rio.write_crs("epsg:4326", inplace=True)

        Write the CRS on a copy:

        >>> raster = raster.rio.write_crs("epsg:4326")
        """
        if input_crs is not None:
            data_obj = self.set_crs(input_crs, inplace=inplace)
        else:
            data_obj = self._get_obj(inplace=inplace)

        # get original transform
        transform = self._cached_transform()
        # remove old grid maping coordinate if exists
        grid_mapping_name = (
            self.grid_mapping if grid_mapping_name is None else grid_mapping_name
        )
        try:
            del data_obj.coords[grid_mapping_name]
        except KeyError:
            pass

        if data_obj.rio.crs is None:
            raise MissingCRS(
                "CRS not found. Please set the CRS with 'rio.write_crs()'."
            )
        # add grid mapping coordinate
        data_obj.coords[grid_mapping_name] = xarray.Variable((), 0)
        if get_option(EXPORT_GRID_MAPPING):
            grid_map_attrs = pyproj.CRS.from_user_input(data_obj.rio.crs).to_cf()
        else:
            grid_map_attrs = {}
        # spatial_ref is for compatibility with GDAL
        crs_wkt = data_obj.rio.crs.to_wkt()
        grid_map_attrs["spatial_ref"] = crs_wkt
        grid_map_attrs["crs_wkt"] = crs_wkt
        if transform is not None:
            grid_map_attrs["GeoTransform"] = " ".join(
                [str(item) for item in transform.to_gdal()]
            )
        data_obj.coords[grid_mapping_name].rio.set_attrs(grid_map_attrs, inplace=True)

        return data_obj.rio.write_grid_mapping(
            grid_mapping_name=grid_mapping_name, inplace=True
        )
Exemplo n.º 7
0
    def reproject(
        self,
        dst_crs,
        resolution=None,
        shape=None,
        transform=None,
        resampling=Resampling.nearest,
        nodata=None,
        **kwargs,
    ):
        """
        Reproject :class:`xarray.Dataset` objects

        .. note:: Only 2D/3D arrays with dimensions 'x'/'y' are currently supported.
            Others are appended as is.
            Requires either a grid mapping variable with 'spatial_ref' or
            a 'crs' attribute to be set containing a valid CRS.
            If using a WKT (e.g. from spatiareference.org), make sure it is an OGC WKT.

        .. versionadded:: 0.0.27 shape
        .. versionadded:: 0.0.28 transform
        .. versionadded:: 0.5.0 nodata, kwargs

        Parameters
        ----------
        dst_crs: str
            OGC WKT string or Proj.4 string.
        resolution: float or tuple(float, float), optional
            Size of a destination pixel in destination projection units
            (e.g. degrees or metres).
        shape: tuple(int, int), optional
            Shape of the destination in pixels (dst_height, dst_width). Cannot be used
            together with resolution.
        transform: optional
            The destination transform.
        resampling: rasterio.enums.Resampling, optional
            See :func:`rasterio.warp.reproject` for more details.
        nodata: float, optional
            The nodata value used to initialize the destination;
            it will remain in all areas not covered by the reprojected source.
            Defaults to the nodata value of the source image if none provided
            and exists or attempts to find an appropriate value by dtype.
        **kwargs: dict
            Additional keyword arguments to pass into :func:`rasterio.warp.reproject`.
            To override:
            - src_transform: `rio.write_transform`
            - src_crs: `rio.write_crs`
            - src_nodata: `rio.write_nodata`

        Returns
        --------
        :class:`xarray.Dataset`:
            The reprojected Dataset.
        """
        resampled_dataset = xarray.Dataset(attrs=self._obj.attrs)
        for var in self.vars:
            try:
                x_dim, y_dim = _get_spatial_dims(self._obj, var)
                resampled_dataset[var] = (self._obj[var].rio.set_spatial_dims(
                    x_dim=x_dim, y_dim=y_dim, inplace=True).rio.reproject(
                        dst_crs,
                        resolution=resolution,
                        shape=shape,
                        transform=transform,
                        resampling=resampling,
                        nodata=nodata,
                        **kwargs,
                    ))
            except MissingSpatialDimensionError:
                if len(self._obj[var].dims) >= 2 and not get_option(
                        SKIP_MISSING_SPATIAL_DIMS):
                    raise
                resampled_dataset[var] = self._obj[var].copy()
        return resampled_dataset
Exemplo n.º 8
0
    def clip(
        self,
        geometries,
        crs=None,
        all_touched=False,
        drop=True,
        invert=False,
        from_disk=False,
    ):
        """
        Crops a :class:`xarray.Dataset` by geojson like geometry dicts in dimensions 'x'/'y'.

        .. warning:: Clips variables that have dimensions 'x'/'y'. Others are appended as is.

        Powered by `rasterio.features.geometry_mask`.

        Examples:

            >>> geometry = ''' {"type": "Polygon",
            ...                 "coordinates": [
            ...                 [[-94.07955380199459, 41.69085871273774],
            ...                 [-94.06082436942204, 41.69103313774798],
            ...                 [-94.06063203899649, 41.67932439500822],
            ...                 [-94.07935807746362, 41.679150041277325],
            ...                 [-94.07955380199459, 41.69085871273774]]]}'''
            >>> cropping_geometries = [geojson.loads(geometry)]
            >>> xds = xarray.open_rasterio('cool_raster.tif')
            >>> cropped = xds.rio.clip(geometries=cropping_geometries, crs=4326)


        .. versionadded:: 0.2 from_disk

        Parameters
        ----------
        geometries: list
            A list of geojson geometry dicts.
        crs: :obj:`rasterio.crs.CRS`, optional
            The CRS of the input geometries. Default is to assume it is the same
            as the dataset.
        all_touched : boolean, optional
            If True, all pixels touched by geometries will be burned in.  If
            false, only pixels whose center is within the polygon or that
            are selected by Bresenham's line algorithm will be burned in.
        drop: bool, optional
            If True, drop the data outside of the extent of the mask geometries
            Otherwise, it will return the same raster with the data masked.
            Default is True.
        invert: boolean, optional
            If False, pixels that do not overlap shapes will be set as nodata.
            Otherwise, pixels that overlap the shapes will be set as nodata.
            False by default.
        from_disk: boolean, optional
            If True, it will clip from disk using rasterio.mask.mask if possible.
            This is beneficial when the size of the data is larger than memory.
            Default is False.

        Returns
        -------
        :obj:`xarray.Dataset`:
            The clipped object.
        """
        clipped_dataset = xarray.Dataset(attrs=self._obj.attrs)
        for var in self.vars:
            try:
                x_dim, y_dim = _get_spatial_dims(self._obj, var)
                clipped_dataset[var] = (self._obj[var].rio.set_spatial_dims(
                    x_dim=x_dim, y_dim=y_dim, inplace=True).rio.clip(
                        geometries,
                        crs=crs,
                        all_touched=all_touched,
                        drop=drop,
                        invert=invert,
                        from_disk=from_disk,
                    ))
            except MissingSpatialDimensionError:
                if len(self._obj[var].dims) >= 2 and not get_option(
                        SKIP_MISSING_SPATIAL_DIMS):
                    raise
                clipped_dataset[var] = self._obj[var].copy()
        return clipped_dataset.rio.set_spatial_dims(x_dim=self.x_dim,
                                                    y_dim=self.y_dim,
                                                    inplace=True)
Exemplo n.º 9
0
def test_set_options__contextmanager():
    assert get_option(EXPORT_GRID_MAPPING)
    with set_options(**{EXPORT_GRID_MAPPING: False}):
        assert not get_option(EXPORT_GRID_MAPPING)
    assert get_option(EXPORT_GRID_MAPPING)