def _plot_2d( pos, field, mesh_type, fig=None, ax=None, latlon=False, ax_names=None, levels=64, antialias=True, ): # pragma: no cover """Plot a 2d field with a contour plot.""" fig, ax = get_fig_ax(fig, ax) title = f"Field 2D {mesh_type}: {field.shape}" ax_names = _ax_names(2, latlon, ax_names=ax_names) x, y = pos[::-1] if latlon else pos if mesh_type == "unstructured": cont = ax.tricontourf(x, y, field.ravel(), levels=levels) if antialias: ax.tricontour(x, y, field.ravel(), levels=levels, zorder=-10) else: plt_fld = field if latlon else field.T cont = ax.contourf(x, y, plt_fld, levels=levels) if antialias: ax.contour(x, y, plt_fld, levels=levels, zorder=-10) ax.set_xlabel(ax_names[0]) ax.set_ylabel(ax_names[1]) ax.set_title(title) fig.colorbar(cont) fig.show() return ax
def plot_spectral_rad_pdf( model, x_min=0.0, x_max=None, fig=None, ax=None, **kwargs ): # pragma: no cover """Plot radial spectral pdf of a given CovModel.""" fig, ax = get_fig_ax(fig, ax) if x_max is None: x_max = 3 / model.len_scale x_s = np.linspace(x_min, x_max) kwargs.setdefault("label", f"{model.name} {model.dim}D spectral-rad-pdf") ax.plot(x_s, model.spectral_rad_pdf(x_s), **kwargs) ax.legend() fig.show() return ax
def plot_cor_axis( model, axis=0, x_min=0.0, x_max=None, fig=None, ax=None, **kwargs ): # pragma: no cover """Plot variogram of a given CovModel.""" fig, ax = get_fig_ax(fig, ax) if x_max is None: x_max = 3 * model.len_scale x_s = np.linspace(x_min, x_max) kwargs.setdefault("label", f"{model.name} correlation on axis {axis}") ax.plot(x_s, model.cor_axis(x_s, axis), **kwargs) ax.legend() fig.show() return ax
def plot_cor_yadrenko( model, x_min=0.0, x_max=None, fig=None, ax=None, **kwargs ): # pragma: no cover """Plot Yadrenko correlation function of a given CovModel.""" fig, ax = get_fig_ax(fig, ax) if x_max is None: x_max = min(3 * model.len_rescaled, np.pi) x_s = np.linspace(x_min, x_max) kwargs.setdefault("label", f"{model.name} Yadrenko correlation") ax.plot(x_s, model.cor_yadrenko(x_s), **kwargs) ax.legend() fig.show() return ax
def plot_vec_field(fld, field="field", fig=None, ax=None): # pragma: no cover """ Plot a spatial random vector field. Parameters ---------- fld : :class:`Field` The given field class instance. field : :class:`str`, optional Field that should be plotted. Default: "field" fig : :class:`Figure` or :any:`None`, optional Figure to plot the axes on. If `None`, a new one will be created. Default: `None` ax : :class:`Axes` or :any:`None`, optional Axes to plot on. If `None`, a new one will be added to the figure. Default: `None` """ if fld.mesh_type == "unstructured": raise RuntimeError( "Only structured vector fields are supported " "for plotting. Please create one on a structured grid.") plt_fld = getattr(fld, field) assert not (fld.pos is None or plt_fld is None) norm = np.sqrt(plt_fld[0, :].T**2 + plt_fld[1, :].T**2) fig, ax = get_fig_ax(fig, ax) title = f"Field 2D {fld.mesh_type}: {plt_fld.shape}" x = fld.pos[0] y = fld.pos[1] sp = plt.streamplot( x, y, plt_fld[0, :].T, plt_fld[1, :].T, color=norm, linewidth=norm / 2, ) ax.set_xlabel("X") ax.set_ylabel("Y") ax.set_title(title) fig.colorbar(sp.lines) fig.show() return ax
def plot_1d(pos, field, fig=None, ax=None, ax_names=None): # pragma: no cover """ Plot a 1D field. Parameters ---------- pos : :class:`list` the position tuple, containing either the point coordinates (x, y, ...) or the axes descriptions (for mesh_type='structured') field : :class:`numpy.ndarray` Field values. fig : :class:`Figure` or :any:`None`, optional Figure to plot the axes on. If `None`, a new one will be created. Default: `None` ax : :class:`Axes` or :any:`None`, optional Axes to plot on. If `None`, a new one will be added to the figure. Default: `None` ax_names : :class:`list` of :class:`str`, optional Axes names. The default is ["$x$", "field"]. Returns ------- ax : :class:`Axes` Axis containing the plot. """ fig, ax = get_fig_ax(fig, ax) title = f"Field 1D: {field.shape}" x = pos[0] x = x.flatten() arg = np.argsort(x) ax_names = _ax_names(1, ax_names=ax_names) ax.plot(x[arg], field.ravel()[arg]) ax.set_xlabel(ax_names[0]) ax.set_ylabel(ax_names[1]) ax.set_title(title) fig.show() return ax
def plot_nd( pos, field, mesh_type, fig=None, ax=None, latlon=False, resolution=128, ax_names=None, aspect="quad", show_colorbar=True, convex_hull=False, contour_plot=True, **kwargs, ): # pragma: no cover """ Plot field in arbitrary dimensions. Parameters ---------- pos : :class:`list` the position tuple, containing either the point coordinates (x, y, ...) or the axes descriptions (for mesh_type='structured') field : :class:`numpy.ndarray` Field values. fig : :class:`Figure` or :any:`None`, optional Figure to plot the axes on. If `None`, a new one will be created. Default: `None` ax : :class:`Axes` or :any:`None`, optional Axes to plot on. If `None`, a new one will be added to the figure. Default: `None` latlon : :class:`bool`, optional Whether the data is representing 2D fields on earths surface described by latitude and longitude. When using this, the estimator will use great-circle distance for variogram estimation. Note, that only an isotropic variogram can be estimated and a ValueError will be raised, if a direction was specified. Bin edges need to be given in radians in this case. Default: False resolution : :class:`int`, optional Resolution of the imshow plot. The default is 128. ax_names : :class:`list` of :class:`str`, optional Axes names. The default is ["$x$", "field"]. aspect : :class:`str` or :any:`None` or :class:`float`, optional Aspect of the plot. Can be "auto", "equal", "quad", None or a number describing the aspect ratio. The default is "quad". show_colorbar : :class:`bool`, optional Whether to show the colorbar. The default is True. convex_hull : :class:`bool`, optional Whether to show the convex hull in 2D with unstructured data. The default is False. contour_plot : :class:`bool`, optional Whether to use a contour-plot in 2D. The default is True. Returns ------- ax : :class:`Axes` Axis containing the plot. """ dim = len(pos) assert dim > 1 assert not latlon or dim == 2 if dim == 2 and contour_plot: return _plot_2d(pos, field, mesh_type, fig, ax, latlon, ax_names, **kwargs) pos = pos[::-1] if latlon else pos field = field.T if (latlon and mesh_type != "unstructured") else field ax_names = _ax_names(dim, latlon, ax_names) # init planes planes = rotation_planes(dim) plane_names = [f" {ax_names[p[0]]} - {ax_names[p[1]]}" for p in planes] ax_ends = [[p.min(), p.max()] for p in pos] ax_rngs = [end[1] - end[0] for end in ax_ends] ax_steps = [rng / resolution for rng in ax_rngs] ax_extents = [ax_ends[p[0]] + ax_ends[p[1]] for p in planes] # create figure reformat = fig is None and ax is None fig, ax = get_fig_ax(fig, ax) ax.set_title(f"Field {dim}D {mesh_type} {field.shape}") if reformat: # only format fig if it was created here fig.set_size_inches(8, 5.5 + 0.5 * (dim - 2)) # init additional axis, radio-buttons and sliders s_frac = 0.5 * (dim - 2) / (6 + 0.5 * (dim - 2)) s_size = s_frac / max(dim - 2, 1) left, bottom = (0.25, s_frac + 0.13) if dim > 2 else (None, None) fig.subplots_adjust(left=left, bottom=bottom) slider = [] for i in range(dim - 2, 0, -1): slider_ax = fig.add_axes([0.3, i * s_size, 0.435, s_size * 0.6]) slider.append(Slider(slider_ax, "", 0, 1, facecolor="grey")) slider[-1].vline.set_color("k") # create radio buttons if dim > 2: rax = fig.add_axes([0.05, 0.85 - 2 * s_frac, 0.15, 2 * s_frac], frame_on=0, alpha=0) rax.set_title(" Plane", loc="left") radio = RadioButtons(rax, plane_names, activecolor="grey") # make radio buttons circular rpos = rax.get_position().get_points() fh, fw = fig.get_figheight(), fig.get_figwidth() rscale = (rpos[:, 1].ptp() / rpos[:, 0].ptp()) * (fh / fw) for circ in radio.circles: circ.set_radius(0.06) circ.height /= rscale elif mesh_type == "unstructured" and convex_hull: # show convex hull in 2D hull = ConvexHull(pos.T) for simplex in hull.simplices: ax.plot(pos[0, simplex], pos[1, simplex], "k") # init imshow and colorbar axis grid = np.mgrid[0:1:resolution * 1j, 0:1:resolution * 1j] f_ini, vmin, vmax = np.full_like(grid[0], np.nan), field.min(), field.max() im = ax.imshow(f_ini.T, interpolation="bicubic", origin="lower", vmin=vmin, vmax=vmax) # actions def inter_plane(cuts, axes): """Interpolate plane.""" plane_ax = [] for i, (rng, end, cut) in enumerate(zip(ax_rngs, ax_ends, cuts)): if i in axes: plane_ax.append(grid[axes.index(i)] * rng + end[0]) else: plane_ax.append(np.full_like(grid[0], cut, dtype=float)) # needs to be a tuple plane_ax = tuple(plane_ax) if mesh_type != "unstructured": return inter.interpn(pos, field, plane_ax, bounds_error=False) return inter.griddata(pos.T, field, plane_ax, method="nearest") def update_field(*args): """Sliders update.""" p = plane_names.index(radio.value_selected) if dim > 2 else 0 # dummy cut values for selected plane-axes (setting to 0) cuts = [s.val for s in slider] cuts.insert(planes[p][0], 0) cuts.insert(planes[p][1], 0) im.set_array(inter_plane(cuts, planes[p]).T) fig.canvas.draw_idle() def update_plane(label): """Radio button update.""" p = plane_names.index(label) cut_select = [i for i in range(dim) if i not in planes[p]] # reset sliders for i, s in zip(cut_select, slider): s.label.set_text(ax_names[i]) s.valmin, s.valmax = ax_ends[i] s.valinit = ax_ends[i][0] + ax_rngs[i] / 2.0 s.valstep = ax_steps[i] s.ax.set_xlim(*ax_ends[i]) # update representation s.poly.xy[:2] = (s.valmin, 0), (s.valmin, 1) s.vline.set_data(2 * [s.valinit], [-0.1, 1.1]) s.reset() im.set_extent(ax_extents[p]) if aspect == "quad": asp = ax_rngs[planes[p][0]] / ax_rngs[planes[p][1]] if aspect is not None: ax.set_aspect(asp if aspect == "quad" else aspect) ax.set_xlabel(ax_names[planes[p][0]]) ax.set_ylabel(ax_names[planes[p][1]]) update_field() # initial plot on xy plane update_plane(plane_names[0]) # bind actions if dim > 2: radio.on_clicked(update_plane) for s in slider: s.on_changed(update_field) if show_colorbar: fig.colorbar(im, ax=ax) fig.show() return ax