Source code for jdaviz.configs.default.plugins.subset_plugin.subset_plugin

from glue.core.message import EditSubsetMessage, SubsetUpdateMessage
from glue.core.edit_subset_mode import (AndMode, AndNotMode, OrMode,
                                        ReplaceMode, XorMode)
from glue.core.subset import RoiSubsetState, RangeSubsetState, CompositeSubsetState
from glue_jupyter.widgets.subset_mode_vuetify import SelectionModeMenu
from traitlets import List, Unicode, Bool, observe

from jdaviz.core.registries import tray_registry
from jdaviz.core.template_mixin import TemplateMixin, SubsetSelect

__all__ = ['SubsetPlugin']

SUBSET_MODES = {
    'replace': ReplaceMode,
    'add': OrMode,
    'and': AndMode,
    'xor': XorMode,
    'remove': AndNotMode
}


[docs]@tray_registry('g-subset-plugin', label="Subset Tools") class SubsetPlugin(TemplateMixin): template_file = __file__, "subset_plugin.vue" select = List([]).tag(sync=True) subset_items = List([]).tag(sync=True) subset_selected = Unicode("Create new").tag(sync=True) mode_selected = Unicode('add').tag(sync=True) show_region_info = Bool(True).tag(sync=True) subset_types = List([]).tag(sync=True) subset_definitions = List([]).tag(sync=True) has_subset_details = Bool(False).tag(sync=True) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.components = { 'g-subset-mode': SelectionModeMenu(session=self.session) } self.session.hub.subscribe(self, EditSubsetMessage, handler=self._sync_selected_from_state) self.session.hub.subscribe(self, SubsetUpdateMessage, handler=self._on_subset_update) self.subset_select = SubsetSelect(self, 'subset_items', 'subset_selected', default_text="Create New") def _sync_selected_from_state(self, *args): if not hasattr(self, 'subset_select'): # during initial init, this can trigger before the component is initialized return if self.session.edit_subset_mode.edit_subset == []: if self.subset_selected != self.subset_select.default_text: self.subset_selected = self.subset_select.default_text self.show_region_info = False else: new_label = self.session.edit_subset_mode.edit_subset[0].label if new_label != self.subset_selected: if new_label not in [s['label'] for s in self.subset_items]: self._sync_available_from_state() self.subset_selected = self.session.edit_subset_mode.edit_subset[0].label self.show_region_info = True def _on_subset_update(self, *args): self._sync_selected_from_state(*args) self._get_subset_definition(*args) subset_to_update = self.session.edit_subset_mode.edit_subset[0] self.subset_select._update_subset(subset_to_update, attribute="type") def _sync_available_from_state(self, *args): if not hasattr(self, 'subset_select'): # during initial init, this can trigger before the component is initialized return self.subset_items = [{'label': self.subset_select.default_text}] + [ self.subset_select._subset_to_dict(subset) for subset in self.data_collection.subset_groups] @observe('subset_selected') def _sync_selected_from_ui(self, change): if not hasattr(self, 'subset_select'): # during initial init, this can trigger before the component is initialized return if change['new'] != self.subset_select.default_text: self._get_subset_definition(change['new']) self.show_region_info = change['new'] != self.subset_select.default_text m = [s for s in self.app.data_collection.subset_groups if s.label == change['new']] if m != self.session.edit_subset_mode.edit_subset: self.session.edit_subset_mode.edit_subset = m ''' # This will be needed once we use a dropdown instead of the actual # g-subset-mode component @observe("mode_selected") def _mode_selected_changed(self, event={}): if self.session.edit_subset_mode != self.mode_selected: self.session.edit_subset_mode = self.mode_selected ''' def _unpack_nested_subset(self, subset_state): ''' Navigate through the tree of subset states for composite subsets made up of multiple regions. ''' if isinstance(subset_state, CompositeSubsetState): self._unpack_nested_subset(subset_state.state1) self._unpack_nested_subset(subset_state.state2) else: if subset_state is not None: self._get_subset_subregion_definition(subset_state) def _get_subset_subregion_definition(self, subset_state): """ Get the type and parameters for a single region in the subset. Note that the string type and operation (if in a composite subset) need to be stored separately from the float parameters for display reasons. """ subset_type = {} subset_definition = None if isinstance(subset_state, RoiSubsetState): subset_classname = subset_state.roi.__class__.__name__ if subset_classname == "CircularROI": x, y = subset_state.roi.get_center() subset_definition = {"X Center": x, "Y Center": y, "Radius": subset_state.roi.radius} elif subset_classname == "RectangularROI": subset_definition = {} for att in ("Xmin", "Xmax", "Ymin", "Ymax"): subset_definition[att] = getattr(subset_state.roi, att.lower()) elif subset_classname == "EllipticalROI": subset_definition = {"X Center": subset_state.roi.xc, "Y Center": subset_state.roi.yc, "X Radius": subset_state.roi.radius_x, "Y Radius": subset_state.roi.radius_y} subset_type["Subset type"] = subset_classname elif isinstance(subset_state, RangeSubsetState): subset_definition = {"Upper bound": subset_state.hi, "Lower bound": subset_state.lo} subset_type["Subset type"] = "Range" if subset_definition is not None and subset_definition not in self.subset_definitions: self.subset_definitions = self.subset_definitions + [subset_definition] self.subset_types = self.subset_types + [subset_type] def _get_subset_definition(self, *args): """ Retrieve the parameters defining the selected subset, for example the upper and lower bounds for a simple spectral subset. """ self.subset_definitions = [] self.subset_types = [] subset_group = [s for s in self.app.data_collection.subset_groups if s.label == self.subset_selected][0] subset_state = subset_group.subset_state self._unpack_nested_subset(subset_state)