From 07b97992a211bcb38b8b2bf9d7debfd434e6ae39 Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Thu, 4 Jan 2024 17:33:15 -0500 Subject: [PATCH 01/14] Working on adding spectrum-from-spaxel on hover --- jdaviz/configs/cubeviz/plugins/tools.py | 27 +++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/jdaviz/configs/cubeviz/plugins/tools.py b/jdaviz/configs/cubeviz/plugins/tools.py index 470de5c30e..895f30105d 100644 --- a/jdaviz/configs/cubeviz/plugins/tools.py +++ b/jdaviz/configs/cubeviz/plugins/tools.py @@ -8,6 +8,7 @@ from jdaviz.configs.imviz.plugins.tools import _MatchedZoomMixin from jdaviz.core.events import SliceToolStateMessage from jdaviz.core.tools import PanZoom, BoxZoom, SinglePixelRegion +from jdaviz.core.marks import PluginLine __all__ = [] @@ -83,3 +84,29 @@ class SpectrumPerSpaxel(SinglePixelRegion): tool_id = 'jdaviz:spectrumperspaxel' action_text = 'See spectrum at a single spaxel' tool_tip = 'Click on the viewer and see the spectrum at that spaxel in the spectrum viewer' + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._spectrum_viewer = None + self._mark = None + + def activate(self): + self.viewer.add_event_callback(self.on_mouse_move, events=['mousemove', 'mouseleave', 'mouseenter']) + if self._spectrum_viewer is None: + self._spectrum_viewer = self.viewer.jdaviz_helper.app.get_viewer('spectrum-viewer') + if self._mark is None: + self._mark = PluginLine(self._spectrum_viewer, visible=False) + super().activate() + + def deactivate(self): + self.viewer.remove_event_callback(self.on_mouse_move) + super().deactivate() + + def on_mouse_move(self, viewer, data): + if data['event'] == 'mouseenter': + self._mark.visible = True + elif data['event'] == 'mouseleave': + self._mark.visible = False + + x = data['domain']['x'] + y = data['domain']['y'] \ No newline at end of file From 956cffbe0e7e4995bfa422c210bd750742722200 Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Fri, 5 Jan 2024 11:48:39 -0500 Subject: [PATCH 02/14] First working version of spectrum on hover --- jdaviz/configs/cubeviz/plugins/tools.py | 29 +++++++++++++++++++------ 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/jdaviz/configs/cubeviz/plugins/tools.py b/jdaviz/configs/cubeviz/plugins/tools.py index 895f30105d..47a18ac6f2 100644 --- a/jdaviz/configs/cubeviz/plugins/tools.py +++ b/jdaviz/configs/cubeviz/plugins/tools.py @@ -4,6 +4,7 @@ from glue.config import viewer_tool from glue_jupyter.bqplot.image import BqplotImageView from glue.viewers.common.tool import CheckableTool +import numpy as np from jdaviz.configs.imviz.plugins.tools import _MatchedZoomMixin from jdaviz.core.events import SliceToolStateMessage @@ -89,24 +90,38 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._spectrum_viewer = None self._mark = None + self._data = None def activate(self): - self.viewer.add_event_callback(self.on_mouse_move, events=['mousemove', 'mouseleave', 'mouseenter']) + self.viewer.add_event_callback(self.on_mouse_move, events=['mousemove', 'mouseleave']) if self._spectrum_viewer is None: self._spectrum_viewer = self.viewer.jdaviz_helper.app.get_viewer('spectrum-viewer') if self._mark is None: self._mark = PluginLine(self._spectrum_viewer, visible=False) + self._spectrum_viewer.figure.marks = self._spectrum_viewer.figure.marks + [self._mark,] super().activate() def deactivate(self): self.viewer.remove_event_callback(self.on_mouse_move) super().deactivate() - def on_mouse_move(self, viewer, data): - if data['event'] == 'mouseenter': - self._mark.visible = True - elif data['event'] == 'mouseleave': + def on_mouse_move(self, data): + if data['event'] == 'mouseleave': self._mark.visible = False + return + + x = int(np.round(data['domain']['x'])) + y = int(np.round(data['domain']['y'])) - x = data['domain']['x'] - y = data['domain']['y'] \ No newline at end of file + # Use first visible layer for now + cube_data = [layer.layer for layer in self.viewer.layers if layer.state.visible][0] + spectrum = cube_data.get_object(statistic=None) + + if x >= spectrum.flux.shape[0] or x < 0 or y >= spectrum.flux.shape[1] or y < 0: + self._mark.visible = False + else: + self._mark.visible = True + y_values = spectrum.flux[x,y,:] + self._mark.update_xy(spectrum.spectral_axis.value, y_values) + self._spectrum_viewer.state.y_max = y_values.max().value * 1.2 + self._spectrum_viewer.state.y_min = y_values.min().value * 0.8 \ No newline at end of file From e448c6c430baff20b0f6f9e57423fb3be3389f7d Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Fri, 5 Jan 2024 11:58:43 -0500 Subject: [PATCH 03/14] Handle NaNs properly --- jdaviz/configs/cubeviz/plugins/tools.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/jdaviz/configs/cubeviz/plugins/tools.py b/jdaviz/configs/cubeviz/plugins/tools.py index 47a18ac6f2..3e1dfe9186 100644 --- a/jdaviz/configs/cubeviz/plugins/tools.py +++ b/jdaviz/configs/cubeviz/plugins/tools.py @@ -122,6 +122,9 @@ def on_mouse_move(self, data): else: self._mark.visible = True y_values = spectrum.flux[x,y,:] + if np.all(np.isnan(y_values)): + self._mark.visible=False + return self._mark.update_xy(spectrum.spectral_axis.value, y_values) - self._spectrum_viewer.state.y_max = y_values.max().value * 1.2 - self._spectrum_viewer.state.y_min = y_values.min().value * 0.8 \ No newline at end of file + self._spectrum_viewer.state.y_max = np.nanmax(y_values.value) * 1.2 + self._spectrum_viewer.state.y_min = np.nanmin(y_values.value) * 0.8 \ No newline at end of file From 5f9b8434935e051ee83a211954d56d1610a81c57 Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Fri, 5 Jan 2024 14:13:40 -0500 Subject: [PATCH 04/14] Update docs and changelog --- CHANGES.rst | 2 ++ docs/cubeviz/displaycubes.rst | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 9b3ab71d2b..fa09350a51 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -17,6 +17,8 @@ Cubeviz - Moment map plugin now supports linear per-spaxel continuum subtraction. [#2587] +- Single-pixel subset tool now shows spectrum-at-spaxel on hover. [#2647] + Imviz ^^^^^ diff --git a/docs/cubeviz/displaycubes.rst b/docs/cubeviz/displaycubes.rst index 9cd89ddb2d..bca8745d8a 100644 --- a/docs/cubeviz/displaycubes.rst +++ b/docs/cubeviz/displaycubes.rst @@ -99,9 +99,10 @@ the bottom of the UI. Spectrum At Spaxel ================== -This tool allows the user to create a one spaxel subset in an image viewer. This subset will then be +This tool allows the user to create a single-spaxel subset in an image viewer. This subset will then be visualized in the spectrum viewer by showing the spectrum at that spaxel. -Activate this tool and then left-click to create the new region. +While this tool is active, hovering over a pixel in the image viewer will show a preview of the spectrum +at that spaxel in the spectrum viewer, and left-clicking will create a new subset at that spaxel. Click again to move the region to a new location under the cursor. Holding down the alt key (Alt key on Windows, Option key on Mac) while clicking on a spaxel creates a new subset at that point instead of moving the previously created region. From ec034002dfa365900f5c1a78cc96823a926916ef Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Fri, 5 Jan 2024 14:58:50 -0500 Subject: [PATCH 05/14] Add simple test Codestyle Codestyle --- jdaviz/configs/cubeviz/plugins/tests/test_tools.py | 11 +++++++++++ jdaviz/configs/cubeviz/plugins/tools.py | 6 +++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/jdaviz/configs/cubeviz/plugins/tests/test_tools.py b/jdaviz/configs/cubeviz/plugins/tests/test_tools.py index 7bc9cffa2b..199fe77634 100644 --- a/jdaviz/configs/cubeviz/plugins/tests/test_tools.py +++ b/jdaviz/configs/cubeviz/plugins/tests/test_tools.py @@ -18,6 +18,12 @@ def test_spectrum_at_spaxel(cubeviz_helper, spectrum1d_cube): assert len(flux_viewer.native_marks) == 2 assert len(spectrum_viewer.data()) == 1 + # Move to spaxel location + flux_viewer.toolbar.active_tool.on_mouse_move( + {'event': 'mousemove', 'domain': {'x': x, 'y': y}, 'altKey': False}) + assert flux_viewer.toolbar.active_tool._mark in spectrum_viewer.figure.marks + assert flux_viewer.toolbar.active_tool._mark.visible is True + # Click on spaxel location flux_viewer.toolbar.active_tool.on_mouse_event( {'event': 'click', 'domain': {'x': x, 'y': y}, 'altKey': False}) @@ -30,6 +36,11 @@ def test_spectrum_at_spaxel(cubeviz_helper, spectrum1d_cube): assert len(subsets) == 1 assert isinstance(reg, RectanglePixelRegion) + # Mouse leave event + flux_viewer.toolbar.active_tool.on_mouse_move( + {'event': 'mouseleave', 'domain': {'x': x, 'y': y}, 'altKey': False}) + assert flux_viewer.toolbar.active_tool._mark.visible is False + # Deselect tool flux_viewer.toolbar.active_tool = None assert len(flux_viewer.native_marks) == 3 diff --git a/jdaviz/configs/cubeviz/plugins/tools.py b/jdaviz/configs/cubeviz/plugins/tools.py index 3e1dfe9186..07a4f5ee5e 100644 --- a/jdaviz/configs/cubeviz/plugins/tools.py +++ b/jdaviz/configs/cubeviz/plugins/tools.py @@ -121,10 +121,10 @@ def on_mouse_move(self, data): self._mark.visible = False else: self._mark.visible = True - y_values = spectrum.flux[x,y,:] + y_values = spectrum.flux[x, y, :] if np.all(np.isnan(y_values)): - self._mark.visible=False + self._mark.visible = False return self._mark.update_xy(spectrum.spectral_axis.value, y_values) self._spectrum_viewer.state.y_max = np.nanmax(y_values.value) * 1.2 - self._spectrum_viewer.state.y_min = np.nanmin(y_values.value) * 0.8 \ No newline at end of file + self._spectrum_viewer.state.y_min = np.nanmin(y_values.value) * 0.8 From cb3b1ed7a5574d23c66cf28c74e3215226b77ce9 Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Mon, 8 Jan 2024 09:45:42 -0500 Subject: [PATCH 06/14] Revert zoom after preview view --- docs/cubeviz/displaycubes.rst | 5 +++++ jdaviz/configs/cubeviz/plugins/tools.py | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/docs/cubeviz/displaycubes.rst b/docs/cubeviz/displaycubes.rst index bca8745d8a..7a3ebb01a7 100644 --- a/docs/cubeviz/displaycubes.rst +++ b/docs/cubeviz/displaycubes.rst @@ -111,6 +111,11 @@ You can also use the subset modes that are explained in the :ref:`Spatial Regions ` section above in the same way you would with the other subset selection tools. +Note that moving the cursor outside of the image viewer or deactivating the spectrum-at-spaxel tool +will revert the spectrum viewer zoom limits from the zoomed-in preview view to the limits set prior +to using the tool. Thus it may be necessary to reset the zoom to see any single-spaxel subset spectra +created using the tool. + .. _cubeviz-display-settings: Display Settings diff --git a/jdaviz/configs/cubeviz/plugins/tools.py b/jdaviz/configs/cubeviz/plugins/tools.py index 07a4f5ee5e..a540e3c7f2 100644 --- a/jdaviz/configs/cubeviz/plugins/tools.py +++ b/jdaviz/configs/cubeviz/plugins/tools.py @@ -89,9 +89,17 @@ class SpectrumPerSpaxel(SinglePixelRegion): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._spectrum_viewer = None + self._previous_bounds = None self._mark = None self._data = None + def _reset_spectrum_viewer_bounds(self): + sv_state = self._spectrum_viewer.state + sv_state.x_min = self._previous_bounds[0] + sv_state.x_max = self._previous_bounds[1] + sv_state.y_min = self._previous_bounds[2] + sv_state.y_max = self._previous_bounds[3] + def activate(self): self.viewer.add_event_callback(self.on_mouse_move, events=['mousemove', 'mouseleave']) if self._spectrum_viewer is None: @@ -99,15 +107,20 @@ def activate(self): if self._mark is None: self._mark = PluginLine(self._spectrum_viewer, visible=False) self._spectrum_viewer.figure.marks = self._spectrum_viewer.figure.marks + [self._mark,] + # Store these so we can revert to previous user-set zoom after preview view + sv_state = self._spectrum_viewer.state + self._previous_bounds = [sv_state.x_min, sv_state.x_max, sv_state.y_min, sv_state.y_max] super().activate() def deactivate(self): self.viewer.remove_event_callback(self.on_mouse_move) + self._reset_spectrum_viewer_bounds() super().deactivate() def on_mouse_move(self, data): if data['event'] == 'mouseleave': self._mark.visible = False + self._reset_spectrum_viewer_bounds() return x = int(np.round(data['domain']['x'])) From 1d4be477593cc17395aa048c00deba2f5a83f142 Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Tue, 16 Jan 2024 09:26:57 -0500 Subject: [PATCH 07/14] Address review comments --- jdaviz/configs/cubeviz/plugins/tools.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/jdaviz/configs/cubeviz/plugins/tools.py b/jdaviz/configs/cubeviz/plugins/tools.py index a540e3c7f2..fbc8e3c559 100644 --- a/jdaviz/configs/cubeviz/plugins/tools.py +++ b/jdaviz/configs/cubeviz/plugins/tools.py @@ -127,17 +127,21 @@ def on_mouse_move(self, data): y = int(np.round(data['domain']['y'])) # Use first visible layer for now - cube_data = [layer.layer for layer in self.viewer.layers if layer.state.visible][0] + cube_data = [layer.layer for layer in self.viewer.layers if layer.state.visible] + if len(cube_data) == 0: + return + cube_data = cube_data[0] spectrum = cube_data.get_object(statistic=None) if x >= spectrum.flux.shape[0] or x < 0 or y >= spectrum.flux.shape[1] or y < 0: + self._reset_spectrum_viewer_bounds() self._mark.visible = False else: - self._mark.visible = True y_values = spectrum.flux[x, y, :] if np.all(np.isnan(y_values)): self._mark.visible = False return self._mark.update_xy(spectrum.spectral_axis.value, y_values) + self._mark.visible = True self._spectrum_viewer.state.y_max = np.nanmax(y_values.value) * 1.2 self._spectrum_viewer.state.y_min = np.nanmin(y_values.value) * 0.8 From 05bd078310401d07705c86d9c28786e8a4a62370 Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Tue, 16 Jan 2024 10:16:20 -0500 Subject: [PATCH 08/14] Only use 3D data --- jdaviz/configs/cubeviz/plugins/tools.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jdaviz/configs/cubeviz/plugins/tools.py b/jdaviz/configs/cubeviz/plugins/tools.py index fbc8e3c559..874b5916f3 100644 --- a/jdaviz/configs/cubeviz/plugins/tools.py +++ b/jdaviz/configs/cubeviz/plugins/tools.py @@ -127,7 +127,8 @@ def on_mouse_move(self, data): y = int(np.round(data['domain']['y'])) # Use first visible layer for now - cube_data = [layer.layer for layer in self.viewer.layers if layer.state.visible] + cube_data = [layer.layer for layer in self.viewer.layers if layer.state.visible + and len(layer.layer.shape) == 3] if len(cube_data) == 0: return cube_data = cube_data[0] From 29cd90c5da9b62f369261eabfa9c77c9732367b1 Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Fri, 19 Jan 2024 14:54:25 -0500 Subject: [PATCH 09/14] Fix preview spectrum for uncertainty cube --- jdaviz/configs/cubeviz/plugins/tools.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/jdaviz/configs/cubeviz/plugins/tools.py b/jdaviz/configs/cubeviz/plugins/tools.py index 874b5916f3..60cb325474 100644 --- a/jdaviz/configs/cubeviz/plugins/tools.py +++ b/jdaviz/configs/cubeviz/plugins/tools.py @@ -5,6 +5,7 @@ from glue_jupyter.bqplot.image import BqplotImageView from glue.viewers.common.tool import CheckableTool import numpy as np +from specutils import Spectrum1D from jdaviz.configs.imviz.plugins.tools import _MatchedZoomMixin from jdaviz.core.events import SliceToolStateMessage @@ -133,6 +134,10 @@ def on_mouse_move(self, data): return cube_data = cube_data[0] spectrum = cube_data.get_object(statistic=None) + # Note: change this when Spectrum1D.with_spectral_axis is fixed. + if spectrum.spectral_axis.unit != self._spectrum_viewer.state.x_display_unit: + new_spectral_axis = spectrum.spectral_axis.to(self._spectrum_viewer.state.x_display_unit) + spectrum = Spectrum1D(spectrum.flux, new_spectral_axis) if x >= spectrum.flux.shape[0] or x < 0 or y >= spectrum.flux.shape[1] or y < 0: self._reset_spectrum_viewer_bounds() From 5145cc479e57bbe198c2fcb1d179305c959bdaaf Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Fri, 19 Jan 2024 15:27:12 -0500 Subject: [PATCH 10/14] Use the same layer selection as coords_info if possible --- jdaviz/configs/cubeviz/plugins/tools.py | 31 ++++++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/jdaviz/configs/cubeviz/plugins/tools.py b/jdaviz/configs/cubeviz/plugins/tools.py index 60cb325474..fdce22b74e 100644 --- a/jdaviz/configs/cubeviz/plugins/tools.py +++ b/jdaviz/configs/cubeviz/plugins/tools.py @@ -3,6 +3,7 @@ from glue.config import viewer_tool from glue_jupyter.bqplot.image import BqplotImageView +from glue_jupyter.bqplot.image.layer_artist import BqplotImageSubsetLayerArtist from glue.viewers.common.tool import CheckableTool import numpy as np from specutils import Spectrum1D @@ -127,12 +128,30 @@ def on_mouse_move(self, data): x = int(np.round(data['domain']['x'])) y = int(np.round(data['domain']['y'])) - # Use first visible layer for now - cube_data = [layer.layer for layer in self.viewer.layers if layer.state.visible - and len(layer.layer.shape) == 3] - if len(cube_data) == 0: - return - cube_data = cube_data[0] + # Use the selected layer from coords_info as long as it's 3D + coords_info_dataset = self.viewer.session.application._tools['g-coords-info'].dataset.selected + if coords_info_dataset == 'auto': + cube_data = self.viewer.active_image_layer.layer + elif coords_info_dataset == 'none': + cube_data = self.viewer.layers[0].layer + else: + for layer in self.viewer.layers: + if layer.layer.label == coords_info_dataset and layer.visible: + if isinstance(layer, BqplotImageSubsetLayerArtist): + # cannot expose info for spatial subset layers + continue + cube_data = layer.layer + break + else: + return + + if cube_data.ndim != 3: + cube_data = [layer.layer for layer in self.viewer.layers if layer.state.visible + and layer.layer.ndim == 3] + if len(cube_data) == 0: + return + cube_data = cube_data[0] + spectrum = cube_data.get_object(statistic=None) # Note: change this when Spectrum1D.with_spectral_axis is fixed. if spectrum.spectral_axis.unit != self._spectrum_viewer.state.x_display_unit: From b652e16c76ec302abc231a3dcdb5cd5e7d64f9bd Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Fri, 19 Jan 2024 15:29:26 -0500 Subject: [PATCH 11/14] Codestyle --- jdaviz/configs/cubeviz/plugins/tools.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/jdaviz/configs/cubeviz/plugins/tools.py b/jdaviz/configs/cubeviz/plugins/tools.py index fdce22b74e..f7903c82b0 100644 --- a/jdaviz/configs/cubeviz/plugins/tools.py +++ b/jdaviz/configs/cubeviz/plugins/tools.py @@ -129,14 +129,14 @@ def on_mouse_move(self, data): y = int(np.round(data['domain']['y'])) # Use the selected layer from coords_info as long as it's 3D - coords_info_dataset = self.viewer.session.application._tools['g-coords-info'].dataset.selected - if coords_info_dataset == 'auto': + coords_dataset = self.viewer.session.application._tools['g-coords-info'].dataset.selected + if coords_dataset == 'auto': cube_data = self.viewer.active_image_layer.layer - elif coords_info_dataset == 'none': + elif coords_dataset == 'none': cube_data = self.viewer.layers[0].layer else: for layer in self.viewer.layers: - if layer.layer.label == coords_info_dataset and layer.visible: + if layer.layer.label == coords_dataset and layer.visible: if isinstance(layer, BqplotImageSubsetLayerArtist): # cannot expose info for spatial subset layers continue @@ -147,15 +147,16 @@ def on_mouse_move(self, data): if cube_data.ndim != 3: cube_data = [layer.layer for layer in self.viewer.layers if layer.state.visible - and layer.layer.ndim == 3] + and layer.layer.ndim == 3] if len(cube_data) == 0: return cube_data = cube_data[0] spectrum = cube_data.get_object(statistic=None) # Note: change this when Spectrum1D.with_spectral_axis is fixed. - if spectrum.spectral_axis.unit != self._spectrum_viewer.state.x_display_unit: - new_spectral_axis = spectrum.spectral_axis.to(self._spectrum_viewer.state.x_display_unit) + x_unit = self._spectrum_viewer.state.x_display_unit + if spectrum.spectral_axis.unit != x_unit: + new_spectral_axis = spectrum.spectral_axis.to(x_unit) spectrum = Spectrum1D(spectrum.flux, new_spectral_axis) if x >= spectrum.flux.shape[0] or x < 0 or y >= spectrum.flux.shape[1] or y < 0: From 34d2c980d7b05deecd9cb6d1846ec97128c60174 Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Mon, 22 Jan 2024 14:19:35 -0500 Subject: [PATCH 12/14] Use selected_obj and get first profile viewer rather than spectrum-viewer specifically --- jdaviz/configs/cubeviz/plugins/tools.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/jdaviz/configs/cubeviz/plugins/tools.py b/jdaviz/configs/cubeviz/plugins/tools.py index f7903c82b0..c8ff3a855e 100644 --- a/jdaviz/configs/cubeviz/plugins/tools.py +++ b/jdaviz/configs/cubeviz/plugins/tools.py @@ -3,6 +3,7 @@ from glue.config import viewer_tool from glue_jupyter.bqplot.image import BqplotImageView +from glue_jupyter.bqplot.profile import BqplotProfileView from glue_jupyter.bqplot.image.layer_artist import BqplotImageSubsetLayerArtist from glue.viewers.common.tool import CheckableTool import numpy as np @@ -105,7 +106,11 @@ def _reset_spectrum_viewer_bounds(self): def activate(self): self.viewer.add_event_callback(self.on_mouse_move, events=['mousemove', 'mouseleave']) if self._spectrum_viewer is None: - self._spectrum_viewer = self.viewer.jdaviz_helper.app.get_viewer('spectrum-viewer') + # Get first profile viewer + for _, viewer in self.viewer.jdaviz_helper.app._viewer_store.items(): + if isinstance(viewer, BqplotProfileView): + self._spectrum_viewer = viewer + break if self._mark is None: self._mark = PluginLine(self._spectrum_viewer, visible=False) self._spectrum_viewer.figure.marks = self._spectrum_viewer.figure.marks + [self._mark,] @@ -135,24 +140,20 @@ def on_mouse_move(self, data): elif coords_dataset == 'none': cube_data = self.viewer.layers[0].layer else: - for layer in self.viewer.layers: - if layer.layer.label == coords_dataset and layer.visible: - if isinstance(layer, BqplotImageSubsetLayerArtist): - # cannot expose info for spatial subset layers - continue - cube_data = layer.layer - break - else: - return + cube_data = self.viewer.session.application._tools['g-coords-info'].dataset.selected_obj - if cube_data.ndim != 3: + data_shape = cube_data.ndim if hasattr(cube_data, "ndim") else len(cube_data.shape) + if data_shape != 3: cube_data = [layer.layer for layer in self.viewer.layers if layer.state.visible and layer.layer.ndim == 3] if len(cube_data) == 0: return cube_data = cube_data[0] - spectrum = cube_data.get_object(statistic=None) + if isinstance(cube_data, Spectrum1D): + spectrum = cube_data + else: + spectrum = cube_data.get_object(statistic=None) # Note: change this when Spectrum1D.with_spectral_axis is fixed. x_unit = self._spectrum_viewer.state.x_display_unit if spectrum.spectral_axis.unit != x_unit: From bd81c8afd438fa9481c2e58b7f13e011816b3a90 Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Mon, 22 Jan 2024 14:21:13 -0500 Subject: [PATCH 13/14] Remove unused import --- jdaviz/configs/cubeviz/plugins/tools.py | 1 - 1 file changed, 1 deletion(-) diff --git a/jdaviz/configs/cubeviz/plugins/tools.py b/jdaviz/configs/cubeviz/plugins/tools.py index c8ff3a855e..28d7f4436f 100644 --- a/jdaviz/configs/cubeviz/plugins/tools.py +++ b/jdaviz/configs/cubeviz/plugins/tools.py @@ -4,7 +4,6 @@ from glue.config import viewer_tool from glue_jupyter.bqplot.image import BqplotImageView from glue_jupyter.bqplot.profile import BqplotProfileView -from glue_jupyter.bqplot.image.layer_artist import BqplotImageSubsetLayerArtist from glue.viewers.common.tool import CheckableTool import numpy as np from specutils import Spectrum1D From 2b2bd3ec57693d8234293266f2dec3ee477ef3d0 Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Mon, 22 Jan 2024 15:07:13 -0500 Subject: [PATCH 14/14] Improve test coverage --- .../cubeviz/plugins/tests/test_tools.py | 26 +++++++++++++++++-- jdaviz/configs/cubeviz/plugins/tools.py | 5 +++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/jdaviz/configs/cubeviz/plugins/tests/test_tools.py b/jdaviz/configs/cubeviz/plugins/tests/test_tools.py index 199fe77634..772f5ef2ab 100644 --- a/jdaviz/configs/cubeviz/plugins/tests/test_tools.py +++ b/jdaviz/configs/cubeviz/plugins/tests/test_tools.py @@ -5,10 +5,11 @@ @pytest.mark.filterwarnings('ignore:No observer defined on WCS') -def test_spectrum_at_spaxel(cubeviz_helper, spectrum1d_cube): - cubeviz_helper.load_data(spectrum1d_cube, data_label='test') +def test_spectrum_at_spaxel(cubeviz_helper, spectrum1d_cube_with_uncerts): + cubeviz_helper.load_data(spectrum1d_cube_with_uncerts, data_label='test') flux_viewer = cubeviz_helper.app.get_viewer("flux-viewer") + uncert_viewer = cubeviz_helper.app.get_viewer("uncert-viewer") spectrum_viewer = cubeviz_helper.app.get_viewer("spectrum-viewer") # Set the active tool to spectrumperspaxel @@ -36,6 +37,11 @@ def test_spectrum_at_spaxel(cubeviz_helper, spectrum1d_cube): assert len(subsets) == 1 assert isinstance(reg, RectanglePixelRegion) + # Move out of bounds + flux_viewer.toolbar.active_tool.on_mouse_move( + {'event': 'mousemove', 'domain': {'x': -1, 'y': -1}, 'altKey': False}) + assert flux_viewer.toolbar.active_tool._mark.visible is False + # Mouse leave event flux_viewer.toolbar.active_tool.on_mouse_move( {'event': 'mouseleave', 'domain': {'x': x, 'y': y}, 'altKey': False}) @@ -45,6 +51,22 @@ def test_spectrum_at_spaxel(cubeviz_helper, spectrum1d_cube): flux_viewer.toolbar.active_tool = None assert len(flux_viewer.native_marks) == 3 + # Check in uncertainty viewer as well. Set mouseover here + cubeviz_helper.app.session.application._tools['g-coords-info'].dataset.selected = 'none' + uncert_viewer.toolbar.active_tool = uncert_viewer.toolbar.tools['jdaviz:spectrumperspaxel'] + uncert_viewer.toolbar.active_tool.on_mouse_move( + {'event': 'mousemove', 'domain': {'x': x, 'y': y}, 'altKey': False}) + assert uncert_viewer.toolbar.active_tool._mark in spectrum_viewer.figure.marks + assert uncert_viewer.toolbar.active_tool._mark.visible is True + + # Select specific data + cubeviz_helper.app.session.application._tools['g-coords-info'].dataset.selected = 'test[FLUX]' + uncert_viewer.toolbar.active_tool = uncert_viewer.toolbar.tools['jdaviz:spectrumperspaxel'] + uncert_viewer.toolbar.active_tool.on_mouse_move( + {'event': 'mousemove', 'domain': {'x': x, 'y': y}, 'altKey': False}) + assert uncert_viewer.toolbar.active_tool._mark in spectrum_viewer.figure.marks + assert uncert_viewer.toolbar.active_tool._mark.visible is True + def test_spectrum_at_spaxel_altkey_true(cubeviz_helper, spectrum1d_cube): cubeviz_helper.load_data(spectrum1d_cube, data_label='test') diff --git a/jdaviz/configs/cubeviz/plugins/tools.py b/jdaviz/configs/cubeviz/plugins/tools.py index 28d7f4436f..d36ab7a42c 100644 --- a/jdaviz/configs/cubeviz/plugins/tools.py +++ b/jdaviz/configs/cubeviz/plugins/tools.py @@ -137,7 +137,10 @@ def on_mouse_move(self, data): if coords_dataset == 'auto': cube_data = self.viewer.active_image_layer.layer elif coords_dataset == 'none': - cube_data = self.viewer.layers[0].layer + if len(self.viewer.layers): + cube_data = self.viewer.layers[0].layer + else: + return else: cube_data = self.viewer.session.application._tools['g-coords-info'].dataset.selected_obj