Strip out all of the superseded `toast.py` code

Finally buckled down and updated the test suite to only use the newer
APIs.
This commit is contained in:
Peter Williams 2020-09-16 12:05:18 -04:00
Родитель af77780b35
Коммит 82c39b1ed1
15 изменённых файлов: 43 добавлений и 765 удалений

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

@ -49,7 +49,3 @@ Python API Reference
.. automodapi:: toasty.toast
:no-inheritance-diagram:
:no-inherited-members:
.. automodapi:: toasty.viewer
:no-inheritance-diagram:
:no-inherited-members:

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

@ -1,6 +0,0 @@
depth2tiles
===========
.. currentmodule:: toasty
.. autofunction:: depth2tiles

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

@ -1,6 +0,0 @@
gen_wtml
========
.. currentmodule:: toasty
.. autofunction:: gen_wtml

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

@ -1,6 +0,0 @@
generate_images
===============
.. currentmodule:: toasty
.. autofunction:: generate_images

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

@ -1,6 +0,0 @@
minmax_tile_filter
==================
.. currentmodule:: toasty
.. autofunction:: minmax_tile_filter

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

@ -1,6 +0,0 @@
gen_wtml
========
.. currentmodule:: toasty.toast
.. autofunction:: gen_wtml

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

@ -1,6 +0,0 @@
generate_images
===============
.. currentmodule:: toasty.toast
.. autofunction:: generate_images

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

@ -1,6 +0,0 @@
toast
=====
.. currentmodule:: toasty.toast
.. autofunction:: toast

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

@ -1,29 +0,0 @@
SimpleWWTHandler
================
.. currentmodule:: toasty.viewer
.. autoclass:: SimpleWWTHandler
:show-inheritance:
.. rubric:: Attributes Summary
.. autosummary::
~SimpleWWTHandler.wtml
.. rubric:: Methods Summary
.. autosummary::
~SimpleWWTHandler.send_head
~SimpleWWTHandler.serve_string
.. rubric:: Attributes Documentation
.. autoattribute:: wtml
.. rubric:: Methods Documentation
.. automethod:: send_head
.. automethod:: serve_string

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

@ -3,10 +3,3 @@
# Licensed under the MIT License.
from __future__ import absolute_import, division, print_function
from .toast import (
depth2tiles,
generate_images,
gen_wtml,
minmax_tile_filter,
)

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

@ -303,10 +303,15 @@ class ImageLoader(object):
-------
A new :class:`Image`.
"""
# Special handling for Numpy arrays. TODO: it would be better to sniff
# filetypes instead of just looking at extensions. But, lazy.
if path.endswith('.npy'):
arr = np.load(path)
return Image.from_array(ImageMode.F32, arr.astype(np.float32))
# Special handling for Photoshop files, used for some very large mosaics
# with transparency (e.g. the PHAT M31/M33 images). TODO: it would be
# better to sniff the PSD filetype instead of just looking at
# extensions. But, lazy.
# with transparency (e.g. the PHAT M31/M33 images).
if path.endswith('.psd') or path.endswith('.psb'):
try:

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

@ -19,28 +19,17 @@ try:
except ImportError:
HAS_ASTRO = False
from . import test_path
from .. import toast
from .._libtoasty import mid
from ..image import ImageMode
from ..image import ImageLoader, ImageMode
from ..pyramid import Pos, PyramidIO
from ..samplers import plate_carree_sampler, healpix_fits_file_sampler
from ..toast import generate_images, gen_wtml, read_image, sample_layer, save_png
def mock_sampler(x, y):
return x
@pytest.mark.parametrize('depth', (0, 1, 2))
def test_generate_images_path(depth):
result = set(r[0] for r in generate_images(mock_sampler, depth))
expected = set(['{n}/{y}/{y}_{x}.png'.format(n=n, x=x, y=y)
for n in range(depth + 1)
for y in range(2 ** n)
for x in range(2 ** n)])
assert result == expected
from ..toast import sample_layer
def test_mid():
from .._libtoasty import mid
result = mid((0, 0), (np.pi / 2, 0))
expected = np.pi / 4, 0
np.testing.assert_array_almost_equal(result, expected)
@ -68,161 +57,43 @@ def image_test(expected, actual, err_msg):
return
_, pth = mkstemp(suffix='.png')
save_png(pth, np.hstack((expected, actual)))
import PIL.Image
PIL.Image.fromarray(np.hstack((expected, actual))).save(pth)
pytest.fail("%s. Saved to %s" % (err_msg, pth))
def test_reference_wtml():
ref = parseString(reference_wtml)
opts = {'FolderName': 'ADS All Sky Survey',
'Name': 'allSources_512',
'Credits': 'ADS All Sky Survey',
'CreditsUrl': 'adsass.org',
'ThumbnailUrl': 'allSources_512.jpg'
}
wtml = gen_wtml('allSources_512', 3, **opts)
val = parseString(wtml)
assert ref.getElementsByTagName('Folder')[0].getAttribute('Name') == \
val.getElementsByTagName('Folder')[0].getAttribute('Name')
for n in ['Credits', 'CreditsUrl', 'ThumbnailUrl']:
assert ref.getElementsByTagName(n)[0].childNodes[0].nodeValue == \
val.getElementsByTagName(n)[0].childNodes[0].nodeValue
ref = ref.getElementsByTagName('ImageSet')[0]
val = val.getElementsByTagName('ImageSet')[0]
for k in ref.attributes.keys():
assert ref.getAttribute(k) == val.getAttribute(k)
def cwd():
return os.path.split(os.path.abspath(__file__))[0]
def test_wwt_compare_sky():
"""Assert that the toast tiling looks similar to the WWT tiles"""
direc = cwd()
im = read_image(os.path.join(direc, 'Equirectangular_projection_SW-tweaked.jpg'))
sampler = plate_carree_sampler(im)
for pth, result in generate_images(sampler, depth=1):
expected = read_image(os.path.join(direc, 'earth_toasted_sky', pth))
expected = expected[:, :, :3]
image_test(expected, result, "Failed for %s" % pth)
@pytest.mark.skipif('not HAS_ASTRO')
def test_healpix_sampler_equ():
direc = cwd()
sampler = healpix_fits_file_sampler(os.path.join(direc, 'earth_healpix_equ.fits'))
for pth, result in generate_images(sampler, depth=1):
expected = read_image(os.path.join(direc, 'earth_toasted_sky', pth))
expected = expected.sum(axis=2) // 3
image_test(expected, result, "Failed for %s" % pth)
@pytest.mark.skipif('not HAS_ASTRO')
def test_healpix_sampler_gal():
direc = cwd()
sampler = healpix_fits_file_sampler(os.path.join(direc, 'earth_healpix_gal.fits'))
for pth, result in generate_images(sampler, depth=1):
expected = read_image(os.path.join(direc, 'earth_toasted_sky', pth))
expected = expected.sum(axis=2) // 3
image_test(expected, result, "Failed for %s" % pth)
def test_merge():
# test that merge function called on non-terminal nodes
im = read_image(os.path.join(cwd(), 'Equirectangular_projection_SW-tweaked.jpg'))
def null_merge(mosaic):
return np.zeros((256, 256, 3), dtype=np.uint8)
sampler = plate_carree_sampler(im)
for pth, im in generate_images(sampler, 2, null_merge):
if pth[0] != '2':
assert im.max() == 0
else:
assert im.max() != 0
class TestToaster(object):
class TestSampleLayer(object):
def setup_method(self, method):
self.base = mkdtemp()
self.cwd = cwd()
im = read_image(os.path.join(self.cwd, 'Equirectangular_projection_SW-tweaked.jpg'))
self.sampler = plate_carree_sampler(im)
def teardown_method(self, method):
rmtree(self.base)
def verify_toast(self):
""" Zip the expected and actual tiles """
for n, x, y in [(0, 0, 0), (1, 0, 0), (1, 0, 1),
(1, 1, 0), (1, 1, 1)]:
subpth = os.path.join(str(n), str(y), "%i_%i.png" % (y, x))
a = read_image(os.path.join(self.base, subpth))[:, :, :3]
b = read_image(os.path.join(self.cwd, 'earth_toasted_sky', subpth))[:, :, :3]
image_test(b, a, 'Failed for %s' % subpth)
def test_default(self):
wtml = os.path.join(self.base, 'test.wtml')
toast.toast(self.sampler, 1, self.base, wtml_file=wtml)
assert os.path.exists(wtml)
self.verify_toast()
def test_no_merge(self):
toast.toast(self.sampler, 1, self.base, merge=False)
self.verify_toast()
reference_wtml = """
<Folder Name="ADS All Sky Survey">
<ImageSet Generic="False" DataSetType="Sky" BandPass="Visible" Name="allSources_512" Url="allSources_512/{1}/{3}/{3}_{2}.png" BaseTileLevel="0" TileLevels="3" BaseDegreesPerTile="180" FileType=".png" BottomsUp="False" Projection="Toast" QuadTreeMap="" CenterX="0" CenterY="0" OffsetX="0" OffsetY="0" Rotation="0" Sparse="False" ElevationModel="False">
<Credits> ADS All Sky Survey </Credits>
<CreditsUrl>adsass.org</CreditsUrl>
<ThumbnailUrl>allSources_512.jpg</ThumbnailUrl>
<Description/>
</ImageSet>
</Folder>
"""
class TestSamplingLayer(object):
def setup_method(self, method):
self.base = mkdtemp()
self.cwd = cwd()
im = read_image(os.path.join(self.cwd, 'Equirectangular_projection_SW-tweaked.jpg'))
self.sampler = plate_carree_sampler(im)
from ..pyramid import PyramidIO
self.pio = PyramidIO(self.base)
def teardown_method(self, method):
rmtree(self.base)
def verify_toast(self):
""" Zip the expected and actual tiles """
for n, x, y in [(1, 0, 0), (1, 0, 1),
(1, 1, 0), (1, 1, 1)]:
subpth = os.path.join(str(n), str(y), "%i_%i.png" % (y, x))
a = read_image(os.path.join(self.base, subpth))[:, :, :3]
b = read_image(os.path.join(self.cwd, 'earth_toasted_sky', subpth))[:, :, :3]
image_test(b, a, 'Failed for %s' % subpth)
def verify_level1(self, mode):
for n, x, y in [(1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1)]:
ref_path = test_path('earth_toasted_sky', str(n), str(y), "%i_%i.png" % (y, x))
expected = ImageLoader().load_path(ref_path).asarray()
if mode == ImageMode.F32:
expected = expected.mean(axis=2)
def test_default(self):
sample_layer(self.pio, ImageMode.RGB, self.sampler, 1)
self.verify_toast()
pos = Pos(n=n, x=x, y=y)
observed = self.pio.read_toasty_image(pos, mode).asarray()
image_test(expected, observed, 'Failed for %s' % ref_path)
def test_plate_carree(self):
img = ImageLoader().load_path(test_path('Equirectangular_projection_SW-tweaked.jpg'))
sampler = plate_carree_sampler(img.asarray())
sample_layer(self.pio, ImageMode.RGB, sampler, 1)
self.verify_level1(ImageMode.RGB)
def test_healpix_equ(self):
sampler = healpix_fits_file_sampler(test_path('earth_healpix_equ.fits'))
sample_layer(self.pio, ImageMode.F32, sampler, 1)
self.verify_level1(ImageMode.F32)
def test_healpix_gal(self):
sampler = healpix_fits_file_sampler(test_path('earth_healpix_gal.fits'))
sample_layer(self.pio, ImageMode.F32, sampler, 1)
self.verify_level1(ImageMode.F32)

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

@ -1,46 +0,0 @@
# -*- mode: python; coding: utf-8 -*-
# Copyright 2013-2019 Chris Beaumont and the AAS WorldWide Telescope project
# Licensed under the MIT License.
from threading import Thread
try:
from SocketServer import TCPServer
from urllib import urlopen
except ImportError: # python 3.X
from socketserver import TCPServer
from urllib.request import urlopen
import sys
import os
from ..viewer import SimpleWWTHandler
def cwd():
return os.path.split(os.path.abspath(__file__))[0]
class TestViewer(object):
def setup_class(cls):
sys.argv.append(os.path.join(cwd(), 'earth_toasted_sky'))
PORT = 8000
# configure to immediately release the socket on close
# http://stackoverflow.com/questions/17659334
cls.server = TCPServer(("", PORT), SimpleWWTHandler, False)
cls.server.allow_reuse_address = True
cls.server.server_bind()
cls.server.server_activate()
cls.thread = Thread(target=cls.server.serve_forever)
cls.thread.start()
def teardown_class(cls):
cls.server.shutdown()
def test_wtml(self):
data = urlopen('http://0.0.0.0:8000/toasty.wtml').read()
assert '<ImageSet' in str(data)
def test_root(self):
data = urlopen('http://0.0.0.0:8000/').read()
assert 'WWTCanvas' in str(data)

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

@ -11,14 +11,11 @@ wwt_data_formats.
from __future__ import absolute_import, division, print_function
__all__ = '''
generate_images
generate_tiles
gen_wtml
minmax_tile_filter
nxy_tile_filter
sample_layer
Tile
toast
toast_tile_area
'''.split()
@ -280,307 +277,3 @@ def sample_layer(pio, mode, sampler, depth):
)
sampled_data = sampler(lon, lat)
pio.write_toasty_image(tile.pos, Image.from_array(mode, sampled_data))
# This is where we start needing to revamp all of the I/O and pyramid-management stuff:
import PIL.Image
def save_png(pth, array):
PIL.Image.fromarray(array).save(pth)
def read_image(path):
return np.asarray(PIL.Image.open(path))
def generate_images(
data_sampler,
depth,
merge = True,
base_level_only = False,
tile_filter = None,
top = 0
):
"""
Create a hierarchy of toast tiles
Parameters
----------
data_sampler : func or string
- A function that takes two 2D numpy arrays of (lon, lat) as input,
and returns an image of the original dataset sampled
at these locations; see :mod:`toasty.samplers`.
- A string giving a base toast directory that contains the
base level of toasted tiles, using this option, only the
merge step takes place, the given directory must contain
a "depth" directory for the given depth parameter
depth : int
The maximum depth to tile to. A depth of N creates
4^N pngs at the deepest level
merge : bool or callable (default True)
How to treat lower resolution tiles.
- If True, tiles above the lowest level (highest resolution)
will be computed by averaging and downsampling the 4 subtiles.
- If False, sampler will be called explicitly for all tiles
- If a callable object, this object will be passed the
4x oversampled image to downsample
base_level_only : bool (default False)
If True only the bottem level of tiles will be created.
In this case merge will be set to True, but no merging will happen,
and only the highest resolution layer of images will be created.
tile_filter: callable (optional)
A function that takes a tile and determines if it is in toasting range.
If not given default_tile_filter will be used which simply returns True.
top: int (optional)
The topmost layer of toast tiles to create (only relevant if
base_level_only is False), default is 0.
Yields
------
(pth, tile) : str, ndarray
pth is the relative path where the tile image should be saved
"""
if tile_filter is None:
tile_filter = lambda t: True
if merge is True:
merge = _default_merge
parents = defaultdict(dict)
for tile in generate_tiles(max(depth, 1), bottom_only=merge, tile_filter=tile_filter):
n, x, y = tile.pos.n, tile.pos.x, tile.pos.y
if type(data_sampler) == str:
img_dir = data_sampler + '/' + str(n) + '/'
try:
img = read_image(img_dir + str(y) + '/' + str(y) + '_' + str(x) + '.png')
except: # could not read image
img = None
else:
l, b = subsample(tile.corners[0], tile.corners[1], tile.corners[2], tile.corners[3], 256, tile.increasing)
img = data_sampler(l, b)
# No image was returned by the sampler -- looks like either image data
# was not available for this position
if img is None and base_level_only:
continue
if not base_level_only:
for pth, img in _trickle_up(img, tile.pos, parents, merge, depth, top):
if img is None:
continue
yield pth, img
else:
pth = os.path.join('%i' % n, '%i' % y, '%i_%i.png' % (y, x))
yield pth, img
def _trickle_up(im, node, parents, merge, depth, top=0):
"""
When a new toast tile is ready, propagate it up the hierarchy
and recursively yield its completed parents
"""
n, x, y = node.n, node.x, node.y
pth = os.path.join('%i' % n, '%i' % y, '%i_%i.png' % (y, x))
nparent = sum(len(v) for v in parents.values())
assert nparent <= 4 * max(depth, 1)
if depth >= n: # handle special case of depth=0, n=1
yield pth, im
if n == top: # This is the uppermost level desired
return
# - If not merging and not at level 1, no need to accumulate
if not merge and n > 1:
return
parent, xc, yc = pos_parent(node)
corners = parents[parent]
corners[(xc, yc)] = im
if len(corners) < 4: # parent not yet ready
return
parents.pop(parent)
# imgs = [ul,ur,bl,br]
#imgs = np.array([corners[(0, 0)],corners[(1, 0)],corners[(1, 0)],corners[(1, 1)]])
ul = corners[(0, 0)]
ur = corners[(1, 0)]
bl = corners[(0, 1)]
br = corners[(1, 1)]
# dealing with any children lacking image data
if all(x is None for x in [ul,ur,bl,br]):
im = None
else:
# get img shape
imgShape = [x for x in [ul,ur,bl,br] if x is not None][0].shape
if not imgShape: # This shouldn't happen but...
print([type(x) for x in [ul,ur,bl,br]])
im = None
else:
if ul is None:
ul = np.zeros(imgShape,dtype=np.uint8)
if ur is None:
ur = np.zeros(imgShape,dtype=np.uint8)
if bl is None:
bl = np.zeros(imgShape,dtype=np.uint8)
if br is None:
br = np.zeros(imgShape,dtype=np.uint8)
try:
mosaic = np.vstack((np.hstack((ul, ur)), np.hstack((bl, br))))
im = (merge or _default_merge)(mosaic)
except:
print(imgShape)
im = None
for item in _trickle_up(im, parent, parents, merge, depth, top):
yield item
def _default_merge(mosaic):
"""The default merge strategy -- just average all 4 pixels"""
return (mosaic[::2, ::2] / 4. +
mosaic[1::2, ::2] / 4. +
mosaic[::2, 1::2] / 4. +
mosaic[1::2, 1::2] / 4.).astype(mosaic.dtype)
# XXX TODO: this should be superseded by use of wwt_data_formats
def gen_wtml(base_dir, depth, **kwargs):
"""
Create a minimal WTML record for a pyramid generated by toasty
Parameters
----------
base_dir : str
The base path to a toast pyramid, as you wish for it to appear
in the WTML file (i.e., this should be a path visible to a server)
depth : int
The maximum depth of the pyramid
**kwargs
Keyword arguments may be used to set parameters that appear in the
generated WTML file. Keywords that are honored are:
- FolderName
- BandPass
- Name
- Credits
- CreditsUrl
- ThumbnailUrl
Unhandled keywords are silently ignored.
Returns
-------
wtml : str
A WTML record
"""
kwargs.setdefault('FolderName', 'Toasty')
kwargs.setdefault('BandPass', 'Visible')
kwargs.setdefault('Name', 'Toasty map')
kwargs.setdefault('Credits', 'Toasty')
kwargs.setdefault('CreditsUrl', 'http://github.com/ChrisBeaumont/toasty')
kwargs.setdefault('ThumbnailUrl', '')
kwargs['url'] = base_dir
kwargs['depth'] = depth
template = ('<Folder Name="{FolderName}">\n'
'<ImageSet Generic="False" DataSetType="Sky" '
'BandPass="{BandPass}" Name="{Name}" '
'Url="{url}/{{1}}/{{3}}/{{3}}_{{2}}.png" BaseTileLevel="0" '
'TileLevels="{depth}" BaseDegreesPerTile="180" '
'FileType=".png" BottomsUp="False" Projection="Toast" '
'QuadTreeMap="" CenterX="0" CenterY="0" OffsetX="0" '
'OffsetY="0" Rotation="0" Sparse="False" '
'ElevationModel="False">\n'
'<Credits> {Credits} </Credits>\n'
'<CreditsUrl>{CreditsUrl}</CreditsUrl>\n'
'<ThumbnailUrl>{ThumbnailUrl}</ThumbnailUrl>\n'
'<Description/>\n</ImageSet>\n</Folder>')
return template.format(**kwargs)
def toast(data_sampler, depth, base_dir,
wtml_file=None, merge=True, base_level_only=False,
tile_filter=None, top_layer=0):
"""Build a directory of toast tiles
Parameters
----------
data_sampler : func or string
- A function of (lon, lat) that samples a dataset
at the input 2D coordinate arrays
- A string giving a base toast directory that contains the
base level of toasted tiles, using this option, only the
merge step takes place, the given directory must contain
a "depth" directory for the given depth parameter
depth : int
The maximum depth to generate tiles for.
4^n tiles are generated at each depth n
base_dir : str
The path to create the files at
wtml_file : str (optional)
The path to write a WTML file to. If not present,
no file will be written
merge : bool or callable (default True)
How to treat lower resolution tiles.
- If True, tiles above the lowest level (highest resolution)
will be computed by averaging and downsampling the 4 subtiles.
- If False, sampler will be called explicitly for all tiles
- If a callable object, this object will be passed the
4x oversampled image to downsample
base_level_only : bool (default False)
If True only the bottem level of tiles will be created.
In this case merge will be set to True, but no merging will happen,
and only the highest resolution layer of images will be created.
tile_filter : callable or None (the default)
An optional function ``accept_tile(tile) -> bool`` that filters tiles;
only tiles for which the fuction returns ``True`` will be
processed.
top_layer: int (optional)
If merging this indicates the uppermost layer to be created.
"""
if wtml_file is not None:
wtml = gen_wtml(base_dir, depth)
with open(wtml_file, 'w') as outfile:
outfile.write(wtml)
if base_level_only:
merge = True
num = 0
for pth, tile in generate_images(data_sampler, depth, merge, base_level_only, tile_filter, top_layer):
num += 1
if num % 10 == 0:
logging.getLogger(__name__).info("Finished %i of %i tiles" %
(num, depth2tiles(depth)))
pth = os.path.join(base_dir, pth)
direc, _ = os.path.split(pth)
if not os.path.exists(direc):
try:
os.makedirs(direc)
except FileExistsError:
print("%s already exists." % direc)
try:
save_png(pth, tile)
except:
print(pth)
print(type(tile))

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

@ -1,163 +0,0 @@
# -*- mode: python; coding: utf-8 -*-
# Copyright 2013-2019 Chris Beaumont and the AAS WorldWide Telescope project
# Licensed under the MIT License.
"""Set up a minimal HTTP Server to preview a Toasty-generated tile pyramid.
"""
from __future__ import absolute_import, division, print_function
import os
import sys
from time import time
try:
from SimpleHTTPServer import SimpleHTTPRequestHandler, test
from cStringIO import StringIO
except: # python 3.X
from http.server import SimpleHTTPRequestHandler, test
from io import BytesIO
from . import gen_wtml
__all__ = '''
SimpleWWTHandler
'''.split()
class SimpleWWTHandler(SimpleHTTPRequestHandler):
def serve_string(self, contents):
if sys.version_info.major == 2:
return StringIO(contents)
return BytesIO(contents.encode('UTF-8'))
@property
def wtml(self):
if not hasattr(self, '_wtml'):
base_dir = sys.argv[-1]
depths = next(os.walk(base_dir))[1]
max_depth = max(map(int, depths))
self._wtml = gen_wtml(base_dir, max_depth)
return self._wtml
def send_head(self):
if self.path == '/toasty.wtml':
self.send_response(200)
self.send_header("Content-type", 'text/xml')
self.send_header("Content-Length", str(len(self.wtml)))
self.send_header("Last-Modified",
self.date_time_string(int(time())))
self.end_headers()
return self.serve_string(self.wtml)
if self.path in ['/', '/index.html']:
self.send_response(200)
self.send_header("Content-type", 'text/html')
self.send_header("Content-Length", str(len(html)))
self.send_header("Last-Modified",
self.date_time_string(int(time())))
self.end_headers()
return self.serve_string(html)
return SimpleHTTPRequestHandler.send_head(self)
html = """
<html>
<head>
<title> Toasty Viewer </title>
<style type="text/css">
html, body {
height: 100%;
overflow: hidden;
}
body {
padding: 0;
margin: 0;
}
#canvas {
padding: 0;
margin: 0 0 0px 0;
}
#UI {
position: relative;
top: -40px;
left: 20px;
}
div {margin: 0 0 0px 0; padding: 0;}
</style>
<script src="http://www.worldwidetelescope.org/scripts/wwtsdk.aspx"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
</head>
<body onload="init();" onresize="resize_canvas();" style="background-color:#000000">
<script type="text/javascript">
function init() {
wwt = wwtlib.WWTControl.initControl("WWTCanvas");
wwt.add_ready(wwtReady);
resize_canvas();
}
function resize_canvas() {
div = document.getElementById("WWTCanvas");
if (div.style.width != (window.innerWidth).toString() + "px") {
div.style.width = (window.innerWidth).toString() + "px";
}
if (div.style.height != (window.innerHeight).toString() + "px") {
div.style.height = ((window.innerHeight)).toString() + "px";
}
}
function wwtReady() {
wwt.settings.set_showCrosshairs(true);
wwt.settings.set_showConstellationFigures(false);
wwt.settings.set_showConstellationBoundries(false);
wwt.loadImageCollection('/toasty.wtml');
wwt.add_collectionLoaded(set_layers);
$('#select-foreground').change(function(e){
wwt.setBackgroundImageByName(this.value)
});
$('#opacity').change(function(e){
wwt.setForegroundOpacity(this.value);
});
}
function set_layers() {
wwt.setBackgroundImageByName('Wise All Sky (Infrared)');
wwt.setForegroundImageByName('Toasty map');
wwt.setForegroundOpacity(50);
}
</script>
<div id="WWTCanvas" style="width: 750px; height: 750px; border-style: none; border-width: 0px;">
</div>
<div id="UI">
<select id="select-foreground">
<option value="Digitized Sky Survey (Color)"> Optical </option>
<option value="WMAP ILC 5-Year Cosmic Microwave Background"> WMAP 5-Year </option>
<option value="SFD Dust Map (Infrared)"> SFD </option>
<option value="IRIS: Improved Reprocessing of IRAS Survey (Infrared)"> IRIS </option>
<option value="Hydrogen Alpha Full Sky Map"> H-alpha </option>
</select>
<input id='opacity' type="range" name="opacity" min="10" max="100">
</div>
</body>
</html>
"""
if __name__ == "__main__":
sys.argv.insert(1, '8000')
test(HandlerClass=SimpleWWTHandler)