diff --git a/hexrdgui/calibration/polarview.py b/hexrdgui/calibration/polarview.py index a51b71132..39d1e7bb4 100644 --- a/hexrdgui/calibration/polarview.py +++ b/hexrdgui/calibration/polarview.py @@ -502,10 +502,16 @@ def apply_intensity_corrections(self, img): return img - def apply_visible_masks(self, img): - # Apply user-specified masks if they are present - img = img.copy() - total_mask = self.warp_mask + @property + def all_masks_pv_array(self) -> np.ndarray: + return np.logical_or( + self.visible_mask_pv_array, + self.boundary_mask_pv_array, + ) + + @property + def visible_mask_pv_array(self) -> np.ndarray: + total_mask = np.zeros(self.shape, dtype=bool) for mask in MaskManager().masks.values(): if mask.type == MaskType.threshold or not mask.visible: continue @@ -517,21 +523,31 @@ def apply_visible_masks(self, img): gt_mask = img > gt_val mask = np.logical_or(lt_mask, gt_mask) total_mask = np.logical_or(total_mask, mask) - img[total_mask] = np.nan - return img + return total_mask - def apply_boundary_masks(self, img): - # Apply user-specified masks if they are present - img = img.copy() - total_mask = self.warp_mask + @property + def boundary_mask_pv_array(self) -> np.ndarray: + total_mask = np.zeros(self.shape, dtype=bool) for mask in MaskManager().masks.values(): if mask.type == MaskType.threshold or not mask.show_border: continue mask_arr = mask.get_masked_arrays(ViewType.polar, self.instr) total_mask = np.logical_or(total_mask, ~mask_arr) + return total_mask + + def apply_visible_masks(self, img): + # Apply user-specified masks if they are present + total_mask = np.logical_or(self.warp_mask, self.visible_mask_pv_array) + img = img.copy() img[total_mask] = np.nan + return img + def apply_boundary_masks(self, img): + # Apply user-specified masks if they are present + total_mask = np.logical_or(self.warp_mask, self.boundary_mask_pv_array) + img = img.copy() + img[total_mask] = np.nan return img def reapply_masks(self): diff --git a/hexrdgui/calibration/wppf_options_dialog.py b/hexrdgui/calibration/wppf_options_dialog.py index e04807909..4aed91150 100644 --- a/hexrdgui/calibration/wppf_options_dialog.py +++ b/hexrdgui/calibration/wppf_options_dialog.py @@ -1943,6 +1943,27 @@ def on_texture_binning_setting_changed(self): self.invalidate_texture_data() self.update_simulated_polar_dialog() + def _compute_2d_pv_bin_mask(self): + canvas = HexrdConfig().active_canvas + if canvas.mode != 'polar' or canvas.iviewer is None: + return + + settings = self.texture_settings + + # Make a float image so that any pixels touched by nans + # in the binning will be nan. + mask_float = np.zeros(canvas.iviewer.pv.shape, dtype=float) + pv = canvas.iviewer.pv + mask = np.logical_or(pv.all_masks_pv_array, pv.warp_mask) + mask_float[mask] = np.nan + binned = bin_polar_view( + canvas.iviewer.pv, + mask_float, + settings['azimuthal_interval'], + settings['integration_range'], + ) + return np.isnan(binned) + def _compute_2d_pv_bin(self): canvas = HexrdConfig().active_canvas if canvas.mode != 'polar' or canvas.iviewer is None: @@ -1967,11 +1988,16 @@ def _compute_2d_pv_sim(self): # Nothing we can do return None + # Compute the mask to apply + mask = self._compute_2d_pv_bin_mask() + try: # Make sure the `eta_step` is up-to-date obj.eta_step = self.texture_settings['azimuthal_interval'] obj.computespectrum_2D() - return obj.simulated_2d + img = obj.simulated_2d.copy() + img[mask] = np.nan + return img finally: if not had_object: self.reset_object() diff --git a/hexrdgui/calibration/wppf_simulated_polar_dialog.py b/hexrdgui/calibration/wppf_simulated_polar_dialog.py index 41b1528f7..34c38c99c 100644 --- a/hexrdgui/calibration/wppf_simulated_polar_dialog.py +++ b/hexrdgui/calibration/wppf_simulated_polar_dialog.py @@ -36,7 +36,7 @@ def __init__(self, pv_bin: np.ndarray, pv_sim: np.ndarray | None, def setup_color_map(self): self.color_map_editor = ColorMapEditor(self, self.ui) self.ui.color_map_editor_layout.addWidget(self.color_map_editor.ui) - self.color_map_editor.update_bounds(self.scaled_image_data) + self.color_map_editor.update_bounds(unmasked(self.scaled_image_data)) self.color_map_editor.data = self.data def setup_canvas(self): @@ -133,7 +133,7 @@ def on_data_modified(self): ax_im.set_data(self.get_scaled_image_data(i)) ax_im.set_extent(self.extent) - self.color_map_editor.data = self.data + self.color_map_editor.data = unmasked(self.data) self.draw_later() @@ -148,3 +148,13 @@ def show(self): def draw_later(self): self.figure.canvas.draw_idle() + + +def unmasked( + array: np.ndarray | np.ma.MaskedArray, + fill_value=np.nan, +) -> np.ndarray: + if isinstance(array, np.ma.MaskedArray): + return array.filled(fill_value) + + return array