From 4e5e2a6c08061f90d247835b0c3d3249369c40c4 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Mon, 12 Feb 2024 14:20:51 -0500 Subject: [PATCH] exclude WCS-only layer subsets from plot options * both sync state and the visibility mixed state for the viewer select tabs --- jdaviz/app.py | 11 +++++----- .../plugins/plot_options/plot_options.py | 8 +++----- jdaviz/configs/default/plugins/viewers.py | 4 ++-- jdaviz/configs/imviz/helper.py | 12 +++++------ .../imviz/plugins/orientation/orientation.py | 7 ++++--- jdaviz/configs/imviz/plugins/parsers.py | 6 +++--- jdaviz/configs/imviz/wcs_utils.py | 3 ++- jdaviz/core/template_mixin.py | 8 +++----- jdaviz/utils.py | 20 +++++++++++++++++++ 9 files changed, 47 insertions(+), 32 deletions(-) diff --git a/jdaviz/app.py b/jdaviz/app.py index d987af1050..4b210c84ec 100644 --- a/jdaviz/app.py +++ b/jdaviz/app.py @@ -51,7 +51,7 @@ data_parser_registry) from jdaviz.core.tools import ICON_DIR from jdaviz.utils import (SnackbarQueue, alpha_index, data_has_valid_wcs, layer_is_table_data, - MultiMaskSubsetState) + MultiMaskSubsetState, _wcs_only_label) __all__ = ['Application', 'ALL_JDAVIZ_CONFIGS'] @@ -306,7 +306,6 @@ def __init__(self, configuration=None, *args, **kwargs): self.auto_link = kwargs.pop('auto_link', True) # Imviz linking - self._wcs_only_label = "_WCS_ONLY" self._link_type = 'pixels' if self.config == "imviz": self._wcs_use_affine = None @@ -470,7 +469,7 @@ def _color_to_level(color): def _on_layers_changed(self, msg): if hasattr(msg, 'data'): layer_name = msg.data.label - is_wcs_only = msg.data.meta.get(self._wcs_only_label, False) + is_wcs_only = msg.data.meta.get(_wcs_only_label, False) elif hasattr(msg, 'subset'): layer_name = msg.subset.label is_wcs_only = False @@ -1947,7 +1946,7 @@ def set_data_visibility(self, viewer_reference, data_label, visible=True, replac # set visibility state of all applicable layers for layer in viewer.layers: - layer_is_wcs_only = getattr(layer.layer, 'meta', {}).get(self._wcs_only_label, False) + layer_is_wcs_only = getattr(layer.layer, 'meta', {}).get(_wcs_only_label, False) if layer.layer.data.label == data_label: if layer_is_wcs_only: layer.visible = False @@ -1976,7 +1975,7 @@ def set_data_visibility(self, viewer_reference, data_label, visible=True, replac # remove WCS-only data from selected items, add to wcs_only_layers: for layer in viewer.layers: - layer_is_wcs_only = getattr(layer.layer, 'meta', {}).get(self._wcs_only_label, False) + layer_is_wcs_only = getattr(layer.layer, 'meta', {}).get(_wcs_only_label, False) if layer.layer.data.label == data_label and layer_is_wcs_only: layer.visible = False if data_label not in viewer.state.wcs_only_layers: @@ -2100,7 +2099,7 @@ def _on_data_deleted(self, msg): def _create_data_item(self, data): ndims = len(data.shape) wcsaxes = data.meta.get('WCSAXES', None) - wcs_only = data.meta.get(self._wcs_only_label, False) + wcs_only = data.meta.get(_wcs_only_label, False) if wcsaxes is None: # then we'll need to determine type another way, we want to avoid # this when we can though since its not as cheap diff --git a/jdaviz/configs/default/plugins/plot_options/plot_options.py b/jdaviz/configs/default/plugins/plot_options/plot_options.py index ca5600580c..b079c8cca3 100644 --- a/jdaviz/configs/default/plugins/plot_options/plot_options.py +++ b/jdaviz/configs/default/plugins/plot_options/plot_options.py @@ -28,6 +28,8 @@ from jdaviz.core.user_api import PluginUserApi from jdaviz.core.tools import ICON_DIR from jdaviz.core.custom_traitlets import IntHandleEmpty +from jdaviz.utils import is_not_wcs_only + from scipy.interpolate import PchipInterpolator @@ -388,10 +390,6 @@ def __init__(self, *args, **kwargs): self.layer = LayerSelect(self, 'layer_items', 'layer_selected', 'viewer_selected', 'layer_multiselect') - def is_not_wcs_only(layer): - # exclude WCS-only layers from the layer choices: - return not getattr(layer.layer, 'meta', {}).get(self.app._wcs_only_label, False) - self.layer.filters += [is_not_wcs_only] self.swatches_palette = [ @@ -427,7 +425,7 @@ def not_image_or_spatial_subset(state): return not is_image(state) and not is_spatial_subset(state) def is_spatial_subset(state): - return isinstance(state, ImageSubsetLayerState) + return isinstance(state, ImageSubsetLayerState) and is_not_wcs_only(state.layer) def is_not_subset(state): return not is_spatial_subset(state) diff --git a/jdaviz/configs/default/plugins/viewers.py b/jdaviz/configs/default/plugins/viewers.py index 6fdfe84108..415d844c91 100644 --- a/jdaviz/configs/default/plugins/viewers.py +++ b/jdaviz/configs/default/plugins/viewers.py @@ -11,7 +11,7 @@ from jdaviz.core.astrowidgets_api import AstrowidgetsImageViewerMixin from jdaviz.core.registries import viewer_registry from jdaviz.core.user_api import ViewerUserApi -from jdaviz.utils import ColorCycler, get_subset_type +from jdaviz.utils import ColorCycler, get_subset_type, _wcs_only_label __all__ = ['JdavizViewerMixin'] @@ -215,7 +215,7 @@ def _get_layer_info(layer): for layer in self.state.layers[::-1]: layer_is_wcs_only = ( hasattr(layer.layer, 'meta') and - layer.layer.meta.get(self.jdaviz_app._wcs_only_label, False) + layer.layer.meta.get(_wcs_only_label, False) ) if layer.visible and not layer_is_wcs_only: prefix_icon, suffix = _get_layer_info(layer) diff --git a/jdaviz/configs/imviz/helper.py b/jdaviz/configs/imviz/helper.py index 39c3028d84..b371f18651 100644 --- a/jdaviz/configs/imviz/helper.py +++ b/jdaviz/configs/imviz/helper.py @@ -15,7 +15,7 @@ from jdaviz.configs.imviz.wcs_utils import ( _get_rotated_nddata_from_label, get_compass_info ) -from jdaviz.utils import data_has_valid_wcs +from jdaviz.utils import data_has_valid_wcs, _wcs_only_label __all__ = ['Imviz'] @@ -191,7 +191,7 @@ def load_data(self, data, data_label=None, show_in_viewer=True, **kwargs): if label not in prev_data_labels: applied_labels.append(label) applied_visible.append(True) - layer_is_wcs_only.append(data.meta.get(self.app._wcs_only_label, False)) + layer_is_wcs_only.append(data.meta.get(_wcs_only_label, False)) layer_has_wcs.append(data_has_valid_wcs(data)) if show_in_viewer is True: @@ -404,14 +404,12 @@ def layer_is_2d(layer): return isinstance(layer, BaseData) and layer.ndim == 2 -# NOTE: Sync with app._wcs_only_label as needed. def layer_is_image_data(layer): - return layer_is_2d(layer) and not layer.meta.get("_WCS_ONLY", False) + return layer_is_2d(layer) and not layer.meta.get(_wcs_only_label, False) -# NOTE: Sync with app._wcs_only_label as needed. def layer_is_wcs_only(layer): - return layer_is_2d(layer) and layer.meta.get("_WCS_ONLY", False) + return layer_is_2d(layer) and layer.meta.get(_wcs_only_label, False) def get_wcs_only_layer_labels(app): @@ -549,7 +547,7 @@ def link_image_data(app, link_type='pixels', wcs_fallback_scheme=None, wcs_use_a data_already_linked = [] if link_type == app._link_type and wcs_use_affine == app._wcs_use_affine: for link in app.data_collection.external_links: - if link.data1.label != app._wcs_only_label: + if link.data1.label != _wcs_only_label: data_already_linked.append(link.data2) else: for viewer in app._viewer_store.values(): diff --git a/jdaviz/configs/imviz/plugins/orientation/orientation.py b/jdaviz/configs/imviz/plugins/orientation/orientation.py index 3e96bfa300..ef9d095098 100644 --- a/jdaviz/configs/imviz/plugins/orientation/orientation.py +++ b/jdaviz/configs/imviz/plugins/orientation/orientation.py @@ -22,6 +22,7 @@ PluginTemplateMixin, SelectPluginComponent, LayerSelect, ViewerSelectMixin, AutoTextField ) from jdaviz.core.user_api import PluginUserApi +from jdaviz.utils import _wcs_only_label __all__ = ['Orientation'] @@ -230,7 +231,7 @@ def _update_link(self, msg={}): data_in_viewer = self.app.get_viewer(viewer_selected.reference).data() for data in self.app.data_collection: - is_wcs_only = data.meta.get(self.app._wcs_only_label, False) + is_wcs_only = data.meta.get(_wcs_only_label, False) has_wcs = hasattr(data.coords, 'pixel_to_world') if not is_wcs_only: if data in data_in_viewer and wcs_linked and not has_wcs: @@ -395,11 +396,11 @@ def _send_wcs_layers_to_all_viewers(self, *args, **kwargs): def _on_data_add_to_viewer(self, msg): all_wcs_only_layers = all( - layer.layer.meta.get(self.app._wcs_only_label) + layer.layer.meta.get(_wcs_only_label) for layer in self.viewer.selected_obj.layers if hasattr(layer.layer, "meta") ) - if all_wcs_only_layers and msg.data.meta.get(self.app._wcs_only_label, False): + if all_wcs_only_layers and msg.data.meta.get(_wcs_only_label, False): # on adding first data layer, reset the limits: self.viewer.selected_obj.state.reset_limits() diff --git a/jdaviz/configs/imviz/plugins/parsers.py b/jdaviz/configs/imviz/plugins/parsers.py index 89dac72771..7228ae5079 100644 --- a/jdaviz/configs/imviz/plugins/parsers.py +++ b/jdaviz/configs/imviz/plugins/parsers.py @@ -14,7 +14,7 @@ from jdaviz.core.registries import data_parser_registry from jdaviz.core.events import SnackbarMessage -from jdaviz.utils import standardize_metadata, PRIHDR_KEY +from jdaviz.utils import standardize_metadata, PRIHDR_KEY, _wcs_only_label try: from roman_datamodels import datamodels as rdd @@ -146,7 +146,7 @@ def get_image_data_iterator(app, file_obj, data_label, ext=None): data_iter = _hdu_to_glue_data(file_obj, data_label) elif isinstance(file_obj, NDData): - if file_obj.meta.get(app._wcs_only_label, False): + if file_obj.meta.get(_wcs_only_label, False): data_iter = _wcsonly_to_glue_data(file_obj, data_label) else: data_iter = _nddata_to_glue_data(file_obj, data_label) @@ -184,7 +184,7 @@ def _parse_image(app, file_obj, data_label, ext=None): # for outside_*_bounding_box should also be updated. data.coords._orig_bounding_box = data.coords.bounding_box data.coords.bounding_box = None - if not data.meta.get(app._wcs_only_label, False): + if not data.meta.get(_wcs_only_label, False): data_label = app.return_data_label(data_label, alt_name="image_data") app.add_data(data, data_label) diff --git a/jdaviz/configs/imviz/wcs_utils.py b/jdaviz/configs/imviz/wcs_utils.py index 315b268aab..7dc17d81a5 100644 --- a/jdaviz/configs/imviz/wcs_utils.py +++ b/jdaviz/configs/imviz/wcs_utils.py @@ -21,6 +21,7 @@ from gwcs.wcs import WCS as GWCS from matplotlib.patches import Polygon +from jdaviz.utils import _wcs_only_label __all__ = ['get_compass_info', 'draw_compass_mpl'] @@ -530,7 +531,7 @@ def _get_rotated_nddata_from_label( data.coords, rotation_angle, refdata_shape, - wcs_only_key=app._wcs_only_label, + wcs_only_key=_wcs_only_label, data=data, cdelt_signs=cdelt_signs ) diff --git a/jdaviz/core/template_mixin.py b/jdaviz/core/template_mixin.py index 41e9f99196..7e23a0e1db 100644 --- a/jdaviz/core/template_mixin.py +++ b/jdaviz/core/template_mixin.py @@ -51,7 +51,7 @@ from jdaviz.core.region_translators import regions2roi, _get_region_from_spatial_subset from jdaviz.core.user_api import UserApiWrapper, PluginUserApi from jdaviz.style_registry import PopoutStyleWrapper -from jdaviz.utils import get_subset_type +from jdaviz.utils import get_subset_type, is_wcs_only, is_not_wcs_only, _wcs_only_label __all__ = ['show_widget', 'TemplateMixin', 'PluginTemplateMixin', @@ -1343,7 +1343,7 @@ def _layer_to_dict(self, layer_label): visibilities = [] for viewer in self.viewer_objs: for layer in viewer.layers: - if layer.layer.label == layer_label: + if layer.layer.label == layer_label and is_not_wcs_only(layer.layer): if is_subset is None: is_subset = ((hasattr(layer, 'state') and hasattr(layer.state, 'subset_state')) or # noqa (hasattr(layer, 'layer') and hasattr(layer.layer, 'subset_state'))) # noqa @@ -1491,8 +1491,6 @@ def update_wcs_only_filter(self, wcs_only): `True` will filter only the WCS-only layers, `False` will give the non-WCS-only layers. """ - def is_wcs_only(layer): - return getattr(layer.layer, 'meta', {}).get(self.app._wcs_only_label, False) filter_names = [getattr(filt, '__name__', '') for filt in self.filters] @@ -2961,7 +2959,7 @@ def is_cube(data): return len(data.shape) == 3 def is_not_wcs_only(data): - return not data.meta.get(self.app._wcs_only_label, False) + return not data.meta.get(_wcs_only_label, False) return super()._is_valid_item(data, locals()) diff --git a/jdaviz/utils.py b/jdaviz/utils.py index 30aa315b8d..f6f5a437c3 100644 --- a/jdaviz/utils.py +++ b/jdaviz/utils.py @@ -229,6 +229,26 @@ def layer_is_table_data(layer): return isinstance(layer, BaseData) and layer.ndim == 1 +_wcs_only_label = "_WCS_ONLY" + + +def is_wcs_only(layer): + # exclude WCS-only layers from the layer choices: + if hasattr(layer, 'layer'): + state = layer.layer + elif hasattr(layer, 'data'): + state = layer.data + elif hasattr(layer, 'meta'): + state = layer + else: + raise NotImplementedError + return getattr(state, 'meta', {}).get(_wcs_only_label, False) + + +def is_not_wcs_only(layer): + return not is_wcs_only(layer) + + def standardize_metadata(metadata): """Standardize given metadata so it can be viewed in Metadata Viewer plugin. The input can be plain