diff --git a/lcviz/components/components.py b/lcviz/components/components.py index 33450407..5b558a50 100644 --- a/lcviz/components/components.py +++ b/lcviz/components/components.py @@ -1,13 +1,153 @@ from astropy import units as u +from functools import cached_property + from ipyvuetify import VuetifyTemplate from glue.core import HubListener from traitlets import List, Unicode -from jdaviz.core.template_mixin import SelectPluginComponent +from jdaviz.core.template_mixin import DatasetSelect, SelectPluginComponent + +from lcviz.events import (EphemerisComponentChangedMessage, + FluxOriginChangedMessage) + +__all__ = ['EphemerisSelect', 'EphemerisSelectMixin', + 'FluxOriginSelect', 'FluxOriginSelectMixin'] + + +class EphemerisSelect(SelectPluginComponent): + """ + Plugin select for ephemeris components defined by the Ephemeris plugin. + + Useful API methods/attributes: + + * :meth:`~SelectPluginComponent.choices` + * ``selected`` + * :attr:`selected_obj` + * :meth:`~SelectPluginComponent.select_default` + """ + + """ + Traitlets (in the object, custom traitlets in the plugin): + + * ``items`` (list of dicts with keys: label) + * ``selected`` (string) + + Properties (in the object only): + + * ``selected_obj`` + + To use in a plugin: + + * create traitlets with default values + * register with all the automatic logic in the plugin's init by passing the string names + of the respective traitlets + * use component in plugin template (see below) + * refer to properties above based on the interally stored reference to the + instantiated object of this component + + Example template (label and hint are optional):: + + -from lcviz.events import FluxOriginChangedMessage + """ + def __init__(self, plugin, items, selected, + default_text='No ephemeris', manual_options=[], + default_mode='first'): + """ + Parameters + ---------- + plugin + the parent plugin object + items : str + the name of the items traitlet defined in ``plugin`` + selected : str + the name of the selected traitlet defined in ``plugin`` + default_text : str or None + the text to show for no selection. If not provided or None, no entry will be provided + in the dropdown for no selection. + manual_options: list + list of options to provide that are not automatically populated by ephemerides. If + ``default`` text is provided but not in ``manual_options`` it will still be included as + the first item in the list. + """ + super().__init__(plugin, items=items, selected=selected, + default_text=default_text, manual_options=manual_options, + default_mode=default_mode) + self.hub.subscribe(self, EphemerisComponentChangedMessage, + handler=self._ephem_component_change) -__all__ = ['FluxOriginSelect', 'FluxOriginSelectMixin'] + @cached_property + def ephemeris_plugin(self): + return self.app._jdaviz_helper.plugins.get('Ephemeris', None) + + @cached_property + def selected_obj(self): + if self.selected in self._manual_options: + return None + return self.ephemeris_plugin.ephemerides.get(self.selected, None) + + def get_data_for_dataset(self, dataset, ycomp='flux'): + if not isinstance(dataset, DatasetSelect): # pragma: no cover + raise ValueError("dataset must be DatasetSelect object") + if self.selected in self._manual_options: + return dataset.selected_obj + return self.ephemeris_plugin.get_data(dataset.selected, self.selected) + + def _ephem_component_change(self, msg=None): + type = getattr(msg, 'type', None) + if type == 'remove' and msg.old_lbl in self.choices: + self.items = [item for item in self.items if item['label'] != msg.old_lbl] + self._apply_default_selection() + elif type == 'rename' and msg.old_lbl in self.choices: + was_selected = self.selected == msg.old_lbl + self.items = [item if item['label'] != msg.old_lbl else {'label': msg.new_lbl} + for item in self.items] + if was_selected: + self.selected = msg.new_lbl + elif type == 'add' and msg.new_lbl not in self.choices: + self.items = self.items + [{'label': msg.new_lbl}] + else: + # something might be out of sync, build from scratch + manual_items = [{'label': label} for label in self.manual_options] + self.items = manual_items + [{'label': component} + for component in self.ephemeris_plugin.ephemerides.keys()] + self._apply_default_selection() + + +class EphemerisSelectMixin(VuetifyTemplate, HubListener): + """ + Applies the EphemerisSelect component as a mixin in the base plugin. This + automatically adds traitlets as well as new properties to the plugin with minimal + extra code. For multiple instances or custom traitlet names/defaults, use the + component instead. + + To use in a plugin: + + * add ``EphemerisSelectMixin`` as a mixin to the class + * use the traitlets available from the plugin or properties/methods available from + ``plugin.ephemeris``. + + Example template (label and hint are optional):: + + + + """ + ephemeris_items = List().tag(sync=True) + ephemeris_selected = Unicode().tag(sync=True) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.ephemeris = EphemerisSelect(self, 'ephemeris_items', 'ephemeris_selected') class FluxOriginSelect(SelectPluginComponent): diff --git a/lcviz/plugins/binning/binning.py b/lcviz/plugins/binning/binning.py index 7be2a514..62f8afaf 100644 --- a/lcviz/plugins/binning/binning.py +++ b/lcviz/plugins/binning/binning.py @@ -18,7 +18,7 @@ from lcviz.helper import _default_time_viewer_reference_name from lcviz.marks import LivePreviewBinning from lcviz.parsers import _data_with_reftime -from lcviz.template_mixin import EphemerisSelectMixin +from lcviz.components import EphemerisSelectMixin __all__ = ['Binning'] diff --git a/lcviz/template_mixin.py b/lcviz/template_mixin.py deleted file mode 100644 index 97c56a7e..00000000 --- a/lcviz/template_mixin.py +++ /dev/null @@ -1,145 +0,0 @@ -from functools import cached_property -from traitlets import List, Unicode -from ipyvuetify import VuetifyTemplate -from glue.core import HubListener - -from jdaviz.core.template_mixin import DatasetSelect, SelectPluginComponent -from lcviz.events import EphemerisComponentChangedMessage - -__all__ = ['EphemerisSelect', 'EphemerisSelectMixin'] - - -class EphemerisSelect(SelectPluginComponent): - """ - Plugin select for ephemeris components defined by the Ephemeris plugin. - - Useful API methods/attributes: - - * :meth:`~SelectPluginComponent.choices` - * ``selected`` - * :attr:`selected_obj` - * :meth:`~SelectPluginComponent.select_default` - """ - - """ - Traitlets (in the object, custom traitlets in the plugin): - - * ``items`` (list of dicts with keys: label) - * ``selected`` (string) - - Properties (in the object only): - - * ``selected_obj`` - - To use in a plugin: - - * create traitlets with default values - * register with all the automatic logic in the plugin's init by passing the string names - of the respective traitlets - * use component in plugin template (see below) - * refer to properties above based on the interally stored reference to the - instantiated object of this component - - Example template (label and hint are optional):: - - - - """ - def __init__(self, plugin, items, selected, - default_text='No ephemeris', manual_options=[], - default_mode='first'): - """ - Parameters - ---------- - plugin - the parent plugin object - items : str - the name of the items traitlet defined in ``plugin`` - selected : str - the name of the selected traitlet defined in ``plugin`` - default_text : str or None - the text to show for no selection. If not provided or None, no entry will be provided - in the dropdown for no selection. - manual_options: list - list of options to provide that are not automatically populated by ephemerides. If - ``default`` text is provided but not in ``manual_options`` it will still be included as - the first item in the list. - """ - super().__init__(plugin, items=items, selected=selected, - default_text=default_text, manual_options=manual_options, - default_mode=default_mode) - self.hub.subscribe(self, EphemerisComponentChangedMessage, - handler=self._ephem_component_change) - - @cached_property - def ephemeris_plugin(self): - return self.app._jdaviz_helper.plugins.get('Ephemeris', None) - - @cached_property - def selected_obj(self): - if self.selected in self._manual_options: - return None - return self.ephemeris_plugin.ephemerides.get(self.selected, None) - - def get_data_for_dataset(self, dataset, ycomp='flux'): - if not isinstance(dataset, DatasetSelect): # pragma: no cover - raise ValueError("dataset must be DatasetSelect object") - if self.selected in self._manual_options: - return dataset.selected_obj - return self.ephemeris_plugin.get_data(dataset.selected, self.selected) - - def _ephem_component_change(self, msg=None): - type = getattr(msg, 'type', None) - if type == 'remove' and msg.old_lbl in self.choices: - self.items = [item for item in self.items if item['label'] != msg.old_lbl] - self._apply_default_selection() - elif type == 'rename' and msg.old_lbl in self.choices: - was_selected = self.selected == msg.old_lbl - self.items = [item if item['label'] != msg.old_lbl else {'label': msg.new_lbl} - for item in self.items] - if was_selected: - self.selected = msg.new_lbl - elif type == 'add' and msg.new_lbl not in self.choices: - self.items = self.items + [{'label': msg.new_lbl}] - else: - # something might be out of sync, build from scratch - manual_items = [{'label': label} for label in self.manual_options] - self.items = manual_items + [{'label': component} - for component in self.ephemeris_plugin.ephemerides.keys()] - self._apply_default_selection() - - -class EphemerisSelectMixin(VuetifyTemplate, HubListener): - """ - Applies the EphemerisSelect component as a mixin in the base plugin. This - automatically adds traitlets as well as new properties to the plugin with minimal - extra code. For multiple instances or custom traitlet names/defaults, use the - component instead. - - To use in a plugin: - - * add ``EphemerisSelectMixin`` as a mixin to the class - * use the traitlets available from the plugin or properties/methods available from - ``plugin.ephemeris``. - - Example template (label and hint are optional):: - - - - """ - ephemeris_items = List().tag(sync=True) - ephemeris_selected = Unicode().tag(sync=True) - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.ephemeris = EphemerisSelect(self, 'ephemeris_items', 'ephemeris_selected')