@@ -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
800867class ColorDialog (QDialog ):
0 commit comments