diff --git a/docs/plugins.rst b/docs/plugins.rst index 0558f69f..66a0f098 100644 --- a/docs/plugins.rst +++ b/docs/plugins.rst @@ -35,6 +35,15 @@ This plugin allows viewing of any metadata associated with the selected data. :ref:`Jdaviz Metadata Viewer ` Jdaviz documentation on the Metadata Viewer plugin. +.. _flux-origin:: + +Flux Origin +=========== + +This plugin allows choosing which column in the underlying data should be used as the flux origin +throughout the app (when plotting and in any data analysis plugins). + + .. _plot-options: Plot Options diff --git a/lcviz/helper.py b/lcviz/helper.py index a6453cd2..b7b17904 100644 --- a/lcviz/helper.py +++ b/lcviz/helper.py @@ -72,7 +72,8 @@ class LCviz(ConfigHelper): 'dense_toolbar': False, 'context': {'notebook': {'max_height': '600px'}}}, 'toolbar': ['g-data-tools', 'g-subset-tools', 'lcviz-coords-info'], - 'tray': ['lcviz-metadata-viewer', 'lcviz-plot-options', 'lcviz-subset-plugin', + 'tray': ['lcviz-metadata-viewer', 'flux-origin', + 'lcviz-plot-options', 'lcviz-subset-plugin', 'lcviz-markers', 'flatten', 'frequency-analysis', 'ephemeris', 'binning', 'lcviz-export-plot'], 'viewer_area': [{'container': 'col', @@ -155,12 +156,17 @@ def _phase_comp_lbl(self, component): return f'phase:{component}' def _set_data_component(self, data, component_label, values): - if component_label not in self._component_ids: - self._component_ids[component_label] = ComponentID(component_label) - - if self._component_ids[component_label] in data.components: - data.update_components({self._component_ids[component_label]: values}) + if component_label in self._component_ids: + component_id = self._component_ids[component_label] else: - data.add_component(values, self._component_ids[component_label]) - - data.add_component(values, self._component_ids[component_label]) + existing_components = [component.label for component in data.components] + if component_label in existing_components: + component_id = data.components[existing_components.index(component_label)] + else: + component_id = ComponentID(component_label) + self._component_ids[component_label] = component_id + + if component_id in data.components: + data.update_components({component_id: values}) + else: + data.add_component(values, component_id) diff --git a/lcviz/parsers.py b/lcviz/parsers.py index e9268c83..637e0cd5 100644 --- a/lcviz/parsers.py +++ b/lcviz/parsers.py @@ -27,9 +27,16 @@ def light_curve_parser(app, file_obj, data_label=None, show_in_viewer=True, **kw new_data_label = f'{data_label}' else: new_data_label = light_curve.meta.get('OBJECT', 'Light curve') + + # handle flux_origin default flux_origin = light_curve.meta.get('FLUX_ORIGIN', None) # i.e. PDCSAP or SAP - if flux_origin is not None: - new_data_label += f'[{flux_origin}]' + if flux_origin == 'flux': + # then make a copy of this column so it won't be lost when changing with the flux_column + # plugin + light_curve['flux:orig'] = light_curve['flux'] + if 'flux_err' in light_curve.columns: + light_curve['flux:orig_err'] = light_curve['flux_err'] + light_curve.meta['FLUX_ORIGIN'] = 'flux:orig' data = _data_with_reftime(app, light_curve) app.add_data(data, new_data_label) diff --git a/lcviz/plugins/__init__.py b/lcviz/plugins/__init__.py index dacdb581..90806175 100644 --- a/lcviz/plugins/__init__.py +++ b/lcviz/plugins/__init__.py @@ -3,6 +3,7 @@ from .ephemeris.ephemeris import * # noqa from .export_plot.export_plot import * # noqa from .flatten.flatten import * # noqa +from .flux_origin.flux_origin import * # noqa from .frequency_analysis.frequency_analysis import * # noqa from .markers.markers import * # noqa from .metadata_viewer.metadata_viewer import * # noqa diff --git a/lcviz/plugins/flux_origin/__init__.py b/lcviz/plugins/flux_origin/__init__.py new file mode 100644 index 00000000..2927ba18 --- /dev/null +++ b/lcviz/plugins/flux_origin/__init__.py @@ -0,0 +1 @@ +from .flux_origin import * # noqa diff --git a/lcviz/plugins/flux_origin/flux_origin.py b/lcviz/plugins/flux_origin/flux_origin.py new file mode 100644 index 00000000..65c1f557 --- /dev/null +++ b/lcviz/plugins/flux_origin/flux_origin.py @@ -0,0 +1,91 @@ +from traitlets import List, Unicode, observe + +from jdaviz.core.registries import tray_registry +from jdaviz.core.template_mixin import (PluginTemplateMixin, + DatasetSelectMixin, SelectPluginComponent) +from jdaviz.core.user_api import PluginUserApi + +__all__ = ['FluxOrigin'] + + +@tray_registry('flux-origin', label="Flux Origin") +class FluxOrigin(PluginTemplateMixin, DatasetSelectMixin): + """ + See the :ref:`Flux Origin Plugin Documentation ` for more details. + + Only the following attributes and methods are available through the + public plugin API. + + * ``dataset`` (:class:`~jdaviz.core.template_mixin.DatasetSelect`): + Dataset to bin. + """ + template_file = __file__, "flux_origin.vue" + + origin_items = List().tag(sync=True) + origin_selected = Unicode().tag(sync=True) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.origin = SelectPluginComponent(self, + items='origin_items', + selected='origin_selected') + + @property + def user_api(self): + expose = ['dataset', 'origin'] + return PluginUserApi(self, expose=expose) + + @observe('dataset_selected') + def _on_change_dataset(self, *args): + def _include_col(lk_obj, col): + if col == 'flux' and lk_obj.meta.get('FLUX_ORIGIN') != 'flux': + # this is the currently active column (and should be copied elsewhere unless) + return False + if col in ('time', 'cadn', 'cadenceno', 'quality'): + return False + if col.startswith('phase:'): + # internal jdaviz ephemeris phase columns + return False + if col.startswith('time'): + return False + if col.startswith('centroid'): + return False + if col.startswith('cbv'): + # cotrending basis vector + return False + if col.endswith('_err'): + return False + if col.endswith('quality'): + return False + return lk_obj[col].unit == lk_obj['flux'].unit + + lk_obj = self.dataset.selected_obj + self.origin.choices = [col for col in lk_obj.columns if _include_col(lk_obj, col)] + flux_origin = lk_obj.meta.get('FLUX_ORIGIN') + if flux_origin in self.origin.choices: + self.origin.selected = flux_origin + else: + self.origin.selected = '' + + @observe('origin_selected') + def _on_change_origin(self, *args): + if self.origin_selected == '': + return + + dc_item = self.dataset.selected_dc_item + old_flux_origin = dc_item.meta.get('FLUX_ORIGIN') + if self.origin.selected == old_flux_origin: + # nothing to do here! + return + + # instead of using lightkurve's select_flux and having to reparse the data entry, we'll + # manipulate the arrays in the data-collection directly, and modify FLUX_ORIGIN so that + # exporting back to a lightkurve object works as expected + dc_item = self.dataset.selected_dc_item + + self.app._jdaviz_helper._set_data_component(dc_item, 'flux', dc_item[self.origin.selected]) + dc_item.meta['FLUX_ORIGIN'] = self.origin.selected + # need to clear the cache manually due to the change in metadata made to the data-collection + # entry + self.dataset._clear_cache('selected_obj') diff --git a/lcviz/plugins/flux_origin/flux_origin.vue b/lcviz/plugins/flux_origin/flux_origin.vue new file mode 100644 index 00000000..9ae32805 --- /dev/null +++ b/lcviz/plugins/flux_origin/flux_origin.vue @@ -0,0 +1,31 @@ +