def test_pyproj_trafo(self): x = np.random.randn(int(1e6)) * 60 y = np.random.randn(int(1e6)) * 60 for i in np.arange(3): xx, yy = pyproj.transform(wgs84, wgs84, x, y) assert_allclose(xx, x) assert_allclose(yy, y) for i in np.arange(3): xx, yy = gis.transform_proj(wgs84, wgs84, x, y) assert_allclose(xx, x) assert_allclose(yy, y) for i in np.arange(3): xx, yy = gis.transform_proj(wgs84, wgs84, x, y, nocopy=True) assert_allclose(xx, x) assert_allclose(yy, y) xx, yy = pyproj.transform(gis.check_crs('+init=epsg:26915'), gis.check_crs('+init=epsg:26915'), x, y) assert_allclose(xx, x, atol=1e-3) assert_allclose(yy, y, atol=1e-3) xx, yy = gis.transform_proj(gis.check_crs('+init=epsg:26915'), gis.check_crs('+init=epsg:26915'), x, y) assert_allclose(xx, x) assert_allclose(yy, y)
def test_pyproj_trafo(self): x = np.random.randn(int(1e6)) * 60 y = np.random.randn(int(1e6)) * 60 t1 = time.time() for i in np.arange(3): xx, yy = pyproj.transform(wgs84, wgs84, x, y) t1 = time.time() - t1 assert_allclose(xx, x) assert_allclose(yy, y) t2 = time.time() for i in np.arange(3): xx, yy = gis.transform_proj(wgs84, wgs84, x, y) t2 = time.time() - t2 assert_allclose(xx, x) assert_allclose(yy, y) t3 = time.time() for i in np.arange(3): xx, yy = gis.transform_proj(wgs84, wgs84, x, y, nocopy=True) t3 = time.time() - t3 assert_allclose(xx, x) assert_allclose(yy, y) self.assertTrue(t1 > t2) self.assertTrue(t2 > t3) t1 = time.time() xx, yy = pyproj.transform(pyproj.Proj(init='epsg:26915'), pyproj.Proj(init='epsg:26915'), x, y) t1 = time.time() - t1 assert_allclose(xx, x, atol=1e-3) assert_allclose(yy, y, atol=1e-3) t2 = time.time() xx, yy = gis.transform_proj(pyproj.Proj(init='epsg:26915'), pyproj.Proj(init='epsg:26915'), x, y) t2 = time.time() - t2 assert_allclose(xx, x) assert_allclose(yy, y) self.assertTrue(t1 > t2)
def __init__(self, x, y, crs=wgs84, size_x=640, size_y=640, scale=1, maptype='satellite', use_cache=True, **kwargs): """Initialize Parameters ---------- x : array x coordinates of the points to include on the map y : array y coordinates of the points to include on the map crs : proj or Grid coordinate reference system of x, y size_x : int image size size_y : int image size scale : int image scaling factor maptype : str, default: 'satellite' 'roadmap', 'satellite', 'hybrid', 'terrain' use_cache : bool, default: True store the downloaded image in the cache to avoid future downloads kwargs : ** any keyword accepted by motionless.CenterMap (e.g. `key` for the API) """ if 'zoom' in kwargs or 'center_ll' in kwargs: raise ValueError('incompatible kwargs.') # Transform to lonlat crs = gis.check_crs(crs) if isinstance(crs, pyproj.Proj): lon, lat = gis.transform_proj(crs, wgs84, x, y) elif isinstance(crs, Grid): lon, lat = crs.ij_to_crs(x, y, crs=wgs84) else: raise NotImplementedError() # surely not the smartest way to do but should be enough for now mc = (np.mean(lon), np.mean(lat)) zoom = 20 while zoom >= 0: grid = gis.googlestatic_mercator_grid(center_ll=mc, nx=size_x, ny=size_y, zoom=zoom, scale=scale) dx, dy = grid.transform(lon, lat, maskout=True) if np.any(dx.mask): zoom -= 1 else: break GoogleCenterMap.__init__(self, center_ll=mc, size_x=size_x, size_y=size_y, zoom=zoom, scale=scale, maptype=maptype, use_cache=use_cache, **kwargs)
def __init__(self, x, y, crs=wgs84, size_x=640, size_y=640, maptype='satellite', use_cache=True, **kwargs): """Initialize Parameters ---------- x : array x coordinates of the points to include on the map y : array y coordinates of the points to include on the map crs : proj or Grid coordinate reference system of x, y size_x : int image size size_y : int image size maptype : str, default: 'satellite' 'roadmap', 'satellite', 'hybrid', 'terrain' use_cache : bool, default: True store the downloaded image in the cache to avoid future downloads kwargs : ** any keyword accepted by motionless.CenterMap (e.g. `key` for the API) """ if 'zoom' in kwargs or 'center_ll' in kwargs: raise ValueError('incompatible kwargs.') # Transform to lonlat crs = gis.check_crs(crs) if isinstance(crs, pyproj.Proj): lon, lat = gis.transform_proj(crs, wgs84, x, y) elif isinstance(crs, Grid): lon, lat = crs.ij_to_crs(x, y, crs=wgs84) else: raise NotImplementedError() # surely not the smartest way to do but should be enough for now mc = (np.mean(lon), np.mean(lat)) zoom = 20 while zoom >= 0: grid = gis.googlestatic_mercator_grid(center_ll=mc, nx=size_x, ny=size_y, zoom=zoom) dx, dy = grid.transform(lon, lat, maskout=True) if np.any(dx.mask): zoom -= 1 else: break GoogleCenterMap.__init__(self, center_ll=mc, size_x=size_x, size_y=size_y, zoom=zoom, maptype=maptype, use_cache=use_cache, **kwargs)
def test_projplot(self): # this caused many problems on fabien's laptop. # this is just to be sure that on your system, everything is fine import pyproj import matplotlib.pyplot as plt from salem.gis import transform_proj, check_crs wgs84 = pyproj.Proj(proj='latlong', datum='WGS84') fig = plt.figure() plt.close() srs = '+units=m +proj=lcc +lat_1=29.0 +lat_2=29.0 +lat_0=29.0 +lon_0=89.8' proj_out = check_crs('+init=EPSG:4326') proj_in = pyproj.Proj(srs, preserve_units=True) lon, lat = transform_proj(proj_in, proj_out, -2235000, -2235000) np.testing.assert_allclose(lon, 70.75731, atol=1e-5)
def __init__(self, x, y, crs=wgs84, size_x=640, size_y=640, scale=1, maptype='satellite', use_cache=True, **kwargs): """Initialize Parameters ---------- x : array x coordinates of the points to include on the map y : array y coordinates of the points to include on the map crs : proj or Grid coordinate reference system of x, y size_x : int image size size_y : int image size scale : int image scaling factor. 1, 2. 2 is higher resolution but takes longer to download maptype : str, default: 'satellite' 'roadmap', 'satellite', 'hybrid', 'terrain' use_cache : bool, default: True store the downloaded image in the cache to avoid future downloads kwargs : ** any keyword accepted by motionless.CenterMap (e.g. `key` for the API) Notes ----- To obtain the exact domain specified in `x` and `y` you may have to play with the `size_x` and `size_y` kwargs. """ global API_KEY if 'zoom' in kwargs or 'center_ll' in kwargs: raise ValueError('incompatible kwargs.') # Transform to lonlat crs = gis.check_crs(crs) if isinstance(crs, pyproj.Proj): lon, lat = gis.transform_proj(crs, wgs84, x, y) elif isinstance(crs, Grid): lon, lat = crs.ij_to_crs(x, y, crs=wgs84) else: raise NotImplementedError() # surely not the smartest way to do but should be enough for now mc = (np.mean(lon), np.mean(lat)) zoom = 20 while zoom >= 0: grid = gis.googlestatic_mercator_grid(center_ll=mc, nx=size_x, ny=size_y, zoom=zoom, scale=scale) dx, dy = grid.transform(lon, lat, maskout=True) if np.any(dx.mask): zoom -= 1 else: break if 'key' not in kwargs: if API_KEY is None: with open(utils.get_demo_file('.api_key'), 'r') as f: API_KEY = f.read().replace('\n', '') kwargs['key'] = API_KEY GoogleCenterMap.__init__(self, center_ll=mc, size_x=size_x, size_y=size_y, zoom=zoom, scale=scale, maptype=maptype, use_cache=use_cache, **kwargs)
def _wrf_grid_from_dataset(ds): """Get the WRF projection out of the file.""" pargs = dict() if hasattr(ds, 'PROJ_ENVI_STRING'): # HAR and other TU Berlin files dx = ds.GRID_DX dy = ds.GRID_DY pargs['lat_1'] = ds.PROJ_STANDARD_PAR1 pargs['lat_2'] = ds.PROJ_STANDARD_PAR2 pargs['lat_0'] = ds.PROJ_CENTRAL_LAT pargs['lon_0'] = ds.PROJ_CENTRAL_LON pargs['center_lon'] = ds.PROJ_CENTRAL_LON if ds.PROJ_NAME in [ 'Lambert Conformal Conic', 'WRF Lambert Conformal' ]: proj_id = 1 else: proj_id = 99 # pragma: no cover else: # Normal WRF file cen_lon = ds.CEN_LON cen_lat = ds.CEN_LAT dx = ds.DX dy = ds.DY pargs['lat_1'] = ds.TRUELAT1 pargs['lat_2'] = ds.TRUELAT2 pargs['lat_0'] = ds.MOAD_CEN_LAT pargs['lon_0'] = ds.STAND_LON pargs['center_lon'] = ds.CEN_LON proj_id = ds.MAP_PROJ if proj_id == 1: # Lambert p4 = '+proj=lcc +lat_1={lat_1} +lat_2={lat_2} ' \ '+lat_0={lat_0} +lon_0={lon_0} ' \ '+x_0=0 +y_0=0 +a=6370000 +b=6370000' p4 = p4.format(**pargs) elif proj_id == 2: # Polar stereo p4 = '+proj=stere +lat_ts={lat_1} +lon_0={lon_0} +lat_0=90.0' \ '+x_0=0 +y_0=0 +a=6370000 +b=6370000' p4 = p4.format(**pargs) elif proj_id == 3: # Mercator p4 = '+proj=merc +lat_ts={lat_1} ' \ '+lon_0={center_lon} ' \ '+x_0=0 +y_0=0 +a=6370000 +b=6370000' p4 = p4.format(**pargs) else: raise NotImplementedError('WRF proj not implemented yet: ' '{}'.format(proj_id)) proj = gis.check_crs(p4) if proj is None: raise RuntimeError('WRF proj not understood: {}'.format(p4)) # Here we have to accept xarray and netCDF4 datasets try: nx = len(ds.dimensions['west_east']) ny = len(ds.dimensions['south_north']) except AttributeError: # maybe an xarray dataset nx = ds.dims['west_east'] ny = ds.dims['south_north'] if hasattr(ds, 'PROJ_ENVI_STRING'): # HAR x0 = ds['west_east'][0] y0 = ds['south_north'][0] else: # Normal WRF file e, n = gis.transform_proj(wgs84, proj, cen_lon, cen_lat) x0 = -(nx - 1) / 2. * dx + e # DL corner y0 = -(ny - 1) / 2. * dy + n # DL corner grid = gis.Grid(nxny=(nx, ny), x0y0=(x0, y0), dxdy=(dx, dy), proj=proj) if tmp_check_wrf: # Temporary asserts if 'XLONG' in ds.variables: # Normal WRF reflon = ds.variables['XLONG'] reflat = ds.variables['XLAT'] elif 'XLONG_M' in ds.variables: # geo_em reflon = ds.variables['XLONG_M'] reflat = ds.variables['XLAT_M'] elif 'lon' in ds.variables: # HAR reflon = ds.variables['lon'] reflat = ds.variables['lat'] else: raise RuntimeError("couldn't test for correct WRF lon-lat") if len(reflon.shape) == 3: reflon = reflon[0, :, :] reflat = reflat[0, :, :] mylon, mylat = grid.ll_coordinates atol = 5e-3 if proj_id == 2 else 1e-3 check = np.isclose(reflon, mylon, atol=atol) if not np.alltrue(check): n_pix = np.sum(~check) maxe = np.max(np.abs(reflon - mylon)) if maxe < (360 - atol): warnings.warn('For {} grid points, the expected accuracy ({}) ' 'of our lons did not match those of the WRF ' 'file. Max error: {}'.format(n_pix, atol, maxe)) check = np.isclose(reflat, mylat, atol=atol) if not np.alltrue(check): n_pix = np.sum(~check) maxe = np.max(np.abs(reflat - mylat)) warnings.warn('For {} grid points, the expected accuracy ({}) ' 'of our lats did not match those of the WRF file. ' 'Max error: {}'.format(n_pix, atol, maxe)) return grid
def _wrf_grid_from_dataset(ds): """Get the WRF projection out of the file.""" pargs = dict() if hasattr(ds, 'PROJ_ENVI_STRING'): # HAR and other TU Berlin files dx = ds.GRID_DX dy = ds.GRID_DY pargs['lat_1'] = ds.PROJ_STANDARD_PAR1 pargs['lat_2'] = ds.PROJ_STANDARD_PAR2 pargs['lat_0'] = ds.PROJ_CENTRAL_LAT pargs['lon_0'] = ds.PROJ_CENTRAL_LON pargs['center_lon'] = ds.PROJ_CENTRAL_LON if ds.PROJ_NAME == 'Lambert Conformal Conic': proj_id = 1 else: proj_id = 99 # pragma: no cover else: # Normal WRF file cen_lon = ds.CEN_LON cen_lat = ds.CEN_LAT dx = ds.DX dy = ds.DY pargs['lat_1'] = ds.TRUELAT1 pargs['lat_2'] = ds.TRUELAT2 pargs['lat_0'] = ds.MOAD_CEN_LAT pargs['lon_0'] = ds.STAND_LON pargs['center_lon'] = ds.CEN_LON proj_id = ds.MAP_PROJ if proj_id == 1: # Lambert p4 = '+proj=lcc +lat_1={lat_1} +lat_2={lat_2} ' \ '+lat_0={lat_0} +lon_0={lon_0} ' \ '+x_0=0 +y_0=0 +a=6370000 +b=6370000' p4 = p4.format(**pargs) elif proj_id == 3: # Mercator p4 = '+proj=merc +lat_ts={lat_1} ' \ '+lon_0={center_lon} ' \ '+x_0=0 +y_0=0 +a=6370000 +b=6370000' p4 = p4.format(**pargs) else: raise NotImplementedError('WRF proj not implemented yet: ' '{}'.format(proj_id)) proj = gis.check_crs(p4) if proj is None: raise RuntimeError('WRF proj not understood: {}'.format(p4)) # Here we have to accept xarray and netCDF4 datasets try: nx = len(ds.dimensions['west_east']) ny = len(ds.dimensions['south_north']) except AttributeError: # maybe an xarray dataset nx = ds.dims['west_east'] ny = ds.dims['south_north'] if hasattr(ds, 'PROJ_ENVI_STRING'): # HAR x0 = ds.GRID_X00 y0 = ds.GRID_Y00 else: # Normal WRF file e, n = gis.transform_proj(wgs84, proj, cen_lon, cen_lat) x0 = -(nx-1) / 2. * dx + e # DL corner y0 = -(ny-1) / 2. * dy + n # DL corner grid = gis.Grid(nxny=(nx, ny), ll_corner=(x0, y0), dxdy=(dx, dy), proj=proj) if tmp_check_wrf: # Temporary asserts if 'XLONG' in ds.variables: # Normal WRF mylon, mylat = grid.ll_coordinates reflon = ds.variables['XLONG'] reflat = ds.variables['XLAT'] if len(reflon.shape) == 3: reflon = reflon[0, :, :] reflat = reflat[0, :, :] assert np.allclose(reflon, mylon, atol=1e-4) assert np.allclose(reflat, mylat, atol=1e-4) if 'lon' in ds.variables: # HAR mylon, mylat = grid.ll_coordinates reflon = ds.variables['lon'] reflat = ds.variables['lat'] if len(reflon.shape) == 3: reflon = reflon[0, :, :] reflat = reflat[0, :, :] assert np.allclose(reflon, mylon, atol=1e-4) assert np.allclose(reflat, mylat, atol=1e-4) return grid
def geogrid_simulator(fpath, do_maps=True, map_kwargs=None): """Emulates geogrid.exe, which is useful when defining new WRF domains. Parameters ---------- fpath: str path to a namelist.wps file do_maps: bool if you want the simulator to return you maps of the grids as well map_kwargs: dict kwargs to pass to salem.Map() Returns ------- (grids, maps) with: - grids: a list of Grids corresponding to the domains defined in the namelist - maps: a list of maps corresponding to the grids (if do_maps==True) """ with open(fpath) as f: lines = f.readlines() pargs = dict() for l in lines: s = l.split('=') if len(s) < 2: continue s0 = s[0].strip().upper() s1 = list(filter(None, s[1].strip().replace('\n', '').split(','))) if s0 == 'PARENT_ID': parent_id = [int(s) for s in s1] if s0 == 'PARENT_GRID_RATIO': parent_ratio = [int(s) for s in s1] if s0 == 'I_PARENT_START': i_parent_start = [int(s) for s in s1] if s0 == 'J_PARENT_START': j_parent_start = [int(s) for s in s1] if s0 == 'E_WE': e_we = [int(s) for s in s1] if s0 == 'E_SN': e_sn = [int(s) for s in s1] if s0 == 'DX': dx = float(s1[0]) if s0 == 'DY': dy = float(s1[0]) if s0 == 'MAP_PROJ': map_proj = s1[0].replace("'", '').strip().upper() if s0 == 'REF_LAT': pargs['lat_0'] = float(s1[0]) if s0 == 'REF_LON': pargs['ref_lon'] = float(s1[0]) if s0 == 'TRUELAT1': pargs['lat_1'] = float(s1[0]) if s0 == 'TRUELAT2': pargs['lat_2'] = float(s1[0]) if s0 == 'STAND_LON': pargs['lon_0'] = float(s1[0]) # Sometimes files are not complete pargs.setdefault('lon_0', pargs['ref_lon']) # define projection if map_proj == 'LAMBERT': pwrf = '+proj=lcc +lat_1={lat_1} +lat_2={lat_2} ' \ '+lat_0={lat_0} +lon_0={lon_0} ' \ '+x_0=0 +y_0=0 +a=6370000 +b=6370000' pwrf = pwrf.format(**pargs) elif map_proj == 'MERCATOR': pwrf = '+proj=merc +lat_ts={lat_1} +lon_0={lon_0} ' \ '+x_0=0 +y_0=0 +a=6370000 +b=6370000' pwrf = pwrf.format(**pargs) elif map_proj == 'POLAR': pwrf = '+proj=stere +lat_ts={lat_1} +lat_0=90.0 +lon_0={lon_0} ' \ '+x_0=0 +y_0=0 +a=6370000 +b=6370000' pwrf = pwrf.format(**pargs) else: raise NotImplementedError('WRF proj not implemented yet: ' '{}'.format(map_proj)) pwrf = gis.check_crs(pwrf) # get easting and northings from dom center (probably unnecessary here) e, n = gis.transform_proj(wgs84, pwrf, pargs['ref_lon'], pargs['lat_0']) # LL corner nx, ny = e_we[0]-1, e_sn[0]-1 x0 = -(nx-1) / 2. * dx + e # -2 because of staggered grid y0 = -(ny-1) / 2. * dy + n # parent grid grid = gis.Grid(nxny=(nx, ny), x0y0=(x0, y0), dxdy=(dx, dy), proj=pwrf) # child grids out = [grid] for ips, jps, pid, ratio, we, sn in zip(i_parent_start, j_parent_start, parent_id, parent_ratio, e_we, e_sn): if ips == 1: continue ips -= 1 jps -= 1 we -= 1 sn -= 1 nx = we / ratio ny = sn / ratio if nx != (we / ratio): raise RuntimeError('e_we and ratios are incompatible: ' '(e_we - 1) / ratio must be integer!') if ny != (sn / ratio): raise RuntimeError('e_sn and ratios are incompatible: ' '(e_sn - 1) / ratio must be integer!') prevgrid = out[pid - 1] xx, yy = prevgrid.corner_grid.x_coord, prevgrid.corner_grid.y_coord dx = prevgrid.dx / ratio dy = prevgrid.dy / ratio grid = gis.Grid(nxny=(we, sn), x0y0=(xx[ips], yy[jps]), dxdy=(dx, dy), pixel_ref='corner', proj=pwrf) out.append(grid.center_grid) maps = None if do_maps: from salem import Map import shapely.geometry as shpg if map_kwargs is None: map_kwargs = {} maps = [] for i, g in enumerate(out): m = Map(g, **map_kwargs) for j in range(i+1, len(out)): cg = out[j] left, right, bottom, top = cg.extent s = np.array([(left, bottom), (right, bottom), (right, top), (left, top)]) l1 = shpg.LinearRing(s) m.set_geometry(l1, crs=cg.proj, linewidth=(len(out)-j), zorder=5) maps.append(m) return out, maps