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

enable coords-info and markers plugin #22

Merged
merged 2 commits into from
Jun 1, 2023
Merged
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
6 changes: 3 additions & 3 deletions lcviz/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ class LCviz(ConfigHelper):
'tab_headers': True},
'dense_toolbar': False,
'context': {'notebook': {'max_height': '600px'}}},
'toolbar': ['g-data-tools', 'g-subset-tools'],
'tray': ['g-metadata-viewer', 'g-subset-plugin',
'lcviz-plot-options', 'ephemeris', 'g-export-plot'],
'toolbar': ['g-data-tools', 'g-subset-tools', 'lcviz-coords-info'],
'tray': ['g-metadata-viewer', 'lcviz-plot-options', 'g-subset-plugin',
'lcviz-markers', 'ephemeris', 'g-export-plot'],
'viewer_area': [{'container': 'col',
'children': [{'container': 'row',
'viewers': [{'name': 'flux-vs-time',
Expand Down
4 changes: 3 additions & 1 deletion lcviz/plugins/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
from .coords_info.coords_info import * # noqa
from .ephemeris.ephemeris import * # noqa
from .plot_options.plot_options import * # noqa
from .markers.markers import * # noqa
from .plot_options.plot_options import * # noqa
1 change: 1 addition & 0 deletions lcviz/plugins/coords_info/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .coords_info import * # noqa
124 changes: 124 additions & 0 deletions lcviz/plugins/coords_info/coords_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import numpy as np

from glue.core.subset_group import GroupedSubset
from jdaviz.configs.imviz.plugins.coords_info import CoordsInfo
from jdaviz.core.registries import tool_registry

from lcviz.viewers import TimeScatterView, PhaseScatterView


__all__ = ['CoordsInfo']


@tool_registry('lcviz-coords-info')
class CoordsInfo(CoordsInfo):
_supported_viewer_classes = (TimeScatterView, PhaseScatterView)
_viewer_classes_with_marker = (TimeScatterView, PhaseScatterView)

def update_display(self, viewer, x, y):
self._dict = {}

if not len(viewer.state.layers):
return

is_phase = isinstance(viewer, PhaseScatterView)
# TODO: update with display_unit when supported in lcviz
x_unit = '' if is_phase else str(viewer.time_unit)
y_unit = str(viewer.data()[0].flux.unit)

def _cursor_fallback():
self._dict['axes_x'] = x
self._dict['axes_x:unit'] = x_unit
self._dict['axes_y'] = y
self._dict['axes_y:unit'] = y_unit

self._dict['data_label'] = ''
self._dict['time'] = x if not is_phase else np.nan
self._dict['phase'] = x if is_phase else np.nan
self._dict['flux'] = y
self._dict['ephemeris'] = ''

self.row2_title = ''
self.row2_text = ''
self.row3_title = ''
self.row3_text = ''
self.icon = 'mdi-cursor-default'
self.marks[viewer._reference_id].visible = False

self.row1a_title = 'Cursor'
self.row1a_text = f'{x:10.5e}, {y:10.5e}'

# show the locked marker/coords only if either no tool or the default tool is active
if self.dataset.selected == 'none':
_cursor_fallback()
return

xrange = abs(viewer.state.x_max - viewer.state.x_min)
yrange = abs(viewer.state.y_max - viewer.state.y_min)

# Snap to the closest data point
closest_distsq = None
closest_x = None
closest_y = None
closest_icon = None
closest_lyr = None
for lyr in viewer.layers:
if isinstance(lyr.layer, GroupedSubset):
continue
if self.dataset.selected == 'auto' and not lyr.visible:
continue
if self.dataset.selected != 'auto' and self.dataset.selected != lyr.layer.label:
continue

scatter = lyr.scatter
lyr_x, lyr_y = scatter.x, scatter.y
# NOTE: unlike specviz which determines the closest point in x per-layer,
# this determines the closest point in x/y per-layer in pixel-space
# (making it easier to get the snapping point into shallow eclipses, etc)
distsqs = ((lyr_x - x)/xrange)**2 + ((lyr_y - y)/yrange)**2
cur_i = np.nanargmin(distsqs)
cur_x, cur_y = float(lyr_x[cur_i]), float(lyr_y[cur_i])
cur_distsq = distsqs[cur_i]

if (closest_distsq is None) or (cur_distsq < closest_distsq):
closest_distsq = cur_distsq
closest_i = cur_i
closest_x = cur_x
closest_y = cur_y
closest_icon = self.app.state.layer_icons.get(lyr.layer.label, '')
closest_lyr = lyr
self._dict['data_label'] = lyr.layer.label

if closest_lyr is None:
_cursor_fallback()
return

self.row2_title = 'Phase' if is_phase else 'Time'
if is_phase:
self.row2_text = f'{closest_x:0.05f}'
component_labels = [comp.label for comp in closest_lyr.layer.components]
time_comp = closest_lyr.layer.components[component_labels.index('World 0')]
times = closest_lyr.layer.get_data(time_comp)
self._dict['time'] = float(times[closest_i])
self._dict['phase'] = closest_x
self._dict['ephemeris'] = viewer.reference.split(':')[1]
else:
self.row2_text = f'{closest_x:10.5e} {x_unit}'
self._dict['time'] = closest_x
self._dict['phase'] = np.nan
self._dict['ephemeris'] = ''

self._dict['axes_x'] = closest_x
self._dict['axes_x:unit'] = x_unit
self._dict['index'] = float(closest_i)

self.row3_title = 'Flux'
self.row3_text = f'{closest_y:10.5e} {y_unit}'
self._dict['axes_y'] = closest_y
self._dict['axes_y:unit'] = y_unit
self._dict['flux'] = closest_y

self.icon = closest_icon

self.marks[viewer._reference_id].update_xy([closest_x], [closest_y]) # noqa
self.marks[viewer._reference_id].visible = True
1 change: 1 addition & 0 deletions lcviz/plugins/markers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .markers import * # noqa
22 changes: 22 additions & 0 deletions lcviz/plugins/markers/markers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import numpy as np

from jdaviz.configs.default.plugins import Markers
from jdaviz.core.registries import tray_registry

__all__ = ['Markers']


@tray_registry('lcviz-markers', label="Markers")
class Markers(Markers):
_default_table_values = {'time': np.nan,
'phase': np.nan,
'ephemeris': '',
'flux': np.nan}

def __init__(self, *args, **kwargs):
kwargs['headers'] = ['time', 'phase', 'ephemeris', 'flux', 'viewer']
super().__init__(*args, **kwargs)

@property
def coords_info(self):
return self.app.session.application._tools['lcviz-coords-info']
103 changes: 103 additions & 0 deletions lcviz/tests/test_plugin_markers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import numpy as np
from numpy.testing import assert_allclose

from jdaviz.core.marks import MarkersMark


def _get_markers_from_viewer(viewer):
return [m for m in viewer.figure.marks if isinstance(m, MarkersMark)][0]


def _assert_dict_allclose(dict1, dict2):
assert dict1.keys() == dict2.keys()
for k, v in dict1.items():
if isinstance(v, float):
assert_allclose(v, dict2.get(k))
elif isinstance(v, (tuple, list)):
assert_allclose(np.asarray(v), np.asarray(dict2.get(k)))
else:
assert v == dict2.get(k)


def test_plugin_markers(helper, light_curve_like_kepler_quarter):
helper.load_data(light_curve_like_kepler_quarter)
tv = helper.app.get_viewer(helper._default_time_viewer_reference_name)

mp = helper.plugins['Markers']
label_mouseover = mp._obj.coords_info
mp.open_in_tray()

# test event in flux-vs-time viewer
label_mouseover._viewer_mouse_event(tv,
{'event': 'mousemove',
'domain': {'x': 0, 'y': 0}})

assert label_mouseover.as_text() == ('Cursor 0.00000e+00, 0.00000e+00',
'Time 5.45833e+00 d',
'Flux 9.67587e-01')

_assert_dict_allclose(label_mouseover.as_dict(), {'data_label': 'Light curve',
'time': 5.4583335,
'phase': np.nan,
'ephemeris': '',
'axes_x': 5.4583335,
'axes_x:unit': 'd',
'index': 262.0,
'axes_y': 0.96758735,
'axes_y:unit': '',
'flux': 0.96758735})

mp._obj._on_viewer_key_event(tv, {'event': 'keydown',
'key': 'm'})
assert len(mp.export_table()) == 1
assert len(_get_markers_from_viewer(tv).x) == 1

ephem = helper.plugins['Ephemeris']
pv = ephem.create_phase_viewer()

# test event in flux-vs-phase viewer
label_mouseover._viewer_mouse_event(pv,
{'event': 'mousemove',
'domain': {'x': 0.5, 'y': 0}})

assert label_mouseover.as_text() == ('Cursor 5.00000e-01, 0.00000e+00',
'Phase 0.45833',
'Flux 9.67587e-01')

_assert_dict_allclose(label_mouseover.as_dict(), {'data_label': 'Light curve',
'time': 5.458333374001086,
'phase': 0.4583333730697632,
'ephemeris': 'default',
'axes_x': 0.4583333730697632,
'axes_x:unit': '',
'index': 262.0,
'axes_y': 0.9675873517990112,
'axes_y:unit': '',
'flux': 0.9675873517990112})

mp._obj._on_viewer_key_event(pv, {'event': 'keydown',
'key': 'm'})
assert len(mp.export_table()) == 2
assert len(_get_markers_from_viewer(tv).x) == 1
assert len(_get_markers_from_viewer(pv).x) == 1

# test event in flux-vs-phase viewer (with cursor only)
label_mouseover.dataset.selected = 'none'
label_mouseover._viewer_mouse_event(pv,
{'event': 'mousemove',
'domain': {'x': 0.6, 'y': 0}})

print(label_mouseover.as_text())
assert label_mouseover.as_text() == ('Cursor 6.00000e-01, 0.00000e+00',
'',
'')

_assert_dict_allclose(label_mouseover.as_dict(), {'axes_x': 0.6,
'axes_x:unit': '',
'axes_y': 0,
'axes_y:unit': '',
'data_label': '',
'time': np.nan,
'phase': 0.6,
'flux': 0,
'ephemeris': ''})
2 changes: 1 addition & 1 deletion lcviz/viewers.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from lightkurve import LightCurve


__all__ = ['TimeScatterView']
__all__ = ['TimeScatterView', 'PhaseScatterView']


@viewer_registry("lcviz-time-viewer", label="flux-vs-time")
Expand Down