Source code for sofia_redux.visualization.display.blitting

#  Licensed under a 3-clause BSD style license - see LICENSE.rst

from matplotlib.backends.backend_agg import FigureCanvasAgg

from sofia_redux.visualization import log
from sofia_redux.visualization.display.gallery import Gallery


__all__ = ['BlitManager']


[docs] class BlitManager(object): """ Manage drawing for background and animated artists. Parameters ---------- canvas : FigureCanvasAgg The canvas to work with, this only works for sub-classes of the Agg canvas which have the `~FigureCanvasAgg.copy_from_bbox` and `~FigureCanvasAgg.restore_region` methods. gallery : sofia_redux.visualization.display.artist.Gallery Gallery instance that tracks all artists to draw. signals : sofia_redux.visualization.signals.Signals Collection of PyQt signals for passing on information to other parts of the Eye. Attributes ---------- draw_cid : int The matplotlib event CID for the draw_event signal. """ def __init__(self, canvas: FigureCanvasAgg, gallery: Gallery, signals) -> None: self._canvas = canvas self._gallery = gallery self._background = None self._signals = signals self.draw_cid = self._canvas.mpl_connect('draw_event', self.update_all)
[docs] def reset_background(self) -> None: """Reset the canvas background.""" self._background = None
[docs] def safe_draw(self) -> None: """ Draw the canvas. Disconnect the draw event signal before drawing, and reconnect it afterward. """ self._canvas.mpl_disconnect(self.draw_cid) self._canvas.draw() self.draw_cid = self._canvas.mpl_connect('draw_event', self.update_all)
[docs] def update_background(self) -> None: """Update the canvas background.""" self.safe_draw() self._background = self._canvas.copy_from_bbox( self._canvas.fig.bbox)
[docs] def update_animated(self) -> None: """Update all animated artists.""" self.blit()
[docs] def update_all(self, event=None) -> None: """Update the background and artists.""" self.update_background() self._draw_animated() self._catch_overlaps()
[docs] def blit(self) -> None: """ Blit the canvas. Restore the background without updating it, then update the animated artists on top of the restored background. """ self._canvas.restore_region(self._background) self._draw_animated() self._canvas.blit(self._canvas.fig.bbox) self._canvas.flush_events()
def _draw_animated(self) -> None: """Draw all animated artists.""" artists = self._gallery.gather_artists(mode='viable') log.debug(f'Drawing {len(artists)} artists') for artist in artists: self._canvas.figure.draw_artist(artist) def _catch_overlaps(self): renderer = self._canvas.get_renderer() updated = self._gallery.catch_label_overlaps(renderer) if updated: self._signals.atrophy_bg_partial.emit()