diff --git a/hexrdgui/calibration/cartesian_plot.py b/hexrdgui/calibration/cartesian_plot.py
index 1b329e5d8..45548722d 100644
--- a/hexrdgui/calibration/cartesian_plot.py
+++ b/hexrdgui/calibration/cartesian_plot.py
@@ -22,6 +22,8 @@
def cartesian_viewer():
return InstrumentViewer()
+def get_xray_propagation_sign(instr):
+ return np.sign(instr.beam_vector[2])
class InstrumentViewer:
@@ -29,6 +31,10 @@ def __init__(self):
self.type = ViewType.cartesian
self.instr = create_hedm_instrument()
self.images_dict = HexrdConfig().images_dict
+
+ # Set invalid pixels to be nan
+ HexrdConfig().apply_panel_buffer_to_images(self.images_dict)
+
self.img = None
# Perform some checks before proceeding
@@ -40,7 +46,8 @@ def __init__(self):
self.detector_corners = {}
dist = HexrdConfig().cartesian_virtual_plane_distance
- dplane_tvec = np.array([0., 0., -dist])
+ sgn = get_xray_propagation_sign(self.instr)
+ dplane_tvec = np.array([0., 0., sgn*dist])
rotate_x = HexrdConfig().cartesian_plane_normal_rotate_x
rotate_y = HexrdConfig().cartesian_plane_normal_rotate_y
@@ -280,8 +287,15 @@ def create_warped_image(self, detector_id):
res = tf.warp(img, tform3,
output_shape=(self.dpanel.rows, self.dpanel.cols),
- preserve_range=True)
- self.warp_dict[detector_id] = res
+ preserve_range=True, cval=np.nan)
+ nan_mask = np.isnan(res)
+
+ self.warp_dict[detector_id] = np.ma.masked_array(
+ res,
+ mask=nan_mask,
+ fill_value=0,
+ )
+
return res
@property
@@ -290,8 +304,15 @@ def display_img(self):
def generate_image(self):
img = np.zeros((self.dpanel.rows, self.dpanel.cols))
+ always_nan = np.ones(img.shape, dtype=bool)
for key in self.images_dict.keys():
- img += self.warp_dict[key]
+ # Use zeros when summing, but identify pixels that
+ # are nans in all images and set those to nan.
+ warp_img = self.warp_dict[key]
+ img += warp_img.filled(0)
+ always_nan = np.logical_and(always_nan, warp_img.mask)
+
+ img[always_nan] = np.nan
# In case there were any nans...
nan_mask = np.isnan(img)
diff --git a/hexrdgui/hexrd_config.py b/hexrdgui/hexrd_config.py
index 8f8afe5b4..2ba5c2b5f 100644
--- a/hexrdgui/hexrd_config.py
+++ b/hexrdgui/hexrd_config.py
@@ -535,6 +535,12 @@ def load_from_state(self, state):
pinhole_settings.pop('pinhole_radius') * 2
)
+ if self.cartesian_virtual_plane_distance < 0:
+ # We used to allow this to be negative, but now must be positive.
+ # Taking the absolute value should correct this adequately.
+ self.cartesian_virtual_plane_distance = abs(
+ self.cartesian_virtual_plane_distance)
+
# All QSettings come back as strings. So check that we are dealing with
# a boolean and convert if necessary
if not isinstance(self.live_update, bool):
@@ -2511,7 +2517,8 @@ def _cartesian_pixel_size(self):
def _set_cartesian_pixel_size(self, v):
if v != self.cartesian_pixel_size:
self.config['image']['cartesian']['pixel_size'] = v
- self.rerender_needed.emit()
+ if self.image_mode == constants.ViewType.cartesian:
+ self.rerender_needed.emit()
cartesian_pixel_size = property(_cartesian_pixel_size,
_set_cartesian_pixel_size)
@@ -2520,9 +2527,13 @@ def _cartesian_virtual_plane_distance(self):
return self.config['image']['cartesian']['virtual_plane_distance']
def set_cartesian_virtual_plane_distance(self, v):
+ if v < 0:
+ raise RuntimeError(f'Invalid plane distance: {v}')
+
if v != self.cartesian_virtual_plane_distance:
self.config['image']['cartesian']['virtual_plane_distance'] = v
- self.rerender_needed.emit()
+ if self.image_mode == constants.ViewType.cartesian:
+ self.rerender_needed.emit()
cartesian_virtual_plane_distance = property(
_cartesian_virtual_plane_distance,
@@ -2534,7 +2545,8 @@ def _cartesian_plane_normal_rotate_x(self):
def set_cartesian_plane_normal_rotate_x(self, v):
if v != self.cartesian_plane_normal_rotate_x:
self.config['image']['cartesian']['plane_normal_rotate_x'] = v
- self.rerender_needed.emit()
+ if self.image_mode == constants.ViewType.cartesian:
+ self.rerender_needed.emit()
cartesian_plane_normal_rotate_x = property(
_cartesian_plane_normal_rotate_x,
@@ -2546,7 +2558,8 @@ def _cartesian_plane_normal_rotate_y(self):
def set_cartesian_plane_normal_rotate_y(self, v):
if v != self.cartesian_plane_normal_rotate_y:
self.config['image']['cartesian']['plane_normal_rotate_y'] = v
- self.rerender_needed.emit()
+ if self.image_mode == constants.ViewType.cartesian:
+ self.rerender_needed.emit()
cartesian_plane_normal_rotate_y = property(
_cartesian_plane_normal_rotate_y,
diff --git a/hexrdgui/image_mode_widget.py b/hexrdgui/image_mode_widget.py
index 6fa540285..cf1f833c3 100644
--- a/hexrdgui/image_mode_widget.py
+++ b/hexrdgui/image_mode_widget.py
@@ -40,6 +40,9 @@ def __init__(self, parent=None):
# Always start with raw tab
self.ui.tab_widget.setCurrentIndex(0)
+ # Don't allow negative distances
+ self.ui.cartesian_virtual_plane_distance.setMinimum(1e-8)
+
# Hide stereo_project_from_polar for now, as projecting from polar
# appears to give a better image (lines up better with overlays)
# than projecting from raw.
diff --git a/hexrdgui/resources/ui/image_mode_widget.ui b/hexrdgui/resources/ui/image_mode_widget.ui
index fa96859e7..051cb5f0f 100644
--- a/hexrdgui/resources/ui/image_mode_widget.ui
+++ b/hexrdgui/resources/ui/image_mode_widget.ui
@@ -38,7 +38,7 @@
QTabWidget::Rounded
- 2
+ 1
@@ -167,6 +167,9 @@
8
+
+ 0.000000000000000
+
1000000.000000000000000