diff --git a/CHANGES.rst b/CHANGES.rst index fa93ac5f59..03c1db06d5 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -45,6 +45,9 @@ API Changes Cubeviz ^^^^^^^ +- ``spatial_subset`` in the spectral extraction plugin is now renamed to ``aperture`` and will + be removed in a future release. [#2664] + Imviz ^^^^^ diff --git a/docs/dev/ui_style_guide.rst b/docs/dev/ui_style_guide.rst index e970b72da2..f1709b03f5 100644 --- a/docs/dev/ui_style_guide.rst +++ b/docs/dev/ui_style_guide.rst @@ -22,7 +22,7 @@ try to adhere to the following principles: components are necessary in a single row. Always emphasize readability at the default/minimum width of the plugin tray, rather than using columns that result in a ton of text overflow. * Use ```` to align content to the right (such as action buttons). -* Action buttons should use ``text`` +* Action buttons should use ``text`` to control the color depending on whether the button affects things outside the plugin itself (adding/modifying data collection or subset entries, etc) or are isolated to within the plugin (adding model components in model fitting, etc). These buttons can be wrapped in tooltip components diff --git a/jdaviz/configs/cubeviz/plugins/slice/slice.py b/jdaviz/configs/cubeviz/plugins/slice/slice.py index 425afbafa6..1b98e6458c 100644 --- a/jdaviz/configs/cubeviz/plugins/slice/slice.py +++ b/jdaviz/configs/cubeviz/plugins/slice/slice.py @@ -11,7 +11,8 @@ from specutils.spectra.spectrum1d import Spectrum1D from jdaviz.core.events import (AddDataMessage, SliceToolStateMessage, - SliceSelectSliceMessage, GlobalDisplayUnitChanged) + SliceSelectSliceMessage, SliceWavelengthUpdatedMessage, + GlobalDisplayUnitChanged) from jdaviz.core.registries import tray_registry from jdaviz.core.template_mixin import PluginTemplateMixin from jdaviz.core.user_api import PluginUserApi @@ -217,6 +218,10 @@ def _on_slider_updated(self, event): for viewer in self._indicator_viewers: viewer._update_slice_indicator(value) + self.hub.broadcast(SliceWavelengthUpdatedMessage(slice=value, + wavelength=self.wavelength, + sender=self)) + def vue_goto_first(self, *args): if self.is_playing: return diff --git a/jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.py b/jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.py index acaee9a9ed..4cc1424fa9 100644 --- a/jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.py +++ b/jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.py @@ -5,17 +5,19 @@ import numpy as np import astropy import astropy.units as u +from astropy.utils.decorators import deprecated from astropy.nddata import ( NDDataArray, StdDevUncertainty, NDUncertainty ) -from traitlets import Bool, List, Unicode, observe +from traitlets import Bool, Float, List, Unicode, observe -from jdaviz.core.events import SnackbarMessage +from jdaviz.core.custom_traitlets import FloatHandleEmpty +from jdaviz.core.events import SnackbarMessage, SliceWavelengthUpdatedMessage from jdaviz.core.registries import tray_registry from jdaviz.core.template_mixin import (PluginTemplateMixin, DatasetSelectMixin, SelectPluginComponent, - SpatialSubsetSelectMixin, + ApertureSubsetSelectMixin, AddResultsMixin, with_spinner) from jdaviz.core.user_api import PluginUserApi @@ -31,7 +33,7 @@ 'cubeviz-spectral-extraction', label="Spectral Extraction", viewer_requirements='spectrum' ) class SpectralExtraction(PluginTemplateMixin, DatasetSelectMixin, - SpatialSubsetSelectMixin, AddResultsMixin): + ApertureSubsetSelectMixin, AddResultsMixin): """ See the :ref:`Spectral Extraction Plugin Documentation ` for more details. @@ -41,12 +43,20 @@ class SpectralExtraction(PluginTemplateMixin, DatasetSelectMixin, * :meth:`~jdaviz.core.template_mixin.PluginTemplateMixin.show` * :meth:`~jdaviz.core.template_mixin.PluginTemplateMixin.open_in_tray` * :meth:`~jdaviz.core.template_mixin.PluginTemplateMixin.close_in_tray` - * ``spatial_subset`` (:class:`~jdaviz.core.template_mixin.SubsetSelect`): - Subset to use for the spectral extraction, or ``No Subset``. + * ``aperture`` (:class:`~jdaviz.core.template_mixin.SubsetSelect`): + Subset to use for the spectral extraction, or ``Entire Cube``. * ``add_results`` (:class:`~jdaviz.core.template_mixin.AddResults`) * :meth:`collapse` """ template_file = __file__, "spectral_extraction.vue" + uses_active_status = Bool(True).tag(sync=True) + + # feature flag for cone support + dev_cone_support = Bool(False).tag(sync=True) + wavelength_dependent = Bool(False).tag(sync=True) + reference_wavelength = FloatHandleEmpty().tag(sync=True) + slice_wavelength = Float().tag(sync=True) + function_items = List().tag(sync=True) function_selected = Unicode('Sum').tag(sync=True) filename = Unicode().tag(sync=True) @@ -68,6 +78,12 @@ def __init__(self, *args, **kwargs): self.extracted_spec = None + # TODO: in the future this could be generalized with support in SelectPluginComponent + self.aperture._default_text = 'Entire Cube' + self.aperture._manual_options = ['Entire Cube'] + self.aperture.items = [{"label": "Entire Cube"}] + self.aperture.select_default() + self.function = SelectPluginComponent( self, items='function_items', @@ -77,6 +93,9 @@ def __init__(self, *args, **kwargs): self._set_default_results_label() self.add_results.viewer.filters = ['is_spectrum_viewer'] + self.session.hub.subscribe(self, SliceWavelengthUpdatedMessage, + handler=self._on_slice_changed) + if ASTROPY_LT_5_3_2: self.disabled_msg = "Spectral Extraction in Cubeviz requires astropy>=5.3.2" @@ -95,11 +114,46 @@ def user_api(self): return PluginUserApi( self, expose=( - 'function', 'spatial_subset', + 'function', 'spatial_subset', 'aperture', 'add_results', 'collapse_to_spectrum' ) ) + @property + @deprecated(since="3.9", alternative="aperture") + def spatial_subset(self): + return self.user_api.aperture + + @property + def slice_plugin(self): + return self.app._jdaviz_helper.plugins['Slice'] + + @observe('wavelength_dependent') + def _wavelength_dependent_changed(self, *args): + if self.wavelength_dependent: + self.reference_wavelength = self.slice_plugin.wavelength + # NOTE: this can be redundant in the case where reference_wavelength changed and triggers + # the observe, but we need to ensure it is updated if reference_wavelength is unchanged + self._update_mark_scale() + + def _on_slice_changed(self, msg): + self.slice_wavelength = msg.wavelength + + def vue_goto_reference_wavelength(self, *args): + self.slice_plugin.wavelength = self.reference_wavelength + # TODO: can we get rid of this extra call after properly observing wavelength? +# self._update_mark_scale() + + def vue_adopt_slice_as_reference(self, *args): + self.reference_wavelength = self.slice_plugin.wavelength + + @observe('reference_wavelength', 'slice_wavelength') + def _update_mark_scale(self, *args): + if not self.wavelength_dependent: + self.aperture.scale_factor = 1.0 + return + self.aperture.scale_factor = self.slice_wavelength/self.reference_wavelength + @with_spinner() def collapse_to_spectrum(self, add_data=True, **kwargs): """ @@ -121,12 +175,12 @@ def collapse_to_spectrum(self, add_data=True, **kwargs): # defaults to ``No Subset``). Since the Cubeviz parser puts the fluxes # and uncertainties in different glue Data objects, we translate the spectral # cube and its uncertainties into separate NDDataArrays, then combine them: - if self.spatial_subset_selected != self.spatial_subset.default_text: + if self.aperture.selected != self.spatial_subset.default_text: nddata = spectral_cube.get_subset_object( - subset_id=self.spatial_subset_selected, cls=NDDataArray + subset_id=self.aperture.selected, cls=NDDataArray ) uncertainties = uncert_cube.get_subset_object( - subset_id=self.spatial_subset_selected, cls=StdDevUncertainty + subset_id=self.aperture.selected, cls=StdDevUncertainty ) else: nddata = spectral_cube.get_object(cls=NDDataArray) @@ -242,15 +296,15 @@ def _save_extracted_spec_to_fits(self, overwrite=False, *args): f"Extracted spectrum saved to {os.path.abspath(filename)}", sender=self, color="success")) - @observe('spatial_subset_selected') + @observe('aperture_selected') def _set_default_results_label(self, event={}): label = "Spectral extraction" if ( - hasattr(self, 'spatial_subset') and - self.spatial_subset.selected != self.spatial_subset.default_text + hasattr(self, 'aperture') and + self.aperture.selected != self.aperture.default_text ): - label += f' ({self.spatial_subset_selected})' + label += f' ({self.aperture_selected})' self.results_label_default = label diff --git a/jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.vue b/jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.vue index 553945daa8..41695b4510 100644 --- a/jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.vue +++ b/jdaviz/configs/cubeviz/plugins/spectral_extraction/spectral_extraction.vue @@ -2,6 +2,9 @@ @@ -18,13 +21,53 @@ +
+ cone support is under active development and hidden from users + + + + +
+ + + + Adopt Current Slice + + + + + + + + + + Slice to Reference Wavelength + + + +
+ +
+