diff --git a/.github/workflows/ci_workflows.yml b/.github/workflows/ci_workflows.yml index 43a26458..b6ae948b 100644 --- a/.github/workflows/ci_workflows.yml +++ b/.github/workflows/ci_workflows.yml @@ -51,24 +51,24 @@ jobs: toxposargs: --remote-data allow_failure: false - - name: OS X - Python 3.9 + - name: OS X - Python 3.10 os: macos-latest - python: 3.9 - toxenv: py39-test + python: '3.10' + toxenv: py310-test allow_failure: false - - name: Windows - Python 3.9 + - name: Windows - Python 3.11 os: windows-latest - python: 3.9 - toxenv: py39-test + python: 3.11 + toxenv: py311-test allow_failure: false # This also runs on cron but we want to make sure new changes # won't break this job at the PR stage. - - name: Python 3.11 with latest dev versions of key dependencies, and remote data + - name: Python 3.12 with latest dev versions of key dependencies, and remote data os: ubuntu-latest - python: '3.11' - toxenv: py311-test-devdeps + python: '3.12' + toxenv: py312-test-devdeps toxposargs: --remote-data --run-slow allow_failure: true diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 27e4e440..73222ffa 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -25,7 +25,7 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: 3.9 + python-version: '3.10' - name: Install python-build and twine run: python -m pip install build "twine>=3.3" diff --git a/CHANGES.rst b/CHANGES.rst index 5a7a153a..f8fc8c96 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,10 @@ 0.4.0 (unreleased) ------------------ +* Updates to use jdaviz 3.10, which now requires python 3.10+. [#105] + +* Support loading, viewing, and slicing through TPF data cubes. [#82, #117] + * Support loading, viewing, and slicing through TPF data cubes. [#82, #117, #118] * Default data labels no longer include flux-origin, but do include quarter/campaign/sector. [#111] diff --git a/docs/installation.rst b/docs/installation.rst index c5ad9fda..6785f21b 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -51,7 +51,7 @@ Common Issues If you encounter problems while following these installation instructions, please consult :ref:`known installation issues `. -Note that ``lcviz`` requires Python 3.9 or newer. If your ``pip`` corresponds to an older version of +Note that ``lcviz`` requires Python 3.10 or newer. If your ``pip`` corresponds to an older version of Python, it will raise an error that it cannot find a valid package. Users occasionally encounter problems running the pure ``pip`` install above. For those diff --git a/lcviz/helper.py b/lcviz/helper.py index 12d32964..a9ac0db5 100644 --- a/lcviz/helper.py +++ b/lcviz/helper.py @@ -4,13 +4,30 @@ from lightkurve import LightCurve +from glue.config import settings as glue_settings from glue.core.component_id import ComponentID from glue.core.link_helpers import LinkSame +from glue.core.units import unit_converter from jdaviz.core.helpers import ConfigHelper from lcviz.viewers import TimeScatterView __all__ = ['LCviz'] + +@unit_converter('custom-lcviz') +class UnitConverter: + def equivalent_units(self, data, cid, units): + return set(list(map(str, u.Unit(units).find_equivalent_units(include_prefix_units=True)))) + + def to_unit(self, data, cid, values, original_units, target_units): + # for some reason, glue is trying to request a change for cid='flux' from d to electron / s + if target_units not in self.equivalent_units(data, cid, original_units): + return values + return (values * u.Unit(original_units)).to_value(u.Unit(target_units)) + + +glue_settings.UNIT_CONVERTER = 'custom-lcviz' + custom_components = {'plugin-ephemeris-select': 'components/plugin_ephemeris_select.vue'} # Register pure vue component. This allows us to do recursive component instantiation only in the @@ -57,6 +74,23 @@ def _link_new_data(app, reference_data=None, data_to_be_linked=None): return +def _get_display_unit(app, axis): + if app._jdaviz_helper is None or app._jdaviz_helper.plugins.get('Unit Conversion') is None: # noqa + # fallback on native units (unit conversion is not enabled) + if axis == 'time': + return u.d + elif axis == 'flux': + return app._jdaviz_helper.default_time_viewer._obj.data()[0].flux.unit + else: + raise ValueError(f"could not find units for axis='{axis}'") + try: + # TODO: need to implement and add unit conversion plugin for this to be able to work + return getattr(app._jdaviz_helper.plugins.get('Unit Conversion')._obj, + f'{axis}_unit_selected') + except AttributeError: + raise ValueError(f"could not find display unit for axis='{axis}'") + + class LCviz(ConfigHelper): _default_configuration = { 'settings': {'configuration': 'lcviz', @@ -92,6 +126,10 @@ def __init__(self, *args, **kwargs): lambda *args, **kwargs: _link_new_data(self.app, *args, **kwargs) ) + self.app._get_display_unit = ( + lambda *args, **kwargs: _get_display_unit(self.app, *args, **kwargs) + ) + # inject custom css from lcviz_style.vue (on top of jdaviz styles) self.app._add_style((__file__, 'lcviz_style.vue')) diff --git a/lcviz/plugins/coords_info/coords_info.py b/lcviz/plugins/coords_info/coords_info.py index 1679043a..2f4c5704 100644 --- a/lcviz/plugins/coords_info/coords_info.py +++ b/lcviz/plugins/coords_info/coords_info.py @@ -194,7 +194,11 @@ def _image_viewer_update(self, viewer, x, y): self.icon = 'mdi-cursor-default' self._dict['data_label'] = '' else: - time = viewer.slice_value + try: + time = viewer.slice_value + except IndexError: + self._viewer_mouse_clear_event(viewer) + return # TODO: store slice unit within image viewer to avoid this assumption? time_unit = str(self.app._jdaviz_helper.default_time_viewer._obj.time_unit) self.row2_title = 'Time' diff --git a/lcviz/plugins/time_selector/time_selector.py b/lcviz/plugins/time_selector/time_selector.py index da1f40d8..76acaee5 100644 --- a/lcviz/plugins/time_selector/time_selector.py +++ b/lcviz/plugins/time_selector/time_selector.py @@ -47,7 +47,7 @@ def __init__(self, *args, **kwargs): handler=self._on_ephemeris_changed) @property - def slice_axis(self): + def slice_display_unit_name(self): # global display unit "axis" corresponding to the slice axis return 'time' diff --git a/lcviz/tests/test_plugin_markers.py b/lcviz/tests/test_plugin_markers.py index c6af3635..85350cf8 100644 --- a/lcviz/tests/test_plugin_markers.py +++ b/lcviz/tests/test_plugin_markers.py @@ -146,17 +146,18 @@ def test_tpf_markers(helper, light_curve_like_kepler_quarter): {'event': 'mousemove', 'domain': {'x': 0, 'y': 0}}) - assert label_mouseover.as_text() == ('Pixel x=00000.0 y=00000.0 Value +1.28035e+01 electron / s', # noqa - 'Time 47.00689 d', + assert label_mouseover.as_text() == ('Pixel x=00000.0 y=00000.0 Value +1.27220e+00 electron / s', # noqa + 'Time 47.00000 d', '') + print(label_mouseover.as_dict()) _assert_dict_allclose(label_mouseover.as_dict(), {'data_label': 'KIC 1429092[TPF]', - 'time': 47.00688790508866, + 'time': 47.00000, 'time:unit': 'd', 'pixel': (0.0, 0.0), 'axes_x': 0, 'axes_x:unit': 'pix', 'axes_y': 0, 'axes_y:unit': 'pix', - 'value': 12.803528785705566, + 'value': 1.272199273109436, 'value:unit': 'electron / s'}) diff --git a/lcviz/viewers.py b/lcviz/viewers.py index 642e9201..a2e79103 100644 --- a/lcviz/viewers.py +++ b/lcviz/viewers.py @@ -103,6 +103,10 @@ def slice_component_label(self): # calling data_collection_item.get_component(slice_component_label) must work return 'dt' + @property + def slice_display_unit_name(self): + return 'time' + def data(self, cls=None): data = [] @@ -334,6 +338,10 @@ def slice_index(self): # index in viewer.slices corresponding to the slice axis return 0 + @property + def slice_display_unit_name(self): + return 'time' + def _initial_x_axis(self, *args): # Make sure that the x_att/y_att is correct on data load # called via a callback set upstream in CubevizImageView when reference_data is changed diff --git a/pyproject.toml b/pyproject.toml index 225c7405..fd7c0707 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "lcviz" description = "A Jdaviz-based light curve analysis and visualization tool" -requires-python = ">=3.9" +requires-python = ">=3.10" authors = [ { name = "JDADF Developers", email = "kconroy@stsci.edu" }, ] @@ -20,10 +20,9 @@ classifiers = [ ] dependencies = [ "astropy>=5.2", - "glue-core<1.19.0", # NOTE: if/when we stop pinning a minor version of jdaviz, add jdaviz # to devdeps in tox.ini - "jdaviz==3.9.*", + "jdaviz>=3.10.2,<3.11", "lightkurve>=2.4.1", ] dynamic = [