Skip to content

Commit

Permalink
cubeviz spectral extraction live-previews (spacetelescope#2733)
Browse files Browse the repository at this point in the history
* migrate temp disabling live-previews from lcviz
* live-preview mark in cubeviz spectral extraction
* changelog entry
  • Loading branch information
kecnry authored Mar 7, 2024
1 parent fbef31f commit c731eef
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 4 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ Cubeviz

- New aperture photometry plugin that can perform aperture photometry on selected cube slice. [#2666]

- Live previews in spectral extraction plugin. [#2733]

Imviz
^^^^^

Expand Down
1 change: 1 addition & 0 deletions jdaviz/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ def to_unit(self, data, cid, values, original_units, target_units):
'j-plugin-section-header': 'components/plugin_section_header.vue',
'j-number-uncertainty': 'components/number_uncertainty.vue',
'j-plugin-popout': 'components/plugin_popout.vue',
'plugin-previews-temp-disabled': 'components/plugin_previews_temp_disabled.vue', # noqa
'plugin-table': 'components/plugin_table.vue',
'plugin-dataset-select': 'components/plugin_dataset_select.vue',
'plugin-subset-select': 'components/plugin_subset_select.vue',
Expand Down
25 changes: 25 additions & 0 deletions jdaviz/components/plugin_previews_temp_disabled.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<template>
<v-alert v-if="previews_temp_disabled && show_live_preview" type='warning' style="margin-left: -12px; margin-right: -12px">
Live-updating is temporarily disabled (last update took {{previews_last_time}}s)
<v-row justify='center'>
<j-tooltip tooltipcontent='hide live preview (can be re-enabled from the settings section in the plugin).' span_style="width: 100%">
<v-btn style='width: 100%' @click="() => {$emit('update:show_live_preview', false); $emit('disable_previews')}">
disable previews
</v-btn>
</j-tooltip>
</v-row>
<v-row justify='center'>
<j-tooltip tooltipcontent='manually update live-previews based on current plugin inputs.' span_style="width: 100%">
<v-btn style='width: 100%' @click="$emit('update:previews_temp_disabled', false)">
update preview
</v-btn>
</j-tooltip>
</v-row>
</v-alert>
</template>

<script>
module.exports = {
props: ['previews_temp_disabled', 'show_live_preview', 'previews_last_time']
};
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,20 @@

from jdaviz.core.custom_traitlets import FloatHandleEmpty
from jdaviz.core.events import SnackbarMessage, SliceValueUpdatedMessage
from jdaviz.core.marks import SpectralExtractionPreview
from jdaviz.core.registries import tray_registry
from jdaviz.core.template_mixin import (PluginTemplateMixin,
DatasetSelectMixin,
SelectPluginComponent,
ApertureSubsetSelectMixin,
ApertureSubsetSelect,
AddResultsMixin,
with_spinner)
skip_if_no_updates_since_last_active,
with_spinner, with_temp_disable)
from jdaviz.core.user_api import PluginUserApi
from jdaviz.core.region_translators import regions2aperture
from jdaviz.configs.cubeviz.plugins.parsers import _return_spectrum_with_correct_units
from jdaviz.configs.cubeviz.plugins.viewers import CubevizProfileView


__all__ = ['SpectralExtraction']
Expand Down Expand Up @@ -59,6 +62,7 @@ class SpectralExtraction(PluginTemplateMixin, ApertureSubsetSelectMixin,
"""
template_file = __file__, "spectral_extraction.vue"
uses_active_status = Bool(True).tag(sync=True)
show_live_preview = Bool(True).tag(sync=True)

# feature flag for background cone support
dev_bg_support = Bool(False).tag(sync=True) # when enabling: add entries to docstring
Expand Down Expand Up @@ -458,3 +462,60 @@ def _set_default_results_label(self, event={}):
):
label += f' ({self.aperture_selected})'
self.results_label_default = label

@property
def marks(self):
marks = {}
for id, viewer in self.app._viewer_store.items():
if not isinstance(viewer, CubevizProfileView):
continue
for mark in viewer.figure.marks:
if isinstance(mark, SpectralExtractionPreview):
marks[id] = mark
break
else:
mark = SpectralExtractionPreview(viewer, visible=self.is_active)
viewer.figure.marks = viewer.figure.marks + [mark]
marks[id] = mark
return marks

def _clear_marks(self):
for mark in self.marks.values():
if mark.visible:
mark.clear()
mark.visible = False

@observe('is_active', 'show_live_preview')
def _toggle_marks(self, event={}):
visible = self.show_live_preview and self.is_active

if not visible:
self._clear_marks()
elif event.get('name', '') in ('is_active', 'show_live_preview'):
# then the marks themselves need to be updated
self._live_update(event)

@observe('aperture_selected', 'function_selected',
'wavelength_dependent', 'reference_wavelength',
'aperture_method_selected',
'previews_temp_disabled')
@skip_if_no_updates_since_last_active()
@with_temp_disable(timeout=0.3)
def _live_update(self, event={}):
if not self.show_live_preview or not self.is_active:
self._clear_marks()
return

if event.get('name', '') not in ('is_active', 'show_live_preview'):
# mark visibility hasn't been handled yet
self._toggle_marks()

try:
sp = self.collapse_to_spectrum(add_data=False)
except Exception:
self._clear_marks()
return

for mark in self.marks.values():
mark.update_xy(sp.spectral_axis.value, sp.flux.value)
mark.visible = True
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,26 @@
:popout_button="popout_button"
:disabled_msg="disabled_msg">

<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 class="plugin-expansion-panel-content">
<v-row>
<v-switch
v-model="show_live_preview"
label="Show live-extraction"
hint="Whether to compute/show extraction when making changes to input parameters. Disable if live-preview becomes laggy."
persistent-hint
></v-switch>
</v-row>
</v-expansion-panel-content>
</v-expansion-panel>
</v-expansion-panels>
</v-row>

<div @mouseover="() => active_step='ap'">
<j-plugin-section-header :active="active_step==='ap'">Aperture</j-plugin-section-header>

Expand Down Expand Up @@ -166,7 +186,11 @@
</span>
</v-row>


<plugin-previews-temp-disabled
:previews_temp_disabled.sync="previews_temp_disabled"
:previews_last_time="previews_last_time"
:show_live_preview.sync="show_live_preview"
/>

<plugin-add-results
:label.sync="results_label"
Expand Down
7 changes: 6 additions & 1 deletion jdaviz/core/marks.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
'LineAnalysisContinuum', 'LineAnalysisContinuumCenter',
'LineAnalysisContinuumLeft', 'LineAnalysisContinuumRight',
'LineUncertainties', 'ScatterMask', 'SelectedSpaxel', 'MarkersMark', 'FootprintOverlay',
'ApertureMark']
'ApertureMark', 'SpectralExtractionPreview']

accent_color = "#c75d2c"

Expand Down Expand Up @@ -663,6 +663,11 @@ def __init__(self, viewer, id, **kwargs):
super().__init__(viewer, **kwargs)


class SpectralExtractionPreview(PluginLine):
def __init__(self, viewer, **kwargs):
super().__init__(viewer, **kwargs)


class HistogramMark(Lines):
def __init__(self, min_max_value, scales, **kwargs):
# Vertical line in LinearScale
Expand Down
35 changes: 34 additions & 1 deletion jdaviz/core/template_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@


__all__ = ['show_widget', 'TemplateMixin', 'PluginTemplateMixin',
'skip_if_no_updates_since_last_active', 'with_spinner',
'skip_if_no_updates_since_last_active', 'with_spinner', 'with_temp_disable',
'ViewerPropertiesMixin',
'BasePluginComponent',
'SelectPluginComponent', 'UnitSelectPluginComponent', 'EditableSelectPluginComponent',
Expand Down Expand Up @@ -307,6 +307,37 @@ def wrapper(self, *args, **kwargs):
return decorator


def with_temp_disable(timeout=0.3,
disable_traitlet='previews_temp_disabled',
time_traitlet='previews_last_time'):
"""
decorator on a plugin method to track the amount of time the wrapped method takes, and disable
live plugin-previews if it takes longer than ``timeout`` seconds. The wrapped method should
also observe ``disable_traitlet`` ('previews_temp_disabled', by default).
This should be used with::
<plugin-previews-temp-disabled
:previews_temp_disabled.sync="previews_temp_disabled"
:previews_last_time="previews_last_time"
:show_live_preview.sync="show_live_preview"
/>
"""
def decorator(meth):
def wrapper(self, *args, **kwargs):
if getattr(self, disable_traitlet):
return
start = time.time()
ret_ = meth(self, *args, **kwargs)
exec_time = np.round(time.time() - start, 2)
setattr(self, time_traitlet, exec_time)
if exec_time > timeout:
setattr(self, disable_traitlet, True)
return ret_
return wrapper
return decorator


class PluginTemplateMixin(TemplateMixin):
"""
This base class can be inherited by all sidebar/tray plugins to expose common functionality.
Expand All @@ -319,6 +350,8 @@ class PluginTemplateMixin(TemplateMixin):
keep_active = Bool(False).tag(sync=True) # noqa whether the live-preview marks show regardless of active state, inapplicable unless uses_active_status is True
is_active = Bool(False).tag(sync=True) # noqa read-only: whether the previews should be shown according to plugin_opened and keep_active
spinner = Bool(False).tag(sync=True) # noqa use along-side @with_spinner() and <plugin-add-results :action_spinner="spinner">
previews_temp_disabled = Bool(False).tag(sync=True) # noqa use along-side @with_temp_disable() and <plugin-previews-temp-disabled :previews_temp_disabled.sync="previews_temp_disabled" :previews_last_time="previews_last_time" :show_live_preview.sync="show_live_preview"/>
previews_last_time = Float(0).tag(sync=True)

def __init__(self, **kwargs):
self._viewer_callbacks = {}
Expand Down

0 comments on commit c731eef

Please sign in to comment.