def draw_heatmap(colors: Union[pd.DataFrame, pd.Series], axes: mpl.axes.Axes, axis=0, index_order: Union[Sequence[Union[str, int]], None] = None, **kwargs): """ :param colors: pd.Series or pd.DataFrame :param axes: matplotlib axes object :param axis: 0 or 1 :param index_order: the order of colors :param kwargs: passed to `axes.pcolormesh` :return: """ colors = colors.copy() # if index_order is not None: # index_order = list(index_order)[::-1] colors, labels = _process_colors(colors, index_order) matrix, cmap = _color_list_to_matrix_and_cmap(colors, axis=axis) axes.pcolormesh(matrix, cmap=cmap, **kwargs) if axis == 1: axes.set_yticks(_determine_ticks(labels)) axes.set_yticklabels(labels) _ = axes.set_xticks([]) elif axis == 0: axes.set_xticks(_determine_ticks(labels)) axes.set_xticklabels(labels, rotation=90) _ = axes.set_yticks([]) else: raise ValueError('axis must be 0 or 1.') for item in ['left', 'right', 'bottom', 'top']: axes.spines[item].set_visible(False)
def plot_on_a_plain_grid(x: np.ndarray, y: np.ndarray, z: np.ndarray, ax: matplotlib.axes.Axes) -> matplotlib.axes.Axes: """ Plot a heatmap of z using x and y as axes. Assumes that the data are rectangular, i.e. that x and y together describe a rectangular grid. The arrays of x and y need not be sorted in any particular way, but data must belong together such that z[n] has x[n] and y[n] as setpoints. The setpoints need not be equidistantly spaced, but linear interpolation is used to find the edges of the plotted squares. Args: x: The x values y: The y values z: The z values Returns: The matplotlib figure handle """ xrow, yrow, z_to_plot = reshape_2D_data(x, y, z) # we use a general edge calculator, # in the case of non-equidistantly spaced data # TODO: is this appropriate for a log ax? dxs = np.diff(xrow) / 2 dys = np.diff(yrow) / 2 x_edges = np.concatenate((np.array([xrow[0] - dxs[0]]), xrow[:-1] + dxs, np.array([xrow[-1] + dxs[-1]]))) y_edges = np.concatenate((np.array([yrow[0] - dys[0]]), yrow[:-1] + dys, np.array([yrow[-1] + dys[-1]]))) ax.pcolormesh(x_edges, y_edges, np.ma.masked_invalid(z_to_plot)) return ax
def plot_sensor_hit_histogram(axes: mpl.axes.Axes, hist: np.ndarray, x_edges: np.ndarray, y_edges: np.ndarray): """ plot the hitmap of the sensor into a given axes . plots the hitmap of the sensor into a provided axes instance and annotates the plot accordingly """ cmap = cm.get_cmap('viridis', 1024) axes.set_title("Sensor Hitmap") axes.set_xlabel("x [mm]") axes.set_ylabel("y [mm]") axes.pcolormesh(x_edges, y_edges, hist, cmap=cmap)
def _do_mesh(self, a: mpl.axes.Axes, x: np.ndarray, y: np.ndarray): """Create density plot Parameters ---------- a Axes to draw on x, y data """ grid = np.array( np.meshgrid(np.linspace(*self._bounds[0], 200), np.linspace(*self._bounds[1], 200))) grid_flat = np.reshape(grid, (2, -1)) c = self._calc_kde(x, y, *grid_flat).reshape(grid.shape[1:]) a.pcolormesh(*grid, c)
def plot_on_a_plain_grid(x: np.ndarray, y: np.ndarray, z: np.ndarray, ax: matplotlib.axes.Axes, colorbar: matplotlib.colorbar.Colorbar = None, **kwargs) -> AxesTuple: """ Plot a heatmap of z using x and y as axes. Assumes that the data are rectangular, i.e. that x and y together describe a rectangular grid. The arrays of x and y need not be sorted in any particular way, but data must belong together such that z[n] has x[n] and y[n] as setpoints. The setpoints need not be equidistantly spaced, but linear interpolation is used to find the edges of the plotted squares. ``**kwargs`` are passed to matplotlib's pcolormesh used for the plotting. By default the data in any vector plot will be rasterized if more that 5000 points are supplied. This can be overridden by supplying the `rasterized` kwarg. Args: x: The x values y: The y values z: The z values ax: The axis to plot onto colorbar: a colorbar to reuse the axis for Returns: The matplotlib axes handle for plot and colorbar """ xrow, yrow, z_to_plot = reshape_2D_data(x, y, z) # we use a general edge calculator, # in the case of non-equidistantly spaced data # TODO: is this appropriate for a log ax? dxs = np.diff(xrow) / 2 dys = np.diff(yrow) / 2 x_edges = np.concatenate((np.array([xrow[0] - dxs[0]]), xrow[:-1] + dxs, np.array([xrow[-1] + dxs[-1]]))) y_edges = np.concatenate((np.array([yrow[0] - dys[0]]), yrow[:-1] + dys, np.array([yrow[-1] + dys[-1]]))) if 'rasterized' in kwargs.keys(): rasterized = kwargs.pop('rasterized') else: rasterized = len(x_edges) * len(y_edges) \ > qc.config.plotting.rasterize_threshold colormesh = ax.pcolormesh(x_edges, y_edges, np.ma.masked_invalid(z_to_plot), rasterized=rasterized, **kwargs) if colorbar is not None: colorbar = ax.figure.colorbar(colormesh, ax=ax, cax=colorbar.ax) else: colorbar = ax.figure.colorbar(colormesh, ax=ax) return ax, colorbar
def plot_correlations( fig: matplotlib.figure.Figure, ax: matplotlib.axes.Axes, r2: float, slope: float, y_inter: float, corr_vals: np.ndarray, vis_vals: np.ndarray, scale_factor: Union[float, int], corr_bname: str, vis_bname: str, odir: Union[Path, str], ): """ Plot the correlations between NIR band and the visible bands for the Hedley et al. (2005) sunglint correction method Parameters ---------- fig : matplotlib.figure object Reusing a matplotlib.figure object to avoid the creation many fig instantances ax : matplotlib.axes._subplots object Reusing the axes object r2 : float The correlation coefficient squared of the linear regression between NIR and a VIS band slope : float The slope/gradient of the linear regression between NIR and a VIS band y_inter : float The intercept of the linear regression between NIR and a VIS band corr_vals : numpy.ndarray 1D array containing the NIR values from the ROI vis_vals : numpy.ndarray 1D array containing the VIS values from the ROI scale_factor : int or None The scale factor used to convert integers to reflectances that range [0...1] corr_bname : str The NIR band number vis_bname : str The VIS band number odir : str Directory where the correlation plots are saved """ # clear previous plot ax.clear() # ----------------------------------- # # Create a unique cmap for hist2d # # ----------------------------------- # ncolours = 256 # get the jet colormap colour_array = plt.get_cmap("jet")(range(ncolours)) # 256 x 4 # change alpha values # e.g. low values have alpha = 1, high values have alpha = 0 # color_array[:,-1] = np.linspace(1.0,0.0,ncolors) # e.g. low values have alpha = 0, high values have alpha = 1 # color_array[:,-1] = np.linspace(0.0,1.0,ncolors) # We want only the first few colours to have low alpha # as they would represent low density [meshgrid] bins # which we are not interested in, and hence would want # them to appear as a white colour (alpha ~ 0) num_alpha = 25 colour_array[0:num_alpha, -1] = np.linspace(0.0, 1.0, num_alpha) colour_array[num_alpha:, -1] = 1 # create a colormap object cmap = LinearSegmentedColormap.from_list(name="jet_alpha", colors=colour_array) # ----------------------------------- # # Plot density using np.histogram2d # # ----------------------------------- # xbin_low, xbin_high = np.percentile(corr_vals, (1, 99), interpolation="linear") ybin_low, ybin_high = np.percentile(vis_vals, (1, 99), interpolation="linear") nbins = [int(xbin_high - xbin_low), int(ybin_high - ybin_low)] bin_range = [[int(xbin_low), int(xbin_high)], [int(ybin_low), int(ybin_high)]] hist2d, xedges, yedges = np.histogram2d(x=corr_vals, y=vis_vals, bins=nbins, range=bin_range) # normalised hist to range [0...1] then rotate and flip hist2d = np.flipud(np.rot90(hist2d / hist2d.max())) # Mask zeros hist_masked = np.ma.masked_where(hist2d == 0, hist2d) # use pcolormesh to plot the hist2D qm = ax.pcolormesh(xedges, yedges, hist_masked, cmap=cmap) # create a colour bar axes within ax cbaxes = inset_axes( ax, width="3%", height="30%", bbox_to_anchor=(0.37, 0.03, 1, 1), loc="lower center", bbox_transform=ax.transAxes, ) # Add a colour bar inside the axes fig.colorbar( cm.ScalarMappable(cmap=cmap), cax=cbaxes, ticks=[0.0, 1], orientation="vertical", label="Point Density", ) # ----------------------------------- # # Plot linear regression line # # ----------------------------------- # x_range = np.array([xbin_low, xbin_high]) (ln, ) = ax.plot( x_range, slope * (x_range) + y_inter, color="k", linestyle="-", label="linear regr.", ) # ----------------------------------- # # Format the figure # # ----------------------------------- # # add legend (top left) lgnd = ax.legend(loc=2, fontsize=10) # add annotation ann_str = (r"$r^{2}$" + " = {0:0.2f}\n" "slope = {1:0.2f}\n" "y-inter = {2:0.2f}".format(r2, slope, y_inter)) ann = ax.annotate(ann_str, xy=(0.02, 0.76), xycoords="axes fraction", fontsize=10) # Add labels to figure xlabel = f"Reflectance ({corr_bname})" ylabel = f"Reflectance ({vis_bname})" if scale_factor is not None: if scale_factor > 1: xlabel += " " + r"$\times$" + " {0}".format(int(scale_factor)) ylabel += " " + r"$\times$" + " {0}".format(int(scale_factor)) ax.set_xlabel(xlabel) ax.set_ylabel(ylabel) # plt.show(); sys.exit() # Save figure png_file = os.path.join( odir, "Correlation_{0}_vs_{1}.png".format(corr_bname, vis_bname)) fig.savefig(png_file, format="png", bbox_inches="tight", pad_inches=0.1, dpi=300) # delete all lines and annotations from figure, # so it can be reused in the next iteration qm.remove() ln.remove() ann.remove() lgnd.remove()
def plot_on_a_plain_grid(x: np.ndarray, y: np.ndarray, z: np.ndarray, ax: matplotlib.axes.Axes, colorbar: matplotlib.colorbar.Colorbar = None, **kwargs: Any) -> AxesTuple: """ Plot a heatmap of z using x and y as axes. Assumes that the data are rectangular, i.e. that x and y together describe a rectangular grid. The arrays of x and y need not be sorted in any particular way, but data must belong together such that z[n] has x[n] and y[n] as setpoints. The setpoints need not be equidistantly spaced, but linear interpolation is used to find the edges of the plotted squares. ``**kwargs`` are passed to matplotlib's pcolormesh used for the plotting. By default the data in any vector plot will be rasterized if more that 5000 points are supplied. This can be overridden by supplying the `rasterized` kwarg. Args: x: The x values y: The y values z: The z values ax: The axis to plot onto colorbar: A colorbar to reuse the axis for Returns: The matplotlib axes handle for plot and colorbar """ log.debug(f'Got kwargs: {kwargs}') x_is_stringy = isinstance(x[0], str) y_is_stringy = isinstance(y[0], str) z_is_stringy = isinstance(z[0], str) if x_is_stringy: x_strings = np.unique(x) x = _strings_as_ints(x) if y_is_stringy: y_strings = np.unique(y) y = _strings_as_ints(y) if z_is_stringy: z_strings = np.unique(z) z = _strings_as_ints(z) if x.ndim == 2 and y.ndim == 2 and z.ndim == 2: if not np.logical_or(np.any(np.isnan(x)), np.any(np.isnan(y))): # data is on a grid that may or may not be # rectilinear. Rely on matplotlib to plot # this directly x_to_plot, y_to_plot, z_to_plot = x, y, z num_points = x_to_plot.size else: x_to_plot, y_to_plot, z_to_plot = _clip_nan_from_shaped_data( x, y, z) num_points = x_to_plot.size * y_to_plot.size else: x_to_plot, y_to_plot, z_to_plot = reshape_2D_data(x, y, z) num_points = x_to_plot.size * y_to_plot.size if 'rasterized' in kwargs.keys(): rasterized = kwargs.pop('rasterized') else: rasterized = num_points > qc.config.plotting.rasterize_threshold cmap = kwargs.pop('cmap') if 'cmap' in kwargs else None if z_is_stringy: name = cmap.name if hasattr(cmap, 'name') else 'viridis' cmap = matplotlib.cm.get_cmap(name, len(z_strings)) colormesh = ax.pcolormesh( x_to_plot, y_to_plot, np.ma.masked_invalid(z_to_plot), rasterized=rasterized, cmap=cmap, shading="nearest", **kwargs, ) if x_is_stringy: ax.set_xticks(np.arange(len(np.unique(x_strings)))) ax.set_xticklabels(x_strings) if y_is_stringy: ax.set_yticks(np.arange(len(np.unique(y_strings)))) ax.set_yticklabels(y_strings) if colorbar is not None: colorbar = ax.figure.colorbar(colormesh, ax=ax, cax=colorbar.ax) else: colorbar = ax.figure.colorbar(colormesh, ax=ax) if z_is_stringy: N = len(z_strings) f = (N - 1) / N colorbar.set_ticks([(n + 0.5) * f for n in range(N)]) colorbar.set_ticklabels(z_strings) return ax, colorbar
def plot_on_a_plain_grid(x: np.ndarray, y: np.ndarray, z: np.ndarray, ax: matplotlib.axes.Axes, colorbar: matplotlib.colorbar.Colorbar=None, **kwargs ) -> AxesTuple: """ Plot a heatmap of z using x and y as axes. Assumes that the data are rectangular, i.e. that x and y together describe a rectangular grid. The arrays of x and y need not be sorted in any particular way, but data must belong together such that z[n] has x[n] and y[n] as setpoints. The setpoints need not be equidistantly spaced, but linear interpolation is used to find the edges of the plotted squares. ``**kwargs`` are passed to matplotlib's pcolormesh used for the plotting. By default the data in any vector plot will be rasterized if more that 5000 points are supplied. This can be overridden by supplying the `rasterized` kwarg. Args: x: The x values y: The y values z: The z values ax: The axis to plot onto colorbar: a colorbar to reuse the axis for Returns: The matplotlib axes handle for plot and colorbar """ log.debug(f'Got kwargs: {kwargs}') x_is_stringy = isinstance(x[0], str) y_is_stringy = isinstance(y[0], str) z_is_stringy = isinstance(z[0], str) if x_is_stringy: x_strings = np.unique(x) x = _strings_as_ints(x) if y_is_stringy: y_strings = np.unique(y) y = _strings_as_ints(y) if z_is_stringy: z_strings = np.unique(z) z = _strings_as_ints(z) xrow, yrow, z_to_plot = reshape_2D_data(x, y, z) # we use a general edge calculator, # in the case of non-equidistantly spaced data # TODO: is this appropriate for a log ax? dxs = np.diff(xrow)/2 dys = np.diff(yrow)/2 x_edges = np.concatenate((np.array([xrow[0] - dxs[0]]), xrow[:-1] + dxs, np.array([xrow[-1] + dxs[-1]]))) y_edges = np.concatenate((np.array([yrow[0] - dys[0]]), yrow[:-1] + dys, np.array([yrow[-1] + dys[-1]]))) if 'rasterized' in kwargs.keys(): rasterized = kwargs.pop('rasterized') else: rasterized = len(x_edges) * len(y_edges) \ > qc.config.plotting.rasterize_threshold cmap = kwargs.pop('cmap') if 'cmap' in kwargs else None if z_is_stringy: name = cmap.name if hasattr(cmap, 'name') else 'viridis' cmap = matplotlib.cm.get_cmap(name, len(z_strings)) colormesh = ax.pcolormesh(x_edges, y_edges, np.ma.masked_invalid(z_to_plot), rasterized=rasterized, cmap=cmap, **kwargs) if x_is_stringy: ax.set_xticks(np.arange(len(np.unique(x_strings)))) ax.set_xticklabels(x_strings) if y_is_stringy: ax.set_yticks(np.arange(len(np.unique(y_strings)))) ax.set_yticklabels(y_strings) if colorbar is not None: colorbar = ax.figure.colorbar(colormesh, ax=ax, cax=colorbar.ax) else: colorbar = ax.figure.colorbar(colormesh, ax=ax) if z_is_stringy: N = len(z_strings) f = (N-1)/N colorbar.set_ticks([(n+0.5)*f for n in range(N)]) colorbar.set_ticklabels(z_strings) return ax, colorbar
def plot_polar_histogram( values: np.ndarray, r_edges: np.ndarray, theta_edges: np.ndarray, ax: mpl.axes.Axes = None, # Not sure how to type this (not optional # but hard to find default) cmap: Optional[str] = None, vmin: Optional[float] = None, vmax: Optional[float] = None, symmetric_color_limits: bool = False, interpolation_factor: float = 5, angle_convention: str = "clock", ): """Plot color polar plot :param values: Values to color-code :param r_edges: Edges in radius :param theta_edges: Edges in angle :param ax: matplotlib.axes.Axes. Needs to be `polar=True` :param cmap: matplotlib colormap :param vmin: lower limit of colorbar range. If None, from data :param vmax: upper limit of colorbar range. If None, from data :param symmetric_color_limits: How to obtain lower and upper limits of colormap from data. If False, limits are (min, max). If True, limits are (-max(abs), max(abs)) :param interpolation_factor: If None or 1, no interpolation is performed. If int > 1, each sector is broken in interpolation_factor parts, so they look more circular and less polygonal :param angle_convention: If "clock", angles increase clockwise and are 0 for positive y axis. If "math", angles increase counterclockwise and are 0 for positive x axis """ if interpolation_factor is not None: values, theta_edges, r_edges = interpolate_polarmap_angles( values, theta_edges, r_edges, factor=interpolation_factor) theta, r = np.meshgrid(theta_edges, r_edges) # Select color limits: if symmetric_color_limits: vmax_ = np.nanmax(np.abs(values)) vmin_ = -vmax_ else: vmax_ = np.nanmax(values) vmin_ = np.nanmin(values) # Only use them if not specified in input if vmin is None: vmin = vmin_ if vmax is None: vmax = vmax_ # Plot histogram/map fig = ax.get_figure() im = ax.pcolormesh(theta, r, values, cmap=cmap, vmin=vmin, vmax=vmax) fig.colorbar(im, ax=ax, cmap=cmap) if angle_convention == "clock": # Adjusting axis and sense of rotation to make it compatible # with [2]: Direction of movement is y axis, angles increase clockwise ax.set_theta_zero_location("N") ax.set_theta_direction(-1)