def test_set_vector_file_wrong_fail(self): """Test set_vector_file with wrong centroids""" shp_file = shapereader.natural_earth(resolution='110m', category='cultural', name='populated_places_simple') centr = Centroids() inten = centr.set_vector_file(shp_file, ['pop_min', 'pop_max']) self.assertEqual(CRS.from_user_input(centr.geometry.crs), CRS.from_epsg(u_coord.NE_EPSG)) self.assertEqual(centr.geometry.size, centr.lat.size) self.assertEqual(CRS.from_user_input(centr.geometry.crs), CRS.from_epsg(u_coord.NE_EPSG)) self.assertAlmostEqual(centr.lon[0], 12.453386544971766) self.assertAlmostEqual(centr.lon[-1], 114.18306345846304) self.assertAlmostEqual(centr.lat[0], 41.903282179960115) self.assertAlmostEqual(centr.lat[-1], 22.30692675357551) self.assertEqual(inten.shape, (2, 243)) # population min self.assertEqual(inten[0, 0], 832) self.assertEqual(inten[0, -1], 4551579) # population max self.assertEqual(inten[1, 0], 832) self.assertEqual(inten[1, -1], 7206000) shp_file = shapereader.natural_earth(resolution='10m', category='cultural', name='populated_places_simple') with self.assertRaises(ValueError): centr.set_vector_file(shp_file, ['pop_min', 'pop_max'])
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_proj_data(projection: Any) -> CRS: """Take projection information and returns a proj CRS. Takes projection information in any format understood by :func:`pyproj.crs.CRS.from_user_input`. There is special handling for the "EPSG:XXXX" case where "XXXX" is an EPSG number code. It can be provided as a string `"EPSG:XXXX"` or as a dictionary (when provided via YAML) as `{'EPSG': XXXX}`. If it is passed as a string ("EPSG:XXXX") then the rules of :func:`~pyresample.utils._proj.proj4_str_to_dict` are followed. If a dictionary and pyproj 2.0+ is installed then the string `"EPSG:XXXX"` is passed to ``proj4_str_to_dict``. If pyproj<2.0 is installed then the string ``+init=EPSG:XXXX`` is passed to ``proj4_str_to_dict`` which provides limited information to area config operations. """ if isinstance(projection, dict) and 'EPSG' in projection: projection = "EPSG:{}".format(projection['EPSG']) return CRS.from_user_input(projection)
def write_hdf5(self, file_data): """Write centroids attributes into hdf5 format. Parameters ---------- file_data : str or h5 If string, path to write data. If h5 object, the datasets will be generated there. """ if isinstance(file_data, str): LOGGER.info('Writting %s', file_data) data = h5py.File(file_data, 'w') else: data = file_data str_dt = h5py.special_dtype(vlen=str) for centr_name, centr_val in self.__dict__.items(): if isinstance(centr_val, np.ndarray): data.create_dataset(centr_name, data=centr_val, compression="gzip") if centr_name == 'meta' and centr_val: centr_meta = data.create_group(centr_name) for key, value in centr_val.items(): if key not in ('crs', 'transform'): if not isinstance(value, str): centr_meta.create_dataset(key, (1, ), data=value, dtype=type(value)) else: hf_str = centr_meta.create_dataset(key, (1, ), dtype=str_dt) hf_str[0] = value elif key == 'transform': centr_meta.create_dataset(key, (6, ), data=[ value.a, value.b, value.c, value.d, value.e, value.f ], dtype=float) hf_str = data.create_dataset('crs', (1, ), dtype=str_dt) hf_str[0] = CRS.from_user_input(self.crs).to_wkt() if isinstance(file_data, str): data.close()
def from_rasterio(crs): """Converts from rasterio CRS to the workflow CRS standard. Parameters ---------- crs : rasterio-crs-object Input rasterio crs. Returns ------- out : crs-type Equivalent workflow CRS. """ try: # from authority seems to get better results with bounds? return CRS.from_authority(*crs.to_authority()) except Exception: return CRS.from_user_input(crs)
def test_read_vector_pass(self): """Test one columns data""" shp_file = shapereader.natural_earth(resolution='110m', category='cultural', name='populated_places_simple') lat, lon, geometry, intensity = read_vector(shp_file, ['pop_min', 'pop_max']) self.assertEqual(PCRS.from_user_input(geometry.crs), PCRS.from_epsg(NE_EPSG)) self.assertEqual(geometry.size, lat.size) self.assertAlmostEqual(lon[0], 12.453386544971766) self.assertAlmostEqual(lon[-1], 114.18306345846304) self.assertAlmostEqual(lat[0], 41.903282179960115) self.assertAlmostEqual(lat[-1], 22.30692675357551) self.assertEqual(intensity.shape, (2, 243)) # population min self.assertEqual(intensity[0, 0], 832) self.assertEqual(intensity[0, -1], 4551579) # population max self.assertEqual(intensity[1, 0], 832) self.assertEqual(intensity[1, -1], 7206000)
def subset_shape( ds: Union[xarray.DataArray, xarray.Dataset], shape: Union[str, Path, gpd.GeoDataFrame], vectorize: bool = True, raster_crs: Optional[Union[str, int]] = None, shape_crs: Optional[Union[str, int]] = None, buffer: Optional[Union[int, float]] = None, start_date: Optional[str] = None, end_date: Optional[str] = None, ) -> Union[xarray.DataArray, xarray.Dataset]: """Subset a DataArray or Dataset spatially (and temporally) using a vector shape and date selection. Return a subset of a DataArray or Dataset for grid points falling within the area of a Polygon and/or MultiPolygon shape, or grid points along the path of a LineString and/or MultiLineString. Parameters ---------- ds : Union[xarray.DataArray, xarray.Dataset] Input values. shape : Union[str, Path, gpd.GeoDataFrame] Path to shape file, or directly a geodataframe. Supports formats compatible with geopandas. vectorize: bool Whether to use the spatialjoin or vectorize backend. raster_crs : Optional[Union[str, int]] EPSG number or PROJ4 string. shape_crs : Optional[Union[str, int]] EPSG number or PROJ4 string. buffer : Optional[Union[int, float]] Buffer the shape in order to select a larger region stemming from it. Units are based on the shape degrees/metres. start_date : Optional[str] Start date of the subset. Date string format -- can be year ("%Y"), year-month ("%Y-%m") or year-month-day("%Y-%m-%d"). Defaults to first day of input data-array. end_date : Optional[str] End date of the subset. Date string format -- can be year ("%Y"), year-month ("%Y-%m") or year-month-day("%Y-%m-%d"). Defaults to last day of input data-array. Returns ------- Union[xarray.DataArray, xarray.Dataset] A subset of `ds` Examples -------- >>> import xarray as xr # doctest: +SKIP >>> from xclim.subset import subset_shape # doctest: +SKIP >>> pr = xr.open_dataset(path_to_pr_file).pr # doctest: +SKIP ... # Subset data array by shape >>> prSub = subset_shape(pr, shape=path_to_shape_file) # doctest: +SKIP ... # Subset data array by shape and single year >>> prSub = subset_shape(pr, shape=path_to_shape_file, start_date='1990-01-01', end_date='1990-12-31') # doctest: +SKIP ... # Subset multiple variables in a single dataset >>> ds = xr.open_mfdataset([path_to_tasmin_file, path_to_tasmax_file]) # doctest: +SKIP >>> dsSub = subset_shape(ds, shape=path_to_shape_file) # doctest: +SKIP """ wgs84 = CRS(4326) # PROJ4 definition for WGS84 with longitudes ranged between -180/+180. wgs84_wrapped = CRS.from_string( "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs lon_wrap=180") if isinstance(ds, xarray.DataArray): ds_copy = ds._to_temp_dataset() else: ds_copy = ds.copy() if isinstance(shape, gpd.GeoDataFrame): poly = shape.copy() else: poly = gpd.GeoDataFrame.from_file(shape) if buffer is not None: poly.geometry = poly.buffer(buffer) # Get the shape's bounding box. minx, miny, maxx, maxy = poly.total_bounds lon_bnds = (minx, maxx) lat_bnds = (miny, maxy) # If polygon doesn't cross prime meridian, subset bbox first to reduce processing time # Only case not implemented is when lon_bnds cross the 0 deg meridian but dataset grid has all positive lons try: ds_copy = subset_bbox(ds_copy, lon_bnds=lon_bnds, lat_bnds=lat_bnds) except NotImplementedError: pass if ds_copy.lon.size == 0 or ds_copy.lat.size == 0: raise ValueError( "No grid cell centroids found within provided polygon bounding box. " 'Try using the "buffer" option to create an expanded area.') if start_date or end_date: ds_copy = subset_time(ds_copy, start_date=start_date, end_date=end_date) # Determine whether CRS types are the same between shape and raster if shape_crs is not None: try: shape_crs = CRS.from_user_input(shape_crs) except ValueError: raise else: shape_crs = CRS(poly.crs) wrap_lons = False if raster_crs is not None: try: raster_crs = CRS.from_user_input(raster_crs) except ValueError: raise else: if np.min(lat_bnds) < -90 or np.max(lat_bnds) > 90: raise ValueError( "Latitudes exceed domain of WGS84 coordinate system.") if np.min(lon_bnds) < -180 or np.max(lon_bnds) > 180: raise ValueError( "Longitudes exceed domain of WGS84 coordinate system.") try: # Extract CF-compliant CRS_WKT from crs variable. raster_crs = CRS.from_cf(ds_copy.crs.attrs) except AttributeError: if np.min(ds_copy.lon) >= 0 and np.max(ds_copy.lon) <= 360: wrap_lons = True raster_crs = wgs84_wrapped else: raster_crs = wgs84 _check_crs_compatibility(shape_crs=shape_crs, raster_crs=raster_crs) # Create mask using the vectorize or spatial join methods. if vectorize: mask_2d = create_mask_vectorize(x_dim=ds_copy.lon, y_dim=ds_copy.lat, poly=poly, wrap_lons=wrap_lons) else: mask_2d = create_mask(x_dim=ds_copy.lon, y_dim=ds_copy.lat, poly=poly, wrap_lons=wrap_lons) if np.all(mask_2d.isnull()): raise ValueError( f"No grid cell centroids found within provided polygon bounds ({poly.bounds}). " 'Try using the "buffer" option to create an expanded areas or verify polygon.' ) # loop through variables for v in ds_copy.data_vars: if set.issubset(set(mask_2d.dims), set(ds_copy[v].dims)): ds_copy[v] = ds_copy[v].where(mask_2d.notnull()) # Remove coordinates where all values are outside of region mask for dim in mask_2d.dims: mask_2d = mask_2d.dropna(dim, how="all") ds_copy = ds_copy.sel({dim: mask_2d[dim] for dim in mask_2d.dims}) # Add a CRS definition using CF conventions and as a global attribute in CRS_WKT for reference purposes ds_copy.attrs["crs"] = raster_crs.to_string() ds_copy["crs"] = 1 ds_copy["crs"].attrs.update(raster_crs.to_cf()) for v in ds_copy.variables: if {"lat", "lon"}.issubset(set(ds_copy[v].dims)): ds_copy[v].attrs["grid_mapping"] = "crs" if isinstance(ds, xarray.DataArray): return ds._from_temp_dataset(ds_copy) return ds_copy
def __init__(self, projparams=None, preserve_units=True, **kwargs): """ initialize a Proj class instance. See the PROJ documentation (https://proj.org) for more information about projection parameters. Parameters ---------- projparams: int, str, dict, pyproj.CRS A PROJ or WKT string, PROJ dict, EPSG integer, or a pyproj.CRS instnace. preserve_units: bool If false, will ensure +units=m. **kwargs: PROJ projection parameters. Example usage: >>> from pyproj import Proj >>> p = Proj(proj='utm',zone=10,ellps='WGS84', preserve_units=False) >>> x,y = p(-120.108, 34.36116666) >>> 'x=%9.3f y=%11.3f' % (x,y) 'x=765975.641 y=3805993.134' >>> 'lon=%8.3f lat=%5.3f' % p(x,y,inverse=True) 'lon=-120.108 lat=34.361' >>> # do 3 cities at a time in a tuple (Fresno, LA, SF) >>> lons = (-119.72,-118.40,-122.38) >>> lats = (36.77, 33.93, 37.62 ) >>> x,y = p(lons, lats) >>> 'x: %9.3f %9.3f %9.3f' % x 'x: 792763.863 925321.537 554714.301' >>> 'y: %9.3f %9.3f %9.3f' % y 'y: 4074377.617 3763936.941 4163835.303' >>> lons, lats = p(x, y, inverse=True) # inverse transform >>> 'lons: %8.3f %8.3f %8.3f' % lons 'lons: -119.720 -118.400 -122.380' >>> 'lats: %8.3f %8.3f %8.3f' % lats 'lats: 36.770 33.930 37.620' >>> p2 = Proj('+proj=utm +zone=10 +ellps=WGS84', preserve_units=False) >>> x,y = p2(-120.108, 34.36116666) >>> 'x=%9.3f y=%11.3f' % (x,y) 'x=765975.641 y=3805993.134' >>> p = Proj(init="epsg:32667", preserve_units=False) >>> 'x=%12.3f y=%12.3f (meters)' % p(-114.057222, 51.045) 'x=-1783506.250 y= 6193827.033 (meters)' >>> p = Proj("+init=epsg:32667") >>> 'x=%12.3f y=%12.3f (feet)' % p(-114.057222, 51.045) 'x=-5851386.754 y=20320914.191 (feet)' >>> # test data with radian inputs >>> p1 = Proj(init="epsg:4214") >>> x1, y1 = p1(116.366, 39.867) >>> '{:.3f} {:.3f}'.format(x1, y1) '2.031 0.696' >>> x2, y2 = p1(x1, y1, inverse=True) >>> '{:.3f} {:.3f}'.format(x2, y2) '116.366 39.867' """ self.crs = CRS.from_user_input( projparams if projparams is not None else kwargs) # make sure units are meters if preserve_units is False. if not preserve_units and "foot" in self.crs.axis_info[0].unit_name: projstring = self.crs.to_proj4(4) projstring = re.sub(r"\s\+units=[\w-]+", "", projstring) projstring += " +units=m" self.crs = CRS(projstring) projstring = self.crs.to_proj4() or self.crs.srs projstring = re.sub(r"\s\+?type=crs", "", projstring) super(Proj, self).__init__(cstrencode(projstring.strip()))
import numpy as np import pandas as pd from pyproj.crs import CRS import rasterio from rasterio.warp import Resampling from scipy import sparse from shapely.geometry.point import Point from climada.util.constants import (DEF_CRS, ONE_LAT_KM, NATEARTH_CENTROIDS) import climada.util.coordinates as u_coord import climada.util.hdf5_handler as u_hdf5 import climada.util.plot as u_plot __all__ = ['Centroids'] PROJ_CEA = CRS.from_user_input({'proj': 'cea'}) DEF_VAR_MAT = { 'field_names': ['centroids', 'hazard'], 'var_name': { 'lat': 'lat', 'lon': 'lon', 'dist_coast': 'distance2coast_km', 'admin0_name': 'admin0_name', 'admin0_iso3': 'admin0_ISO3', 'comment': 'comment', 'region_id': 'NatId' } } """MATLAB variable names"""
def __init__( self, projparams: Any = None, preserve_units: bool = True, network=None, **kwargs, ) -> None: """ A Proj class instance is initialized with proj map projection control parameter key/value pairs. The key/value pairs can either be passed in a dictionary, or as keyword arguments, or as a PROJ string (compatible with the proj command). See https://proj.org/operations/projections/index.html for examples of key/value pairs defining different map projections. .. versionadded:: 3.0.0 network Parameters ---------- projparams: int, str, dict, pyproj.CRS A PROJ or WKT string, PROJ dict, EPSG integer, or a pyproj.CRS instance. preserve_units: bool If false, will ensure +units=m. network: bool, optional Default is None, which uses the system defaults for networking. If True, it will force the use of network for grids regardless of any other network setting. If False, it will force disable use of network for grids regardless of any other network setting. **kwargs: PROJ projection parameters. Example usage: >>> from pyproj import Proj >>> p = Proj(proj='utm',zone=10,ellps='WGS84', preserve_units=False) >>> x,y = p(-120.108, 34.36116666) >>> 'x=%9.3f y=%11.3f' % (x,y) 'x=765975.641 y=3805993.134' >>> 'lon=%8.3f lat=%5.3f' % p(x,y,inverse=True) 'lon=-120.108 lat=34.361' >>> # do 3 cities at a time in a tuple (Fresno, LA, SF) >>> lons = (-119.72,-118.40,-122.38) >>> lats = (36.77, 33.93, 37.62 ) >>> x,y = p(lons, lats) >>> 'x: %9.3f %9.3f %9.3f' % x 'x: 792763.863 925321.537 554714.301' >>> 'y: %9.3f %9.3f %9.3f' % y 'y: 4074377.617 3763936.941 4163835.303' >>> lons, lats = p(x, y, inverse=True) # inverse transform >>> 'lons: %8.3f %8.3f %8.3f' % lons 'lons: -119.720 -118.400 -122.380' >>> 'lats: %8.3f %8.3f %8.3f' % lats 'lats: 36.770 33.930 37.620' >>> p2 = Proj('+proj=utm +zone=10 +ellps=WGS84', preserve_units=False) >>> x,y = p2(-120.108, 34.36116666) >>> 'x=%9.3f y=%11.3f' % (x,y) 'x=765975.641 y=3805993.134' >>> p = Proj("epsg:32667", preserve_units=False) >>> 'x=%12.3f y=%12.3f (meters)' % p(-114.057222, 51.045) 'x=-1783506.250 y= 6193827.033 (meters)' >>> p = Proj("epsg:32667") >>> 'x=%12.3f y=%12.3f (feet)' % p(-114.057222, 51.045) 'x=-5851386.754 y=20320914.191 (feet)' >>> # test data with radian inputs >>> p1 = Proj("epsg:4214") >>> x1, y1 = p1(116.366, 39.867) >>> f'{x1:.3f} {y1:.3f}' '116.366 39.867' >>> x2, y2 = p1(x1, y1, inverse=True) >>> f'{x2:.3f} {y2:.3f}' '116.366 39.867' """ self.crs = CRS.from_user_input(projparams, **kwargs) # make sure units are meters if preserve_units is False. if not preserve_units and "foot" in self.crs.axis_info[0].unit_name: # ignore export to PROJ string deprecation warning with warnings.catch_warnings(): warnings.filterwarnings( "ignore", "You will likely lose important projection information", UserWarning, ) projstring = self.crs.to_proj4(4) projstring = re.sub(r"\s\+units=[\w-]+", "", projstring) projstring += " +units=m" self.crs = CRS(projstring) # ignore export to PROJ string deprecation warning with warnings.catch_warnings(): warnings.filterwarnings( "ignore", "You will likely lose important projection information", UserWarning, ) projstring = self.crs.to_proj4() or self.crs.srs self.srs = re.sub(r"\s\+?type=crs", "", projstring).strip() super().__init__( _Transformer.from_pipeline(cstrencode(self.srs), network=network) )
def _handler(self, request, response): # Process inputs # --------------- shape_url = request.inputs["shape"][0].file destination_crs = request.inputs["projected_crs"][0].data touches = request.inputs["select_all_touching"][0].data # Checks for valid CRS and that CRS is projected # ----------------------------------------------- projection = CRS.from_user_input(destination_crs) if not projection.is_projected: msg = f"Destination CRS {projection.to_epsg()} is not projected. Terrain analysis values will not be valid." LOGGER.error(ValueError(msg)) raise ValueError(msg) # Collect and process the shape # ----------------------------- vectors = [".gml", ".shp", ".gpkg", ".geojson", ".json"] vector_file = single_file_check( archive_sniffer(shape_url, working_dir=self.workdir, extensions=vectors)) vec_crs = crs_sniffer(vector_file) # Check that boundaries within 60N and 60S boundary_check(vector_file) if "raster" in request.inputs: raster_url = request.inputs["raster"][0].file rasters = [".tiff", ".tif"] raster_file = single_file_check( archive_sniffer(raster_url, working_dir=self.workdir, extensions=rasters)) else: # Assuming that the shape coordinate are in WGS84 raster_file = gather_dem_tile(vector_file, self.workdir) ras_crs = crs_sniffer(raster_file) # Reproject raster # ---------------- if ras_crs != projection.to_epsg(): msg = f"CRS for {raster_file} is not {projection}. Reprojecting raster..." LOGGER.warning(msg) warped_fn = tempfile.NamedTemporaryFile(prefix="warped_", suffix=".tiff", delete=False, dir=self.workdir).name generic_raster_warp(raster_file, warped_fn, projection) else: warped_fn = raster_file # Perform the terrain analysis # ---------------------------- rpj = tempfile.NamedTemporaryFile(prefix="reproj_", suffix=".json", delete=False, dir=self.workdir).name generic_vector_reproject(vector_file, rpj, source_crs=vec_crs, target_crs=projection.to_epsg()) with open(rpj) as src: geo = json.load(src) features = [sgeo.shape(feat["geometry"]) for feat in geo["features"]] union = ops.unary_union(features) clipped_fn = tempfile.NamedTemporaryFile(prefix="clipped_", suffix=".tiff", delete=False, dir=self.workdir).name # Ensure that values for regions outside of clip are kept generic_raster_clip( raster=warped_fn, output=clipped_fn, geometry=union, touches=touches, fill_with_nodata=True, padded=True, ) # Compute DEM properties for each feature. properties = [] for i in range(len(features)): properties.append( dem_prop(clipped_fn, geom=features[i], directory=self.workdir)) properties.append(dem_prop(clipped_fn, directory=self.workdir)) response.outputs["properties"].data = json.dumps(properties) response.outputs["dem"].file = clipped_fn return response
def __init__(self, projparams=None, preserve_units=True, **kwargs): """ initialize a Proj class instance. See the proj documentation (https://github.com/OSGeo/proj.4/wiki) for more information about projection parameters. Parameters ---------- projparams: int, str, dict, pyproj.CRS A proj.4 or WKT string, proj.4 dict, EPSG integer, or a pyproj.CRS instnace. preserve_units: bool If false, will ensure +units=m. **kwargs: proj.4 projection parameters. Example usage: >>> from pyproj import Proj >>> p = Proj(proj='utm',zone=10,ellps='WGS84', preserve_units=False) # use kwargs >>> x,y = p(-120.108, 34.36116666) >>> 'x=%9.3f y=%11.3f' % (x,y) 'x=765975.641 y=3805993.134' >>> 'lon=%8.3f lat=%5.3f' % p(x,y,inverse=True) 'lon=-120.108 lat=34.361' >>> # do 3 cities at a time in a tuple (Fresno, LA, SF) >>> lons = (-119.72,-118.40,-122.38) >>> lats = (36.77, 33.93, 37.62 ) >>> x,y = p(lons, lats) >>> 'x: %9.3f %9.3f %9.3f' % x 'x: 792763.863 925321.537 554714.301' >>> 'y: %9.3f %9.3f %9.3f' % y 'y: 4074377.617 3763936.941 4163835.303' >>> lons, lats = p(x, y, inverse=True) # inverse transform >>> 'lons: %8.3f %8.3f %8.3f' % lons 'lons: -119.720 -118.400 -122.380' >>> 'lats: %8.3f %8.3f %8.3f' % lats 'lats: 36.770 33.930 37.620' >>> p2 = Proj('+proj=utm +zone=10 +ellps=WGS84', preserve_units=False) # use proj4 string >>> x,y = p2(-120.108, 34.36116666) >>> 'x=%9.3f y=%11.3f' % (x,y) 'x=765975.641 y=3805993.134' >>> p = Proj(init="epsg:32667", preserve_units=False) >>> 'x=%12.3f y=%12.3f (meters)' % p(-114.057222, 51.045) 'x=-1783506.250 y= 6193827.033 (meters)' >>> p = Proj("+init=epsg:32667") >>> 'x=%12.3f y=%12.3f (feet)' % p(-114.057222, 51.045) 'x=-5851386.754 y=20320914.191 (feet)' >>> # test data with radian inputs >>> p1 = Proj(init="epsg:4214") >>> x1, y1 = p1(116.366, 39.867) >>> '{:.3f} {:.3f}'.format(x1, y1) '2.031 0.696' >>> x2, y2 = p1(x1, y1, inverse=True) >>> '{:.3f} {:.3f}'.format(x2, y2) '116.366 39.867' """ self.crs = CRS.from_user_input(projparams if projparams is not None else kwargs) # make sure units are meters if preserve_units is False. if not preserve_units and "foot" in self.crs.axis_info[0].unit_name: projstring = self.crs.to_proj4(4) projstring = re.sub(r"\s\+units=[\w-]+", "", projstring) projstring += " +units=m" self.crs = CRS(projstring) super(Proj, self).__init__( cstrencode( (self.crs.to_proj4() or self.crs.srs).replace("+type=crs", "").strip() ) )