def test_eccentric_globe(): globe = ccrs.Globe(semimajor_axis=10000, semiminor_axis=5000, ellipse=None) crs = ccrs.Mercator(globe=globe, min_latitude=-40, max_latitude=40) other_args = { 'a=10000', 'b=5000', 'lon_0=0.0', 'x_0=0.0', 'y_0=0.0', 'units=m' } check_proj_params('merc', crs, other_args) assert_almost_equal(crs.boundary.bounds, [-31415.93, -2190.5, 31415.93, 2190.5], decimal=2) assert_almost_equal(crs.x_limits, [-31415.93, 31415.93], decimal=2) assert_almost_equal(crs.y_limits, [-2190.5, 2190.5], decimal=2)
def test_ellipse_globe(): globe = ccrs.Globe(ellipse='WGS84') with pytest.warns(UserWarning, match='does not handle elliptical globes.') as w: robin = ccrs.Robinson(globe=globe) assert len(w) == 1 other_args = {'ellps=WGS84', 'lon_0=0'} check_proj_params('robin', robin, other_args) # Limits are the same as default since ellipses are not supported. assert_almost_equal(robin.x_limits, [-17005833.3305252, 17005833.3305252]) assert_almost_equal(robin.y_limits, [-8625154.6651000, 8625154.6651000], _LIMIT_TOL)
def test_scale_factor(): # Should be same as lat_ts=20 for a sphere scale_factor = 0.939692620786 crs = ccrs.Mercator(scale_factor=scale_factor, globe=ccrs.Globe(ellipse='sphere')) other_args = { 'ellps=sphere', 'lon_0=0.0', 'x_0=0.0', 'y_0=0.0', 'units=m', 'k_0={:.12f}'.format(scale_factor) } check_proj_params('merc', crs, other_args) assert_almost_equal(crs.boundary.bounds, [-18808021, -14585266, 18808021, 17653216], decimal=0)
def test_eccentric_globe(): globe = ccrs.Globe(semimajor_axis=1000, semiminor_axis=500, ellipse=None) eqearth = ccrs.EqualEarth(globe=globe) other_args = {'a=1000', 'b=500', 'lon_0=0'} check_proj_params('eqearth', eqearth, other_args) assert_almost_equal(eqearth.x_limits, [-2248.43664092550, 2248.43664092550]) assert_almost_equal(eqearth.y_limits, [-1094.35228122148, 1094.35228122148]) # Expected aspect ratio from the paper. assert_almost_equal(np.diff(eqearth.x_limits) / np.diff(eqearth.y_limits), 2.05458, decimal=5)
def test_eccentric_globe(): globe = ccrs.Globe(semimajor_axis=1000, semiminor_axis=500, ellipse=None) with pytest.warns(UserWarning, match='does not handle elliptical globes.') as w: robin = ccrs.Robinson(globe=globe) assert len(w) == 1 other_args = {'a=1000', 'b=500', 'lon_0=0'} check_proj_params('robin', robin, other_args) # Limits are the same as spheres since ellipses are not supported. assert_almost_equal(robin.x_limits, [-2666.2696851, 2666.2696851]) assert_almost_equal(robin.y_limits, [-1352.3000000, 1352.3000000], _LIMIT_TOL)
def test_eccentric_globe(self): globe = ccrs.Globe(semimajor_axis=1000, semiminor_axis=500, ellipse=None) eqdc = ccrs.EquidistantConic(globe=globe) other_args = {'a=1000', 'b=500', 'lon_0=0.0', 'lat_0=0.0', 'x_0=0.0', 'y_0=0.0', 'lat_1=20.0', 'lat_2=50.0'} check_proj4_params(eqdc, other_args) assert_almost_equal(np.array(eqdc.x_limits), (-3016.869847713461, 3016.869847713461), decimal=7) assert_almost_equal(np.array(eqdc.y_limits), (-1216.6029342241113, 2511.0574375797723), decimal=7)
def test_eccentric_globe(): globe = ccrs.Globe(semimajor_axis=1000, semiminor_axis=500, ellipse=None) with pytest.warns(UserWarning, match='does not handle elliptical globes.') as w: gnom = ccrs.Gnomonic(globe=globe) assert len(w) == 1 other_args = {'a=1000', 'b=500', 'lon_0=0.0', 'lat_0=0.0'} check_proj_params('gnom', gnom, other_args) # Limits are the same as spheres since ellipses are not supported. assert_almost_equal(gnom.x_limits, [-5e7, 5e7]) assert_almost_equal(gnom.y_limits, [-5e7, 5e7])
def test_eccentric_globe(self): globe = ccrs.Globe(semimajor_axis=1000, semiminor_axis=500, ellipse=None) aea = ccrs.AlbersEqualArea(globe=globe) other_args = {'a=1000', 'b=500', 'lon_0=0.0', 'lat_0=0.0', 'x_0=0.0', 'y_0=0.0', 'lat_1=20.0', 'lat_2=50.0'} check_proj_params('aea', aea, other_args) assert_almost_equal(np.array(aea.x_limits), [-2323.47073363411, 2323.47073363411], decimal=-2) assert_almost_equal(np.array(aea.y_limits), [-572.556243423972, 2402.36176984391], decimal=10)
def test_eccentric_globe(): globe = ccrs.Globe(semimajor_axis=1000, semiminor_axis=500, ellipse=None) with pytest.warns(UserWarning, match='does not handle elliptical globes.') as w: ortho = ccrs.Orthographic(globe=globe) assert len(w) == (2 if (5, 0, 0) <= ccrs.PROJ4_VERSION < (5, 1, 0) else 1) other_args = {'a=1000', 'b=500', 'lon_0=0.0', 'lat_0=0.0'} check_proj_params('ortho', ortho, other_args) # Limits are the same as spheres since ellipses are not supported. assert_almost_equal(ortho.x_limits, [-999.99, 999.99]) assert_almost_equal(ortho.y_limits, [-999.99, 999.99])
def test_ellipse_globe(): globe = ccrs.Globe(ellipse='WGS84') with pytest.warns(UserWarning, match='does not handle elliptical globes.') as w: ortho = ccrs.Orthographic(globe=globe) assert len(w) == (2 if (5, 0, 0) <= ccrs.PROJ4_VERSION < (5, 1, 0) else 1) other_args = {'ellps=WGS84', 'lon_0=0.0', 'lat_0=0.0'} check_proj_params('ortho', ortho, other_args) # Limits are the same as default since ellipses are not supported. assert_almost_equal(ortho.x_limits, [-6378073.21863, 6378073.21863]) assert_almost_equal(ortho.y_limits, [-6378073.21863, 6378073.21863])
def test_eccentric_globe(self): globe = ccrs.Globe(semimajor_axis=10000, semiminor_axis=5000, ellipse=None) geos = ccrs.Geostationary(satellite_height=50000, globe=globe) expected = [ '+a=10000', 'b=5000', 'h=50000', 'lat_0=0', 'lon_0=0.0', 'no_defs', 'proj=geos', 'units=m', 'x_0=0', 'y_0=0' ] self.check_proj4_params(geos, expected) assert_almost_equal(geos.boundary.bounds, (-8245.7306, -4531.3879, 8257.4339, 4531.3879), decimal=4)
def __init__(self, dataset_path, dx, dy, name): """Store the grid information. Parameters ---------- dataset_path : str Is used to read the gridcell coordinates dx : float Longitudinal size of a gridcell in meters dy : float Latitudinal size of a gridcell in meters name : str, optional """ self.dx = dx self.dy = dy projection = ccrs.LambertConformal( central_longitude=12.5, central_latitude=51.604, standard_parallels=[51.604], globe=ccrs.Globe( ellipse=None, semimajor_axis=6370000, semiminor_axis=6370000 ), ) # Read grid-values in lat/lon, which are distorted, then # project them to LambertConformal where the grid is # regular and rectangular. with Dataset(dataset_path) as dataset: proj_lon = np.array(dataset["lon"][:]) proj_lat = np.array(dataset["lat"][:]) self.lon_vals = projection.transform_points( ccrs.PlateCarree(), proj_lon[0, :], proj_lat[0, :] )[:, 0] self.lat_vals = projection.transform_points( ccrs.PlateCarree(), proj_lon[:, 0], proj_lat[:, 0] )[:, 1] # Cell corners x = self.lon_vals y = self.lat_vals dx2 = self.dx / 2 dy2 = self.dy / 2 self.cell_x = np.array([x + dx2, x + dx2, x - dx2, x - dx2]) self.cell_y = np.array([y + dy2, y - dy2, y - dy2, y + dy2]) super().__init__(name, projection)
def test_projection_creation(self): res = self.laea_cs.as_cartopy_projection() globe = ccrs.Globe( semimajor_axis=self.semi_major_axis, semiminor_axis=self.semi_minor_axis, ellipse=None, ) expected = ccrs.LambertAzimuthalEqualArea( self.latitude_of_projection_origin, self.longitude_of_projection_origin, self.false_easting, self.false_northing, globe=globe, ) self.assertEqual(res, expected)
def test_eccentric_globe(self): globe = ccrs.Globe(semimajor_axis=1000, semiminor_axis=500, ellipse=None) aeqd = ccrs.AzimuthalEquidistant(globe=globe) expected = ('+a=1000 +b=500 +proj=aeqd +lon_0=0.0 +lat_0=0.0 ' '+x_0=0.0 +y_0=0.0 +no_defs') assert aeqd.proj4_init == expected assert_almost_equal(np.array(aeqd.x_limits), [-3141.59265359, 3141.59265359], decimal=6) assert_almost_equal(np.array(aeqd.y_limits), [-1570.796326795, 1570.796326795], decimal=6)
def test_eccentric_globe(self): globe = ccrs.Globe(semimajor_axis=1000, semiminor_axis=500, ellipse=None) stereo = ccrs.Stereographic(globe=globe) expected = ('+a=1000 +b=500 +proj=stere +lat_0=0.0 +lon_0=0.0 ' '+x_0=0.0 +y_0=0.0 +no_defs') assert_equal(stereo.proj4_init, expected) # The limits in this test are sensible values, but are by no means # a "correct" answer - they mean that plotting the crs results in a # reasonable map. assert_almost_equal(np.array(stereo.x_limits), [-7839.27971444, 7839.27971444], decimal=4) assert_almost_equal(np.array(stereo.y_limits), [-3932.82587779, 3932.82587779], decimal=4)
def test_osgb_vals(self, approx): proj = ccrs.TransverseMercator(central_longitude=-2, central_latitude=49, scale_factor=0.9996012717, false_easting=400000, false_northing=-100000, globe=ccrs.Globe(datum='OSGB36', ellipse='airy'), approx=approx) res = proj.transform_point(*self.point_a, src_crs=self.src_crs) np.testing.assert_array_almost_equal(res, (295971.28668, 93064.27666), decimal=5) res = proj.transform_point(*self.point_b, src_crs=self.src_crs) np.testing.assert_array_almost_equal(res, (577274.98380, 69740.49227), decimal=5)
def test_eccentric_globe(self): globe = ccrs.Globe(semimajor_axis=1000, semiminor_axis=500, ellipse=None) stereo = ccrs.Stereographic(globe=globe) other_args = {'a=1000', 'b=500', 'lat_0=0.0', 'lon_0=0.0', 'x_0=0.0', 'y_0=0.0'} check_proj_params('stere', stereo, other_args) # The limits in this test are sensible values, but are by no means # a "correct" answer - they mean that plotting the crs results in a # reasonable map. assert_almost_equal(np.array(stereo.x_limits), [-7839.27971444, 7839.27971444], decimal=4) assert_almost_equal(np.array(stereo.y_limits), [-3932.82587779, 3932.82587779], decimal=4)
def test_set_xyticks(): fig = plt.figure(figsize=(10, 10)) projections = (ccrs.PlateCarree(), ccrs.Mercator(globe=ccrs.Globe( semimajor_axis=math.degrees(1))), ccrs.TransverseMercator(approx=False)) x = -3.275024 y = 50.753998 for i, prj in enumerate(projections, 1): ax = fig.add_subplot(3, 1, i, projection=prj) ax.set_extent([-12.5, 4, 49, 60], ccrs.Geodetic()) ax.coastlines('110m') p, q = prj.transform_point(x, y, ccrs.Geodetic()) ax.set_xticks([p]) ax.set_yticks([q])
def test_eccentric_globe(self): globe = ccrs.Globe(semimajor_axis=1000, semiminor_axis=500, ellipse=None) crs = ccrs.LambertAzimuthalEqualArea(globe=globe) other_args = { 'a=1000', 'b=500', 'lon_0=0.0', 'lat_0=0.0', 'x_0=0.0', 'y_0=0.0' } check_proj_params('laea', crs, other_args) assert_almost_equal(np.array(crs.x_limits), [-1999.9, 1999.9], decimal=1) assert_almost_equal(np.array(crs.y_limits), [-1380.17298647, 1380.17298647], decimal=4)
def __init__(self, lon0, lat0, Size, path_pdsfile=defaut_pdsfile): self.path_pdsfiles = path_pdsfile self.lat0 = lat0 self.lon0 = lon0 self.ppdlola = 512 self.ppdwac = 128 self.globe = ccrs.Globe(semimajor_axis=self.rsphere, semiminor_axis=self.rsphere) self.laea = ccrs.LambertAzimuthalEqualArea(central_longitude=self.lon0, central_latitude=self.lat0, globe=self.globe) assert (self.lon0 > 0.0) and (self.lon0 < 360.0), 'Longitude has to span 0-360 !!!' self.change_window(Size)
def test_inverted_poly_removed_hole(self): proj = ccrs.NorthPolarStereo(globe=ccrs.Globe(ellipse='WGS84')) poly = sgeom.Polygon([(0, 0), (-90, 0), (-180, 0), (-270, 0)], [[(-135, -75), (-45, -75), (45, -75), (135, -75)]]) multi_polygon = proj.project_geometry(poly) # Check the structure self.assertEqual(len(multi_polygon), 1) self.assertEqual(len(multi_polygon[0].interiors), 1) # Check the rough shape polygon = multi_polygon[0] self._assert_bounds(polygon.bounds, -5.0e7, -5.0e7, 5.0e7, 5.0e7, 1e6) self._assert_bounds(polygon.interiors[0].bounds, -1.2e7, -1.2e7, 1.2e7, 1.2e7, 1e6) self.assertAlmostEqual(polygon.area, 7.34e15, delta=1e13)
def test_eccentric_globe(self): globe = ccrs.Globe(semimajor_axis=10000, semiminor_axis=5000, ellipse=None) geos = self.test_class(satellite_height=50000, globe=globe) expected = [ '+a=10000', 'b=5000', 'h=50000', 'lat_0=0.0', 'lon_0=0.0', 'no_defs', 'proj={}'.format(self.expected_proj_name), 'units=m', 'x_0=0', 'y_0=0' ] check_proj4_params(geos, expected) assert_almost_equal(geos.boundary.bounds, (-8372.4040, -4171.5043, 8372.4040, 4171.5043), decimal=4)
def test_as_cartopy_projection(self): longitude_of_projection_origin = 90.0 ellipsoid = GeogCS(semi_major_axis=6377563.396, semi_minor_axis=6356256.909) merc_cs = Mercator(longitude_of_projection_origin, ellipsoid=ellipsoid) expected = ccrs.Mercator( central_longitude=longitude_of_projection_origin, globe=ccrs.Globe(semimajor_axis=6377563.396, semiminor_axis=6356256.909, ellipse=None)) res = merc_cs.as_cartopy_projection() self.assertEqual(res, expected)
def test_eckert_sphere_transform(name, proj, lim, expected): globe = ccrs.Globe(semimajor_axis=1.0, ellipse=None) eck = proj(central_longitude=-90.0, globe=globe) geodetic = eck.as_geodetic() other_args = {'a=1.0', 'lon_0=-90.0'} check_proj_params(name, eck, other_args) assert_almost_equal(eck.x_limits, [-lim, lim], decimal=2) assert_almost_equal(eck.y_limits, [-lim / 2, lim / 2]) result = eck.transform_point(-75.0, -50.0, geodetic) assert_almost_equal(result, expected) inverse_result = geodetic.transform_point(result[0], result[1], eck) assert_almost_equal(inverse_result, [-75.0, -50.0])
def test_eccentric_globe(self): globe = ccrs.Globe(semimajor_axis=1000, semiminor_axis=500, ellipse=None) aeqd = ccrs.AzimuthalEquidistant(globe=globe) other_args = { 'a=1000', 'b=500', 'lon_0=0.0', 'lat_0=0.0', 'x_0=0.0', 'y_0=0.0' } check_proj_params('aeqd', aeqd, other_args) assert_almost_equal(np.array(aeqd.x_limits), [-3141.59265359, 3141.59265359], decimal=6) assert_almost_equal(np.array(aeqd.y_limits), [-1570.796326795, 1570.796326795], decimal=6)
def test_eccentric_globe(self): globe = ccrs.Globe(semimajor_axis=10000, semiminor_axis=5000, ellipse=None) geos = self.test_class(satellite_height=50000, globe=globe) other_args = { 'a=10000', 'b=5000', 'h=50000', 'lat_0=0.0', 'lon_0=0.0', 'x_0=0', 'y_0=0' } self.adjust_expected_params(other_args) check_proj4_params(self.expected_proj_name, geos, other_args) assert_almost_equal(geos.boundary.bounds, (-8372.4040, -4171.5043, 8372.4040, 4171.5043), decimal=4)
def test_projection_creation(self): res = self.aea_cs.as_cartopy_projection() globe = ccrs.Globe( semimajor_axis=self.semi_major_axis, semiminor_axis=self.semi_minor_axis, ellipse=None, ) expected = ccrs.AlbersEqualArea( self.latitude_of_projection_origin, self.longitude_of_central_meridian, self.false_easting, self.false_northing, self.standard_parallels, globe=globe, ) self.assertEqual(res, expected)
def test_multiple_projections(): projections = [ ccrs.PlateCarree(), ccrs.Robinson(), ccrs.RotatedPole(pole_latitude=45, pole_longitude=180), ccrs.OSGB(approx=True), ccrs.TransverseMercator(approx=True), ccrs.Mercator(globe=ccrs.Globe(semimajor_axis=math.degrees(1)), min_latitude=-85., max_latitude=85.), ccrs.LambertCylindrical(), ccrs.Miller(), ccrs.Gnomonic(), ccrs.Stereographic(), ccrs.NorthPolarStereo(), ccrs.SouthPolarStereo(), ccrs.Orthographic(), ccrs.Mollweide(), ccrs.InterruptedGoodeHomolosine(emphasis='land'), ccrs.EckertI(), ccrs.EckertII(), ccrs.EckertIII(), ccrs.EckertIV(), ccrs.EckertV(), ccrs.EckertVI(), ] rows = np.ceil(len(projections) / 5).astype(int) fig = plt.figure(figsize=(10, 2 * rows)) for i, prj in enumerate(projections, 1): ax = fig.add_subplot(rows, 5, i, projection=prj) ax.set_global() ax.coastlines(resolution="110m") plt.plot(-0.08, 51.53, 'o', transform=ccrs.PlateCarree()) plt.plot([-0.08, 132], [51.53, 43.17], color='red', transform=ccrs.PlateCarree()) plt.plot([-0.08, 132], [51.53, 43.17], color='blue', transform=ccrs.Geodetic())
def overplot_craters(): """Overplot a lunar map with known crater outlines""" imdata_small = mio.load_lola_downsampled() smalldata = downscale_local_mean(imdata_small, factors=(10, 10)) moon_globe = ccrs.Globe(ellipse=None, # can remove after #1588/#564 semimajor_axis=Constants.moon_radius, flattening=Constants.moon_flattening) moon_crs = ccrs.Robinson(globe=moon_globe) moon_transform = ccrs.PlateCarree(globe=moon_globe) plt.rc('text', usetex=True) fig = plt.figure(figsize=(12, 6), dpi=120) ax = plt.axes(projection=moon_crs) ax.gridlines(color='#252525', linestyle='dotted') im = ax.imshow(smalldata, origin="upper", transform=moon_transform) cbar = fig.colorbar(im, orientation='vertical', shrink=0.7) cbar.set_label(r'$\mathrm{LOLA~digital~elevation~model~(m)}$') ax.set_global() # Reference: International Astronomical Union (IAU) Planetary Gazetteer # CSV data downloaded from: https://planetarynames.wr.usgs.gov/ # Check the page here for all the history behind the moon feature naming: # https://the-moon.us/wiki/IAU_nomenclature iau_fname = os.path.join(Paths.table_dir, 'iau_approved_craters.csv') #iau_fname = os.path.join(Paths.table_dir, 'iau_approved_features.csv') iau_lunar_craters = pd.read_csv(iau_fname) lons = iau_lunar_craters.Center_Longitude lats = iau_lunar_craters.Center_Latitude radii_in_meters = iau_lunar_craters.Diameter * 500 # km to m moon_geodesic = geodesic.Geodesic(radius=Constants.moon_radius, flattening=Constants.moon_flattening) craters = [] crater_proj = ccrs.Geodetic(globe=moon_globe) for lon, lat, radius in zip(lons, lats, radii_in_meters): if not radius: continue crater = moon_geodesic.circle(lon=lon, lat=lat, radius=radius, n_samples=15) craters.append(crater) geom = shapely.geometry.Polygon(crater) ax.add_geometries((geom,), crs=crater_proj, alpha=0.6, facecolor='none', edgecolor='white', linewidth=0.5) plt.savefig(os.path.join(Paths.fig_dir, "lunar_craters.png"), dpi=120)
def get_closest_satellite_vis(time): """ Get the super national 8 km visible satellite image. The image closest to the requested time will be returned. time : datetime object of image """ catalog = TDSCatalog( 'http://thredds.ucar.edu/thredds/catalog/satellite/VIS/' 'SUPER-NATIONAL_8km/current/catalog.xml') # Figure out the closest image to the requested time in the catalog datasets = list(catalog.datasets) dt_stamps = [] for dataset in datasets: fmt = 'SUPER-NATIONAL_8km_VIS_%Y%m%d_%H%M.gini' dt_stamps.append(datetime.strptime(dataset, fmt)) closest_time = min(dt_stamps, key=lambda x: abs(x - time)) index = dt_stamps.index(closest_time) # Request that image and convert it to a netCDF like dataset satellite = list(catalog.datasets.values())[index] sat_data = GiniFile( urllib.request.urlopen(satellite.access_urls['HTTPServer'])) ds = sat_data.to_dataset() # Pull out the variables we need x = ds.variables['x'][:] y = ds.variables['y'][:] channel_data = ds.variables['Visible'] time_var = ds.variables['time'] proj_var = ds.variables[channel_data.grid_mapping] # Make a globe and projection for this dataset globe = ccrs.Globe(ellipse='sphere', semimajor_axis=proj_var.earth_radius, semiminor_axis=proj_var.earth_radius) proj = ccrs.Stereographic( central_longitude=proj_var.straight_vertical_longitude_from_pole, central_latitude=proj_var.latitude_of_projection_origin, true_scale_latitude=proj_var.standard_parallel, globe=globe) timestamp = netCDF4.num2date(time_var[:].squeeze(), time_var.units) return timestamp, globe, proj, x, y, channel_data