def test_quadmesh_deprecated_signature(fig_test, fig_ref, flat_ref, kwargs): # test that the new and old quadmesh signature produce the same results # remove when the old QuadMesh.__init__ signature expires (v3.5+2) from matplotlib.collections import QuadMesh x = [0, 1, 2, 3.] y = [1, 2, 3.] X, Y = np.meshgrid(x, y) X += 0.2 * Y coords = np.stack([X, Y], axis=-1) assert coords.shape == (3, 4, 2) C = np.linspace(0, 2, 6).reshape(2, 3) ax = fig_test.add_subplot() ax.set(xlim=(0, 5), ylim=(0, 4)) if 'transform' in kwargs: kwargs['transform'] = mtransforms.Affine2D().scale(1.2) + ax.transData qmesh = QuadMesh(coords, **kwargs) qmesh.set_array(C) ax.add_collection(qmesh) assert qmesh._shading == 'flat' ax = fig_ref.add_subplot() ax.set(xlim=(0, 5), ylim=(0, 4)) if 'transform' in kwargs: kwargs['transform'] = mtransforms.Affine2D().scale(1.2) + ax.transData with pytest.warns(MatplotlibDeprecationWarning): qmesh = QuadMesh(4 - 1, 3 - 1, coords.copy().reshape(-1, 2) if flat_ref else coords, **kwargs) qmesh.set_array(C.flatten() if flat_ref else C) ax.add_collection(qmesh) assert qmesh._shading == 'flat'
def test_quadmesh_deprecated_positional(fig_test, fig_ref): # test that positional parameters are still accepted with the old signature # and work correctly # remove when the old QuadMesh.__init__ signature expires (v3.5+2) from matplotlib.collections import QuadMesh x = [0, 1, 2, 3.] y = [1, 2, 3.] X, Y = np.meshgrid(x, y) X += 0.2 * Y coords = np.stack([X, Y], axis=-1) assert coords.shape == (3, 4, 2) C = np.linspace(0, 2, 12).reshape(3, 4) ax = fig_test.add_subplot() ax.set(xlim=(0, 5), ylim=(0, 4)) qmesh = QuadMesh(coords, antialiased=False, shading='gouraud') qmesh.set_array(C) ax.add_collection(qmesh) ax = fig_ref.add_subplot() ax.set(xlim=(0, 5), ylim=(0, 4)) with pytest.warns(MatplotlibDeprecationWarning): qmesh = QuadMesh(4 - 1, 3 - 1, coords.copy().reshape(-1, 2), False, 'gouraud') qmesh.set_array(C) ax.add_collection(qmesh)
def plot( self, title = None, scalelabel = None, xlim=None, ylim=None, xlog=False, ylog=False ): """ :param title: :param scalelabel: :param xlim: :param ylim: :param xlog: :param ylog: :return: """ import matplotlib.pyplot as plt import numpy as np from matplotlib.collections import QuadMesh # determine where to get the settings for the potentially mirrored second axis if self.matrix.axes[1].style == 'link': axis1index = 2 else: axis1index = 1 x = self.matrix.axes[2].values y = self.matrix.axes[axis1index].values X, Y = np.meshgrid( x, y ) XY = np.hstack((X.ravel()[:,np.newaxis], Y.ravel()[:,np.newaxis])) Z = (self.matrix.array.constructArray()).ravel() ax = plt.subplot(1,1,1) if title is None: title = str( self.toXLink() ) plt.suptitle(title) qc = QuadMesh( meshWidth=len(x)-1, meshHeight=len(y)-1, coordinates=XY, # showedges=True, antialiased=True, shading='flat', transOffset=ax.transData) qc.set_array(Z) ax.add_collection(qc,autolim=True) if xlim is None: ax.set_xlim( x[0], x[-1] ) else: ax.set_xlim( xlim[0], xlim[1] ) if ylim is None: ax.set_ylim( y[0], y[-1] ) else: ax.set_ylim( ylim[0], ylim[1] ) if xlog: ax.set_xscale( 'log' ) if ylog: ax.set_yscale( 'log' ) xlabel = self.matrix.axes[2].label + ' (' + self.matrix.axes[2].unit +')' ylabel = self.matrix.axes[axis1index].label + ' (' + self.matrix.axes[axis1index].unit +')' ax.set_xlabel( xlabel ) ax.set_ylabel( ylabel ) cbar = plt.colorbar(qc) if scalelabel is not None: cbar.set_label(scalelabel) else: cbar.set_label(str(self.type)+' covariance ('+str(self.matrix.axes[0].unit)+')') plt.show()
def mesh(self): if self._mesh is not None: return self._mesh px, py, dx, dy = self._corners x, y, c = self.axes._pcolorargs('pcolormesh', dx, dy, self.im[:, :, 0], allmatch=False) ny, nx = x.shape coords = np.column_stack((x.ravel(), y.ravel())) collection = QuadMesh(nx - 1, ny - 1, coords, shading='flat', antialiased=False, edgecolors='None', cmap='gray') collection.set_array(c.ravel()) collection.set_clip_path(self.axes.patch) collection.set_transform(self.axes.transData) self._mesh = collection return self._mesh
def clear_color_mesh(qmesh: QuadMesh, default_val=0): qmesh.set_array(qmesh.get_array() * default_val)
def update_color_mesh(self, qmesh: QuadMesh, time_step, node_id, value_name): df = self.update_area(time_step, node_id, value_name) data = np.array(df) qmesh.set_array(data.ravel()) return qmesh
def plot(self, ax=None, mode="local", **kwargs): """ plot a frame. this can be useful for plotting as background for a velocimetry result. Plotting can be done in three modes: - "local": a simple planar view plot, with a local coordinate system in meters, with the top-left coordinate being the 0, 0 point, and ascending coordinates towards the right and bottom. - "geographical": a geographical plot, requiring the package `cartopy`, the results are plotted on a geographical axes, so that combinations with tile layers such as OpenStreetMap, or shapefiles can be made. - "camera": i.e. seen from the camera perspective. This is the most intuitive view for end users. :param ax: pre-defined axes object. If not set, a new axes will be prepared. In case `mode=="geographical"`, a cartopy GeoAxes needs to be provided, or will be made in case ax is not set. :param mode: can be "local", "geographical", or "camera". For "geographical" a frames set from frames.project should be used that contains "lon" and "lat" coordinates. For "camera", a non-projected frames set should be used. :param kwargs: dict, plotting parameters to be passed to matplotlib.pyplot.pcolormesh, for plotting the background frame. """ # prepare axes if "time" in self._obj.coords: if self._obj.time.size > 1: raise AttributeError( f'Object contains dimension "time" with length {len(self._obj.time)}. Reduce dataset by selecting one time step or taking a median, mean or other statistic.' ) ax = plot_orc.prepare_axes(ax=ax, mode=mode) f = ax.figure # handle to figure if mode == "local": x = "x" y = "y" elif mode == "geographical": # import some additional packages import cartopy.crs as ccrs # add transform for GeoAxes kwargs["transform"] = ccrs.PlateCarree() x = "lon" y = "lat" else: # mode is camera x = "xp" y = "yp" assert all( v in self._obj.coords for v in [x, y] ), f'required coordinates "{x}" and/or "{y}" are not available' if (len(self._obj.shape) == 3 and self._obj.shape[-1] == 3): # looking at an rgb image facecolors = self._obj.values.reshape( self._obj.shape[0] * self._obj.shape[1], 3) / 255 facecolors = np.hstack([facecolors, np.ones((len(facecolors), 1))]) quad = ax.pcolormesh(self._obj[x], self._obj[y], self._obj.mean(dim="rgb"), shading="nearest", facecolors=facecolors, **kwargs) # remove array values, override .set_array, needed in case GeoAxes is provided, because GeoAxes asserts if array has dims QuadMesh.set_array(quad, None) else: ax.pcolormesh(self._obj[x], self._obj[y], self._obj, **kwargs) # fix axis limits to min and max of extent of frames ax.set_xlim([self._obj[x].min(), self._obj[x].max()]) ax.set_ylim([self._obj[y].min(), self._obj[y].max()]) return ax