Skip to content

Commit d06fb2f

Browse files
Implementing blitting for colorbar indicators (#168)
Co-authored-by: Patrick Shriwise <pshriwise@gmail.com>
1 parent df7599c commit d06fb2f

1 file changed

Lines changed: 86 additions & 19 deletions

File tree

openmc_plotter/plotgui.py

Lines changed: 86 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,18 @@ def __init__(self, model: PlotModel, parent, main_window):
4444
self.x_plot_origin = None
4545
self.y_plot_origin = None
4646

47-
self.colorbar = None
47+
self.property_colorbar = None
4848
self.data_indicator = None
4949
self.tally_data_indicator = None
50+
self.tally_colorbar = None
51+
self.tally_image = None
5052
self.image = None
5153

54+
self._property_colorbar_bg = None
55+
self._tally_colorbar_bg = None
56+
self._last_tally_indicator_value = None
57+
self._last_data_indicator_value = None
58+
5259
self.menu = QMenu(self)
5360

5461
def enterEvent(self, event):
@@ -526,20 +533,21 @@ def updatePixmap(self):
526533
alpha=cv.domainAlpha)
527534

528535
# add colorbar
529-
self.colorbar = self.figure.colorbar(self.image,
530-
anchor=(1.0, 0.0))
531-
self.colorbar.set_label(cmap_label,
532-
rotation=-90,
533-
labelpad=15)
536+
self.property_colorbar = self.figure.colorbar(self.image,
537+
anchor=(1.0, 0.0))
538+
self.property_colorbar.set_label(cmap_label,
539+
rotation=-90,
540+
labelpad=15)
534541
# draw line on colorbar
535-
dl = self.colorbar.ax.dataLim.get_points()
542+
dl = self.property_colorbar.ax.dataLim.get_points()
536543
self.data_indicator = mlines.Line2D(dl[:][0],
537544
[0.0, 0.0],
538545
linewidth=3.,
539546
color='blue',
540547
clip_on=True)
541-
self.colorbar.ax.add_line(self.data_indicator)
542-
self.colorbar.ax.margins(0.0, 0.0)
548+
self.data_indicator.set_animated(True)
549+
self.property_colorbar.ax.add_line(self.data_indicator)
550+
self.property_colorbar.ax.margins(0.0, 0.0)
543551
self.updateDataIndicatorVisibility()
544552
self.updateColorMinMax(cv.colorby)
545553

@@ -626,6 +634,7 @@ def updatePixmap(self):
626634
linewidth=3.,
627635
color='blue',
628636
clip_on=True)
637+
self.tally_data_indicator.set_animated(True)
629638
self.tally_colorbar.ax.add_line(self.tally_data_indicator)
630639
self.tally_colorbar.ax.margins(0.0, 0.0)
631640

@@ -655,6 +664,9 @@ def updatePixmap(self):
655664
self.ax.dataLim.y1 = data_bounds[3]
656665

657666
self.draw()
667+
self._cache_colorbar_backgrounds()
668+
self._blit_indicator(self.data_indicator, self.property_colorbar)
669+
self._blit_indicator(self.tally_data_indicator, self.tally_colorbar)
658670
return "Done"
659671

660672
def current_view_data_bounds(self):
@@ -740,21 +752,63 @@ def parseContoursLine(line):
740752
def updateColorbarScale(self):
741753
self.updatePixmap()
742754

755+
def _cache_colorbar_backgrounds(self):
756+
"""Cache colorbar backgrounds for fast indicator blitting."""
757+
self._property_colorbar_bg = None
758+
self._tally_colorbar_bg = None
759+
760+
if self.property_colorbar and self.data_indicator:
761+
self._property_colorbar_bg = self.copy_from_bbox(
762+
self.property_colorbar.ax.bbox)
763+
764+
if self.tally_colorbar and self.tally_data_indicator:
765+
self._tally_colorbar_bg = self.copy_from_bbox(
766+
self.tally_colorbar.ax.bbox)
767+
768+
def _blit_indicator(self, indicator, colorbar):
769+
"""Blit a single indicator line onto its colorbar if possible."""
770+
if colorbar is None or indicator is None:
771+
return False
772+
773+
if not indicator.get_visible():
774+
return False
775+
776+
if colorbar is self.property_colorbar:
777+
background = self._property_colorbar_bg
778+
else:
779+
background = self._tally_colorbar_bg
780+
781+
if background is None:
782+
return False
783+
784+
self.restore_region(background)
785+
colorbar.ax.draw_artist(indicator)
786+
self.blit(colorbar.ax.bbox)
787+
return True
788+
743789
def updateTallyDataIndicatorValue(self, y_val):
744790
cv = self.model.currentView
745791

746792
if not cv.tallyDataVisible or not cv.tallyDataIndicator:
747793
return
748794

749-
if self.tally_data_indicator is not None:
750-
data = self.tally_data_indicator.get_data()
795+
if self.tally_data_indicator is not None and self.tally_image is not None:
751796
# use norm to get axis value if log scale
752797
if cv.tallyDataLogScale:
753798
y_val = self.tally_image.norm(y_val)
799+
800+
# If indicator value hasn't changed, skip update
801+
if self._last_tally_indicator_value == y_val:
802+
return
803+
self._last_tally_indicator_value = y_val
804+
805+
data = self.tally_data_indicator.get_data()
754806
self.tally_data_indicator.set_data([data[0], [y_val, y_val]])
755807
dl_color = invert_rgb(self.tally_image.get_cmap()(y_val), True)
756808
self.tally_data_indicator.set_c(dl_color)
757-
self.draw()
809+
810+
if not self._blit_indicator(self.tally_data_indicator, self.tally_colorbar):
811+
self.draw_idle()
758812

759813
def updateDataIndicatorValue(self, y_val):
760814
cv = self.model.currentView
@@ -763,38 +817,51 @@ def updateDataIndicatorValue(self, y_val):
763817
not cv.data_indicator_enabled[cv.colorby]:
764818
return
765819

766-
if self.data_indicator:
767-
data = self.data_indicator.get_data()
820+
if self.data_indicator and self.image is not None:
768821
# use norm to get axis value if log scale
769822
if cv.color_scale_log[cv.colorby]:
770823
y_val = self.image.norm(y_val)
824+
825+
# If indicator value hasn't changed, skip update
826+
if self._last_data_indicator_value == y_val:
827+
return
828+
self._last_data_indicator_value = y_val
829+
830+
data = self.data_indicator.get_data()
771831
self.data_indicator.set_data([data[0], [y_val, y_val]])
772832
dl_color = invert_rgb(self.image.get_cmap()(y_val), True)
773833
self.data_indicator.set_c(dl_color)
774-
self.draw()
834+
835+
if not self._blit_indicator(self.data_indicator, self.property_colorbar):
836+
self.draw_idle()
775837

776838
def updateDataIndicatorVisibility(self):
777839
cv = self.model.currentView
778840
if self.data_indicator and cv.colorby in _MODEL_PROPERTIES:
779841
val = cv.data_indicator_enabled[cv.colorby]
780842
self.data_indicator.set_visible(val)
781-
self.draw()
843+
if not self._blit_indicator(self.data_indicator, self.property_colorbar):
844+
self.draw_idle()
782845

783846
def updateColorMap(self, colormap_name, property_type):
784-
if self.colorbar and property_type == self.model.activeView.colorby:
847+
if self.property_colorbar and property_type == self.model.activeView.colorby:
785848
self.image.set_cmap(colormap_name)
786849
self.figure.draw_without_rendering()
787850
self.draw()
851+
self._cache_colorbar_backgrounds()
852+
self._blit_indicator(self.data_indicator, self.property_colorbar)
788853

789854
def updateColorMinMax(self, property_type):
790855
av = self.model.activeView
791-
if self.colorbar and property_type == av.colorby:
856+
if self.property_colorbar and property_type == av.colorby:
792857
clim = av.getColorLimits(property_type)
793-
self.colorbar.mappable.set_clim(*clim)
858+
self.property_colorbar.mappable.set_clim(*clim)
794859
self.data_indicator.set_data(clim[:2],
795860
(0.0, 0.0))
796861
self.figure.draw_without_rendering()
797862
self.draw()
863+
self._cache_colorbar_backgrounds()
864+
self._blit_indicator(self.data_indicator, self.property_colorbar)
798865

799866

800867
class ColorDialog(QDialog):

0 commit comments

Comments
 (0)