From 6deaad2a5e26e04b4ff7d9fe7f01fb8b8fcb0e5e Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Thu, 7 Dec 2023 14:06:31 -0500 Subject: [PATCH 01/21] Working on section for bounds editing --- .../default/plugins/plot_options/plot_options.vue | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.vue b/jdaviz/configs/default/plugins/plot_options/plot_options.vue index a94d73d1b4..1487b93010 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.vue +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.vue @@ -39,6 +39,21 @@ :hint="viewer_multiselect ? 'Select viewers to set options simultaneously' : 'Select the viewer to set options.'" /> +
+ + + + Viewer axis limits + + + + TESTING + + + + +
+
Date: Fri, 8 Dec 2023 15:00:58 -0500 Subject: [PATCH 02/21] More work --- .../plugins/plot_options/plot_options.py | 9 ++++++++- .../plugins/plot_options/plot_options.vue | 17 ++++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.py b/jdaviz/configs/default/plugins/plot_options/plot_options.py index 75bf5c9c9c..c31c91c302 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.py +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.py @@ -177,6 +177,7 @@ class PlotOptions(PluginTemplateMixin): viewer_multiselect = Bool(False).tag(sync=True) viewer_items = List().tag(sync=True) viewer_selected = Any().tag(sync=True) # Any needed for multiselect + spectrum_viewer_limits = List().tag(sync=True) layer_multiselect = Bool(False).tag(sync=True) layer_items = List().tag(sync=True) @@ -557,7 +558,13 @@ def state_attr_for_line_visible(state): self.axes_visible = PlotOptionsSyncState(self, self.viewer, self.layer, 'show_axes', 'axes_visible_value', 'axes_visible_sync', state_filter=not_profile) - # zoom limits + + # zoom limits (spectrum viewer only) + self.spectrum_viewer_limits = [{"label": "x_min", "value": 0, "unit": "test"}, + {"label": "x_max", "value": 1, "unit": "test"}, + {"label": "y_min", "value": 0, "unit": "test"}, + {"label": "y_max", "value": 1, "unit": "test"}] + # display_units self.show_viewer_labels = self.app.state.settings['viewer_labels'] diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.vue b/jdaviz/configs/default/plugins/plot_options/plot_options.vue index 1487b93010..2ab6a11568 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.vue +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.vue @@ -39,20 +39,27 @@ :hint="viewer_multiselect ? 'Select viewers to set options simultaneously' : 'Select the viewer to set options.'" /> -
+ - Viewer axis limits + Viewer bounds - - TESTING + + -
+
From 6fcab6eaf7fe735dc80f8ee256400527a2b75ead Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Mon, 11 Dec 2023 14:08:45 -0500 Subject: [PATCH 03/21] Now works to update from UI for spectrum-viewer --- .../plugins/plot_options/plot_options.py | 30 +++++++++++++++---- .../plugins/plot_options/plot_options.vue | 5 +++- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.py b/jdaviz/configs/default/plugins/plot_options/plot_options.py index c31c91c302..dd189673c8 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.py +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.py @@ -177,7 +177,7 @@ class PlotOptions(PluginTemplateMixin): viewer_multiselect = Bool(False).tag(sync=True) viewer_items = List().tag(sync=True) viewer_selected = Any().tag(sync=True) # Any needed for multiselect - spectrum_viewer_limits = List().tag(sync=True) + spectrum_viewer_limits = Dict().tag(sync=True) layer_multiselect = Bool(False).tag(sync=True) layer_items = List().tag(sync=True) @@ -560,10 +560,15 @@ def state_attr_for_line_visible(state): state_filter=not_profile) # zoom limits (spectrum viewer only) - self.spectrum_viewer_limits = [{"label": "x_min", "value": 0, "unit": "test"}, - {"label": "x_max", "value": 1, "unit": "test"}, - {"label": "y_min", "value": 0, "unit": "test"}, - {"label": "y_max", "value": 1, "unit": "test"}] + self.spectrum_viewer_limits = {"x_min": {"value": 0, "unit": "test"}, + "x_max": {"value": 1, "unit": "test"}, + "y_min": {"value": 0, "unit": "test"}, + "y_max": {"value": 1, "unit": "test"}} + + if "spectrum-viewer" in self.viewer.choices: + self.spectrum_viewer = self.app.get_viewer('spectrum-viewer') + for attr in ('x_min', 'x_max', 'y_min', 'y_max'): + self.spectrum_viewer.state.add_callback(attr, self._sync_sv_limits) # display_units @@ -719,6 +724,21 @@ def _update_stretch_hist_sync(self, msg={}): self.stretch_hist_sync = {'in_subscribed_states': bool(np.any([sync.get('in_subscribed_states', False) for sync in all_syncs])), # noqa 'mixed': bool(np.any([sync.get('mixed', False) for sync in all_syncs]))} # noqa + def _sync_sv_limits(self, msg={}): + for axis in ("x", "y"): + unit = getattr(self.spectrum_viewer.state, f"{axis}_display_unit") + for bound in ("_min", "_max"): + value = getattr(self.spectrum_viewer.state, f"{axis}{bound}") + self.spectrum_viewer_limits[f"{axis}{bound}"]["value"] = value + self.spectrum_viewer_limits[f"{axis}{bound}"]["unit"] = unit + self.send_state("spectrum_viewer_limits") + + def vue_apply_updated_bounds(self, msg={}): + self.spectrum_viewer.set_limits(x_min = self.spectrum_viewer_limits["x_min"]["value"], + x_max = self.spectrum_viewer_limits["x_max"]["value"], + y_min = self.spectrum_viewer_limits["y_min"]["value"], + y_max = self.spectrum_viewer_limits["y_max"]["value"],) + @observe('is_active', 'layer_selected', 'viewer_selected', 'stretch_hist_zoom_limits') @skip_if_no_updates_since_last_active() diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.vue b/jdaviz/configs/default/plugins/plot_options/plot_options.vue index 2ab6a11568..67aec819b9 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.vue +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.vue @@ -39,7 +39,7 @@ :hint="viewer_multiselect ? 'Select viewers to set options simultaneously' : 'Select the viewer to set options.'" /> - + @@ -56,6 +56,9 @@ :suffix="item.unit" > + + Apply Updated Bounds + From 670efa3651d21da054b7ed8965a35738e2e66541 Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Mon, 11 Dec 2023 14:09:36 -0500 Subject: [PATCH 04/21] Fix codestyle --- .../configs/default/plugins/plot_options/plot_options.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.py b/jdaviz/configs/default/plugins/plot_options/plot_options.py index dd189673c8..d7585aaf53 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.py +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.py @@ -734,10 +734,10 @@ def _sync_sv_limits(self, msg={}): self.send_state("spectrum_viewer_limits") def vue_apply_updated_bounds(self, msg={}): - self.spectrum_viewer.set_limits(x_min = self.spectrum_viewer_limits["x_min"]["value"], - x_max = self.spectrum_viewer_limits["x_max"]["value"], - y_min = self.spectrum_viewer_limits["y_min"]["value"], - y_max = self.spectrum_viewer_limits["y_max"]["value"],) + self.spectrum_viewer.set_limits(x_min=self.spectrum_viewer_limits["x_min"]["value"], + x_max=self.spectrum_viewer_limits["x_max"]["value"], + y_min=self.spectrum_viewer_limits["y_min"]["value"], + y_max=self.spectrum_viewer_limits["y_max"]["value"],) @observe('is_active', 'layer_selected', 'viewer_selected', 'stretch_hist_zoom_limits') From c84f99992fe72d40bbbe0012752b8611d24da8b0 Mon Sep 17 00:00:00 2001 From: Ricky O'Steen <39831871+rosteen@users.noreply.github.com> Date: Mon, 11 Dec 2023 15:42:33 -0500 Subject: [PATCH 05/21] Update jdaviz/configs/default/plugins/plot_options/plot_options.vue Co-authored-by: Kyle Conroy --- jdaviz/configs/default/plugins/plot_options/plot_options.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.vue b/jdaviz/configs/default/plugins/plot_options/plot_options.vue index 67aec819b9..ed5e632d68 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.vue +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.vue @@ -57,7 +57,8 @@ > - Apply Updated Bounds + Apply Updated Bounds + From 07942e195b78064ac7a0fbf26e9b38cd2fa55d3d Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Tue, 12 Dec 2023 11:48:23 -0500 Subject: [PATCH 06/21] Add changelog --- CHANGES.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 61bc87d29e..9b3ab71d2b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -7,6 +7,8 @@ New Features - Stretch histogram shows a spinner when the histogram data is updating. [#2644] +- Spectrum viewer bounds can now be set through the Plot Options UI. [#2604] + Cubeviz ^^^^^^^ - Calculated moments can now be output in velocity units. [#2584, #2588] From a7adb7e0c582561fcb5eac59ffb486a00cec9692 Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Fri, 15 Dec 2023 12:53:15 -0500 Subject: [PATCH 07/21] Working on handling multiselect --- .../plugins/plot_options/plot_options.py | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.py b/jdaviz/configs/default/plugins/plot_options/plot_options.py index d7585aaf53..a1fe83ff90 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.py +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.py @@ -177,7 +177,7 @@ class PlotOptions(PluginTemplateMixin): viewer_multiselect = Bool(False).tag(sync=True) viewer_items = List().tag(sync=True) viewer_selected = Any().tag(sync=True) # Any needed for multiselect - spectrum_viewer_limits = Dict().tag(sync=True) + viewer_limits = Dict().tag(sync=True) layer_multiselect = Bool(False).tag(sync=True) layer_items = List().tag(sync=True) @@ -559,16 +559,17 @@ def state_attr_for_line_visible(state): 'axes_visible_value', 'axes_visible_sync', state_filter=not_profile) - # zoom limits (spectrum viewer only) - self.spectrum_viewer_limits = {"x_min": {"value": 0, "unit": "test"}, - "x_max": {"value": 1, "unit": "test"}, - "y_min": {"value": 0, "unit": "test"}, - "y_max": {"value": 1, "unit": "test"}} - - if "spectrum-viewer" in self.viewer.choices: - self.spectrum_viewer = self.app.get_viewer('spectrum-viewer') - for attr in ('x_min', 'x_max', 'y_min', 'y_max'): - self.spectrum_viewer.state.add_callback(attr, self._sync_sv_limits) + # zoom limits (spectrum viewers only) + self.viewer_limits = {} + for viewer in self.viewer.choices: + temp_viewer = self.app.get_viewer(viewer) + if not_image(temp_viewer.state): + self.viewer_limits[viewer] = {"x_min": {"value": 0, "unit": "test"}, + "x_max": {"value": 1, "unit": "test"}, + "y_min": {"value": 0, "unit": "test"}, + "y_max": {"value": 1, "unit": "test"}} + for attr in ('x_min', 'x_max', 'y_min', 'y_max'): + temp_viewer.state.add_callback(attr, self._sync_viewer_limits) # display_units @@ -724,20 +725,21 @@ def _update_stretch_hist_sync(self, msg={}): self.stretch_hist_sync = {'in_subscribed_states': bool(np.any([sync.get('in_subscribed_states', False) for sync in all_syncs])), # noqa 'mixed': bool(np.any([sync.get('mixed', False) for sync in all_syncs]))} # noqa - def _sync_sv_limits(self, msg={}): + def _sync_viewer_limits(self, msg={}): + print(msg) for axis in ("x", "y"): unit = getattr(self.spectrum_viewer.state, f"{axis}_display_unit") for bound in ("_min", "_max"): value = getattr(self.spectrum_viewer.state, f"{axis}{bound}") - self.spectrum_viewer_limits[f"{axis}{bound}"]["value"] = value - self.spectrum_viewer_limits[f"{axis}{bound}"]["unit"] = unit - self.send_state("spectrum_viewer_limits") + self.viewer_limits[f"{axis}{bound}"]["value"] = value + self.viewer_limits[f"{axis}{bound}"]["unit"] = unit + self.send_state("viewer_limits") def vue_apply_updated_bounds(self, msg={}): - self.spectrum_viewer.set_limits(x_min=self.spectrum_viewer_limits["x_min"]["value"], - x_max=self.spectrum_viewer_limits["x_max"]["value"], - y_min=self.spectrum_viewer_limits["y_min"]["value"], - y_max=self.spectrum_viewer_limits["y_max"]["value"],) + self.spectrum_viewer.set_limits(x_min=self.viewer_limits["x_min"]["value"], + x_max=self.viewer_limits["x_max"]["value"], + y_min=self.viewer_limits["y_min"]["value"], + y_max=self.viewer_limits["y_max"]["value"],) @observe('is_active', 'layer_selected', 'viewer_selected', 'stretch_hist_zoom_limits') From 438a3c1333eec87f5d61d5b9513c5ac3b54ad9b8 Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Fri, 15 Dec 2023 15:57:10 -0500 Subject: [PATCH 08/21] More work on multi Forgot vue file --- .../plugins/plot_options/plot_options.py | 31 +++++++++++-------- .../plugins/plot_options/plot_options.vue | 10 +++--- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.py b/jdaviz/configs/default/plugins/plot_options/plot_options.py index a1fe83ff90..5090a10cb8 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.py +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.py @@ -14,7 +14,7 @@ from glue.config import colormaps, stretches from glue.viewers.scatter.state import ScatterViewerState from glue.viewers.profile.state import ProfileViewerState, ProfileLayerState -from glue.viewers.image.state import ImageSubsetLayerState +from glue.viewers.image.state import ImageSubsetLayerState, ImageViewerState from glue.viewers.scatter.state import ScatterLayerState as BqplotScatterLayerState from glue.viewers.image.composite_array import COLOR_CONVERTER from glue_jupyter.bqplot.image.state import BqplotImageLayerState @@ -563,7 +563,8 @@ def state_attr_for_line_visible(state): self.viewer_limits = {} for viewer in self.viewer.choices: temp_viewer = self.app.get_viewer(viewer) - if not_image(temp_viewer.state): + if not isinstance(temp_viewer.state, ImageViewerState): + print(f"Adding callback for {temp_viewer}, {type(temp_viewer.state)}") self.viewer_limits[viewer] = {"x_min": {"value": 0, "unit": "test"}, "x_max": {"value": 1, "unit": "test"}, "y_min": {"value": 0, "unit": "test"}, @@ -726,20 +727,24 @@ def _update_stretch_hist_sync(self, msg={}): 'mixed': bool(np.any([sync.get('mixed', False) for sync in all_syncs]))} # noqa def _sync_viewer_limits(self, msg={}): - print(msg) - for axis in ("x", "y"): - unit = getattr(self.spectrum_viewer.state, f"{axis}_display_unit") - for bound in ("_min", "_max"): - value = getattr(self.spectrum_viewer.state, f"{axis}{bound}") - self.viewer_limits[f"{axis}{bound}"]["value"] = value - self.viewer_limits[f"{axis}{bound}"]["unit"] = unit + for viewer in self.viewer_limits: + temp_viewer = self.app.get_viewer(viewer) + for axis in ("x", "y"): + unit = getattr(temp_viewer.state, f"{axis}_display_unit") + for bound in ("_min", "_max"): + value = getattr(temp_viewer.state, f"{axis}{bound}") + self.viewer_limits[viewer][f"{axis}{bound}"]["value"] = value + self.viewer_limits[viewer][f"{axis}{bound}"]["unit"] = unit self.send_state("viewer_limits") def vue_apply_updated_bounds(self, msg={}): - self.spectrum_viewer.set_limits(x_min=self.viewer_limits["x_min"]["value"], - x_max=self.viewer_limits["x_max"]["value"], - y_min=self.viewer_limits["y_min"]["value"], - y_max=self.viewer_limits["y_max"]["value"],) + viewers = self.viewer.selected_obj if self.viewer_multiselect else [self.viewer.selected_obj] + for viewer in viewers: + temp_viewer = self.app.get_viewer(viewer) + temp_viewer.set_limits(x_min=self.viewer_limits["x_min"]["value"], + x_max=self.viewer_limits["x_max"]["value"], + y_min=self.viewer_limits["y_min"]["value"], + y_max=self.viewer_limits["y_max"]["value"],) @observe('is_active', 'layer_selected', 'viewer_selected', 'stretch_hist_zoom_limits') diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.vue b/jdaviz/configs/default/plugins/plot_options/plot_options.vue index ed5e632d68..68aa7563e9 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.vue +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.vue @@ -46,7 +46,7 @@ Viewer bounds - +
- @@ -505,7 +505,7 @@
Date: Tue, 19 Dec 2023 12:24:27 -0500 Subject: [PATCH 09/21] Converting these to PlotOptionSynchedState objects with multiselect handling --- .../plugins/plot_options/plot_options.py | 42 ++++++++++++++----- .../plugins/plot_options/plot_options.vue | 42 +++++++++++++++---- jdaviz/core/template_mixin.py | 2 +- 3 files changed, 67 insertions(+), 19 deletions(-) diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.py b/jdaviz/configs/default/plugins/plot_options/plot_options.py index 5090a10cb8..4c7d990de4 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.py +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.py @@ -205,6 +205,18 @@ class PlotOptions(PluginTemplateMixin): uncertainty_visible_value = Int().tag(sync=True) uncertainty_visible_sync = Dict().tag(sync=True) + viewer_x_min_value = Float().tag(sync=True) + viewer_x_min_sync = Dict().tag(sync=True) + + viewer_x_max_value = Float().tag(sync=True) + viewer_x_max_sync = Dict().tag(sync=True) + + viewer_y_min_value = Float().tag(sync=True) + viewer_y_min_sync = Dict().tag(sync=True) + + viewer_y_max_value = Float().tag(sync=True) + viewer_y_max_sync = Dict().tag(sync=True) + # scatter/marker options marker_visible_value = Bool().tag(sync=True) marker_visible_sync = Dict().tag(sync=True) @@ -369,6 +381,9 @@ def is_image(state): def not_image(state): return not is_image(state) + def not_image_viewer(state): + return not isinstance(state, ImageViewerState) + def not_image_or_spatial_subset(state): return not is_image(state) and not is_spatial_subset(state) @@ -407,6 +422,22 @@ def state_attr_for_line_visible(state): self.uncertainty_visible = PlotOptionsSyncState(self, self.viewer, self.layer, 'show_uncertainty', # noqa 'uncertainty_visible_value', 'uncertainty_visible_sync') # noqa + self.viewer_x_min = PlotOptionsSyncState(self, self.viewer, self.layer, 'x_min', + 'viewer_x_min_value', 'viewer_x_min_sync', + state_filter=not_image_viewer) + + self.viewer_x_max = PlotOptionsSyncState(self, self.viewer, self.layer, 'x_max', + 'viewer_x_max_value', 'viewer_x_max_sync', + state_filter=not_image_viewer) + + self.viewer_y_min = PlotOptionsSyncState(self, self.viewer, self.layer, 'y_min', + 'viewer_y_min_value', 'viewer_y_min_sync', + state_filter=not_image) + + self.viewer_y_max = PlotOptionsSyncState(self, self.viewer, self.layer, 'y_max', + 'viewer_y_max_value', 'viewer_y_max_sync', + state_filter=not_image) + # Scatter/marker options: # NOTE: marker_visible hides the entire layer (including the line) self.marker_visible = PlotOptionsSyncState(self, self.viewer, self.layer, 'visible', @@ -733,19 +764,10 @@ def _sync_viewer_limits(self, msg={}): unit = getattr(temp_viewer.state, f"{axis}_display_unit") for bound in ("_min", "_max"): value = getattr(temp_viewer.state, f"{axis}{bound}") - self.viewer_limits[viewer][f"{axis}{bound}"]["value"] = value + setattr(self, f"{axis}{bound}_value", value) self.viewer_limits[viewer][f"{axis}{bound}"]["unit"] = unit self.send_state("viewer_limits") - def vue_apply_updated_bounds(self, msg={}): - viewers = self.viewer.selected_obj if self.viewer_multiselect else [self.viewer.selected_obj] - for viewer in viewers: - temp_viewer = self.app.get_viewer(viewer) - temp_viewer.set_limits(x_min=self.viewer_limits["x_min"]["value"], - x_max=self.viewer_limits["x_max"]["value"], - y_min=self.viewer_limits["y_min"]["value"], - y_max=self.viewer_limits["y_max"]["value"],) - @observe('is_active', 'layer_selected', 'viewer_selected', 'stretch_hist_zoom_limits') @skip_if_no_updates_since_last_active() diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.vue b/jdaviz/configs/default/plugins/plot_options/plot_options.vue index 68aa7563e9..feb721d24b 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.vue +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.vue @@ -46,16 +46,42 @@ Viewer bounds - + - + + + + + + + + + + Apply Updated Bounds diff --git a/jdaviz/core/template_mixin.py b/jdaviz/core/template_mixin.py index 887212c9b2..612faeaedc 100644 --- a/jdaviz/core/template_mixin.py +++ b/jdaviz/core/template_mixin.py @@ -3301,7 +3301,7 @@ def _on_viewer_layer_changed(self, msg=None): 'in_subscribed_states': in_subscribed_states, 'icons': icons, 'mixed': self.is_mixed(current_glue_values)} - if len(current_glue_values): + if len(current_glue_values) and current_glue_values[0] is not None: # sync the initial value of the widget, avoiding recursion self._on_glue_value_changed(current_glue_values[0]) From 25cb824c45276aeca2502f957e2b89d3c68fc19b Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Tue, 19 Dec 2023 14:09:03 -0500 Subject: [PATCH 10/21] Re-add unit suffix --- .../plugins/plot_options/plot_options.py | 29 +++++++++---------- .../plugins/plot_options/plot_options.vue | 8 ++--- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.py b/jdaviz/configs/default/plugins/plot_options/plot_options.py index 4c7d990de4..8752208a20 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.py +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.py @@ -211,12 +211,18 @@ class PlotOptions(PluginTemplateMixin): viewer_x_max_value = Float().tag(sync=True) viewer_x_max_sync = Dict().tag(sync=True) + viewer_x_unit_value = Unicode().tag(sync=True) + viewer_x_unit_sync = Dict().tag(sync=True) + viewer_y_min_value = Float().tag(sync=True) viewer_y_min_sync = Dict().tag(sync=True) viewer_y_max_value = Float().tag(sync=True) viewer_y_max_sync = Dict().tag(sync=True) + viewer_y_unit_value = Unicode().tag(sync=True) + viewer_y_unit_sync = Dict().tag(sync=True) + # scatter/marker options marker_visible_value = Bool().tag(sync=True) marker_visible_sync = Dict().tag(sync=True) @@ -430,6 +436,10 @@ def state_attr_for_line_visible(state): 'viewer_x_max_value', 'viewer_x_max_sync', state_filter=not_image_viewer) + self.viewer_x_unit = PlotOptionsSyncState(self, self.viewer, self.layer, 'x_display_unit', + 'viewer_x_unit_value', 'viewer_x_unit_sync', + state_filter=not_image_viewer) + self.viewer_y_min = PlotOptionsSyncState(self, self.viewer, self.layer, 'y_min', 'viewer_y_min_value', 'viewer_y_min_sync', state_filter=not_image) @@ -438,6 +448,10 @@ def state_attr_for_line_visible(state): 'viewer_y_max_value', 'viewer_y_max_sync', state_filter=not_image) + self.viewer_y_unit = PlotOptionsSyncState(self, self.viewer, self.layer, 'y_display_unit', + 'viewer_y_unit_value', 'viewer_y_unit_sync', + state_filter=not_image_viewer) + # Scatter/marker options: # NOTE: marker_visible hides the entire layer (including the line) self.marker_visible = PlotOptionsSyncState(self, self.viewer, self.layer, 'visible', @@ -590,21 +604,6 @@ def state_attr_for_line_visible(state): 'axes_visible_value', 'axes_visible_sync', state_filter=not_profile) - # zoom limits (spectrum viewers only) - self.viewer_limits = {} - for viewer in self.viewer.choices: - temp_viewer = self.app.get_viewer(viewer) - if not isinstance(temp_viewer.state, ImageViewerState): - print(f"Adding callback for {temp_viewer}, {type(temp_viewer.state)}") - self.viewer_limits[viewer] = {"x_min": {"value": 0, "unit": "test"}, - "x_max": {"value": 1, "unit": "test"}, - "y_min": {"value": 0, "unit": "test"}, - "y_max": {"value": 1, "unit": "test"}} - for attr in ('x_min', 'x_max', 'y_min', 'y_max'): - temp_viewer.state.add_callback(attr, self._sync_viewer_limits) - - # display_units - self.show_viewer_labels = self.app.state.settings['viewer_labels'] self.app.state.add_callback('settings', self._on_app_settings_changed) diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.vue b/jdaviz/configs/default/plugins/plot_options/plot_options.vue index feb721d24b..eca2ed98d7 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.vue +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.vue @@ -53,6 +53,7 @@ v-model.number="viewer_x_min_value" type="number" :step="stretch_vstep" + :suffix="viewer_x_unit_value" > @@ -62,6 +63,7 @@ v-model.number="viewer_x_max_value" type="number" :step="stretch_vstep" + :suffix="viewer_x_unit_value" > @@ -71,6 +73,7 @@ v-model.number="viewer_y_min_value" type="number" :step="stretch_vstep" + :suffix="viewer_y_unit_value" > @@ -80,12 +83,9 @@ v-model.number="viewer_y_max_value" type="number" :step="stretch_vstep" + :suffix="viewer_y_unit_value" > - - Apply Updated Bounds - - From b074a291a92182149cb7a910345e25e90858c46a Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Tue, 19 Dec 2023 14:34:22 -0500 Subject: [PATCH 11/21] Dynamic viewer bounds based on max when viewer selected --- .../plugins/plot_options/plot_options.py | 27 +++++++++++-------- .../plugins/plot_options/plot_options.vue | 8 +++--- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.py b/jdaviz/configs/default/plugins/plot_options/plot_options.py index 8752208a20..e2c474e2f7 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.py +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.py @@ -223,6 +223,9 @@ class PlotOptions(PluginTemplateMixin): viewer_y_unit_value = Unicode().tag(sync=True) viewer_y_unit_sync = Dict().tag(sync=True) + viewer_x_bound_step = Float(0.1).tag(sync=True) # dynamic based on maximum value + viewer_y_bound_step = Float(0.1).tag(sync=True) # dynamic based on maximum value + # scatter/marker options marker_visible_value = Bool().tag(sync=True) marker_visible_sync = Dict().tag(sync=True) @@ -743,6 +746,19 @@ def apply_RGB_presets(self): def vue_apply_RGB_presets(self, data): self.apply_RGB_presets() + @observe('viewer_selected') + def _update_viewer_bound_steps(self, msg={}): + if not hasattr(self, 'viewer'): # pragma: no cover + # plugin hasn't been fully initialized yet + return + + viewer = self.viewer.selected_obj[0] if self.viewer_multiselect else self.viewer.selected_obj + if not isinstance(viewer.state, ImageViewerState): + stretch_step = (viewer.state.x_max) / 100. + self.viewer_x_bound_step = np.round(stretch_step, decimals=-int(np.log10(stretch_step))+1) + stretch_step = (viewer.state.y_max) / 100. + self.viewer_y_bound_step = np.round(stretch_step, decimals=-int(np.log10(stretch_step))+1) + @observe('stretch_function_sync', 'stretch_params_sync', 'stretch_vmin_sync', 'stretch_vmax_sync', 'image_color_mode_sync', 'image_color_sync', 'image_colormap_sync') @@ -756,17 +772,6 @@ def _update_stretch_hist_sync(self, msg={}): self.stretch_hist_sync = {'in_subscribed_states': bool(np.any([sync.get('in_subscribed_states', False) for sync in all_syncs])), # noqa 'mixed': bool(np.any([sync.get('mixed', False) for sync in all_syncs]))} # noqa - def _sync_viewer_limits(self, msg={}): - for viewer in self.viewer_limits: - temp_viewer = self.app.get_viewer(viewer) - for axis in ("x", "y"): - unit = getattr(temp_viewer.state, f"{axis}_display_unit") - for bound in ("_min", "_max"): - value = getattr(temp_viewer.state, f"{axis}{bound}") - setattr(self, f"{axis}{bound}_value", value) - self.viewer_limits[viewer][f"{axis}{bound}"]["unit"] = unit - self.send_state("viewer_limits") - @observe('is_active', 'layer_selected', 'viewer_selected', 'stretch_hist_zoom_limits') @skip_if_no_updates_since_last_active() diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.vue b/jdaviz/configs/default/plugins/plot_options/plot_options.vue index eca2ed98d7..9fc4895c9a 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.vue +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.vue @@ -52,7 +52,7 @@ label="Viewer X Min" v-model.number="viewer_x_min_value" type="number" - :step="stretch_vstep" + :step="viewer_x_bound_step" :suffix="viewer_x_unit_value" > @@ -62,7 +62,7 @@ label="Viewer X Max" v-model.number="viewer_x_max_value" type="number" - :step="stretch_vstep" + :step="viewer_x_bound_step" :suffix="viewer_x_unit_value" > @@ -72,7 +72,7 @@ label="Viewer Y Min" v-model.number="viewer_y_min_value" type="number" - :step="stretch_vstep" + :step="viewer_y_bound_step" :suffix="viewer_y_unit_value" > @@ -82,7 +82,7 @@ label="Viewer Y Max" v-model.number="viewer_y_max_value" type="number" - :step="stretch_vstep" + :step="viewer_y_bound_step" :suffix="viewer_y_unit_value" > From a1fffcd87d4ef7d5cbdced45dcdb78c75025d019 Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Tue, 19 Dec 2023 14:36:31 -0500 Subject: [PATCH 12/21] Codestyle --- .../plugins/plot_options/plot_options.py | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.py b/jdaviz/configs/default/plugins/plot_options/plot_options.py index e2c474e2f7..ece774c458 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.py +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.py @@ -431,29 +431,25 @@ def state_attr_for_line_visible(state): self.uncertainty_visible = PlotOptionsSyncState(self, self.viewer, self.layer, 'show_uncertainty', # noqa 'uncertainty_visible_value', 'uncertainty_visible_sync') # noqa + # Viewer bounds self.viewer_x_min = PlotOptionsSyncState(self, self.viewer, self.layer, 'x_min', 'viewer_x_min_value', 'viewer_x_min_sync', state_filter=not_image_viewer) - self.viewer_x_max = PlotOptionsSyncState(self, self.viewer, self.layer, 'x_max', 'viewer_x_max_value', 'viewer_x_max_sync', state_filter=not_image_viewer) - self.viewer_x_unit = PlotOptionsSyncState(self, self.viewer, self.layer, 'x_display_unit', - 'viewer_x_unit_value', 'viewer_x_unit_sync', - state_filter=not_image_viewer) - + 'viewer_x_unit_value', 'viewer_x_unit_sync', + state_filter=not_image_viewer) self.viewer_y_min = PlotOptionsSyncState(self, self.viewer, self.layer, 'y_min', 'viewer_y_min_value', 'viewer_y_min_sync', state_filter=not_image) - self.viewer_y_max = PlotOptionsSyncState(self, self.viewer, self.layer, 'y_max', 'viewer_y_max_value', 'viewer_y_max_sync', state_filter=not_image) - self.viewer_y_unit = PlotOptionsSyncState(self, self.viewer, self.layer, 'y_display_unit', - 'viewer_y_unit_value', 'viewer_y_unit_sync', - state_filter=not_image_viewer) + 'viewer_y_unit_value', 'viewer_y_unit_sync', + state_filter=not_image_viewer) # Scatter/marker options: # NOTE: marker_visible hides the entire layer (including the line) @@ -752,12 +748,14 @@ def _update_viewer_bound_steps(self, msg={}): # plugin hasn't been fully initialized yet return - viewer = self.viewer.selected_obj[0] if self.viewer_multiselect else self.viewer.selected_obj + viewer = self.viewer.selected_obj[0] if self.viewer_multiselect else self.viewer.selected_obj # noqa if not isinstance(viewer.state, ImageViewerState): stretch_step = (viewer.state.x_max) / 100. - self.viewer_x_bound_step = np.round(stretch_step, decimals=-int(np.log10(stretch_step))+1) + self.viewer_x_bound_step = np.round(stretch_step, + decimals=-int(np.log10(stretch_step))+1) stretch_step = (viewer.state.y_max) / 100. - self.viewer_y_bound_step = np.round(stretch_step, decimals=-int(np.log10(stretch_step))+1) + self.viewer_y_bound_step = np.round(stretch_step, + decimals=-int(np.log10(stretch_step))+1) @observe('stretch_function_sync', 'stretch_params_sync', 'stretch_vmin_sync', 'stretch_vmax_sync', From 5fb880630a87860a15620327d21bc8daf8ae22bb Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Tue, 19 Dec 2023 14:57:29 -0500 Subject: [PATCH 13/21] Lost this in rebase --- jdaviz/core/template_mixin.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/jdaviz/core/template_mixin.py b/jdaviz/core/template_mixin.py index 612faeaedc..660b756371 100644 --- a/jdaviz/core/template_mixin.py +++ b/jdaviz/core/template_mixin.py @@ -3323,6 +3323,11 @@ def is_mixed(self, glue_values): return True return False + + # Need this for temporary None value during startup + elif len(glue_values) and glue_values[0] is None: + return False + return len(np.unique(glue_values, axis=0)) > 1 def _update_mixed_state(self): From abb7ccccb27c7aecf6dfd8151f1de8b1884d0b19 Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Tue, 19 Dec 2023 15:43:46 -0500 Subject: [PATCH 14/21] Use FloatHandleEmpty --- .../default/plugins/plot_options/plot_options.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.py b/jdaviz/configs/default/plugins/plot_options/plot_options.py index ece774c458..3922034a1d 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.py +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.py @@ -26,7 +26,7 @@ skip_if_no_updates_since_last_active, with_spinner) from jdaviz.core.user_api import PluginUserApi from jdaviz.core.tools import ICON_DIR -from jdaviz.core.custom_traitlets import IntHandleEmpty +from jdaviz.core.custom_traitlets import IntHandleEmpty, FloatHandleEmpty from scipy.interpolate import PchipInterpolator @@ -205,19 +205,19 @@ class PlotOptions(PluginTemplateMixin): uncertainty_visible_value = Int().tag(sync=True) uncertainty_visible_sync = Dict().tag(sync=True) - viewer_x_min_value = Float().tag(sync=True) + viewer_x_min_value = FloatHandleEmpty().tag(sync=True) viewer_x_min_sync = Dict().tag(sync=True) - viewer_x_max_value = Float().tag(sync=True) + viewer_x_max_value = FloatHandleEmpty().tag(sync=True) viewer_x_max_sync = Dict().tag(sync=True) viewer_x_unit_value = Unicode().tag(sync=True) viewer_x_unit_sync = Dict().tag(sync=True) - viewer_y_min_value = Float().tag(sync=True) + viewer_y_min_value = FloatHandleEmpty().tag(sync=True) viewer_y_min_sync = Dict().tag(sync=True) - viewer_y_max_value = Float().tag(sync=True) + viewer_y_max_value = FloatHandleEmpty().tag(sync=True) viewer_y_max_sync = Dict().tag(sync=True) viewer_y_unit_value = Unicode().tag(sync=True) From 5968634426dfafa41d24fe7edce6c39c0ab715d8 Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Tue, 19 Dec 2023 16:11:40 -0500 Subject: [PATCH 15/21] Resolve test failures --- .../plugins/plot_options/plot_options.py | 22 ++++++++++++------- jdaviz/core/template_mixin.py | 8 +++++-- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.py b/jdaviz/configs/default/plugins/plot_options/plot_options.py index 3922034a1d..912401ad6c 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.py +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.py @@ -211,7 +211,7 @@ class PlotOptions(PluginTemplateMixin): viewer_x_max_value = FloatHandleEmpty().tag(sync=True) viewer_x_max_sync = Dict().tag(sync=True) - viewer_x_unit_value = Unicode().tag(sync=True) + viewer_x_unit_value = Unicode(allow_none=True).tag(sync=True) viewer_x_unit_sync = Dict().tag(sync=True) viewer_y_min_value = FloatHandleEmpty().tag(sync=True) @@ -220,7 +220,7 @@ class PlotOptions(PluginTemplateMixin): viewer_y_max_value = FloatHandleEmpty().tag(sync=True) viewer_y_max_sync = Dict().tag(sync=True) - viewer_y_unit_value = Unicode().tag(sync=True) + viewer_y_unit_value = Unicode(allow_none=True).tag(sync=True) viewer_y_unit_sync = Dict().tag(sync=True) viewer_x_bound_step = Float(0.1).tag(sync=True) # dynamic based on maximum value @@ -748,14 +748,20 @@ def _update_viewer_bound_steps(self, msg={}): # plugin hasn't been fully initialized yet return + if not self.viewer.selected: # pragma: no cover + # nothing selected yet + return + viewer = self.viewer.selected_obj[0] if self.viewer_multiselect else self.viewer.selected_obj # noqa if not isinstance(viewer.state, ImageViewerState): - stretch_step = (viewer.state.x_max) / 100. - self.viewer_x_bound_step = np.round(stretch_step, - decimals=-int(np.log10(stretch_step))+1) - stretch_step = (viewer.state.y_max) / 100. - self.viewer_y_bound_step = np.round(stretch_step, - decimals=-int(np.log10(stretch_step))+1) + if hasattr(viewer.state, "x_max") and viewer.state.x_max is not None: + stretch_step = (viewer.state.x_max) / 100. + self.viewer_x_bound_step = np.round(stretch_step, + decimals=-int(np.log10(stretch_step))+1) + if hasattr(viewer.state, "y_max") and viewer.state.y_max is not None: + stretch_step = (viewer.state.y_max) / 100. + self.viewer_y_bound_step = np.round(stretch_step, + decimals=-int(np.log10(stretch_step))+1) @observe('stretch_function_sync', 'stretch_params_sync', 'stretch_vmin_sync', 'stretch_vmax_sync', diff --git a/jdaviz/core/template_mixin.py b/jdaviz/core/template_mixin.py index 660b756371..cc04dbf7ec 100644 --- a/jdaviz/core/template_mixin.py +++ b/jdaviz/core/template_mixin.py @@ -3325,8 +3325,12 @@ def is_mixed(self, glue_values): return False # Need this for temporary None value during startup - elif len(glue_values) and glue_values[0] is None: - return False + elif len(glue_values): + no_nones = [x for x in glue_values if x is not None] + if len(no_nones) == 0: + return False + if len(no_nones) != len(glue_values): + return True return len(np.unique(glue_values, axis=0)) > 1 From 5018d1b1823275b4e1a82e45183f071396926b1c Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Thu, 28 Dec 2023 13:48:19 -0500 Subject: [PATCH 16/21] Also round displayed min/max values --- .../default/plugins/plot_options/plot_options.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.py b/jdaviz/configs/default/plugins/plot_options/plot_options.py index 912401ad6c..a6b35b2903 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.py +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.py @@ -754,14 +754,19 @@ def _update_viewer_bound_steps(self, msg={}): viewer = self.viewer.selected_obj[0] if self.viewer_multiselect else self.viewer.selected_obj # noqa if not isinstance(viewer.state, ImageViewerState): + # We round these values to show, e.g., 7.15 instead of 7.1499999 if hasattr(viewer.state, "x_max") and viewer.state.x_max is not None: stretch_step = (viewer.state.x_max) / 100. - self.viewer_x_bound_step = np.round(stretch_step, - decimals=-int(np.log10(stretch_step))+1) + decimals = -int(np.log10(stretch_step))+1 + self.viewer_x_bound_step = np.round(stretch_step, decimals=decimals) + self.viewer_x_max_value = np.round(self.viewer_x_max_value, decimals=decimals) + self.viewer_x_min_value = np.round(self.viewer_x_min_value, decimals=decimals) if hasattr(viewer.state, "y_max") and viewer.state.y_max is not None: stretch_step = (viewer.state.y_max) / 100. - self.viewer_y_bound_step = np.round(stretch_step, - decimals=-int(np.log10(stretch_step))+1) + decimals=-int(np.log10(stretch_step))+1 + self.viewer_y_bound_step = np.round(stretch_step, decimals=decimals) + self.viewer_y_max_value = np.round(self.viewer_y_max_value, decimals=decimals) + self.viewer_y_min_value = np.round(self.viewer_y_min_value, decimals=decimals) @observe('stretch_function_sync', 'stretch_params_sync', 'stretch_vmin_sync', 'stretch_vmax_sync', From dc1a3ee53fb0b5208c52e1bf2ebb17a305dd05a1 Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Thu, 28 Dec 2023 14:01:43 -0500 Subject: [PATCH 17/21] Round on home zoom click as well --- jdaviz/configs/default/plugins/plot_options/plot_options.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.py b/jdaviz/configs/default/plugins/plot_options/plot_options.py index a6b35b2903..6afce2a477 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.py +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.py @@ -742,7 +742,8 @@ def apply_RGB_presets(self): def vue_apply_RGB_presets(self, data): self.apply_RGB_presets() - @observe('viewer_selected') + @observe('viewer_selected', 'viewer_x_max_value', 'viewer_x_min_value', + 'viewer_y_max_value', 'viewer_y_min_value') def _update_viewer_bound_steps(self, msg={}): if not hasattr(self, 'viewer'): # pragma: no cover # plugin hasn't been fully initialized yet From de39bc1fba75d7af217fee28af62926ca3640d0b Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Thu, 28 Dec 2023 16:28:13 -0500 Subject: [PATCH 18/21] Fix empty field handling --- .../plugins/plot_options/plot_options.py | 22 +++++++++----- .../plugins/plot_options/plot_options.vue | 30 +++++++++++-------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.py b/jdaviz/configs/default/plugins/plot_options/plot_options.py index 6afce2a477..6017711b91 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.py +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.py @@ -742,8 +742,7 @@ def apply_RGB_presets(self): def vue_apply_RGB_presets(self, data): self.apply_RGB_presets() - @observe('viewer_selected', 'viewer_x_max_value', 'viewer_x_min_value', - 'viewer_y_max_value', 'viewer_y_min_value') + @observe('viewer_selected','viewer_x_max_value', 'viewer_x_min_value', 'viewer_y_max_value', 'viewer_y_min_value') def _update_viewer_bound_steps(self, msg={}): if not hasattr(self, 'viewer'): # pragma: no cover # plugin hasn't been fully initialized yet @@ -757,18 +756,25 @@ def _update_viewer_bound_steps(self, msg={}): if not isinstance(viewer.state, ImageViewerState): # We round these values to show, e.g., 7.15 instead of 7.1499999 if hasattr(viewer.state, "x_max") and viewer.state.x_max is not None: - stretch_step = (viewer.state.x_max) / 100. - decimals = -int(np.log10(stretch_step))+1 - self.viewer_x_bound_step = np.round(stretch_step, decimals=decimals) + bound_step = (viewer.state.x_max) / 100. + decimals = -int(np.log10(bound_step))+1 + self.viewer_x_bound_step = np.round(bound_step, decimals=decimals) self.viewer_x_max_value = np.round(self.viewer_x_max_value, decimals=decimals) self.viewer_x_min_value = np.round(self.viewer_x_min_value, decimals=decimals) if hasattr(viewer.state, "y_max") and viewer.state.y_max is not None: - stretch_step = (viewer.state.y_max) / 100. - decimals=-int(np.log10(stretch_step))+1 - self.viewer_y_bound_step = np.round(stretch_step, decimals=decimals) + bound_step = (viewer.state.y_max) / 100. + decimals=-int(np.log10(bound_step))+1 + self.viewer_y_bound_step = np.round(bound_step, decimals=decimals) self.viewer_y_max_value = np.round(self.viewer_y_max_value, decimals=decimals) self.viewer_y_min_value = np.round(self.viewer_y_min_value, decimals=decimals) + def vue_reset_viewer_bounds(self, _): + # This button is currently only exposed if only the spectrum viewer is selected + viewer = self.app.get_viewer('spectrum-viewer') + # Have to put something in each field or they won't update properly on home click + + viewer.toolbar.tools['jdaviz:homezoom'].activate() + @observe('stretch_function_sync', 'stretch_params_sync', 'stretch_vmin_sync', 'stretch_vmax_sync', 'image_color_mode_sync', 'image_color_sync', 'image_colormap_sync') diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.vue b/jdaviz/configs/default/plugins/plot_options/plot_options.vue index 9fc4895c9a..7aa86271de 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.vue +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.vue @@ -47,45 +47,51 @@ - + /> - + /> - + /> - + /> + + Reset viewer bounds + From e95c620710dad8f6ec84426ad0bf1d65c98daad9 Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Thu, 28 Dec 2023 16:35:13 -0500 Subject: [PATCH 19/21] Change to diff based steps --- .../default/plugins/plot_options/plot_options.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.py b/jdaviz/configs/default/plugins/plot_options/plot_options.py index 6017711b91..5e9f669846 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.py +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.py @@ -742,7 +742,8 @@ def apply_RGB_presets(self): def vue_apply_RGB_presets(self, data): self.apply_RGB_presets() - @observe('viewer_selected','viewer_x_max_value', 'viewer_x_min_value', 'viewer_y_max_value', 'viewer_y_min_value') + @observe('viewer_selected', 'viewer_x_max_value', 'viewer_x_min_value', + 'viewer_y_max_value', 'viewer_y_min_value') def _update_viewer_bound_steps(self, msg={}): if not hasattr(self, 'viewer'): # pragma: no cover # plugin hasn't been fully initialized yet @@ -756,14 +757,14 @@ def _update_viewer_bound_steps(self, msg={}): if not isinstance(viewer.state, ImageViewerState): # We round these values to show, e.g., 7.15 instead of 7.1499999 if hasattr(viewer.state, "x_max") and viewer.state.x_max is not None: - bound_step = (viewer.state.x_max) / 100. - decimals = -int(np.log10(bound_step))+1 + bound_step = (viewer.state.x_max - viewer.state.x_min) / 100. + decimals = -int(np.log10(bound_step)) + 1 self.viewer_x_bound_step = np.round(bound_step, decimals=decimals) self.viewer_x_max_value = np.round(self.viewer_x_max_value, decimals=decimals) self.viewer_x_min_value = np.round(self.viewer_x_min_value, decimals=decimals) if hasattr(viewer.state, "y_max") and viewer.state.y_max is not None: - bound_step = (viewer.state.y_max) / 100. - decimals=-int(np.log10(bound_step))+1 + bound_step = (viewer.state.y_max - viewer.state.y_min) / 100. + decimals = -int(np.log10(bound_step)) + 1 self.viewer_y_bound_step = np.round(bound_step, decimals=decimals) self.viewer_y_max_value = np.round(self.viewer_y_max_value, decimals=decimals) self.viewer_y_min_value = np.round(self.viewer_y_min_value, decimals=decimals) From edc1e88e5a1533b90fd8d24f31b1e3d89bd1d193 Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Fri, 29 Dec 2023 16:01:24 -0500 Subject: [PATCH 20/21] Handle negative bounds diff and 0 diff --- jdaviz/configs/default/plugins/plot_options/plot_options.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.py b/jdaviz/configs/default/plugins/plot_options/plot_options.py index 5e9f669846..582424a365 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.py +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.py @@ -758,13 +758,13 @@ def _update_viewer_bound_steps(self, msg={}): # We round these values to show, e.g., 7.15 instead of 7.1499999 if hasattr(viewer.state, "x_max") and viewer.state.x_max is not None: bound_step = (viewer.state.x_max - viewer.state.x_min) / 100. - decimals = -int(np.log10(bound_step)) + 1 + decimals = -int(np.log10(abs(bound_step))) + 1 if bound_step != 0 else 6 self.viewer_x_bound_step = np.round(bound_step, decimals=decimals) self.viewer_x_max_value = np.round(self.viewer_x_max_value, decimals=decimals) self.viewer_x_min_value = np.round(self.viewer_x_min_value, decimals=decimals) if hasattr(viewer.state, "y_max") and viewer.state.y_max is not None: bound_step = (viewer.state.y_max - viewer.state.y_min) / 100. - decimals = -int(np.log10(bound_step)) + 1 + decimals = -int(np.log10(abs(bound_step))) + 1 if bound_step != 0 else 6 self.viewer_y_bound_step = np.round(bound_step, decimals=decimals) self.viewer_y_max_value = np.round(self.viewer_y_max_value, decimals=decimals) self.viewer_y_min_value = np.round(self.viewer_y_min_value, decimals=decimals) From b31e26819da38f3bce84af5f3600c663acb6c3fc Mon Sep 17 00:00:00 2001 From: Ricky O'Steen Date: Tue, 2 Jan 2024 16:00:21 -0500 Subject: [PATCH 21/21] Handle non-spectrum non-image viewers, fix decimal rounding for large numbers --- .../plugins/plot_options/plot_options.py | 21 +++++++++++++++---- .../plugins/plot_options/plot_options.vue | 2 +- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.py b/jdaviz/configs/default/plugins/plot_options/plot_options.py index 582424a365..7855565200 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.py +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.py @@ -352,6 +352,7 @@ class PlotOptions(PluginTemplateMixin): icon_checktoradial = Unicode(read_icon(os.path.join(ICON_DIR, 'checktoradial.svg'), 'svg+xml')).tag(sync=True) # noqa show_viewer_labels = Bool(True).tag(sync=True) + show_viewer_bounds = Bool(True).tag(sync=True) cmap_samples = Dict().tag(sync=True) swatches_palette = List().tag(sync=True) @@ -753,28 +754,40 @@ def _update_viewer_bound_steps(self, msg={}): # nothing selected yet return + if self.viewer_multiselect: + not_image = [not isinstance(v.state, ImageViewerState) for v in self.viewer.selected_obj] # noqa + if np.all(not_image): + self.show_viewer_bounds = True + else: + self.show_viewer_bounds = False + return + viewer = self.viewer.selected_obj[0] if self.viewer_multiselect else self.viewer.selected_obj # noqa if not isinstance(viewer.state, ImageViewerState): + self.show_viewer_bounds = True # We round these values to show, e.g., 7.15 instead of 7.1499999 if hasattr(viewer.state, "x_max") and viewer.state.x_max is not None: bound_step = (viewer.state.x_max - viewer.state.x_min) / 100. decimals = -int(np.log10(abs(bound_step))) + 1 if bound_step != 0 else 6 + if decimals < 0: + decimals = 0 self.viewer_x_bound_step = np.round(bound_step, decimals=decimals) self.viewer_x_max_value = np.round(self.viewer_x_max_value, decimals=decimals) self.viewer_x_min_value = np.round(self.viewer_x_min_value, decimals=decimals) if hasattr(viewer.state, "y_max") and viewer.state.y_max is not None: bound_step = (viewer.state.y_max - viewer.state.y_min) / 100. decimals = -int(np.log10(abs(bound_step))) + 1 if bound_step != 0 else 6 + if decimals < 0: + decimals = 0 self.viewer_y_bound_step = np.round(bound_step, decimals=decimals) self.viewer_y_max_value = np.round(self.viewer_y_max_value, decimals=decimals) self.viewer_y_min_value = np.round(self.viewer_y_min_value, decimals=decimals) def vue_reset_viewer_bounds(self, _): # This button is currently only exposed if only the spectrum viewer is selected - viewer = self.app.get_viewer('spectrum-viewer') - # Have to put something in each field or they won't update properly on home click - - viewer.toolbar.tools['jdaviz:homezoom'].activate() + viewers = [self.viewer.selected_obj] if not self.viewer_multiselect else self.viewer.selected_obj # noqa + for viewer in viewers: + viewer.toolbar.tools['jdaviz:homezoom'].activate() @observe('stretch_function_sync', 'stretch_params_sync', 'stretch_vmin_sync', 'stretch_vmax_sync', diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.vue b/jdaviz/configs/default/plugins/plot_options/plot_options.vue index 7aa86271de..4c84405fdc 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.vue +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.vue @@ -39,7 +39,7 @@ :hint="viewer_multiselect ? 'Select viewers to set options simultaneously' : 'Select the viewer to set options.'" /> - +