def _proj4_str_to_dict(self, proj4_string): """ Converts PROJ4 compatible string to dictionary. Parameters ---------- proj4_string : str PROJ4 parameters as a string (e.g., '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'). Returns ------- dict Dictionary containing PROJ4 parameters. Notes ----- Key only parameters will be assigned a value of `True`. EPSG codes should be provided as "EPSG:XXXX" where "XXXX" is the EPSG code number. It can also be provided as "+init=EPSG:XXXX" as long as the underlying PROJ library supports it (deprecated in PROJ 6.0+). """ # convert EPSG codes to equivalent PROJ4 string definition if proj4_string.lower().startswith('epsg:'): crs = CRS(proj4_string) return crs.to_dict() else: proj4_pairs = (x.split('=', 1) for x in proj4_string.replace('+', '').split(" ")) return self.__convert_proj4_pairs_to_dict(proj4_pairs)
def _convert_units(var, name: str, units: str, p: Proj, crs: CRS, inverse: bool = False, center=None): """Converts units from lon/lat to projection coordinates (meters). If `inverse` it True then the inverse calculation is done. """ if var is None: return None if isinstance(var, DataArray): units = var.units var = tuple(var.data.tolist()) if crs.is_geographic and not ('deg' == units or 'degrees' == units): raise ValueError( 'latlon/latlong projection cannot take {0} as units: {1}'.format( units, name)) # Check if units are an angle. is_angle = ('deg' == units or 'degrees' == units) if ('deg' in units) and not is_angle: logging.warning('units provided to {0} are incorrect: {1}'.format( name, units)) # Convert from var projection units to projection units given by projection from user. if not is_angle: if units == 'meters' or units == 'metres': units = 'm' if _get_proj_units(crs) != units: tmp_proj_dict = crs.to_dict() tmp_proj_dict['units'] = units transformer = Transformer.from_crs(tmp_proj_dict, p.crs) var = transformer.transform(*var) if name == 'center': var = _round_poles(var, units, p) # Return either degrees or meters depending on if the inverse is true or not. # Don't convert if inverse is True: Want degrees. # Converts list-like from degrees to meters. if is_angle and not inverse: if name in ('radius', 'resolution'): var = _distance_from_center_forward(var, center, p) elif not crs.is_geographic: # only convert to meters # this allows geographic projections to use coordinates outside # normal lon/lat ranges (ex. -90/90) var = p(*var, errcheck=True) # Don't convert if inverse is False: Want meters. elif not is_angle and inverse: # Converts list-like from meters to degrees. var = p(*var, inverse=True, errcheck=True) if name in ['radius', 'resolution']: var = (abs(var[0]), abs(var[1])) return var
def proj4_radius_parameters(proj4_dict): """Calculate 'a' and 'b' radius parameters. Arguments: proj4_dict (str or dict): PROJ.4 parameters Returns: a (float), b (float): equatorial and polar radius """ if CRS is not None: import math crs = CRS(proj4_dict) a = crs.ellipsoid.semi_major_metre b = crs.ellipsoid.semi_minor_metre if not math.isnan(b): return a, b # older versions of pyproj didn't always have a valid minor radius proj4_dict = crs.to_dict() if isinstance(proj4_dict, str): new_info = proj4_str_to_dict(proj4_dict) else: new_info = proj4_dict.copy() # load information from PROJ.4 about the ellipsis if possible from pyproj import Geod if 'ellps' in new_info: geod = Geod(**new_info) new_info['a'] = geod.a new_info['b'] = geod.b elif 'a' not in new_info or 'b' not in new_info: if 'rf' in new_info and 'f' not in new_info: new_info['f'] = 1. / float(new_info['rf']) if 'a' in new_info and 'f' in new_info: new_info['b'] = float(new_info['a']) * (1 - float(new_info['f'])) elif 'b' in new_info and 'f' in new_info: new_info['a'] = float(new_info['b']) / (1 - float(new_info['f'])) elif 'R' in new_info: new_info['a'] = new_info['R'] new_info['b'] = new_info['R'] else: geod = Geod(**{'ellps': 'WGS84'}) new_info['a'] = geod.a new_info['b'] = geod.b return float(new_info['a']), float(new_info['b'])
def _proj4_str_to_dict(self, proj4_str): """Convert PROJ.4 compatible string definition to dict EPSG codes should be provided as "EPSG:XXXX" where "XXXX" is the EPSG number code. It can also be provided as ``"+init=EPSG:XXXX"`` as long as the underlying PROJ library supports it (deprecated in PROJ 6.0+). Note: Key only parameters will be assigned a value of `True`. """ # TODO: @shahn I would got for one solution, i.e. PyProj > 2.2 # TODO: test if this can be simplified # # convert EPSG codes to equivalent PROJ4 string definition if proj4_str.startswith('EPSG:'): crs = CRS(proj4_str) return crs.to_dict() else: proj4_pairs = (x.split('=', 1) for x in proj4_str.replace('+', '').split(" ")) return self.__convert_proj4_pairs_to_dict(proj4_pairs)
def proj4_str_to_dict(proj4_str): """Convert PROJ.4 compatible string definition to dict EPSG codes should be provided as "EPSG:XXXX" where "XXXX" is the EPSG number code. It can also be provided as ``"+init=EPSG:XXXX"`` as long as the underlying PROJ library supports it (deprecated in PROJ 6.0+). Note: Key only parameters will be assigned a value of `True`. """ # convert EPSG codes to equivalent PROJ4 string definition if proj4_str.startswith('EPSG:') and CRS is not None: crs = CRS(proj4_str) if hasattr(crs, 'to_dict'): # pyproj 2.2+ return crs.to_dict() proj4_str = crs.to_proj4() elif proj4_str.startswith('EPSG:'): # legacy +init= PROJ4 string and no pyproj 2.0+ to help convert proj4_str = "+init={}".format(proj4_str) pairs = (x.split('=', 1) for x in proj4_str.replace('+', '').split(" ")) return convert_proj_floats(pairs)