def _rescale_ticks_and_units( ax: matplotlib.axes.Axes, data: Sequence[DSPlotData], cax: matplotlib.colorbar.Colorbar = None, ) -> None: """ Rescale ticks and units for the provided axes as described in :func:`~_make_rescaled_ticks_and_units` """ # for x axis if not _is_string_valued_array(data[0]['data']): x_ticks_formatter, new_x_label = \ _make_rescaled_ticks_and_units(data[0]) ax.xaxis.set_major_formatter(x_ticks_formatter) ax.set_xlabel(new_x_label) # for y axis if not _is_string_valued_array(data[1]['data']): y_ticks_formatter, new_y_label = \ _make_rescaled_ticks_and_units(data[1]) ax.yaxis.set_major_formatter(y_ticks_formatter) ax.set_ylabel(new_y_label) # for z aka colorbar axis if cax is not None and len(data) > 2: if not _is_string_valued_array(data[2]['data']): z_ticks_formatter, new_z_label = \ _make_rescaled_ticks_and_units(data[2]) cax.set_label(new_z_label) cax.formatter = z_ticks_formatter cax.update_ticks()
def _rescale_ticks_and_units(ax: matplotlib.axes.Axes, data: List[Dict[str, Any]], cax: matplotlib.colorbar.Colorbar = None): """ Rescale ticks and units for the provided axes as described in :meth:`~_make_rescaled_ticks_and_units` """ # for x axis x_ticks_formatter, new_x_label = _make_rescaled_ticks_and_units(data[0]) if x_ticks_formatter is not None and new_x_label is not None: ax.xaxis.set_major_formatter(x_ticks_formatter) ax.set_xlabel(new_x_label) # for y axis y_ticks_formatter, new_y_label = _make_rescaled_ticks_and_units(data[1]) if y_ticks_formatter is not None and new_y_label is not None: ax.yaxis.set_major_formatter(y_ticks_formatter) ax.set_ylabel(new_y_label) # for z aka colorbar axis if cax is not None and len(data) > 2: z_ticks_formatter, new_z_label = _make_rescaled_ticks_and_units( data[2]) if z_ticks_formatter is not None and new_z_label is not None: cax.set_label(new_z_label) cax.formatter = z_ticks_formatter cax.update_ticks()
def _set_colorbar_extend(colorbar: matplotlib.colorbar.Colorbar, extend: str): """ Workaround for a missing setter for the extend property of a matplotlib colorbar. The colorbar object in matplotlib has no setter method and setting the colorbar extend does not take any effect. Calling a subsequent update will cause a runtime error because of the internal implementation of the rendering of the colorbar. To circumvent this we need to manually specify the property `_inside`, which is a slice that describes which of the colorbar levels lie inside of the box and it is thereby dependent on the extend. Args: colorbar: the colorbar for which to set the extend extend: the desired extend ('neither', 'both', 'min' or 'max') """ colorbar.extend = extend _slice_dict = { 'neither': slice(0, None), 'both': slice(1, -1), 'min': slice(1, None), 'max': slice(0, -1) } colorbar._inside = _slice_dict[extend]
def plot_2d_scatterplot(x: np.ndarray, y: np.ndarray, z: np.ndarray, ax: matplotlib.axes.Axes, colorbar: matplotlib.colorbar.Colorbar = None, **kwargs: Any) -> AxesTuple: """ Make a 2D scatterplot of the data. ``**kwargs`` are passed to matplotlib's scatter used for the plotting. By default the data will be rasterized in any vector plot if more than 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: The colorbar to plot into Returns: The matplotlib axis handles for plot and colorbar """ if 'rasterized' in kwargs.keys(): rasterized = kwargs.pop('rasterized') else: rasterized = len(z) > qc.config.plotting.rasterize_threshold z_is_stringy = isinstance(z[0], str) if z_is_stringy: z_strings = np.unique(z) z = _strings_as_ints(z) 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)) mappable = ax.scatter(x=x, y=y, c=z, rasterized=rasterized, cmap=cmap, **kwargs) if colorbar is not None: colorbar = ax.figure.colorbar(mappable, ax=ax, cax=colorbar.ax) else: colorbar = ax.figure.colorbar(mappable, 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: 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