1010from matplotlib .backends .backend_qtagg import FigureCanvas
1111from matplotlib .figure import Figure
1212from matplotlib .lines import Line2D
13- from matplotlib .patches import Circle
13+ from matplotlib .patches import Circle , Polygon
1414from matplotlib .ticker import AutoLocator , AutoMinorLocator , FuncFormatter
1515
1616import matplotlib as mpl
@@ -122,6 +122,10 @@ def setup_connections(self):
122122 HexrdConfig ().oscillation_stage_changed .connect (
123123 self .oscillation_stage_changed )
124124 MaskManager ().polar_masks_changed .connect (self .polar_masks_changed )
125+ # Update mask highlights without re-running expensive mask logic
126+ MaskManager ().mask_highlights_changed .connect (
127+ self .mask_highlights_changed
128+ )
125129 HexrdConfig ().overlay_renamed .connect (self .overlay_renamed )
126130 HexrdConfig ().azimuthal_options_modified .connect (
127131 self .update_azimuthal_integral_plot )
@@ -302,8 +306,10 @@ def load_images(self, image_names):
302306
303307 self .raw_view_images_dict = computed_images_dict
304308 self .clear_mask_boundaries ()
309+ self .clear_mask_highlights ()
305310 for name , axis in self .raw_axes .items ():
306311 self .draw_mask_boundaries (axis , name )
312+ self .highlight_masks (axis , name )
307313
308314 # This will call self.draw_idle()
309315 self .show_saturation ()
@@ -394,6 +400,10 @@ def blit_artists(self):
394400 def overlay_artists (self ):
395401 return self .blit_artists .setdefault ('overlays' , {})
396402
403+ @property
404+ def mask_highlight_artists (self ):
405+ return self .blit_artists .setdefault ('mask_highlights' , {})
406+
397407 def remove_all_overlay_artists (self ):
398408 self .blit_manager .remove_artists ('overlays' )
399409 self .blit_manager .artists ['overlays' ] = {}
@@ -1238,6 +1248,7 @@ def render_polar(self):
12381248 self .axes_images [0 ].set_data (img )
12391249
12401250 self .update_mask_boundaries (self .axis )
1251+ self .update_mask_highlights (self .axis )
12411252
12421253 # Get the "tth" vector
12431254 angular_grid = self .iviewer .angular_grid
@@ -1365,6 +1376,7 @@ def finish_show_stereo(self, iviewer):
13651376 self .figure .tight_layout ()
13661377
13671378 self .update_mask_boundaries (self .axis )
1379+ self .update_mask_highlights (self .axis )
13681380
13691381 self .draw_stereo_border ()
13701382 self .update_auto_picked_data ()
@@ -1566,6 +1578,19 @@ def is_stereo_from_polar(self):
15661578 self .iviewer .project_from_polar
15671579 )
15681580
1581+ def mask_highlights_changed (self ):
1582+ if not self .iviewer :
1583+ return
1584+
1585+ if self .mode == ViewType .raw :
1586+ self .clear_mask_highlights ()
1587+ for det_name , ax in self .raw_axes .items ():
1588+ self .highlight_masks (ax , det_name )
1589+ return
1590+
1591+ if self .mode in (ViewType .polar , ViewType .stereo ):
1592+ self .update_mask_highlights (self .axis )
1593+
15691594 def polar_masks_changed (self ):
15701595 skip = (
15711596 not self .iviewer or
@@ -1576,6 +1601,7 @@ def polar_masks_changed(self):
15761601 return
15771602
15781603 self .update_mask_boundaries (self .axis )
1604+ self .update_mask_highlights (self .axis )
15791605 self .iviewer .reapply_masks ()
15801606 img = self .scaled_display_images [0 ]
15811607 self .axes_images [0 ].set_data (img )
@@ -2182,11 +2208,23 @@ def clear_mask_boundaries(self):
21822208
21832209 self ._mask_boundary_artists .clear ()
21842210
2185- def draw_mask_boundaries (self , axis , det = None ):
2211+ def update_mask_highlights (self , axis ):
2212+ # Update is a clear followed by a draw
2213+ self .clear_mask_highlights ()
2214+ self .highlight_masks (axis )
2215+
2216+ def clear_mask_highlights (self ):
2217+ self .remove_all_mask_highlight_artists ()
2218+
2219+ def get_mask_verts (self , visible_attr , det = None ):
21862220 # Create an instrument once that we will re-use
21872221 instr = create_view_hedm_instrument ()
21882222 all_verts = []
2189- for name in MaskManager ().visible_boundaries :
2223+ options = {
2224+ 'boundaries' : MaskManager ().visible_boundaries ,
2225+ 'highlights' : MaskManager ().visible_highlights
2226+ }
2227+ for name in options [visible_attr ]:
21902228 mask = MaskManager ().masks [name ]
21912229 verts = None
21922230 if self .mode == ViewType .raw :
@@ -2251,6 +2289,10 @@ def draw_mask_boundaries(self, axis, det=None):
22512289 [np .vstack ((x , (np .nan , np .nan ))) for x in verts ]
22522290 ))
22532291
2292+ return all_verts
2293+
2294+ def draw_mask_boundaries (self , axis , det = None ):
2295+ all_verts = self .get_mask_verts ('boundaries' , det )
22542296 if not all_verts :
22552297 return
22562298
@@ -2264,6 +2306,35 @@ def draw_mask_boundaries(self, axis, det=None):
22642306 ** kwargs ,
22652307 )
22662308
2309+ def highlight_masks (self , axis , det = None ):
2310+ all_verts = self .get_mask_verts ('highlights' , det )
2311+ if not all_verts :
2312+ return
2313+
2314+ kwargs = {
2315+ 'facecolor' : MaskManager ().highlight_color ,
2316+ 'alpha' : MaskManager ().highlight_opacity ,
2317+ 'edgecolor' : 'none' ,
2318+ 'fill' : True ,
2319+ }
2320+
2321+ highlight_artists = self .mask_highlight_artists .setdefault (det or 'default' , [])
2322+
2323+ for vert in all_verts :
2324+ polygon = Polygon (vert , ** kwargs )
2325+ polygon .set_animated (True )
2326+ axis .add_patch (polygon )
2327+ highlight_artists .append (polygon )
2328+
2329+ self .blit_manager .update ()
2330+
2331+ def remove_all_mask_highlight_artists (self ):
2332+ self .blit_manager .remove_artists ('mask_highlights' )
2333+ self .blit_manager .artists ['mask_highlights' ] = {}
2334+
2335+ def remove_mask_highlight_artists (self , key ):
2336+ self .blit_manager .remove_artists ('mask_highlights' , key )
2337+
22672338
22682339class PolarXAxisTickLocator (AutoLocator ):
22692340 """Subclass the tick locator so we can modify its behavior
0 commit comments