Source code for jdaviz.configs.imviz.plugins.rotate_canvas.rotate_canvas

import os
from traitlets import Bool, Unicode, observe

from glue_jupyter.common.toolbar_vuetify import read_icon

from jdaviz.configs.imviz.wcs_utils import get_compass_info
from jdaviz.core.custom_traitlets import FloatHandleEmpty
from jdaviz.core.events import AddDataMessage, RemoveDataMessage, CanvasRotationChangedMessage
from jdaviz.core.registries import tray_registry
from jdaviz.core.template_mixin import PluginTemplateMixin, ViewerSelectMixin
from jdaviz.core.user_api import PluginUserApi
from jdaviz.core.tools import ICON_DIR

__all__ = ['RotateCanvas']


[docs] @tray_registry('imviz-rotate-canvas', label="Canvas Rotation", viewer_requirements='image') class RotateCanvas(PluginTemplateMixin, ViewerSelectMixin): """ See the :ref:`Canvas Rotation Plugin Documentation <rotate-canvas>` for more details. Only the following attributes and methods are available through the :ref:`public plugin API <plugin-apis>`: * :meth:`~jdaviz.core.template_mixin.PluginTemplateMixin.show` * :meth:`~jdaviz.core.template_mixin.PluginTemplateMixin.open_in_tray` * :meth:`~jdaviz.core.template_mixin.PluginTemplateMixin.close_in_tray` * ``viewer`` (:class:`~jdaviz.core.template_mixin.ViewerSelect`): Viewer to show orientation/compass information. * ``angle``: Angle to rotate the axes canvas, clockwise. * ``flip_horizontal``: Whether to flip the canvas horizontally, after applying rotation. * :meth:`reset` * :meth:`set_north_up_east_left` * :meth:`set_north_up_east_right` """ template_file = __file__, "rotate_canvas.vue" angle = FloatHandleEmpty(0).tag(sync=True) # degrees, clockwise flip_horizontal = Bool(False).tag(sync=True) # horizontal flip applied after rotation has_wcs = Bool(False).tag(sync=True) icon_nuer = Unicode(read_icon(os.path.join(ICON_DIR, 'right-east.svg'), 'svg+xml')).tag(sync=True) # noqa icon_nuel = Unicode(read_icon(os.path.join(ICON_DIR, 'left-east.svg'), 'svg+xml')).tag(sync=True) # noqa 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) @property def user_api(self): return PluginUserApi(self, expose=('viewer', 'angle', 'flip_horizontal', 'reset', 'set_north_up_east_right', 'set_north_up_east_left')) @property def ref_data(self): return self.app.get_viewer_by_id(self.viewer.selected_id).state.reference_data def _on_viewer_data_changed(self, msg=None): if not self.viewer_selected: # pragma: no cover return self.has_wcs = getattr(self.ref_data, 'coords', None) is not None @observe('viewer_selected') def _viewer_selected_changed(self, *args, **kwargs): if not hasattr(self, 'viewer'): return vid = self.viewer.selected_id self.angle = self.app._viewer_item_by_id(vid).get('canvas_angle', 0) self.flip_horizontal = self.app._viewer_item_by_id(vid).get('canvas_flip_horizontal', False) def _get_wcs_angles(self): if not self.has_wcs: raise ValueError("reference data does not have WCS, cannot determine orientation") ref_data = self.ref_data if ref_data is None: # pragma: no cover raise ValueError("no data loaded in viewer, cannot determine orientation") _, _, _, _, _, _, degn, dege, flip = get_compass_info(ref_data.coords, ref_data.shape) return degn, dege, flip
[docs] def reset(self): """ Reset the rotation to an angle of 0 and no flip """ self.angle = 0 self.flip_horizontal = False
[docs] def set_north_up_east_left(self): """ Set the rotation angle and flip to achieve North up and East left according to the reference image WCS. """ degn, dege, flip = self._get_wcs_angles() self.angle = -degn self.flip_horizontal = flip
[docs] def set_north_up_east_right(self): """ Set the rotation angle and flip to achieve North up and East right according to the reference image WCS. """ degn, dege, flip = self._get_wcs_angles() self.angle = -degn self.flip_horizontal = not flip
[docs] def vue_reset(self, *args, **kwargs): self.reset() # pragma: no cover
[docs] def vue_set_north_up_east_left(self, *args, **kwargs): self.set_north_up_east_left() # pragma: no cover
[docs] def vue_set_north_up_east_right(self, *args, **kwargs): self.set_north_up_east_right() # pragma: no cover
@observe('angle') def _angle_changed(self, *args, **kwargs): try: angle = float(self.angle) except ValueError: # pragma: no cover # empty string, etc angle = 0 # Rotate selected viewer canvas. This changes zoom too. self.app._viewer_item_by_id(self.viewer.selected_id)['canvas_angle'] = angle # broadcast message (used by compass, etc) self.hub.broadcast(CanvasRotationChangedMessage(self.viewer.selected_id, angle, self.flip_horizontal, sender=self)) @observe('flip_horizontal') def _flip_changed(self, *args, **kwargs): self.app._viewer_item_by_id(self.viewer.selected_id)['canvas_flip_horizontal'] = self.flip_horizontal # noqa self.hub.broadcast(CanvasRotationChangedMessage(self.viewer.selected_id, self.angle, self.flip_horizontal, sender=self))