From e1e30e7c1999c4a2538c6da7ca1f39d7fe67b0f5 Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Fri, 12 May 2023 10:09:01 -0400 Subject: [PATCH 01/21] Add option to get_data to apply spectral subset to collapse spatial --- jdaviz/configs/cubeviz/helper.py | 9 +++++++-- jdaviz/configs/specviz/helper.py | 7 +++++-- jdaviz/core/helpers.py | 17 ++++++++++++++--- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/jdaviz/configs/cubeviz/helper.py b/jdaviz/configs/cubeviz/helper.py index dc102af7e0..85b0e2dfa9 100644 --- a/jdaviz/configs/cubeviz/helper.py +++ b/jdaviz/configs/cubeviz/helper.py @@ -120,7 +120,8 @@ def specviz(self): self._specviz = Specviz(app=self.app) return self._specviz - def get_data(self, data_label=None, cls=None, subset_to_apply=None, function=None): + def get_data(self, data_label=None, cls=None, subset_to_apply=None, function=None, + spectral_to_spatial=None): """ Returns data with name equal to data_label of type cls with subsets applied from subset_to_apply. @@ -138,6 +139,9 @@ def get_data(self, data_label=None, cls=None, subset_to_apply=None, function=Non If True, will collapse according to the current collapse function defined in the spectrum viewer. If provided as a string, the cube will be collapsed with the provided function. If False, None, or not passed, the entire cube will be returned. + spectral_to_spatial : str, optional + Spectral subset to be applied to spatial subset. Only possible if function is + set to True. Returns ------- @@ -147,7 +151,8 @@ def get_data(self, data_label=None, cls=None, subset_to_apply=None, function=Non """ if function is True: return self.specviz.get_data(data_label=data_label, cls=cls, - subset_to_apply=subset_to_apply) + subset_to_apply=subset_to_apply, + spectral_to_spatial=spectral_to_spatial) elif function is False: function = None return self._get_data(data_label=data_label, cls=cls, subset_to_apply=subset_to_apply, diff --git a/jdaviz/configs/specviz/helper.py b/jdaviz/configs/specviz/helper.py index 04db731d89..396986ee42 100644 --- a/jdaviz/configs/specviz/helper.py +++ b/jdaviz/configs/specviz/helper.py @@ -271,7 +271,7 @@ def set_spectrum_tick_format(self, fmt, axis=None): self._default_spectrum_viewer_reference_name ).figure.axes[axis].tick_format = fmt - def get_data(self, data_label=None, cls=None, subset_to_apply=None): + def get_data(self, data_label=None, cls=None, subset_to_apply=None, spectral_to_spatial=None): """ Returns data with name equal to data_label of type cls with subsets applied from subset_to_apply. @@ -284,6 +284,9 @@ def get_data(self, data_label=None, cls=None, subset_to_apply=None): The type that data will be returned as. subset_to_apply : str, optional Subset that is to be applied to data before it is returned. + spectral_to_spatial : str, optional + Spectral subset to be applied to spatial subset. Only possible if this is + a specviz instance inside cubeviz. Returns ------- @@ -302,4 +305,4 @@ def get_data(self, data_label=None, cls=None, subset_to_apply=None): function = None return self._get_data(data_label=data_label, cls=cls, subset_to_apply=subset_to_apply, - function=function) + function=function, spectral_to_spatial=spectral_to_spatial) diff --git a/jdaviz/core/helpers.py b/jdaviz/core/helpers.py index d9a415768d..e8695dc956 100644 --- a/jdaviz/core/helpers.py +++ b/jdaviz/core/helpers.py @@ -22,6 +22,7 @@ from glue.config import data_translator from ipywidgets.widgets import widget_serialization from specutils import Spectrum1D +from specutils.manipulation import extract_region from jdaviz.app import Application @@ -410,7 +411,8 @@ def show_in_new_tab(self, title=None): # pragma: no cover DeprecationWarning) return self.show(loc="sidecar:tab-after", title=title) - def _get_data(self, data_label=None, cls=None, subset_to_apply=None, function=None): + def _get_data(self, data_label=None, cls=None, subset_to_apply=None, function=None, + spectral_to_spatial=None): list_of_valid_function_values = ('minimum', 'maximum', 'mean', 'median', 'sum') if function and function not in list_of_valid_function_values: @@ -480,9 +482,15 @@ def _get_data(self, data_label=None, cls=None, subset_to_apply=None, function=No warnings.warn(f"Not able to get {data_label} returned with" f" subset {subsets.label} applied of type {cls}." f" Exception: {e}") + # Apply spectral subset to spatial subset if applicable + if spectral_to_spatial: + sr = self.app.get_subsets(spectral_to_spatial) + if sr: + data = extract_region(data, sr, return_single_spectrum=True) + return data - def get_data(self, data_label=None, cls=None, subset_to_apply=None): + def get_data(self, data_label=None, cls=None, subset_to_apply=None, spectral_to_spatial=None): """ Returns data with name equal to data_label of type cls with subsets applied from subset_to_apply. @@ -495,6 +503,8 @@ def get_data(self, data_label=None, cls=None, subset_to_apply=None): The type that data will be returned as. subset_to_apply : str, optional Subset that is to be applied to data before it is returned. + spectral_to_spatial : str, optional + Spectral subset to be applied to spatial subset. Returns ------- @@ -502,7 +512,8 @@ def get_data(self, data_label=None, cls=None, subset_to_apply=None): Data is returned as type cls with subsets applied. """ - return self._get_data(data_label=data_label, cls=cls, subset_to_apply=subset_to_apply) + return self._get_data(data_label=data_label, cls=cls, subset_to_apply=subset_to_apply, + spectral_to_spatial=spectral_to_spatial) class ImageConfigHelper(ConfigHelper): From 797096eda43b77f561c5434b3d4b2d6324486b2a Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Fri, 19 May 2023 10:09:04 -0400 Subject: [PATCH 02/21] Fix tests that use get_data --- jdaviz/configs/cubeviz/helper.py | 17 ++++---- .../plugins/tests/test_cubeviz_helper.py | 12 +++--- jdaviz/configs/specviz/helper.py | 21 ++++++---- .../plugins/line_analysis/line_analysis.py | 2 +- jdaviz/core/helpers.py | 40 +++++++++++++------ jdaviz/core/template_mixin.py | 10 +++-- jdaviz/core/tests/test_helpers.py | 4 +- 7 files changed, 66 insertions(+), 40 deletions(-) diff --git a/jdaviz/configs/cubeviz/helper.py b/jdaviz/configs/cubeviz/helper.py index 85b0e2dfa9..cccc521f0b 100644 --- a/jdaviz/configs/cubeviz/helper.py +++ b/jdaviz/configs/cubeviz/helper.py @@ -120,8 +120,8 @@ def specviz(self): self._specviz = Specviz(app=self.app) return self._specviz - def get_data(self, data_label=None, cls=None, subset_to_apply=None, function=None, - spectral_to_spatial=None): + def get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, function=None, + cls=None): """ Returns data with name equal to data_label of type cls with subsets applied from subset_to_apply. @@ -149,14 +149,15 @@ def get_data(self, data_label=None, cls=None, subset_to_apply=None, function=Non Data is returned as type cls with subsets applied. """ - if function is True: - return self.specviz.get_data(data_label=data_label, cls=cls, - subset_to_apply=subset_to_apply, - spectral_to_spatial=spectral_to_spatial) + if function: + return self.specviz.get_data(data_label=data_label, spectral_subset=spectral_subset, + cls=cls, spatial_subset=spatial_subset, function=function) + elif function is None and spectral_subset and spatial_subset: + function = True elif function is False: function = None - return self._get_data(data_label=data_label, cls=cls, subset_to_apply=subset_to_apply, - function=function) + return self._get_data(data_label=data_label, spatial_subset=spatial_subset, + spectral_subset=spectral_subset, function=function, cls=cls) def layer_is_cube_image_data(layer): diff --git a/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py b/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py index 2e9b0422a1..c958535eba 100644 --- a/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py +++ b/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py @@ -29,7 +29,7 @@ def test_invalid_function(cubeviz_helper, spectrum1d_cube): cubeviz_helper._apply_interactive_region('bqplot:ellipse', (0, 0), (9, 8)) with pytest.raises(ValueError, match='function 42 not in list of valid '): - cubeviz_helper.get_data(data_label="test[FLUX]", subset_to_apply='Subset 1', function=42) + cubeviz_helper.get_data(data_label="test[FLUX]", spatial_subset='Subset 1', function=42) # Also make sure specviz redshift slider warning does not show up. # https://github.com/spacetelescope/jdaviz/issues/2029 @@ -41,20 +41,20 @@ def test_valid_function(cubeviz_helper, spectrum1d_cube): cubeviz_helper._apply_interactive_region('bqplot:ellipse', (0, 0), (9, 8)) results_cube = cubeviz_helper.get_data(data_label="test[FLUX]", - subset_to_apply='Subset 1') + spatial_subset='Subset 1') assert results_cube.flux.ndim == 3 results_false = cubeviz_helper.get_data(data_label="test[FLUX]", - subset_to_apply='Subset 1', function=False) + spatial_subset='Subset 1', function=False) assert results_false.flux.ndim == 3 results_def = cubeviz_helper.get_data(data_label="test[FLUX]", - subset_to_apply='Subset 1', function=True) + spatial_subset='Subset 1', function=True) assert results_def.flux.ndim == 1 results_min = cubeviz_helper.get_data(data_label="test[FLUX]", - subset_to_apply='Subset 1', function="minimum") + spatial_subset='Subset 1', function="minimum") results_max = cubeviz_helper.get_data(data_label="test[FLUX]", - subset_to_apply='Subset 1', function="maximum") + spatial_subset='Subset 1', function="maximum") assert isinstance(results_min, Spectrum1D) assert_quantity_allclose(results_min.flux, [6., 14.] * u.Jy, atol=1e-5 * u.Jy) diff --git a/jdaviz/configs/specviz/helper.py b/jdaviz/configs/specviz/helper.py index 396986ee42..2d104f0975 100644 --- a/jdaviz/configs/specviz/helper.py +++ b/jdaviz/configs/specviz/helper.py @@ -79,7 +79,7 @@ def get_spectra(self, data_label=None, subset_to_apply=None, apply_slider_redshi if data_label is not None: spectrum = get_data_method(data_label=data_label, - subset_to_apply=subset_to_apply, + spectral_subset=subset_to_apply, cls=Spectrum1D) spectra[data_label] = spectrum else: @@ -88,7 +88,7 @@ def get_spectra(self, data_label=None, subset_to_apply=None, apply_slider_redshi if subset_to_apply is not None: if lyr.label == subset_to_apply: spectrum = get_data_method(data_label=lyr.data.label, - subset_to_apply=subset_to_apply, + spectral_subset=subset_to_apply, cls=Spectrum1D, **function_kwargs) spectra[lyr.data.label] = spectrum @@ -97,7 +97,7 @@ def get_spectra(self, data_label=None, subset_to_apply=None, apply_slider_redshi else: if isinstance(lyr, GroupedSubset): spectrum = get_data_method(data_label=lyr.data.label, - subset_to_apply=lyr.label, + spectral_subset=lyr.label, cls=Spectrum1D, **function_kwargs) spectra[f'{lyr.data.label} ({lyr.label})'] = spectrum @@ -271,7 +271,7 @@ def set_spectrum_tick_format(self, fmt, axis=None): self._default_spectrum_viewer_reference_name ).figure.axes[axis].tick_format = fmt - def get_data(self, data_label=None, cls=None, subset_to_apply=None, spectral_to_spatial=None): + def get_data(self, data_label=None, spectral_subset=None, cls=None, **kwargs): """ Returns data with name equal to data_label of type cls with subsets applied from subset_to_apply. @@ -294,15 +294,22 @@ def get_data(self, data_label=None, cls=None, subset_to_apply=None, spectral_to_ Data is returned as type cls with subsets applied. """ + spatial_subset = kwargs.pop("spatial_subset", None) + function = kwargs.pop("function", None) if self.app.config == 'cubeviz': # then this is a specviz instance inside cubeviz and we want to default to the # viewer's collapse function default_sp_viewer = self.app.get_viewer(self._default_spectrum_viewer_reference_name) - function = getattr(default_sp_viewer.state, 'function', None) + if function is True or function is None: + function = getattr(default_sp_viewer.state, 'function', None) + if cls is None: cls = Spectrum1D else: function = None - return self._get_data(data_label=data_label, cls=cls, subset_to_apply=subset_to_apply, - function=function, spectral_to_spatial=spectral_to_spatial) + # return self._get_data(data_label=data_label, cls=cls, subset_to_apply=subset_to_apply, + # function=function, spectral_to_spatial=spectral_to_spatial) + # print(function) + return self._get_data(data_label=data_label, spatial_subset=spatial_subset, + spectral_subset=spectral_subset, function=function, cls=cls) diff --git a/jdaviz/configs/specviz/plugins/line_analysis/line_analysis.py b/jdaviz/configs/specviz/plugins/line_analysis/line_analysis.py index 134a9b917d..e19b115b1d 100644 --- a/jdaviz/configs/specviz/plugins/line_analysis/line_analysis.py +++ b/jdaviz/configs/specviz/plugins/line_analysis/line_analysis.py @@ -383,7 +383,7 @@ def _calculate_statistics(self, *args, **kwargs): # cube, but still apply that to the spatially-collapsed spectrum. continuum_mask = ~self._specviz_helper.get_data( self.dataset.selected, - subset_to_apply=self.continuum_subset_selected).mask + spectral_subset=self.continuum_subset_selected).mask spectral_axis_nanmasked = spectral_axis.value.copy() spectral_axis_nanmasked[~continuum_mask] = np.nan if self.spectral_subset_selected == "Entire Spectrum": diff --git a/jdaviz/core/helpers.py b/jdaviz/core/helpers.py index e8695dc956..79b1dc5f55 100644 --- a/jdaviz/core/helpers.py +++ b/jdaviz/core/helpers.py @@ -411,8 +411,10 @@ def show_in_new_tab(self, title=None): # pragma: no cover DeprecationWarning) return self.show(loc="sidecar:tab-after", title=title) - def _get_data(self, data_label=None, cls=None, subset_to_apply=None, function=None, - spectral_to_spatial=None): + # def _get_data(self, data_label=None, cls=None, subset_to_apply=None, function=None, + # spectral_to_spatial=None): + def _get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, + function=None, cls=None): list_of_valid_function_values = ('minimum', 'maximum', 'mean', 'median', 'sum') if function and function not in list_of_valid_function_values: @@ -420,9 +422,14 @@ def _get_data(self, data_label=None, cls=None, subset_to_apply=None, function=No f" function values {list_of_valid_function_values}") list_of_valid_subset_names = [x.label for x in self.app.data_collection.subset_groups] - if subset_to_apply and subset_to_apply not in list_of_valid_subset_names: - raise ValueError(f"Subset {subset_to_apply} not in list of valid" + if spatial_subset and spatial_subset not in list_of_valid_subset_names: + raise ValueError(f"Subset {spatial_subset} not in list of valid" f" subset names {list_of_valid_subset_names}") + elif spectral_subset and spectral_subset not in list_of_valid_subset_names: + raise ValueError(f"Subset {spectral_subset} not in list of valid" + f" subset names {list_of_valid_subset_names}") + + # TODO: check if spectral is spectral and spatial is spatial if data_label and data_label not in self.app.data_collection.labels: raise ValueError(f'{data_label} not in {self.app.data_collection.labels}.') @@ -451,7 +458,7 @@ def _get_data(self, data_label=None, cls=None, subset_to_apply=None, function=No if cls == Spectrum1D: object_kwargs['statistic'] = function - if not subset_to_apply: + if not spatial_subset and not spectral_subset: if 'Trace' in data.meta: if cls is not None: # pragma: no cover raise ValueError("cls not supported for Trace object") @@ -461,11 +468,15 @@ def _get_data(self, data_label=None, cls=None, subset_to_apply=None, function=No return data - if not cls and subset_to_apply: + if not cls and spatial_subset: raise AttributeError(f"A valid cls must be provided to" - f" apply subset {subset_to_apply} to data. " + f" apply subset {spatial_subset} to data. " f"Instead, {cls} was given.") - + elif not cls and spectral_subset: + raise AttributeError(f"A valid cls must be provided to" + f" apply subset {spectral_subset} to data. " + f"Instead, {cls} was given.") + subset_to_apply = spatial_subset if spatial_subset else spectral_subset if spectral_subset else None # Loop through each subset for subsets in self.app.data_collection.subset_groups: # If name matches the name in subsets_to_apply, continue @@ -483,14 +494,15 @@ def _get_data(self, data_label=None, cls=None, subset_to_apply=None, function=No f" subset {subsets.label} applied of type {cls}." f" Exception: {e}") # Apply spectral subset to spatial subset if applicable - if spectral_to_spatial: - sr = self.app.get_subsets(spectral_to_spatial) + if spatial_subset and spectral_subset: + sr = self.app.get_subsets(spectral_subset) if sr: data = extract_region(data, sr, return_single_spectrum=True) return data - def get_data(self, data_label=None, cls=None, subset_to_apply=None, spectral_to_spatial=None): + # def get_data(self, data_label=None, cls=None, subset_to_apply=None, spectral_to_spatial=None): + def get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, cls=None): """ Returns data with name equal to data_label of type cls with subsets applied from subset_to_apply. @@ -512,8 +524,10 @@ def get_data(self, data_label=None, cls=None, subset_to_apply=None, spectral_to_ Data is returned as type cls with subsets applied. """ - return self._get_data(data_label=data_label, cls=cls, subset_to_apply=subset_to_apply, - spectral_to_spatial=spectral_to_spatial) + # return self._get_data(data_label=data_label, cls=cls, subset_to_apply=subset_to_apply, + # spectral_to_spatial=spectral_to_spatial) + return self._get_data(data_label=data_label, spatial_subset=spatial_subset, + spectral_subset=spectral_subset, function=None, cls=None) class ImageConfigHelper(ConfigHelper): diff --git a/jdaviz/core/template_mixin.py b/jdaviz/core/template_mixin.py index fb094d6f5e..28f2f89d8a 100644 --- a/jdaviz/core/template_mixin.py +++ b/jdaviz/core/template_mixin.py @@ -1031,8 +1031,12 @@ def selected_subset_state(self): @property def selected_subset_mask(self): - get_data_kwargs = {'data_label': self.plugin.dataset.selected, - 'subset_to_apply': self.selected} + if self._allowed_type == 'spatial': + get_data_kwargs = {'data_label': self.plugin.dataset.selected, + 'spatial_subset': self.selected} + elif self._allowed_type == 'spectral': + get_data_kwargs = {'data_label': self.plugin.dataset.selected, + 'spectral_subset': self.selected} if self.app.config == 'cubeviz' and self._allowed_type == 'spectral': viewer_ref = getattr(self.plugin, @@ -1487,7 +1491,7 @@ def selected_spectrum_for_spatial_subset(self, spatial_subset=SPATIAL_DEFAULT_TE if spatial_subset == SPATIAL_DEFAULT_TEXT: spatial_subset = None return self.plugin._specviz_helper.get_data(data_label=self.selected, - subset_to_apply=spatial_subset) + spatial_subset=spatial_subset) def _is_valid_item(self, data): def not_from_plugin(data): diff --git a/jdaviz/core/tests/test_helpers.py b/jdaviz/core/tests/test_helpers.py index 5340bd5f21..6b32860f30 100644 --- a/jdaviz/core/tests/test_helpers.py +++ b/jdaviz/core/tests/test_helpers.py @@ -64,7 +64,7 @@ def setup_class(self, specviz_helper, spectrum1d, multi_order_spectrum_list): def test_get_data_with_one_subset_per_data(self, specviz_helper, label, subset_name, answer): results = specviz_helper.get_data(data_label=label, - subset_to_apply=subset_name) + spectral_subset=subset_name) assert list(results.mask) == answer def test_get_data_no_label_multiple_in_dc(self, specviz_helper): @@ -88,4 +88,4 @@ def test_get_data_invald_cls_class(self, specviz_helper): def test_get_data_invald_subset_name(self, specviz_helper): with pytest.raises(ValueError, match="not in list of valid subset names"): - specviz_helper.get_data('Test 1D Spectrum', subset_to_apply="Fail") + specviz_helper.get_data('Test 1D Spectrum', spectral_subset="Fail") From b9cd460a559eb5f41c3fb580936090e47f8fdb4c Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Fri, 19 May 2023 15:03:06 -0400 Subject: [PATCH 03/21] Implement review comments --- jdaviz/configs/specviz/helper.py | 6 +++--- jdaviz/core/helpers.py | 6 ++---- jdaviz/core/template_mixin.py | 9 +++------ 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/jdaviz/configs/specviz/helper.py b/jdaviz/configs/specviz/helper.py index 2d104f0975..0df9094c4c 100644 --- a/jdaviz/configs/specviz/helper.py +++ b/jdaviz/configs/specviz/helper.py @@ -296,6 +296,9 @@ def get_data(self, data_label=None, spectral_subset=None, cls=None, **kwargs): """ spatial_subset = kwargs.pop("spatial_subset", None) function = kwargs.pop("function", None) + if len(kwargs) > 0: + raise ValueError(f'kwargs {[x for x in kwargs.keys()]} are not valid') + if self.app.config == 'cubeviz': # then this is a specviz instance inside cubeviz and we want to default to the # viewer's collapse function @@ -308,8 +311,5 @@ def get_data(self, data_label=None, spectral_subset=None, cls=None, **kwargs): else: function = None - # return self._get_data(data_label=data_label, cls=cls, subset_to_apply=subset_to_apply, - # function=function, spectral_to_spatial=spectral_to_spatial) - # print(function) return self._get_data(data_label=data_label, spatial_subset=spatial_subset, spectral_subset=spectral_subset, function=function, cls=cls) diff --git a/jdaviz/core/helpers.py b/jdaviz/core/helpers.py index 79b1dc5f55..00457046d2 100644 --- a/jdaviz/core/helpers.py +++ b/jdaviz/core/helpers.py @@ -411,8 +411,6 @@ def show_in_new_tab(self, title=None): # pragma: no cover DeprecationWarning) return self.show(loc="sidecar:tab-after", title=title) - # def _get_data(self, data_label=None, cls=None, subset_to_apply=None, function=None, - # spectral_to_spatial=None): def _get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, function=None, cls=None): list_of_valid_function_values = ('minimum', 'maximum', 'mean', @@ -476,7 +474,8 @@ def _get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, raise AttributeError(f"A valid cls must be provided to" f" apply subset {spectral_subset} to data. " f"Instead, {cls} was given.") - subset_to_apply = spatial_subset if spatial_subset else spectral_subset if spectral_subset else None + subset_to_apply = (spatial_subset if spatial_subset + else spectral_subset if spectral_subset else None) # Loop through each subset for subsets in self.app.data_collection.subset_groups: # If name matches the name in subsets_to_apply, continue @@ -501,7 +500,6 @@ def _get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, return data - # def get_data(self, data_label=None, cls=None, subset_to_apply=None, spectral_to_spatial=None): def get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, cls=None): """ Returns data with name equal to data_label of type cls with subsets applied from diff --git a/jdaviz/core/template_mixin.py b/jdaviz/core/template_mixin.py index 28f2f89d8a..82b2670cba 100644 --- a/jdaviz/core/template_mixin.py +++ b/jdaviz/core/template_mixin.py @@ -1031,12 +1031,9 @@ def selected_subset_state(self): @property def selected_subset_mask(self): - if self._allowed_type == 'spatial': - get_data_kwargs = {'data_label': self.plugin.dataset.selected, - 'spatial_subset': self.selected} - elif self._allowed_type == 'spectral': - get_data_kwargs = {'data_label': self.plugin.dataset.selected, - 'spectral_subset': self.selected} + get_data_kwargs = {'data_label': self.plugin.dataset.selected} + if self._allowed_type: + get_data_kwargs[f'{self._allowed_type}_subset'] = self.selected if self.app.config == 'cubeviz' and self._allowed_type == 'spectral': viewer_ref = getattr(self.plugin, From b2f3f791e85689e2839935c373e18069d9d071dc Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Fri, 19 May 2023 15:41:14 -0400 Subject: [PATCH 04/21] Apply spectral subset mask to collapsed spatial subset --- jdaviz/core/helpers.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/jdaviz/core/helpers.py b/jdaviz/core/helpers.py index 00457046d2..e0ecb81b66 100644 --- a/jdaviz/core/helpers.py +++ b/jdaviz/core/helpers.py @@ -476,6 +476,7 @@ def _get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, f"Instead, {cls} was given.") subset_to_apply = (spatial_subset if spatial_subset else spectral_subset if spectral_subset else None) + spec_sub = None # Loop through each subset for subsets in self.app.data_collection.subset_groups: # If name matches the name in subsets_to_apply, continue @@ -492,11 +493,22 @@ def _get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, warnings.warn(f"Not able to get {data_label} returned with" f" subset {subsets.label} applied of type {cls}." f" Exception: {e}") + elif (spatial_subset and spectral_subset and + subsets.label.lower() == spectral_subset.lower()): + # Same logic as if statement + spec_sub = [spec_sub_data for spec_sub_data in subsets.subsets if + spec_sub_data.data.label == data_label][0] # Apply spectral subset to spatial subset if applicable if spatial_subset and spectral_subset: - sr = self.app.get_subsets(spectral_subset) - if sr: - data = extract_region(data, sr, return_single_spectrum=True) + handler, _ = data_translator.get_handler_for(cls) + try: + spec_subset = handler.to_object(spec_sub, **object_kwargs) + except Exception as e: + warnings.warn(f"Not able to get {data_label} returned with" + f" subset {subsets.label} applied of type {cls}." + f" Exception: {e}") + # Return collapsed Spectrum1D object with spectral subset mask applied + data.mask = ~spec_subset.mask return data From edd3b55e09601983b52296bea9df791c0bab5850 Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Fri, 19 May 2023 15:49:47 -0400 Subject: [PATCH 05/21] Update docstrings --- jdaviz/configs/cubeviz/helper.py | 16 ++++++++-------- jdaviz/configs/specviz/helper.py | 7 ++----- jdaviz/core/helpers.py | 11 ++++------- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/jdaviz/configs/cubeviz/helper.py b/jdaviz/configs/cubeviz/helper.py index cccc521f0b..171109fb74 100644 --- a/jdaviz/configs/cubeviz/helper.py +++ b/jdaviz/configs/cubeviz/helper.py @@ -130,18 +130,18 @@ def get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, f ---------- data_label : str, optional Provide a label to retrieve a specific data set from data_collection. - cls : `~specutils.Spectrum1D`, `~astropy.nddata.CCDData`, optional - The type that data will be returned as. - subset_to_apply : str, optional - Subset that is to be applied to data before it is returned. + spatial_subset : str, optional + Spatial subset applied to data. + spectral_subset : str, optional + Spectral subset applied to data. function : {True, False, 'minimum', 'maximum', 'mean', 'median', 'sum'}, optional Ignored if ``data_label`` does not point to cube-like data. If True, will collapse according to the current collapse function defined in the spectrum viewer. If provided as a string, the cube will be collapsed with the provided - function. If False, None, or not passed, the entire cube will be returned. - spectral_to_spatial : str, optional - Spectral subset to be applied to spatial subset. Only possible if function is - set to True. + function. If False, None, or not passed, the entire cube will be returned (unless there + are values for ``spatial_subset`` and ``spectral_subset``). + cls : `~specutils.Spectrum1D`, `~astropy.nddata.CCDData`, optional + The type that data will be returned as. Returns ------- diff --git a/jdaviz/configs/specviz/helper.py b/jdaviz/configs/specviz/helper.py index 0df9094c4c..7e2efa0c38 100644 --- a/jdaviz/configs/specviz/helper.py +++ b/jdaviz/configs/specviz/helper.py @@ -280,13 +280,10 @@ def get_data(self, data_label=None, spectral_subset=None, cls=None, **kwargs): ---------- data_label : str, optional Provide a label to retrieve a specific data set from data_collection. + spectral_subset : str, optional + Spectral subset applied to data. cls : `~specutils.Spectrum1D`, optional The type that data will be returned as. - subset_to_apply : str, optional - Subset that is to be applied to data before it is returned. - spectral_to_spatial : str, optional - Spectral subset to be applied to spatial subset. Only possible if this is - a specviz instance inside cubeviz. Returns ------- diff --git a/jdaviz/core/helpers.py b/jdaviz/core/helpers.py index e0ecb81b66..c141b12b85 100644 --- a/jdaviz/core/helpers.py +++ b/jdaviz/core/helpers.py @@ -22,7 +22,6 @@ from glue.config import data_translator from ipywidgets.widgets import widget_serialization from specutils import Spectrum1D -from specutils.manipulation import extract_region from jdaviz.app import Application @@ -521,12 +520,12 @@ def get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, c ---------- data_label : str, optional Provide a label to retrieve a specific data set from data_collection. + spatial_subset : str, optional + Spatial subset applied to data. + spectral_subset : str, optional + Spectral subset applied to data. cls : `~specutils.Spectrum1D`, `~astropy.nddata.CCDData`, optional The type that data will be returned as. - subset_to_apply : str, optional - Subset that is to be applied to data before it is returned. - spectral_to_spatial : str, optional - Spectral subset to be applied to spatial subset. Returns ------- @@ -534,8 +533,6 @@ def get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, c Data is returned as type cls with subsets applied. """ - # return self._get_data(data_label=data_label, cls=cls, subset_to_apply=subset_to_apply, - # spectral_to_spatial=spectral_to_spatial) return self._get_data(data_label=data_label, spatial_subset=spatial_subset, spectral_subset=spectral_subset, function=None, cls=None) From dd13038439508a970ba8051d2af7793a45307cbc Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Fri, 19 May 2023 16:16:06 -0400 Subject: [PATCH 06/21] Add tests --- jdaviz/configs/cubeviz/helper.py | 4 +-- .../plugins/tests/test_cubeviz_helper.py | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/jdaviz/configs/cubeviz/helper.py b/jdaviz/configs/cubeviz/helper.py index 171109fb74..16361cc44d 100644 --- a/jdaviz/configs/cubeviz/helper.py +++ b/jdaviz/configs/cubeviz/helper.py @@ -149,11 +149,9 @@ def get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, f Data is returned as type cls with subsets applied. """ - if function: + if function or (spectral_subset and spatial_subset): return self.specviz.get_data(data_label=data_label, spectral_subset=spectral_subset, cls=cls, spatial_subset=spatial_subset, function=function) - elif function is None and spectral_subset and spatial_subset: - function = True elif function is False: function = None return self._get_data(data_label=data_label, spatial_subset=spatial_subset, diff --git a/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py b/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py index c958535eba..8cb634c94c 100644 --- a/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py +++ b/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py @@ -4,6 +4,8 @@ from astropy.tests.helper import assert_quantity_allclose from specutils import Spectrum1D +from glue.core.roi import XRangeROI + def test_nested_helper(cubeviz_helper): '''Ensures the Cubeviz helper is always returned, even after the Specviz helper is called''' @@ -65,3 +67,31 @@ def test_valid_function(cubeviz_helper, spectrum1d_cube): assert cubeviz_helper.get_data(data_label="test[FLUX]").flux.ndim == 3 # but calling through specviz automatically collapses assert cubeviz_helper.specviz.get_data(data_label="test[FLUX]").flux.ndim == 1 + + +def test_get_data_spatial_and_spectral(cubeviz_helper, spectrum1d_cube_larger): + data_label = "test" + cubeviz_helper.load_data(spectrum1d_cube_larger, data_label) + cubeviz_helper._apply_interactive_region('bqplot:ellipse', (0, 0), (9, 8)) + + spec_viewer = cubeviz_helper.app.get_viewer(cubeviz_helper._default_spectrum_viewer_reference_name) + spec_viewer.apply_roi(XRangeROI(4.62440061e-07, 4.62520112e-07)) + + data_label = data_label + "[FLUX]" + # This will be the same if function is None or True + spatial_with_spec = cubeviz_helper.get_data(data_label=data_label, + spatial_subset="Subset 1", + spectral_subset="Subset 2") + assert spatial_with_spec.flux.ndim == 1 + assert list(spatial_with_spec.mask) == [False, False, True, True, False, + False, False, False, False, False] + assert max(list(spatial_with_spec.flux.value)) == 157. + assert min(list(spatial_with_spec.flux.value)) == 13. + + spatial_with_spec = cubeviz_helper.get_data(data_label=data_label, + spatial_subset="Subset 1", + spectral_subset="Subset 2", + function='minimum') + assert max(list(spatial_with_spec.flux.value)) == 78. + assert min(list(spatial_with_spec.flux.value)) == 6. + From dfd7d60e8372f74cc018e1e54a8e4a64a69006da Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Fri, 19 May 2023 16:19:48 -0400 Subject: [PATCH 07/21] Fix style checks --- jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py b/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py index 8cb634c94c..223501d69d 100644 --- a/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py +++ b/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py @@ -74,7 +74,7 @@ def test_get_data_spatial_and_spectral(cubeviz_helper, spectrum1d_cube_larger): cubeviz_helper.load_data(spectrum1d_cube_larger, data_label) cubeviz_helper._apply_interactive_region('bqplot:ellipse', (0, 0), (9, 8)) - spec_viewer = cubeviz_helper.app.get_viewer(cubeviz_helper._default_spectrum_viewer_reference_name) + spec_viewer = cubeviz_helper.app.get_viewer(cubeviz_helper._default_spectrum_viewer_reference_name) # noqa spec_viewer.apply_roi(XRangeROI(4.62440061e-07, 4.62520112e-07)) data_label = data_label + "[FLUX]" @@ -94,4 +94,3 @@ def test_get_data_spatial_and_spectral(cubeviz_helper, spectrum1d_cube_larger): function='minimum') assert max(list(spatial_with_spec.flux.value)) == 78. assert min(list(spatial_with_spec.flux.value)) == 6. - From ff0ecb6da0a898d34a0f9c2fa3169f759a2da6cf Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Fri, 19 May 2023 16:45:35 -0400 Subject: [PATCH 08/21] Change error message --- jdaviz/core/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdaviz/core/helpers.py b/jdaviz/core/helpers.py index c141b12b85..07122e5ff8 100644 --- a/jdaviz/core/helpers.py +++ b/jdaviz/core/helpers.py @@ -504,7 +504,7 @@ def _get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, spec_subset = handler.to_object(spec_sub, **object_kwargs) except Exception as e: warnings.warn(f"Not able to get {data_label} returned with" - f" subset {subsets.label} applied of type {cls}." + f" subset {spectral_subset} applied of type {cls}." f" Exception: {e}") # Return collapsed Spectrum1D object with spectral subset mask applied data.mask = ~spec_subset.mask From da88b3b2b81db44f45c5c05f7bcf931a29c964c7 Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Mon, 22 May 2023 08:40:51 -0400 Subject: [PATCH 09/21] Add explicit get_data to imviz --- jdaviz/configs/imviz/helper.py | 22 ++++++++++++++++++++++ jdaviz/core/helpers.py | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/jdaviz/configs/imviz/helper.py b/jdaviz/configs/imviz/helper.py index ed5fe8cf8c..5d09c9a045 100644 --- a/jdaviz/configs/imviz/helper.py +++ b/jdaviz/configs/imviz/helper.py @@ -239,6 +239,28 @@ def get_catalog_source_results(self): """ return getattr(self.app, '_catalog_source_table', None) + def get_data(self, data_label=None, spatial_subset=None, cls=None): + """ + Returns data with name equal to data_label of type cls with subsets applied from + spatial_subset. + + Parameters + ---------- + data_label : str, optional + Provide a label to retrieve a specific data set from data_collection. + spatial_subset : str, optional + Spatial subset applied to data. + cls : `~specutils.Spectrum1D`, `~astropy.nddata.CCDData`, optional + The type that data will be returned as. + + Returns + ------- + data : cls + Data is returned as type cls with subsets applied. + + """ + return self._get_data(data_label=data_label, spatial_subset=spatial_subset, cls=cls) + def split_filename_with_fits_ext(filename): """Split a ``filename[ext]`` input into filename and FITS extension. diff --git a/jdaviz/core/helpers.py b/jdaviz/core/helpers.py index 07122e5ff8..8f72191633 100644 --- a/jdaviz/core/helpers.py +++ b/jdaviz/core/helpers.py @@ -514,7 +514,7 @@ def _get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, def get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, cls=None): """ Returns data with name equal to data_label of type cls with subsets applied from - subset_to_apply. + spatial_subsets and/or spectral_subsets. Parameters ---------- From 1831afde7164ecd6ff488f4da0368079cf1acbbc Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Mon, 22 May 2023 08:51:21 -0400 Subject: [PATCH 10/21] Raise error when cubeviz kwargs are used in specviz get_data --- jdaviz/configs/specviz/helper.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jdaviz/configs/specviz/helper.py b/jdaviz/configs/specviz/helper.py index 7e2efa0c38..1b558ca25a 100644 --- a/jdaviz/configs/specviz/helper.py +++ b/jdaviz/configs/specviz/helper.py @@ -305,6 +305,8 @@ def get_data(self, data_label=None, spectral_subset=None, cls=None, **kwargs): if cls is None: cls = Spectrum1D + elif spatial_subset or function: + raise ValueError('kwargs spatial subset and function are not valid in specviz') else: function = None From 01207fd6738daa20894672070a77143c96f2c5dd Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Mon, 22 May 2023 09:03:18 -0400 Subject: [PATCH 11/21] Implement review requests --- jdaviz/configs/specviz/helper.py | 1 + jdaviz/core/helpers.py | 15 +++++---------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/jdaviz/configs/specviz/helper.py b/jdaviz/configs/specviz/helper.py index 1b558ca25a..8f44c4f99a 100644 --- a/jdaviz/configs/specviz/helper.py +++ b/jdaviz/configs/specviz/helper.py @@ -308,6 +308,7 @@ def get_data(self, data_label=None, spectral_subset=None, cls=None, **kwargs): elif spatial_subset or function: raise ValueError('kwargs spatial subset and function are not valid in specviz') else: + spatial_subset = None function = None return self._get_data(data_label=data_label, spatial_subset=spatial_subset, diff --git a/jdaviz/core/helpers.py b/jdaviz/core/helpers.py index 8f72191633..4418551b49 100644 --- a/jdaviz/core/helpers.py +++ b/jdaviz/core/helpers.py @@ -511,30 +511,25 @@ def _get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, return data - def get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, cls=None): + def get_data(self, data_label=None, cls=None): """ - Returns data with name equal to data_label of type cls with subsets applied from - spatial_subsets and/or spectral_subsets. + Returns data with name equal to data_label of type cls. Parameters ---------- data_label : str, optional Provide a label to retrieve a specific data set from data_collection. - spatial_subset : str, optional - Spatial subset applied to data. - spectral_subset : str, optional - Spectral subset applied to data. cls : `~specutils.Spectrum1D`, `~astropy.nddata.CCDData`, optional The type that data will be returned as. Returns ------- data : cls - Data is returned as type cls with subsets applied. + Data is returned as type cls. """ - return self._get_data(data_label=data_label, spatial_subset=spatial_subset, - spectral_subset=spectral_subset, function=None, cls=None) + return self._get_data(data_label=data_label, spatial_subset=None, + spectral_subset=None, function=None, cls=None) class ImageConfigHelper(ConfigHelper): From b9203d7bf131429c32077a26c6670a3af92bf27b Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Mon, 22 May 2023 10:17:12 -0400 Subject: [PATCH 12/21] Add get_data to specviz2d --- jdaviz/configs/cubeviz/helper.py | 5 ++++- jdaviz/configs/specviz2d/helper.py | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/jdaviz/configs/cubeviz/helper.py b/jdaviz/configs/cubeviz/helper.py index 16361cc44d..b207569faa 100644 --- a/jdaviz/configs/cubeviz/helper.py +++ b/jdaviz/configs/cubeviz/helper.py @@ -149,9 +149,12 @@ def get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, f Data is returned as type cls with subsets applied. """ - if function or (spectral_subset and spatial_subset): + if function and spectral_subset and spatial_subset: return self.specviz.get_data(data_label=data_label, spectral_subset=spectral_subset, cls=cls, spatial_subset=spatial_subset, function=function) + elif function is False and (spectral_subset and spatial_subset): + raise ValueError("function cannot be False if spectral_subset" + " and spatial_subset have values") elif function is False: function = None return self._get_data(data_label=data_label, spatial_subset=spatial_subset, diff --git a/jdaviz/configs/specviz2d/helper.py b/jdaviz/configs/specviz2d/helper.py index c2a50a7888..c41be5df54 100644 --- a/jdaviz/configs/specviz2d/helper.py +++ b/jdaviz/configs/specviz2d/helper.py @@ -238,3 +238,25 @@ def load_trace(self, trace, data_label, show_in_viewer=True): self.app.add_data_to_viewer( self._default_spectrum_2d_viewer_reference_name, data_label ) + + def get_data(self, data_label=None, spectral_subset=None, cls=None): + """ + Returns data with name equal to data_label of type cls with subsets applied from + spectral_subset. + + Parameters + ---------- + data_label : str, optional + Provide a label to retrieve a specific data set from data_collection. + spectral_subset : str, optional + Spectral subset applied to data. + cls : `~specutils.Spectrum1D`, `~astropy.nddata.CCDData`, optional + The type that data will be returned as. + + Returns + ------- + data : cls + Data is returned as type cls with subsets applied. + + """ + return self._get_data(data_label=data_label, spectral_subset=spectral_subset, cls=cls) From 8389ee4c5be4449c878369f8f5610c1d0e0efe51 Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Mon, 22 May 2023 10:48:40 -0400 Subject: [PATCH 13/21] Add line to fix CI --- jdaviz/configs/cubeviz/helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdaviz/configs/cubeviz/helper.py b/jdaviz/configs/cubeviz/helper.py index b207569faa..0bf4625974 100644 --- a/jdaviz/configs/cubeviz/helper.py +++ b/jdaviz/configs/cubeviz/helper.py @@ -149,7 +149,7 @@ def get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, f Data is returned as type cls with subsets applied. """ - if function and spectral_subset and spatial_subset: + if (function or function is None) and spectral_subset and spatial_subset: return self.specviz.get_data(data_label=data_label, spectral_subset=spectral_subset, cls=cls, spatial_subset=spatial_subset, function=function) elif function is False and (spectral_subset and spatial_subset): From afca9a9587946d0c64cfcce714a9480b8838da02 Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Mon, 22 May 2023 11:21:15 -0400 Subject: [PATCH 14/21] Make sure function is respected with just spatial subset --- jdaviz/configs/cubeviz/helper.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/jdaviz/configs/cubeviz/helper.py b/jdaviz/configs/cubeviz/helper.py index 0bf4625974..1e918fda10 100644 --- a/jdaviz/configs/cubeviz/helper.py +++ b/jdaviz/configs/cubeviz/helper.py @@ -149,7 +149,10 @@ def get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, f Data is returned as type cls with subsets applied. """ - if (function or function is None) and spectral_subset and spatial_subset: + if function is not False and spectral_subset and spatial_subset: + return self.specviz.get_data(data_label=data_label, spectral_subset=spectral_subset, + cls=cls, spatial_subset=spatial_subset, function=function) + elif function and spatial_subset: return self.specviz.get_data(data_label=data_label, spectral_subset=spectral_subset, cls=cls, spatial_subset=spatial_subset, function=function) elif function is False and (spectral_subset and spatial_subset): From dea9920d647f45ba2c9081c67c150dd7f448cebe Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Tue, 23 May 2023 13:55:34 -0400 Subject: [PATCH 15/21] Add more catches for incorrect or invalid parameters --- jdaviz/configs/cubeviz/helper.py | 13 +++++----- .../plugins/tests/test_cubeviz_helper.py | 26 ++++++++++++++++--- jdaviz/core/helpers.py | 15 ++++++++--- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/jdaviz/configs/cubeviz/helper.py b/jdaviz/configs/cubeviz/helper.py index 1e918fda10..bb7a23e2e5 100644 --- a/jdaviz/configs/cubeviz/helper.py +++ b/jdaviz/configs/cubeviz/helper.py @@ -149,15 +149,16 @@ def get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, f Data is returned as type cls with subsets applied. """ - if function is not False and spectral_subset and spatial_subset: + # If function is a value ('sum' or 'minimum') or True and spatial and spectral + # are set, then we collapse the cube along the spatial subset using the function, then + # we apply the mask from the spectral subset. + # If function is any value other than False, we use specviz + if (function is not False and spectral_subset and spatial_subset) or function: return self.specviz.get_data(data_label=data_label, spectral_subset=spectral_subset, cls=cls, spatial_subset=spatial_subset, function=function) - elif function and spatial_subset: - return self.specviz.get_data(data_label=data_label, spectral_subset=spectral_subset, - cls=cls, spatial_subset=spatial_subset, function=function) - elif function is False and (spectral_subset and spatial_subset): + elif function is False and spectral_subset: raise ValueError("function cannot be False if spectral_subset" - " and spatial_subset have values") + " is set") elif function is False: function = None return self._get_data(data_label=data_label, spatial_subset=spatial_subset, diff --git a/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py b/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py index 223501d69d..6429d3ca7c 100644 --- a/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py +++ b/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py @@ -71,6 +71,8 @@ def test_valid_function(cubeviz_helper, spectrum1d_cube): def test_get_data_spatial_and_spectral(cubeviz_helper, spectrum1d_cube_larger): data_label = "test" + spatial_subset = "Subset 1" + spectral_subset = "Subset 2" cubeviz_helper.load_data(spectrum1d_cube_larger, data_label) cubeviz_helper._apply_interactive_region('bqplot:ellipse', (0, 0), (9, 8)) @@ -80,8 +82,8 @@ def test_get_data_spatial_and_spectral(cubeviz_helper, spectrum1d_cube_larger): data_label = data_label + "[FLUX]" # This will be the same if function is None or True spatial_with_spec = cubeviz_helper.get_data(data_label=data_label, - spatial_subset="Subset 1", - spectral_subset="Subset 2") + spatial_subset=spatial_subset, + spectral_subset=spectral_subset) assert spatial_with_spec.flux.ndim == 1 assert list(spatial_with_spec.mask) == [False, False, True, True, False, False, False, False, False, False] @@ -89,8 +91,24 @@ def test_get_data_spatial_and_spectral(cubeviz_helper, spectrum1d_cube_larger): assert min(list(spatial_with_spec.flux.value)) == 13. spatial_with_spec = cubeviz_helper.get_data(data_label=data_label, - spatial_subset="Subset 1", - spectral_subset="Subset 2", + spatial_subset=spatial_subset, + spectral_subset=spectral_subset, function='minimum') assert max(list(spatial_with_spec.flux.value)) == 78. assert min(list(spatial_with_spec.flux.value)) == 6. + + collapse_with_spectral = cubeviz_helper.get_data(data_label=data_label, + spectral_subset=spectral_subset, + function=True) + + with pytest.raises(ValueError, match=f'{spectral_subset} is not a spatial subset.'): + cubeviz_helper.get_data(data_label=data_label, spatial_subset=spectral_subset, function=True) + with pytest.raises(ValueError, match=f'{spatial_subset} is not a spectral subset.'): + cubeviz_helper.get_data(data_label=data_label, spectral_subset=spatial_subset, function=True) + with pytest.raises(ValueError, match='function cannot be False if spectral_subset'): + cubeviz_helper.get_data(data_label=data_label, spectral_subset=spectral_subset, function=False) + + collapse_with_spectral2 = cubeviz_helper.get_data(data_label=data_label, + function=True) + + assert list(collapse_with_spectral.flux) == list(collapse_with_spectral2.flux) diff --git a/jdaviz/core/helpers.py b/jdaviz/core/helpers.py index 4418551b49..15e9f63a19 100644 --- a/jdaviz/core/helpers.py +++ b/jdaviz/core/helpers.py @@ -15,13 +15,14 @@ import astropy.units as u from astropy.wcs.wcsapi import BaseHighLevelWCS from astropy.nddata import CCDData +from regions.core.core import Region from glue.core import HubListener from glue.core.edit_subset_mode import NewMode from glue.core.message import SubsetCreateMessage, SubsetDeleteMessage from glue.core.subset import Subset, MaskSubsetState from glue.config import data_translator from ipywidgets.widgets import widget_serialization -from specutils import Spectrum1D +from specutils import Spectrum1D, SpectralRegion from jdaviz.app import Application @@ -426,8 +427,6 @@ def _get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, raise ValueError(f"Subset {spectral_subset} not in list of valid" f" subset names {list_of_valid_subset_names}") - # TODO: check if spectral is spectral and spatial is spatial - if data_label and data_label not in self.app.data_collection.labels: raise ValueError(f'{data_label} not in {self.app.data_collection.labels}.') elif not data_label and len(self.app.data_collection) > 1: @@ -439,7 +438,16 @@ def _get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, if cls is not None and not isclass(cls): raise TypeError( "cls in get_data must be a class or None.") + + # Check if spectral is spectral and spatial is spatial + all_subsets = self.app.get_subsets(object_only=True) data = self.app.data_collection[data_label] + if spatial_subset and not isinstance(all_subsets[spatial_subset][0], + Region): + raise ValueError(f"{spatial_subset} is not a spatial subset.") + if spectral_subset and not isinstance(all_subsets[spectral_subset], + SpectralRegion): + raise ValueError(f"{spectral_subset} is not a spectral subset.") if not cls: if 'Trace' in data.meta: @@ -484,7 +492,6 @@ def _get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, for subset in subsets.subsets: # If the subset applies to data with the same name as data_label, continue if subset.data.label == data_label: - handler, _ = data_translator.get_handler_for(cls) try: data = handler.to_object(subset, **object_kwargs) From 3b22c46572d07055f8b6de9ef9840039b2d91237 Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Tue, 23 May 2023 13:58:46 -0400 Subject: [PATCH 16/21] Fix style check --- .../configs/cubeviz/plugins/tests/test_cubeviz_helper.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py b/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py index 6429d3ca7c..037d837e96 100644 --- a/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py +++ b/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py @@ -102,11 +102,14 @@ def test_get_data_spatial_and_spectral(cubeviz_helper, spectrum1d_cube_larger): function=True) with pytest.raises(ValueError, match=f'{spectral_subset} is not a spatial subset.'): - cubeviz_helper.get_data(data_label=data_label, spatial_subset=spectral_subset, function=True) + cubeviz_helper.get_data(data_label=data_label, spatial_subset=spectral_subset, + function=True) with pytest.raises(ValueError, match=f'{spatial_subset} is not a spectral subset.'): - cubeviz_helper.get_data(data_label=data_label, spectral_subset=spatial_subset, function=True) + cubeviz_helper.get_data(data_label=data_label, spectral_subset=spatial_subset, + function=True) with pytest.raises(ValueError, match='function cannot be False if spectral_subset'): - cubeviz_helper.get_data(data_label=data_label, spectral_subset=spectral_subset, function=False) + cubeviz_helper.get_data(data_label=data_label, spectral_subset=spectral_subset, + function=False) collapse_with_spectral2 = cubeviz_helper.get_data(data_label=data_label, function=True) From d4fe3fa0238d5b27a86847585ceedb9e55a7d3c6 Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Tue, 23 May 2023 15:38:16 -0400 Subject: [PATCH 17/21] Cover case where cubeviz.get_data uses spectral subset and function --- .../plugins/tests/test_cubeviz_helper.py | 9 +-- jdaviz/configs/specviz/helper.py | 3 +- jdaviz/core/helpers.py | 77 ++++++++++--------- 3 files changed, 47 insertions(+), 42 deletions(-) diff --git a/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py b/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py index 037d837e96..d3a4363d0f 100644 --- a/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py +++ b/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py @@ -100,6 +100,10 @@ def test_get_data_spatial_and_spectral(cubeviz_helper, spectrum1d_cube_larger): collapse_with_spectral = cubeviz_helper.get_data(data_label=data_label, spectral_subset=spectral_subset, function=True) + collapse_with_spectral2 = cubeviz_helper.get_data(data_label=data_label, + function=True) + + assert list(collapse_with_spectral.flux) == list(collapse_with_spectral2.flux) with pytest.raises(ValueError, match=f'{spectral_subset} is not a spatial subset.'): cubeviz_helper.get_data(data_label=data_label, spatial_subset=spectral_subset, @@ -110,8 +114,3 @@ def test_get_data_spatial_and_spectral(cubeviz_helper, spectrum1d_cube_larger): with pytest.raises(ValueError, match='function cannot be False if spectral_subset'): cubeviz_helper.get_data(data_label=data_label, spectral_subset=spectral_subset, function=False) - - collapse_with_spectral2 = cubeviz_helper.get_data(data_label=data_label, - function=True) - - assert list(collapse_with_spectral.flux) == list(collapse_with_spectral2.flux) diff --git a/jdaviz/configs/specviz/helper.py b/jdaviz/configs/specviz/helper.py index 8f44c4f99a..2adde425c3 100644 --- a/jdaviz/configs/specviz/helper.py +++ b/jdaviz/configs/specviz/helper.py @@ -85,6 +85,7 @@ def get_spectra(self, data_label=None, subset_to_apply=None, apply_slider_redshi else: for layer_state in viewer.state.layers: lyr = layer_state.layer + print(lyr.label, type(lyr)) if subset_to_apply is not None: if lyr.label == subset_to_apply: spectrum = get_data_method(data_label=lyr.data.label, @@ -97,7 +98,7 @@ def get_spectra(self, data_label=None, subset_to_apply=None, apply_slider_redshi else: if isinstance(lyr, GroupedSubset): spectrum = get_data_method(data_label=lyr.data.label, - spectral_subset=lyr.label, + spatial_subset=lyr.label, cls=Spectrum1D, **function_kwargs) spectra[f'{lyr.data.label} ({lyr.label})'] = spectrum diff --git a/jdaviz/core/helpers.py b/jdaviz/core/helpers.py index 15e9f63a19..2a0485fc1a 100644 --- a/jdaviz/core/helpers.py +++ b/jdaviz/core/helpers.py @@ -413,6 +413,7 @@ def show_in_new_tab(self, title=None): # pragma: no cover def _get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, function=None, cls=None): + # Start validity checks list_of_valid_function_values = ('minimum', 'maximum', 'mean', 'median', 'sum') if function and function not in list_of_valid_function_values: @@ -439,15 +440,8 @@ def _get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, raise TypeError( "cls in get_data must be a class or None.") - # Check if spectral is spectral and spatial is spatial - all_subsets = self.app.get_subsets(object_only=True) + # End validity checks and start data retrieval data = self.app.data_collection[data_label] - if spatial_subset and not isinstance(all_subsets[spatial_subset][0], - Region): - raise ValueError(f"{spatial_subset} is not a spatial subset.") - if spectral_subset and not isinstance(all_subsets[spectral_subset], - SpectralRegion): - raise ValueError(f"{spectral_subset} is not a spectral subset.") if not cls: if 'Trace' in data.meta: @@ -481,40 +475,51 @@ def _get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, raise AttributeError(f"A valid cls must be provided to" f" apply subset {spectral_subset} to data. " f"Instead, {cls} was given.") - subset_to_apply = (spatial_subset if spatial_subset - else spectral_subset if spectral_subset else None) - spec_sub = None - # Loop through each subset - for subsets in self.app.data_collection.subset_groups: - # If name matches the name in subsets_to_apply, continue - if subsets.label.lower() == subset_to_apply.lower(): - # Loop through each data a subset applies to - for subset in subsets.subsets: - # If the subset applies to data with the same name as data_label, continue - if subset.data.label == data_label: - handler, _ = data_translator.get_handler_for(cls) - try: - data = handler.to_object(subset, **object_kwargs) - except Exception as e: - warnings.warn(f"Not able to get {data_label} returned with" - f" subset {subsets.label} applied of type {cls}." - f" Exception: {e}") - elif (spatial_subset and spectral_subset and - subsets.label.lower() == spectral_subset.lower()): - # Same logic as if statement - spec_sub = [spec_sub_data for spec_sub_data in subsets.subsets if - spec_sub_data.data.label == data_label][0] - # Apply spectral subset to spatial subset if applicable - if spatial_subset and spectral_subset: + + # Now we work on applying subsets to the data + all_subsets = self.app.get_subsets(object_only=True) + + # Handle spatial subset + if spatial_subset and not isinstance(all_subsets[spatial_subset][0], + Region): + raise ValueError(f"{spatial_subset} is not a spatial subset.") + elif spatial_subset: + real_spatial = [sub for subsets in self.app.data_collection.subset_groups + for sub in subsets.subsets + if sub.data.label == data_label and subsets.label == spatial_subset][0] + handler, _ = data_translator.get_handler_for(cls) + try: + data = handler.to_object(real_spatial, **object_kwargs) + except Exception as e: + warnings.warn(f"Not able to get {data_label} returned with" + f" subset {spatial_subset} applied of type {cls}." + f" Exception: {e}") + elif function: + # This covers the case where cubeviz.get_data is called using a spectral_subset + # with function set. + data = data.get_object(cls=cls, **object_kwargs) + + # Handle spectral subset, including case where spatial subset is also set + if spectral_subset and not isinstance(all_subsets[spectral_subset], + SpectralRegion): + raise ValueError(f"{spectral_subset} is not a spectral subset.") + elif spectral_subset: + real_spectral = [sub for subsets in self.app.data_collection.subset_groups + for sub in subsets.subsets + if sub.data.label == data_label and subsets.label == spectral_subset][0] # noqa + handler, _ = data_translator.get_handler_for(cls) try: - spec_subset = handler.to_object(spec_sub, **object_kwargs) + spec_subset = handler.to_object(real_spectral, **object_kwargs) except Exception as e: warnings.warn(f"Not able to get {data_label} returned with" f" subset {spectral_subset} applied of type {cls}." f" Exception: {e}") - # Return collapsed Spectrum1D object with spectral subset mask applied - data.mask = ~spec_subset.mask + if spatial_subset or function: + # Return collapsed Spectrum1D object with spectral subset mask applied + data.mask = ~spec_subset.mask + else: + data = spec_subset return data From e49baabe0289909a629665a1a1509bd79100d853 Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Tue, 23 May 2023 15:55:05 -0400 Subject: [PATCH 18/21] Fix bug with get_spectra --- jdaviz/configs/specviz/helper.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/jdaviz/configs/specviz/helper.py b/jdaviz/configs/specviz/helper.py index 2adde425c3..c2a918b681 100644 --- a/jdaviz/configs/specviz/helper.py +++ b/jdaviz/configs/specviz/helper.py @@ -1,6 +1,7 @@ import warnings from astropy import units as u +from regions.core.core import Region from glue.core.subset_group import GroupedSubset from specutils import SpectralRegion, Spectrum1D @@ -76,6 +77,7 @@ def get_spectra(self, data_label=None, subset_to_apply=None, apply_slider_redshi get_data_method = self.app._jdaviz_helper.get_data viewer = self.app.get_viewer(self._default_spectrum_viewer_reference_name) function_kwargs = {'function': getattr(viewer.state, "function")} if self.app.config == 'cubeviz' else {} # noqa + all_subsets = self.app.get_subsets(object_only=True) if data_label is not None: spectrum = get_data_method(data_label=data_label, @@ -85,7 +87,6 @@ def get_spectra(self, data_label=None, subset_to_apply=None, apply_slider_redshi else: for layer_state in viewer.state.layers: lyr = layer_state.layer - print(lyr.label, type(lyr)) if subset_to_apply is not None: if lyr.label == subset_to_apply: spectrum = get_data_method(data_label=lyr.data.label, @@ -96,12 +97,20 @@ def get_spectra(self, data_label=None, subset_to_apply=None, apply_slider_redshi else: continue else: - if isinstance(lyr, GroupedSubset): + if (isinstance(lyr, GroupedSubset) and lyr.label in all_subsets.keys() and + isinstance(all_subsets[lyr.label][0], Region)): spectrum = get_data_method(data_label=lyr.data.label, spatial_subset=lyr.label, cls=Spectrum1D, **function_kwargs) spectra[f'{lyr.data.label} ({lyr.label})'] = spectrum + elif (isinstance(lyr, GroupedSubset) and lyr.label in all_subsets.keys() and + isinstance(all_subsets[lyr.label], SpectralRegion)): + spectrum = get_data_method(data_label=lyr.data.label, + spectral_subset=lyr.label, + cls=Spectrum1D, + **function_kwargs) + spectra[f'{lyr.data.label} ({lyr.label})'] = spectrum else: spectrum = get_data_method(data_label=lyr.label, cls=Spectrum1D, From 43a342ff957e889800ab04e01379e1f75aad77c6 Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Tue, 23 May 2023 16:51:47 -0400 Subject: [PATCH 19/21] Switch mask to be False where spectral subset is applied --- jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py | 4 ++-- jdaviz/core/helpers.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py b/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py index d3a4363d0f..c4229448a2 100644 --- a/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py +++ b/jdaviz/configs/cubeviz/plugins/tests/test_cubeviz_helper.py @@ -85,8 +85,8 @@ def test_get_data_spatial_and_spectral(cubeviz_helper, spectrum1d_cube_larger): spatial_subset=spatial_subset, spectral_subset=spectral_subset) assert spatial_with_spec.flux.ndim == 1 - assert list(spatial_with_spec.mask) == [False, False, True, True, False, - False, False, False, False, False] + assert list(spatial_with_spec.mask) == [True, True, False, False, True, + True, True, True, True, True] assert max(list(spatial_with_spec.flux.value)) == 157. assert min(list(spatial_with_spec.flux.value)) == 13. diff --git a/jdaviz/core/helpers.py b/jdaviz/core/helpers.py index 2a0485fc1a..c6759786c9 100644 --- a/jdaviz/core/helpers.py +++ b/jdaviz/core/helpers.py @@ -517,7 +517,7 @@ def _get_data(self, data_label=None, spatial_subset=None, spectral_subset=None, f" Exception: {e}") if spatial_subset or function: # Return collapsed Spectrum1D object with spectral subset mask applied - data.mask = ~spec_subset.mask + data.mask = spec_subset.mask else: data = spec_subset From e84a308c9d3f5e18c9b0b1091af33b841006de42 Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Wed, 24 May 2023 09:48:10 -0400 Subject: [PATCH 20/21] Add get_data to mosviz --- jdaviz/configs/mosviz/helper.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/jdaviz/configs/mosviz/helper.py b/jdaviz/configs/mosviz/helper.py index eefc35a968..8d16f085a7 100644 --- a/jdaviz/configs/mosviz/helper.py +++ b/jdaviz/configs/mosviz/helper.py @@ -1076,3 +1076,25 @@ def get_spectrum_2d(self, row=None, apply_slider_redshift="Warn"): `~specutils.Spectrum1D` """ return self._get_spectrum('2D Spectra', row, apply_slider_redshift) + + def get_data(self, data_label=None, spectral_subset=None, cls=None): + """ + Returns data with name equal to data_label of type cls with subsets applied from + spectral_subset. + + Parameters + ---------- + data_label : str, optional + Provide a label to retrieve a specific data set from data_collection. + spectral_subset : str, optional + Spectral subset applied to data. + cls : `~specutils.Spectrum1D`, `~astropy.nddata.CCDData`, optional + The type that data will be returned as. + + Returns + ------- + data : cls + Data is returned as type cls with subsets applied. + + """ + return self._get_data(data_label=data_label, spectral_subset=spectral_subset, cls=cls) From 155bc857eda3ad0584374b8dbfd7db9d52e38b80 Mon Sep 17 00:00:00 2001 From: Jesse Averbukh Date: Wed, 24 May 2023 13:30:51 -0400 Subject: [PATCH 21/21] Update change file --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 91b8ccdc1a..be85848478 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -20,6 +20,9 @@ Cubeviz - ``get_data`` now supports ``function=True`` to adopt the collapse-function from the spectrum viewer. [#2117] +- ``get_data`` now supports applying a spectral mask to a collapse spatial subset. [#2199] + + Imviz ^^^^^