From ba7a5b291c9bd40a43c10231b62b1eeda2ea0f31 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Tue, 1 Oct 2024 13:02:28 -0400 Subject: [PATCH] WIP: update to use upstream generalization https://github.com/spacetelescope/jdaviz/pull/3166 --- .../unit_conversion/unit_conversion.py | 80 ++++++++++++++++--- lcviz/state.py | 1 + lcviz/viewers.py | 2 +- 3 files changed, 73 insertions(+), 10 deletions(-) diff --git a/lcviz/plugins/unit_conversion/unit_conversion.py b/lcviz/plugins/unit_conversion/unit_conversion.py index 9af821a..a59f33e 100644 --- a/lcviz/plugins/unit_conversion/unit_conversion.py +++ b/lcviz/plugins/unit_conversion/unit_conversion.py @@ -4,6 +4,8 @@ from jdaviz.configs.specviz.plugins import UnitConversion from jdaviz.core.registries import tray_registry +from lcviz.viewers import (CubeView, TimeScatterView) + __all__ = ['UnitConversion'] @@ -30,9 +32,8 @@ def __init__(self, *args, **kwargs): self.docs_description = "Choose units for the time and flux axes." self.disabled_msg = "" # otherwise disabled upstream - remove once upstream no longer has a config check - self.time_unit = UnitSelectPluginComponent(self, - items='time_unit_items', - selected='time_unit_selected') + self.has_time = True + self.has_flux = True @property def spectrum_viewer(self): @@ -44,10 +45,71 @@ def spectrum_viewer(self): return self.app.get_viewer(viewer_reference) - @property - def user_api(self): - api = super().user_api - expose = ['time_unit', 'flux_unit'] - api._expose = expose + def _on_add_data_to_viewer(self, msg): + viewer = msg.viewer + + if (not len(self.time_unit_selected) or not len(self.flux_unit_selected)): + # TODO: default based on the native units of the data (LC or TPF) + self.time_unit.choices = ['d', 'hr', 'min', 's'] + self.time_unit_selected = 'd' + self.flux_unit.choices = ['erg / (Angstrom cm2 s)'] + self.flux_unit_selected = 'erg / (Angstrom cm2 s)' + # setting default values will trigger the observes to set the units + # in _on_unit_selected, so return here to avoid setting twice + return + + # TODO: when enabling unit-conversion in rampviz, this may need to be more specific + # or handle other cases for ramp profile viewers + if isinstance(viewer, TimeScatterView): + if (viewer.state.x_display_unit == self.time_unit_selected + and viewer.state.y_display_unit == self.flux_unit_selected): + # data already existed in this viewer and display units were already set + return + + # this spectral viewer was empty (did not have display units set yet),˜ + # but global selections are available in the plugin, + # so we'll set them to the viewer here + viewer.state.x_display_unit = self.time_unit_selected + viewer.state.y_display_unit = self.flux_unit_selected + + elif isinstance(viewer, CubeView): + # set the attribute display unit (contour and stretch units) for the new layer + # NOTE: this assumes that all image data is coerced to surface brightness units + layers = [lyr for lyr in msg.viewer.layers if lyr.layer.data.label == msg.data.label] + self._handle_attribute_display_unit(self.flux_unit_selected, layers=layers) + self._clear_cache('image_layers') + + def _on_unit_selected(self, msg): + """ + When any user selection is made, update the relevant viewer(s) with the new unit, + and then emit a GlobalDisplayUnitChanged message to notify other plugins of the change. + """ + if not len(msg.get('new', '')): + # empty string, nothing to set yet + return + + axis = msg.get('name').split('_')[0] + + if axis == 'time': + xunit = _valid_glue_display_unit(self.spectral_unit.selected, self.spectrum_viewer, 'x') + self.spectrum_viewer.state.x_display_unit = xunit + self.spectrum_viewer.set_plot_axes() + + elif axis == 'flux': + # handle spectral y-unit first since that is a more apparent change to the user + # and feels laggy if it is done later + if self.spectral_y_type_selected == 'Flux': + self._handle_spectral_y_unit() + + if len(self.angle_unit_selected): + # NOTE: setting sb_unit_selected will call this method again with axis=='sb', + # which in turn will call _handle_attribute_display_unit, + # _handle_spectral_y_unit (if spectral_y_type_selected == 'Surface Brightness'), + # and send a second GlobalDisplayUnitChanged message for sb + self.sb_unit_selected = _flux_to_sb_unit(self.flux_unit.selected, + self.angle_unit.selected) + - return api + # axis (first) argument will be one of: time, flux + self.hub.broadcast(GlobalDisplayUnitChanged(axis, + msg.new, sender=self)) diff --git a/lcviz/state.py b/lcviz/state.py index fbab96c..4d6adcd 100644 --- a/lcviz/state.py +++ b/lcviz/state.py @@ -35,6 +35,7 @@ def _reset_y_limits(self, *event): self._reset_att_limits('y') def reset_limits(self, *event): + # TODO: this is not working correctly when units are changed (probably the same for _reset_att_limits) x_min, x_max = np.inf, -np.inf y_min, y_max = np.inf, -np.inf diff --git a/lcviz/viewers.py b/lcviz/viewers.py index 33e2c7c..1c0321e 100644 --- a/lcviz/viewers.py +++ b/lcviz/viewers.py @@ -164,7 +164,7 @@ def set_plot_axes(self): def _set_plot_x_axes(self, dc, component_labels, light_curve): self.state.x_att = dc[0].components[component_labels.index('dt')] - x_unit = self.time_unit + x_unit = self.time_unit # TODO: use get display unit instead? Or at least update self.time_unit reference_time = light_curve.meta.get('reference_time', None) if reference_time is not None: