Source code for mast_aladin.adapters.viewport_outline

from datetime import datetime
from echo import delay_callback
from traitlets import Unicode, Bool, Float, observe, HasTraits

from mast_aladin import gca
import jdaviz


[docs] class ViewportOutline(HasTraits): """ Draw the outline of a mast-aladin viewport's coordinate limits in jdaviz, and vice versa. On initialization, clears any existing viewport outlines in the viewers, before creating new ones. Traitlets --------- outline_color : str Hex color code for the outline overlay, default is red. outline_width : str Width of the outline overlay, default is 4. jdaviz_outline_in_aladin : bool Draw the outline of the jdaviz viewport in mast-aladin. Default is True. aladin_outline_in_jdaviz : bool Draw the outline of the mast-aladin viewport in jdaviz. Default is True. """ aladin_overlay = None jdaviz_overlay = None outline_color = Unicode('#ff0000').tag(sync=True) outline_width = Float(4).tag(sync=True) jdaviz_outline_in_aladin = Bool(True).tag(sync=True) aladin_outline_in_jdaviz = Bool(True).tag(sync=True) def __init__( self, jdaviz_viewer, aladin, jdaviz_outline_in_aladin=True, aladin_outline_in_jdaviz=True, clear_existing=True ): """ Parameters ---------- jdaviz_viewer : `jdaviz.configs.imviz.plugins.viewers.ImvizImageView` Instance of a jdaviz viewer. Can be retrieved from ``jdaviz_app.viewers`` dict (e.g., ``app.viewers['imviz-0']``). aladin : `~mast_aladin.MastAladin` Instance of a Mast Aladin app. jdaviz_outline_in_aladin : bool Draw the outline of the jdaviz viewport in mast-aladin. Default is True. aladin_outline_in_jdaviz : bool Draw the outline of the mast-aladin viewport in jdaviz. Default is True. """ self.jdaviz_viewer = jdaviz_viewer self.aladin = aladin self.aladin_outline_in_jdaviz = aladin_outline_in_jdaviz self.jdaviz_outline_in_aladin = jdaviz_outline_in_aladin self._clear_existing_outlines() self._update_or_clear_outlines() def _clear_jdaviz_outline_in_aladin(self): """ Clear the latest jdaviz viewport outline drawn in aladin. """ if self.aladin_overlay is not None: overlay_label = self.aladin_overlay['options']['name'] if overlay_label in self.aladin._overlays: self.aladin.remove_overlay(self.aladin_overlay) def _clear_aladin_outline_in_jdaviz(self): """ Clear the latest mast-aladin viewport outline drawn in jdaviz. """ if self.jdaviz_overlay is not None: glue_viewer = self.jdaviz_viewer._obj.glue_viewer overlay_label = self.jdaviz_overlay['region_label'] if overlay_label in glue_viewer._get_region_overlay_labels(): glue_viewer._remove_region_overlay(overlay_label) def _update_jdaviz_outline_in_aladin(self, msg={}): """ Update the jdaviz viewport outline drawn in aladin. """ self._clear_jdaviz_outline_in_aladin() imviz_viewport = self.jdaviz_viewer.get_viewport_region() self.aladin_overlay = self.aladin.add_graphic_overlay_from_region( imviz_viewport, name=self._viewport_label(app_name='jdaviz'), color=self.outline_color, lineWidth=self.outline_width, ) def _update_aladin_outline_in_jdaviz(self, msg={}): """ Update the mast-aladin viewport outline drawn in jdaviz. """ self._clear_aladin_outline_in_jdaviz() # it's possible that this method has been called before the # aladin instance has been rendered. Check, and raise an error # if aladin hasn't been rendered yet. if not self.aladin._wcs: raise ValueError( f"{self.aladin} is not yet rendered. Viewport outlines " "cannot be initialized until mast-aladin has been rendered " "in the Jupyter environment." ) self.jdaviz_overlay = dict( region=self.aladin.get_viewport_region(), region_label=self._viewport_label(app_name='mast-aladin'), colors=[self.outline_color], stroke_width=self.outline_width, ) glue_viewer = self.jdaviz_viewer._obj.glue_viewer glue_viewer._add_region_overlay(**self.jdaviz_overlay) def _viewport_label(self, app_name=None): """ Generate a label for the viewport outline overlay layers. """ # hours, minutes, seconds: time = datetime.now().time().strftime('%H:%M:%S') return ( ('' if app_name is None else f"{app_name} @ ") + time ) @observe('jdaviz_outline_in_aladin', 'aladin_outline_in_jdaviz') def _update_or_clear_outlines(self, msg={}): """ Update requested or existing outlines, and clear others. """ if self.aladin_outline_in_jdaviz: # add jdaviz viewport overlay in mast-aladin self._update_aladin_outline_in_jdaviz() # observe mast-aladin traitlets to trigger updates in jdaviz: self.aladin.observe(self._update_aladin_outline_in_jdaviz, '_fov') self.aladin.observe(self._update_aladin_outline_in_jdaviz, '_target') else: self._clear_aladin_outline_in_jdaviz() if self.jdaviz_outline_in_aladin: self._update_jdaviz_outline_in_aladin() glue_viewer = self.jdaviz_viewer._obj.glue_viewer # add callback to jdaviz viewerport limits to trigger updates in mast-aladin glue_viewer.state.add_callback( 'x_min', self._update_jdaviz_outline_in_aladin ) else: self._clear_jdaviz_outline_in_aladin() @observe('outline_color', 'outline_width') def _redraw(self, msg={}): """ Force an udpate on the overlays """ if self.aladin_outline_in_jdaviz: self._update_aladin_outline_in_jdaviz() if self.jdaviz_outline_in_aladin: self._update_jdaviz_outline_in_aladin()
[docs] def clear_all(self): """ Clear all outlines, including those that were created by another instance of ``ViewportOutline``. """ with delay_callback('jdaviz_outline_in_aladin', 'aladin_outline_in_jdaviz'): self.jdaviz_outline_in_aladin = False self.aladin_outline_in_jdaviz = False self._clear_existing_outlines()
def _clear_existing_outlines(self): """ Find and remove existing outlines drawn by any instance of `ViewportOutline`. """ aladin_overlays_to_remove = [ overlay_name for overlay_name in self.aladin.overlays if overlay_name.startswith('jdaviz @') ] self.aladin.remove_overlay(aladin_overlays_to_remove) glue_viewer = self.jdaviz_viewer._obj.glue_viewer jdaviz_overlays = glue_viewer._get_region_overlay_labels() jdaviz_overlays_to_remove = [ overlay_name for overlay_name in jdaviz_overlays if overlay_name.startswith('mast-aladin @') ] glue_viewer._remove_region_overlay(jdaviz_overlays_to_remove)
[docs] @classmethod def for_current_apps(cls, jdaviz_viewer_name=None): """ Construct a ``ViewportOutline`` for the latest instantiated instances of `mast_aladin.MastAladin` and `~jdaviz.configs.imviz.plugins.viewers.ImvizImageView`. Parameters ---------- jdaviz_viewer_name : str or None Name for one viewer in jdaviz. If None, uses the first available viewer. """ current_jdaviz_app = jdaviz.gca() mast_aladin = gca() if jdaviz_viewer_name is None: # Get first available image viewer image_viewers = current_jdaviz_app.app.get_viewers_of_cls( 'ImvizImageView' ) if image_viewers: glue_viewer = image_viewers[0] jdaviz_viewer = current_jdaviz_app.viewers[ glue_viewer._ref_or_id ] else: raise ValueError( "No image viewers available in jdaviz app. " "Load image data or create a viewer first." ) else: jdaviz_viewer = current_jdaviz_app.viewers[jdaviz_viewer_name] return cls(jdaviz_viewer, mast_aladin)