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

Expose time functionality #103

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
5af4063
Expose play/pause time and clock rate settings.
Carifio24 Oct 17, 2023
1c1077b
Start exposing time attribute and decay functionality.
Carifio24 Oct 17, 2023
a794a0e
Allow setting current WWT time from Qt glue. Basic time functionality…
Carifio24 Oct 24, 2023
bfad9d1
Improve performance of setting time attribute for table layer.
Carifio24 Oct 25, 2023
18ba293
Last set time doesn't need to be a callback property.
Carifio24 Oct 25, 2023
1af0533
Fix issues with setting time from dialog. Add label displaying curren…
Carifio24 Oct 25, 2023
6fd3bf5
Work on UI for Jupyter viewer. Refactor to allow sharing linked widge…
Carifio24 Oct 27, 2023
7660416
Fix small bugs in Jupyter UI and table layer code.
Carifio24 Nov 27, 2023
f8c7ae6
Work on modifying UI to allow setting min/max time and change time us…
Carifio24 Jan 3, 2024
b241da0
Adjusting the time via the time slider is working. Need to adjust sli…
Carifio24 Jan 3, 2024
82ffd79
Ensure that min, max, and current time always have correct relative o…
Carifio24 Jan 4, 2024
9619210
Use UTC as time spec for datetime widgets.
Carifio24 Jan 6, 2024
7de2868
Set the correct starting tab for the options widget.
Carifio24 Jan 9, 2024
901695c
More updates to Jupyter time-control UI.
Carifio24 Jan 11, 2024
bd516d6
Update slider fraction when bounds change.
Carifio24 Jan 11, 2024
a1b8b44
Fix a typo.
Carifio24 Jan 11, 2024
4729886
Round current time label to ms to prevent adjusting size of sidebar i…
Carifio24 Jan 12, 2024
9d6eb46
Update datetime edit format.
Carifio24 Jan 26, 2024
8bb7b8d
Codestyle fixes.
Carifio24 Mar 21, 2024
8cc2ff6
Reset default viewer state tab to first one.
Carifio24 Sep 5, 2024
f8650e1
Use dev version of glue-qt for devdeps.
Carifio24 Sep 9, 2024
7884fe8
Put slider update inside a try block.
Carifio24 Sep 9, 2024
8cbaeed
Account for the fact that image layers don't have a time attribute.
Carifio24 Sep 9, 2024
9843f23
astropy has dropped Python 3.10 support so we can't use that for devd…
Carifio24 Sep 9, 2024
5023841
Update timer configuration and cleanup.
Carifio24 Nov 5, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/ci_workflows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
# Standard tests
- linux: py38-test
- linux: py39-test
- linux: py310-test-devdeps
- linux: py310-test
- linux: py311-test
- linux: py312-test-devdeps

Expand Down
44 changes: 44 additions & 0 deletions glue_wwt/viewer/data_viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
from __future__ import absolute_import, division, print_function

from astropy.coordinates import SkyCoord
from astropy.time import Time
import astropy.units as u
from glue.core.coordinates import WCSCoordinates
from glue.logger import logger
from pywwt import ViewerNotAvailableError
from pywwt.layers import guess_lon_lat_columns
from threading import Timer
from numpy import datetime64

from .image_layer import WWTImageLayerArtist
from .table_layer import WWTTableLayerArtist
Expand All @@ -16,6 +19,12 @@
__all__ = ['WWTDataViewerBase']


class RepeatTimer(Timer):
def run(self):
while not self.finished.wait(self.interval):
self.function(*self.args, **self.kwargs)


class WWTDataViewerBase(object):
LABEL = 'Earth/Planet/Sky Viewer (WWT)'
_wwt = None
Expand All @@ -29,6 +38,10 @@ class WWTDataViewerBase(object):
"equatorial_text": "grid_text"
}

_CLOCK_SETTINGS = [
"play_time", "clock_rate"
]

_UPDATE_SETTINGS = [
"equatorial_grid", "equatorial_grid_color", "equatorial_text",
"ecliptic_grid", "ecliptic_grid_color", "ecliptic_text",
Expand All @@ -48,9 +61,25 @@ def __init__(self):
self._wwt.actual_planet_scale = True
self.state.imagery_layers = list(self._wwt.available_layers)

# The more obvious thing to do would be to listen to the WWT widget's "wwt_view_state" message,
# which contains information about WWT's internal time. But we only get those messages when something
# changes with the WWT view, so we can't rely on that here.
# This just kicks off the first timer; the method repeatedly time-calls itself
self._current_time_timer = RepeatTimer(1.0, self._update_time)
self._current_time_timer.start()

self.state.add_global_callback(self._update_wwt)

self._update_wwt(force=True)

# NB: Specific frontend implementations need to call this
# We just consolidate the logic here
def _cleanup(self):
try:
self._current_time_timer.cancel()
except RuntimeError:
pass

def _initialize_wwt(self):
raise NotImplementedError('subclasses should set _wwt here')

Expand All @@ -67,6 +96,15 @@ def _update_wwt(self, force=False, **kwargs):
self._wwt.constellation_boundaries = self.state.constellation_boundaries != 'None'
self._wwt.constellation_selection = self.state.constellation_boundaries == 'Selection only'

if force or 'current_time' in kwargs:
self._wwt.set_current_time(Time(self.state.current_time))

if force or any(setting in kwargs for setting in self._CLOCK_SETTINGS):
if self.state.play_time:
self._wwt.play_time(self.state.clock_rate)
else:
self._wwt.pause_time()

for setting in self._UPDATE_SETTINGS:
if force or setting in kwargs:
wwt_attr = self._GLUE_TO_WWT_ATTR_MAP.get(setting, setting)
Expand Down Expand Up @@ -138,3 +176,9 @@ def add_data(self, data):
self.state.lon_att = data.id[lon]
self.state.lat_att = data.id[lat]
return add

def _update_time(self):
try:
self.state.current_time = datetime64(self._wwt.get_current_time().to_string())
except ViewerNotAvailableError:
pass
33 changes: 33 additions & 0 deletions glue_wwt/viewer/jupyter_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from ipywidgets import Checkbox, ColorPicker, FloatText, Layout

from glue.utils import color2hex
from glue_jupyter.link import dlink, link

__all__ = ['linked_checkbox', 'linked_color_picker', 'set_enabled_from_checkbox']


def opposite(value):
return not value


def linked_checkbox(state, attr, description='', layout=None):
widget = Checkbox(getattr(state, 'attr', False), description=description,
indent=False, layout=layout or Layout())
link((state, attr), (widget, 'value'))
return widget


def linked_color_picker(state, attr, description='', layout=None):
widget = ColorPicker(concise=True, layout=layout or Layout(), description=description)
link((state, attr), (widget, 'value'), color2hex)
return widget


def linked_float_text(state, attr, default=0, description='', layout=None):
widget = FloatText(description=description, layout=layout or Layout())
link((state, attr), (widget, 'value'), lambda value: value or default)
return widget


def set_enabled_from_checkbox(widget, checkbox):
dlink((checkbox, 'value'), (widget, 'disabled'), opposite)
Loading
Loading