From 6a86f6cc8321bdfac3bd45696842cf537e5c6b87 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Mon, 3 Apr 2023 15:31:19 -0400 Subject: [PATCH 1/4] update markers plugin for display units --- .../default/plugins/markers/markers.py | 21 +++++++++++++++++-- jdaviz/core/marks.py | 15 +++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/jdaviz/configs/default/plugins/markers/markers.py b/jdaviz/configs/default/plugins/markers/markers.py index ed06f00910..c8e69b8208 100644 --- a/jdaviz/configs/default/plugins/markers/markers.py +++ b/jdaviz/configs/default/plugins/markers/markers.py @@ -1,7 +1,9 @@ import numpy as np from traitlets import observe -from jdaviz.core.events import ViewerAddedMessage +from jdaviz.configs.mosviz.plugins.viewers import MosvizProfile2DView +from jdaviz.configs.specviz.plugins.viewers import SpecvizProfileView +from jdaviz.core.events import ViewerAddedMessage, GlobalDisplayUnitChanged from jdaviz.core.marks import MarkersMark from jdaviz.core.registries import tray_registry from jdaviz.core.template_mixin import PluginTemplateMixin, ViewerSelectMixin, TableMixin @@ -76,6 +78,8 @@ def __init__(self, *args, **kwargs): # subscribe to mouse events on any new viewers self.hub.subscribe(self, ViewerAddedMessage, handler=self._on_viewer_added) + self.hub.subscribe(self, GlobalDisplayUnitChanged, + handler=self._on_global_display_unit_changed) def _create_viewer_callbacks(self, viewer): if not self.plugin_opened: @@ -122,6 +126,20 @@ def _on_plugin_opened_changed(self, *args): else: viewer.remove_event_callback(callback) + def _on_global_display_unit_changed(self, msg): + for viewer_id, mark in self.marks.items(): + viewer = self.app.get_viewer_by_id(viewer_id) + if isinstance(viewer, SpecvizProfileView): + axis_map = {'spectral': 'x', 'flux': 'y'} + elif isinstance(viewer, + (MosvizProfile2DView)): + axis_map = {'spectral': 'x'} + else: + return + axis = axis_map.get(msg.axis, None) + if axis is not None: + getattr(mark, f'set_{axis}_unit')(msg.unit) + def _on_viewer_key_event(self, viewer, data): if data['event'] == 'keydown' and data['key'] == 'm': row_info = self.app.session.application._tools['g-coords-info'].as_dict() @@ -139,7 +157,6 @@ def _on_viewer_key_event(self, viewer, data): raise ValueError(f'failed to add {row_info} to table: {repr(err)}') x, y = row_info['axes_x'], row_info['axes_y'] - # TODO: will need to test/update when adding support for display units self._get_mark(viewer).append_xy(getattr(x, 'value', x), getattr(y, 'value', y)) def clear_table(self): diff --git a/jdaviz/core/marks.py b/jdaviz/core/marks.py index 7c2cc5a223..6b9809c93c 100644 --- a/jdaviz/core/marks.py +++ b/jdaviz/core/marks.py @@ -485,6 +485,9 @@ def _on_shadowing_changed(self, change): class PluginMark(): + xunit = None + yunit = None + def update_xy(self, x, y): self.x = np.asarray(x) self.y = np.asarray(y) @@ -493,6 +496,18 @@ def append_xy(self, x, y): self.x = np.append(self.x, x) self.y = np.append(self.y, y) + def set_x_unit(self, unit): + unit = u.Unit(unit) + if self.xunit is not None: + self.x = (self.x * self.xunit).to_value(unit, u.spectral()) + self.xunit = unit + + def set_y_unit(self, unit): + unit = u.Unit(unit) + if self.yunit is not None: + self.y = (self.y * self.yunit).to_value(unit) + self.yunit = unit + def clear(self): self.update_xy([], []) From 7bd825c2d2b9883e14d34eed60a7ebd68578a863 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Tue, 4 Apr 2023 09:42:34 -0400 Subject: [PATCH 2/4] move unit-updating logic to mark itself --- .../default/plugins/markers/markers.py | 20 +------ jdaviz/configs/default/plugins/viewers.py | 4 ++ jdaviz/core/marks.py | 57 +++++++++++++++++-- 3 files changed, 56 insertions(+), 25 deletions(-) diff --git a/jdaviz/configs/default/plugins/markers/markers.py b/jdaviz/configs/default/plugins/markers/markers.py index c8e69b8208..754eee5d8c 100644 --- a/jdaviz/configs/default/plugins/markers/markers.py +++ b/jdaviz/configs/default/plugins/markers/markers.py @@ -1,9 +1,7 @@ import numpy as np from traitlets import observe -from jdaviz.configs.mosviz.plugins.viewers import MosvizProfile2DView -from jdaviz.configs.specviz.plugins.viewers import SpecvizProfileView -from jdaviz.core.events import ViewerAddedMessage, GlobalDisplayUnitChanged +from jdaviz.core.events import ViewerAddedMessage from jdaviz.core.marks import MarkersMark from jdaviz.core.registries import tray_registry from jdaviz.core.template_mixin import PluginTemplateMixin, ViewerSelectMixin, TableMixin @@ -78,8 +76,6 @@ def __init__(self, *args, **kwargs): # subscribe to mouse events on any new viewers self.hub.subscribe(self, ViewerAddedMessage, handler=self._on_viewer_added) - self.hub.subscribe(self, GlobalDisplayUnitChanged, - handler=self._on_global_display_unit_changed) def _create_viewer_callbacks(self, viewer): if not self.plugin_opened: @@ -126,20 +122,6 @@ def _on_plugin_opened_changed(self, *args): else: viewer.remove_event_callback(callback) - def _on_global_display_unit_changed(self, msg): - for viewer_id, mark in self.marks.items(): - viewer = self.app.get_viewer_by_id(viewer_id) - if isinstance(viewer, SpecvizProfileView): - axis_map = {'spectral': 'x', 'flux': 'y'} - elif isinstance(viewer, - (MosvizProfile2DView)): - axis_map = {'spectral': 'x'} - else: - return - axis = axis_map.get(msg.axis, None) - if axis is not None: - getattr(mark, f'set_{axis}_unit')(msg.unit) - def _on_viewer_key_event(self, viewer, data): if data['event'] == 'keydown' and data['key'] == 'm': row_info = self.app.session.application._tools['g-coords-info'].as_dict() diff --git a/jdaviz/configs/default/plugins/viewers.py b/jdaviz/configs/default/plugins/viewers.py index 7023f19671..70f33aa657 100644 --- a/jdaviz/configs/default/plugins/viewers.py +++ b/jdaviz/configs/default/plugins/viewers.py @@ -216,6 +216,10 @@ def jdaviz_helper(self): """The Jdaviz configuration helper tied to the viewer.""" return self.jdaviz_app._jdaviz_helper + @property + def hub(self): + return self.session.hub + @property def reference_id(self): return self._reference_id diff --git a/jdaviz/core/marks.py b/jdaviz/core/marks.py index 6b9809c93c..b8885fff77 100644 --- a/jdaviz/core/marks.py +++ b/jdaviz/core/marks.py @@ -7,6 +7,7 @@ from glue.core import HubListener from specutils import Spectrum1D +from jdaviz.core.events import GlobalDisplayUnitChanged from jdaviz.core.events import (SliceToolStateMessage, LineIdentifyMessage, SpectralMarksChangedMessage, RedshiftMessage) @@ -485,8 +486,19 @@ def _on_shadowing_changed(self, change): class PluginMark(): - xunit = None - yunit = None + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.xunit = None + self.yunit = None + # whether to update existing marks when global display units are changed + self.auto_update_units = True + self.hub.subscribe(self, GlobalDisplayUnitChanged, + handler=self._on_global_display_unit_changed) + self._update_units() + + @property + def hub(self): + return self.viewer.hub def update_xy(self, x, y): self.x = np.asarray(x) @@ -496,36 +508,69 @@ def append_xy(self, x, y): self.x = np.append(self.x, x) self.y = np.append(self.y, y) - def set_x_unit(self, unit): + def _update_units(self): + if not self.auto_update_units: + return + if self.xunit is None: + self.set_x_unit() + if self.yunit is None: + self.set_y_unit() + + def set_x_unit(self, unit=None): + if unit is None: + unit = self.viewer.state.x_display_unit unit = u.Unit(unit) if self.xunit is not None: - self.x = (self.x * self.xunit).to_value(unit, u.spectral()) + x = (self.x * self.xunit).to_value(unit, u.spectral()) + self.xunit = unit + self.x = x self.xunit = unit - def set_y_unit(self, unit): + def set_y_unit(self, unit=None): + if unit is None: + unit = self.viewer.state.y_display_unit unit = u.Unit(unit) if self.yunit is not None: self.y = (self.y * self.yunit).to_value(unit) self.yunit = unit + def _on_global_display_unit_changed(self, msg): + if not self.auto_update_units: + return + if self.viewer.__class__.__name__ == 'SpecvizProfileView': + axis_map = {'spectral': 'x', 'flux': 'y'} + elif self.viewer.__class__.__name__ == 'MosvizProfile2DView': + axis_map = {'spectral': 'x'} + else: + return + axis = axis_map.get(msg.axis, None) + if axis is not None: + getattr(self, f'set_{axis}_unit')(msg.unit) + def clear(self): self.update_xy([], []) class PluginLine(Lines, PluginMark, HubListener): def __init__(self, viewer, x=[], y=[], **kwargs): + self.viewer = viewer # color is same blue as import button super().__init__(x=x, y=y, colors=["#007BA1"], scales=viewer.scales, **kwargs) class PluginScatter(Scatter, PluginMark, HubListener): def __init__(self, viewer, x=[], y=[], **kwargs): + self.viewer = viewer # color is same blue as import button super().__init__(x=x, y=y, colors=["#007BA1"], scales=viewer.scales, **kwargs) class LineAnalysisContinuum(PluginLine): - pass + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + # units do not need to be updated because the plugin itself reruns + # the computation and automatically changes the arrays themselves + self.auto_update_units = False class LineAnalysisContinuumCenter(LineAnalysisContinuum): From 3e3e7786e80bf81b3942f73f22227864acc79de9 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Tue, 4 Apr 2023 13:13:18 -0400 Subject: [PATCH 3/4] LineUncertainties to be unit-aware --- jdaviz/core/marks.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/jdaviz/core/marks.py b/jdaviz/core/marks.py index b8885fff77..0bcf4a5270 100644 --- a/jdaviz/core/marks.py +++ b/jdaviz/core/marks.py @@ -551,6 +551,12 @@ def clear(self): self.update_xy([], []) +class LinesAutoUnit(PluginMark, Lines, HubListener): + def __init__(self, viewer, *args, **kwargs): + self.viewer = viewer + super().__init__(*args, **kwargs) + + class PluginLine(Lines, PluginMark, HubListener): def __init__(self, viewer, x=[], y=[], **kwargs): self.viewer = viewer @@ -589,9 +595,9 @@ class LineAnalysisContinuumRight(LineAnalysisContinuumLeft): pass -class LineUncertainties(Lines): - def __init__(self, **kwargs): - super().__init__(**kwargs) +class LineUncertainties(LinesAutoUnit): + def __init__(self, viewer, *args, **kwargs): + super().__init__(viewer, *args, **kwargs) class ScatterMask(Scatter): From 1123061bc54dcd9331b530c87b96d228beef210c Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Tue, 11 Apr 2023 09:00:38 -0400 Subject: [PATCH 4/4] fix support for markers in cubeviz --- jdaviz/core/marks.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/jdaviz/core/marks.py b/jdaviz/core/marks.py index 0bcf4a5270..08ffba76b9 100644 --- a/jdaviz/core/marks.py +++ b/jdaviz/core/marks.py @@ -518,6 +518,8 @@ def _update_units(self): def set_x_unit(self, unit=None): if unit is None: + if not hasattr(self.viewer.state, 'x_display_unit'): + return unit = self.viewer.state.x_display_unit unit = u.Unit(unit) if self.xunit is not None: @@ -528,6 +530,8 @@ def set_x_unit(self, unit=None): def set_y_unit(self, unit=None): if unit is None: + if not hasattr(self.viewer.state, 'y_display_unit'): + return unit = self.viewer.state.y_display_unit unit = u.Unit(unit) if self.yunit is not None: @@ -537,7 +541,7 @@ def set_y_unit(self, unit=None): def _on_global_display_unit_changed(self, msg): if not self.auto_update_units: return - if self.viewer.__class__.__name__ == 'SpecvizProfileView': + if self.viewer.__class__.__name__ in ['SpecvizProfileView', 'CubevizProfileView']: axis_map = {'spectral': 'x', 'flux': 'y'} elif self.viewer.__class__.__name__ == 'MosvizProfile2DView': axis_map = {'spectral': 'x'}