def test_web_tiles(): extent = [-15, 0.1, 50, 60] target_domain = sgeom.Polygon([[extent[0], extent[1]], [extent[2], extent[1]], [extent[2], extent[3]], [extent[0], extent[3]], [extent[0], extent[1]]]) map_prj = cimgt.GoogleTiles().crs ax = plt.subplot(3, 2, 1, projection=map_prj) gt = cimgt.GoogleTiles() gt._image_url = types.MethodType(ctest_tiles.GOOGLE_IMAGE_URL_REPLACEMENT, gt) img, extent, origin = gt.image_for_domain(target_domain, 1) ax.imshow(np.array(img), extent=extent, transform=gt.crs, interpolation='bilinear', origin=origin) ax.coastlines(color='white') ax = plt.subplot(3, 2, 2, projection=map_prj) qt = cimgt.QuadtreeTiles() img, extent, origin = qt.image_for_domain(target_domain, 1) ax.imshow(np.array(img), extent=extent, transform=qt.crs, interpolation='bilinear', origin=origin) ax.coastlines(color='white') ax = plt.subplot(3, 2, 3, projection=map_prj) mq_osm = cimgt.MapQuestOSM() img, extent, origin = mq_osm.image_for_domain(target_domain, 1) ax.imshow(np.array(img), extent=extent, transform=mq_osm.crs, interpolation='bilinear', origin=origin) ax.coastlines() ax = plt.subplot(3, 2, 4, projection=map_prj) mq_oa = cimgt.MapQuestOpenAerial() img, extent, origin = mq_oa.image_for_domain(target_domain, 1) ax.imshow(np.array(img), extent=extent, transform=mq_oa.crs, interpolation='bilinear', origin=origin) ax.coastlines() ax = plt.subplot(3, 2, 5, projection=map_prj) osm = cimgt.OSM() img, extent, origin = osm.image_for_domain(target_domain, 1) ax.imshow(np.array(img), extent=extent, transform=osm.crs, interpolation='bilinear', origin=origin) ax.coastlines()
def plot_cartopy_cont (proj, C, spc, figtitle, amsx, amsy, amsname, outfile, aspect): ''' Funkcia na vykreslovanie rastra xarray, CONTOURS Parametre: C - geodataframe s mriezkou a hodnotami na zobrazenie v stlpci 'col' unit - string s jednotkami figtitle - nazov mapy ktory chceme zobrazit ams - tuple alebo list s x a y suradnicou stanice ktoru chceme zobrazit amsname - string s nazvom stanice ktory chceme zobrazit outfile - cesta k vyslednemu obrazku aspect - pomer vysky a sirky domeny ''' cmap = 'CMRmap_r' plt.rcParams.update({'font.size': 16}) plt.rcParams.update({'xtick.labelsize': 16}) plt.rcParams.update({'ytick.labelsize': 16}) plt.rcParams['figure.figsize'] = 15, 15*aspect mapsource = cimgt.GoogleTiles(style='satellite') extent = get_lalo_extent_from_xarray(C) ax = plt.axes(projection=proj) ax.set_extent(extent) ax.add_image(mapsource, 13, interpolation='bilinear') a = C.plot.contour(cmap=cmap, add_colorbar=False, linewidths=3) # a = c.plot( levels=levely[spc], alpha=0.5, cmap=cmap, add_colorbar=False) cb = plt.colorbar(a,label=unit_string(spc), orientation="vertical", shrink=0.62) cb.outline.set_visible(False) ax.set_title(figtitle, fontdict={'fontsize': '20', 'fontweight' : '4'}) plt.plot(amsx, amsy,'o', markerfacecolor='red', markeredgecolor='black') plt.text(amsx-400, amsy+150 , amsname, color='white', fontsize=12) plt.tight_layout() plt.savefig(outfile, dpi=300, bbox_inches='tight')
def test_google_wts(): gt = cimgt.GoogleTiles() ll_target_domain = sgeom.box(-15, 50, 0, 60) multi_poly = gt.crs.project_geometry(ll_target_domain, ccrs.PlateCarree()) target_domain = multi_poly.geoms[0] with pytest.raises(AssertionError): list(gt.find_images(target_domain, -1)) assert (tuple(gt.find_images(target_domain, 0)) == ((0, 0, 0), )) assert (tuple(gt.find_images(target_domain, 2)) == ((1, 1, 2), (2, 1, 2))) assert (list(gt.subtiles((0, 0, 0))) == [(0, 0, 1), (0, 1, 1), (1, 0, 1), (1, 1, 1)]) assert (list(gt.subtiles((1, 0, 1))) == [(2, 0, 2), (2, 1, 2), (3, 0, 2), (3, 1, 2)]) with pytest.raises(AssertionError): gt.tileextent((0, 1, 0)) assert_arr_almost(gt.tileextent((0, 0, 0)), KNOWN_EXTENTS[(0, 0, 0)]) assert_arr_almost(gt.tileextent((2, 0, 2)), KNOWN_EXTENTS[(2, 0, 2)]) assert_arr_almost(gt.tileextent((0, 2, 2)), KNOWN_EXTENTS[(0, 2, 2)]) assert_arr_almost(gt.tileextent((2, 2, 2)), KNOWN_EXTENTS[(2, 2, 2)]) assert_arr_almost(gt.tileextent((8, 9, 4)), KNOWN_EXTENTS[(8, 9, 4)])
def mapImg(img, lons, lats, vmin, vmax, pad, title): minlat = lats.min() maxlat = lats.max() minlon = lons.min() maxlon = lons.max() url = 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer/tile/{z}/{y}/{x}.jpg' image = cimgt.GoogleTiles(url=url) data_crs = ccrs.PlateCarree() fig = plt.figure() ax = plt.axes(projection=data_crs) img_handle = plt.pcolormesh(lons, lats, img, transform=data_crs) lon_range = (pad + maxlon) - (minlon - pad) lat_range = (pad + maxlat) - (minlat - pad) rangeMin = np.min(np.array([lon_range, lat_range])) tick_increment = round(rangeMin / 4, 1) ax.set_xticks(np.arange(np.floor(minlon - pad), np.ceil(maxlon + pad), tick_increment), crs=ccrs.PlateCarree()) ax.set_yticks(np.arange(np.floor(minlat - pad), np.ceil(maxlat + pad), tick_increment), crs=ccrs.PlateCarree()) lon_formatter = LongitudeFormatter(zero_direction_label=True) lat_formatter = LatitudeFormatter() ax.xaxis.set_major_formatter(lon_formatter) ax.yaxis.set_major_formatter(lat_formatter) ax.add_image(image, 8) #zoom level plt.colorbar(img_handle, fraction=0.03, pad=0.09, orientation='horizontal') plt.title(title) plt.show()
def test_image_merge(): # tests the basic image merging functionality tiles = [] for i in range(1, 4): for j in range(0, 3): tiles.append((i, j, 2)) gt = cimgt.GoogleTiles() gt._image_url = types.MethodType(ctest_tiles.GOOGLE_IMAGE_URL_REPLACEMENT, gt) images_to_merge = [] for tile in tiles: img, extent, origin = gt.get_image(tile) img = np.array(img) x = np.linspace(extent[0], extent[1], img.shape[1], endpoint=False) y = np.linspace(extent[2], extent[3], img.shape[0], endpoint=False) images_to_merge.append([img, x, y, origin]) img, extent, origin = cimgt._merge_tiles(images_to_merge) ax = plt.axes(projection=gt.crs) ax.set_global() ax.coastlines() ax.imshow(img, origin=origin, extent=extent, alpha=0.5) return ax.figure
def background(extent=[-81.15, -80.51, 26.65, 27.24], request=cimgt.GoogleTiles(style='satellite'), ax=None, projection=None, out=False): # Plots lake O background map if request is None: projection = projection image = False else: projection = request.crs image = True if ax is None: fig = plt.figure(figsize=(10, 10)) ax = plt.axes(projection=projection) ax.set_extent(extent) try: gl = ax.gridlines(draw_labels=True, alpha=0.2) gl.xlabels_top = gl.ylabels_right = False gl.xformatter = LONGITUDE_FORMATTER gl.yformatter = LATITUDE_FORMATTER except: print('Projection does not allow gridlines') if image: ax.add_image(request, 10) if out is True: return fig, ax
def tester_bg3(): """specify extent, and use caropy.io.img_tiles.GootleTiles""" from plotter import calpost_reader as reader import cartopy.crs as ccrs import cartopy.io.img_tiles as cimgt with open('../data/tseries_ch4_1min_conc_co_fl.dat') as f: dat = reader.Reader(f, slice(60 * 12, 60 * 12 + 10)) # background bext = [-11344200.0, -11338900.0, 3724300.0, 3731100.0] plotter_options = { 'contour_options': { 'alpha': .2 }, 'extent': bext, 'projection': ccrs.epsg(3857), # GoogleMap, we may need license 'customize_once': lambda p: p.ax.add_image(cimgt.GoogleTiles(style='satellite'), 15) } x = dat['x'] * 1000 y = dat['y'] * 1000 p = Plotter(dat['v'], dat['ts'], x=x, y=y, plotter_options=plotter_options) p(outdir / 'test_bg3.png')
def test_google_wts(): gt = cimgt.GoogleTiles() extent = [-15, 00, 50, 60] target_domain = shapely.geometry.Polygon([[extent[0], extent[1]], [extent[2], extent[1]], [extent[2], extent[3]], [extent[0], extent[3]], [extent[0], extent[1]]]) with assert_raises(AssertionError): list(gt.find_images(target_domain, -1)) assert_equal(tuple(gt.find_images(target_domain, 0)), ((0, 0, 0), )) assert_equal(tuple(gt.find_images(target_domain, 2)), ((1, 1, 2), (2, 1, 2))) assert_equal(list(gt.subtiles((0, 0, 0))), [(0, 0, 1), (0, 1, 1), (1, 0, 1), (1, 1, 1)]) assert_equal(list(gt.subtiles((1, 0, 1))), [(2, 0, 2), (2, 1, 2), (3, 0, 2), (3, 1, 2)]) with assert_raises(AssertionError): gt.tileextent((0, 1, 0)) assert_equal(gt.tileextent((0, 0, 0)), (-180.0, 180.0, 179.41035067677481, -179.41035067677487)) assert_equal(gt.tileextent((2, 0, 2)), (0.0, 90.0, 179.41035067677481, 89.705175338387392)) assert_equal(gt.tileextent((0, 2, 2)), (-180.0, -90.0, -2.8421709430404007e-14, -89.70517533838742)) assert_equal(gt.tileextent((2, 2, 2)), (0.0, 90.0, -2.8421709430404007e-14, -89.70517533838742)) assert_equal(gt.tileextent((8, 9, 4)), (0.0, 22.5, -22.426293834596891, -44.852587669193753))
def save_map_image(loc): """ Code adapted from https://ocefpaf.github.io/python4oceanographers/blog/2015/06/22/osm/ Grab google maps image covering geographic area given by 'extent' and save image to file for use as background map. Use this function to generate the basemap image. It is also possible to plot data directly on the cartopy object (map_ax) which provides higher resolution, however that requires an internet connection onsite. :param loc: path defining location to save image :return: nothing """ import cartopy.io.img_tiles as cimgt extent = [left_lon, right_lon, bottom_lat, top_lat] request = cimgt.GoogleTiles() map_fig, map_ax = make_map(projection=request.crs) map_ax.set_extent(extent) map_ax.add_image(request, 10) # put star at launch site map_ax.plot(home_lon, home_lat, marker='*', color='black', markersize=10, transform=ccrs.Geodetic()) map_ax.savefig(loc)
def scale_bar(ax, length, location=(0.5, 0.05), linewidth=3): """ ax is the axes to draw the scalebar on. location is center of the scalebar in axis coordinates ie. 0.5 is the middle of the plot length is the length of the scalebar in km. linewidth is the thickness of the scalebar. """ #Projection in metres, need to change this to suit your own figure utm = img_tiles.GoogleTiles().crs #ccrs.UTM(36) #Get the extent of the plotted area in coordinates in metres x0, x1, y0, y1 = ax.get_extent(utm) #Turn the specified scalebar location into coordinates in metres sbcx, sbcy = x0 + (x1 - x0) * location[0], y0 + (y1 - y0) * location[1] #Generate the x coordinate for the ends of the scalebar bar_xs = [sbcx - length * 500, sbcx + length * 500] #Plot the scalebar ax.plot(bar_xs, [sbcy, sbcy], transform=utm, color='k', linewidth=linewidth) #Plot the scalebar label ax.text(sbcx, sbcy, str(length) + ' km', transform=utm, horizontalalignment='center', verticalalignment='bottom', size=13)
def background(): """ This comes from the tests of the Cartopy library. It ensures that the background will never be changed by google and is only used in tests. """ gt = cimgt.GoogleTiles() gt._image_url = types.MethodType(GOOGLE_IMAGE_URL_REPLACEMENT, gt) return gt
def gmaps(): request = cimgt.GoogleTiles() fig, ax = make_map(projection=request.crs) extent = [-50, -47.4, -30.5, -25] ax.set_extent(extent) ax.add_image(request, 10) plt.show()
def mapImg(img, lons, lats, vmin, vmax, pad, zoom, title): minlat = lats.min() maxlat = lats.max() minlon = lons.min() maxlon = lons.max() bg = 'World_Imagery' url = 'https://server.arcgisonline.com/ArcGIS/rest/services/' + bg + '/MapServer/tile/{z}/{y}/{x}.jpg' image = cimgt.GoogleTiles(url=url) data_crs = ccrs.PlateCarree() fig = plt.figure(figsize=(6, 8)) ax = plt.axes(projection=data_crs) img_handle = plt.pcolormesh(lons, lats, img, vmin=vmin, vmax=vmax, transform=data_crs, rasterized=True) lon_range = (pad + maxlon) - (minlon - pad) lat_range = (pad + maxlat) - (minlat - pad) rangeMin = np.min(np.array([lon_range, lat_range])) tick_increment = round(rangeMin / 4, 1) import matplotlib.ticker as mticker from cartopy.mpl.ticker import (LongitudeFormatter, LatitudeFormatter, LatitudeLocator) gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True, linewidth=0.5, color='gray', alpha=0.5, linestyle='--') gl.xlocator = mticker.FixedLocator( np.arange(np.floor(minlon - pad), np.ceil(maxlon + pad), tick_increment)) gl.ylocator = LatitudeLocator() gl.xformatter = LongitudeFormatter() gl.yformatter = LatitudeFormatter() gl.ylabel_style = {'size': 8, 'color': 'black'} gl.xlabel_style = {'size': 8, 'color': 'black'} gl.top_labels = False gl.right_labels = False # ax.set_xticks(np.arange(np.floor(minlon-pad),np.ceil(maxlon+pad),tick_increment), crs=ccrs.PlateCarree()) # ax.set_yticks(np.arange(np.floor(minlat-pad),np.ceil(maxlat+pad),tick_increment), crs=ccrs.PlateCarree()) # ax.lon_formatter = LongitudeFormatter(zero_direction_label=True) # lat_formatter = LatitudeFormatter() # ax.xlabel_style = {'size': 15, 'color': 'gray'} # ax.xlabel_style = {'color': 'red', 'weight': 'bold'} # ax.xaxis.set_major_formatter(lon_formatter) # ax.yaxis.set_major_formatter(lat_formatter) ax.add_image(image, zoom) #zoom level plt.colorbar(img_handle, fraction=0.03, pad=0.05, orientation='horizontal') plt.title(title) plt.show()
def test_web_tiles(): extent = [-15, 0.1, 50, 60] target_domain = shapely.geometry.Polygon([[extent[0], extent[1]], [extent[2], extent[1]], [extent[2], extent[3]], [extent[0], extent[3]], [extent[0], extent[1]]]) ax = plt.subplot(3, 2, 1, projection=ccrs.Mercator()) gt = cimgt.GoogleTiles() img, extent, origin = gt.image_for_domain(target_domain, 1) ax.imshow(np.array(img), extent=extent, transform=ccrs.Mercator(), interpolation='bilinear', origin=origin) ax.coastlines(color='white') ax = plt.subplot(3, 2, 2, projection=ccrs.Mercator()) qt = cimgt.QuadtreeTiles() img, extent, origin = qt.image_for_domain(target_domain, 1) ax.imshow(np.array(img), extent=extent, transform=ccrs.Mercator(), interpolation='bilinear', origin=origin) ax.coastlines(color='white') ax = plt.subplot(3, 2, 3, projection=ccrs.Mercator()) mq_osm = cimgt.MapQuestOSM() img, extent, origin = mq_osm.image_for_domain(target_domain, 1) ax.imshow(np.array(img), extent=extent, transform=ccrs.Mercator(), interpolation='bilinear', origin=origin) ax.coastlines() ax = plt.subplot(3, 2, 4, projection=ccrs.Mercator()) mq_oa = cimgt.MapQuestOpenAerial() img, extent, origin = mq_oa.image_for_domain(target_domain, 1) ax.imshow(np.array(img), extent=extent, transform=ccrs.Mercator(), interpolation='bilinear', origin=origin) ax.coastlines() ax = plt.subplot(3, 2, 5, projection=ccrs.Mercator()) osm = cimgt.OSM() img, extent, origin = osm.image_for_domain(target_domain, 1) ax.imshow(np.array(img), extent=extent, transform=ccrs.Mercator(), interpolation='bilinear', origin=origin) ax.coastlines()
def plot_google_map(extent, size=(13, 13)): plt.figure(figsize=size) img = cimgt.GoogleTiles() ax = plt.axes(projection=img.crs) ax.set_extent(extent) ax.add_image(img, 9, interpolation='bicubic') # should be 7
def test_tile_find_images(): gt = cimgt.GoogleTiles() # Test the find_images method on a GoogleTiles instance. ll_target_domain = sgeom.box(-10, 50, 10, 60) multi_poly = gt.crs.project_geometry(ll_target_domain, ccrs.PlateCarree()) target_domain = multi_poly.geoms[0] assert (list(gt.find_images(target_domain, 4)) == [(7, 4, 4), (7, 5, 4), (8, 4, 4), (8, 5, 4)])
def arcgisimage(ax, service="World_Shaded_Relief", zoom=1): """ Duplicate the functionality of Basemap `arcgisimage()` function. My favorite background is the "World_Shaded_Relief" """ url = 'https://server.arcgisonline.com/ArcGIS/rest/services/' \ '%s/MapServer/tile/{z}/{y}/{x}.jpg' % service image = cimgt.GoogleTiles(url=url) ax.add_image(image, zoom)
def gen_nest(): from_config = cimg_nest.NestedImageCollection.from_configuration files = [['aerial z0 test', os.path.join(_TEST_DATA_DIR, 'z_0')], ['aerial z1 test', os.path.join(_TEST_DATA_DIR, 'z_1')], ] crs = cimgt.GoogleTiles().crs nest_z0_z1 = from_config('aerial test', crs, files, glob_pattern='*.png', img_class=RoundedImg) return nest_z0_z1
def make_cartopy(self, projection, ax=None, figsize=(10, 10)): self.projection = projection if ax is None: # Create figure instance fig, ax = plt.subplots(figsize=figsize, subplot_kw=dict(projection=projection)) Lat_1 = self.mapcorners[1] Lat_2 = self.mapcorners[3] Lon_1 = self.mapcorners[0] Lon_2 = self.mapcorners[2] xlocs_1 = ((round(Lon_1 / 10)) - 1) * 10 xlocs_2 = ((round(Lon_2 / 10)) + 1) * 10 ylocs_1 = ((round(Lat_1 / 10)) - 1) * 10 ylocs_2 = ((round(Lat_2 / 10)) + 1) * 10 extent = [Lon_1, Lon_2, Lat_1, Lat_2] x_space = self.latlon_spacing[0] y_space = self.latlon_spacing[1] xlocs = np.arange(xlocs_1, xlocs_2, x_space) ylocs = np.arange(ylocs_1, ylocs_2, y_space) import cartopy.io.img_tiles as cimgt if self.bg_service == 'Stamen': request = cimgt.Stamen(style=self.bg_style) ax.set_extent(extent, crs=self.projection) ax.add_image(request, self.xsize, interpolation='spline36') if self.bg_service == 'OSM': request = cimgt.OSM() ax.set_extent(extent, crs=self.projection) ax.add_image(request, self.xsize, interpolation='spline36') if self.bg_service == 'Google': request = cimgt.GoogleTiles(style=self.bg_style) ax.set_extent(extent) ax.add_image(request, self.xsize, interpolation='spline36') if self.bg_service == 'Esri': request = cimgt.Esri(style=self.bg_style) ax.set_extent(extent, crs=self.projection) ax.add_image(request, self.xsize, interpolation='spline36') gl = ax.gridlines(draw_labels=self.draw_labels, xlocs=xlocs, ylocs=ylocs, alpha=self.alpha_gl) gl.ylabels_left = self.ylabels_left gl.ylabels_right = self.ylabels_right gl.xlabels_top = self.xlabels_top gl.xlabels_bottom = self.xlabels_bottom gl.xformatter = LONGITUDE_FORMATTER gl.yformatter = LATITUDE_FORMATTER gl.xlabel_style = self.xlabel_style gl.ylabel_style = self.ylabel_style return ax
def test_image_for_domain(): gt = cimgt.GoogleTiles() gt._image_url = types.MethodType(GOOGLE_IMAGE_URL_REPLACEMENT, gt) ll_target_domain = sgeom.box(-10, 50, 10, 60) multi_poly = gt.crs.project_geometry(ll_target_domain, ccrs.PlateCarree()) target_domain = multi_poly.geoms[0] _, extent, _ = gt.image_for_domain(target_domain, 6) ll_extent = ccrs.Geodetic().transform_points(gt.crs, np.array(extent[:2]), np.array(extent[2:])) assert_arr_almost(ll_extent[:, :2], [[-11.25, 48.92249926], [11.25, 61.60639637]])
def setup_axis(ax=None, extent=None, projection=None, background=False, zoom=10): """Setup a ``matplotlib.pyplot.Axes`` instance. Args: ax (``matplotlib.pyplot.Axes``, optional): The axis object to update. extent (:py:class:`~gps_data_analyzer.raster_analysis.Extent` or :py:obj:`list`\ of :py:obj:`float`): The extent to set. projection (:py:class:`cartopy.crs.Projection`, optional): The projection of the axis (:py:class:`~cartopy.crs.PlateCarree` by default). background (bool or :py:class:`cartopy.io.img_tiles.GoogleWTS`, optional): If true, a default background is added using Google Satellite. If a :obj:`~cartopy.io.img_tiles.GoogleWTS` object is given, it is used. zoom (int, mandatory if :py:obj:`background` is not :py:obj:`None`): The zoom value used to generate the background. """ # Define projection if projection is None: projection = ccrs.PlateCarree() # Create the figure instance if ax is None: fig = plt.figure() # Create a GeoAxes in the tile's projection. ax = fig.add_subplot(1, 1, 1, projection=projection) else: fig = None # pragma: no cover # Limit the extent of the map to the min/max coords if extent is not None: # pragma: no cover - Should usually not happen ax.set_extent(extent, crs=projection) # Create a terrain background instance if background is True: background = cimgt.GoogleTiles(style="satellite") # pragma: no cover # Add the background data if background is not False: ax.add_image(background, zoom) return fig, ax
def plot_map(longitude_lim, latitude_lim, map_quality=11): """ Plot map. Parameters ---------- longitude_lim : list(2) latitude_lim : list(2) map_quality : int Map rendering quality. 6 is very bad, 10 is ok, 12 is good, 13 is very good, 14 excellent. """ # Map extent eps = 0*0.01 extent = [longitude_lim[0] - eps, longitude_lim[1] + eps, latitude_lim[0] - eps, latitude_lim[1] + eps] # Plot map of Stockholm map_design = 'StamenTerrain' if map_design == 'GoogleTiles': request = cimgt.GoogleTiles() elif map_design == 'QuadtreeTiles': request = cimgt.QuadtreeTiles() elif map_design == 'StamenTerrain': request = cimgt.Stamen('terrain-background') else: # Map designs 'OSM' and 'MapboxTiles' do not work raise Exception('Untested map design') ax = plt.axes(projection=request.crs) gl = ax.gridlines(draw_labels=True, alpha=0., linewidth=0, linestyle='-') gl.top_labels = False gl.right_labels = False gl.xformatter = LONGITUDE_FORMATTER gl.yformatter = LATITUDE_FORMATTER gl.xlabel_style = {'size': 10, 'color': 'black'} gl.ylabel_style = {'size': 10, 'color': 'black', 'weight': 'normal'} ax.set_extent(extent) ax.add_image(request, map_quality)
def tianditu(self, ax=None, scale=5, map_type='VECTOR', token=None): """ 增加天地图作为地图背景. http://lbs.tianditu.gov.cn/server/MapService.html Parameters: ---------------------- ax Axes instance, if not None then overrides the default axes instance. scale Map scale, large value for detail map. token Tianditu api token, if not given, default token will be used. type map type, 'VECTOR', 'TERAIN', or 'SATELLITE'. """ #Get current axes if not specified ax = ax or self._check_ax() #Check token if token is None: # token = CONFIG.CONFIG['TIANDITU']['token'] token = '4267820f43926eaf808d61dc07269beb' #Create image tile URL map_types = { 'VECTOR': 'vec_w', 'TERAIN': 'ter_w', 'SATELLITE': 'img_w' } map_type = map_types.get(map_type.upper(), 'VECTOR') url = "http://t3.tianditu.gov.cn/DataServer?T=%s&x={x}&y={y}&l={z}&tk=%s" % ( map_type, token) # add image image = cimgt.GoogleTiles(url=url) return ax.add_image(image, scale)
def arcgis(self, ax=None, scale=4, map_type='World_Physical_Map', service='server.arcgisonline.com'): """ 以ArcGIS地图在线服务为背景. refer to: https://server.arcgisonline.com/arcgis/rest/services http://map.geoq.cn/arcgis/rest/services Args: ax (object, optional): Axes instance, if not None then overrides the default axes instance. scale (int, optional): Map scale, large value for detail map, defaults to 5. type (str, optional): Map type string. Defaults to 'World_Physical_Map'. 'server.arcgisonline.com', scale 0~8, NatGeo_World_Map, USA_Topo_Maps, World_Imagery, World_Physical_Map, World_Shaded_Relief, World_Street_Map, World_Terrain_Base, World_Topo_Map 'map.geoq.cn', scale 0-19 ChinaOnlineCommunity_Mobile, ChinaOnlineCommunityENG, ChinaOnlineCommunity, ChinaOnlineStreetGray, ChinaOnlineStreetPurplishBlue, ChinaOnlineStreetWarm service (str, optional): Map service, Detaults to 'server.arcgisonline.com'. """ #Get current axes if not specified ax = ax or self._check_ax() #Create image tile URL url = "http://%s/arcgis/rest/services/%s/MapServer/tile/{z}/{y}/{x}" % ( service, map_type) # add image image = cimgt.GoogleTiles(url=url) return ax.add_image(image, scale)
def test_google_wts(): gt = cimgt.GoogleTiles() extent = [-15, 0.1, 50, 60] target_domain = shapely.geometry.Polygon([[extent[0], extent[1]], [extent[2], extent[1]], [extent[2], extent[3]], [extent[0], extent[3]], [extent[0], extent[1]]]) with assert_raises(AssertionError): list(gt.find_images(target_domain, -1)) assert_equal(tuple(gt.find_images(target_domain, 0)), ((0, 0, 0), )) assert_equal(tuple(gt.find_images(target_domain, 2)), ((1, 1, 2), (2, 1, 2))) assert_equal(list(gt.subtiles((0, 0, 0))), [(0, 0, 1), (0, 1, 1), (1, 0, 1), (1, 1, 1)]) assert_equal(list(gt.subtiles((1, 0, 1))), [(2, 0, 2), (2, 1, 2), (3, 0, 2), (3, 1, 2)]) with assert_raises(AssertionError): gt.tileextent((0, 1, 0)) assert_arr_almost(gt.tileextent((0, 0, 0)), (-180.0, 180.0, 179.02740096396502, -179.02740096396491)) assert_arr_almost(gt.tileextent((2, 0, 2)), (0.0, 90.0, 179.02740096396502, 89.513700481982539)) assert_arr_almost(gt.tileextent( (0, 2, 2)), (-180.0, -90.0, 5.6843418860808015e-14, -89.513700481982426)) assert_arr_almost(gt.tileextent((2, 2, 2)), (0.0, 90.0, 5.6843418860808015e-14, -89.513700481982426)) assert_arr_almost(gt.tileextent((8, 9, 4)), (0.0, 22.5, -22.37842512, -44.75685024)) # <- zoom 4, contains cape town.
def test_google_tile_styles(): """ Tests that setting the Google Maps tile style works as expected. This is essentially just assures information is properly propagated through the class structure. """ reference_url = ("https://mts0.google.com/vt/lyrs={style}@177000000&hl=en" "&src=api&x=1&y=2&z=3&s=G") tile = ["1", "2", "3"] # Default is street. gt = cimgt.GoogleTiles() url = gt._image_url(tile) assert reference_url.format(style="m") == url # Street gt = cimgt.GoogleTiles(style="street") url = gt._image_url(tile) assert reference_url.format(style="m") == url # Satellite gt = cimgt.GoogleTiles(style="satellite") url = gt._image_url(tile) assert reference_url.format(style="s") == url # Terrain gt = cimgt.GoogleTiles(style="terrain") url = gt._image_url(tile) assert reference_url.format(style="t") == url # Streets only gt = cimgt.GoogleTiles(style="only_streets") url = gt._image_url(tile) assert reference_url.format(style="h") == url # Exception is raised if unknown style is passed. with pytest.raises(ValueError): cimgt.GoogleTiles(style="random_style")
def test_nest(nest_from_config): crs = cimgt.GoogleTiles().crs z0 = cimg_nest.ImageCollection('aerial z0 test', crs) z0.scan_dir_for_imgs(os.path.join(_TEST_DATA_DIR, 'z_0'), glob_pattern='*.png', img_class=RoundedImg) z1 = cimg_nest.ImageCollection('aerial z1 test', crs) z1.scan_dir_for_imgs(os.path.join(_TEST_DATA_DIR, 'z_1'), glob_pattern='*.png', img_class=RoundedImg) z2 = cimg_nest.ImageCollection('aerial z2 test', crs) z2.scan_dir_for_imgs(os.path.join(_TEST_DATA_DIR, 'z_2'), glob_pattern='*.png', img_class=RoundedImg) # make sure all the images from z1 are contained by the z0 image. The # only reason this might occur is if the tfw files are handling # floating point values badly for img in z1.images: if not z0.images[0].bbox().contains(img.bbox()): raise OSError( 'The test images aren\'t all "contained" by the z0 images, ' 'the nest cannot possibly work.\n' f'img {img!s} not contained by {z0.images[0]!s}\n' f'Extents: {img.extent!s}; {z0.images[0].extent!s}') nest_z0_z1 = cimg_nest.NestedImageCollection('aerial test', crs, [z0, z1]) nest = cimg_nest.NestedImageCollection('aerial test', crs, [z0, z1, z2]) z0_key = ('aerial z0 test', z0.images[0]) assert z0_key in nest_z0_z1._ancestry.keys() assert len(nest_z0_z1._ancestry) == 1 # check that it has figured out that all the z1 images are children of # the only z0 image for img in z1.images: key = ('aerial z0 test', z0.images[0]) assert ('aerial z1 test', img) in nest_z0_z1._ancestry[key] x1_y0_z1, = [ img for img in z1.images if img.filename.endswith('z_1/x_1_y_0.png') ] assert (1, 0, 1) == _tile_from_img(x1_y0_z1) assert ([(2, 0, 2), (2, 1, 2), (3, 0, 2), (3, 1, 2)] == sorted([ _tile_from_img(img) for z, img in nest.subtiles(('aerial z1 test', x1_y0_z1)) ])) # check that the the images in the nest from configuration are the # same as those created by hand. for name in nest_z0_z1._collections_by_name.keys(): for img in nest_z0_z1._collections_by_name[name].images: collection = nest_from_config._collections_by_name[name] assert img in collection.images assert nest_z0_z1._ancestry == nest_from_config._ancestry # check that a nest can be pickled and unpickled easily. s = io.BytesIO() pickle.dump(nest_z0_z1, s) s.seek(0) nest_z0_z1_from_pickle = pickle.load(s) assert nest_z0_z1._ancestry == nest_z0_z1_from_pickle._ancestry
import cartopy.io.img_tiles as cimgt url = "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}" esri = cimgt.GoogleTiles(url=url) fig, ax = plt.subplots( figsize=(14, 14), subplot_kw={"projection": esri.crs} ) ax.set_extent(extent) ax.add_image(esri, 11) # ax.images[0].write_png("data/esri-image-floripa.png") data = sul.groupby("balneario_nome").mean() ax.plot( data["lon"], data["lat"], linestyle="none", marker="o", label="Sul", transform=ccrs.PlateCarree(), ) data = norte.groupby("balneario_nome").mean() ax.plot( data["lon"], data["lat"], linestyle="none", marker="o", label="Norte", transform=ccrs.PlateCarree() );
def plot_from_wps( patch_nml_path: str, figFilename: str = None, display: bool = True, useCartopy: bool = True, TileService: bool = False, xyzTiles: str = 'http://tile.openstreetmap.org/{z}/{x}/{y}.png'): # namelist options to be passed as kwargs dict to projparams namelist_patch = f90nml.read(patch_nml_path) # Strip out all namelist classes plot_options = namelist_patch['geogrid'] plot_options = dict(plot_options) # get options not used by proj_params e_we = plot_options['e_we'] e_sn = plot_options['e_sn'] # Remove unnescesary information keys_to_keep = [ 'ref_lat', 'ref_lon', 'dx', 'dy', 'map_proj', 'truelat1', 'truelat2', 'stand_lon' ] keys_to_keep = set(keys_to_keep) all_keys = set(plot_options.keys()) keys_to_delete = all_keys - keys_to_keep for key in keys_to_delete: del plot_options[key] tic = time.time() # Gather parameters from WPS namelist and submit to function projparams = build_projparams(**plot_options, pole_lat=90.0, pole_lon=0.0, known_x=0.0, known_y=0.0) # Resolve parameter inconsistencies # ################################################################## # # # MOAD_CEN_LAT is calculated internally by WPS, not provided in the WPS namelist. # wrf-python requires either a defined MOAD_CEN_LAT or CEN_LAT to build the CRS. # The projection origin (MOAD_CEN_LAT,STAND_LON) is not necessarily going to be # identical to each grid origin (like with nested or subsetted domains), thus # MOAD_CEN_LAT can be anywhere (?). # # Make up a MOAD_CEN_LAT in order to use wrf-python if projparams['MOAD_CEN_LAT'] is None: # Fill with a dummy latitude (average the standard parallell latitudes) somelat = 0.5 * (projparams['TRUELAT1'] + projparams['TRUELAT2']) projparams['MOAD_CEN_LAT'] = somelat # ################################################################## # # ################################################################## # # Hack to get the projection away from the ref_lat and ref_lon # # The issue is that if ref_lat and ref_lon are provided to the projection.getproj # function, then they are not used in building the projection definition, but # they do get used later on by the _ll_to_xy and _xy_to_ll functions as the CRS origin. # That causes issues when trying to offset the grid origin from it's coordinate # system origin. To solve, set REF_LAT and REF_LON to the CRS origin # (MOAD_CEN_LAT,STAND_LON) and that will persist the CRS origin even when using # _ll_to_xy and _xy_to_ll functions. # reflat = projparams[ 'REF_LAT'] # To be used later in calculating domain center xy reflon = projparams[ 'REF_LON'] # To be used later in calculating domain center xy # # Set the ref_lat and ref_lon parameters to match MOAD_CEN_LAT and STAND_LON for # the purposes of building a coordinate system projparams['REF_LAT'] = projparams['MOAD_CEN_LAT'] projparams['REF_LON'] = projparams['STAND_LON'] # ################################################################## # # ################################################################## # # Use the wrf-python funcitonality to define the coordinate system given the input parameters inproj = projection.getproj(**projparams) wrf_proj4 = inproj.proj4() # Test the coordinate system definition print('Proj4: %s' % wrf_proj4) # ################################################################## # # ################################################################## # # the wrf-python functions _xy_to_ll and _ll_to_xy provide the xy in cell coordinates, # not projected coordinates. Be sure to convert to projected coordinates by multiplying # by the resolution. # center_xy = latlonutils._ll_to_xy(reflat, reflon, as_int=False, **projparams) center_ll = latlonutils._xy_to_ll(center_xy[0], center_xy[0], as_int=False, **projparams) center_xy[0] = center_xy[0] * projparams[ 'DX'] # Rescale from pixel coords to projected coords center_xy[1] = center_xy[1] * projparams[ 'DY'] # Rescale from pixel coords to projected coords print('Grid center x,y: %s' % center_xy) print('Grid center lat,lon: %s' % center_ll) # ################################################################## # # ################################################################## # # Build exent and handle any false_easting and false_northings nrows = e_sn - 1 # Subtract 1 for the number of rows in y ncols = e_we - 1 # Subtract 1 for the number of columns in x minX, maxX, minY, maxY = find_corner(projparams['DX'], projparams['DY'], nrows, ncols, 2, xOffset=center_xy[0], yOffset=center_xy[1]) xbbox = [minX, minX, maxX, maxX, minX] # Used to draw a box in ax.plot() ybbox = [minY, maxY, maxY, minY, minY] # Used to draw a box in ax.plot() img_extent = find_corner(projparams['DX'], projparams['DY'], nrows, ncols, 1.75, xOffset=center_xy[0], yOffset=center_xy[1]) print('Domain extent: %s' % [minX, maxX, minY, maxY]) # ################################################################## # # --- PLOTTING --- # wrf_crs = inproj.cartopy() # Create a cartopy projection object # Create the plot image fig = plt.figure(figsize=(12, 12)) ax = fig.add_subplot(1, 1, 1, projection=wrf_crs) ax.set_extent(img_extent, crs=wrf_crs) figsize = fig.get_size_inches() * fig.dpi # Figure size in pixels # Add the polygon boundary extent ax.plot(xbbox, ybbox, color='red', transform=wrf_crs) #You have to calculate the tile zoom level manually dist = img_extent[1] - img_extent[ 0] # Horizontal distance of the map image percent_of_image = 0.85 # The percent of the image a horizontal line should cover zoomLev = calculateZoom(figsize[1], percent_of_image, center_ll[0], dist) # Request the XYZ tiles request = cimgt.GoogleTiles(url=xyzTiles) ax.add_image(request, zoomLev, interpolation='bicubic') ax.gridlines() if figFilename is not None: plt.savefig(figFilename) if display: plt.show() print('Process completed after %3.2f seconds.' % (time.time() - tic))
def draw_total_precipitation(prep, map_extent=(107., 112, 23.2, 26.5), back_image='terrain-background', back_image_zoom=8, title="降水量实况图", draw_station=True, station_info='cities', station_size=22, just_contourf=False): """ 该程序用于显示多日的累积降水量分布特征, 2020/6/7按业务要求制作. Args: ax (matplotlib.axes.Axes): the `Axes` instance used for plotting. prep (dictionary): precipitation, dictionary: {'lon': 1D array, 'lat': 1D array, 'data': 2D array} map_extent (tuple, optional): (lonmin, lonmax, latmin, latmax),. Defaults to (107., 112, 23.2, 26.5). back_image (str, opional): the background image name. Default is stamen 'terrain-background', else is arcgis map server 'World_Physical_Map' (max zoom level is 8) back_image_zoom (int, optional): the zoom level for background image. Defaults to 8. draw_station (bool, optional): draw station name. Defaults to True. station_info (str, optional): station information, 'cities' is 260 city names, or province captial shows. station_size (int, optional): station font size. Defaults to 22. title (str, optional): title string. Defaults to "降水量实况图". Example: import pandas as pd from nmc_met_graphics.plot.precipitation import draw_total_precipitation from nmc_met_io.retrieve_micaps_server import get_model_grids # read data times = pd.date_range(start = pd.to_datetime('2020-06-02 08:00'), end = pd.to_datetime('2020-06-07 08:00'), freq='1H') dataset = get_model_grids("CLDAS/RAIN01_TRI_DATA_SOURCE", times.strftime("%y%m%d%H.000")) data = dataset.sum(dim="time") data['data'].values[data['data'].values > 2400.0] = np.nan prep = {'lon': data['lon'].values, 'lat': data['lat'].values, 'data': data['data'].values} # draw the figure draw_total_precipitation(prep); """ # set figure size fig = plt.figure(figsize=(16, 14.5)) # set map projection datacrs = ccrs.PlateCarree() mapcrs = ccrs.LambertConformal( central_longitude=np.mean(map_extent[0:1]), central_latitude=np.mean(map_extent[2:3]), standard_parallels=(30, 60)) ax = plt.axes((0.1, 0.08, 0.85, 0.92), projection=mapcrs) ax.set_extent(map_extent, crs=datacrs) # add map background add_china_map_2cartopy(ax, name='province', edgecolor='k', lw=1) add_china_map_2cartopy(ax, name='river', edgecolor='cyan', lw=1) if back_image == 'terrain-background': stamen_terrain = cimg.Stamen('terrain-background') ax.add_image(stamen_terrain, back_image_zoom) else: image = cimg.GoogleTiles(url="https://server.arcgisonline.com/arcgis/rest/services/World_Physical_Map/MapServer/tile/{z}/{y}/{x}.jpg") ax.add_image(image, back_image_zoom) # set colors and levels clevs = [50, 100, 200, 300, 400, 500, 600] colors = ['#6ab4f1', '#0001f6', '#f405ee', '#ffa900', '#fc6408', '#e80000', '#9a0001'] linewidths = [1, 1, 2, 2, 3, 4, 4] cmap, norm = mpl.colors.from_levels_and_colors(clevs, colors, extend='max') # draw precipitation contour map x, y = np.meshgrid(prep['lon'], prep['lat']) if just_contourf: _ = ax.contourf( x, y, np.squeeze(prep['data']), clevs, norm=norm, cmap=cmap, transform=datacrs, extend='max', alpha=0.5) else: _ = ax.contourf( x, y, np.squeeze(prep['data']), clevs, norm=norm, cmap=cmap, transform=datacrs, extend='max', alpha=0.1) con2 = ax.contour( x, y, np.squeeze(prep['data']), clevs, norm=norm, cmap=cmap, transform=datacrs, linewidths=linewidths) # add path effects plt.setp(con2.collections, path_effects=[ path_effects.SimpleLineShadow(), path_effects.Normal()]) # add title and legend font = FontProperties(family='Microsoft YaHei', size=32) ax.set_title('降水量实况图(累计降水: 6月02日—6月06日)', loc='center', fontproperties=font) font = FontProperties(family='Microsoft YaHei', size=16) plt.legend([mpatches.Patch(color=b) for b in colors],[ '50~100 毫米', '100~200 毫米', '200-300 毫米', '300~400 毫米', '400~500 毫米', '500~600 毫米', '>=600毫米'], prop=font) # add city information if draw_station: if station_info == 'cities': cities = pd.read_csv(pkg_resources.resource_filename( 'nmc_met_graphics', "resources/stations/cma_city_station_info.dat"), delimiter=r"\s+") else: cities = pd.read_csv(pkg_resources.resource_filename( 'nmc_met_graphics', "resources/stations/provincial_capital.csv")) font = FontProperties(family='SimHei', size=22, weight='bold') geodetic_transform = ccrs.Geodetic()._as_mpl_transform(ax) for _, row in cities.iterrows(): text_transform = offset_copy(geodetic_transform, units='dots', x=-5) ax.plot(row['lon'], row['lat'], marker='o', color='white', markersize=8, alpha=0.7, transform=datacrs) ax.text(row['lon'], row['lat'], row['city_name'], clip_on=True, verticalalignment='center', horizontalalignment='right', transform=text_transform, fontproperties=font, color='white', path_effects=[ path_effects.Stroke(linewidth=1, foreground='black'),path_effects.Normal()]) return fig