def color_translator(**kw): """ Translates colors specified in the Matplotlib system into pyqtgraph color descriptions :param kw: dict Dictionary of Matplotlib style plot keywords in which color may be specified. The entire set of mpl plot keywords may be passed in, although only color-relevant ones will be used. :return: iterable An RGBA color description (each from 0 to 255) for use with pyqtgraph """ if 'color' in kw and kw['color'] is not None: try: printd( ' color_translator input: kw["color"] = {}, to_rgba(kw.get("color", None)) = {}' .format(kw.get('color', None), to_rgba(kw.get('color', None))), level=3) except ValueError: printd(' color_translator input: kw["color"] = {}'.format( kw.get('color', None)), level=3) if kw['color'] in ['', ' ']: return 0, 0, 0, 0 # Empty strings and spaces are code for invisible (alpha = 0) elif 'alpha' in kw and kw['alpha'] is not None: return np.append(np.array(to_rgba(kw['color']))[0:3], kw['alpha']) * 255 else: return np.array(to_rgba(kw['color'])) * 255 else: return (0, 0, 0, int( round(kw['alpha'] * 255))) if 'alpha' in kw and kw['alpha'] is not None else None
def plot(self, *args, **kwargs): """ Translates arguments and keywords to matplotlib.axes.Axes.plot() method so they can be passed to pg.PlotItem.plot() instead. See https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.axes.Axes.plot.html :param args: Plot arguments They will be passed straight through to plot() :param kwargs: Plot keywords They will be translated from mpl to pg conventions and then passed to plot() :return: plotItem instance returned by pg.PlotItem.plot() """ need_cycle = any( [k not in kwargs.keys() for k in self.prop_cycle.keys]) if need_cycle: printd('keys needed', list(self.prop_cycle.keys), level=2) cur = self.cyc for k in self.prop_cycle.keys: if k not in kwargs.keys(): kwargs[str(k)] = cur[self.prop_cycle_index][k] printd('kwargs["{}"] = {}'.format(k, kwargs[str(k)]), level=2) self.prop_cycle_index += 1 if self.prop_cycle_index > len(self.prop_cycle): self.prop_cycle_index = 0 return super(Axes, self).plot(*args, **plotkw_translator(**kwargs))
def clear(self): """Removes the legend from Axes instance""" printd(' Clearing legend {}...'.format(self.leg)) try: self.leg.scene().removeItem(self.leg) # https://stackoverflow.com/a/42794442/6605826 except AttributeError: printd(' Could not clear legend (maybe it is already invisible?')
def window_closed(self, win): if win in self.open_windows: printd(' tracker detected window closed: {}'.format(win)) self.open_windows.remove(win) else: warnings.warn( ' tracker received notification of closing of untracked window!' ) self.status()
def clear(self): """ Clears the axes https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.axes.Axes.clear.html """ printd(' Clearing Axes instance {}...'.format(self)) super(Axes, self).clear() self.legend.clear() self.prop_cycle_index = 0
def closeEvent(self, event): """ Intercepts window closing events and updates window tracker Not an imitation of matplotlib, but used for interfacing with pyqtgraph behavior :param event: window closing event """ printd('window closing') tracker.window_closed(self) event.accept() return
def contourf(self, *args, **kwargs): """ Initializes a QuadContourSet instance for the current Axes with filled=True enforced https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.axes.Axes.contourf.html :return: QuadContourSet instance """ printd(' pgmpl.axes.Axes.contourf()...') kwargs['filled'] = True return QuadContourSet(self, *args, **kwargs)
def handle_info(handles, comment=None): """For debugging: prints information on legend handles""" if comment is not None: printd(comment) for i, handle in enumerate(tolist(handles)): printd(' {i:02d} handle name: {name:}, class: {cls:}, isVisible: {isvis:}'.format( i=i, name=getattr(handle, 'name', None), cls=getattr(handle, '__class__', ' not found '), isvis=getattr(handle, 'isVisible', None), ))
def color_map_translator(x, **kw): """ Translates colors for a matplotlib colormap and a dataset, such as would be used for scatter, imshow, contour, etc. :param x: numeric scalar or iterable Data to be mapped. Very boring if scalar. :param cmap: string Color map nape, passed to matplotlib.cm.get_cmap() :param norm: matplotlib normalization class Defaults to new instance of mpl.colors.Normalize :param vmin: numeric Lower limit passed to new Normalize instance if norm is None; ignored if norm is provided. :param vmax: numeric Lower limit passed to new Normalize instance if norm is None; ignored if norm is provided. :param clip: bool Passed to Normalize if a new Normalize instance is created. Otherwise, not used. :param ncol: int passed to Colormap to set number of colors :param alpha: float: opacity from 0 to 1 or None :return: list List of pyqtgraph-compatible color specifications with length matching x """ printd('color_map_translator...') norm = kw.pop('norm', None) if norm is None: printd(' norm was None, normalizing...') norm = Normalize(vmin=kw.pop('vmin', None), vmax=kw.pop('vmax', None), clip=kw.pop('clip', False)) comap = matplotlib.cm.get_cmap(kw.pop('cmap', None), lut=kw.pop('ncol', 256)) colors = comap(norm(np.atleast_1d(x))) return [ color_translator(color=color, alpha=kw.get('alpha', None)) for color in tolist(colors) ]
def __call__(self, handles=None, labels=None, **kw): """ Adds a legend to the plot axes. This class should be added to axes as they are created so that calling it acts like a method of the class and adds a legend, imitating matplotlib legend calling. """ printd(' custom legend call') self.leg = self.ax.addLegend() # ax.addLegend modifies ax.legend, so we have to put it back in order to # preserve a reference to pgmpl.axes.Legend. self.ax.legend = self handles = tolist(handles if handles is not None else self.get_visible_handles()) for handle, label in zip(*self._cleanup_legend_labels(handles, labels)): if self.supported(handle): self.leg.addItem(handle, label) self.check_call_kw(**kw) return self
def test_printd(self): test_string_1 = '\nthis string should print, but the other string should not' test_string_2 = '\nthis string should NOT print, but the other string SHOULD' debug = os.environ.get('PGMPL_DEBUG', "0") os.environ['PGMPL_DEBUG'] = "1" printd(test_string_1) printd('this-should-print:', 'test-item-1a', 'test_item_2a_in-list-of-things', 5, 6, 'more-things-in-the-list') os.environ['PGMPL_DEBUG'] = "0" printd(test_string_2) printd('SHOULD-NOT-PRINT:', 'test-item-1b', 'testitem2b-in-a-listofthings', 5, 6.1, 'morelistlol', 'blah') os.environ['PGMPL_DEBUG'] = debug # Put it back how it was (polite~~)
def _setup_fill_between_colors(**kwargs): """ Prepares edge plotting keywords and brush for fill_between :param kwargs: dictionary of keywords from fill_between :return: dict, brush """ # Set up colors and display settings ekw = copy.deepcopy(kwargs) ekw['color'] = ekw.pop('edgecolor', ekw.pop('color', 'k')) if 'facecolor' in kwargs: brush = color_translator(color=kwargs['facecolor'], alpha=kwargs.get('alpha', None)) elif 'color' in kwargs: brush = color_translator(color=kwargs['color'], alpha=kwargs.get('alpha', None)) else: brush = color_translator(color='b', alpha=kwargs.get('alpha', None)) printd( ' pgmpl.axes.Axes.fill_between(): brush = {}, ekw = {}, setup_pen_kw(**ekw) = {}' .format(brush, ekw, setup_pen_kw(**ekw))) return ekw, brush
def __init__(self, ax, **kw): self.check_kw(**kw) self.orientation = kw.pop('orientation', 'vertical') printd( 'ColorbarBase.__init__: mappable.vmin = {}, mappable.vmax = {}, ' 'orientation = {}'.format(self.mappable.vmin, self.mappable.vmax, self.orientation)) a = np.linspace(0, 1, 256).reshape(256, 1) if self.orientation == 'horizontal': ylim = [0, 1] xlim = [self.mappable.vmin, self.mappable.vmax] a = a.T show_ax = 'bottom' else: xlim = [0, 1] ylim = [self.mappable.vmin, self.mappable.vmax] show_ax = 'right' extent = tuple(xlim + ylim) ax.imshow( a, cmap=kw.get('cmap', None), norm=kw.get('norm', None), alpha=kw.get('alpha', None), origin='lower', extent=extent, ) ax.set_ylim(ylim) ax.set_xlim(xlim) for ax_side in ['top', 'bottom', 'right', 'left']: if ax_side == show_ax: ax.showAxis(ax_side) else: ax.hideAxis(ax_side) ax.setLabel(show_ax, text=kw.get('label', '')) ax.setMouseEnabled(x=False, y=False)
def _setup_fill_between_where(x, **kwargs): """ Handles where and interpolate keywords :param x: x values :param kwargs: dictionary of keywords received by fill_between :return: tuple with two lists of ints giving start and end indices for each segment of data passing where """ if kwargs.get('where', None) is not None: if kwargs.pop('interpolate', False): warnings.warn( 'Warning: interpolate keyword to fill_between is not handled yet.' ) d = np.diff(np.append(0, kwargs['where'])) start_i = np.where(d == 1)[0] end_i = np.where(d == -1)[0] if len(end_i) < len(start_i): end_i = np.append(end_i, len(d)) printd(' fill_between where: start_i = {}, end_i = {}'.format( start_i, end_i)) else: start_i = [0] end_i = [len(x)] return start_i, end_i
from pyqtgraph import QtGui # Plotting imports import pyqtgraph as pg from matplotlib import rcParams # pgmpl imports from pgmpl.info import * # Defines __version__, etc. from pgmpl.util import printd from pgmpl.translate import color_translator __all__ = ['figure', 'axes', 'pyplot', 'translate', 'text', 'util'] # Handle debugging if os.environ.get('PGMPL_DEBUG', None) is None: os.environ['PGMPL_DEBUG'] = "0" # Setup style, etc. pg.setConfigOption('background', color_translator(**{'color': rcParams['axes.facecolor']})) pg.setConfigOption('foreground', color_translator(**{'color': rcParams['axes.edgecolor']})) # Check for an existing QApp and make one if none found so that windows can be opened app = QtGui.QApplication.instance() if app is None: printd('No pre-existing QApplication found. Creating one...') app = QtGui.QApplication(sys.argv) else: printd('Using pre-existing QApplication.')
def status(self): printd(' {} tracked windows = {}'.format(len(self.open_windows), self.open_windows))
def window_opened(self, win): printd(' tracker detected new window opened: {}'.format(win)) self.open_windows += [win] self.status()
def __init__(self, ax, mappable, **kw): printd('pgmpl.colorbar.Colorbar.__init__()...') self.mappable = mappable kw['cmap'] = mappable.cmap kw['norm'] = mappable.norm super(Colorbar, self).__init__(ax, **kw)