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

live-preview marks based on mouseover #2293

Closed
wants to merge 1 commit into from
Closed
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: 1 addition & 1 deletion docs/dev/ui_style_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Tray Plugins
In order to be consistent with layout, styling, and spacing, UI development on plugins should
try to adhere to the following principles:

* Any tray plugin should utilize ``<j-tray-plugin :disabled_msg='disabled_msg'>`` as the
* Any tray plugin should utilize ``<j-tray-plugin :has_previews="has_previews" :plugin_active.sync="plugin_active" :persistent_previews.sync="persistent_previews" :disabled_msg='disabled_msg' :popout_button="popout_button">`` as the
outer-container (which provides consistent styling rules). Any changes to style
across all plugins should then take place in the
``j-tray-plugin`` stylesheet (``jdaviz/components/tray_plugin.vue``).
Expand Down
50 changes: 33 additions & 17 deletions jdaviz/components/tray_plugin.vue
Original file line number Diff line number Diff line change
@@ -1,26 +1,42 @@
<template>
<v-container class="tray-plugin" style="padding-left: 24px; padding-right: 24px; padding-top: 12px">
<v-row>
<div style="width: calc(100% - 32px)">
<j-docs-link :link="link">{{ description }}</j-docs-link>
</div>
<div style="width: 32px">
<j-plugin-popout :popout_button="popout_button"></j-plugin-popout>
</div>
</v-row>

<v-row v-if="isDisabled()">
<span> {{ getDisabledMsg() }}</span>
</v-row>
<div v-else>
<slot></slot>
<div
@mouseenter="if (!persistent_previews){$emit('update:plugin_active', true)}"
@mouseleave="if (!persistent_previews){$emit('update:plugin_active', false)}"
:style="(plugin_active || persistent_previews) ? 'border-left: 4px solid rgb(2 123 161 / 80%)' : 'margin-left: 4px'"
>
<v-container class="tray-plugin" style="padding-left: 24px; padding-right: 24px; padding-top: 12px">
<v-row>
<div style="width: calc(100% - 32px)">
<j-docs-link :link="link">{{ description }}</j-docs-link>
</div>
<div style="width: 32px">
<j-plugin-popout :popout_button="popout_button"></j-plugin-popout>
</div>
</v-row>

<v-row v-if="isDisabled()">
<span> {{ getDisabledMsg() }}</span>
</v-row>
<div v-else>
<v-row v-if="has_previews">
<v-switch
v-model="persistent_previews"
@change="$emit('update:persistent_previews', $event)"
label="persistent live-preview"
hint="show live-preview even when mouse is not over plugin"
persistent-hint>
</v-switch>
</v-row>
<slot></slot>
</div>
</v-container>
</div>
</v-container>
</template>

<script>
module.exports = {
props: ['disabled_msg', 'description', 'link', 'popout_button'],
props: ['disabled_msg', 'description', 'link', 'popout_button',
'has_previews', 'plugin_active', 'persistent_previews'],
methods: {
isDisabled() {
return this.getDisabledMsg().length > 0
Expand Down
18 changes: 9 additions & 9 deletions jdaviz/configs/cubeviz/plugins/tests/test_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ def test_spectrum_at_spaxel(cubeviz_helper, spectrum1d_cube):
flux_viewer.toolbar.active_tool = flux_viewer.toolbar.tools['jdaviz:spectrumperspaxel']
x = 1
y = 1
assert len(flux_viewer.figure.marks) == 2
assert len(flux_viewer.native_marks) == 2
assert len(spectrum_viewer.data()) == 1

# Click on spaxel location
flux_viewer.toolbar.active_tool.on_mouse_event(
{'event': 'click', 'domain': {'x': x, 'y': y}, 'altKey': False})
assert len(flux_viewer.figure.marks) == 3
assert len(flux_viewer.native_marks) == 3
assert len(spectrum_viewer.data()) == 2

# Check that a new subset was created
Expand All @@ -32,7 +32,7 @@ def test_spectrum_at_spaxel(cubeviz_helper, spectrum1d_cube):

# Deselect tool
flux_viewer.toolbar.active_tool = None
assert len(flux_viewer.figure.marks) == 3
assert len(flux_viewer.native_marks) == 3


def test_spectrum_at_spaxel_altkey_true(cubeviz_helper, spectrum1d_cube):
Expand All @@ -46,7 +46,7 @@ def test_spectrum_at_spaxel_altkey_true(cubeviz_helper, spectrum1d_cube):
flux_viewer.toolbar.active_tool = flux_viewer.toolbar.tools['jdaviz:spectrumperspaxel']
x = 1
y = 1
assert len(flux_viewer.figure.marks) == 2
assert len(flux_viewer.native_marks) == 2
assert len(spectrum_viewer.data()) == 1

# Check coordinate info panel
Expand All @@ -60,7 +60,7 @@ def test_spectrum_at_spaxel_altkey_true(cubeviz_helper, spectrum1d_cube):
# Click on spaxel location
flux_viewer.toolbar.active_tool.on_mouse_event(
{'event': 'click', 'domain': {'x': x, 'y': y}, 'altKey': False})
assert len(flux_viewer.figure.marks) == 3
assert len(flux_viewer.native_marks) == 3
assert len(spectrum_viewer.data()) == 2

# Check that subset was created
Expand All @@ -74,7 +74,7 @@ def test_spectrum_at_spaxel_altkey_true(cubeviz_helper, spectrum1d_cube):
y = 2
flux_viewer.toolbar.active_tool.on_mouse_event(
{'event': 'click', 'domain': {'x': x, 'y': y}, 'altKey': True})
assert len(flux_viewer.figure.marks) == 4
assert len(flux_viewer.native_marks) == 4
assert len(spectrum_viewer.data()) == 3

subsets = cubeviz_helper.app.get_subsets()
Expand Down Expand Up @@ -118,15 +118,15 @@ def test_spectrum_at_spaxel_with_2d(cubeviz_helper):
flux_viewer.toolbar.active_tool = flux_viewer.toolbar.tools['jdaviz:spectrumperspaxel']
x = 1
y = 1
assert len(flux_viewer.figure.marks) == 2
assert len(flux_viewer.native_marks) == 2
assert len(spectrum_viewer.data()) == 0

# Click on spaxel location
flux_viewer.toolbar.active_tool.on_mouse_event(
{'event': 'click', 'domain': {'x': x, 'y': y}, 'altKey': False})
assert len(flux_viewer.figure.marks) == 3
assert len(flux_viewer.native_marks) == 3
assert len(spectrum_viewer.data()) == 0

# Deselect tool
flux_viewer.toolbar.active_tool = None
assert len(flux_viewer.figure.marks) == 3
assert len(flux_viewer.native_marks) == 3
10 changes: 2 additions & 8 deletions jdaviz/configs/default/plugins/line_lists/line_lists.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,12 +322,7 @@ def _on_rs_redshift_updated(self, event):
msg = RedshiftMessage("redshift", value, sender=self)
self.app.hub.broadcast(msg)

@observe('plugin_opened')
def _update_line_list_obs(self, *args):
if not self.plugin_opened:
return

new_list_contents = {}
for list_name, line_list in self.list_contents.items():
for i, line in enumerate(line_list['lines']):
if self._rs_line_obs_change[0] == list_name and self._rs_line_obs_change[1] == i: # noqa
Expand All @@ -339,10 +334,9 @@ def _update_line_list_obs(self, *args):
else:
line_list['lines'][i]['obs'] = self._rest_to_obs(float(line['rest']))

new_list_contents[list_name] = line_list
self.list_contents[list_name] = line_list

self.list_contents = {}
self.list_contents = new_list_contents
self.send_state('list_contents')

def vue_change_line_obs(self, kwargs):
# NOTE: we can only pass one argument from vue (it seems), so we'll pass as
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def test_redshift(specviz_helper, spectrum1d):

ll_plugin = specviz_helper.app.get_tray_item_from_name('g-line-list')
# fake the plugin to be opened so that all updates run
ll_plugin.plugin_opened = True
ll_plugin.plugin_active = True
line = ll_plugin.list_contents['Test List']['lines'][0]
assert_allclose(line['obs'], line['rest'])
# test API access
Expand Down
16 changes: 10 additions & 6 deletions jdaviz/configs/default/plugins/markers/markers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import numpy as np
from traitlets import observe
from traitlets import Bool, observe

from jdaviz.core.events import ViewerAddedMessage
from jdaviz.core.marks import MarkersMark
Expand All @@ -24,6 +24,7 @@ class Markers(PluginTemplateMixin, ViewerSelectMixin, TableMixin):
* :meth:`~jdaviz.core.template_mixin.TableMixin.export_table`
"""
template_file = __file__, "markers.vue"
has_previews = Bool(True).tag(sync=True)

_default_table_values = {'spectral_axis': np.nan,
'spectral_axis:unit': '',
Expand Down Expand Up @@ -78,8 +79,11 @@ def __init__(self, *args, **kwargs):
# subscribe to mouse events on any new viewers
self.hub.subscribe(self, ViewerAddedMessage, handler=self._on_viewer_added)

# need to keep preview marks when mouse is not over plugin (by default)
self.persistent_previews = True

def _create_viewer_callbacks(self, viewer):
if not self.plugin_opened:
if not self.show_previews:
return

callback = self._viewer_callback(viewer, self._on_viewer_key_event)
Expand All @@ -106,14 +110,14 @@ def marks(self):
def coords_info(self):
return self.app.session.application._tools['g-coords-info']

@observe('plugin_opened')
def _on_plugin_opened_changed(self, *args):
@observe('show_previews')
def _on_show_previews_changed(self, *args):
if self.disabled_msg:
return

# toggle visibility of markers
for mark in self.marks.values():
mark.visible = self.plugin_opened
mark.visible = self.show_previews

# subscribe/unsubscribe to keypress events across all viewers
for viewer in self.app._viewer_store.values():
Expand All @@ -122,7 +126,7 @@ def _on_plugin_opened_changed(self, *args):
continue
callback = self._viewer_callback(viewer, self._on_viewer_key_event)

if self.plugin_opened:
if self.show_previews:
viewer.add_event_callback(callback, events=['keydown'])
else:
viewer.remove_event_callback(callback)
Expand Down
7 changes: 7 additions & 0 deletions jdaviz/configs/default/plugins/markers/markers.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,15 @@
<j-tray-plugin
description='Create and export markers. Press "m" with the cursor over a viewer to log the mouseover information. To change the selected layer, click the layer cycler in the mouseover information section of the app-level toolbar.'
:link="'https://jdaviz.readthedocs.io/en/'+vdocs+'/'+config+'/plugins.html#markers'"
:has_previews="has_previews"
:plugin_active.sync="plugin_active"
:persistent_previews.sync="persistent_previews"
:popout_button="popout_button">

<v-row v-if="!persistent_previews">
<v-alert color="warning">Persistent live-preview must be enabled for logging via keypress to be active</v-alert>
</v-row>

<jupyter-widget :widget="table_widget"></jupyter-widget>

</j-tray-plugin>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ def test_markers_cubeviz(cubeviz_helper, spectrum1d_cube):
label_mouseover = cubeviz_helper.app.session.application._tools['g-coords-info']

mp = cubeviz_helper.plugins['Markers']
mp.open_in_tray()

# test event in flux viewer
label_mouseover._viewer_mouse_event(fv,
Expand Down Expand Up @@ -112,13 +111,13 @@ def test_markers_cubeviz(cubeviz_helper, spectrum1d_cube):
assert len(_get_markers_from_viewer(fv).x) == 1
assert len(_get_markers_from_viewer(sv).x) == 2

# markers hide when plugin closed
cubeviz_helper.app.state.drawer = False
# markers hide when persistent_previews disabled (and not active)
mp.persistent_previews = False
assert _get_markers_from_viewer(fv).visible is False
assert _get_markers_from_viewer(sv).visible is False

# markers re-appear when plugin re-opened
mp.open_in_tray()
mp.persistent_previews = True
assert _get_markers_from_viewer(fv).visible is True
assert _get_markers_from_viewer(sv).visible is True
assert len(_get_markers_from_viewer(fv).x) == 1
Expand All @@ -136,7 +135,6 @@ def test_markers_layer_cycle(self):
label_mouseover = self.imviz.app.session.application._tools['g-coords-info']

mp = self.imviz.plugins['Markers']
mp.open_in_tray()

# cycle through dataset options (used for both coords info and markers)
assert label_mouseover.dataset.choices == ['auto', 'none',
Expand Down Expand Up @@ -216,9 +214,6 @@ def test_markers_layer_cycle(self):
def test_markers_custom_viewer(self):
label_mouseover = self.imviz.app.session.application._tools['g-coords-info']

mp = self.imviz.plugins['Markers']
mp.open_in_tray()

nv = self.imviz.create_image_viewer()
self.imviz.app.add_data_to_viewer('imviz-1', 'has_wcs[SCI,1]')

Expand Down
14 changes: 8 additions & 6 deletions jdaviz/configs/default/plugins/plot_options/plot_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,10 @@ def user_api(self):

return PluginUserApi(self, expose)

def show(self, *args, **kwargs):
super().show(*args, **kwargs)
self._update_stretch_histogram()

@observe('show_viewer_labels')
def _on_show_viewer_labels_changed(self, event):
self.app.state.settings['viewer_labels'] = event['new']
Expand Down Expand Up @@ -479,18 +483,15 @@ def vue_set_value(self, data):
value = data.get('value')
setattr(self, attr_name, value)

@observe('plugin_opened', 'layer_selected', 'viewer_selected',
'stretch_hist_zoom_limits')
@observe('plugin_opened_in_tray', 'layer_selected', 'viewer_selected', 'stretch_hist_zoom_limits')
def _update_stretch_histogram(self, msg={}):
if not self.stretch_function_sync.get('in_subscribed_states'): # pragma: no cover
# no (image) viewer with stretch function options
return
if not hasattr(self, 'viewer'): # pragma: no cover
# plugin hasn't been fully initialized yet
return
if (not self.plugin_opened
or not self.viewer.selected
or not self.layer.selected): # pragma: no cover
if (not self.viewer.selected or not self.layer.selected): # pragma: no cover
# no need to make updates, updates will be redrawn when plugin is opened
# NOTE: this won't update when the plugin is shown but not open in the tray
return
Expand All @@ -504,7 +505,8 @@ def _update_stretch_histogram(self, msg={}):
or len(self.layer.selected) > 1): # pragma: no cover
# currently only support single-layer/viewer. For now we'll just clear and return.
# TODO: add support for multi-layer/viewer
bqplot_clear_figure(self.stretch_histogram)
if self.stretch_histogram is not None:
bqplot_clear_figure(self.stretch_histogram)
return

viewer = self.viewer.selected_obj[0] if self.multiselect else self.viewer.selected_obj
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ def test_multiselect(cubeviz_helper, spectrum1d_cube):
def test_stretch_histogram(cubeviz_helper, spectrum1d_cube_with_uncerts):
cubeviz_helper.load_data(spectrum1d_cube_with_uncerts)
po = cubeviz_helper.app.get_tray_item_from_name('g-plot-options')
po.open_in_tray() # forces histogram to draw

assert po.stretch_histogram is not None

Expand Down
2 changes: 1 addition & 1 deletion jdaviz/configs/default/plugins/viewers.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class JdavizViewerMixin:
toolbar = None
tools_nested = []
_prev_limits = None
_native_mark_classnames = ('Lines', 'LinesGL')
_native_mark_classnames = ('Lines', 'LinesGL', 'FRBImage', 'Contour')

def __init__(self, *args, **kwargs):
# NOTE: anything here most likely won't be called by viewers because of inheritance order
Expand Down
4 changes: 2 additions & 2 deletions jdaviz/configs/imviz/plugins/compass/compass.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,15 @@ def _set_compass_rotation(self):
self.canvas_angle = viewer_item.get('canvas_angle', 0) # noqa
self.canvas_flip_horizontal = viewer_item.get('canvas_flip_horizontal', False)

@observe("viewer_selected", "plugin_opened")
@observe("viewer_selected", "plugin_opened_in_tray")
def _compass_with_new_viewer(self, *args, **kwargs):
if not hasattr(self, 'viewer'):
# mixin object not yet initialized
return

# There can be only one!
for vid, viewer in self.app._viewer_store.items():
if vid == self.viewer.selected_id and (self.plugin_opened or kwargs.get('from_show')):
if vid == self.viewer.selected_id and (self.plugin_opened_in_tray or kwargs.get('from_show')): # noqa
viewer.compass = self
viewer.on_limits_change() # Force redraw

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def reset_results(self):
@observe("selected_viewer")
def vue_draw_plot(self, *args, **kwargs):
"""Draw line profile plots for given Data across given X and Y indices (0-indexed)."""
if not self.selected_x or not self.selected_y or not self.plugin_opened:
if not self.selected_x or not self.selected_y:
return

viewer = self.app.get_viewer_by_id(self.selected_viewer)
Expand Down
3 changes: 2 additions & 1 deletion jdaviz/configs/imviz/plugins/viewers.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ def on_mouse_or_key_event(self, data):
if key_pressed in ('b', 'B'):
self.blink_once(reversed=key_pressed=='B') # noqa: E225

elif key_pressed == 'l' and self.line_profile_xy.plugin_opened:
# TODO: move into plugin callback?
elif key_pressed == 'l':
# Same data as mousemove above.
image = self.active_image_layer.layer
x = data['domain']['x']
Expand Down
Loading
Loading