Source code for toasty.builder

# -*- mode: python; coding: utf-8 -*-
# Copyright 2020 the AAS WorldWide Telescope project
# Licensed under the MIT License.

"""
Building up WWT imagery data sets.

This gets a little complex since the generation of a tiled image involves
several tasks that may or may not be implemented in several, swappable ways:
generating the tiled pixel data; positioning the image on the sky; filling in
metadata; and so on. We try to provide a framework that allows the
implementations of different tasks to be swapped out without getting too airy
and abstract.

"""
from __future__ import absolute_import, division, print_function

__all__ = '''
Builder
'''.split()

from wwt_data_formats.enums import DataSetType, ProjectionType
from wwt_data_formats.imageset import ImageSet
from wwt_data_formats.layers import ImageSetLayer, LayerContainerReader
from wwt_data_formats.place import Place

from .image import ImageLoader


[docs]class Builder(object): """ State for some kind of imagery data set that's being assembled. """ pio = None "A PyramidIO object representing the backing storage of the tiles and other image data." imgset = None """ The WWT ImageSet data describing the image data and their positioning on the sky. Data URLs in this ImageSet should be populated as relative URLs. """ place = None "The WWT Place data describing a default view of the image data." def __init__(self, pio): self.pio = pio self.imgset = ImageSet() self.imgset.name = 'Toasty' self.place = Place() self.place.foreground_image_set = self.imgset self.place.name = 'Toasty'
[docs] def tile_base_as_study(self, image, **kwargs): from .study import tile_study_image tiling = tile_study_image(image, self.pio, **kwargs) tiling.apply_to_imageset(self.imgset) self.imgset.url = self.pio.get_path_scheme() + '.png' self.imgset.file_type = '.png' return self
[docs] def default_tiled_study_astrometry(self): self.imgset.data_set_type = DataSetType.SKY self.imgset.base_degrees_per_tile = 1.0 self.imgset.projection = ProjectionType.TAN self.place.zoom_level = 1.0 return self
[docs] def load_from_wwtl(self, cli_settings, wwtl_path): from io import BytesIO # Load WWTL and see if it matches expectations lc = LayerContainerReader.from_file(wwtl_path) if len(lc.layers) != 1: raise Exception('WWTL file must contain exactly one layer') layer = lc.layers[0] if not isinstance(layer, ImageSetLayer): raise Exception('WWTL file must contain an imageset layer') imgset = layer.image_set if imgset.projection != ProjectionType.SKY_IMAGE: raise Exception('WWTL imageset layer must have "SkyImage" projection type') # Looks OK. Read and parse the image. loader = ImageLoader.create_from_args(cli_settings) img_data = lc.read_layer_file(layer, layer.extension) img = loader.load_stream(BytesIO(img_data)) # Transmogrify untiled image info to tiled image info. We reuse the # existing imageset as much as possible, but update the parameters that # change in the tiling process. self.imgset = imgset self.place.foreground_image_set = self.imgset wcs_keywords = self.imgset.wcs_headers_from_position() self.tile_base_as_study(img) self.imgset.set_position_from_wcs(wcs_keywords, img.width, img.height, place=self.place) return img
[docs] def toast_base(self, mode, sampler, depth, **kwargs): from .toast import sample_layer sample_layer(self.pio, mode, sampler, depth, **kwargs) self.imgset.data_set_type = DataSetType.SKY self.imgset.base_degrees_per_tile = 180 self.imgset.file_type = '.png' self.imgset.projection = ProjectionType.TOAST self.imgset.tile_levels = depth self.imgset.url = self.pio.get_path_scheme() + '.png' self.place.zoom_level = 360 return self
[docs] def cascade(self, **kwargs): from .image import ImageMode from .merge import averaging_merger, cascade_images cascade_images(self.pio, ImageMode.RGBA, self.imgset.tile_levels, averaging_merger, **kwargs) return self
[docs] def make_thumbnail_from_other(self, thumbnail_image): thumb = thumbnail_image.make_thumbnail_bitmap() with self.pio.open_metadata_for_write('thumb.jpg') as f: thumb.save(f, format='JPEG') self.imgset.thumbnail_url = 'thumb.jpg' return self
[docs] def make_placeholder_thumbnail(self): import numpy as np from .image import Image, ImageMode arr = np.zeros((45, 96, 3), dtype=np.uint8) img = Image.from_array(ImageMode.RGB, arr) with self.pio.open_metadata_for_write('thumb.jpg') as f: img.aspil().save(f, format='JPEG') self.imgset.thumbnail_url = 'thumb.jpg' return self
[docs] def apply_wcs_info(self, wcs, width, height): self.imgset.set_position_from_wcs( wcs.to_header(), width, height, place = self.place, ) return self
[docs] def apply_avm_info(self, avm, width, height): self.apply_wcs_info(avm.to_wcs(target_shape=(width, height)), width, height) if avm.Title: self.imgset.name = avm.Title if avm.Description: self.imgset.description = avm.Description if avm.Credit: self.imgset.credits = avm.Credit if avm.ReferenceURL: self.imgset.credits_url = avm.ReferenceURL return self
[docs] def write_index_rel_wtml(self): from wwt_data_formats import write_xml_doc from wwt_data_formats.folder import Folder self.place.name = self.imgset.name self.place.data_set_type = self.imgset.data_set_type self.place.thumbnail = self.imgset.thumbnail_url folder = Folder() folder.name = self.imgset.name folder.children = [self.place] with self.pio.open_metadata_for_write('index_rel.wtml') as f: write_xml_doc(folder.to_xml(), dest_stream=f, dest_wants_bytes=True) return self