def multiline(feature, extent=None): """Process cartopy feature""" if extent is None: geometries = feature.geometries() else: geometries = feature.intersecting_geometries(extent) return xs_ys(cut(iterlines(geometries), 180))
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')
plotter = plot_2D_obs('../obs_series/obs_epoch_001.nc') fig = plt.figure() 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)