Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add composite subset fixes #2291

Merged
merged 6 commits into from
Jul 12, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ Cubeviz
- Moment Map plugin now writes FITS file to working directory if no path provided
in standalone mode. [#2264]

- Fixes detection of spatial vs spectral subsets for composite subsets. [#2207, #2266, #2291]

Imviz
^^^^^

Expand Down
19 changes: 14 additions & 5 deletions jdaviz/configs/cubeviz/plugins/viewers.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from glue.core import BaseData
from glue.core.subset import RoiSubsetState, RangeSubsetState
from glue_jupyter.bqplot.image import BqplotImageView

from jdaviz.core.registries import viewer_registry
from jdaviz.core.marks import SliceIndicatorMarks, ShadowSpatialSpectral
from jdaviz.configs.cubeviz.helper import layer_is_cube_image_data
from jdaviz.configs.default.plugins.viewers import JdavizViewerMixin
from jdaviz.configs.specviz.plugins.viewers import SpecvizProfileView
from jdaviz.utils import get_subset_type

__all__ = ['CubevizImageView', 'CubevizProfileView']

Expand Down Expand Up @@ -108,15 +108,23 @@ def __init__(self, *args, **kwargs):
def _is_spatial_subset(self, layer):
# spatial subset layers will have the same data-label as the collapsed flux cube
ref_data_label = self.state.reference_data.label
return (isinstance(getattr(layer.layer, 'subset_state', None), RoiSubsetState)

subset_state = getattr(layer.layer, 'subset_state', None)
if subset_state is None:
return False
return (get_subset_type(subset_state) == 'spatial'
and layer.layer.data.label == ref_data_label)

def _get_spatial_subset_layers(self):
return [ls for ls in self.state.layers if self._is_spatial_subset(ls)]

def _is_spectral_subset(self, layer):
ref_data_label = self.layers[0].layer.data.label
return (isinstance(getattr(layer.layer, 'subset_state', None), RangeSubsetState)

subset_state = getattr(layer.layer, 'subset_state', None)
if subset_state is None:
return False
return (get_subset_type(subset_state) == 'spectral'
and layer.layer.data.label == ref_data_label)

def _get_spectral_subset_layers(self):
Expand Down Expand Up @@ -152,14 +160,15 @@ def _expected_subset_layer_default(self, layer_state):
"""
super()._expected_subset_layer_default(layer_state)

if not (self._is_spatial_subset(layer_state) or self._is_spectral_subset(layer_state)):
subset_type = get_subset_type(layer_state.layer)
if subset_type is None:
return

this_mark = self._get_marks_for_layers([layer_state])[0]

new_marks = []

if isinstance(layer_state.layer.subset_state, RoiSubsetState):
if subset_type == 'spatial':
layer_state.linewidth = 1

# need to add marks for every intersection between THIS spatial subset and ALL spectral
Expand Down
6 changes: 3 additions & 3 deletions jdaviz/configs/default/plugins/viewers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import numpy as np

from glue.core.subset import RoiSubsetState
from glue_jupyter.bqplot.profile import BqplotProfileView
from glue_jupyter.bqplot.image import BqplotImageView
from glue_jupyter.bqplot.scatter.layer_artist import BqplotScatterLayerState
Expand All @@ -9,7 +8,7 @@
from jdaviz.configs.imviz.helper import layer_is_image_data
from jdaviz.components.toolbar_nested import NestedJupyterToolbar
from jdaviz.core.registries import viewer_registry
from jdaviz.utils import ColorCycler
from jdaviz.utils import ColorCycler, get_subset_type

__all__ = ['JdavizViewerMixin']

Expand Down Expand Up @@ -112,7 +111,8 @@ def _get_layer_info(layer):
# want to include the collapse function *unless* the layer is a spectral subset
for subset in self.jdaviz_app.data_collection.subset_groups:
if subset.label == layer.layer.label:
if isinstance(subset.subset_state, RoiSubsetState):
subset_type = get_subset_type(subset)
if subset_type == 'spatial':
return "mdi-chart-scatter-plot", suffix
else:
return "mdi-chart-bell-curve", ""
Expand Down
8 changes: 6 additions & 2 deletions jdaviz/configs/imviz/plugins/coords_info/coords_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

from astropy import units as u
from glue.core import BaseData
from glue.core.subset import RoiSubsetState
from glue.core.subset_group import GroupedSubset
from glue_jupyter.bqplot.image.layer_artist import BqplotImageSubsetLayerArtist

Expand All @@ -17,6 +16,7 @@
from jdaviz.core.marks import PluginScatter
from jdaviz.core.registries import tool_registry
from jdaviz.core.template_mixin import TemplateMixin, DatasetSelectMixin
from jdaviz.utils import get_subset_type

__all__ = ['CoordsInfo']

Expand Down Expand Up @@ -443,7 +443,11 @@
continue

if isinstance(lyr.layer, GroupedSubset):
if not isinstance(lyr.layer.subset_state, RoiSubsetState):
subset_state = getattr(lyr.layer, 'subset_state', None)
if subset_state is None:
return False

Check warning on line 448 in jdaviz/configs/imviz/plugins/coords_info/coords_info.py

View check run for this annotation

Codecov / codecov/patch

jdaviz/configs/imviz/plugins/coords_info/coords_info.py#L448

Added line #L448 was not covered by tests
javerbukh marked this conversation as resolved.
Show resolved Hide resolved
subset_type = get_subset_type(subset_state)
if subset_type == 'spectral':
# then this is a SPECTRAL subset
continue
# For use later in data retrieval
Expand Down
3 changes: 2 additions & 1 deletion jdaviz/configs/specviz/plugins/viewers.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from jdaviz.core.linelists import load_preset_linelist, get_available_linelists
from jdaviz.core.freezable_state import FreezableProfileViewerState
from jdaviz.configs.default.plugins.viewers import JdavizViewerMixin
from jdaviz.utils import get_subset_type

__all__ = ['SpecvizProfileView']

Expand Down Expand Up @@ -377,7 +378,7 @@ def add_data(self, data, color=None, alpha=None, **layer_state):
# that new data entries (from model fitting or gaussian smooth, etc) will only be spectra
# and all subsets affected will be spectral
for layer in self.state.layers:
if "Subset" in layer.layer.label and layer.layer.data.label == data.label:
if get_subset_type(layer.layer) == 'spectral' and layer.layer.data.label == data.label:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think get_subset_type assumes the input is a subset... does the fact that this works depend on the assumption that spectral is defined first in that function (do we need some way to still detect if the layer is a subset at all vs actual data)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_subset_type has a check to start if the layer.layer object has attribute "subset_state" and if not it returns None. I added a check to this if statement though to make it more clear that this should only accept layer's associated with subsets.

layer.linewidth = 3

return result
Expand Down
9 changes: 5 additions & 4 deletions jdaviz/core/template_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from jdaviz.core.events import (AddDataMessage, RemoveDataMessage,
ViewerAddedMessage, ViewerRemovedMessage)
from jdaviz.core.user_api import UserApiWrapper, PluginUserApi
from jdaviz.utils import get_subset_type


__all__ = ['show_widget', 'TemplateMixin', 'PluginTemplateMixin',
Expand Down Expand Up @@ -1014,8 +1015,8 @@ def _subset_to_dict(self, subset):
for layer in viewer.layers:
if layer.layer.label == subset.label:
color = layer.state.color
subset_type = _subset_type(subset)
return {"label": subset.label, "color": color, "type": subset_type}
type = get_subset_type(subset)
return {"label": subset.label, "color": color, "type": type}
return {"label": subset.label, "color": False, "type": False}

def _delete_subset(self, subset):
Expand Down Expand Up @@ -1511,7 +1512,7 @@ def _cubeviz_include_spatial_subsets(self):
# for changes in style, etc, we'll try to filter out extra messages in advance.
def _subset_update(msg):
if msg.attribute == 'subset_state':
if _subset_type(msg.subset) == 'spatial':
if get_subset_type(msg.subset) == 'spatial':
self._on_data_changed()

self.hub.subscribe(self, SubsetUpdateMessage,
Expand Down Expand Up @@ -1624,7 +1625,7 @@ def _dc_to_dict(data):
if getattr(self, '_include_spatial_subsets', False):
# allow for spatial subsets to be listed
self.items = self.items + [_dc_to_dict(subset) for subset in self.app.data_collection.subset_groups # noqa
if _subset_type(subset) == 'spatial']
if get_subset_type(subset) == 'spatial']
self._apply_default_selection()
# future improvement: only clear cache if the selected data entry was changed?
self._clear_cache(*self._cached_properties)
Expand Down
4 changes: 2 additions & 2 deletions jdaviz/tests/test_subsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ def test_region_spectral_spatial(cubeviz_helper, spectral_cube_wcs):
flux_viewer.toolbar.active_tool = flux_viewer.toolbar.tools['bqplot:rectangle']
flux_viewer.apply_roi(RectangularROI(1, 3.5, -0.2, 3.3))

assert len([m for m in spectrum_viewer.figure.marks if isinstance(m, ShadowSpatialSpectral)]) == 1 # noqa
assert len([m for m in spectrum_viewer.figure.marks if isinstance(m, ShadowSpatialSpectral)]) == 2 # noqa
Comment on lines -202 to +204
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this (and the next set of changes to line 229) is only temporary until #2292 is addressed, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming Gaussian Smooth stays a cube, this is the correct number for the amount of ShadowSpatialSpectral marks. A spatial subset is applied to the flux cube AND the smoothed cube, which creates two collapsed spectra in the spectrum viewer. Each of those spectra then has a spectral subset applied to them, creating 2 shadow marks. If you add another spectral subset, that number goes up to 4. If you delete the smooth cube, that number goes back down to 2 since you still have the flux cube's spatial subset intersecting with the two spectral subsets.


subsets = cubeviz_helper.app.get_subsets(spectral_only=True)
reg = subsets.get('Subset 1')
Expand All @@ -226,7 +226,7 @@ def test_region_spectral_spatial(cubeviz_helper, spectral_cube_wcs):
spectrum_viewer.toolbar.active_tool = spectrum_viewer.toolbar.tools['jdaviz:panzoom']
spectrum_viewer.toolbar.active_tool = spectrum_viewer.toolbar.tools['bqplot:xrange']
spectrum_viewer.apply_roi(XRangeROI(3, 16))
assert len([m for m in spectrum_viewer.figure.marks if isinstance(m, ShadowSpatialSpectral)]) == 2 # noqa
assert len([m for m in spectrum_viewer.figure.marks if isinstance(m, ShadowSpatialSpectral)]) == 4 # noqa


def test_disjoint_spatial_subset(cubeviz_helper, spectral_cube_wcs):
Expand Down
33 changes: 32 additions & 1 deletion jdaviz/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
from astropy.io import fits
from ipyvue import watch
from glue.config import settings
from glue.core.subset import RangeSubsetState, RoiSubsetState


__all__ = ['SnackbarQueue', 'enable_hot_reloading', 'bqplot_clear_figure',
'standardize_metadata', 'ColorCycler', 'alpha_index']
'standardize_metadata', 'ColorCycler', 'alpha_index', 'get_subset_type']

# For Metadata Viewer plugin internal use only.
PRIHDR_KEY = '_primary_header'
Expand Down Expand Up @@ -259,3 +261,32 @@ def __call__(self):

def reset(self):
self.counter = -1


def get_subset_type(subset):
"""
Determine the subset type of a subset or layer

Parameters
----------
subset : should have ``subset_state`` as an attribute, otherwise will return ``None``.
javerbukh marked this conversation as resolved.
Show resolved Hide resolved

Returns
-------
subset_type : str or None
'spatial', 'spectral', or None
"""
if not hasattr(subset, 'subset_state'):
return None

while hasattr(subset.subset_state, 'state1'):
# this assumes no mixing between spatial and spectral subsets and just
# taking the first component (down the hierarchical tree) to determine the type
subset = subset.subset_state.state1

if isinstance(subset.subset_state, RoiSubsetState):
return 'spatial'
elif isinstance(subset.subset_state, RangeSubsetState):
return 'spectral'
else:
return None
Loading