From a126296bbad6bb272f5410379615e4babd709b22 Mon Sep 17 00:00:00 2001 From: Hatice Karatay <66814693+haticekaratay@users.noreply.github.com> Date: Tue, 30 Jul 2024 15:08:09 -0400 Subject: [PATCH] Update the mouse over units by listening to the unit-conversion plugin (#2931) * Respond to changed unit and display on the UI * Convert all sb<>sb units listed in the dropdown menu * Use the default current unit from the cube * Apply only for relevant configs * Update current_unit setting logic * Fix failing tests * Add tests * Add a changelog * Move conversion logic to utils * Move the conversion to utils * Pass when unable to convert * Update tests * Update based on the feedback * Only subscribe to cubeviz * Check for equivalency rather than image dimension * Refactor conversion logic Co-authored-by: P. L. Lim <2090236+pllim@users.noreply.github.com> * Rename unit and broadcast 'sb' as part of msg * Code style --------- Co-authored-by: P. L. Lim <2090236+pllim@users.noreply.github.com> --- CHANGES.rst | 2 ++ .../imviz/plugins/coords_info/coords_info.py | 26 +++++++++++++++--- .../tests/test_unit_conversion.py | 27 +++++++++++++++++++ .../unit_conversion/unit_conversion.py | 8 +++--- jdaviz/utils.py | 5 ++++ 5 files changed, 61 insertions(+), 7 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 438bfd0c1b..da8f87b455 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -107,6 +107,8 @@ Cubeviz - Flux units are now correct for collapsed spectra when using the sum function when units are in per steradian. [#2873] +- Mouse over coordinates now responds to the selected surface brightness unit. [#2931] + Imviz ^^^^^ diff --git a/jdaviz/configs/imviz/plugins/coords_info/coords_info.py b/jdaviz/configs/imviz/plugins/coords_info/coords_info.py index 326c80f5ce..26b8b75b91 100644 --- a/jdaviz/configs/imviz/plugins/coords_info/coords_info.py +++ b/jdaviz/configs/imviz/plugins/coords_info/coords_info.py @@ -12,12 +12,12 @@ from jdaviz.configs.mosviz.plugins.viewers import (MosvizImageView, MosvizProfileView, MosvizProfile2DView) from jdaviz.configs.specviz.plugins.viewers import SpecvizProfileView -from jdaviz.core.events import ViewerAddedMessage +from jdaviz.core.events import ViewerAddedMessage, GlobalDisplayUnitChanged from jdaviz.core.helpers import data_has_valid_wcs from jdaviz.core.marks import PluginScatter, PluginLine from jdaviz.core.registries import tool_registry from jdaviz.core.template_mixin import TemplateMixin, DatasetSelectMixin -from jdaviz.utils import _eqv_pixar_sr +from jdaviz.utils import _eqv_pixar_sr, _convert_surface_brightness_units __all__ = ['CoordsInfo'] @@ -34,7 +34,9 @@ class CoordsInfo(TemplateMixin, DatasetSelectMixin): _viewer_classes_with_marker = (SpecvizProfileView, MosvizProfile2DView) - dataset_icon = Unicode("").tag(sync=True) # option for layer (auto, none, or specific layer) + dataset_icon = Unicode("").tag( + sync=True + ) # option for layer (auto, none, or specific layer) icon = Unicode("").tag(sync=True) # currently exposed layer row1a_title = Unicode("").tag(sync=True) @@ -56,6 +58,7 @@ def __init__(self, *args, **kwargs): self._marks = {} self._dict = {} # dictionary representation of current mouseover info self._x, self._y = None, None # latest known cursor positions + self.image_unit = None # subscribe/unsubscribe to mouse events across all existing viewers viewer_refs = [] @@ -73,6 +76,10 @@ def __init__(self, *args, **kwargs): # subscribe to mouse events on any new viewers self.hub.subscribe(self, ViewerAddedMessage, handler=self._on_viewer_added) + if self.config == "cubeviz": + self.hub.subscribe( + self, GlobalDisplayUnitChanged, handler=self._on_global_display_unit_changed + ) def _create_marks_for_viewer(self, viewer, id=None): if id is None: @@ -112,6 +119,10 @@ def _create_viewer_callbacks(self, viewer): def _on_viewer_added(self, msg): self._create_viewer_callbacks(self.app.get_viewer_by_id(msg.viewer_id)) + def _on_global_display_unit_changed(self, msg): + if msg.axis == "sb": + self.image_unit = u.Unit(msg.unit) + @property def marks(self): """ @@ -458,7 +469,14 @@ def _image_viewer_update(self, viewer, x, y): elif isinstance(viewer, CubevizImageView): arr = image.get_component(attribute).data unit = image.get_component(attribute).units - value = self._get_cube_value(image, arr, x, y, viewer) + value = self._get_cube_value( + image, arr, x, y, viewer + ) + if self.image_unit is not None and self.image_unit.is_equivalent(unit): + value = _convert_surface_brightness_units( + value, unit, self.image_unit + ) + unit = self.image_unit if associated_dq_layers is not None: associated_dq_layer = associated_dq_layers[0] diff --git a/jdaviz/configs/specviz/plugins/unit_conversion/tests/test_unit_conversion.py b/jdaviz/configs/specviz/plugins/unit_conversion/tests/test_unit_conversion.py index 624d69ea2c..6ab2bd439d 100644 --- a/jdaviz/configs/specviz/plugins/unit_conversion/tests/test_unit_conversion.py +++ b/jdaviz/configs/specviz/plugins/unit_conversion/tests/test_unit_conversion.py @@ -201,17 +201,44 @@ def test_sb_unit_conversion(cubeviz_helper): uc_plg.sb_unit = 'Jy / sr' y_display_unit = u.Unit(viewer_1d.state.y_display_unit) assert y_display_unit == u.Jy / u.sr + label_mouseover = cubeviz_helper.app.session.application._tools["g-coords-info"] + flux_viewer = cubeviz_helper.app.get_viewer( + cubeviz_helper._default_flux_viewer_reference_name + ) + label_mouseover._viewer_mouse_event( + flux_viewer, {"event": "mousemove", "domain": {"x": 10, "y": 8}} + ) + assert label_mouseover.as_text() == ( + "Pixel x=00010.0 y=00008.0 Value +1.00000e+06 Jy / sr", + "World 13h39m59.7037s +27d00m03.2400s (ICRS)", + "204.9987654313 27.0008999946 (deg)") # Try a second conversion uc_plg.sb_unit = 'W / Hz sr m2' y_display_unit = u.Unit(viewer_1d.state.y_display_unit) assert y_display_unit == u.Unit("W / (Hz sr m2)") + y_display_unit = u.Unit(viewer_1d.state.y_display_unit) + label_mouseover._viewer_mouse_event( + flux_viewer, {"event": "mousemove", "domain": {"x": 10, "y": 8}} + ) + assert label_mouseover.as_text() == ( + "Pixel x=00010.0 y=00008.0 Value +1.00000e-20 W / (Hz sr m2)", + "World 13h39m59.7037s +27d00m03.2400s (ICRS)", + "204.9987654313 27.0008999946 (deg)") + # really a translation test, test_unit_translation loads a Flux # cube, this test load a Surface Brightness Cube, this ensures # two-way translation uc_plg.sb_unit = 'MJy / sr' y_display_unit = u.Unit(viewer_1d.state.y_display_unit) + label_mouseover._viewer_mouse_event( + flux_viewer, {"event": "mousemove", "domain": {"x": 10, "y": 8}} + ) + assert label_mouseover.as_text() == ( + "Pixel x=00010.0 y=00008.0 Value +1.00000e+00 MJy / sr", + "World 13h39m59.7037s +27d00m03.2400s (ICRS)", + "204.9987654313 27.0008999946 (deg)") uc_plg._obj.flux_or_sb_selected = 'Flux' uc_plg.flux_unit = 'MJy' diff --git a/jdaviz/configs/specviz/plugins/unit_conversion/unit_conversion.py b/jdaviz/configs/specviz/plugins/unit_conversion/unit_conversion.py index 39655cdf20..4bacd38f92 100644 --- a/jdaviz/configs/specviz/plugins/unit_conversion/unit_conversion.py +++ b/jdaviz/configs/specviz/plugins/unit_conversion/unit_conversion.py @@ -279,9 +279,11 @@ def _on_flux_unit_changed(self, msg): if self.spectrum_viewer.state.y_display_unit != yunit: self.spectrum_viewer.state.y_display_unit = yunit - self.hub.broadcast(GlobalDisplayUnitChanged('flux', - flux_or_sb, - sender=self)) + self.hub.broadcast( + GlobalDisplayUnitChanged( + "flux" if name == "flux_unit_selected" else "sb", flux_or_sb, sender=self + ) + ) self.spectrum_viewer.reset_limits() if ( diff --git a/jdaviz/utils.py b/jdaviz/utils.py index e381aea407..a9d0d517f6 100644 --- a/jdaviz/utils.py +++ b/jdaviz/utils.py @@ -357,6 +357,11 @@ def flux_conversion(spec, values, original_units, target_units): return (values * orig_units).to_value(targ_units, equivalencies=eqv) +def _convert_surface_brightness_units(data, from_unit, to_unit): + quantity = data * u.Unit(from_unit) + return quantity.to_value(u.Unit(to_unit)) + + def _eqv_pixar_sr(pixar_sr): def converter_flux(x): # Surface Brightness -> Flux return x * pixar_sr