Skip to content

Commit

Permalink
plugin active status determined by "alive" pings
Browse files Browse the repository at this point in the history
  • Loading branch information
kecnry committed Jul 12, 2023
1 parent 683d989 commit baa1eaa
Show file tree
Hide file tree
Showing 26 changed files with 185 additions and 115 deletions.
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_ping.sync="plugin_ping" :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
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>
</v-expansion-panel-content>
</div>
</v-expansion-panel>
Expand Down
26 changes: 24 additions & 2 deletions jdaviz/components/tray_plugin.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,44 @@
<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 plugin is 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',
'has_previews', 'plugin_ping', 'persistent_previews'],
methods: {
isDisabled() {
return this.getDisabledMsg().length > 0
},
getDisabledMsg() {
return this.disabled_msg || ''
},
}
sendPing() {
if (!this.$el.isConnected) {
return
}
this.$emit('update:plugin_ping', Date.now())
setTimeout(() => {
this.sendPing()
}, 100) // ms
}
},
mounted() {
this.sendPing();
},
};
</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: 4 additions & 6 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,11 @@ def _on_rs_redshift_updated(self, event):
msg = RedshiftMessage("redshift", value, sender=self)
self.app.hub.broadcast(msg)

@observe('plugin_opened')
@observe('plugin_active')
def _update_line_list_obs(self, *args):
if not self.plugin_opened:
if not self.plugin_active:
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 +338,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 @@ -64,8 +64,8 @@ def test_redshift(specviz_helper, spectrum1d):
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
ll_plugin.plugin_opened = True
# open the plugin so that all updates run
ll_plugin.open_in_tray()
line = ll_plugin.list_contents['Test List']['lines'][0]
assert_allclose(line['obs'], line['rest'])
# test API access
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"
has_previews = 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.show_previews:
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('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 +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.show_previews:
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'"
:has_previews="has_previews"
:plugin_ping.sync="plugin_ping"
:persistent_previews.sync="persistent_previews"
: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 @@ -112,7 +112,7 @@ 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
# markers hide when plugin closed (since persistent_previews == False)
cubeviz_helper.app.state.drawer = False
assert _get_markers_from_viewer(fv).visible is False
assert _get_markers_from_viewer(sv).visible is False
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
6 changes: 3 additions & 3 deletions jdaviz/configs/imviz/tests/test_catalogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def test_plugin_no_image(self, imviz_helper):
self.imviz = imviz_helper

catalogs_plugin = self.imviz.app.get_tray_item_from_name('imviz-catalogs')
catalogs_plugin.plugin_opened = True
catalogs_plugin.plugin_active = True
# running the search without any data loaded into Imviz
catalogs_plugin.vue_do_search()

Expand All @@ -54,7 +54,7 @@ def test_plugin_image_no_result(self, imviz_helper, image_2d_wcs):
self.imviz = imviz_helper

catalogs_plugin = self.imviz.app.get_tray_item_from_name('imviz-catalogs')
catalogs_plugin.plugin_opened = True
catalogs_plugin.plugin_active = True
catalogs_plugin.vue_do_search()

# number of results should be 0
Expand Down Expand Up @@ -91,7 +91,7 @@ def test_plugin_image_with_result(self, imviz_helper, tmp_path):
self.imviz = imviz_helper

catalogs_plugin = self.imviz.app.get_tray_item_from_name('imviz-catalogs')
catalogs_plugin.plugin_opened = True
catalogs_plugin.plugin_active = True
# This basically calls the following under the hood:
# skycoord_center = SkyCoord(6.62754354, 1.54466139, unit="deg")
# zoom_radius = r_max = 3 * u.arcmin
Expand Down
4 changes: 2 additions & 2 deletions jdaviz/configs/imviz/tests/test_line_profile_xy.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class TestLineProfileXY(BaseImviz_WCS_NoWCS):
def test_plugin_linked_by_pixel(self):
"""Go through plugin logic but does not check plot contents."""
lp_plugin = self.imviz.app.get_tray_item_from_name('imviz-line-profile-xy')
lp_plugin.plugin_opened = True
lp_plugin.plugin_active = True

lp_plugin._on_viewers_changed() # Populate plugin menu items.
assert lp_plugin.viewer_items == ['imviz-0']
Expand Down Expand Up @@ -66,7 +66,7 @@ def test_plugin_linked_by_pixel(self):
assert lp_plugin.plot_available

# Nothing should update on "l" when plugin closed.
lp_plugin.plugin_opened = False
lp_plugin.plugin_active = False
self.viewer.on_mouse_or_key_event(
{'event': 'keydown', 'key': 'l', 'domain': {'x': 5.1, 'y': 5}})
lp_plugin.selected_x = '1.1'
Expand Down
Loading

0 comments on commit baa1eaa

Please sign in to comment.