This commit is contained in:
Thomas Robitaille 2020-03-30 17:41:56 +01:00
Родитель 94d4a92410
Коммит 67836e56d0
15 изменённых файлов: 230 добавлений и 136 удалений

Просмотреть файл

@ -6,5 +6,5 @@ __version__ = '%s.%s.%s%s' % (
version_info[0],
version_info[1],
version_info[2],
'' if version_info[3]=='final' else _specifier_[version_info[3]]+str(version_info[4])
'' if version_info[3] == 'final' else _specifier_[version_info[3]]+str(version_info[4])
)

Просмотреть файл

@ -2,7 +2,6 @@ import uuid
from traitlets import HasTraits, TraitError, validate
from astropy import units as u
from astropy.coordinates import concatenate, SkyCoord
import requests
import numpy as np
from .traits import (Color, ColorWithOpacity, Bool,
@ -164,7 +163,7 @@ class Circle(Annotation):
def _serialize_state(self):
state = super(Circle, self)._serialize_state()
state['settings']['skyRelative'] = self.radius.unit.is_equivalent(u.degree)
state['settings']['skyRelative'] = self.radius.unit.is_equivalent(u.degree)
state['center'] = {'ra': self._center.ra.deg,
'dec': self._center.dec.deg}
return state

Просмотреть файл

@ -42,6 +42,7 @@ if QT_INSTALLED and OPENGL_INSTALLED:
_cached_opengl_renderer = ''
def pytest_report_header(config):
global _cached_opengl_renderer
@ -88,7 +89,6 @@ def pytest_report_header(config):
def pytest_unconfigure(config):
if QT_INSTALLED:
from .app import cleanup_qapp
cleanup_qapp()

Просмотреть файл

@ -3,7 +3,6 @@ from traitlets import HasTraits, observe, validate, TraitError
from astropy import units as u
from astropy.time import Time
from astropy.coordinates import SkyCoord
from datetime import datetime
# We import the trait classes from .traits since we do various customizations
from .traits import Color, Bool, Float, Unicode, AstropyQuantity
@ -16,7 +15,6 @@ from .instruments import Instruments
from .utils import ensure_utc
import json
import os
import shutil
import tempfile
@ -128,11 +126,17 @@ class BaseWWTWidget(HasTraits):
help='Whether to only show boundaries for '
'the selected constellation '
'(`bool`)').tag(wwt='showConstellationSelection', wwt_reset=True)
#constellation_pictures = Bool(False, help='Whether to show pictures of the constellations\' mythological representations (`bool`)').tag(wwt='showConstellationPictures', wwt_reset=True)
#constellation_labels = Bool(False, help='Whether to show labelss for constellations (`bool`)').tag(wwt='showConstellationLabels', wwt_reset=True)
# constellation_pictures = Bool(False,
# help='Whether to show pictures of the constellations\' '
# 'mythological representations '
# '(`bool`)').tag(wwt='showConstellationPictures', wwt_reset=True)
# constellation_labels = Bool(False,
# help='Whether to show labelss for constellations '
# '(`bool`)').tag(wwt='showConstellationLabels', wwt_reset=True)
crosshairs = Bool(False, help='Whether to show crosshairs at the center of '
'the field (`bool`)').tag(wwt='showCrosshairs', wwt_reset=True)
'the field (`bool`)').tag(wwt='showCrosshairs', wwt_reset=True)
crosshairs_color = Color('white',
help='The color of the crosshairs '
'(`str` or `tuple`)').tag(wwt='crosshairsColor', wwt_reset=True)
@ -260,10 +264,14 @@ class BaseWWTWidget(HasTraits):
'in the viewer (`bool`)').tag(wwt='galacticMode', wwt_reset=True)
galactic_grid = Bool(False, help='Whether to show a grid relative to the '
'galactic plane (`bool`)').tag(wwt='showGalacticGrid', wwt_reset=True)
#galactic_text = Bool(False, help='Whether to show labels for the galactic grid\'s text (`bool`)').tag(wwt='showGalacticGridText', wwt_reset=True)
# galactic_text = Bool(False,
# help='Whether to show labels for the galactic grid\'s text '
# '(`bool`)').tag(wwt='showGalacticGridText', wwt_reset=True)
alt_az_grid = Bool(False, help='Whether to show an altitude-azimuth grid '
'(`bool`)').tag(wwt='showAltAzGrid', wwt_reset=True)
#alt_az_text = Bool(False, help='Whether to show labels for the altitude-azimuth grid\'s text (`bool`)').tag(wwt='showAltAzGridText', wwt_reset=True)
# alt_az_text = Bool(False,
# help='Whether to show labels for the altitude-azimuth grid\'s text '
# '(`bool`)').tag(wwt='showAltAzGridText', wwt_reset=True)
local_horizon_mode = Bool(False, help='Whether the view should be that of '
'a local latitude, longitude, and '
@ -274,8 +282,8 @@ class BaseWWTWidget(HasTraits):
'(:class:`~astropy.units.Quantity`)').tag(wwt='locationAltitude', wwt_reset=True)
location_latitude = AstropyQuantity(47.633 * u.deg,
help='The latitude of the viewing '
'location in local horizon mode '
'(:class:`~astropy.units.Quantity`)').tag(wwt='locationLat', wwt_reset=True)
'location in local horizon mode '
'(:class:`~astropy.units.Quantity`)').tag(wwt='locationLat', wwt_reset=True)
location_longitude = AstropyQuantity(122.133333 * u.deg,
help='The longitude of the viewing '
'location in local horizon mode '
@ -589,7 +597,7 @@ class BaseWWTWidget(HasTraits):
If left blank, the WWT viewport will fill the enitre height of the browser.
"""
dest_root, dest_extension = os.path.splitext(dest)
if (dest_extension and dest_extension != ".zip"):
if (dest_extension and dest_extension != ".zip"):
raise ValueError("'dest' must be either a directory or a .zip file")
is_compressed = dest_extension == '.zip'
@ -610,10 +618,10 @@ class BaseWWTWidget(HasTraits):
shutil.copy(os.path.join(nbexten_dir, 'wwt_json_api.js'), script_dir)
shutil.copy(os.path.join(fig_src_dir, "interactive_figure.js"), script_dir)
self._serialize_to_json(os.path.join(figure_dir,'wwt_figure.json'), title, max_width, max_height)
self._serialize_to_json(os.path.join(figure_dir, 'wwt_figure.json'), title, max_width, max_height)
if len(self.layers) > 0:
data_dir = os.path.join(figure_dir,'data')
data_dir = os.path.join(figure_dir, 'data')
if not os.path.exists(data_dir):
os.mkdir(data_dir)
self._save_added_data(data_dir)
@ -662,8 +670,8 @@ class BaseWWTWidget(HasTraits):
def _serialize_to_json(self, file, title, max_width, max_height):
state = self._serialize_state(title, max_width, max_height)
with open(file,'w') as file_obj:
json.dump(state,file_obj)
with open(file, 'w') as file_obj:
json.dump(state, file_obj)
def _save_added_data(self, dir):
self.layers._save_all_data_for_serialization(dir)

Просмотреть файл

@ -60,35 +60,35 @@ class ImageryLayers():
# (og_list) into a dict.
for layer in og_list:
if re.search(r'(?i)gamma',layer) is not None:
if re.search(r'(?i)gamma', layer) is not None:
self._add2dict(self._layers, layer, 'gamma')
continue # automatically advance to next iteration
continue # automatically advance to next iteration
if re.search(r'(?i)x(-|\s)?ray',layer) is not None:
if re.search(r'(?i)x(-|\s)?ray', layer) is not None:
self._add2dict(self._layers, layer, 'x')
continue
if (re.search(r'(?i)ultra(-|\s)?violet',layer) is not None or
re.search(r'(?i)[^\d\w]+uv|uv[^\d\w]+',layer) is not None):
if (re.search(r'(?i)ultra(-|\s)?violet', layer) is not None or
re.search(r'(?i)[^\d\w]+uv|uv[^\d\w]+', layer) is not None):
self._add2dict(self._layers, layer, 'uv')
continue
if (re.search(r'(?i)optical',layer) is not None or
re.search(r'(?i)visible',layer) is not None):
if (re.search(r'(?i)optical', layer) is not None or
re.search(r'(?i)visible', layer) is not None):
self._add2dict(self._layers, layer, 'visible')
continue
if (re.search(r'(?i)infrared',layer) is not None or
re.search(r'(?i)[^\d\w]+ir|ir[^\d\w]+',layer) is not None):
if (re.search(r'(?i)infrared', layer) is not None or
re.search(r'(?i)[^\d\w]+ir|ir[^\d\w]+', layer) is not None):
self._add2dict(self._layers, layer, 'ir')
continue
if (re.search(r'(?i)microwave',layer) is not None or
re.search(r'(?i)[^\d\w]+cmb|cmb[^\d\w]+',layer) is not None):
if (re.search(r'(?i)microwave', layer) is not None or
re.search(r'(?i)[^\d\w]+cmb|cmb[^\d\w]+', layer) is not None):
self._add2dict(self._layers, layer, 'micro')
continue
if re.search(r'(?i)radio',layer) is not None:
if re.search(r'(?i)radio', layer) is not None:
self._add2dict(self._layers, layer, 'radio')
continue

Просмотреть файл

@ -1,5 +1,6 @@
import requests
class Instruments():
"""
A supplemental class that enables tab-completion for available

Просмотреть файл

@ -4,7 +4,7 @@
# Python and Javascript parts so that we can re-use this for the Qt client.
import sys
PY2 = sys.version_info[0] == 2
PY2 = sys.version_info[0] == 2 # noqa
import ipywidgets as widgets
from traitlets import Unicode, Float, default, link, directional_link
@ -12,9 +12,9 @@ from traitlets import Unicode, Float, default, link, directional_link
if not PY2:
from ipyevents import Event as DOMListener
from .core import BaseWWTWidget
from .layers import ImageLayer
from .jupyter_server import serve_file
from .core import BaseWWTWidget # noqa
from .layers import ImageLayer # noqa
from .jupyter_server import serve_file # noqa
__all__ = ['WWTJupyterWidget']
@ -107,7 +107,7 @@ class JupyterImageLayer(ImageLayer):
@property
def controls(self):
from .layers import VALID_STRETCHES, VALID_COLORMAPS, UI_COLORMAPS
from .layers import VALID_STRETCHES, UI_COLORMAPS
if self._controls is not None:
return self._controls

Просмотреть файл

@ -88,7 +88,7 @@ def _compute_notebook_server_base_url():
for s in list_running_servers():
response = requests.get(
requests.compat.urljoin(s['url'], 'api/sessions'),
params = {'token': s.get('token', '')}
params={'token': s.get('token', '')}
)
for n in json.loads(response.text):
@ -100,6 +100,7 @@ def _compute_notebook_server_base_url():
_server_base_url = None
def get_notebook_server_base_url():
"""Get the "base_url" of the current Jupyter notebook server.
@ -144,9 +145,9 @@ def load_jupyter_server_extension(nb_server_app):
with open(CONFIG, 'w') as f:
json.dump(config, f)
mimetypes.add_type('image/fits','.fits')
mimetypes.add_type('image/fits','.fts')
mimetypes.add_type('image/fits','.fit')
mimetypes.add_type('image/fits', '.fits')
mimetypes.add_type('image/fits', '.fts')
mimetypes.add_type('image/fits', '.fit')
route_pattern = url_path_join(web_app.settings['base_url'], '/wwt/(.*)')
web_app.add_handlers(host_pattern, [(route_pattern, WWTFileHandler)])

Просмотреть файл

@ -24,7 +24,6 @@ from astropy.table import Column
from astropy.time import Time
from datetime import datetime
from ipywidgets import HBox, Dropdown, FloatText, FloatSlider, link
from traitlets import HasTraits, validate, observe
from .traits import Color, Bool, Float, Unicode, AstropyQuantity, Any, to_hex
from .utils import sanitize_image, validate_traits, ensure_utc
@ -81,7 +80,7 @@ UI_COLORMAPS = OrderedDict([
# Save string types for validating ISOT strings in time series tables
if sys.version_info[0] == 2:
STR_TYPE = basestring
STR_TYPE = basestring # noqa
NP_STR_TYPE = np.string_
else:
STR_TYPE = str
@ -176,7 +175,7 @@ def csv_table_win_newline(table):
s = StringIO()
table.write(s, format='ascii.basic', delimiter=',', comment=False)
s.seek(0)
#Replace single \r or \n characters with \r\n
# Replace single \r or \n characters with \r\n
return re.sub(r"(?<![\r\n])(\r|\n)(?![\r\n])", "\r\n", s.read())
@ -299,7 +298,7 @@ class LayerManager(object):
return layer_states
def _save_all_data_for_serialization (self, dir):
def _save_all_data_for_serialization(self, dir):
for layer in self._layers:
layer._save_data_for_serialization(dir)
@ -506,7 +505,6 @@ class TableLayer(HasTraits):
else:
raise ValueError('alt_type should be one of {0}'.format('/'.join(str(x) for x in VALID_ALT_TYPES)))
@validate('time_att')
def _check_time_att(self, proposal):
# Parse the time_att column and make sure it's in the proper format
@ -514,11 +512,11 @@ class TableLayer(HasTraits):
col = self.table[proposal['value']]
if (all(isinstance(t, datetime) for t in col)
or all(isinstance(t, Time) for t in col)):
or all(isinstance(t, Time) for t in col)):
return proposal['value']
elif (isinstance(col, STR_TYPE)
or np.issubdtype(col.dtype, NP_STR_TYPE)):
or np.issubdtype(col.dtype, NP_STR_TYPE)):
try:
Time(col, format='isot')
@ -753,7 +751,7 @@ class TableLayer(HasTraits):
@observe('time_att')
def _on_time_att_change(self, *value):
if len(self.time_att) == 0 or self.time_series == False:
if len(self.time_att) == 0 or self.time_series is False:
self.parent._send_msg(event='table_layer_set', id=self.id,
setting='startDateColumn', value=-1)
return
@ -883,9 +881,9 @@ class TableLayer(HasTraits):
return state
def _save_data_for_serialization(self, dir):
file_path = path.join(dir,"{0}.csv".format(self.id))
file_path = path.join(dir, "{0}.csv".format(self.id))
table_str = csv_table_win_newline(self.table)
with open(file_path, 'wb') as file: # binary mode to preserve windows line endings
with open(file_path, 'wb') as file: # binary mode to preserve windows line endings
file.write(table_str.encode('ascii', errors='replace'))
def __str__(self):
@ -1030,7 +1028,8 @@ class ImageLayer(HasTraits):
'settings': {}
}
#A bit overkill for just the opacity, but more future-proof in case we add more wwt traits
# A bit overkill for just the opacity, but more future-proof in case
# we add more wwt traits
for trait in self.traits().values():
wwt_name = trait.metadata.get('wwt')
if wwt_name:
@ -1047,8 +1046,8 @@ class ImageLayer(HasTraits):
return state
def _save_data_for_serialization(self, dir):
file_path = path.join(dir,"{0}.fits".format(self.id))
shutil.copyfile(self._sanitized_image,file_path)
file_path = path.join(dir, "{0}.fits".format(self.id))
shutil.copyfile(self._sanitized_image, file_path)
def __str__(self):
return 'ImageLayer'

Просмотреть файл

@ -5,4 +5,3 @@ def _jupyter_nbextension_paths():
'dest': 'pywwt',
'require': 'pywwt/extension'
}]

Просмотреть файл

@ -16,7 +16,7 @@ class SolarSystem(HasTraits):
super(SolarSystem, self).__init__()
self.base_widget = base_wwt_widget
self.observe(self._on_trait_change, type='change')
self._tracked_obj_id = 0 #Default to tracking sun
self._tracked_obj_id = 0 # Default to tracking sun
def _on_trait_change(self, changed):
# This method gets called anytime a trait gets changed. Since this class
@ -31,21 +31,23 @@ class SolarSystem(HasTraits):
new_value = new_value.value
self.base_widget._send_msg(event='setting_set',
setting=wwt_name,
value=new_value)
setting=wwt_name,
value=new_value)
#cmb = Bool(False, help='Whether to show the cosmic microwave background in solar system mode (`bool`)').tag(wwt='solarSystemCMB') ###
cosmos = Bool(True, help='Whether to show data from the SDSS survey (`bool`)').tag(wwt='solarSystemCosmos') ###
#display = Bool(False, help='Whether to show the solar system while in solar system mode (`bool`)').tag(wwt='solarSystemOverlays') ###
# cmb = Bool(False, help='Whether to show the cosmic microwave background in solar system mode (`bool`)').tag(wwt='solarSystemCMB')
cosmos = Bool(True, help='Whether to show data from the SDSS survey (`bool`)').tag(wwt='solarSystemCosmos')
# display = Bool(False, help='Whether to show the solar system while in solar system mode (`bool`)').tag(wwt='solarSystemOverlays')
lighting = Bool(True,
help='Whether to show the lighting effect of the Sun on the'
' solar system (`bool`)').tag(wwt='solarSystemLighting')
milky_way = Bool(True, help='Whether to show the galactic bulge in the '
'background in solar system mode '
'(`bool`)').tag(wwt='solarSystemMilkyWay')
#multi_res = Bool(False, help='Whether to show the multi-resolution textures for planets where available (`bool`)').tag(wwt='solarSystemMultiRes') ###
minor_orbits = Bool(False, help='Whether to show the orbits of minor planets in solar system mode (`bool`)').tag(wwt='solarSystemMinorOrbits')
#minor_planets = Bool(False, help='Whether to show minor planets in solar system mode (`bool`)').tag(wwt='solarSystemMinorPlanets') ###
# multi_res = Bool(False, help='Whether to show the multi-resolution textures for planets where available (`bool`)').tag(wwt='solarSystemMultiRes')
minor_orbits = Bool(False,
help='Whether to show the orbits of minor planets '
'in solar system mode (`bool`)').tag(wwt='solarSystemMinorOrbits')
# minor_planets = Bool(False, help='Whether to show minor planets in solar system mode (`bool`)').tag(wwt='solarSystemMinorPlanets')
orbits = Bool(True,
help='Whether to show orbit paths when the solar system is '
'displayed (`bool`)').tag(wwt='solarSystemOrbits')

Просмотреть файл

@ -178,7 +178,7 @@ class TestLayers:
self.table['flux'].unit = 'm'
layer = self.client.layers.add_table_layer(table=self.table,
lon_att='ra', lat_att='dec', alt_att='flux')
lon_att='ra', lat_att='dec', alt_att='flux')
assert layer.lon_att == 'ra'
assert layer.lon_unit is u.deg
@ -213,11 +213,11 @@ class TestLayers:
assert layer.alt_att == ''
def test_line_endings(self):
self.table['ra'] = [1,2,3]
self.table['ra'] = [1, 2, 3]
expected_str = "flux,dec,ra\r\n"\
"2,4,1\r\n"\
"3,5,2\r\n"\
"4,6,3\r\n"
"2,4,1\r\n"\
"3,5,2\r\n"\
"4,6,3\r\n"
assert csv_table_win_newline(self.table) == expected_str
def test_deprecated_api_call(self, capsys):
@ -236,8 +236,6 @@ class TestLayers:
assert len(self.client.layers) == 1
assert str(self.client.layers) == ('Layer manager with 1 layers:\n\n'
' [0]: TableLayer with 3 markers\n')
assert len(w) == 1
assert issubclass(w[-1].category, DeprecationWarning)
def test_cartesian_layer(self):
@ -320,7 +318,7 @@ def test_table_layers_image(tmpdir, wwt_qt_client):
table['dec'] = [84, 85, 86, 87, 88]
table['ra'] = [250, 260, 270, 280, 290] * u.deg
layer1 = wwt.layers.add_table_layer(table=table)
layer1 = wwt.layers.add_table_layer(table=table) # noqa
# Case where we change the default values on initialization
@ -330,7 +328,7 @@ def test_table_layers_image(tmpdir, wwt_qt_client):
table['ra'] = [250, 260, 270, 280, 290] * u.deg
table['other'] = [255, 265, 275, 285, 295] * u.deg
layer2 = wwt.layers.add_table_layer(table=table, color='red', lon_att='other', size_scale=100, opacity=0.5)
layer2 = wwt.layers.add_table_layer(table=table, color='red', lon_att='other', size_scale=100, opacity=0.5) # noqa
# Case where we change the values after initialization
@ -357,7 +355,7 @@ def test_table_layers_image(tmpdir, wwt_qt_client):
table['ra'] = [250, 260, 270, 280, 290] * u.deg
table['other'] = [255, 265, 275, 285, 295] * u.deg
layer4 = wwt.layers.add_table_layer(table=table, cmap_att='other', size_att='flux', size_scale=100)
layer4 = wwt.layers.add_table_layer(table=table, cmap_att='other', size_att='flux', size_scale=100) # noqa
# Case with size and color encoding where we change the values after initialization
@ -404,11 +402,11 @@ def test_table_layers_cartesian_image(tmpdir, wwt_qt_client):
table['y'] = [0, 0.2, 0.4, 0.6, 0.8] * u.au
table['z'] = [0, 0.1, 0.2, 0.3, 0.4] * u.au
layer1 = wwt.layers.add_table_layer(table=table, coord_type='rectangular', size_scale=100, frame='Sky')
layer1 = wwt.layers.add_table_layer(table=table, coord_type='rectangular', size_scale=100, frame='Sky') # noqa
table = Table()
table['x'] = [1, 2, 3, 4, 5] * u.au
table['y'] = [-0.2, 0, 0.2, 0.4, 0.6 ] * u.au
table['y'] = [-0.2, 0, 0.2, 0.4, 0.6] * u.au
table['z'] = [0, 0.2, 0.4, 0.6, 0.8] * u.au
layer2 = wwt.layers.add_table_layer(table=table, coord_type='rectangular', frame='Sky')

Просмотреть файл

@ -1,7 +1,7 @@
import pytest
from ..core import BaseWWTWidget
from ..layers import SIZE_COLUMN_NAME, CMAP_COLUMN_NAME
from ..layers import SIZE_COLUMN_NAME, CMAP_COLUMN_NAME
import numpy as np
@ -18,8 +18,11 @@ STARDARD_WWT_SETTINGS = ['actualPlanetScale', 'showAltAzGrid', 'showConstellatio
'locationAltitude', 'locationLat', 'locationLng']
# Mock class so that we test serialization without instantiating an actual widget
class MockWWTWidget(BaseWWTWidget):
"""
Mock class so that we test serialization without instantiating an actual widget
"""
def quick_serialize(self):
return self._serialize_state(None, None, None)
@ -30,6 +33,7 @@ class MockWWTWidget(BaseWWTWidget):
def _serve_file(self, filename, extension=''):
return filename
def test_basic_serialization():
widget = MockWWTWidget()
test_state = widget._serialize_state('Title', 100, 200)
@ -62,6 +66,7 @@ def test_basic_serialization():
assert 'annotations' in test_state
assert test_state['annotations'] == []
def test_widget_settings_serialization():
widget = MockWWTWidget()
widget.actual_planet_scale = True
@ -71,9 +76,9 @@ def test_widget_settings_serialization():
widget.constellation_figure_color = '#24680b'
widget.constellation_figures = False
widget.constellation_selection = True
widget.constellation_selection_color = 'c' #cyan
widget.constellation_selection_color = 'c' # cyan
widget.crosshairs = True
widget.crosshairs_color = (128./255.,64./255.,16./255.)
widget.crosshairs_color = (128./255., 64./255., 16./255.)
widget.ecliptic = False
widget.ecliptic_grid = True
widget.galactic_grid = False
@ -83,36 +88,63 @@ def test_widget_settings_serialization():
widget.location_altitude = 7*u.m
widget.location_latitude = 12*u.deg
widget.location_longitude = -18*u.deg
expected_settings = {'actualPlanetScale': True, 'showAltAzGrid': False, 'showConstellationBoundries': True,
'constellationBoundryColor': '#ff0000', 'constellationFigureColor': '#24680b',
'showConstellationFigures': False, 'showConstellationSelection': True,
'constellationSelectionColor': '#00bfbf', 'showCrosshairs': True, 'crosshairsColor': '#804010',
'showEcliptic': False, 'showEclipticGrid': True, 'showGalacticGrid': False,
'galacticMode': True, 'showGrid': False, 'localHorizonMode': True, 'locationAltitude': 7,
'locationLat': 12., 'locationLng': -18.}
expected_settings = {'actualPlanetScale': True,
'showAltAzGrid': False,
'showConstellationBoundries': True,
'constellationBoundryColor': '#ff0000',
'constellationFigureColor': '#24680b',
'showConstellationFigures': False,
'showConstellationSelection': True,
'constellationSelectionColor': '#00bfbf',
'showCrosshairs': True,
'crosshairsColor': '#804010',
'showEcliptic': False,
'showEclipticGrid': True,
'showGalacticGrid': False,
'galacticMode': True,
'showGrid': False,
'localHorizonMode': True,
'locationAltitude': 7,
'locationLat': 12.,
'locationLng': -18.}
state = widget.quick_serialize()
assert state['wwt_settings'] == expected_settings
def test_mode_serialization():
view_mode_map = {'sky': 'sky', 'Sun': 'sun', 'Mercury': 'mercury', 'venus': 'venus', 'Earth': 'Bing Maps Aerial',
'moon': 'moon', 'mars': 'Visible Imagery', 'jupiter': 'jupiter', 'callisto': 'callisto',
'europa': 'europa', 'ganymede': 'ganymede', 'Io': 'io', 'saturn': 'saturn', 'Uranus': 'uranus',
'neptune': 'neptune', 'Pluto': 'pluto', 'panorama': 'panorama',
'Solar System': '3D Solar System View', 'milky way': '3D Solar System View',
view_mode_map = {'sky': 'sky',
'Sun': 'sun',
'Mercury': 'mercury',
'venus': 'venus',
'Earth': 'Bing Maps Aerial',
'moon': 'moon',
'mars': 'Visible Imagery',
'jupiter': 'jupiter',
'callisto': 'callisto',
'europa': 'europa',
'ganymede': 'ganymede',
'Io': 'io',
'saturn': 'saturn',
'Uranus': 'uranus',
'neptune': 'neptune',
'Pluto': 'pluto',
'panorama': 'panorama',
'Solar System': '3D Solar System View',
'milky way': '3D Solar System View',
'universe': '3D Solar System View'}
widget = MockWWTWidget()
for in_mode, out_mode in view_mode_map.items():
widget.set_view(in_mode)
assert widget.quick_serialize()['view_settings']['mode'] == out_mode, 'Mismatch for requested mode: {0}'.format(in_mode)
assert widget.quick_serialize()['view_settings']['mode'] == out_mode, \
'Mismatch for requested mode: {0}'.format(in_mode)
def test_3d_serialization():
widget = MockWWTWidget()
widget.set_view('milky way')
widget.solar_system.cosmos=True
widget.solar_system.lighting=False
widget.solar_system.cosmos = True
widget.solar_system.lighting = False
widget.solar_system.milky_way = True
widget.solar_system.minor_orbits = False
widget.solar_system.orbits = True
@ -120,10 +152,14 @@ def test_3d_serialization():
widget.solar_system.scale = 8
widget.solar_system.stars = True
expected_3d_settings = {'solarSystemCosmos':True, 'solarSystemLighting':False, 'solarSystemMilkyWay':True,
'solarSystemMinorOrbits':False, 'solarSystemOrbits':True, 'solarSystemPlanets':False,
expected_3d_settings = {'solarSystemCosmos': True,
'solarSystemLighting': False,
'solarSystemMilkyWay': True,
'solarSystemMinorOrbits': False,
'solarSystemOrbits': True,
'solarSystemPlanets': False,
'solarSystemScale': '8', # The validation method casts the int to a string
'solarSystemStars':True}
'solarSystemStars': True}
init_state = widget.quick_serialize()
settings = init_state['wwt_settings']
@ -135,13 +171,31 @@ def test_3d_serialization():
assert 'tracked_object_id' in init_state['view_settings']
assert init_state['view_settings']['tracked_object_id'] == 0
track_id_map = {'sun': 0, 'mercury': 1, 'venus': 2, 'mars': 3, 'jupiter': 4, 'saturn': 5, 'uranus': 6, 'neptune': 7,
'pluto': 8, 'moon': 9, 'io': 10, 'europa': 11, 'ganymede': 12, 'callisto': 13, 'ioshadow': 14,
'europashadow': 15, 'ganymedeshadow': 16, 'callistoshadow': 17, 'suneclipsed': 18, 'earth': 19}
track_id_map = {'sun': 0,
'mercury': 1,
'venus': 2,
'mars': 3,
'jupiter': 4,
'saturn': 5,
'uranus': 6,
'neptune': 7,
'pluto': 8,
'moon': 9,
'io': 10,
'europa': 11,
'ganymede': 12,
'callisto': 13,
'ioshadow': 14,
'europashadow': 15,
'ganymedeshadow': 16,
'callistoshadow': 17,
'suneclipsed': 18,
'earth': 19}
for obj_name, obj_id in track_id_map.items():
widget.solar_system.track_object(obj_name)
assert widget.quick_serialize()['view_settings']['tracked_object_id'] == obj_id, "ID mismatch for {0}".format(obj_name)
assert widget.quick_serialize()['view_settings']['tracked_object_id'] == obj_id, \
"ID mismatch for {0}".format(obj_name)
def test_add_remove_annotation_serialization():
@ -168,7 +222,7 @@ def test_add_remove_annotation_serialization():
def test_circle_annotation_serialization():
widget = MockWWTWidget()
circ = widget.add_circle(fill_color='#012345', radius=0.3*u.deg)
circ.set_center(SkyCoord(0.1*u.deg,0.2*u.deg))
circ.set_center(SkyCoord(0.1 * u.deg, 0.2 * u.deg))
circ.fill = True
circ.tag = 'Test Circ Tag'
circ.line_color = 'orange'
@ -176,8 +230,16 @@ def test_circle_annotation_serialization():
circ.opacity = 0.7
circ.label = 'Test Circ Label'
circ.hover_label = True
expected_settings = {'radius': 0.3, 'fill': True, 'tag': 'Test Circ Tag', 'fillColor': '#012345', 'lineColor': '#ffa500',
'lineWidth': 5, 'opacity': 0.7, 'label': 'Test Circ Label', 'showHoverLabel': True, 'skyRelative': True}
expected_settings = {'radius': 0.3,
'fill': True,
'tag': 'Test Circ Tag',
'fillColor': '#012345',
'lineColor': '#ffa500',
'lineWidth': 5,
'opacity': 0.7,
'label': 'Test Circ Label',
'showHoverLabel': True,
'skyRelative': True}
annot_state = widget.quick_serialize()['annotations'][0]
@ -199,16 +261,16 @@ def test_circle_annotation_serialization():
annot_state = widget.quick_serialize()['annotations'][0]
assert annot_state['settings'] == expected_settings
#Check circle annotation with no specified center
# Check circle annotation with no specified center
circ.remove()
circ2 = widget.add_circle()
center = widget.quick_serialize()['annotations'][0]['center']
assert center['ra'] == pytest.approx(5.)
assert center['dec'] == 10.
#Circle annotation with center in constructor
# Circle annotation with center in constructor
circ2.remove()
widget.add_circle(center = SkyCoord(15*u.deg,16*u.deg))
widget.add_circle(center=SkyCoord(15 * u.deg, 16 * u.deg))
center = widget.quick_serialize()['annotations'][0]['center']
assert center['ra'] == 15
assert center['dec'] == 16
@ -216,25 +278,31 @@ def test_circle_annotation_serialization():
def test_poly_annotation_setting():
widget = MockWWTWidget()
poly = widget.add_polygon(fill = True, tag='Test Poly Tag')
poly = widget.add_polygon(fill=True, tag='Test Poly Tag')
poly.fill_color = '#123456'
poly.line_color = 'antiquewhite'
poly.line_width = 9*u.pix
poly.opacity = 0.9
poly.label = 'Test Poly Label'
poly.hover_label = False
poly.add_point(SkyCoord([1,2,3]*u.deg,[5,6,7]*u.deg))
poly.add_point(SkyCoord(4*u.deg,8*u.deg))
expected_settings = {'fill': True, 'tag': 'Test Poly Tag', 'fillColor': '#123456', 'lineColor': '#faebd7',
'lineWidth': 9, 'opacity': 0.9, 'label': 'Test Poly Label', 'showHoverLabel': False}
poly.add_point(SkyCoord([1, 2, 3]*u.deg, [5, 6, 7]*u.deg))
poly.add_point(SkyCoord(4 * u.deg, 8 * u.deg))
expected_settings = {'fill': True,
'tag': 'Test Poly Tag',
'fillColor': '#123456',
'lineColor': '#faebd7',
'lineWidth': 9,
'opacity': 0.9,
'label': 'Test Poly Label',
'showHoverLabel': False}
annot_state = widget.quick_serialize()['annotations'][0]
assert annot_state['id'] == poly.id
assert annot_state['shape'] == 'polygon'
expected_ras = [1,2,3,4]
expected_decs = [5,6,7,8]
expected_ras = [1, 2, 3, 4]
expected_decs = [5, 6, 7, 8]
assert 'points' in annot_state
pts = annot_state['points']
assert len(pts) == 4
@ -245,26 +313,31 @@ def test_poly_annotation_setting():
assert 'settings' in annot_state
assert annot_state['settings'] == expected_settings
def test_line_annotation_setting():
widget = MockWWTWidget()
line = widget.add_line(color = '#abcde0')
line = widget.add_line(color='#abcde0')
line.tag = 'Test Line Tag'
line.width = 11*u.pix
line.opacity = 0.2
line.label = 'Test Line Label'
line.hover_label = True
line.add_point(SkyCoord([2,4,6]*u.deg,[10,12,14]*u.deg))
line.add_point(SkyCoord(8*u.deg,16*u.deg))
expected_settings = {'tag': 'Test Line Tag', 'lineColor': '#abcde0', 'lineWidth': 11, 'opacity': 0.2,
'label': 'Test Line Label', 'showHoverLabel': True}
line.add_point(SkyCoord([2, 4, 6] * u.deg, [10, 12, 14] * u.deg))
line.add_point(SkyCoord(8 * u.deg, 16 * u.deg))
expected_settings = {'tag': 'Test Line Tag',
'lineColor': '#abcde0',
'lineWidth': 11,
'opacity': 0.2,
'label': 'Test Line Label',
'showHoverLabel': True}
annot_state = widget.quick_serialize()['annotations'][0]
assert annot_state['id'] == line.id
assert annot_state['shape'] == 'line'
expected_ras = [2,4,6,8]
expected_decs = [10,12,14,16]
expected_ras = [2, 4, 6, 8]
expected_decs = [10, 12, 14, 16]
assert 'points' in annot_state
pts = annot_state['points']
assert len(pts) == 4
@ -309,7 +382,7 @@ def test_add_remove_layer_serialization():
widget.layers.remove_layer(img2)
state = widget.quick_serialize()
layer_ids = [table1.id,img1.id]
layer_ids = [table1.id, img1.id]
assert len(state['layers']) == 2
for layer in state['layers']:
assert layer['id'] in layer_ids
@ -319,6 +392,7 @@ def test_add_remove_layer_serialization():
state = widget.quick_serialize()
assert len(state['layers']) == 0
def test_table_setting_serialization():
widget = MockWWTWidget()
@ -341,21 +415,31 @@ def test_table_setting_serialization():
assert layer_state['frame'] == 'Earth'
assert 'settings' in layer_state
expected_settings = {'lngColumn':'ra', 'raUnits': 'degrees',
'latColumn': 'dec', 'altColumn': 'flux',
'timeSeries': False, 'decay': 16 * u.day,
'altUnit': None, 'altType': 'distance',
'color': '#aacc00', 'scaleFactor': 14,
'opacity': 0.75, 'plotType': 'square',
'markerScale': 'world', 'showFarSide': True,
'sizeColumn': -1, '_colorMap': 0,
'colorMapColumn': -1, 'xAxisColumn': '',
'yAxisColumn': '', 'zAxisColumn': '',
expected_settings = {'lngColumn': 'ra',
'raUnits': 'degrees',
'latColumn': 'dec',
'altColumn': 'flux',
'timeSeries': False,
'decay': 16 * u.day,
'altUnit': None,
'altType': 'distance',
'color': '#aacc00',
'scaleFactor': 14,
'opacity': 0.75,
'plotType': 'square',
'markerScale': 'world',
'showFarSide': True,
'sizeColumn': -1,
'_colorMap': 0,
'colorMapColumn': -1,
'xAxisColumn': '',
'yAxisColumn': '',
'zAxisColumn': '',
'cartesianScale': None,
'coordinatesType': 'spherical'}
assert layer_state['settings'] == expected_settings
#Check when we have colormap and scaling
# Check when we have colormap and scaling
layer.cmap_att = 'flux'
layer.size_att = 'dec'
layer.alt_unit = u.Mpc
@ -368,6 +452,7 @@ def test_table_setting_serialization():
assert widget.quick_serialize()['layers'][0]['settings'] == expected_settings
def test_image_setting_serialization():
widget = MockWWTWidget()
@ -400,4 +485,5 @@ def test_image_setting_serialization():
stretches = {'linear': 0, 'log': 1, 'power': 2, 'sqrt': 3, 'histeq': 4}
for stretch_name, stretch_id in stretches.items():
layer.stretch = stretch_name
assert widget.quick_serialize()['layers'][0]['stretch_info']['stretch'] == stretch_id, "Stretch id mismatch for: {0}".format(stretch_name)
assert widget.quick_serialize()['layers'][0]['stretch_info']['stretch'] == stretch_id, \
"Stretch id mismatch for: {0}".format(stretch_name)

Просмотреть файл

@ -89,8 +89,8 @@ class Color(TraitType):
self.from_cwo = False
def validate(self, obj, value):
if (isinstance(value, six.string_types)
or (isinstance(value, tuple) and len(value) == 3)):
if (isinstance(value, six.string_types) or
(isinstance(value, tuple) and len(value) == 3)):
return to_hex(value)
else:
if self.from_cwo:

Просмотреть файл

@ -43,6 +43,7 @@ def validate_traits(cls, traits):
mismatch,
'' if len(mismatch) > 1 else 'es'))
def ensure_utc(tm, str_allowed):
'''
Helper function to convert a time object (Time, datetime, or UTC string
@ -65,7 +66,7 @@ def ensure_utc(tm, str_allowed):
utc_tm = tm.to_datetime(pytz.UTC).isoformat()
else:
if str_allowed: # is an ISOT string
if str_allowed: # is an ISOT string
dt = Time(tm, format='isot').to_datetime(pytz.UTC)
utc_tm = dt.isoformat()
else: