Skip to content

Commit

Permalink
basic markers plugin implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
kecnry committed Jan 26, 2023
1 parent d9e71d6 commit b8247bc
Show file tree
Hide file tree
Showing 18 changed files with 356 additions and 1 deletion.
9 changes: 9 additions & 0 deletions docs/cubeviz/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ Subset Tools
:ref:`Subset Tools <imviz-subset-plugin>`
Imviz documentation describing the concept of subsets in Jdaviz.


Markers
=======

.. seealso::

:ref:`Markers <markers-plugin>`
Imviz documentation describing the markers plugin.

.. _slice:

Slice
Expand Down
10 changes: 10 additions & 0 deletions docs/imviz/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@ parameters, shape, and orientation (if applicable) all update concurrently.

Angle is counter-clockwise rotation around the center in degrees.

.. _markers-plugin:

Markers
=======

This plugin allows for interactively creating markers in any viewer and logging information about
the location of that marker into a table, which can then be exported via the API using
:meth:`~jdaviz.core.template_mixin.TableMixin.export_table`
(see :ref:`plugin-apis`).

.. _imviz-link-control:

Link Control
Expand Down
8 changes: 8 additions & 0 deletions docs/mosviz/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ Subset Tools
:ref:`Subset Tools <imviz-subset-plugin>`
Imviz documentation describing the concept of subsets in Jdaviz.

Markers
=======

.. seealso::

:ref:`Markers <markers-plugin>`
Imviz documentation describing the markers plugin.

Gaussian Smooth
===============

Expand Down
8 changes: 8 additions & 0 deletions docs/specviz/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ Subset Tools
:ref:`Subset Tools <imviz-subset-plugin>`
Imviz documentation describing the concept of subsets in Jdaviz.

Markers
=======

.. seealso::

:ref:`Markers <markers-plugin>`
Imviz documentation describing the markers plugin.

.. _gaussian-smooth:

Gaussian Smooth
Expand Down
8 changes: 8 additions & 0 deletions docs/specviz2d/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ Subset Tools

:ref:`Subset Tools <imviz-subset-plugin>`
Imviz documentation describing the concept of subsets in Jdaviz.

Markers
=======

.. seealso::

:ref:`Markers <markers-plugin>`
Imviz documentation describing the markers plugin.

.. _specviz2d-spectral-extraction:

Expand Down
1 change: 1 addition & 0 deletions jdaviz/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
'j-plugin-section-header': 'components/plugin_section_header.vue',
'j-number-uncertainty': 'components/number_uncertainty.vue',
'j-plugin-popout': 'components/plugin_popout.vue',
'plugin-table': 'components/plugin_table.vue',
'plugin-dataset-select': 'components/plugin_dataset_select.vue',
'plugin-subset-select': 'components/plugin_subset_select.vue',
'plugin-viewer-select': 'components/plugin_viewer_select.vue',
Expand Down
68 changes: 68 additions & 0 deletions jdaviz/components/plugin_table.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<template>
<div>
<v-row>
<v-select
v-model="headers_visible"
:items="headers_avail"
@change="$emit('update:headers_visible', $event)"
label="Columns"
multiple
>
<template v-slot:selection="{ item, index }">
<v-chip v-if="headers_visible.length <= 3">
<span>{{ item }}</span>
</v-chip>
<span
v-if="headers_visible.length > 3 && index === 0"
class="grey--text text-caption"
>
({{ headers_visible.length}} selected)
</span>
</template>
<template v-slot:prepend-item>
<v-list-item
ripple
@mousedown.prevent
@click="() => {if (headers_visible.length < headers_avail.length) { $emit('update:headers_visible', headers_avail)} else {$emit('update:headers_visible', [])}}"
>
<v-list-item-action>
<v-icon>
{{ headers_visible.length == headers_avail.length ? 'mdi-close-box' : headers_visible.length ? 'mdi-minus-box' : 'mdi-checkbox-blank-outline' }}
</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>
{{ headers_visible.length < headers_avail.length ? "Select All" : "Clear All" }}
</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-divider class="mt-2"></v-divider>
</template>
</v-select>
</v-row>

<v-row class="no-outside-padding">
<v-data-table
dense
:headers="headers_visible.map(item => {return {'text': item, 'value': item}})"
:items="items"
class="elevation-1"
></v-data-table>
</v-row>

<v-row v-if="clear_table" justify="end">
<v-btn
color="accent"
text
@click="clear_table"
>Clear Table
</v-btn>
</v-row>
</div>
</template>

<script>
module.exports = {
props: ['headers_visible', 'headers_avail', 'items', 'clear_table'],
};
</script>
1 change: 1 addition & 0 deletions jdaviz/configs/cubeviz/cubeviz.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ tray:
- g-metadata-viewer
- g-plot-options
- g-subset-plugin
- g-markers
- cubeviz-slice
- g-gaussian-smooth
- g-collapse
Expand Down
1 change: 1 addition & 0 deletions jdaviz/configs/default/plugins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
from .metadata_viewer.metadata_viewer import * # noqa
from .export_plot.export_plot import * # noqa
from .plot_options.plot_options import * # noqa
from .markers.markers import * # noqa
1 change: 1 addition & 0 deletions jdaviz/configs/default/plugins/markers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .markers import * # noqa
115 changes: 115 additions & 0 deletions jdaviz/configs/default/plugins/markers/markers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
from traitlets import observe

from glue_jupyter.bqplot.image import BqplotImageView

from jdaviz.configs.imviz.helper import layer_is_image_data
from jdaviz.configs.cubeviz.helper import layer_is_cube_image_data
from jdaviz.core.marks import MarkersMark
from jdaviz.core.registries import tray_registry
from jdaviz.core.template_mixin import PluginTemplateMixin, ViewerSelectMixin, TableMixin
from jdaviz.core.user_api import PluginUserApi

__all__ = ['Markers']


@tray_registry('g-markers', label="Markers")
class Markers(PluginTemplateMixin, ViewerSelectMixin, TableMixin):
"""
See the :ref:`Markers Plugin Documentation <imviz-markers>` for more details.
Only the following attributes and methods are available through the
:ref:`public plugin API <plugin-apis>`:
* :meth:`~jdaviz.core.template_mixin.PluginTemplateMixin.show`
* :meth:`~jdaviz.core.template_mixin.PluginTemplateMixin.open_in_tray`
"""
template_file = __file__, "markers.vue"

@property
def user_api(self):
return PluginUserApi(self, expose=('clear_table', 'export_table',))

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
headers = ['x', 'y']

if self.config in ['imviz', 'cubeviz', 'mosviz', 'specviz2d']:
headers += ['viewer']
if self.config in ['imviz', 'cubeviz']:
headers += ['data_label']

self.table.headers_avail = headers
self.table.headers_visible = headers

def _get_mark(self, viewer):
matches = [mark for mark in viewer.figure.marks if isinstance(mark, MarkersMark)]
if len(matches):
return matches[0]
mark = MarkersMark(viewer)
viewer.figure.marks = viewer.figure.marks + [mark]
return mark

@property
def marks(self):
return {viewer_id: self._get_mark(viewer)
for viewer_id, viewer in self.app._viewer_store.items()}

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

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

# subscribe/unsubscribe to keypress events across all viewers
for viewer in self.app._viewer_store.values():
callback = self._viewer_callback(viewer, self._on_viewer_key_event)

if self.plugin_opened:
viewer.add_event_callback(callback, events=['keydown'])
else:
viewer.remove_event_callback(callback)

def _on_viewer_key_event(self, viewer, data):
if data['event'] == 'keydown' and data['key'] in ('m', 'M'):
# TODO: refactor to share code with mouseover display if PR#1976 merged
# TODO: merge with mouseover display entirely and show mouseover info in table

x = data['domain']['x']
y = data['domain']['y']

if x is None or y is None: # Out of bounds
return

row_info = {'x': x, 'y': y}

if 'viewer' in self.table.headers_avail:
row_info['viewer'] = viewer.reference_id

if isinstance(viewer, BqplotImageView):
# TODO: access viewer.active_image_layer if PR#1976 merged
visible_layers = [layer for layer in viewer.state.layers
if (layer.visible and (layer_is_image_data(layer.layer) or layer_is_cube_image_data(layer.layer)))] # noqa

if len(visible_layers) == 0:
return

active_layer = visible_layers[-1]

row_info['data_label'] = active_layer.layer.label
elif 'data_label' in self.table.headers_avail:
row_info['data_label'] = ''

self.table.add_row(row_info)

self._get_mark(viewer).append_xy(x, y)

def clear_table(self):
"""
Clear all entries/markers from the current table.
"""
super().clear_table()
for mark in self.marks.values():
mark.clear()
17 changes: 17 additions & 0 deletions jdaviz/configs/default/plugins/markers/markers.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<template>
<j-tray-plugin
description='Create and export markers. Press "m" with the cursor over a viewer to log the mouseover information.'
:link="'https://jdaviz.readthedocs.io/en/'+vdocs+'/'+config+'/plugins.html#markers'"
:popout_button="popout_button">

<plugin-table
:headers_visible.sync="table_headers_visible"
:headers_avail="table_headers_avail"
:items="table_items"
:clear_table="clear_table"
></plugin-table>



</j-tray-plugin>
</template>
1 change: 1 addition & 0 deletions jdaviz/configs/imviz/imviz.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ tray:
- g-metadata-viewer
- g-plot-options
- g-subset-plugin
- g-markers
- imviz-links-control
- imviz-compass
- imviz-line-profile-xy
Expand Down
1 change: 1 addition & 0 deletions jdaviz/configs/mosviz/mosviz.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ tray:
- g-metadata-viewer
- g-plot-options
- g-subset-plugin
- g-markers
- g-gaussian-smooth
- g-slit-overlay
- g-model-fitting
Expand Down
1 change: 1 addition & 0 deletions jdaviz/configs/specviz/specviz.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ tray:
- g-metadata-viewer
- g-plot-options
- g-subset-plugin
- g-markers
- g-gaussian-smooth
- g-model-fitting
- g-unit-conversion
Expand Down
1 change: 1 addition & 0 deletions jdaviz/configs/specviz2d/specviz2d.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ tray:
- g-metadata-viewer
- g-plot-options
- g-subset-plugin
- g-markers
- spectral-extraction
- g-gaussian-smooth
- g-model-fitting
Expand Down
8 changes: 7 additions & 1 deletion jdaviz/core/marks.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
'PluginMark', 'PluginLine', 'PluginScatter',
'LineAnalysisContinuum', 'LineAnalysisContinuumCenter',
'LineAnalysisContinuumLeft', 'LineAnalysisContinuumRight',
'LineUncertainties', 'ScatterMask', 'SelectedSpaxel']
'LineUncertainties', 'ScatterMask', 'SelectedSpaxel', 'MarkersMark']


class OffscreenLinesMarks(HubListener):
Expand Down Expand Up @@ -542,3 +542,9 @@ def __init__(self, **kwargs):
class SelectedSpaxel(Lines):
def __init__(self, **kwargs):
super().__init__(**kwargs)


class MarkersMark(PluginScatter):
def __init__(self, viewer, **kwargs):
kwargs.setdefault('marker', 'circle')
super().__init__(viewer, **kwargs)
Loading

0 comments on commit b8247bc

Please sign in to comment.