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

clone viewer tool #74

Merged
merged 3 commits into from
Dec 18, 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
7 changes: 6 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
0.1.0 - unreleased
0.2.0 - unreleased
------------------

* Clone viewer tool. [#74]

0.1.0 (12-14-2023)
------------------

* Initial release of lcviz with support to import time-series light curves via lightkurve and
Expand Down
1 change: 1 addition & 0 deletions lcviz/data/icons/viewer_clone.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion lcviz/plugins/ephemeris/ephemeris.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,8 @@ def vue_period_double(self, *args):
self.period *= 2

def _check_if_phase_viewer_exists(self, *args):
self.phase_viewer_exists = self.phase_viewer_id in self.app.get_viewer_ids()
viewer_base_refs = [id.split('[')[0] for id in self.app.get_viewer_ids()]
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm OK with assuming there aren't other square brackets in the viewer ID. Just leaving a comment here to hopefully remind us both that, going forward, we're assuming that.

Copy link
Member Author

Choose a reason for hiding this comment

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

yep, this is very much assuming we always stick to these syntax rules... but if we ever want viewer renaming, we can always move these things into attributes rather than parsing the viewer name itself, I just don't want to overengineer it until then.

self.phase_viewer_exists = self.phase_viewer_id in viewer_base_refs

def _on_component_add(self, lbl):
self.hub.broadcast(EphemerisComponentChangedMessage(old_lbl=None, new_lbl=lbl,
Expand Down
10 changes: 10 additions & 0 deletions lcviz/tests/test_viewers.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,13 @@ def test_reset_limits(helper, light_curve_like_kepler_quarter):

tv.state._reset_y_limits()
assert tv.state.y_min == orig_ylims[0]


def test_clone(helper, light_curve_like_kepler_quarter):
helper.load_data(light_curve_like_kepler_quarter)

def_viewer = helper.viewers['flux-vs-time']
assert def_viewer._obj._get_clone_viewer_reference() == 'flux-vs-time[1]'

new_viewer = def_viewer._obj.clone_viewer()
assert new_viewer._obj._get_clone_viewer_reference() == 'flux-vs-time[2]'
21 changes: 21 additions & 0 deletions lcviz/tools.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
import os

from glue.config import viewer_tool
from glue.viewers.common.tool import Tool

from jdaviz.core.tools import SidebarShortcutPlotOptions, SidebarShortcutExportPlot

ICON_DIR = os.path.normpath(os.path.join(os.path.dirname(__file__), 'data', 'icons'))

# point to the lcviz-version of plot options instead of jdaviz's
SidebarShortcutPlotOptions.plugin_name = 'lcviz-plot-options'
SidebarShortcutExportPlot.plugin_name = 'lcviz-export-plot'


__all__ = ['ViewerClone']


@viewer_tool
class ViewerClone(Tool):
icon = os.path.join(ICON_DIR, 'viewer_clone')
tool_id = 'lcviz:viewer_clone'
action_text = 'Clone viewer'
tool_tip = 'Clone this viewer'

def activate(self):
self.viewer.clone_viewer()

Check warning on line 26 in lcviz/tools.py

View check run for this annotation

Codecov / codecov/patch

lcviz/tools.py#L26

Added line #L26 was not covered by tests
39 changes: 37 additions & 2 deletions lcviz/viewers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from astropy import units as u
from astropy.time import Time

from jdaviz.core.events import NewViewerMessage
from jdaviz.core.registries import viewer_registry
from jdaviz.configs.default.plugins.viewers import JdavizViewerMixin
from jdaviz.configs.specviz.plugins.viewers import SpecvizProfileView
Expand All @@ -30,7 +31,7 @@ class TimeScatterView(JdavizViewerMixin, BqplotScatterView):
['jdaviz:boxzoom', 'jdaviz:xrangezoom', 'jdaviz:yrangezoom'],
['jdaviz:panzoom', 'jdaviz:panzoom_x', 'jdaviz:panzoom_y'],
['bqplot:xrange', 'bqplot:yrange', 'bqplot:rectangle'],
['jdaviz:sidebar_plot', 'jdaviz:sidebar_export']
['lcviz:viewer_clone', 'jdaviz:sidebar_plot', 'jdaviz:sidebar_export']
]
default_class = LightCurve
_state_cls = ScatterViewerState
Expand Down Expand Up @@ -209,12 +210,46 @@ def apply_roi(self, roi, use_current=False):

super().apply_roi(roi, use_current=use_current)

def _get_clone_viewer_reference(self):
base_name = self.reference.split("[")[0]
name = base_name
ind = 0
while name in self.jdaviz_helper.viewers.keys():
ind += 1
name = f"{base_name}[{ind}]"
return name

def clone_viewer(self):
name = self._get_clone_viewer_reference()

self.jdaviz_app._on_new_viewer(NewViewerMessage(self.__class__,
data=None,
sender=self.jdaviz_app),
vid=name, name=name)

this_viewer_item = self.jdaviz_app._get_viewer_item(self.reference)
this_state = self.state.as_dict()
for data in self.jdaviz_app.data_collection:
data_id = self.jdaviz_app._data_id_from_label(data.label)
visible = this_viewer_item['selected_data_items'].get(data_id, 'hidden')
self.jdaviz_app.set_data_visibility(name, data.label, visible == 'visible')
# TODO: don't revert color when adding same data to a new viewer
# (same happens when creating a phase-viewer from ephemeris plugin)

new_viewer = self.jdaviz_helper.viewers[name]._obj
for k, v in this_state.items():
if k in ('layers',):
continue
setattr(new_viewer.state, k, v)

return new_viewer.user_api


@viewer_registry("lcviz-phase-viewer", label="phase-vs-time")
class PhaseScatterView(TimeScatterView):
@property
def ephemeris_component(self):
return self.reference.split(':')[-1]
return self.reference.split('[')[0].split(':')[-1]

def _set_plot_x_axes(self, dc, component_labels, light_curve):
# setting of y_att will be handled by ephemeris plugin
Expand Down