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

Viewer/layer labels #1465

Merged
merged 17 commits into from
Jul 14, 2022
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -4,6 +4,8 @@
New Features
------------

- Viewer/layer labels with icons that are synced app-wide. [#1465]

Cubeviz
^^^^^^^

Expand Down
36 changes: 33 additions & 3 deletions jdaviz/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
from glue.core.link_helpers import LinkSame
from glue.plugins.wcs_autolinking.wcs_autolinking import WCSLink, IncompatibleWCS
from glue.core.message import (DataCollectionAddMessage,
DataCollectionDeleteMessage)
DataCollectionDeleteMessage,
SubsetCreateMessage,
SubsetDeleteMessage)
from glue.core.state_objects import State
from glue.core.subset import Subset, RangeSubsetState, RoiSubsetState
from glue_jupyter.app import JupyterApplication
Expand Down Expand Up @@ -127,6 +129,7 @@ class ApplicationState(State):
'tray': True,
'tab_headers': True,
},
'viewer_labels': True,
'dense_toolbar': True,
'context': {
'notebook': {
Expand All @@ -142,6 +145,9 @@ class ApplicationState(State):
'checktoradial': read_icon(os.path.join(ICON_DIR, 'checktoradial.svg'), 'svg+xml')
}, docstring="Custom application icons")

viewer_icons = DictCallbackProperty({}, docstring="Indexed icons for viewers across the app")
layer_icons = DictCallbackProperty({}, docstring="Indexed icons for layers across the app")

data_items = ListCallbackProperty(
docstring="List of data items parsed from the Glue data collection.")

Expand Down Expand Up @@ -261,6 +267,16 @@ def __init__(self, configuration=None, *args, **kwargs):
if cur_cm not in colormaps.members:
colormaps.add(*cur_cm)

# Subscribe to messages that result in changes to the layers
self.hub.subscribe(self, AddDataMessage,
handler=self._on_layers_changed)
self.hub.subscribe(self, RemoveDataMessage,
handler=self._on_layers_changed)
self.hub.subscribe(self, SubsetCreateMessage,
handler=self._on_layers_changed)
self.hub.subscribe(self, SubsetDeleteMessage,
handler=self._on_layers_changed)

@property
def hub(self):
"""
Expand Down Expand Up @@ -351,6 +367,18 @@ def _color_to_level(color):
history=msg_level >= history_level,
popup=msg_level >= popup_level)

def _on_layers_changed(self, msg):
if hasattr(msg, 'data'):
layer_name = msg.data.label
elif hasattr(msg, 'subset'):
layer_name = msg.subset.label
else:
raise NotImplementedError(f"cannot recognize new layer from {msg}")

if layer_name not in self.state.layer_icons:
self.state.layer_icons = {**self.state.layer_icons,
layer_name: f"mdi-alpha-{chr(97 + len(self.state.layer_icons))}-box-outline"} # noqa

def _link_new_data(self, reference_data=None, data_to_be_linked=None):
"""
When additional data is loaded, check to see if the spectral axis of
Expand Down Expand Up @@ -1429,6 +1457,8 @@ def _create_viewer_item(self, viewer, vid=None, name=None, reference=None):
# own attribute instead.
viewer._reference_id = vid # For reverse look-up

self.state.viewer_icons.setdefault(vid, f"mdi-numeric-{len(self.state.viewer_icons)+1}-circle-outline") # noqa

return {
'id': vid,
'name': name or vid,
Expand All @@ -1438,8 +1468,8 @@ def _create_viewer_item(self, viewer, vid=None, name=None, reference=None):
'tools_open': False,
'layer_options': "IPY_MODEL_" + viewer.layer_options.model_id,
'viewer_options': "IPY_MODEL_" + viewer.viewer_options.model_id,
'layer_viewer_open': False,
'selected_data_items': {},
'selected_data_items': {}, # data-label: visibility state (visible, hidden, mixed)
'visible_layers': {}, # label: {color, label_suffix} (read-only access)
'config': self.config, # give viewer access to app config/layout
'data_open': False,
'collapse': True,
Expand Down
5 changes: 4 additions & 1 deletion jdaviz/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@
:data_items="state.data_items"
:app_settings="state.settings"
:icons="state.icons"
:viewer_icons="state.viewer_icons"
:layer_icons="state.layer_icons"
@resize="relayout"
:closefn="destroy_viewer_item"
@data-item-selected="data_item_selected($event)"
Expand Down Expand Up @@ -342,8 +344,9 @@ a:active {
filter: invert(1) saturate(1) brightness(100);
}

.invert-if-dark.theme--dark {
.invert, .invert-if-dark.theme--dark {
filter: invert(1) saturate(1) brightness(100);
color: white;
}

.jdaviz-nested-toolbar .v-btn {
Expand Down
5 changes: 5 additions & 0 deletions jdaviz/components/plugin_dataset_select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@
<template slot="selection" slot-scope="data">
<div class="single-line">
<span>
<v-icon style='margin-right: 2px'>{{ data.item.icon }}</v-icon>
{{ data.item.label }}
</span>
</div>
</template>
<template slot="item" slot-scope="data">
<div class="single-line">
<span>
<v-icon style='margin-right: 2px'>{{ data.item.icon }}</v-icon>
{{ data.item.label }}
</span>
</div>
Expand All @@ -37,6 +39,9 @@ module.exports = {
</script>

<style>
.v-select__selections {
flex-wrap: nowrap !important;
}
.single-line {
white-space: nowrap;
overflow: hidden;
Expand Down
5 changes: 5 additions & 0 deletions jdaviz/components/plugin_layer_select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
</span>
</v-chip>
<span v-else>
<v-icon style='margin-right: 2px'>{{ data.item.icon }}</v-icon>
{{ data.item.label }}
</span>
</div>
Expand All @@ -49,6 +50,7 @@
<template slot="item" slot-scope="data">
<div class="single-line">
<span>
<v-icon style='margin-left: -2px; margin-right: 2px'>{{ data.item.icon }}</v-icon>
{{ data.item.label }}
</span>
</div>
Expand All @@ -65,6 +67,9 @@ module.exports = {
</script>

<style>
.v-select__selections {
flex-wrap: nowrap !important;
}
.single-line {
white-space: nowrap;
overflow: hidden;
Expand Down
3 changes: 3 additions & 0 deletions jdaviz/components/plugin_subset_select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ module.exports = {
</script>

<style>
.v-select__selections {
flex-wrap: nowrap !important;
}
.single-line {
white-space: nowrap;
overflow: hidden;
Expand Down
7 changes: 6 additions & 1 deletion jdaviz/components/plugin_viewer_select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
<v-chip v-if="multiselect" style="width: calc(100% - 20px)">
<span>
<v-icon style='margin-left: -10px; margin-right: 2px'>{{ data.item.icon }}</v-icon>
{{ data.item.label.split("-viewer")[0] }}
{{ data.item.label }}
</span>
</v-chip>
<span v-else>
<v-icon style='margin-right: 2px'>{{ data.item.icon }}</v-icon>
{{ data.item.label }}
</span>
</div>
Expand All @@ -49,6 +50,7 @@
<template slot="item" slot-scope="data">
<div class="single-line">
<span>
<v-icon style='margin-left: -2px; margin-right: 2px'>{{ data.item.icon }}</v-icon>
{{ data.item.label }}
</span>
</div>
Expand All @@ -65,6 +67,9 @@ module.exports = {
</script>

<style>
.v-select__selections {
flex-wrap: nowrap !important;
}
.single-line {
white-space: nowrap;
overflow: hidden;
Expand Down
6 changes: 4 additions & 2 deletions jdaviz/components/viewer_data_select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</v-btn>
</template>

<v-list style="max-height: 500px; width: 430px; padding-top: 0px" class="overflow-y-auto">
<v-list style="max-height: 500px; width: 460px; padding-top: 0px" class="overflow-y-auto">
<v-row key="title" style="padding-left: 25px; margin-right: 0px; background-color: #E3F2FD">
<span style="overflow-wrap: anywhere; font-size: 12pt; padding-top: 6px; padding-left: 6px; font-weight: bold; color: black">
{{viewerTitleCase}}
Expand Down Expand Up @@ -47,6 +47,7 @@
<v-row v-for="item in filteredDataItems" :key="item.id" style="padding-left: 25px; margin-right: 0px; margin-top: 4px; margin-bottom: 4px">
<j-viewer-data-select-item
:item="item"
:icon="layer_icons[item.name]"
:viewer="viewer"
:multi_select="multi_select"
@data-item-selected="$emit('data-item-selected', $event)"
Expand Down Expand Up @@ -75,6 +76,7 @@
<v-row v-if="showExtraItems" v-for="item in extraDataItems" :key="item.id" style="padding-left: 25px; margin-right: 0px; margin-top: 4px; margin-bottom: 4px">
<j-viewer-data-select-item
:item="item"
:icon="layer_icons[item.name]"
:viewer="viewer"
:multi_select="multi_select"
@data-item-selected="$emit('data-item-selected', $event)"
Expand All @@ -91,7 +93,7 @@
<script>

module.exports = {
props: ['data_items', 'viewer', 'app_settings', 'viewer_data_visibility', 'icons'],
props: ['data_items', 'viewer', 'layer_icons', 'app_settings', 'viewer_data_visibility', 'icons'],
data: function () {
var multi_select = true
if (this.$props.viewer.config === 'cubeviz') {
Expand Down
7 changes: 4 additions & 3 deletions jdaviz/components/viewer_data_select_item.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@
</j-tooltip>
</div>

<j-tooltip :tooltipcontent="'data label: '+item.name" span_style="font-size: 12pt; padding-top: 6px; padding-left: 6px; width: calc(100% - 80px); cursor: default;">
<div class="text-ellipsis-middle">
<j-tooltip :tooltipcontent="'data label: '+item.name" span_style="font-size: 12pt; padding-top: 6px; padding-left: 6px; width: calc(100% - 140px); white-space: nowrap; cursor: default;">
<v-icon class='invert-if-dark' style='color: #000000DE; margin-left: 4px; margin-right: -2px'>{{icon}}</v-icon>
<div class="text-ellipsis-middle" style="font-weight: 500">
<span>
{{itemNamePrefix}}
</span>
Expand Down Expand Up @@ -61,7 +62,7 @@
<script>

module.exports = {
props: ['item', 'multi_select', 'viewer'],
props: ['item', 'icon', 'multi_select', 'viewer'],
methods: {
selectClicked() {
prevVisibleState = this.visibleState
Expand Down
1 change: 1 addition & 0 deletions jdaviz/configs/cubeviz/plugins/viewers.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def on_mouse_or_key_event(self, data):
# of dataset shouldn't matter if the datasets are linked correctly
active_layer = visible_layers[-1]
image = active_layer.layer
self.label_mouseover.icon = self.jdaviz_app.state.layer_icons.get(active_layer.layer.label) # noqa

# Extract data coordinates - these are pixels in the reference image
x = data['domain']['x']
Expand Down
14 changes: 13 additions & 1 deletion jdaviz/configs/default/plugins/plot_options/plot_options.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os

from traitlets import Any, Dict, Float, Bool, Int, List, Unicode
from traitlets import Any, Dict, Float, Bool, Int, List, Unicode, observe

from glue.viewers.profile.state import ProfileViewerState, ProfileLayerState
from glue.viewers.image.state import ImageSubsetLayerState
Expand Down Expand Up @@ -107,6 +107,8 @@ class PlotOptions(TemplateMixin):
icon_radialtocheck = Unicode(read_icon(os.path.join(ICON_DIR, 'radialtocheck.svg'), 'svg+xml')).tag(sync=True) # noqa
icon_checktoradial = Unicode(read_icon(os.path.join(ICON_DIR, 'checktoradial.svg'), 'svg+xml')).tag(sync=True) # noqa

setting_show_viewer_labels = Bool(True).tag(sync=True)

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.viewer = ViewerSelect(self, 'viewer_items', 'viewer_selected', 'multiselect')
Expand Down Expand Up @@ -197,6 +199,16 @@ def is_not_subset(state):
# zoom limits
# display_units

self.setting_show_viewer_labels = self.app.state.settings['viewer_labels']
self.app.state.add_callback('settings', self._on_app_settings_changed)

@observe('setting_show_viewer_labels')
def _on_show_viewer_labels_changed(self, event):
self.app.state.settings['viewer_labels'] = event['new']

def _on_app_settings_changed(self, value):
self.setting_show_viewer_labels = value['viewer_labels']

def vue_unmix_state(self, name):
sync_state = getattr(self, name)
sync_state.unmix_state()
Expand Down
20 changes: 20 additions & 0 deletions jdaviz/configs/default/plugins/plot_options/plot_options.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,26 @@
:link="'https://jdaviz.readthedocs.io/en/'+vdocs+'/'+config+'/plugins.html#plot-options'"
:popout_button="popout_button">

<v-row>
<v-expansion-panels popout>
<v-expansion-panel>
<v-expansion-panel-header v-slot="{ open }">
<span style="padding: 6px">Settings</span>
</v-expansion-panel-header>
<v-expansion-panel-content>
<v-row>
<v-switch
v-model="setting_show_viewer_labels"
label="Show labels in viewers"
hint="Whether to show viewer/layer labels on each viewer"
persistent-hint
></v-switch>
</v-row>
</v-expansion-panel-content>
</v-expansion-panel>
</v-expansion-panels>
</v-row>

<v-row>
<div style="width: calc(100% - 32px)">
</div>
Expand Down
Loading