Source code for jdaviz.configs.default.plugins.metadata_viewer.metadata_viewer

from astropy.io.fits import Header
from traitlets import Bool, List, Unicode, observe

from jdaviz.core.events import AddDataMessage, RemoveDataMessage
from jdaviz.core.registries import tray_registry
from jdaviz.core.template_mixin import TemplateMixin

__all__ = ['MetadataViewer']


[docs]@tray_registry('g-metadata-viewer', label="Metadata Viewer") class MetadataViewer(TemplateMixin): template_file = __file__, "metadata_viewer.vue" dc_items = List([]).tag(sync=True) selected_data = Unicode("").tag(sync=True) has_metadata = Bool(False).tag(sync=True) metadata = List([]).tag(sync=True) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.hub.subscribe(self, AddDataMessage, handler=self._on_viewer_data_changed) self.hub.subscribe(self, RemoveDataMessage, handler=self._on_viewer_data_changed) def _on_viewer_data_changed(self, *args, **kwargs): self.dc_items = [data.label for data in self.app.data_collection] @observe("selected_data") def _show_metadata(self, event): try: data = self.app.data_collection[self.app.data_collection.labels.index(event['new'])] except ValueError: self.has_metadata = False self.metadata = [] return if not hasattr(data, 'meta') or not isinstance(data.meta, dict) or len(data.meta) < 1: self.has_metadata = False self.metadata = [] else: if 'header' in data.meta and isinstance(data.meta['header'], (dict, Header)): if isinstance(data.meta['header'], Header): # Specviz meta = dict(data.meta['header']) else: meta = data.meta['header'] else: meta = data.meta d = flatten_nested_dict(meta) for badkey in ('COMMENT', 'HISTORY', ''): if badkey in d: del d[badkey] # ipykernel cannot clean for JSON # TODO: Option to not sort? self.metadata = sorted(zip(d.keys(), map(str, d.values()))) self.has_metadata = True
# TODO: If this is natively supported by asdf in the future, replace with native function. # This code below is taken code from stdatamodels/model_base.py, and the method to_flat_dict() def flatten_nested_dict(asdfnode, include_arrays=True): """ Returns a dictionary of all of the schema items as a flat dictionary. Each dictionary key is a dot-separated name. For example, the schema element ``meta.observation.date`` at the root node will end up in the dictionary as:: { "meta.observation.date": "2012-04-22T03:22:05.432" } """ import datetime import numpy as np from astropy.time import Time def convert_val(val): if isinstance(val, datetime.datetime): # pragma: no cover return val.isoformat() elif isinstance(val, Time): # pragma: no cover return str(val) return val if include_arrays: return dict((key, convert_val(val)) for (key, val) in _iteritems(asdfnode)) else: # pragma: no cover return dict((key, convert_val(val)) for (key, val) in _iteritems(asdfnode) if not isinstance(val, np.ndarray)) def _iteritems(asdfnode): """ Iterates over all of the schema items in a flat way. Each element is a pair (`key`, `value`). Each `key` is a dot-separated name. For example, the schema element `meta.observation.date` will end up in the result as:: ("meta.observation.date": "2012-04-22T03:22:05.432") """ def recurse(asdfnode, path=[]): if isinstance(asdfnode, dict): for key, val in asdfnode.items(): for x in recurse(val, path + [key]): yield x elif isinstance(asdfnode, (list, tuple)): for i, val in enumerate(asdfnode): for x in recurse(val, path + [i]): yield x else: yield ('.'.join(str(x) for x in path), asdfnode) for x in recurse(asdfnode): yield x