예제 #1
0
    def test_to_crs_user_input(self):
        pcrs = PCRS.from_epsg(4326)
        rcrs = RCRS.from_epsg(4326)

        # are they the default?
        self.assertTrue(
            pcrs == PCRS.from_user_input(to_crs_user_input(DEF_CRS)))
        self.assertEqual(rcrs,
                         RCRS.from_user_input(to_crs_user_input(DEF_CRS)))

        # can they be understood from the provider?
        for arg in ['epsg:4326', b'epsg:4326', DEF_CRS, 4326]:
            self.assertEqual(pcrs,
                             PCRS.from_user_input(to_crs_user_input(arg)))
            self.assertEqual(rcrs,
                             RCRS.from_user_input(to_crs_user_input(arg)))

        # can they be misunderstood from the provider?
        for arg in [{
                'init': 'epsg:4326',
                'no_defs': True
        }, b'{"init": "epsg:4326", "no_defs": True}']:
            self.assertFalse(
                pcrs == PCRS.from_user_input(to_crs_user_input(arg)))
            self.assertEqual(rcrs,
                             RCRS.from_user_input(to_crs_user_input(arg)))

        # are they noticed?
        for arg in [4326.0, [4326]]:
            with self.assertRaises(ValueError):
                to_crs_user_input(arg)
        with self.assertRaises(SyntaxError):
            to_crs_user_input('{init: epsg:4326, no_defs: True}')
예제 #2
0
def get_transformation(crs_in):
    """Get projection and its units to use in cartopy transforamtions from
    current crs

    Returns:
        ccrs.Projection, str
    """
    try:
        if CRS.from_user_input(crs_in) == CRS.from_user_input(
            {'init': 'epsg:3395'}):
            crs_epsg = ccrs.Mercator()
        else:
            crs_epsg = ccrs.epsg(CRS.from_user_input(crs_in).to_epsg())
    except ValueError:
        crs_epsg = ccrs.PlateCarree()
    except requests.exceptions.ConnectionError:
        LOGGER.warning(
            'No internet connection. Using projection PlateCarree in plot.')
        crs_epsg = ccrs.PlateCarree()

    try:
        units = crs_epsg.proj4_params['units']
    except KeyError:
        units = '°'
    return crs_epsg, units
예제 #3
0
    def _read_crs(collection):

        # if there is no defined CRS in geojson file, we folloe the standard, which says that it must be lat-lon
        if 'crs' not in collection.keys():
            return CRS_LATLON

        crs_raw = collection.get('crs', CRS_LATLON)
        crs = CRS()

        try:
            if isinstance(crs_raw, str):
                crs = CRS.from_user_input(crs_raw)
            elif isinstance(crs_raw, dict):
                if 'type' in crs_raw.keys() and 'properties' in crs_raw.keys():
                    if crs_raw['type'] == 'name':
                        crs = CRS.from_user_input(crs_raw['properties']['name'])
            # Old rasterio compatibility: a separate check for validity
            if not crs.is_valid:
                message = 'CRS {} is not supported by rasterio,' \
                          'May cause an error in further reprojection or rasterization'.format(crs)
                warnings.warn(message, RuntimeWarning)
            return crs
            # Really invalid CRS will throw CRSError
        except CRSError:
            message = 'CRS was not imported correctly, assuming EPSG:4326 (lat-lon). ' \
                      'May cause an error in further reprojection or rasterization if it is not so.'
            warnings.warn(message, RuntimeWarning)
            return CRS_LATLON
예제 #4
0
    def from_vector(self, vector_data):
        """Get the geobox to use for the grid.

        Parameters
        ----------
        vector_data: str or :obj:`geopandas.GeoDataFrame`
            A file path to an OGR supported source or GeoDataFrame
            containing the vector data.

        Returns
        -------
        :obj:`datacube.utils.geometry.GeoBox`
            The geobox for the grid to be generated from the vector data.

        """
        vector_data = load_vector_data(vector_data)

        if self.like is not None:
            assert (self.output_crs is
                    None), "'like' and 'output_crs' are not supported together"
            assert (self.resolution is
                    None), "'like' and 'resolution' are not supported together"
            assert self.align is None, "'like' and 'align' are not supported together"
            try:
                geobox = self.like.geobox
            except AttributeError:
                geobox = geobox_from_rio(self.like)
            return geobox

        if self.resolution is None:
            raise RuntimeError(
                "Must specify 'resolution' if 'like' not specified.")

        if self.output_crs:
            crs = geometry.CRS(self.output_crs)
        else:
            crs = geometry.CRS(crs_to_wkt(CRS.from_user_input(
                vector_data.crs)))

        if self.geom is None:
            geopoly = geometry.Geometry(
                mapping(box(*vector_data.total_bounds)),
                crs=geometry.CRS(
                    crs_to_wkt(CRS.from_user_input(vector_data.crs))),
            )

        else:
            geom_json = json.loads(self.geom)
            geom_crs = geometry.CRS(
                "+init={}".format(geom_json["crs"]["properties"]["name"].lower(
                ) if "crs" in geom_json else "epsg:4326"))

            geopoly = geometry.Geometry(geom_json, crs=geom_crs)

        return geometry.GeoBox.from_geopolygon(geopoly, self.resolution, crs,
                                               self.align)
def equal_crs(crs_one, crs_two):
    """ Compare two crs

    Parameters:
        crs_one (dict or string or wkt): user crs
        crs_two (dict or string or wkt): user crs

    Returns:
        bool
    """
    return CRS.from_user_input(crs_one) == CRS.from_user_input(crs_two)
예제 #6
0
def get_transformation(crs_in):
    """
    Get projection and its units to use in cartopy transforamtions from current crs.

    Parameters
    ----------
    crs_in : str
        Current crs

    Returns
    ------
    crs_epsg : ccrs.Projection
    units : str
    """

    # projection
    try:
        if CRS.from_user_input(crs_in) == CRS.from_user_input('EPSG:3395'):
            crs_epsg = ccrs.Mercator()
        else:
            crs_epsg = ccrs.epsg(CRS.from_user_input(crs_in).to_epsg())
    except ValueError:
        LOGGER.warning(
            "Error parsing coordinate system '%s'. Using projection PlateCarree in plot.",
            crs_in)
        crs_epsg = ccrs.PlateCarree()
    except requests.exceptions.ConnectionError:
        LOGGER.warning(
            'No internet connection. Using projection PlateCarree in plot.')
        crs_epsg = ccrs.PlateCarree()

    # units
    with warnings.catch_warnings():
        # The method `to_dict` converts the crs into a string, which causes a user warning about
        # losing important information. Since we are only interested in its units at this point,
        # we may safely ignore it.
        warnings.simplefilter(action="ignore", category=UserWarning)
        try:
            units = (
                crs_epsg.proj4_params.get('units')
                # As of cartopy 0.20 the proj4_params attribute is {} for CRS from an EPSG number
                # (see issue raised https://github.com/SciTools/cartopy/issues/1974
                # and longterm discussion on https://github.com/SciTools/cartopy/issues/813).
                # In these cases the units can be fetched through the method `to_dict`.
                or crs_epsg.to_dict().get('units', '°'))
        except AttributeError:
            # This happens in setups with cartopy<0.20, where `to_dict` is not defined.
            # Officially, we require cartopy>=0.20, but there are still users around that
            # can't upgrade due to https://github.com/SciTools/iris/issues/4468
            units = '°'

    return crs_epsg, units
예제 #7
0
    def set_crs(self, input_crs, inplace=True):
        """
        Set the CRS value for the Dataset/DataArray without modifying
        the dataset/data array.

        Parameters
        ----------
        input_crs: object
            Anythong accepted by `rasterio.crs.CRS.from_user_input`.

        Returns
        -------
        xarray.Dataset or xarray.DataArray:
        Dataset with crs attribute.

        """
        if hasattr(input_crs, "wkt"):
            input_crs = input_crs.wkt
        crs = CRS.from_user_input(input_crs)
        if inplace:
            self._crs = crs
            return self._obj
        xobj = self._obj.copy(deep=True)
        xobj.rio._crs = crs
        return xobj
예제 #8
0
    def parse_flow_dir(self):
        """Parse the flow direction variable and define the CRS and mask for other
        variables based on this. This step must be performed before NetCDF file is generated."""

        if self.config['flow_dir']['type'] == 'raster':
            self.grid = rasterio.open(
                os.path.join(self.root_dir, self.config['flow_dir']['path']))
            # If a CRS has been specified for the flowdir raster, use this instead of the raster's
            # internal CRS. This is useful if a raster has an ill-defined CRS
            self.grid_crs = CRS.from_user_input(
                self.config['flow_dir']
                ['crs']) if 'crs' in self.config['flow_dir'] else self.grid.crs
            # Only projected rasters allowed for the moment
            if self.grid_crs.is_geographic:
                print(
                    'Sorry, the flow_dir raster must be projected, not geographic. I got a geographic CRS: \'{0}\'.'
                    .format(self.grid_crs))
                sys.exit()
            self.grid_bbox = box(
                *self.grid.bounds
            )  # Create Shapely box from bounds, to clip other rasters to
        elif self.config['flow_dir']['type'] == 'csv':
            print(
                "CSV flow direction not currently supported. Please provide a raster file."
            )
            sys.exit()

        else:
            print(
                "Unrecognised file type {0} for variable flow_dir. Type should be rs, csv or nc."
                .format(self.config['flow_dir']['type']))
            sys.exit()
def rasterio_get_data(filepath, geojson):
    """
    Returns the data rectangle surrounding the geometry over several channels from a raster.

    :param filepath: the path to the raster file
    :param geojson: the GeoJSON feature
    :return: the extracted data
    :rtype: np.ndarray
    """
    try:
        crs_obj = geojson["properties"]["crs"]
    except KeyError:
        # Default coordinates reference system is WGS84
        crs = "EPSG:4326"
    else:
        crs = CRS.from_user_input(crs_obj["properties"]["name"]).to_string()
    logging.info(f"GeoJSON CRS: {crs}")

    with rasterio.open(filepath) as img:
        img_crs = img.profile["crs"].to_string()
        logging.info(f"Raster CRS: {img_crs}")

        if crs != img_crs:
            geometry = transform_geom(crs, img_crs, geojson["geometry"])
        else:
            geometry = geojson["geometry"]
        logging.info(f"GeoJSON geometry: {geometry}")

        array, _ = rasterio.mask.mask(img,
                                      shapes=[geometry],
                                      crop=True,
                                      filled=False)
        logging.info(f"Array extracted from raster. Shape={array.shape}")

        return array.data
예제 #10
0
    def crs(self):
        """:obj:`rasterio.crs.CRS`:
            Retrieve projection from `xarray.DataArray`
        """
        if self._crs is not None:
            return self._crs

        try:
            # look in grid_mapping
            grid_mapping_coord = self._obj.attrs["grid_mapping"]
            self._crs = CRS.from_user_input(
                self._obj.coords[grid_mapping_coord].attrs["spatial_ref"]
            )
        except KeyError:
            # look in attrs for 'crs' from rasterio xarray
            self._crs = CRS.from_user_input(self._obj.attrs["crs"])
        return self._crs
예제 #11
0
파일: warp.py 프로젝트: mapbox/rasterio
def transform_bounds(src_crs,
                     dst_crs,
                     left,
                     bottom,
                     right,
                     top,
                     densify_pts=21):
    """Transform bounds from src_crs to dst_crs.

    Optionally densifying the edges (to account for nonlinear transformations
    along these edges) and extracting the outermost bounds.

    Note: antimeridian support added in version 1.3.0

    Parameters
    ----------
    src_crs: CRS or dict
        Source coordinate reference system, in rasterio dict format.
        Example: CRS({'init': 'EPSG:4326'})
    dst_crs: CRS or dict
        Target coordinate reference system.
    left, bottom, right, top: float
        Bounding coordinates in src_crs, from the bounds property of a raster.
    densify_pts: uint, optional
        Number of points to add to each edge to account for nonlinear
        edges produced by the transform process.  Large numbers will produce
        worse performance.  Default: 21 (gdal default).

    Returns
    -------
    left, bottom, right, top: float
        Outermost coordinates in target coordinate reference system.
    """
    src_crs = CRS.from_user_input(src_crs)
    dst_crs = CRS.from_user_input(dst_crs)
    return _transform_bounds(
        src_crs,
        dst_crs,
        left,
        bottom,
        right,
        top,
        densify_pts,
    )
예제 #12
0
def get_transformation(crs_in):
    """
    Get projection and its units to use in cartopy transforamtions from
    current crs

    Parameters
    ----------
    crs_in : str
        Current crs

    Returns
    ------
    crs_epsg : ccrs.Projection
    units : str
    """
    try:
        if CRS.from_user_input(crs_in) == CRS.from_user_input('EPSG:3395'):
            crs_epsg = ccrs.Mercator()
        else:
            crs_epsg = ccrs.epsg(CRS.from_user_input(crs_in).to_epsg())
    except ValueError:
        crs_epsg = ccrs.PlateCarree()
    except requests.exceptions.ConnectionError:
        LOGGER.warning('No internet connection.'
                       ' Using projection PlateCarree in plot.')
        crs_epsg = ccrs.PlateCarree()

    try:
        units = (
            crs_epsg.proj4_params.get('units')
            # As of cartopy 0.20 the proj4_params attribute is {} for CRS from an EPSG number
            # (see issue raised https://github.com/SciTools/cartopy/issues/1974
            # and longterm discussion on https://github.com/SciTools/cartopy/issues/813).
            # In these cases the units can be fetched through the method `to_dict`.
            or crs_epsg.to_dict().get('units', '°'))
    except AttributeError:
        # This happens in setups with cartopy<0.20, where `to_dict` is not defined.
        # Officially, we require cartopy>=0.20, but there are still users around that
        # can't upgrade due to https://github.com/SciTools/iris/issues/4468
        units = '°'
    return crs_epsg, units
예제 #13
0
def test_reproject__grid_mapping(modis_reproject):
    mask_args = (dict(masked=False) if modis_reproject["open"].__name__
                 == "open_rasterio" else dict(mask_and_scale=False))
    with modis_reproject["open"](modis_reproject["input"],
                                 **mask_args) as mda, modis_reproject["open"](
                                     modis_reproject["compare"],
                                     **mask_args) as mdc:

        # remove 'crs' attribute and add grid mapping
        mda.coords["spatial_ref"] = 0
        mda.coords["spatial_ref"].attrs["spatial_ref"] = CRS.from_user_input(
            _get_attr(mda, "crs")).wkt
        _mod_attr(mda, "grid_mapping", val="spatial_ref")
        _del_attr(mda, "crs")
        mdc.coords["spatial_ref"] = 0
        mdc.coords["spatial_ref"].attrs["spatial_ref"] = CRS.from_user_input(
            _get_attr(mdc, "crs")).wkt
        _mod_attr(mdc, "grid_mapping", val="spatial_ref")
        _del_attr(mdc, "crs")

        # reproject
        mds_repr = mda.rio.reproject(modis_reproject["to_proj"])
        # test
        _assert_xarrays_equal(mds_repr, mdc)
def test_reproject__grid_mapping(modis_reproject):
    with modis_reproject["open"](
            modis_reproject["input"], mask_and_scale=False,
            autoclose=True) as mda, modis_reproject["open"](
                modis_reproject["compare"],
                mask_and_scale=False,
                autoclose=True) as mdc:

        # remove 'crs' attribute and add grid mapping
        mda.coords["spatial_ref"] = 0
        mda.coords["spatial_ref"].attrs["spatial_ref"] = CRS.from_user_input(
            _get_attr(mda, "crs")).wkt
        _mod_attr(mda, "grid_mapping", val="spatial_ref")
        _del_attr(mda, "crs")
        mdc.coords["spatial_ref"] = 0
        mdc.coords["spatial_ref"].attrs["spatial_ref"] = CRS.from_user_input(
            _get_attr(mdc, "crs")).wkt
        _mod_attr(mdc, "grid_mapping", val="spatial_ref")
        _del_attr(mdc, "crs")

        # reproject
        mds_repr = mda.rio.reproject(modis_reproject["to_proj"])
        # test
        _assert_xarrays_equal(mds_repr, mdc)
예제 #15
0
    def __init__(self, name, raster, crs, transform, nodata=0):
        """

        """

        super().__init__()

        self._name = name
        self._raster = band_shape_guard(raster)
        self._nodata = nodata
        self._transform = Affine(*transform) if not isinstance(transform, Affine) else transform
        self._crs = CRS.from_user_input(crs) if not isinstance(crs, CRS) else crs

        # Old rasterio compatibility: a separate check for validity
        if not self._crs.is_valid:
            raise rasterio.errors.CRSError('Invalid CRS {} given'.format(crs))
예제 #16
0
    def __enter__(self):
        """Support using with Context Managers."""
        self.scene_params = s2_sceneid_parser(self.sceneid)

        prefix = self._prefix.format(**self.scene_params)
        self.tileInfo = json.loads(
            get_object(self._hostname,
                       f"{prefix}/tileInfo.json",
                       request_pays=True))
        input_geom = self.tileInfo["tileDataGeometry"]
        input_crs = CRS.from_user_input(
            input_geom["crs"]["properties"]["name"])
        self.datageom = transform_geom(input_crs, constants.WGS84_CRS,
                                       input_geom)
        self.bounds = featureBounds(self.datageom)
        return self
예제 #17
0
def add_spatial_ref(in_ds, dst_crs, grid_map_name):
    # remove old grid map if exists
    try:
        del in_ds.coords[grid_map_name]
    except KeyError:
        pass

    # add grid mapping variable
    in_ds.coords[grid_map_name] = xarray.Variable((), 0)
    match_proj = crs_to_wkt(CRS.from_user_input(dst_crs))

    grid_map_attrs = dict()
    # add grid mapping variable
    grid_map_attrs["spatial_ref"] = match_proj
    # http://cfconventions.org/Data/cf-conventions/cf-conventions-1.7/cf-conventions.html#appendix-grid-mappings
    # http://desktop.arcgis.com/en/arcmap/10.3/manage-data/netcdf/spatial-reference-for-netcdf-data.htm
    grid_map_attrs["crs_wkt"] = match_proj
    in_ds.coords[grid_map_name].attrs = grid_map_attrs
    return in_ds
예제 #18
0
    def reproject(self, dst_crs):
        """
        Reprojects all the features to the new crs
        Args:
            dst_crs: rasterio.CRS or any acceptable by your rasterio version input (str, dict, epsg code), ot 'utm'

        Returns:
            new reprojected FeatureCollection
        """
        if isinstance(dst_crs, str) and dst_crs == 'utm':
            lon1, lat1, lon2, lat2 = self.index.bounds
            dst_crs = _utm_zone((lat1 + lat2)/2, (lon1 + lon2)/2)
        else:
            dst_crs = dst_crs if isinstance(dst_crs, CRS) else CRS.from_user_input(dst_crs)

        # Old rasterio compatibility: a separate check for validity
        if not dst_crs.is_valid:
            raise CRSError('Invalid CRS {} given'.format(dst_crs))

        features = [f.reproject(dst_crs) for f in self.features]
        return FeatureCollection(features, dst_crs)
예제 #19
0
    def reproject(self, dst_crs, interpolation='nearest'):
        """ Change coordinate system (projection) of the band.
        It returns a new BandSample and does not alter the current object

        It is based on `rasterio.warp.reproject
        <https://rasterio.readthedocs.io/en/latest/api/rasterio.warp.html#rasterio.warp.reproject>`_,
        see for more variants of interpolation.

        Args:
            dst_crs: new CRS, may be in any form acceptable by rasterio, for example as EPSG code, string, CRS object; if dst_crs == `utm`, the appropriate UTM zone is used according to the center of the image
            interpolation: interpolation type as in rasterio,  `nearest`, `bilinear`, `cubic`, `lanzsos` or others

        Returns:
            BandSample: a new instance with changed CRS.
        """
        if isinstance(dst_crs, str) and dst_crs == 'utm':
            dst_crs = get_utm_zone(self.crs, self.transform, (self.height, self.width))
        else:
            dst_crs = dst_crs if isinstance(dst_crs, CRS) else CRS.from_user_input(dst_crs)

        # Old rasterio compatibility: a separate check for validity
        if not dst_crs.is_valid:
            raise rasterio.errors.CRSError('Invalid CRS {} given'.format(dst_crs))

        dst_transform, dst_width, dst_height = calculate_default_transform(
            self.crs, dst_crs, self.width, self.height, *self.bounds)

        new_raster = np.empty(shape=(1, dst_height, dst_width), dtype=self.dtype)

        reproject(
            self._raster, new_raster,
            src_transform=self.transform,
            dst_transform=dst_transform,
            src_crs=self.crs,
            dst_crs=dst_crs,
            resampling=getattr(Resampling, interpolation))

        return BandSample(self.name, new_raster, dst_crs, dst_transform, self.nodata)
예제 #20
0
    def set_crs(self, input_crs, inplace=True):
        """
        Set the CRS value for the Dataset/DataArray without modifying
        the dataset/data array.

        Parameters
        ----------
        input_crs: object
            Anything accepted by `rasterio.crs.CRS.from_user_input`.
        inplace: bool, optional
            If True, it will write to the existing dataset. Default is False.

        Returns
        -------
        xarray.Dataset or xarray.DataArray:
        Dataset with crs attribute.

        """
        if hasattr(input_crs, "wkt"):
            input_crs = input_crs.wkt
        crs = CRS.from_user_input(input_crs)
        obj = self._get_obj(inplace=inplace)
        obj.rio._crs = crs
        return obj
예제 #21
0
파일: test_crs.py 프로젝트: mapbox/rasterio
def test_from_user_input_epsg():
    assert 'init' in CRS.from_user_input('epsg:4326')
예제 #22
0
    def reproject(self, dst_crs, dst_res=None, fp=None, interpolation='nearest'):
        """ Change coordinate system (projection) of the band.
        It does not alter the existing file, and creates a new file either in the specified location or a temporary file.

        The band ground sampling distance is not changed, however the resolution may change due to the new coordinate system
        It is based on `rasterio.warp.reproject
        <https://rasterio.readthedocs.io/en/latest/api/rasterio.warp.html#rasterio.warp.reproject>`_,
        see for more variants of interpolation.

        Args:
            dst_crs: new CRS, may be in any form acceptable by rasterio, for example as EPSG code, string, CRS object; if dst_crs == `utm`, the appropriate UTM zone is used according to the center of the image
            fp (str): a filename for the new resampled band. If none, a temporary file is created
            interpolation: interpolation type as in rasterio,  `nearest`, `bilinear`, `cubic`, `lanzsos` or others
            dst_res (Tuple[float, float]): new resoluton, georeferenced pixel size for the new band

        Returns:
            a new reprojected and resampled Band
        """
        if dst_crs == 'utm':
            dst_crs = get_utm_zone(self.crs, self.transform, (self.height, self.width))
        else:
            dst_crs = dst_crs if isinstance(dst_crs, CRS) else CRS.from_user_input(dst_crs)

        # Old rasterio compatibility: a separate check for validity
        if not dst_crs.is_valid:
            raise rasterio.errors.CRSError('Invalid CRS {} given'.format(dst_crs))

        # get temporary filepath if such is not provided
        tmp_file = False if fp is not None else True
        if fp is None:
            fp = '{tmp}/reprojected_{crs}/{directory}/{name}.tif'.format(
                tmp=TMP_DIR, crs=dst_crs, directory=random_name(), name=self.name)
        os.makedirs(os.path.dirname(fp), exist_ok=True)

        # calculate params of new reprojected Band
        transform, width, height = calculate_default_transform(
            self.crs, dst_crs, self.width, self.height, resolution=dst_res,*self.bounds)
        
        kwargs = self.meta.copy()
        kwargs.update({
            'crs': dst_crs,
            'transform': transform,
            'width': width,
            'height': height
        })

        # reproject
        with rasterio.open(fp, 'w', **kwargs) as dst:
                reproject(
                    source=rasterio.band(self._band, 1),
                    destination=rasterio.band(dst, 1),
                    src_transform=self.transform,
                    src_crs=self.crs,
                    dst_transform=transform,
                    dst_crs=dst_crs,
                    resampling=getattr(Resampling, interpolation))

        # new band
        band = Band(fp)
        band._tmp_file = tmp_file # file will be automatically removed when `Band` instance will be deleted
        return band
예제 #23
0
def test_esri_auth__to_authority():
    assert CRS.from_user_input('ESRI:54009').to_authority() == ('ESRI',
                                                                '54009')
예제 #24
0
def test_esri_auth__to_epsg():
    assert CRS.from_user_input('ESRI:54009').to_epsg() is None
예제 #25
0
    def __init__(
        self,
        crs=None,
        tile_matrix_params=None,
        is_global=False,
        identifier=None,
        title=None,
        abstract=None,
        keywords=None,
        well_known_scale_set=None,
        bounding_box=None,
        **kwargs
    ):
        """
        Initialize a Tile Matrix Set.

        Parameters
        ----------
        crs : str or rasterio.crs.CRS
            CRS object or reference to one coordinate reference system. (e.g. an OGC URI)
        tile_matrix_params : list of dicts
            Describes a scale level and its tile matrix. See parameters required by
            meintile.TileMatrix.
        is_global : bool
            Indicates whether TileMatrixSet covers the globe. This helps meintile to
            decide whether to wrap around the Antimeridian in the Tile.get_neighbors()
            function.
        identifier : str, optional
            Tile matrix set identifier.
        title : str, optional
            Title of this tile matrix set, normally used for display to a human.
        abstract : str, optional
            Brief narrative description of this tile matrix set, normally available for
            display to a human.
        keywords : list
            Unordered list of one or more commonly used or formalized word(s) or phrase(s)
            used to describe this dataset.
        well_known_scale_set : str, optional
            Reference to a well-known scale set.
        bounding_box : dict, optional
            Minimum bounding rectangle surrounding the tile matrix set, in the supported
            CRS. The dictionary requires the following entries: 'type' (must be
            'BoundingBoxType'), 'crs' (reference to one coordinate reference system),
            'lower_corner' (lower left corner coordinates) and 'upper_corner' (upper
            right corner coordinates).
        """
        self._well_known_scale_set = well_known_scale_set
        self._identifier = identifier
        self._title = title
        self._abstract = abstract
        self._keywords = keywords
        self._bounding_box = bounding_box
        self._tile_matrix_params = tile_matrix_params

        self.bounds = None
        if self._bounding_box:
            left, bottom = self._bounding_box["lower_corner"]
            right, top = self._bounding_box["upper_corner"]
            self.bounds = Bounds(left, bottom, right, top)
        self.crs = CRS.from_user_input(crs)
        self.crs_str = crs if isinstance(crs, str) else self.crs.to_string()
        self.tile_matrices = OrderedDict(
            [
                (
                    int(i["identifier"]),
                    TileMatrix(
                        **dict(
                            i,
                            identifier=int(i["identifier"]),
                            crs=self.crs,
                            bounds=self.bounds,
                            tile_pyramid=self,
                        )
                    ),
                )
                for i in tile_matrix_params
            ]
        )
        self.is_global = is_global
예제 #26
0
    def clip(self, geometries, crs, all_touched=False, drop=True, invert=False):
        """
        Crops a :class:`xarray.DataArray` by geojson like geometry dicts.

        Powered by `rasterio.features.geometry_mask`.

        Parameters
        ----------
        geometries: list
            A list of geojson geometry dicts.
        crs: :obj:`rasterio.crs.CRS`
            The CRS of the input geometries.
        all_touched : bool, 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 geoemtries
            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.

        Returns
        -------
        DataArray: A clipped :class:`xarray.DataArray` object.


        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)
        """
        geometries = [
            rasterio.warp.transform_geom(CRS.from_user_input(crs), self.crs, geometry)
            for geometry in geometries
        ]

        clip_mask_arr = geometry_mask(
            geometries=geometries,
            out_shape=(int(self.height), int(self.width)),
            transform=self.transform(),
            invert=not invert,
            all_touched=all_touched,
        )
        clip_mask_xray = xarray.DataArray(
            clip_mask_arr,
            coords={
                self.y_dim: self._obj.coords[self.y_dim],
                self.x_dim: self._obj.coords[self.x_dim],
            },
            dims=(self.y_dim, self.x_dim),
        )
        cropped_ds = self._obj.where(clip_mask_xray, drop=drop)
        if self.nodata is not None and not np.isnan(self.nodata):
            cropped_ds = cropped_ds.fillna(self.nodata)

        cropped_ds = cropped_ds.astype(self._obj.dtype)

        if (
            cropped_ds.coords[self.x_dim].size < 1
            or cropped_ds.coords[self.y_dim].size < 1
        ):
            raise NoDataInBounds("No data found in bounds.")

        # make sure correct attributes preserved & projection added
        _add_attrs_proj(cropped_ds, self._obj)

        return cropped_ds
예제 #27
0
def test_crs84():
    """Create CRS from OGC code"""
    assert "WGS 84" in CRS.from_user_input("urn:ogc:def:crs:OGC::CRS84").wkt
예제 #28
0
def test_from_user_input_epsg():
    assert 'init' in CRS.from_user_input('EPSG:4326')
예제 #29
0
@pytest.mark.parametrize("other", ["", 4.2, 0])
def test_equals_different_type(other):
    """Comparison to non-CRS objects is False"""
    assert CRS.from_epsg(4326) != other


def test_from_user_input_custom_crs_class():
    """Support comparison to foreign objects that provide to_wkt()"""
    assert CRS.from_user_input(CustomCRS()) == CRS.from_epsg(4326)


@pytest.mark.parametrize(
    "crs_obj",
    [
        CRS.from_user_input("http://www.opengis.net/def/crs/EPSG/0/4326"),
        pytest.param(
            CRS.from_epsg(4326),
            marks=pytest.mark.xfail(gdal_version.major < 3,
                                    reason="GDAL 2 always returns False"),
        ),
    ],
)
def test_epsg_treats_as_latlong(crs_obj):
    """EPSG treats this CRS as lat, lon (see also PR #1943)."""
    assert epsg_treats_as_latlong(crs_obj)


@pytest.mark.parametrize("crs_obj", [
    CRS.from_user_input("http://www.opengis.net/def/crs/OGC/1.3/CRS84"),
    CRS.from_user_input("http://www.opengis.net/def/crs/EPSG/0/2193"),
예제 #30
0
def test_crs_proj_json__user_input():
    aeqd_crs = CRS(proj="aeqd", lon_0=-80, lat_0=40.5)
    assert CRS.from_user_input(json.dumps(aeqd_crs.to_dict(projjson=True))) == aeqd_crs
예제 #31
0
def test_from_user_input_custom_crs_class():
    """Support comparison to foreign objects that provide to_wkt()"""
    assert CRS.from_user_input(CustomCRS()) == CRS.from_epsg(4326)