def test_polygon_interiors(): ax = plt.subplot(211, projection=ccrs.PlateCarree()) ax.coastlines() ax.set_global() pth = Path([[0, -45], [60, -45], [60, 45], [0, 45], [0, 45], [10, -20], [10, 20], [40, 20], [40, -20], [10, 20]], [1, 2, 2, 2, 79, 1, 2, 2, 2, 79]) patches_native = [] patches = [] for geos in cpatch.path_to_geos(pth): for pth in cpatch.geos_to_path(geos): patches.append(mpatches.PathPatch(pth)) # buffer by 10 degrees (leaves a small hole in the middle) geos_buffered = geos.buffer(10) for pth in cpatch.geos_to_path(geos_buffered): patches_native.append(mpatches.PathPatch(pth)) # Set high zorder to ensure the polygons are drawn on top of coastlines. collection = PatchCollection(patches_native, facecolor='red', alpha=0.4, transform=ax.projection, zorder=10) ax.add_collection(collection) collection = PatchCollection(patches, facecolor='yellow', alpha=0.4, transform=ccrs.Geodetic(), zorder=10) ax.add_collection(collection) # test multiple interior polygons ax = plt.subplot(212, projection=ccrs.PlateCarree(), xlim=[-5, 15], ylim=[-5, 15]) ax.coastlines() exterior = np.array(sgeom.box(0, 0, 12, 12).exterior.coords) interiors = [np.array(sgeom.box(1, 1, 2, 2, ccw=False).exterior.coords), np.array(sgeom.box(1, 8, 2, 9, ccw=False).exterior.coords)] poly = sgeom.Polygon(exterior, interiors) patches = [] for pth in cpatch.geos_to_path(poly): patches.append(mpatches.PathPatch(pth)) collection = PatchCollection(patches, facecolor='yellow', alpha=0.4, transform=ccrs.Geodetic(), zorder=10) ax.add_collection(collection)
def test_polygon_interiors(): ax = plt.subplot(211, projection=ccrs.PlateCarree()) ax.coastlines() ax.set_global() # XXX could be the default??? pth = Path([[0, -45], [60, -45], [60, 45], [0, 45], [0, 45], [10, -20], [10, 20], [40, 20], [40, -20], [10, 20]], [1, 2, 2, 2, 79, 1, 2, 2, 2, 79]) patches_native = [] patches = [] for geos in cpatch.path_to_geos(pth): for pth in cpatch.geos_to_path(geos): patches.append(mpatches.PathPatch(pth)) # buffer by 10 degrees (leaves a small hole in the middle) geos_buffered = geos.buffer(10) for pth in cpatch.geos_to_path(geos_buffered): patches_native.append(mpatches.PathPatch(pth)) # Set high zorder to ensure the polygons are drawn on top of coastlines. collection = PatchCollection(patches_native, facecolor='red', alpha=0.4, transform=ax.projection, zorder=10) ax.add_collection(collection) collection = PatchCollection(patches, facecolor='yellow', alpha=0.4, transform=ccrs.Geodetic(), zorder=10) ax.add_collection(collection) # test multiple interior polygons ax = plt.subplot(212, projection=ccrs.PlateCarree(), xlim=[-5, 15], ylim=[-5, 15]) ax.coastlines() exterior = np.array(sgeom.box(0, 0, 12, 12).exterior.coords) interiors = [np.array(sgeom.box(1, 1, 2, 2, ccw=False).exterior.coords), np.array(sgeom.box(1, 8, 2, 9, ccw=False).exterior.coords)] poly = sgeom.Polygon(exterior, interiors) patches = [] for pth in cpatch.geos_to_path(poly): patches.append(mpatches.PathPatch(pth)) collection = PatchCollection(patches, facecolor='yellow', alpha=0.4, transform=ccrs.Geodetic(), zorder=10) ax.add_collection(collection)
def set_subplot_map(self, highlights, cgeorange): ###SUBPLOT: SET MAP self.oldax = self.p.ax self.p.ax = self.p.fig.add_axes([0.02, -0.39, 1.04, 0.44]) self.p.setmap(projection='cyl', georange=cgeorange, resolution='i') self.p.draw('country coastline province city') ###SUBPLOT: HIGHLIGHT COASTLINES & PLOT LEGEND colors = ['#AAFFAA', '#FFFF44', '#FF3333', '#BB0044'] descr = ['10~25%', '25~50%', '50~75%', '>75%'] handles = [] for i, clr in enumerate(colors, 0): patch = PathCollection(geos_to_path( MultiLineString(highlights[i]).buffer(self.buffersize)), facecolor=clr) self.p.ax.add_collection(patch) handles.append(Patch(color=clr, label=descr[i])) self.p.ax.text(0.98, 0.27, '中心经过1经纬度\n范围内的几率', transform=self.p.ax.transAxes, va='bottom', ha='right', fontsize=6, family='Source Han Sans CN') self.p.legend(handles=handles, loc='lower right', framealpha=0.8)
def tissot(rads_km=None, lons=None, lats=None, n_samples=80, globe=None, ax=None, draw=False, **kwargs): import numpy as np import cartopy.crs as ccrs import cartopy.feature as feature import shapely.geometry as sgeom from cartopy import geodesic import cartopy.mpl.patch as cpatch geod = geodesic.Geodesic(radius=globe.semimajor_axis, flattening=globe.flattening) geoms = [] rads_km = np.asarray(rads_km) lons = np.asarray(lons) lats = np.asarray(lats) for i in range(len(lons)): circle = geod.circle(lons[i], lats[i], rads_km[i], n_samples=n_samples) geoms.append(sgeom.Polygon(circle)) polys = cpatch.geos_to_path(geoms) if draw: if ax==None: ax = plt.gca() f = feature.ShapelyFeature(geoms, ccrs.Geodetic(globe=globe), **kwargs) ax.add_feature(f) return polys
def show(projection, geometry): orig_backend = mpl.get_backend() plt.switch_backend('tkagg') if geometry.type == 'MultiPolygon' and 1: multi_polygon = geometry for polygon in multi_polygon: import cartopy.mpl.patch as patch paths = patch.geos_to_path(polygon) for pth in paths: patch = mpatches.PathPatch(pth, edgecolor='none', lw=0, alpha=0.2) plt.gca().add_patch(patch) line_string = polygon.exterior plt.plot(*zip(*line_string.coords), marker='+', linestyle='-') elif geometry.type == 'MultiPolygon': multi_polygon = geometry for polygon in multi_polygon: line_string = polygon.exterior plt.plot(*zip(*line_string.coords), marker='+', linestyle='-') elif geometry.type == 'MultiLineString': multi_line_string = geometry for line_string in multi_line_string: plt.plot(*zip(*line_string.coords), marker='+', linestyle='-') elif geometry.type == 'LinearRing': plt.plot(*zip(*geometry.coords), marker='+', linestyle='-') if 1: # Whole map domain plt.autoscale() elif 0: # The left-hand triangle plt.xlim(-1.65e7, -1.2e7) plt.ylim(0.3e7, 0.65e7) elif 0: # The tip of the left-hand triangle plt.xlim(-1.65e7, -1.55e7) plt.ylim(0.3e7, 0.4e7) elif 1: # The very tip of the left-hand triangle plt.xlim(-1.632e7, -1.622e7) plt.ylim(0.327e7, 0.337e7) elif 1: # The tip of the right-hand triangle plt.xlim(1.55e7, 1.65e7) plt.ylim(0.3e7, 0.4e7) plt.plot(*zip(*projection.boundary.coords), marker='o', scalex=False, scaley=False, zorder=-1) plt.show() plt.switch_backend(orig_backend)
def draw_polygon(projection, polygon, color=None): multi_polygon = projection.project_geometry(polygon) for polygon in multi_polygon: #plt.plot(*zip(*polygon.exterior.coords), marker='+', color=color) #_arrows(projection, polygon.exterior) #continue import cartopy.mpl.patch as patch paths = patch.geos_to_path(polygon) for pth in paths: patch = mpatches.PathPatch(pth, edgecolor='none', alpha=0.5, facecolor=color, lw=0) plt.gca().add_patch(patch)
def maskcountries(self, conf, ax=None, regions=["China"], pathkw=dict(facecolor='none', edgecolor='black', linewidth=1.5)): """ 在cartopy中, 对选定的国家进行白化. refer to https://cloud.tencent.com/developer/article/1618341 Args: conf (matplotlib object): matplotlib的contour或contourf绘图返回值. ax (object, optional): Axes instance, if not None then overrides the default axes instance. regions (list, optional): 指定无需白化的国家. Defaults to ["China"]. pathkw (dict, optional): PathPatch关键字参数. Defaults to dict(facecolor='none',edgecolor='black', linewidth=1.0). Returns: clipping path, matplotlib.patches.PathPatch """ #Get current axes if not specified ax = ax or self._check_ax() #Convert region name to upper regions = list(regions) regions = [region.upper() for region in regions] # get shape file shpfile = pkg_resources.resource_filename( 'nmc_met_graphics', "resources/maps/country1.shp") # retrive region geometry reader = Reader(shpfile) countries = reader.records() multipoly, = [ country.geometry for country in countries if country.attributes['CNTRY_NAME'].upper() in regions ] main_geom = sorted(multipoly.geoms, key=lambda geom: geom.area)[-1] path, = geos_to_path(main_geom) plate_carre_data_transform = ccrs.PlateCarree()._as_mpl_transform(ax) for collection in conf.collections: collection.set_clip_path(path, plate_carre_data_transform) # Draw the path of interest. path = PathPatch(path, transform=ccrs.PlateCarree(), **pathkw) return path
def draw(self, renderer, *args, **kwargs): """ Draws the geometries of the feature that intersect with the extent of the :class:`cartopy.mpl.GeoAxes` instance to which this object has been added. """ if not self.get_visible(): return ax = self.get_axes() feature_crs = self._feature.crs # Get geometries that we need to draw. extent = None try: extent = ax.get_extent(feature_crs) except ValueError: warnings.warn('Unable to determine extent. Defaulting to global.') geoms = self._feature.intersecting_geometries(extent) # Project (if necessary) and convert geometries to matplotlib paths. paths = [] key = ax.projection for geom in geoms: mapping = FeatureArtist._geometry_to_path_cache.setdefault(geom, {}) geom_paths = mapping.get(key) if geom_paths is None: if ax.projection != feature_crs: projected_geom = ax.projection.project_geometry( geom, feature_crs) else: projected_geom = geom geom_paths = cpatch.geos_to_path(projected_geom) mapping[key] = geom_paths paths.extend(geom_paths) # Build path collection and draw it. transform = ax.projection._as_mpl_transform(ax) # Combine all the keyword args in priority order final_kwargs = dict(self._feature.kwargs) final_kwargs.update(self._kwargs) final_kwargs.update(kwargs) c = matplotlib.collections.PathCollection(paths, transform=transform, **final_kwargs) c.set_clip_path(ax.patch) c.set_figure(ax.figure) return c.draw(renderer)
def draw(self, renderer, *args, **kwargs): """ Draws the geometries of the feature that intersect with the extent of the :class:`cartopy.mpl.GeoAxes` instance to which this object has been added. """ if not self.get_visible(): return ax = self.get_axes() feature_crs = self._feature.crs # Get geometries that we need to draw. extent = None try: extent = ax.get_extent(feature_crs) except ValueError: warnings.warn('Unable to determine extent. Defaulting to global.') geoms = self._feature.intersecting_geometries(extent) # Project (if necessary) and convert geometries to matplotlib paths. paths = [] key = ax.projection for geom in geoms: mapping = FeatureArtist._geometry_to_path_cache.setdefault( geom, {}) geom_paths = mapping.get(key) if geom_paths is None: if ax.projection != feature_crs: projected_geom = ax.projection.project_geometry( geom, feature_crs) else: projected_geom = geom geom_paths = cpatch.geos_to_path(projected_geom) mapping[key] = geom_paths paths.extend(geom_paths) # Build path collection and draw it. transform = ax.projection._as_mpl_transform(ax) # Combine all the keyword args in priority order final_kwargs = dict(self._feature.kwargs) final_kwargs.update(self._kwargs) final_kwargs.update(kwargs) c = matplotlib.collections.PathCollection(paths, transform=transform, **final_kwargs) c.set_clip_path(ax.patch) c.set_figure(ax.figure) return c.draw(renderer)
def add_feature3d(ax, feature, clip_geom=None, zs=None): """ Add the given feature to the given axes. """ concat = lambda iterable: list(itertools.chain.from_iterable(iterable)) target_projection = ax.projection if hasattr(feature, 'geometries'): # cartopy.feature.Feature feature_hook = feature elif hasattr(feature._feature, 'geometries'): # cartopy.feature_artist.FeatureArtist ? feature_hook = feature._feature else: raise RuntimeError('problem with feature: %s' % type(feature)) geoms = list(feature_hook.geometries()) if target_projection != feature_hook.crs: # Transform the geometries from the feature's CRS into the # desired projection. geoms = [ target_projection.project_geometry(geom, feature_hook.crs) for geom in geoms ] if clip_geom: # Clip the geometries based on the extent of the map (because mpl3d # can't do it for us) geoms = [geom.intersection(clip_geom) for geom in geoms] # Convert the geometries to paths so we can use them in matplotlib. paths = concat(geos_to_path(geom) for geom in geoms) # Bug: mpl3d can't handle edgecolor='face' kwargs = feature_hook.kwargs if kwargs.get('edgecolor') == 'face': kwargs['edgecolor'] = kwargs['facecolor'] polys = concat(path.to_polygons(closed_only=False) for path in paths) if kwargs.get('facecolor', 'none') == 'none': lc = mcoll.LineCollection(polys, **kwargs) else: lc = mcoll.PolyCollection(polys, closed=False, **kwargs) #ax.add_collection3d(lc, zs=zs) add_fixzordercollection3d(ax, lc, zs=zs)
def _boundary(self): """ Adds the map's boundary. Note: The boundary is not the axes.patch, which provides rectilinear clipping for all of the map's artists. The axes.patch will have its visibility set to False inside GeoAxes.gca() """ import cartopy.mpl.patch as p path, = p.geos_to_path(self.projection.boundary) # from matplotlib.collections import PatchCollection sct = SimpleClippedTransform(self.transScale + self.transLimits, self.transAxes) # XXX Should be exactly one path... collection = mpatches.PathPatch(path, facecolor='none', edgecolor='k', zorder=1000, # transform=self.transData, transform=sct, clip_on=False, ) self.outline_patch = collection # XXX autolim = False self.add_patch(collection) # put a color patch for background color # XXX Should be exactly one path... collection = mpatches.PathPatch(path, facecolor='w', edgecolor='none', zorder=-1, transform=sct, clip_on=False, ) self.background_patch = collection # XXX autolim = False self.add_patch(collection) self.patch.set_facecolor((1, 1, 1, 0)) self.patch.set_edgecolor((0.5, 0.5, 0.5)) self.patch.set_linewidth(0.0)
def crsmask(ax, conf, crs, shpfile=None, region='China', attribute_name='CNTRY_NAME', pathkw=None): """ 在cartopy中, 对选定的区域进行白化. refer to https://cloud.tencent.com/developer/article/1618341 TODO: 如果Cartopy设置set_extent, 显示的图像不会剪裁外部等值线, 还未找到有效解决办法. Args: shpfile (string): 用于白化区域的shapefile文件名. region (string): shpfile中包含的区域名. ax (GeoAxes instance): cartopy的坐标轴实例 crs (cartopy.crs): cartopy坐标投影 conf (matplotlib): matplotlib的contour或contourf绘图返回值 pathkw (dict, optional): PathPatch关键字参数. Defaults to None. Return: clipping path, matplotlib.patches.PathPatch """ # get shape file if shpfile is None: shpfile = pkg_resources.resource_filename( 'nmc_met_graphics', "resources/maps/country1.shp") # retrive region geometry reader = shapereader.Reader(shpfile) countries = reader.records() multipoly, = [country.geometry for country in countries if country.attributes['CNTRY_NAME'] == region] main_geom = sorted(multipoly.geoms, key=lambda geom: geom.area)[-1] path, = geos_to_path(main_geom) plate_carre_data_transform = crs._as_mpl_transform(ax) for collection in conf.collections: collection.set_clip_path(path, plate_carre_data_transform) # Draw the path of interest. path = PathPatch(path, transform = crs, **pathkw) return path
def add_storm(self, storm): count = self.grid.copy() length = NUM_OF_MEMS name = storm.get_fullname() i = 0 for code in storm.iter_members(): linestring = list(zip(storm.lons, storm.lats)) if len(linestring) < 2: continue path = geos_to_path(LineString(linestring).buffer(RADIUS))[0] boolarr = path.contains_points(self.xy).reshape( (self.yshape, self.xshape)).astype(np.uint8) count += boolarr i += 1 print('\r{:s}: [{: <10s}] {:.0%}'.format(name, '#' * (i * 10 // length), i / length), end='') print() return count
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.tick_params(labelsize=15) contourf = ax.contourf(lon,lat,u1_avg,lev,cmap='Blues',transform=proj,extend='both') countries = shp.records() cn_multipoly, = [country.geometry for country in countries if country.attributes['CNTRY_NAME'] == 'China'] # 选择地图属性下'NAME'属性里名字是'China'的一条多边形 paths = [] for i in range(len(cn_multipoly)): cn_geom, = geos_to_path(cn_multipoly.geoms[i]) paths.append(cn_geom) path = Path.make_compound_path(*paths) for collection in contourf.collections: collection.set_clip_path(path, proj._as_mpl_transform(ax)) # 白化刻度 # contour = ax.contour(lon,lat,u1_avg,lev,cmap='Blues',transform=proj,extend='both') # cn_label = plt.clabel(contour,inline=1,fontsize=10,fmt="%.fr") # if cn_label: # clip_map_shapely = Polygon(path.vertices) # for text_object in cn_label: # if not clip_map_shapely.contains(Point(text_object.get_position())): # text_object.set_visible(False)
def draw(self, renderer, *args, **kwargs): """ Draws the geometries of the feature that intersect with the extent of the :class:`cartopy.mpl.GeoAxes` instance to which this object has been added. """ if not self.get_visible(): return ax = self.axes feature_crs = self._feature.crs # Get geometries that we need to draw. extent = None try: extent = ax.get_extent(feature_crs) except ValueError: warnings.warn('Unable to determine extent. Defaulting to global.') geoms = self._feature.intersecting_geometries(extent) # Project (if necessary) and convert geometries to matplotlib paths. paths = [] key = ax.projection for geom in geoms: # As Shapely geometries cannot be relied upon to be # hashable, we have to use a WeakValueDictionary to manage # their weak references. The key can then be a simple, # "disposable", hashable geom-key object that just uses the # id() of a geometry to determine equality and hash value. # The only persistent, strong reference to the geom-key is # in the WeakValueDictionary, so when the geometry is # garbage collected so is the geom-key. # The geom-key is also used to access the WeakKeyDictionary # cache of transformed geometries. So when the geom-key is # garbage collected so are the transformed geometries. geom_key = _GeomKey(geom) FeatureArtist._geom_key_to_geometry_cache.setdefault( geom_key, geom) mapping = FeatureArtist._geom_key_to_path_cache.setdefault( geom_key, {}) geom_paths = mapping.get(key) if geom_paths is None: if ax.projection != feature_crs: projected_geom = ax.projection.project_geometry( geom, feature_crs) else: projected_geom = geom geom_paths = cpatch.geos_to_path(projected_geom) mapping[key] = geom_paths paths.extend(geom_paths) # Build path collection and draw it. transform = ax.projection._as_mpl_transform(ax) # Combine all the keyword args in priority order final_kwargs = dict(self._feature.kwargs) final_kwargs.update(self._kwargs) final_kwargs.update(kwargs) c = matplotlib.collections.PathCollection(paths, transform=transform, **final_kwargs) c.set_clip_path(ax.patch) c.set_figure(ax.figure) return c.draw(renderer)
def draw(self, renderer, *args, **kwargs): """ Draw the geometries of the feature that intersect with the extent of the :class:`cartopy.mpl.GeoAxes` instance to which this object has been added. """ if not self.get_visible(): return ax = self.axes feature_crs = self._feature.crs # Get geometries that we need to draw. extent = None try: extent = ax.get_extent(feature_crs) except ValueError: warnings.warn('Unable to determine extent. Defaulting to global.') geoms = self._feature.intersecting_geometries(extent) # Project (if necessary) and convert geometries to matplotlib paths. paths = [] key = ax.projection for geom in geoms: # As Shapely geometries cannot be relied upon to be # hashable, we have to use a WeakValueDictionary to manage # their weak references. The key can then be a simple, # "disposable", hashable geom-key object that just uses the # id() of a geometry to determine equality and hash value. # The only persistent, strong reference to the geom-key is # in the WeakValueDictionary, so when the geometry is # garbage collected so is the geom-key. # The geom-key is also used to access the WeakKeyDictionary # cache of transformed geometries. So when the geom-key is # garbage collected so are the transformed geometries. geom_key = _GeomKey(geom) FeatureArtist._geom_key_to_geometry_cache.setdefault( geom_key, geom) mapping = FeatureArtist._geom_key_to_path_cache.setdefault( geom_key, {}) geom_paths = mapping.get(key) if geom_paths is None: if ax.projection != feature_crs: projected_geom = ax.projection.project_geometry( geom, feature_crs) else: projected_geom = geom geom_paths = cpatch.geos_to_path(projected_geom) mapping[key] = geom_paths paths.extend(geom_paths) # Build path collection and draw it. transform = ax.projection._as_mpl_transform(ax) # Combine all the keyword args in priority order final_kwargs = dict(self._feature.kwargs) final_kwargs.update(self._kwargs) final_kwargs.update(kwargs) c = matplotlib.collections.PathCollection(paths, transform=transform, **final_kwargs) c.set_clip_path(ax.patch) c.set_figure(ax.figure) return c.draw(renderer)
def transform_path_non_affine(self, src_path): """ Transforms from source to target coordinates. Caches results, so subsequent calls with the same *src_path* argument (and the same source and target projections) are faster. Args: * src_path - A matplotlib :class:`~matplotlib.path.Path` object with vertices in source coordinates. Returns * A matplotlib :class:`~matplotlib.path.Path` with vertices in target coordinates. """ mapping = _PATH_TRANSFORM_CACHE.get(src_path) if mapping is not None: key = (self.source_projection, self.target_projection) result = mapping.get(key) if result is not None: return result # Allow the vertices to be quickly transformed, if # quick_vertices_transform allows it. new_vertices = self.target_projection.quick_vertices_transform( src_path.vertices, self.source_projection) if new_vertices is not None: if new_vertices is src_path.vertices: return src_path else: return mpath.Path(new_vertices, src_path.codes) if src_path.vertices.shape == (1, 2): return mpath.Path(self.transform(src_path.vertices)) transformed_geoms = [] for geom in patch.path_to_geos(src_path): transformed_geoms.append( self.target_projection.project_geometry(geom, self.source_projection) ) if not transformed_geoms: result = mpath.Path(np.empty([0, 2])) else: paths = patch.geos_to_path(transformed_geoms) if not paths: return mpath.Path(np.empty([0, 2])) points, codes = zip(*[patch.path_segments(path, curves=False, simplify=False) for path in paths]) result = mpath.Path(np.concatenate(points, 0), np.concatenate(codes)) # store the result in the cache for future performance boosts key = (self.source_projection, self.target_projection) if mapping is None: _PATH_TRANSFORM_CACHE[src_path] = {key: result} else: mapping[key] = result return result
# Define the contour levels (T) clevs = np.arange(228, 273, 4, dtype=float) # Import an NCL colormap, truncating it by using geocat.viz.util convenience function newcmp = gvutil.truncate_colormap(gvcmaps.BkBlAqGrYeOrReViWh200, minval=0.1, maxval=0.6, n=len(clevs)) # Draw the contour plot, "clipped" to the country boundaries # (NOTE: There are multiple closed polygons representing the boundaries of the # countries. This is both because there are 2 country borders being used # to clip the contour plot, but also because China consists of many islands. # As a result, we have to loop over *all closed paths* and construct a # matplotlib patch object that we can use the clip the contour plot.) for path in geos_to_path(country_geos): patch = PathPatch(path, transform=ax.transData, facecolor='none', edgecolor='black', lw=1.5) # Draw the patch on the plot ax.add_patch(patch) # Draw the contour plot # (NOTE: Because this line is in the loop over closed paths, the contour plot # is being drawn for each closed path. This has to be done because # matplotlib cannot apply *multiple* closed paths at the same time to # to the same plot. Hence, for each closed path, we need to generate # another contour plot and clip that contour plot with the patch. In
def plot_3D(self, event=None): '''Plot observation QC values on a global 2D map Keyword arguments: event -- an argument passed by any tkiner menu event. Has no influence on output but tkinter requires it to be passed to any method called by a menu event ''' qc = [ np.int64(self.qc_menu.get(val).split(": ", 1)[1][0]) for val in self.qc_menu.curselection() ] #make figure and canvas to draw on fig = Figure(figsize=(12, 8)) #ax = fig.add_axes([0.01, 0.01, 0.98, 0.98], projection = ccrs.PlateCarree()) canvas = FigureCanvasTkAgg(fig, master=self.main_frame) canvas.get_tk_widget().grid(column=1, row=1, rowspan=4, sticky="N, S, E, W") #have to set up a separate toolbar frame because toolbar doesn't like gridding with others self.toolbar_frame = ttk.Frame(self.main_frame) self.toolbar = NavigationToolbar2TkAgg(canvas, self.toolbar_frame) self.toolbar_frame.grid(column=1, row=5, sticky="N, S, E, W") self.toolbar.grid(column=1, row=1, sticky="N, S, E, W") #resizing self.toolbar_frame.grid_columnconfigure(1, weight=1) self.toolbar_frame.grid_rowconfigure(1, weight=1) #disable part of the coordinate display functionality, else everything flickers (may need for smaller window) #ax.format_coord = lambda x, y: '' data = self.plotter.filter(self.data_qc, ('qc_DART', qc)) target_projection = ccrs.PlateCarree() #weird redundant line that works for transformation transform = target_projection.transform_points(target_projection, data.lons.values, data.lats.values) lons, lats = transform[:, 0], transform[:, 1] concat = lambda iterable: list(itertools.chain.from_iterable(iterable)) feature = cartopy.feature.NaturalEarthFeature('Physical', 'land', '110m') geoms = feature.geometries() geoms = [ target_projection.project_geometry(geom, feature.crs) for geom in geoms ] paths = concat(geos_to_path(geom) for geom in geoms) polys = concat(path.to_polygons() for path in paths) ax = Axes3D(fig, [0.02, 0.02, 0.97, 0.97], xlim=[-180, 180], ylim=[-90, 90]) z_max = max(data.z.values) #deal with orientation of graph for different vert types if data.vert_types.values[0] < 0 or data.vert_types.values[0] == 3: #surface, heights, or unknown units where up is positive direction #don't need to do 3D polygons since it will plot 2D polygons at z = 0 by default lc = PolyCollection(polys, edgecolor='black', facecolor='green', closed=False) ax.set_zlim(bottom=0, top=z_max) ax.add_collection3d(lc) else: #level or pressure units where down is positive direction polys = [[(point[0], point[1], z_max) for point in shape] for shape in polys] lc = Poly3DCollection(polys, edgecolor='black', facecolor='green', closed=False) ax.set_zlim(bottom=z_max, top=0) ax.add_collection3d(lc) plot_values = None cmap = None max_value = None min_value = None #colormap for QC values if self.val_type.get() == 'QC': cmap = plt.get_cmap('gist_ncar', 9) plot_values = data.qc_DART max_value = 8 min_value = 0 elif self.val_type.get() == 'Observation value': cmap = plt.get_cmap('jet', np.unique(data.values).size) plot_values = data.values.ravel() max_value = max(plot_values) min_value = min(plot_values) #plot each observation type separately to get differing edge colors and markers ax.scatter(lons, lats, data.z, c=plot_values, cmap=cmap, vmin=min_value, vmax=max_value, s=35, alpha=0.5) #make color bar sm = plt.cm.ScalarMappable(cmap=cmap, norm=plt.Normalize(0, max_value + 1)) sm._A = [] cbar = plt.colorbar(sm, ax=ax, orientation='horizontal', pad=0.04) #set up color bar title according to plot type if self.val_type.get() == 'QC': cbar.ax.set_xlabel('DART QC Value') #also center colorbar ticks and labels labels = np.arange(0, max_value + 1, 1) loc = labels + 0.5 cbar.set_ticks(loc) cbar.set_ticklabels(labels) elif self.val_type.get() == 'Observation value': #get observation name cbar.ax.set_xlabel( self.obs_menu.get(self.obs_menu.curselection()).split( " : ", 1)[1]) ax.set_aspect('auto') #ax.margins(0.5, tight = False) s = ttk.Style() s.theme_use('clam')
def draw(self, renderer, *args, **kwargs): """ Draw the geometries of the feature that intersect with the extent of the :class:`cartopy.mpl.GeoAxes` instance to which this object has been added. """ if not self.get_visible(): return ax = self.axes feature_crs = self._feature.crs # Get geometries that we need to draw. extent = None try: extent = ax.get_extent(feature_crs) except ValueError: warnings.warn('Unable to determine extent. Defaulting to global.') geoms = self._feature.intersecting_geometries(extent) # Combine all the keyword args in priority order. prepared_kwargs = style_merge(self._feature.kwargs, self._kwargs, kwargs) # Freeze the kwargs so that we can use them as a dict key. We will # need to unfreeze this with dict(frozen) before passing to mpl. prepared_kwargs = _freeze(prepared_kwargs) # Project (if necessary) and convert geometries to matplotlib paths. stylised_paths = OrderedDict() key = ax.projection for geom in geoms: # As Shapely geometries cannot be relied upon to be # hashable, we have to use a WeakValueDictionary to manage # their weak references. The key can then be a simple, # "disposable", hashable geom-key object that just uses the # id() of a geometry to determine equality and hash value. # The only persistent, strong reference to the geom-key is # in the WeakValueDictionary, so when the geometry is # garbage collected so is the geom-key. # The geom-key is also used to access the WeakKeyDictionary # cache of transformed geometries. So when the geom-key is # garbage collected so are the transformed geometries. geom_key = _GeomKey(geom) FeatureArtist._geom_key_to_geometry_cache.setdefault( geom_key, geom) mapping = FeatureArtist._geom_key_to_path_cache.setdefault( geom_key, {}) geom_paths = mapping.get(key) if geom_paths is None: if ax.projection != feature_crs: projected_geom = ax.projection.project_geometry( geom, feature_crs) else: projected_geom = geom geom_paths = cpatch.geos_to_path(projected_geom) mapping[key] = geom_paths if not self._styler: style = prepared_kwargs else: # Unfreeze, then add the computed style, and then re-freeze. style = style_merge(dict(prepared_kwargs), self._styler(geom)) style = _freeze(style) stylised_paths.setdefault(style, []).extend(geom_paths) transform = ax.projection._as_mpl_transform(ax) # Draw one PathCollection per style. We could instead pass an array # of style items through to a single PathCollection, but that # complexity does not yet justify the effort. for style, paths in stylised_paths.items(): style = style_finalize(dict(style)) # Build path collection and draw it. c = matplotlib.collections.PathCollection(paths, transform=transform, **style) c.set_clip_path(ax.patch) c.set_figure(ax.figure) c.draw(renderer) # n.b. matplotlib.collection.Collection.draw returns None return None
def draw(self, renderer, *args, **kwargs): """ Draw the geometries of the feature that intersect with the extent of the :class:`cartopy.mpl.GeoAxes` instance to which this object has been added. """ if not self.get_visible(): return ax = self.axes feature_crs = self._feature.crs # Get geometries that we need to draw. extent = None try: extent = ax.get_extent(feature_crs) except ValueError: warnings.warn('Unable to determine extent. Defaulting to global.') geoms = self._feature.intersecting_geometries(extent) # Combine all the keyword args in priority order. prepared_kwargs = style_merge( self._feature.kwargs, self._kwargs, kwargs) # Freeze the kwargs so that we can use them as a dict key. We will # need to unfreeze this with dict(frozen) before passing to mpl. prepared_kwargs = _freeze(prepared_kwargs) # Project (if necessary) and convert geometries to matplotlib paths. stylised_paths = OrderedDict() key = ax.projection for geom in geoms: # As Shapely geometries cannot be relied upon to be # hashable, we have to use a WeakValueDictionary to manage # their weak references. The key can then be a simple, # "disposable", hashable geom-key object that just uses the # id() of a geometry to determine equality and hash value. # The only persistent, strong reference to the geom-key is # in the WeakValueDictionary, so when the geometry is # garbage collected so is the geom-key. # The geom-key is also used to access the WeakKeyDictionary # cache of transformed geometries. So when the geom-key is # garbage collected so are the transformed geometries. geom_key = _GeomKey(geom) FeatureArtist._geom_key_to_geometry_cache.setdefault( geom_key, geom) mapping = FeatureArtist._geom_key_to_path_cache.setdefault( geom_key, {}) geom_paths = mapping.get(key) if geom_paths is None: if ax.projection != feature_crs: projected_geom = ax.projection.project_geometry( geom, feature_crs) else: projected_geom = geom geom_paths = cpatch.geos_to_path(projected_geom) mapping[key] = geom_paths if not self._styler: style = prepared_kwargs else: # Unfreeze, then add the computed style, and then re-freeze. style = style_merge(dict(prepared_kwargs), self._styler(geom)) style = _freeze(style) stylised_paths.setdefault(style, []).extend(geom_paths) transform = ax.projection._as_mpl_transform(ax) # Draw one PathCollection per style. We could instead pass an array # of style items through to a single PathCollection, but that # complexity does not yet justify the effort. for style, paths in stylised_paths.items(): style = style_finalize(dict(style)) # Build path collection and draw it. c = matplotlib.collections.PathCollection( paths, transform=transform, **style) c.set_clip_path(ax.patch) c.set_figure(ax.figure) c.draw(renderer) # n.b. matplotlib.collection.Collection.draw returns None return None
a = ccrs.PlateCarree().transform_points(ccrs.PlateCarree(), plotter.data.lons[1:10000].values, plotter.data.lats[1:10000].values) lons, lats = a[:, 0], a[:, 1] ax = Axes3D(fig, xlim = [-180, 180], ylim = [-90, 90]) zmax = max(plotter.data.z.values) concat = lambda iterable: list(itertools.chain.from_iterable(iterable)) target_projection = ccrs.PlateCarree() feature = cartopy.feature.NaturalEarthFeature('Physical', 'land', '110m') geoms = feature.geometries() geoms = [target_projection.project_geometry(geom, feature.crs) for geom in geoms] paths = concat(geos_to_path(geom) for geom in geoms) polys = concat(path.to_polygons() for path in paths) print(type(polys[0][0])) #print(polys) #print([[[point] for point in shape] for shape in polys]) polys = [[(point[0], point[1], zmax) for point in shape] for shape in polys] #print(polys.shape) #polys = [x, y, zmax for x,y lc = Poly3DCollection(polys, edgecolor = 'black', facecolor = 'green', closed = False) ax.add_collection3d(lc) print(plotter.data.qc_DART.values[:].shape) ax.scatter(lons, lats, plotter.data.z[1:10000], c = plotter.data.values[1:10000].ravel(), cmap = plt.get_cmap('gist_ncar'))
def pcolor_mask_geoms(cube, geoms, transform): path = Path.make_compound_path(*geos_to_path(geoms)) im = iplt.pcolor(cube) im.set_clip_path(path, transform=transform)
fig = plt.figure() ax = Axes3D(fig, xlim=[-180, 180], ylim=[-90, 90]) ax.set_zlim(bottom=0) target_projection = ccrs.PlateCarree() feature = cartopy.feature.NaturalEarthFeature('physical', 'land', '110m') geoms = feature.geometries() geoms = [ target_projection.project_geometry(geom, feature.crs) for geom in geoms ] paths = list( itertools.chain.from_iterable(geos_to_path(geom) for geom in geoms)) # At this point, we start working around mpl3d's slightly broken interfaces. # So we produce a LineCollection rather than a PathCollection. segments = [] for path in paths: vertices = [vertex for vertex, _ in path.iter_segments()] vertices = np.asarray(vertices) segments.append(vertices) lc = LineCollection(segments, color='black') ax.add_collection3d(lc) ax.set_xlabel('X') ax.set_ylabel('Y')