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

plugin active status based on pings #2295

Merged
merged 13 commits into from
Jul 27, 2023
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ Bug Fixes

- Fixed ``cls`` input being ignored in ``viz.get_data()``. [#2242]

- Live-previews and keypress events that depend on the plugin being opened now work for inline
and popout windows. [#2295]

Cubeviz
^^^^^^^

Expand Down
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 :uses_active_status="uses_active_status" @plugin-ping="plugin_ping($event)" :keep_active.sync="keep_active" :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
2 changes: 1 addition & 1 deletion jdaviz/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@
</j-tooltip>
</v-expansion-panel-header>
<v-expansion-panel-content style="margin-left: -12px; margin-right: -12px;">
<jupyter-widget :widget="trayItem.widget"></jupyter-widget>
<jupyter-widget :widget="trayItem.widget" v-if="state.tray_items_open.includes(index)"></jupyter-widget>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is needed so that the same logic works for plugins in the tray (otherwise the plugin element when collapsed will continue sending pings)

</v-expansion-panel-content>
</div>
</v-expansion-panel>
Expand Down
36 changes: 34 additions & 2 deletions jdaviz/components/tray_plugin.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,54 @@
<span> {{ getDisabledMsg() }}</span>
</v-row>
<div v-else>
<v-row v-if="uses_active_status">
<v-switch
v-model="keep_active"
@change="$emit('update:keep_active', $event)"
label="keep active"
hint="consider plugin active (showing any previews and enabling all keypress events) even when not opened"
persistent-hint>
</v-switch>
</v-row>
<slot></slot>
</div>
</v-container>
</template>

<script>
module.exports = {
props: ['disabled_msg', 'description', 'link', 'popout_button'],
props: ['disabled_msg', 'description', 'link', 'popout_button',
'uses_active_status', 'keep_active'],
methods: {
isDisabled() {
return this.getDisabledMsg().length > 0
},
getDisabledMsg() {
return this.disabled_msg || ''
},
}
sendPing(recursive) {
if (!this.$el.isConnected) {
return
}
if (!document.hidden) {
this.$emit('plugin-ping', Date.now())
}
if (!recursive) {
return
}
setTimeout(() => {
this.sendPing(true)
}, 200) // ms
}
},
mounted() {
this.sendPing(true);
document.addEventListener("visibilitychange", () => {
if (!document.hidden) {
this.sendPing(false)
}
});
},
};
</script>

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 @@ -47,13 +47,13 @@ def test_line_lists(specviz_helper):

def test_redshift(specviz_helper, spectrum1d):
# Also test that plugin is disabled before data is loaded.
plg = specviz_helper.plugins['Line Lists']
assert plg._obj.disabled_msg
ll_plugin = specviz_helper.plugins['Line Lists']._obj
assert ll_plugin.disabled_msg

label = "Test 1D Spectrum"
specviz_helper.load_data(spectrum1d, data_label=label)

assert not plg._obj.disabled_msg
assert not ll_plugin.disabled_msg

lt = QTable()
lt['linename'] = ['O III', 'Halpha']
Expand All @@ -63,8 +63,7 @@ def test_redshift(specviz_helper, spectrum1d):
with pytest.warns(UserWarning, match='per line/list redshifts not supported, use viz.set_redshift'): # noqa
specviz_helper.load_line_list(lt)

ll_plugin = specviz_helper.app.get_tray_item_from_name('g-line-list')
# fake the plugin to be opened so that all updates run
# open the plugin so that all updates run
ll_plugin.plugin_opened = True
line = ll_plugin.list_contents['Test List']['lines'][0]
assert_allclose(line['obs'], line['rest'])
Expand Down
13 changes: 7 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"
uses_active_status = Bool(True).tag(sync=True)

_default_table_values = {'spectral_axis': np.nan,
'spectral_axis:unit': '',
Expand Down Expand Up @@ -79,7 +80,7 @@ def __init__(self, *args, **kwargs):
self.hub.subscribe(self, ViewerAddedMessage, handler=self._on_viewer_added)

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

callback = self._viewer_callback(viewer, self._on_viewer_key_event)
Expand All @@ -106,14 +107,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('is_active')
def _on_is_active_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.is_active

# subscribe/unsubscribe to keypress events across all viewers
for viewer in self.app._viewer_store.values():
Expand All @@ -122,7 +123,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.is_active:
viewer.add_event_callback(callback, events=['keydown'])
else:
viewer.remove_event_callback(callback)
Expand Down
3 changes: 3 additions & 0 deletions jdaviz/configs/default/plugins/markers/markers.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
<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'"
:uses_active_status="uses_active_status"
@plugin-ping="plugin_ping($event)"
:keep_active.sync="keep_active"
:popout_button="popout_button">

<jupyter-widget :widget="table_widget"></jupyter-widget>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ 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()
mp.keep_active = True

# test event in flux viewer
label_mouseover._viewer_mouse_event(fv,
Expand Down Expand Up @@ -112,13 +112,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 plugin closed and keep_active = False
mp.keep_active = 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._obj.plugin_opened = 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 +136,7 @@ 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()
mp.plugin_opened = True

# cycle through dataset options (used for both coords info and markers)
assert label_mouseover.dataset.choices == ['auto', 'none',
Expand Down Expand Up @@ -217,7 +217,7 @@ 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()
mp.plugin_opened = True

nv = self.imviz.create_image_viewer()
self.imviz.app.add_data_to_viewer('imviz-1', 'has_wcs[SCI,1]')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ 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
po.plugin_opened = True

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 @@ -21,7 +21,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
6 changes: 1 addition & 5 deletions jdaviz/configs/imviz/plugins/compass/compass.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ def __init__(self, *args, **kwargs):
def user_api(self):
return PluginUserApi(self, expose=('viewer',), readonly=('data_label',))

def show(self, *args, **kwargs):
super().show(*args, **kwargs)
self._compass_with_new_viewer(from_show=True)

def _on_viewer_data_changed(self, msg=None):
if self.viewer_selected:
viewer = self.viewer.selected_obj
Expand All @@ -69,7 +65,7 @@ def _compass_with_new_viewer(self, *args, **kwargs):

# 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:
viewer.compass = self
viewer.on_limits_change() # Force redraw

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def reset_results(self):
self.plot_across_y.clear_all_marks()

# This is also triggered from viewer code.
@observe("selected_viewer")
@observe("plugin_opened", "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:
Expand Down
1 change: 1 addition & 0 deletions jdaviz/configs/imviz/plugins/viewers.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ def on_mouse_or_key_event(self, data):
if key_pressed in ('b', 'B'):
self.blink_once(reversed=key_pressed=='B') # noqa: E225

# TODO: move into plugin callback?
elif key_pressed == 'l' and self.line_profile_xy.plugin_opened:
# Same data as mousemove above.
image = self.active_image_layer.layer
Expand Down
2 changes: 1 addition & 1 deletion jdaviz/configs/imviz/tests/test_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ def test_blink(imviz_helper):

def test_compass_open_while_load(imviz_helper):
plg = imviz_helper.plugins['Compass']
plg.open_in_tray()
plg.plugin_opened = True

# Should not crash even if Compass is open in tray.
imviz_helper.load_data(np.ones((2, 2)))
Expand Down
Loading
Loading