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_comparisons(self): """See if the grids can compare themselves""" args = dict(nxny=(3, 3), dxdy=(1, 1), x0y0=(0, 0), proj=wgs84) g1 = Grid(**args) self.assertEqual(g1.center_grid, g1.corner_grid) self.assertTrue(g1.center_grid.almost_equal(g1.center_grid)) g2 = Grid(**args) self.assertEqual(g1, g2) self.assertTrue(g1.almost_equal(g2)) args['dxdy'] = (1. + 1e-6, 1. + 1e-6) g2 = Grid(**args) self.assertNotEqual(g1, g2) self.assertTrue(g1.almost_equal(g2)) # serialization d = g1.to_dict() rg = Grid.from_dict(d) self.assertEqual(g1, rg) d = g2.to_dict() rg = Grid.from_dict(d) self.assertEqual(g2, rg) self.assertNotEqual(g1, rg) self.assertTrue(g1.almost_equal(rg)) g1.to_json('test.json') rg = Grid.from_json('test.json') os.remove('test.json') self.assertEqual(g1, rg) g2.to_json('test.json') rg = Grid.from_json('test.json') os.remove('test.json') self.assertEqual(g2, rg) self.assertNotEqual(g1, rg) self.assertTrue(g1.almost_equal(rg)) args['proj'] = gis.check_crs('+init=epsg:26915') g2 = Grid(**args) self.assertNotEqual(g1, g2) self.assertFalse(g1.almost_equal(g2)) # New instance, same proj args['proj'] = gis.check_crs('+init=epsg:26915') g1 = Grid(**args) self.assertEqual(g1, g2) self.assertTrue(g1.almost_equal(g2)) # serialization d = g1.to_dict() rg = Grid.from_dict(d) self.assertEqual(g1, rg) self.assertTrue(g1.almost_equal(rg)) g1.to_json('test.json') rg = Grid.from_json('test.json') os.remove('test.json') self.assertEqual(g1, rg) self.assertTrue(g1.almost_equal(rg))
def test_ij_to_crs(self): """Converting to projection""" # It should work exact same for any projection projs = [wgs84, gis.check_crs('+init=epsg:26915')] for proj in projs: args = dict(nxny=(3, 3), dxdy=(1, 1), x0y0=(0, 0), proj=proj) g = Grid(**args) exp_i, exp_j = np.meshgrid(np.arange(3), np.arange(3)) r_i, r_j = g.ij_to_crs(exp_i, exp_j) assert_allclose(exp_i, r_i, atol=1e-03) assert_allclose(exp_j, r_j, atol=1e-03) proj_out = proj r_i, r_j = g.ij_to_crs(exp_i, exp_j, crs=proj_out) assert_allclose(exp_i, r_i, atol=1e-03) assert_allclose(exp_j, r_j, atol=1e-03) # The equivalents gc = g.corner_grid r_i, r_j = gc.ij_to_crs(exp_i + 0.5, exp_j + 0.5) assert_allclose(exp_i, r_i, atol=1e-03) assert_allclose(exp_j, r_j, atol=1e-03) gc = g.center_grid r_i, r_j = gc.ij_to_crs(exp_i, exp_j) assert_allclose(exp_i, r_i, atol=1e-03) assert_allclose(exp_j, r_j, atol=1e-03) args = dict(nxny=(3, 3), dxdy=(1, -1), x0y0=(0, 0), proj=proj) g = Grid(**args) exp_i, exp_j = np.meshgrid(np.arange(3), -np.arange(3)) in_i, in_j = np.meshgrid(np.arange(3), np.arange(3)) r_i, r_j = g.ij_to_crs(in_i, in_j) assert_allclose(exp_i, r_i, atol=1e-03) assert_allclose(exp_j, r_j, atol=1e-03) proj_out = proj r_i, r_j = g.ij_to_crs(in_i, in_j, crs=proj_out) assert_allclose(exp_i, r_i, atol=1e-03) assert_allclose(exp_j, r_j, atol=1e-03) # The equivalents gc = g.corner_grid r_i, r_j = gc.ij_to_crs(in_i, in_j) assert_allclose(exp_i - 0.5, r_i, atol=1e-03) assert_allclose(exp_j + 0.5, r_j, atol=1e-03) gc = g.center_grid r_i, r_j = gc.ij_to_crs(in_i, in_j) assert_allclose(exp_i, r_i, atol=1e-03) assert_allclose(exp_j, r_j, atol=1e-03) # if we take some random projection it wont work proj_out = pyproj.Proj(proj="utm", zone=10, datum='NAD27') r_i, r_j = g.ij_to_crs(exp_i, exp_j, crs=proj_out) self.assertFalse(np.allclose(exp_i, r_i)) self.assertFalse(np.allclose(exp_j, r_j)) # Raise self.assertRaises(ValueError, g.ij_to_crs, exp_i, exp_j, crs='ups')
def test_map_gridded_data(self): """Ok now the serious stuff starts with some fake data""" # It should work exact same for any projection projs = [wgs84, gis.check_crs('+init=epsg:26915')] for proj in projs: nx, ny = (3, 4) data = np.arange(nx * ny).reshape((ny, nx)) # Nearest Neighbor args = dict(nxny=(nx, ny), dxdy=(1, 1), x0y0=(0, 0), proj=proj) g = Grid(**args) odata = g.map_gridded_data(data, g) self.assertTrue(odata.shape == data.shape) assert_allclose(data, odata, atol=1e-03) # Out of the grid go = Grid(nxny=(nx, ny), dxdy=(1, 1), x0y0=(9, 9), proj=proj) odata = g.map_gridded_data(data, go) odata.set_fill_value(-999) self.assertTrue(odata.shape == data.shape) self.assertTrue(np.all(odata.mask)) args = dict(nxny=(nx - 1, ny - 1), dxdy=(1, 1), x0y0=(0, 0), proj=proj) ig = Grid(**args) odata = g.map_gridded_data(data[0:ny - 1, 0:nx - 1], ig) self.assertTrue(odata.shape == (ny, nx)) assert_allclose(data[0:ny - 1, 0:nx - 1], odata[0:ny - 1, 0:nx - 1], atol=1e-03) assert_array_equal([True] * 3, odata.mask[ny - 1, :]) data = np.arange(nx * ny).reshape((ny, nx)) * 1.2 odata = g.map_gridded_data(data[0:ny - 1, 0:nx - 1], ig) self.assertTrue(odata.shape == (ny, nx)) assert_allclose(data[0:ny - 1, 0:nx - 1], odata[0:ny - 1, 0:nx - 1], atol=1e-03) self.assertTrue( np.sum(np.isfinite(odata)) == ((ny - 1) * (nx - 1))) # Bilinear data = np.arange(nx * ny).reshape((ny, nx)) exp_data = np.array([2., 3., 5., 6., 8., 9.]).reshape( (ny - 1, nx - 1)) args = dict(nxny=(nx, ny), dxdy=(1, 1), x0y0=(0, 0), proj=proj) gfrom = Grid(**args) args = dict(nxny=(nx - 1, ny - 1), dxdy=(1, 1), x0y0=(0.5, 0.5), proj=proj) gto = Grid(**args) odata = gto.map_gridded_data(data, gfrom, interp='linear') self.assertTrue(odata.shape == (ny - 1, nx - 1)) assert_allclose(exp_data, odata, atol=1e-03)
def test_extent(self): # It should work exact same for any projection args = dict(nxny=(9, 9), dxdy=(1, 1), x0y0=(0, 0), proj=wgs84) g1 = Grid(**args) assert_allclose(g1.extent, g1.extent_in_crs(crs=g1.proj), atol=1e-3) args = dict(nxny=(9, 9), dxdy=(30000, 30000), x0y0=(0., 1577463), proj=gis.check_crs('+init=epsg:26915')) g2 = Grid(**args) assert_allclose(g2.extent, g2.extent_in_crs(crs=g2.proj), atol=1e-3) exg = np.array(g2.extent_in_crs(crs=g1)) exgx, exgy = g1.ij_to_crs(exg[[0, 1]], exg[[2, 3]], crs=wgs84) lon, lat = g2.corner_grid.ll_coordinates assert_allclose([np.min(lon), np.min(lat)], [exgx[0], exgy[0]], rtol=0.1) p = g2.extent_as_polygon(crs=g2.proj) assert p.is_valid x, y = p.exterior.coords.xy assert_allclose([np.min(x), np.max(x), np.min(y), np.max(y)], g2.extent)
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, file): self.nc = netCDF4.Dataset(file) proj = gis.check_crs(str(self.nc.proj4_str)) x = self.nc.variables['x'] y = self.nc.variables['y'] dxdy = (x[1] - x[0], y[1] - y[0]) nxny = (len(x), len(y)) x0y0 = None if dxdy[1] > 0: x0y0 = (x[0], y[0]) if dxdy[1] < 0: x0y0 = (x[0], y[0]) self.grid = Grid(nxny=nxny, dxdy=dxdy, proj=proj, x0y0=x0y0)
def test_geometry(self): projs = [wgs84, gis.check_crs('+init=epsg:26915')] from shapely.geometry import Point for proj in projs: g = Grid(nxny=(3, 3), dxdy=(1, 1), x0y0=(0.5, 0.5), proj=proj) gdf = g.to_geometry() self.assertEqual(len(gdf), 9) self.assertTrue(gdf.contains(Point(1.5, 1.5))[4]) self.assertFalse(gdf.contains(Point(1.5, 1.5))[5]) gdf = g.to_geometry(to_crs=wgs84) # This is now quite off self.assertFalse(gdf.contains(Point(1.5, 1.5))[4])
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 _check_data(self, data=None, crs=None, interp='nearest', overplot=False): """Interpolates the data to the map grid.""" if crs is None: # try xarray # TODO: note that this might slow down the plotting a bit # if the data already matches the grid... try: crs = data.salem.grid except: pass data = np.ma.fix_invalid(np.squeeze(data)) shp = data.shape if len(shp) != 2: raise ValueError('Data should be 2D.') crs = gis.check_crs(crs) if crs is None: # Reform case, but with a sanity check if not np.isclose( shp[0] / shp[1], self.grid.ny / self.grid.nx, atol=1e-2): raise ValueError('Dimensions of data do not match the map.') # need to resize if not same if not ((shp[0] == self.grid.ny) and (shp[1] == self.grid.nx)): if interp.lower() == 'linear': interp = 'bilinear' if interp.lower() == 'spline': interp = 'cubic' # TODO: this does not work well with masked arrays data = imresize(data.filled(np.NaN), (self.grid.ny, self.grid.nx), interp=interp, mode='F') elif isinstance(crs, Grid): # Remap if overplot: data = self.grid.map_gridded_data(data, crs, interp=interp, out=self.data) else: data = self.grid.map_gridded_data(data, crs, interp=interp) else: raise ValueError('crs not understood') return data
def test_regrid(self): """New grids""" # It should work exact same for any projection projs = [wgs84, gis.check_crs('+init=epsg:26915')] for proj in projs: kargs = [ dict(nxny=(3, 2), dxdy=(1, 1), x0y0=(0, 0), proj=proj), dict(nxny=(3, 2), dxdy=(1, -1), x0y0=(0, 0), proj=proj), dict(nxny=(3, 2), dxdy=(1, 1), x0y0=(0, 0), proj=proj, pixel_ref='corner'), dict(nxny=(3, 2), dxdy=(1, -1), x0y0=(0, 0), proj=proj, pixel_ref='corner') ] for ka in kargs: g = Grid(**ka) rg = g.regrid() self.assertTrue(g == rg) rg = g.regrid(factor=3) assert_array_equal(g.extent, rg.extent) assert_array_equal(g.extent, rg.extent) bg = rg.regrid(factor=1 / 3) self.assertEqual(g, bg) gx, gy = g.center_grid.xy_coordinates rgx, rgy = rg.center_grid.xy_coordinates assert_allclose(gx, rgx[1::3, 1::3], atol=1e-7) assert_allclose(gy, rgy[1::3, 1::3], atol=1e-7) gx, gy = g.center_grid.ll_coordinates rgx, rgy = rg.center_grid.ll_coordinates assert_allclose(gx, rgx[1::3, 1::3], atol=1e-7) assert_allclose(gy, rgy[1::3, 1::3], atol=1e-7) nrg = g.regrid(nx=9) self.assertTrue(nrg == rg) nrg = g.regrid(ny=6) self.assertTrue(nrg == rg)
def test_to_dataset(self): projs = [wgs84, gis.check_crs('+init=epsg:26915')] for proj in projs: g = Grid(nxny=(3, 3), dxdy=(1, 1), x0y0=(0, 0), proj=proj) ds = g.to_dataset() self.assertTrue(g == ds.salem.grid) g = Grid(nxny=(3, 3), dxdy=(1, 1), x0y0=(0, 0), proj=proj, pixel_ref='corner') ds = g.to_dataset() self.assertTrue(g == ds.salem.grid)
def __init__(self, file): self.nc = netCDF4.Dataset(file) proj = gis.check_crs(str(self.nc.proj4_str)) x = self.nc.variables['x'] y = self.nc.variables['y'] dxdy = (x[1]-x[0], y[1]-y[0]) nxny = (len(x), len(y)) ll_corner = None ul_corner = None if dxdy[1] > 0: ll_corner = (x[0], y[0]) if dxdy[1] < 0: ul_corner = (x[0], y[0]) self.grid = Grid(nxny=nxny, dxdy=dxdy, proj=proj, ll_corner=ll_corner, ul_corner=ul_corner)
def test_same_proj(self): # this should work regardless of gdal or not: p1 = pyproj.Proj('+proj=utm +zone=15 +datum=NAD83 ' '+ellps=GRS80 +towgs84=0,0,0 +units=m +no_defs') p2 = pyproj.Proj('+proj=utm +zone=15 +datum=NAD83 +units=m +no_defs ' '+ellps=GRS80 +towgs84=0,0,0') self.assertTrue(gis.proj_is_same(p1, p2)) # this needs gdal p1 = gis.check_crs('+init=epsg:26915') p2 = pyproj.Proj('+proj=utm +zone=15 +ellps=GRS80 +datum=NAD83 ' '+units=m +no_defs') if gis.has_gdal: self.assertTrue(gis.proj_is_same(p1, p2))
def test_xarray_support(self): # what happens if we use salem's funcs with xarray? import xarray as xr projs = [wgs84, gis.check_crs('+init=epsg:26915')] for proj in projs: args = dict(nxny=(3, 3), dxdy=(1, 1), x0y0=(0, 0), proj=proj) g = Grid(**args) exp_i, exp_j = np.meshgrid(np.arange(3), np.arange(3)) exp_i, exp_j = (xr.DataArray(exp_i, dims=['y', 'x']), xr.DataArray(exp_j, dims=['y', 'x'])) r_i, r_j = g.ij_to_crs(exp_i, exp_j) assert_allclose(exp_i, r_i, atol=1e-03) assert_allclose(exp_j, r_j, atol=1e-03) self.assertTrue(r_i.dims == exp_i.dims) # transform r_i, r_j = g.transform(exp_i, exp_j, crs=proj) assert_allclose(exp_i, r_i, atol=1e-03) assert_allclose(exp_j, r_j, atol=1e-03) # TODO: this doesn't work: # self.assertTrue(r_i.dims == exp_i.dims) # map nx, ny = (3, 4) data = np.arange(nx * ny).reshape((ny, nx)) data = xr.DataArray(data, coords={ 'y': np.arange(ny), 'x': np.arange(nx) }, dims=['y', 'x']) data.attrs = {'test': 'attr'} # Nearest Neighbor args = dict(nxny=(nx, ny), dxdy=(1, 1), x0y0=(0, 0), proj=proj) g = Grid(**args) odata = g.map_gridded_data(data, g) self.assertTrue(odata.shape == data.shape) assert_allclose(data, odata, atol=1e-03) # Transform can understand a grid data.attrs['pyproj_srs'] = g.proj.srs odata = g.map_gridded_data(data) self.assertTrue(odata.shape == data.shape) assert_allclose(data, odata, atol=1e-03)
def _check_data(self, data=None, crs=None, interp='nearest', overplot=False): """Interpolates the data to the map grid.""" if crs is None: # try xarray # TODO: note that this might slow down the plotting a bit # if the data already matches the grid... try: crs = data.salem.grid except: pass data = np.ma.fix_invalid(np.squeeze(data)) shp = data.shape if len(shp) != 2: raise ValueError('Data should be 2D.') crs = gis.check_crs(crs) if crs is None: # Reform case, but with a sanity check if not np.isclose(shp[0] / shp[1], self.grid.ny / self.grid.nx, atol=1e-2): raise ValueError('Dimensions of data do not match the map.') # need to resize if not same if not ((shp[0] == self.grid.ny) and (shp[1] == self.grid.nx)): if interp.lower() == 'linear': interp = 'bilinear' if interp.lower() == 'spline': interp = 'cubic' # TODO: this does not work well with masked arrays data = imresize(data.filled(np.NaN), (self.grid.ny, self.grid.nx), interp=interp, mode='F') elif isinstance(crs, Grid): # Remap if overplot: data = self.grid.map_gridded_data(data, crs, interp=interp, out=self.data) else: data = self.grid.map_gridded_data(data, crs, interp=interp) else: raise ValueError('crs not understood') return data
def _salem_grid_from_dataset(ds): """Seek for coordinates that Salem might have created. Current convention: x_coord, y_coord, pyproj_srs as attribute """ # Projection try: proj = ds.pyproj_srs except AttributeError: proj = None proj = gis.check_crs(proj) if proj is None: return None # Do we have some standard names as variable? vns = ds.variables.keys() xc = utils.str_in_list(vns, utils.valid_names['x_dim']) yc = utils.str_in_list(vns, utils.valid_names['y_dim']) # Sometimes there are more than one coordinates, one of which might have # more dims (e.g. lons in WRF files): take the first one with ndim = 1: x = None for xp in xc: if len(ds.variables[xp].shape) == 1: x = xp y = None for yp in yc: if len(ds.variables[yp].shape) == 1: y = yp if (x is None) or (y is None): return None # OK, get it x = ds.variables[x][:] y = ds.variables[y][:] # Make the grid dx = x[1] - x[0] dy = y[1] - y[0] args = dict(nxny=(x.shape[0], y.shape[0]), proj=proj, dxdy=(dx, dy), x0y0=(x[0], y[0])) return gis.Grid(**args)
def _salem_grid_from_dataset(ds): """Seek for coordinates that Salem might have created. Current convention: x_coord, y_coord, pyproj_srs as attribute """ # Projection try: proj = ds.pyproj_srs except AttributeError: proj = None proj = gis.check_crs(proj) if proj is None: return None # Do we have some standard names as variable? vns = ds.variables.keys() xc = utils.str_in_list(vns, utils.valid_names['x_dim']) yc = utils.str_in_list(vns, utils.valid_names['y_dim']) # Sometimes there are more than one coordinates, one of which might have # more dims (e.g. lons in WRF files): take the first one with ndim = 1: x = None for xp in xc: if len(ds.variables[xp].shape) == 1: x = xp y = None for yp in yc: if len(ds.variables[yp].shape) == 1: y = yp if (x is None) or (y is None): return None # OK, get it x = ds.variables[x][:] y = ds.variables[y][:] # Make the grid dx = x[1]-x[0] dy = y[1]-y[0] args = dict(nxny=(x.shape[0], y.shape[0]), proj=proj, dxdy=(dx, dy)) args['corner'] = (x[0], y[0]) return gis.Grid(**args)
def test_stagg(self): """Staggered grids.""" # It should work exact same for any projection projs = [wgs84, gis.check_crs('+init=epsg:26915')] for proj in projs: args = dict(nxny=(3, 2), dxdy=(1, 1), x0y0=(0, 0), proj=proj, pixel_ref='corner') g = Grid(**args) x, y = g.xstagg_xy_coordinates assert_array_equal(x, np.array([[0, 1, 2, 3], [0, 1, 2, 3]])) assert_array_equal( y, np.array([[0.5, 0.5, 0.5, 0.5], [1.5, 1.5, 1.5, 1.5]])) xx, yy = g.corner_grid.xstagg_xy_coordinates assert_array_equal(x, xx) assert_array_equal(y, yy) xt, yt = x, y x, y = g.ystagg_xy_coordinates assert_array_equal( x, np.array([[0.5, 1.5, 2.5], [0.5, 1.5, 2.5], [0.5, 1.5, 2.5]])) assert_array_equal(y, np.array([[0, 0, 0], [1, 1, 1], [2, 2, 2]])) xx, yy = g.corner_grid.ystagg_xy_coordinates assert_array_equal(x, xx) assert_array_equal(y, yy) if proj is wgs84: xx, yy = g.corner_grid.ystagg_ll_coordinates assert_allclose(x, xx) assert_allclose(y, yy) xx, yy = g.corner_grid.xstagg_ll_coordinates assert_allclose(xt, xx) assert_allclose(yt, yy) x, y = g.pixcorner_ll_coordinates assert_allclose( x, np.array([[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]])) assert_allclose( y, np.array([[0, 0, 0, 0], [1, 1, 1, 1], [2, 2, 2, 2]]))
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 test_to_cartopy(self): import cartopy.crs as ccrs from salem import GeoNetcdf, GeoTiff grid = gis.mercator_grid(center_ll=(11.38, 47.26), extent=(2000000, 2000000)) p = gis.proj_to_cartopy(grid.proj) assert isinstance(p, ccrs.TransverseMercator) fuzzy_proj_tester(grid.proj, pyproj.Proj(p.proj4_params)) ds = GeoNetcdf(get_demo_file('wrfout_d01.nc')) p = gis.proj_to_cartopy(ds.grid.proj) assert isinstance(p, ccrs.LambertConformal) fuzzy_proj_tester(ds.grid.proj, pyproj.Proj(p.proj4_params)) ds = GeoNetcdf(get_demo_file('wrf_mercator.nc')) p = gis.proj_to_cartopy(ds.grid.proj) assert isinstance(p, ccrs.Mercator) fuzzy_proj_tester(ds.grid.proj, pyproj.Proj(p.proj4_params)) ds = GeoTiff(get_demo_file('himalaya.tif')) p = gis.proj_to_cartopy(ds.grid.proj) assert isinstance(p, ccrs.PlateCarree) ds = GeoTiff(get_demo_file('hef_roi.tif')) p = gis.proj_to_cartopy(ds.grid.proj) assert isinstance(p, ccrs.PlateCarree) p = gis.proj_to_cartopy(wgs84) assert isinstance(p, ccrs.PlateCarree) p = gis.proj_to_cartopy(pyproj.Proj('+proj=utm +zone=15')) assert isinstance(p, ccrs.UTM) # this needs gdal if gis.has_gdal: p = gis.proj_to_cartopy(gis.check_crs('+init=epsg:26915')) assert isinstance(p, ccrs.UTM)
def test_map_gridded_data_over(self): # It should work exact same for any projection projs = [wgs84, gis.check_crs('epsg:26915')] for proj in projs: nx, ny = (4, 5) data = np.arange(nx * ny).reshape((ny, nx)).astype(np.float) in_data = data * np.NaN in_data[0, :] = 78 # Nearest Neighbor args = dict(nxny=(nx, ny), dxdy=(1, 1), x0y0=(0, 0), proj=proj) g = Grid(**args) odata = g.map_gridded_data(data, g, out=data.copy()) self.assertTrue(odata.shape == data.shape) assert_allclose(data, odata, atol=1e-03) odata = g.map_gridded_data(in_data, g, out=data.copy()) self.assertTrue(odata.shape == data.shape) assert_allclose(data[1:, :], odata[1:, :], atol=1e-03) assert_allclose(odata[0, :], 78, atol=1e-03) # Bilinear odata = g.map_gridded_data(data, g, interp='linear', out=data.copy()) self.assertTrue(odata.shape == data.shape) assert_allclose(data, odata, atol=1e-03) # Spline odata = g.map_gridded_data(data, g, interp='spline', out=data.copy()) self.assertTrue(odata.shape == data.shape) assert_allclose(data, odata, atol=1e-03)
def _check_data(self, data=None, crs=None, interp='nearest', overplot=False): """Interpolates the data to the map grid.""" if crs is None: # try xarray # TODO: note that this might slow down the plotting a bit # if the data already matches the grid... try: crs = data.salem.grid except: pass data = np.ma.fix_invalid(np.squeeze(data)) shp = data.shape if len(shp) != 2: raise ValueError('Data should be 2D.') if crs is None: # Reform case, but with a sanity check if not np.isclose( shp[0] / shp[1], self.grid.ny / self.grid.nx, atol=1e-2): raise ValueError('Dimensions of data do not match the map.') # need to resize if not same if not ((shp[0] == self.grid.ny) and (shp[1] == self.grid.nx)): # We convert to float for img resizing if data.dtype not in [np.float32, np.float64]: data = data.astype(np.float64) if interp.lower() == 'nearest': interp = 0 elif interp.lower() == 'linear': interp = 1 elif interp.lower() == 'spline': interp = 3 if not has_skimage: raise ImportError('Needs scikit-image to be installed.') with warnings.catch_warnings(): mess = "invalid value encountered in reduce" warnings.filterwarnings("ignore", message=mess) mess = ("Possible precision loss when converting from " "int64 to float64") warnings.filterwarnings("ignore", message=mess) try: data = imresize(data.filled(np.NaN), (self.grid.ny, self.grid.nx), order=interp, mode='edge', anti_aliasing=True) except RuntimeError: # For some order anti_aliasing doesnt work with 'edge' data = imresize(data.filled(np.NaN), (self.grid.ny, self.grid.nx), order=interp, mode='edge', anti_aliasing=False) return data crs = gis.check_crs(crs, raise_on_error=True) if isinstance(crs, Grid): # Remap if overplot: data = self.grid.map_gridded_data(data, crs, interp=interp, out=self.data) else: data = self.grid.map_gridded_data(data, crs, interp=interp) else: raise ValueError('crs should be a grid, not a proj') return data
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 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 = pyproj.transform(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
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): """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 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['lon_0'] = float(s1[0]) if s0 == 'TRUELAT1': pargs['lat_1'] = float(s1[0]) if s0 == 'TRUELAT2': pargs['lat_2'] = float(s1[0]) # 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) 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 = pyproj.transform(wgs84, pwrf, pargs['lon_0'], 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), ll_corner=(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), ll_corner=(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 maps = [] for i, g in enumerate(out): m = Map(g) 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)) maps.append(m) return out, maps
def test_errors(self): """Check that errors are occurring""" # It should work exact same for any projection projs = [wgs84, gis.check_crs('+init=epsg:26915')] for proj in projs: with warnings.catch_warnings(): warnings.simplefilter("ignore") args = dict(nxny=(3, 3), dxdy=(1, -1), ll_corner=(0, 0), proj=proj) self.assertRaises(ValueError, Grid, **args) args = dict(nxny=(3, 3), dxdy=(-1, 0), ul_corner=(0, 0), proj=proj) self.assertRaises(ValueError, Grid, **args) args = dict(nxny=(3, 3), dxdy=(1, 1), proj=proj) self.assertRaises(ValueError, Grid, **args) args = dict(nxny=(3, -3), dxdy=(1, 1), ll_corner=(0, 0), proj=proj) self.assertRaises(ValueError, Grid, **args) args = dict(nxny=(3, 3), dxdy=(1, 1), ll_corner=(0, 0), proj=proj, pixel_ref='areyoudumb') self.assertRaises(ValueError, Grid, **args) args = dict(nxny=(3, 3), dxdy=(1, 1), ll_corner=(0, 0), proj=proj) g = Grid(**args) self.assertRaises(ValueError, g.transform, 0, 0, crs=None) self.assertRaises(ValueError, g.transform, 0, 0, crs='areyou?') self.assertRaises(ValueError, g.map_gridded_data, np.zeros((3, 3)), 'areyou?') self.assertRaises(ValueError, g.map_gridded_data, np.zeros(3), g) self.assertRaises(ValueError, g.map_gridded_data, np.zeros((3, 4)), g) self.assertRaises(ValueError, g.map_gridded_data, np.zeros((3, 3)), g, interp='youare') # deprecation warnings for proj in projs: with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") args = dict(nxny=(3, 3), dxdy=(1, -1), corner=(0, 0), proj=proj) Grid(**args) args = dict(nxny=(3, 3), dxdy=(1, -1), ul_corner=(0, 0), proj=proj) Grid(**args) args = dict(nxny=(3, 3), dxdy=(1, 1), ll_corner=(0, 0), proj=proj) Grid(**args) if python_version == 'py3': self.assertEqual(len(w), 3)
def test_transform(self): """Converting to the grid""" # It should work exact same for any projection projs = [wgs84, gis.check_crs('+init=epsg:26915')] for proj in projs: args = dict(nxny=(3, 3), dxdy=(1, 1), x0y0=(0, 0), proj=proj) g = Grid(**args) exp_i, exp_j = np.meshgrid(np.arange(3), np.arange(3)) r_i, r_j = g.transform(exp_i, exp_j, crs=proj) assert_allclose(exp_i, r_i, atol=1e-03) assert_allclose(exp_j, r_j, atol=1e-03) r_i, r_j = g.transform(exp_i, exp_j, crs=g) assert_allclose(exp_i, r_i, atol=1e-03) assert_allclose(exp_j, r_j, atol=1e-03) r_i, r_j = g.corner_grid.transform(exp_i, exp_j, crs=proj) assert_allclose(exp_i + 0.5, r_i, atol=1e-03) assert_allclose(exp_j + 0.5, r_j, atol=1e-03) r_i, r_j = g.corner_grid.transform(exp_i, exp_j, crs=g) assert_allclose(exp_i + 0.5, r_i, atol=1e-03) assert_allclose(exp_j + 0.5, r_j, atol=1e-03) args['pixel_ref'] = 'corner' g = Grid(**args) exp_i, exp_j = np.meshgrid(np.arange(3), np.arange(3)) r_i, r_j = g.transform(exp_i, exp_j, crs=proj) assert_allclose(exp_i, r_i, atol=1e-03) assert_allclose(exp_j, r_j, atol=1e-03) r_i, r_j = g.transform(exp_i, exp_j, crs=g) assert_allclose(exp_i, r_i, atol=1e-03) assert_allclose(exp_j, r_j, atol=1e-03) r_i, r_j = g.corner_grid.transform(exp_i, exp_j, crs=proj) assert_allclose(exp_i, r_i, atol=1e-03) assert_allclose(exp_j, r_j, atol=1e-03) r_i, r_j = g.corner_grid.transform(exp_i, exp_j, crs=g) assert_allclose(exp_i, r_i, atol=1e-03) assert_allclose(exp_j, r_j, atol=1e-03) r_i, r_j = g.center_grid.transform(exp_i, exp_j, crs=proj) assert_allclose(exp_i - 0.5, r_i, atol=1e-03) assert_allclose(exp_j - 0.5, r_j, atol=1e-03) r_i, r_j = g.center_grid.transform(exp_i, exp_j, crs=g) assert_allclose(exp_i - 0.5, r_i, atol=1e-03) assert_allclose(exp_j - 0.5, r_j, atol=1e-03) ex = g.corner_grid.extent assert_allclose([0, 3, 0, 3], ex, atol=1e-03) assert_allclose(g.center_grid.extent, g.corner_grid.extent, atol=1e-03) # Masked xi = [-0.6, 0.5, 1.2, 2.9, 3.1, 3.6] yi = xi ex = [-1, 0, 1, 2, 3, 3] ey = ex r_i, r_j = g.corner_grid.transform(xi, yi, crs=proj) assert_allclose(xi, r_i, atol=1e-03) assert_allclose(yi, r_j, atol=1e-03) r_i, r_j = g.corner_grid.transform(xi, yi, crs=proj, nearest=True) assert_array_equal(ex, r_i) assert_array_equal(ey, r_j) r_i, r_j = g.center_grid.transform(xi, yi, crs=proj, nearest=True) assert_array_equal(ex, r_i) assert_array_equal(ey, r_j) ex = np.ma.masked_array(ex, mask=[1, 0, 0, 0, 1, 1]) ey = ex r_i, r_j = g.center_grid.transform(xi, yi, crs=proj, nearest=True, maskout=True) assert_array_equal(ex, r_i) assert_array_equal(ey, r_j) assert_array_equal(ex.mask, r_i.mask) assert_array_equal(ey.mask, r_j.mask) r_i, r_j = g.corner_grid.transform(xi, yi, crs=proj, nearest=True, maskout=True) assert_array_equal(ex, r_i) assert_array_equal(ey, r_j) assert_array_equal(ex.mask, r_i.mask) assert_array_equal(ey.mask, r_j.mask) del args['pixel_ref'] args['x0y0'] = (0, 0) args['dxdy'] = (1, -1) g = Grid(**args) in_i, in_j = np.meshgrid(np.arange(3), -np.arange(3)) exp_i, exp_j = np.meshgrid(np.arange(3), np.arange(3)) r_i, r_j = g.transform(in_i, in_j, crs=proj) assert_allclose(exp_i, r_i, atol=1e-03) assert_allclose(exp_j, r_j, atol=1e-03) in_i, in_j = np.meshgrid(np.arange(3), np.arange(3)) r_i, r_j = g.transform(in_i, in_j, crs=g) assert_allclose(exp_i, r_i, atol=1e-03) assert_allclose(exp_j, r_j, atol=1e-03)
def test_simple_dataset(self): # see if with is working with SimpleNcDataSet(get_demo_file('dem_wgs84.nc')) as nc: nc = SimpleNcDataSet(get_demo_file('dem_wgs84.nc')) grid_from = nc.grid self.assertTrue(gis.check_crs(grid_from))
def test_check_crs_log(self): assert gis.check_crs('wrong') is None with pytest.raises(ValueError): gis.check_crs('wrong', raise_on_error=True)
def test_constructor(self): # It should work exact same for any projection projs = [wgs84, gis.check_crs('+init=epsg:26915')] for proj in projs: args = dict(nxny=(3, 3), dxdy=(1, 1), x0y0=(0, 0), proj=proj) g = Grid(**args) self.assertTrue(isinstance(g, Grid)) self.assertEqual(g.center_grid, g.corner_grid) # serialization d = g.to_dict() rg = Grid.from_dict(d) self.assertEqual(g, rg) g.to_json('test.json') rg = Grid.from_json('test.json') os.remove('test.json') self.assertEqual(g, rg) oargs = dict(nxny=(3, 3), dxdy=(1, 1), x0y0=(0, 0), proj=proj) og = Grid(**oargs) self.assertEqual(g, og) # very simple test exp_i, exp_j = np.meshgrid(np.arange(3), np.arange(3)) i, j = g.ij_coordinates assert_allclose(i, exp_i) assert_allclose(j, exp_j) i, j = g.xy_coordinates assert_allclose(i, exp_i) assert_allclose(j, exp_j) if proj == projs[0]: i, j = g.ll_coordinates assert_allclose(i, exp_i) assert_allclose(j, exp_j) args['proj'] = 'dummy' self.assertRaises(ValueError, Grid, **args) args['proj'] = proj args['nxny'] = (1, -1) self.assertRaises(ValueError, Grid, **args) args['nxny'] = (3, 3) args['dxdy'] = (1, -1) args['ll_corner'] = args['x0y0'] del args['x0y0'] with warnings.catch_warnings(record=True) as w: warnings.simplefilter('always') self.assertRaises(ValueError, Grid, **args) self.assertEqual(len(w), 1) args['x0y0'] = args['ll_corner'] del args['ll_corner'] # Center VS corner - multiple times because it was a bug assert_allclose(g.center_grid.xy_coordinates, g.xy_coordinates) assert_allclose(g.center_grid.center_grid.xy_coordinates, g.xy_coordinates) assert_allclose(g.corner_grid.corner_grid.xy_coordinates, g.corner_grid.xy_coordinates) ex = g.corner_grid.extent assert_allclose([-0.5, 2.5, -0.5, 2.5], ex) assert_allclose(g.center_grid.extent, g.corner_grid.extent) args['x0y0'] = (0, 0) g = Grid(**args) self.assertTrue(isinstance(g, Grid)) oargs = dict(nxny=(3, 3), dxdy=(1, -1), x0y0=(0, 0), proj=proj) og = Grid(**oargs) self.assertEqual(g, og) # serialization d = og.to_dict() rg = Grid.from_dict(d) self.assertEqual(og, rg) # The simple test should work here too i, j = g.ij_coordinates assert_allclose(i, exp_i) assert_allclose(j, exp_j) # But the lonlats are the other way around: exp_x, exp_y = np.meshgrid(np.arange(3), -np.arange(3)) x, y = g.xy_coordinates assert_allclose(x, exp_x) assert_allclose(y, exp_y) if proj == projs[0]: i, j = g.ll_coordinates assert_allclose(i, exp_x) assert_allclose(j, exp_y) # Center VS corner - multiple times because it was a bug assert_allclose(g.center_grid.xy_coordinates, g.xy_coordinates) assert_allclose(g.center_grid.center_grid.xy_coordinates, g.xy_coordinates) assert_allclose(g.corner_grid.corner_grid.xy_coordinates, g.corner_grid.xy_coordinates) ex = g.corner_grid.extent assert_allclose([-0.5, 2.5, -2.5, 0.5], ex) assert_allclose(g.center_grid.extent, g.corner_grid.extent) # The equivalents g = g.corner_grid i, j = g.ij_coordinates assert_allclose(i, exp_i) assert_allclose(j, exp_j) exp_x, exp_y = np.meshgrid(np.arange(3) - 0.5, -np.arange(3) + 0.5) x, y = g.xy_coordinates assert_allclose(x, exp_x) assert_allclose(y, exp_y) args = dict(nxny=(3, 2), dxdy=(1, 1), x0y0=(0, 0)) g = Grid(**args) self.assertTrue(isinstance(g, Grid)) self.assertTrue(g.xy_coordinates[0].shape == (2, 3)) self.assertTrue(g.xy_coordinates[1].shape == (2, 3))