def from_string(cls, proj_string): """Make a CRS from an EPSG, PROJ, or WKT string Parameters ---------- proj_string : str An EPSG, PROJ, or WKT string. Returns ------- CRS """ if not proj_string: raise CRSError("CRS is empty or invalid: {!r}".format(proj_string)) elif proj_string.strip().upper().startswith("EPSG:"): auth, val = proj_string.strip().split(":") if not val: raise CRSError("Invalid CRS: {!r}".format(proj_string)) return cls.from_epsg(val) elif "{" in proj_string: # may be json, try to decode it try: val = json.loads(proj_string, strict=False) except ValueError: raise CRSError("CRS appears to be JSON but is not valid") if not val: raise CRSError("CRS is empty JSON") else: return cls(**val) return cls(proj_string)
def _prepare_from_string(in_crs_string: str) -> str: if not in_crs_string: raise CRSError("CRS is empty or invalid: {!r}".format(in_crs_string)) elif "{" in in_crs_string: # may be json, try to decode it try: crs_dict = json.loads(in_crs_string, strict=False) except ValueError: raise CRSError("CRS appears to be JSON but is not valid") if not crs_dict: raise CRSError("CRS is empty JSON") return _prepare_from_dict(crs_dict) elif is_proj(in_crs_string): in_crs_string = re.sub(r"[\s+]?=[\s+]?", "=", in_crs_string.lstrip()) # make sure the projection starts with +proj or +init starting_params = ("+init", "+proj", "init", "proj") if not in_crs_string.startswith(starting_params): kvpairs = [] # type: List[str] first_item_inserted = False for kvpair in in_crs_string.split(): if not first_item_inserted and ( kvpair.startswith(starting_params)): kvpairs.insert(0, kvpair) first_item_inserted = True else: kvpairs.append(kvpair) in_crs_string = " ".join(kvpairs) # make sure it is the CRS type if "type=crs" not in in_crs_string: if "+" in in_crs_string: in_crs_string += " +type=crs" else: in_crs_string += " type=crs" # look for EPSG, replace with epsg (EPSG only works # on case-insensitive filesystems). in_crs_string = in_crs_string.replace("+init=EPSG", "+init=epsg").strip() if in_crs_string.startswith(("+init", "init")): warnings.warn( "'+init=<authority>:<code>' syntax is deprecated. " "'<authority>:<code>' is the preferred initialization method. " "When making the change, be mindful of axis order changes: " "https://pyproj4.github.io/pyproj/stable/gotchas.html" "#axis-order-changes-in-proj-6", FutureWarning, stacklevel=2, ) return in_crs_string
def from_user_input(cls, value): """Make a CRS from various input Dispatches to from_epsg, from_proj, or from_string Parameters ---------- value : obj A Python int, dict, or str. Returns ------- CRS """ if isinstance(value, _CRS): return value elif isinstance(value, int): return cls.from_epsg(value) elif isinstance(value, dict): return cls(**value) elif isinstance(value, string_types): return cls.from_string(value) elif hasattr(value, "to_wkt"): return cls(value.to_wkt()) else: raise CRSError("CRS is invalid: {!r}".format(value))
def __init__(self, crs_spec: Any): """ :param crs_str: string representation of a CRS, often an EPSG code like 'EPSG:4326' :raises: `pyproj.exceptions.CRSError` """ if isinstance(crs_spec, str): self._crs, self._str, self._epsg = _make_crs(crs_spec) elif isinstance(crs_spec, CRS): self._crs = crs_spec._crs self._epsg = crs_spec._epsg self._str = crs_spec._str elif isinstance(crs_spec, _CRS): self._crs, self._str, self._epsg = _make_crs(crs_spec) elif isinstance(crs_spec, dict): self._crs, self._str, self._epsg = _make_crs(_CRS.from_dict(crs_spec)) else: _to_epsg = getattr(crs_spec, "to_epsg", None) if _to_epsg is not None: self._crs, self._str, self._epsg = _make_crs(f"EPSG:{_to_epsg()}") return _to_wkt = getattr(crs_spec, "to_wkt", None) if _to_wkt is not None: self._crs, self._str, self._epsg = _make_crs(_to_wkt()) return raise CRSError( "Expect string or any object with `.to_epsg()` or `.to_wkt()` methods" )
def __init__(self, crs=None, window_size=15, resolution=0.01, lens_position=None, corners=None, gcps=None, lens_pars=None): """ CameraConfig object with several settings. This object allows for treatment of movies with defined settings. :param crs: int, dict, or str, optional. Coordinate Reference System. Accepts EPSG codes (int or str); proj (str or dict) or wkt (str). Only used if the data has no native CRS. :param window_size: int, pixel size of interrogation window (default: 15) :param resolution: float, resolution in m. of projected pixels :param lens_position: list of 3 floats, containing x, y, z coordinate of lens position in CRS :param corners: list of 4 lists with [x, y] coordinates defining corners of area of interest in camera cols/rows :param gcps: dict, containing: "src": list of 4 lists, with column, row locations in objective of control points. "dst": list of 4 lists, with x, y locations (local or global coordinate reference system) of control points. "h_ref": float, measured water level [m] in local reference system (e.g. from staff gauge or pressure gauge) during gcp survey. "z_0": float, water level [m] in global reference system (e.g. from used GPS system CRS). This must be in the same vertical reference as the measured bathymetry and other survey points. "crs": int, str or CRS object, CRS in which "dst" points are measured. If None, a local coordinate system is assumed (e.g. from spirit level). :param lens_pars: dict, containing: "k1": float, barrel lens distortion parameter (default: 0.) "c": float, optical center (default: 2.) "f": float, focal length (default: 1.) """ assert (isinstance(window_size, int)), 'window_size must be of type "int"' if crs is not None: try: crs = CRS.from_user_input(crs) except CRSError: raise CRSError( f'crs "{crs}" is not a valid Coordinate Reference System') assert (crs.is_geographic == 0 ), "Provided crs must be projected with units like [m]" self.crs = crs.to_wkt() if resolution is not None: self.resolution = resolution if lens_position is not None: self.set_lens_position(*lens_position) if gcps is not None: self.set_gcps(**gcps) if lens_pars is not None: self.set_lens_pars(**lens_pars) if window_size is not None: self.window_size = window_size # override the transform and bbox with the set corners if corners is not None: self.set_corners(corners)
def _from_string(in_crs_string): if not in_crs_string: raise CRSError("CRS is empty or invalid: {!r}".format(in_crs_string)) elif "{" in in_crs_string: # may be json, try to decode it try: crs_dict = json.loads(in_crs_string, strict=False) except ValueError: raise CRSError("CRS appears to be JSON but is not valid") if not crs_dict: raise CRSError("CRS is empty JSON") return _from_dict(crs_dict) elif not is_wkt(in_crs_string) and "=" in in_crs_string: # make sure the projection starts with +proj or +init starting_params = ("+init", "+proj", "init", "proj") if not in_crs_string.lstrip().startswith(starting_params): kvpairs = [] first_item_inserted = False for kvpair in in_crs_string.split(): if not first_item_inserted and ( kvpair.startswith(starting_params)): kvpairs.insert(0, kvpair) first_item_inserted = True else: kvpairs.append(kvpair) in_crs_string = " ".join(kvpairs) # make sure it is the CRS type if "type=crs" not in in_crs_string: if "+" in in_crs_string: in_crs_string += " +type=crs" else: in_crs_string += " type=crs" # look for EPSG, replace with epsg (EPSG only works # on case-insensitive filesystems). in_crs_string = in_crs_string.replace("+init=EPSG", "+init=epsg").strip() # remove no_defs as it does nothing as of PROJ 6.0.0 and breaks # initialization with +init=epsg:... in_crs_string = re.sub(r"\s\+?no_defs([\w=]+)?", "", in_crs_string) return in_crs_string
def from_wkt(cls, in_wkt_string): """Make a CRS from a WKT string Parameters ---------- in_wkt_string : str A WKT string. Returns ------- CRS """ if not is_wkt(in_wkt_string): raise CRSError("Invalid WKT string: {}".format(in_wkt_string)) return cls(_from_string(in_wkt_string))
def from_proj4(cls, in_proj_string): """Make a CRS from a PROJ string Parameters ---------- in_proj_string : str A PROJ string. Returns ------- CRS """ if is_wkt(in_proj_string) or "=" not in in_proj_string: raise CRSError("Invalid PROJ string: {}".format(in_proj_string)) return cls(_from_string(in_proj_string))
def __init__(self, crs_str: Any): """ :param crs_str: string representation of a CRS, often an EPSG code like 'EPSG:4326' :raises: `pyproj.exceptions.CRSError` """ crs_str = _guess_crs_str(crs_str) if crs_str is None: raise CRSError( "Expect string or any object with `.to_epsg()` or `.to_wkt()` method" ) _crs, _epsg = _make_crs(crs_str) self._crs = _crs self._epsg = _epsg self._str = crs_str
def from_proj4(in_proj_string: str) -> "CRS": """ .. versionadded:: 2.2.0 Make a CRS from a PROJ string Parameters ---------- in_proj_string : str A PROJ string. Returns ------- CRS """ if not is_proj(in_proj_string): raise CRSError("Invalid PROJ string: {}".format(in_proj_string)) return CRS(_prepare_from_string(in_proj_string))
def from_wkt(in_wkt_string: str) -> "CRS": """ .. versionadded:: 2.2.0 Make a CRS from a WKT string Parameters ---------- in_wkt_string : str A WKT string. Returns ------- CRS """ if not is_wkt(in_wkt_string): raise CRSError("Invalid WKT string: {}".format(in_wkt_string)) return CRS(_prepare_from_string(in_wkt_string))
def from_epsg(cls, code): """Make a CRS from an EPSG code Parameters ---------- code : int or str An EPSG code. Strings will be converted to integers. Notes ----- The input code is not validated against an EPSG database. Returns ------- CRS """ if int(code) <= 0: raise CRSError("EPSG codes are positive integers") return cls("epsg:{}".format(code))
def from_auth(cls, auth_name, code): """Make a CRS from an EPSG code Parameters ---------- auth_name: str The name of the authority. code : int or str The code used by the authority. Strings will be converted to integers. Notes ----- The input code is not validated against an EPSG database. Returns ------- ~CRS """ if int(code) <= 0: raise CRSError("Authority codes are positive integers") return cls("{}:{}".format(auth_name, code))
def from_cf( in_cf: dict, ellipsoidal_cs: Any = None, cartesian_cs: Any = None, vertical_cs: Any = None, errcheck=False, ) -> "CRS": """ .. versionadded:: 2.2.0 .. versionadded:: 3.0.0 ellipsoidal_cs, cartesian_cs, vertical_cs This converts a Climate and Forecast (CF) Grid Mapping Version 1.8 dict to a :obj:`pyproj.crs.CRS` object. :ref:`build_crs_cf` Parameters ---------- in_cf: dict CF version of the projection. ellipsoidal_cs: Any, optional Input to create an Ellipsoidal Coordinate System. Anything accepted by :meth:`pyproj.crs.CoordinateSystem.from_user_input` or an Ellipsoidal Coordinate System created from :ref:`coordinate_system`. cartesian_cs: Any, optional Input to create a Cartesian Coordinate System. Anything accepted by :meth:`pyproj.crs.CoordinateSystem.from_user_input` or :class:`pyproj.crs.coordinate_system.Cartesian2DCS`. vertical_cs: Any, optional Input to create a Vertical Coordinate System accepted by :meth:`pyproj.crs.CoordinateSystem.from_user_input` or :class:`pyproj.crs.coordinate_system.VerticalCS` errcheck: bool, optional This parameter is for backwards compatibility with the old version. It currently does nothing when True or False. Returns ------- CRS """ unknown_names = ("unknown", "undefined") if "crs_wkt" in in_cf: return CRS(in_cf["crs_wkt"]) elif "spatial_ref" in in_cf: # for previous supported WKT key return CRS(in_cf["spatial_ref"]) grid_mapping_name = in_cf.get("grid_mapping_name") if grid_mapping_name is None: raise CRSError( "CF projection parameters missing 'grid_mapping_name'") # build datum if possible datum = _horizontal_datum_from_params(in_cf) # build geographic CRS try: geographic_conversion_method = _GEOGRAPHIC_GRID_MAPPING_NAME_MAP[ grid_mapping_name] # type: Optional[Callable] except KeyError: geographic_conversion_method = None geographic_crs_name = in_cf.get("geographic_crs_name") if datum: geographic_crs = GeographicCRS( name=geographic_crs_name or "undefined", datum=datum, ellipsoidal_cs=ellipsoidal_cs, ) # type: CRS elif geographic_crs_name and geographic_crs_name not in unknown_names: geographic_crs = CRS(geographic_crs_name) if ellipsoidal_cs is not None: geographic_crs_json = geographic_crs.to_json_dict() geographic_crs_json[ "coordinate_system"] = CoordinateSystem.from_user_input( ellipsoidal_cs).to_json_dict() geographic_crs = CRS(geographic_crs_json) else: geographic_crs = GeographicCRS(ellipsoidal_cs=ellipsoidal_cs) if grid_mapping_name == "latitude_longitude": return geographic_crs if geographic_conversion_method is not None: return DerivedGeographicCRS( base_crs=geographic_crs, conversion=geographic_conversion_method(in_cf), ellipsoidal_cs=ellipsoidal_cs, ) # build projected CRS try: conversion_method = _GRID_MAPPING_NAME_MAP[grid_mapping_name] except KeyError: raise CRSError( f"Unsupported grid mapping name: {grid_mapping_name}") projected_crs = ProjectedCRS( name=in_cf.get("projected_crs_name", "undefined"), conversion=conversion_method(in_cf), geodetic_crs=geographic_crs, cartesian_cs=cartesian_cs, ) # build bound CRS if exists bound_crs = None if "towgs84" in in_cf: bound_crs = BoundCRS( source_crs=projected_crs, target_crs="WGS 84", transformation=ToWGS84Transformation( projected_crs.geodetic_crs, *_try_list_if_string(in_cf["towgs84"])), ) if "geopotential_datum_name" not in in_cf: return bound_crs or projected_crs # build Vertical CRS vertical_crs = VerticalCRS( name="undefined", datum=in_cf["geopotential_datum_name"], geoid_model=in_cf.get("geoid_name"), vertical_cs=vertical_cs, ) # build compound CRS return CompoundCRS( name="undefined", components=[bound_crs or projected_crs, vertical_crs])
def __init__(self, projparams: Any = None, **kwargs) -> None: """ Initialize a CRS class instance with: - PROJ string - Dictionary of PROJ parameters - PROJ keyword arguments for parameters - JSON string with PROJ parameters - CRS WKT string - An authority string [i.e. 'epsg:4326'] - An EPSG integer code [i.e. 4326] - A tuple of ("auth_name": "auth_code") [i.e ('epsg', '4326')] - An object with a `to_wkt` method. - A :class:`pyproj.crs.CRS` class Example usage: >>> from pyproj import CRS >>> crs_utm = CRS.from_user_input(26915) >>> crs_utm <Projected CRS: EPSG:26915> Name: NAD83 / UTM zone 15N Axis Info [cartesian]: - E[east]: Easting (metre) - N[north]: Northing (metre) Area of Use: - name: North America - 96°W to 90°W and NAD83 by country - bounds: (-96.0, 25.61, -90.0, 84.0) Coordinate Operation: - name: UTM zone 15N - method: Transverse Mercator Datum: North American Datum 1983 - Ellipsoid: GRS 1980 - Prime Meridian: Greenwich <BLANKLINE> >>> crs_utm.area_of_use.bounds (-96.0, 25.61, -90.0, 84.0) >>> crs_utm.ellipsoid ELLIPSOID["GRS 1980",6378137,298.257222101, LENGTHUNIT["metre",1], ID["EPSG",7019]] >>> crs_utm.ellipsoid.inverse_flattening 298.257222101 >>> crs_utm.ellipsoid.semi_major_metre 6378137.0 >>> crs_utm.ellipsoid.semi_minor_metre 6356752.314140356 >>> crs_utm.prime_meridian PRIMEM["Greenwich",0, ANGLEUNIT["degree",0.0174532925199433], ID["EPSG",8901]] >>> crs_utm.prime_meridian.unit_name 'degree' >>> crs_utm.prime_meridian.unit_conversion_factor 0.017453292519943295 >>> crs_utm.prime_meridian.longitude 0.0 >>> crs_utm.datum DATUM["North American Datum 1983", ELLIPSOID["GRS 1980",6378137,298.257222101, LENGTHUNIT["metre",1]], ID["EPSG",6269]] >>> crs_utm.coordinate_system CS[Cartesian,2], AXIS["(E)",east, ORDER[1], LENGTHUNIT["metre",1, ID["EPSG",9001]]], AXIS["(N)",north, ORDER[2], LENGTHUNIT["metre",1, ID["EPSG",9001]]] >>> print(crs_utm.coordinate_operation.to_wkt(pretty=True)) CONVERSION["UTM zone 15N", METHOD["Transverse Mercator", ID["EPSG",9807]], PARAMETER["Latitude of natural origin",0, ANGLEUNIT["degree",0.0174532925199433], ID["EPSG",8801]], PARAMETER["Longitude of natural origin",-93, ANGLEUNIT["degree",0.0174532925199433], ID["EPSG",8802]], PARAMETER["Scale factor at natural origin",0.9996, SCALEUNIT["unity",1], ID["EPSG",8805]], PARAMETER["False easting",500000, LENGTHUNIT["metre",1], ID["EPSG",8806]], PARAMETER["False northing",0, LENGTHUNIT["metre",1], ID["EPSG",8807]], ID["EPSG",16015]] >>> crs = CRS(proj='utm', zone=10, ellps='WGS84') >>> print(crs.to_wkt(pretty=True)) PROJCRS["unknown", BASEGEOGCRS["unknown", DATUM["Unknown based on WGS84 ellipsoid", ELLIPSOID["WGS 84",6378137,298.257223563, LENGTHUNIT["metre",1], ID["EPSG",7030]]], PRIMEM["Greenwich",0, ANGLEUNIT["degree",0.0174532925199433], ID["EPSG",8901]]], CONVERSION["UTM zone 10N", METHOD["Transverse Mercator", ID["EPSG",9807]], PARAMETER["Latitude of natural origin",0, ANGLEUNIT["degree",0.0174532925199433], ID["EPSG",8801]], PARAMETER["Longitude of natural origin",-123, ANGLEUNIT["degree",0.0174532925199433], ID["EPSG",8802]], PARAMETER["Scale factor at natural origin",0.9996, SCALEUNIT["unity",1], ID["EPSG",8805]], PARAMETER["False easting",500000, LENGTHUNIT["metre",1], ID["EPSG",8806]], PARAMETER["False northing",0, LENGTHUNIT["metre",1], ID["EPSG",8807]], ID["EPSG",16010]], CS[Cartesian,2], AXIS["(E)",east, ORDER[1], LENGTHUNIT["metre",1, ID["EPSG",9001]]], AXIS["(N)",north, ORDER[2], LENGTHUNIT["metre",1, ID["EPSG",9001]]]] >>> geod = crs.get_geod() >>> "+a={:.0f} +f={:.8f}".format(geod.a, geod.f) '+a=6378137 +f=0.00335281' >>> crs.is_projected True >>> crs.is_geographic False """ projstring = "" if projparams: if isinstance(projparams, str): projstring = _prepare_from_string(projparams) elif isinstance(projparams, dict): projstring = _prepare_from_dict(projparams) elif isinstance(projparams, int): projstring = _prepare_from_epsg(projparams) elif isinstance(projparams, (list, tuple)) and len(projparams) == 2: projstring = _prepare_from_authority(*projparams) elif hasattr(projparams, "to_wkt"): projstring = projparams.to_wkt() # type: ignore else: raise CRSError("Invalid CRS input: {!r}".format(projparams)) if kwargs: projkwargs = _prepare_from_dict(kwargs, allow_json=False) projstring = _prepare_from_string(" ".join( (projstring, projkwargs))) super().__init__(projstring)
def __init__(self, projparams=None, **kwargs): """ Initialize a CRS class instance with a WKT string, a proj,4 string, a proj.4 dictionary, or with proj.4 keyword arguments. CRS projection control parameters must either be given in a dictionary 'projparams' or as keyword arguments. See the proj.4 documentation (https://github.com/OSGeo/proj.4/wiki) for more information about specifying projection parameters. Example usage: >>> from pyproj import CRS >>> crs_utm = CRS.from_user_input(26915) >>> crs_utm <CRS: epsg:26915> Name: NAD83 / UTM zone 15N Ellipsoid: - semi_major_metre: 6378137.00 - semi_minor_metre: 6356752.31 - inverse_flattening: 298.26 Area of Use: - name: North America - 96°W to 90°W and NAD83 by country - bounds: (-96.0, 25.61, -90.0, 84.0) Prime Meridian: - longitude: 0.0000 - unit_name: degree - unit_conversion_factor: 0.01745329 Axis Info: - Easting[E] (east) EPSG:9001 (metre) - Northing[N] (north) EPSG:9001 (metre) <BLANKLINE> >>> crs_utm.area_of_use.bounds (-96.0, 25.61, -90.0, 84.0) >>> crs_utm.ellipsoid.inverse_flattening 298.257222101 >>> crs_utm.ellipsoid.semi_major_metre 6378137.0 >>> crs_utm.ellipsoid.semi_minor_metre 6356752.314140356 >>> crs_utm.prime_meridian.unit_name 'degree' >>> crs_utm.prime_meridian.unit_conversion_factor 0.017453292519943295 >>> crs_utm.prime_meridian.longitude 0.0 >>> crs = CRS(proj='utm', zone=10, ellps='WGS84') >>> crs.to_proj4() '+proj=utm +zone=10 +ellps=WGS84 +units=m +no_defs +type=crs' >>> crs.to_wkt() 'PROJCRS["unknown",BASEGEOGCRS["unknown",DATUM["Unknown based on WGS84 ellipsoid",ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1],ID["EPSG",7030]]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8901]]],CONVERSION["UTM zone 10N",METHOD["Transverse Mercator",ID["EPSG",9807]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",-123,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["Scale factor at natural origin",0.9996,SCALEUNIT["unity",1],ID["EPSG",8805]],PARAMETER["False easting",500000,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1],ID["EPSG",8807]],ID["EPSG",16010]],CS[Cartesian,2],AXIS["(E)",east,ORDER[1],LENGTHUNIT["metre",1,ID["EPSG",9001]]],AXIS["(N)",north,ORDER[2],LENGTHUNIT["metre",1,ID["EPSG",9001]]]]' >>> geod = crs.get_geod() >>> "+a={:.0f} +f={:.8f}".format(geod.a, geod.f) '+a=6378137 +f=0.00335281' >>> crs.is_projected True >>> crs.is_geographic False >>> crs.is_valid True """ # if projparams is None, use kwargs. if projparams is None: if len(kwargs) == 0: raise CRSError("no projection control parameters specified") else: projstring = _dict2string(kwargs) elif isinstance(projparams, string_types): # if projparams is a string or a unicode string, interpret as a proj4 init string. projstring = projparams else: # projparams a dict projstring = _dict2string(projparams) # make sure the projection starts with +proj or +init starting_params = ("+init", "+proj") if not projstring.lstrip().startswith(starting_params): kvpairs = [] first_item_inserted = False for kvpair in projstring.split(): if not first_item_inserted and ( kvpair.startswith(starting_params)): kvpairs.insert(0, kvpair) first_item_inserted = True else: kvpairs.append(kvpair) projstring = " ".join(kvpairs) # look for EPSG, replace with epsg (EPSG only works # on case-insensitive filesystems). projstring = projstring.replace("+init=EPSG", "+init=epsg").strip() super(CRS, self).__init__(projstring)
def from_cf(in_cf, errcheck=False): """ This converts a Climate and Forecast (CF) Grid Mapping Version 1.8 dict to a :obj:`~pyproj.crs.CRS` object. .. warning:: Parameters may be lost if a mapping from the CF parameter is not found. For best results store the WKT of the projection in the crs_wkt attribute. Parameters ---------- in_cf: dict CF version of the projection. errcheck: bool, optional If True, will warn when parameters are ignored. Defaults to False. Returns ------- CRS """ in_cf = in_cf.copy() # preserve user input if "crs_wkt" in in_cf: return CRS(in_cf["crs_wkt"]) elif "spatial_ref" in in_cf: # for previous supported WKT key return CRS(in_cf["spatial_ref"]) grid_mapping_name = in_cf.pop("grid_mapping_name", None) if grid_mapping_name is None: raise CRSError( "CF projection parameters missing 'grid_mapping_name'") proj_name = GRID_MAPPING_NAME_MAP.get(grid_mapping_name) if proj_name is None: raise CRSError( "Unsupported grid mapping name: {}".format(grid_mapping_name)) proj_dict = {"proj": proj_name} if grid_mapping_name == "rotated_latitude_longitude": proj_dict["o_proj"] = "latlon" elif grid_mapping_name == "oblique_mercator": try: proj_dict["lonc"] = in_cf.pop("longitude_of_projection_origin") except KeyError: pass if "standard_parallel" in in_cf: standard_parallel = in_cf.pop("standard_parallel") if isinstance(standard_parallel, list): proj_dict["lat_1"] = standard_parallel[0] proj_dict["lat_2"] = standard_parallel[1] else: proj_dict["lat_1"] = standard_parallel # The values are opposite to sweep_angle_axis if "fixed_angle_axis" in in_cf: proj_dict["sweep"] = { "x": "y", "y": "x" }[in_cf.pop("fixed_angle_axis").lower()] skipped_params = [] for cf_param, proj_val in in_cf.items(): try: proj_dict[PROJ_PARAM_MAP[cf_param]] = proj_val except KeyError: skipped_params.append(cf_param) if errcheck and skipped_params: warnings.warn("CF parameters not mapped to PROJ: {}".format( tuple(skipped_params))) return CRS(proj_dict)
def from_cf(in_cf: dict, errcheck=False) -> "CRS": """ .. versionadded:: 2.2.0 This converts a Climate and Forecast (CF) Grid Mapping Version 1.8 dict to a :obj:`pyproj.crs.CRS` object. .. warning:: Parameters may be lost if a mapping from the CF parameter is not found. For best results store the WKT of the projection in the crs_wkt attribute. Parameters ---------- in_cf: dict CF version of the projection. errcheck: bool, optional This parameter is for backwards compatibility with the old version. It currently does nothing when True or False. Returns ------- CRS """ unknown_names = ("unknown", "undefined") if "crs_wkt" in in_cf: return CRS(in_cf["crs_wkt"]) elif "spatial_ref" in in_cf: # for previous supported WKT key return CRS(in_cf["spatial_ref"]) grid_mapping_name = in_cf.get("grid_mapping_name") if grid_mapping_name is None: raise CRSError( "CF projection parameters missing 'grid_mapping_name'") # build datum if possible datum = _horizontal_datum_from_params(in_cf) # build geographic CRS try: geographic_conversion_method = _GEOGRAPHIC_GRID_MAPPING_NAME_MAP[ grid_mapping_name] # type: Optional[Callable] except KeyError: geographic_conversion_method = None geographic_crs_name = in_cf.get("geographic_crs_name") if datum: geographic_crs = GeographicCRS( name=geographic_crs_name or "undefined", datum=datum, ) # type: CRS elif geographic_crs_name and geographic_crs_name not in unknown_names: geographic_crs = CRS(geographic_crs_name) else: geographic_crs = GeographicCRS() if grid_mapping_name == "latitude_longitude": return geographic_crs if geographic_conversion_method is not None: return DerivedGeographicCRS( base_crs=geographic_crs, conversion=geographic_conversion_method(in_cf), ) # build projected CRS try: conversion_method = _GRID_MAPPING_NAME_MAP[grid_mapping_name] except KeyError: raise CRSError( "Unsupported grid mapping name: {}".format(grid_mapping_name)) projected_crs = ProjectedCRS( name=in_cf.get("projected_crs_name", "undefined"), conversion=conversion_method(in_cf), geodetic_crs=geographic_crs, ) # build bound CRS if exists bound_crs = None if "towgs84" in in_cf: bound_crs = BoundCRS( source_crs=projected_crs, target_crs="WGS 84", transformation=ToWGS84Transformation( projected_crs.geodetic_crs, *_try_list_if_string(in_cf["towgs84"])), ) if "geopotential_datum_name" not in in_cf: return bound_crs or projected_crs # build Vertical CRS vertical_crs = VerticalCRS( name="undefined", datum=in_cf["geopotential_datum_name"], geoid_model=in_cf.get("geoid_name"), ) # build compound CRS return CompoundCRS( name="undefined", components=[bound_crs or projected_crs, vertical_crs])
def __init__(self, projparams=None, **kwargs): """ Initialize a CRS class instance with: - PROJ string - Dictionary of PROJ parameters - PROJ keyword arguments for parameters - JSON string with PROJ parameters - CRS WKT string - An authority string [i.e. 'epsg:4326'] - An EPSG integer code [i.e. 4326] - A tuple of ("auth_name": "auth_code") [i.e ('epsg', '4326')] - An object with a `to_wkt` method. - A :class:`~pyproj.CRS` Example usage: >>> from pyproj import CRS >>> crs_utm = CRS.from_user_input(26915) >>> crs_utm <Projected CRS: EPSG:26915> Name: NAD83 / UTM zone 15N Axis Info [cartesian]: - E[east]: Easting (metre) - N[north]: Northing (metre) Area of Use: - name: North America - 96°W to 90°W and NAD83 by country - bounds: (-96.0, 25.61, -90.0, 84.0) Coordinate Operation: - name: UTM zone 15N - method: Transverse Mercator Datum: North American Datum 1983 - Ellipsoid: GRS 1980 - Prime Meridian: Greenwich <BLANKLINE> >>> crs_utm.area_of_use.bounds (-96.0, 25.61, -90.0, 84.0) >>> crs_utm.ellipsoid ELLIPSOID["GRS 1980",6378137,298.257222101, LENGTHUNIT["metre",1], ID["EPSG",7019]] >>> crs_utm.ellipsoid.inverse_flattening 298.257222101 >>> crs_utm.ellipsoid.semi_major_metre 6378137.0 >>> crs_utm.ellipsoid.semi_minor_metre 6356752.314140356 >>> crs_utm.prime_meridian PRIMEM["Greenwich",0, ANGLEUNIT["degree",0.0174532925199433], ID["EPSG",8901]] >>> crs_utm.prime_meridian.unit_name 'degree' >>> crs_utm.prime_meridian.unit_conversion_factor 0.017453292519943295 >>> crs_utm.prime_meridian.longitude 0.0 >>> crs_utm.datum DATUM["North American Datum 1983", ELLIPSOID["GRS 1980",6378137,298.257222101, LENGTHUNIT["metre",1]], ID["EPSG",6269]] >>> crs_utm.coordinate_system CS[Cartesian,2], AXIS["(E)",east, ORDER[1], LENGTHUNIT["metre",1, ID["EPSG",9001]]], AXIS["(N)",north, ORDER[2], LENGTHUNIT["metre",1, ID["EPSG",9001]]] >>> crs_utm.coordinate_operation CONVERSION["UTM zone 15N", METHOD["Transverse Mercator", ID["EPSG",9807]], PARAMETER["Latitude of natural origin",0, ANGLEUNIT["degree",0.0174532925199433], ID["EPSG",8801]], PARAMETER["Longitude of natural origin",-93, ANGLEUNIT["degree",0.0174532925199433], ID["EPSG",8802]], PARAMETER["Scale factor at natural origin",0.9996, SCALEUNIT["unity",1], ID["EPSG",8805]], PARAMETER["False easting",500000, LENGTHUNIT["metre",1], ID["EPSG",8806]], PARAMETER["False northing",0, LENGTHUNIT["metre",1], ID["EPSG",8807]], ID["EPSG",16015]] >>> print(crs_utm.to_json(pretty=True)) { "$schema": "https://proj.org/schemas/v0.1/projjson.schema.json", "type": "ProjectedCRS", "name": "NAD83 / UTM zone 15N", "base_crs": { "name": "NAD83", "datum": { "type": "GeodeticReferenceFrame", "name": "North American Datum 1983", "ellipsoid": { "name": "GRS 1980", "semi_major_axis": 6378137, "inverse_flattening": 298.257222101 } }, "coordinate_system": { "subtype": "ellipsoidal", "axis": [ { "name": "Geodetic latitude", "abbreviation": "Lat", "direction": "north", "unit": "degree" }, { "name": "Geodetic longitude", "abbreviation": "Lon", "direction": "east", "unit": "degree" } ] }, "id": { "authority": "EPSG", "code": 4269 } }, "conversion": { "name": "UTM zone 15N", "method": { "name": "Transverse Mercator", "id": { "authority": "EPSG", "code": 9807 } }, "parameters": [ { "name": "Latitude of natural origin", "value": 0, "unit": "degree", "id": { "authority": "EPSG", "code": 8801 } }, { "name": "Longitude of natural origin", "value": -93, "unit": "degree", "id": { "authority": "EPSG", "code": 8802 } }, { "name": "Scale factor at natural origin", "value": 0.9996, "unit": "unity", "id": { "authority": "EPSG", "code": 8805 } }, { "name": "False easting", "value": 500000, "unit": "metre", "id": { "authority": "EPSG", "code": 8806 } }, { "name": "False northing", "value": 0, "unit": "metre", "id": { "authority": "EPSG", "code": 8807 } } ] }, "coordinate_system": { "subtype": "Cartesian", "axis": [ { "name": "Easting", "abbreviation": "E", "direction": "east", "unit": "metre" }, { "name": "Northing", "abbreviation": "N", "direction": "north", "unit": "metre" } ] }, "area": "North America - 96°W to 90°W and NAD83 by country", "bbox": { "south_latitude": 25.61, "west_longitude": -96, "north_latitude": 84, "east_longitude": -90 }, "id": { "authority": "EPSG", "code": 26915 } } >>> crs = CRS(proj='utm', zone=10, ellps='WGS84') >>> crs.to_proj4() '+proj=utm +zone=10 +ellps=WGS84 +units=m +no_defs +type=crs' >>> print(crs.to_wkt(pretty=True)) PROJCRS["unknown", BASEGEOGCRS["unknown", DATUM["Unknown based on WGS84 ellipsoid", ELLIPSOID["WGS 84",6378137,298.257223563, LENGTHUNIT["metre",1], ID["EPSG",7030]]], PRIMEM["Greenwich",0, ANGLEUNIT["degree",0.0174532925199433], ID["EPSG",8901]]], CONVERSION["UTM zone 10N", METHOD["Transverse Mercator", ID["EPSG",9807]], PARAMETER["Latitude of natural origin",0, ANGLEUNIT["degree",0.0174532925199433], ID["EPSG",8801]], PARAMETER["Longitude of natural origin",-123, ANGLEUNIT["degree",0.0174532925199433], ID["EPSG",8802]], PARAMETER["Scale factor at natural origin",0.9996, SCALEUNIT["unity",1], ID["EPSG",8805]], PARAMETER["False easting",500000, LENGTHUNIT["metre",1], ID["EPSG",8806]], PARAMETER["False northing",0, LENGTHUNIT["metre",1], ID["EPSG",8807]], ID["EPSG",16010]], CS[Cartesian,2], AXIS["(E)",east, ORDER[1], LENGTHUNIT["metre",1, ID["EPSG",9001]]], AXIS["(N)",north, ORDER[2], LENGTHUNIT["metre",1, ID["EPSG",9001]]]] >>> geod = crs.get_geod() >>> "+a={:.0f} +f={:.8f}".format(geod.a, geod.f) '+a=6378137 +f=0.00335281' >>> crs.is_projected True >>> crs.is_geographic False """ if isinstance(projparams, str): projstring = _prepare_from_string(projparams) elif isinstance(projparams, dict): projstring = _prepare_from_dict(projparams) elif kwargs: projstring = _prepare_from_dict(kwargs) elif isinstance(projparams, int): projstring = _prepare_from_epsg(projparams) elif isinstance(projparams, (list, tuple)) and len(projparams) == 2: projstring = _prepare_from_authority(*projparams) elif hasattr(projparams, "to_wkt"): projstring = projparams.to_wkt() else: raise CRSError("Invalid CRS input: {!r}".format(projparams)) super(CRS, self).__init__(projstring)