diff --git a/jdaviz/configs/default/plugins/subset_plugin/subset_plugin.py b/jdaviz/configs/default/plugins/subset_plugin/subset_plugin.py
index b1e00c65ef..9b84929adb 100644
--- a/jdaviz/configs/default/plugins/subset_plugin/subset_plugin.py
+++ b/jdaviz/configs/default/plugins/subset_plugin/subset_plugin.py
@@ -7,8 +7,9 @@
from glue.core.message import EditSubsetMessage, SubsetUpdateMessage
from glue.core.edit_subset_mode import (AndMode, AndNotMode, OrMode,
ReplaceMode, XorMode)
+from glue.core.exceptions import IncompatibleAttribute
from glue.core.roi import CircularROI, CircularAnnulusROI, EllipticalROI, RectangularROI
-from glue.core.subset import RoiSubsetState, RangeSubsetState, CompositeSubsetState
+from glue.core.subset import SubsetState, RoiSubsetState, RangeSubsetState, CompositeSubsetState
from glue.icons import icon_path
from glue_jupyter.widgets.subset_mode_vuetify import SelectionModeMenu
from glue_jupyter.common.toolbar_vuetify import read_icon
@@ -32,6 +33,44 @@
}
+class MultiMaskSubsetState(SubsetState):
+ """
+ A subset state that can include a different mask for different datasets.
+ Adopted from https://github.com/glue-viz/glue/pull/2415
+
+ Parameters
+ ----------
+ masks : dict
+ A dictionary mapping data UUIDs to boolean arrays with the same
+ dimensions as the data arrays.
+ """
+
+ def __init__(self, masks=None):
+ super(MultiMaskSubsetState, self).__init__()
+ self._masks = masks
+
+ def to_mask(self, data, view=None):
+ if data.uuid in self._masks:
+ mask = self._masks[data.uuid]
+ if view is not None:
+ mask = mask[view]
+ return mask
+ else:
+ raise IncompatibleAttribute()
+
+ def copy(self):
+ return MultiMaskSubsetState(masks=self._masks)
+
+ def __gluestate__(self, context):
+ serialized = {key: context.do(value) for key, value in self._masks.items()}
+ return {'masks': serialized}
+
+ @classmethod
+ def __setgluestate__(cls, rec, context):
+ masks = {key: context.object(value) for key, value in rec['masks'].items()}
+ return cls(masks=masks)
+
+
@tray_registry('g-subset-plugin', label="Subset Tools")
class SubsetPlugin(PluginTemplateMixin, DatasetSelectMixin):
template_file = __file__, "subset_plugin.vue"
@@ -51,6 +90,7 @@ class SubsetPlugin(PluginTemplateMixin, DatasetSelectMixin):
multiselect = Bool(False).tag(sync=True)
is_centerable = Bool(False).tag(sync=True)
can_simplify = Bool(False).tag(sync=True)
+ can_freeze = Bool(False).tag(sync=True)
icon_replace = Unicode(read_icon(os.path.join(icon_path("glue_replace", icon_format="svg")), 'svg+xml')).tag(sync=True) # noqa
icon_or = Unicode(read_icon(os.path.join(icon_path("glue_or", icon_format="svg")), 'svg+xml')).tag(sync=True) # noqa
@@ -258,6 +298,16 @@ def _get_subset_definition(self, *args):
self._unpack_get_subsets_for_ui()
+ def vue_freeze_subset(self, *args):
+ sgs = {sg.label: sg for sg in self.app.data_collection.subset_groups}
+ sg = sgs.get(self.subset_selected)
+
+ masks = {}
+ for data in self.app.data_collection:
+ masks[data.uuid] = sg.subset_state.to_mask(data)
+
+ sg.subset_state = MultiMaskSubsetState(masks)
+
def vue_simplify_subset(self, *args):
if self.multiselect:
self.hub.broadcast(SnackbarMessage("Cannot simplify spectral subset "
diff --git a/jdaviz/configs/default/plugins/subset_plugin/subset_plugin.vue b/jdaviz/configs/default/plugins/subset_plugin/subset_plugin.vue
index 14060d4135..36284ed71f 100644
--- a/jdaviz/configs/default/plugins/subset_plugin/subset_plugin.vue
+++ b/jdaviz/configs/default/plugins/subset_plugin/subset_plugin.vue
@@ -113,10 +113,13 @@
-
- Simplify
-
- Update
-
+
+ Freeze
+
+
+ Simplify
+
+ Update
+