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}')
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
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
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)
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
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
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
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
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, )
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
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)
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))
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
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
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)
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)
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
def test_from_user_input_epsg(): assert 'init' in CRS.from_user_input('epsg:4326')
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
def test_esri_auth__to_authority(): assert CRS.from_user_input('ESRI:54009').to_authority() == ('ESRI', '54009')
def test_esri_auth__to_epsg(): assert CRS.from_user_input('ESRI:54009').to_epsg() is None
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
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
def test_crs84(): """Create CRS from OGC code""" assert "WGS 84" in CRS.from_user_input("urn:ogc:def:crs:OGC::CRS84").wkt
def test_from_user_input_epsg(): assert 'init' in CRS.from_user_input('EPSG:4326')
@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"),
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
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)