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

Unit conversion plugin #147

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
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
28 changes: 28 additions & 0 deletions docs/plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,34 @@ This plugin allows choosing which column in the underlying data should be used a
* :meth:`lightkurve.LightCurve.select_flux`


.. _unit-conversion

Unit Conversion
===============

This plugin allows choosing app-wide units to use for the time and flux axes.


.. admonition:: User API Example
:class: dropdown

See the :class:`~lcviz.plugins.unit_conversion.unit_conversion.UnitConversion` user API documentation for more details.

.. code-block:: python

from lcviz import LCviz
from lightkurve import search_lightcurve
lc = search_lightcurve("HAT-P-11", mission="Kepler",
cadence="long", quarter=10).download().flatten()
lcviz = LCviz()
lcviz.load_data(lc)
lcviz.show()

units = lcviz.plugins['Unit Conversion']
print(units.time_unit.choices)
units.time_unit = 'hr'


.. _plot-options:

Plot Options
Expand Down
3 changes: 3 additions & 0 deletions docs/reference/api_plugins.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,6 @@ Plugins API

.. automodapi:: lcviz.plugins.time_selector.time_selector
:no-inheritance-diagram:

.. automodapi:: lcviz.plugins.unit_conversion.unit_conversion
:no-inheritance-diagram:
2 changes: 1 addition & 1 deletion lcviz/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ class LCviz(ConfigHelper):
'dense_toolbar': False,
'context': {'notebook': {'max_height': '600px'}}},
'toolbar': ['g-data-tools', 'g-subset-tools', 'g-viewer-creator', 'lcviz-coords-info'],
'tray': ['lcviz-metadata-viewer', 'flux-column',
'tray': ['lcviz-metadata-viewer', 'flux-column', 'lcviz-unit-conversion',
'lcviz-plot-options', 'lcviz-subset-plugin',
'lcviz-markers', 'time-selector',
'stitch', 'flatten', 'frequency-analysis', 'ephemeris',
Expand Down
1 change: 1 addition & 0 deletions lcviz/plugins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@
from .plot_options.plot_options import * # noqa
from .stitch.stitch import * # noqa
from .subset_plugin.subset_plugin import * # noqa
from .unit_conversion.unit_conversion import * # noqa
1 change: 1 addition & 0 deletions lcviz/plugins/unit_conversion/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .unit_conversion import * # noqa
107 changes: 107 additions & 0 deletions lcviz/plugins/unit_conversion/unit_conversion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
from jdaviz.configs.specviz.plugins.unit_conversion.unit_conversion import (UnitConversion,
_valid_glue_display_unit, # noqa
_flux_to_sb_unit)
from jdaviz.core.events import GlobalDisplayUnitChanged
from jdaviz.core.registries import tray_registry

from lcviz.viewers import (CubeView, TimeScatterView)

__all__ = ['UnitConversion']


@tray_registry('lcviz-unit-conversion', label="Unit Conversion")
class UnitConversion(UnitConversion):
"""
See the :ref:`Unit Conversion Plugin Documentation <unit-conversion>` for more details.

For a full list of exposed attributes, call ``dir(plugin)``. Note that some attributes are
applicable depending on the selection of ``viewer`` and/or ``layer``. Below are
a list of some common 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`
* :meth:`~jdaviz.core.template_mixin.PluginTemplateMixin.close_in_tray`
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.docs_link = f"https://lcviz.readthedocs.io/en/{self.vdocs}/plugins.html#unit-conversion"
self.docs_description = "Choose units for the time and flux axes."
self.disabled_msg = "" # otherwise disabled upstream - remove once upstream no longer has a config check

self.has_time = True
self.has_flux = True

@property
def spectrum_viewer(self):
if hasattr(self, '_default_time_viewer_reference_name'):
viewer_reference = self._default_time_viewer_reference_name
else:
viewer_reference = self.app._get_first_viewer_reference_name(
)

return self.app.get_viewer(viewer_reference)

def _on_add_data_to_viewer(self, msg):
viewer = msg.viewer

if (not len(self.time_unit_selected) or not len(self.flux_unit_selected)):
# TODO: default based on the native units of the data (LC or TPF)
self.time_unit.choices = ['d', 'hr', 'min', 's']
self.time_unit_selected = 'd'
self.flux_unit.choices = ['erg / (Angstrom cm2 s)']
self.flux_unit_selected = 'erg / (Angstrom cm2 s)'
# setting default values will trigger the observes to set the units
# in _on_unit_selected, so return here to avoid setting twice
return

# TODO: when enabling unit-conversion in rampviz, this may need to be more specific
# or handle other cases for ramp profile viewers
if isinstance(viewer, TimeScatterView):
if (viewer.state.x_display_unit == self.time_unit_selected
and viewer.state.y_display_unit == self.flux_unit_selected):
# data already existed in this viewer and display units were already set
return

# this spectral viewer was empty (did not have display units set yet),˜
# but global selections are available in the plugin,
# so we'll set them to the viewer here
viewer.state.x_display_unit = self.time_unit_selected
viewer.state.y_display_unit = self.flux_unit_selected

elif isinstance(viewer, CubeView):
# set the attribute display unit (contour and stretch units) for the new layer
# NOTE: this assumes that all image data is coerced to surface brightness units
layers = [lyr for lyr in msg.viewer.layers if lyr.layer.data.label == msg.data.label]
self._handle_attribute_display_unit(self.flux_unit_selected, layers=layers)
self._clear_cache('image_layers')

def _on_unit_selected(self, msg):
"""
When any user selection is made, update the relevant viewer(s) with the new unit,
and then emit a GlobalDisplayUnitChanged message to notify other plugins of the change.
"""
print("*** _on_unit_selected", msg.get('name'), msg.get('new'))
if not len(msg.get('new', '')):
# empty string, nothing to set yet
return

axis = msg.get('name').split('_')[0]

if axis == 'time':
xunit = _valid_glue_display_unit(self.time_unit.selected, self.spectrum_viewer, 'x')
# TODO: iterate over all TimeScatterViewers
self.spectrum_viewer.state.x_display_unit = xunit
self.spectrum_viewer.set_plot_axes()

elif axis == 'flux':
yunit = _valid_glue_display_unit(self.flux_unit.selected, self.spectrum_viewer, 'y')
# TODO: iterate over all Time and Phase Scatter Viewers
self.spectrum_viewer.state.y_display_unit = yunit
self.spectrum_viewer.set_plot_axes()

# TODO: handle setting surface brightness units for CubeView

# axis (first) argument will be one of: time, flux
self.hub.broadcast(GlobalDisplayUnitChanged(axis,
msg.new, sender=self))
1 change: 1 addition & 0 deletions lcviz/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def _reset_y_limits(self, *event):
self._reset_att_limits('y')

def reset_limits(self, *event):
# TODO: this is not working correctly when units are changed (probably the same for _reset_att_limits)
x_min, x_max = np.inf, -np.inf
y_min, y_max = np.inf, -np.inf

Expand Down
7 changes: 5 additions & 2 deletions lcviz/viewers.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def set_plot_axes(self):
def _set_plot_x_axes(self, dc, component_labels, light_curve):
self.state.x_att = dc[0].components[component_labels.index('dt')]

x_unit = self.time_unit
x_unit = self.time_unit # TODO: use get display unit instead? Or at least update self.time_unit
reference_time = light_curve.meta.get('reference_time', None)

if reference_time is not None:
Expand All @@ -176,7 +176,10 @@ def _set_plot_x_axes(self, dc, component_labels, light_curve):
self.figure.axes[0].num_ticks = 5

def _set_plot_y_axes(self, dc, component_labels, light_curve):
self.state.y_att = dc[0].components[component_labels.index('flux')]
try:
self.state.y_att = dc[0].components[component_labels.index('flux')]
except ValueError:
pass

y_unit = light_curve.flux.unit
y_unit_physical_type = str(y_unit.physical_type).title()
Expand Down
Loading