class GingaWidget(ImageWidgetBase): LABEL = "Ginga Viewer" _toolbar_cls = BasicToolbar tools = ['ginga:rectangle', 'ginga:circle', 'ginga:polygon', 'ginga:pan', 'ginga:freepan', 'ginga:rotate', 'ginga:contrast', 'ginga:cuts', 'ginga:colormap', 'ginga:slicer', 'ginga:spectrum'] def __init__(self, session, parent=None): self.logger = log.get_logger(name='ginga', level=20, null=True, # uncomment for debugging # log_stderr=True ) self.viewer = ImageViewCanvas(self.logger, render='widget') self.canvas = self.viewer # prevent widget from grabbing focus try: self.canvas.set_enter_focus(False) except AttributeError: self.canvas.set_follow_focus(False) # enable interactive features bindings = self.canvas.get_bindings() bindings.enable_all(True) self.canvas.add_callback('none-move', self.motion_readout) self.canvas.add_callback('draw-event', self._apply_roi_cb) self.canvas.add_callback('draw-down', self._clear_roi_cb) self.canvas.enable_draw(False) self.canvas.enable_autozoom('off') self.canvas.set_zoom_algorithm('rate') self.canvas.set_zoomrate(1.4) bm = self.canvas.get_bindmap() bm.add_callback('mode-set', self.mode_set_cb) self.mode_w = None self.mode_actns = {} # Create settings and set defaults settings = self.canvas.get_settings() self.settings = settings settings.getSetting('cuts').add_callback('set', self.cut_levels_cb) settings.set(autozoom='off', autocuts='override', autocenter='override') # make color bar, with color maps shared from ginga canvas rgbmap = self.viewer.get_rgbmap() self.colorbar = ColorBar.ColorBar(self.logger) rgbmap.add_callback('changed', self.rgbmap_cb, self.viewer) self.colorbar.set_rgbmap(rgbmap) # make coordinates/value readout self.readout = Readout.Readout(-1, 20) self.roi_tag = None super(GingaWidget, self).__init__(session, parent) def make_client(self): return GingaClient(self._data, self.viewer, self._layer_artist_container) def make_central_widget(self): topw = QtWidgets.QWidget() layout = QtWidgets.QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) layout.addWidget(self.viewer.get_widget(), stretch=1) cbar_w = self.colorbar.get_widget() if not isinstance(cbar_w, QtWidgets.QWidget): # ginga wrapped widget cbar_w = cbar_w.get_widget() layout.addWidget(cbar_w, stretch=0) readout_w = self.readout.get_widget() if not isinstance(readout_w, QtWidgets.QWidget): # ginga wrapped widget readout_w = readout_w.get_widget() layout.addWidget(readout_w, stretch=0) topw.setLayout(layout) return topw def match_colorbar(self, canvas, colorbar): rgbmap = self.viewer.get_rgbmap() loval, hival = self.viewer.get_cut_levels() colorbar.set_range(loval, hival) colorbar.set_rgbmap(rgbmap) def rgbmap_cb(self, rgbmap, canvas): self.match_colorbar(canvas, self.colorbar) def cut_levels_cb(self, setting, tup): (loval, hival) = tup self.colorbar.set_range(loval, hival) def _set_roi_mode(self, name, tf): self.canvas.enable_draw(True) # XXX need better way of setting draw contexts self.canvas.draw_context = self self.canvas.set_drawtype(name, color='cyan', linestyle='dash') bm = self.viewer.get_bindmap() bm.set_mode('draw', mode_type='locked') def _clear_roi_cb(self, canvas, *args): try: self.canvas.deleteObjectByTag(self.roi_tag) except: pass def _apply_roi_cb(self, canvas, tag): if self.canvas.draw_context is not self: return self.roi_tag = tag obj = self.canvas.getObjectByTag(self.roi_tag) roi = ginga_graphic_to_roi(obj) # delete outline self.canvas.deleteObject(obj, redraw=False) self.apply_roi(roi) def _tweak_geometry(self): super(GingaWidget, self)._tweak_geometry() # rgb mode not supported yet, so hide option self.ui.monochrome.hide() self.ui.rgb.hide() def motion_readout(self, canvas, button, data_x, data_y): """This method is called when the user moves the mouse around the Ginga canvas. """ d = self.client.point_details(data_x, data_y) # Get the value under the data coordinates try: # value = fitsimage.get_data(data_x, data_y) # We report the value across the pixel, even though the coords # change halfway across the pixel value = self.viewer.get_data(int(data_x + 0.5), int(data_y + 0.5)) except Exception: value = None x_lbl, y_lbl = d['labels'][0], d['labels'][1] # x_txt, y_txt = d['world'][0], d['world'][1] text = "%s %s X=%.2f Y=%.2f Value=%s" % ( x_lbl, y_lbl, data_x, data_y, value) self.readout.set_text(text) def mode_cb(self, modname, tf): """This method is called when a toggle button in the toolbar is pressed selecting one of the modes. """ bm = self.viewer.get_bindmap() if not tf: bm.reset_mode(self.viewer) return bm.set_mode(modname, mode_type='locked') return True def mode_set_cb(self, bm, modname, mtype): """This method is called when a mode is selected in the viewer widget. NOTE: it may be called when mode_cb() is not called (for example, when a keypress initiates a mode); however, the converse is not true: calling mode_cb() will always result in this method also being called as a result. This logic is to insure that the toggle buttons are left in a sane state that reflects the current mode, however it was initiated. """ if modname in self.mode_actns: if self.mode_w and (self.mode_w != self.mode_actns[modname]): self.mode_w.setChecked(False) self.mode_w = self.mode_actns[modname] self.mode_w.setChecked(True) elif self.mode_w: # keystroke turned on a mode for which we have no GUI button # and a GUI button is selected--unselect it self.mode_w.setChecked(False) self.mode_w = None return True
class GingaWidget(ImageWidgetBase): LABEL = "Ginga Viewer" def __init__(self, session, parent=None): self.logger = log.get_logger( name='ginga', level=20, null=True, # uncomment for debugging # log_stderr=True ) self.viewer = ImageViewCanvas(self.logger, render='widget') self.canvas = self.viewer # prevent widget from grabbing focus try: self.canvas.set_enter_focus(False) except AttributeError: self.canvas.set_follow_focus(False) # enable interactive features bindings = self.canvas.get_bindings() bindings.enable_all(True) self.canvas.add_callback('none-move', self.motion_readout) self.canvas.add_callback('draw-event', self._apply_roi_cb) self.canvas.add_callback('draw-down', self._clear_roi_cb) self.canvas.enable_draw(False) self.canvas.enable_autozoom('off') self.canvas.set_zoom_algorithm('rate') self.canvas.set_zoomrate(1.4) bm = self.canvas.get_bindmap() bm.add_callback('mode-set', self.mode_set_cb) self.mode_w = None self.mode_actns = {} # Create settings and set defaults settings = self.canvas.get_settings() self.settings = settings settings.getSetting('cuts').add_callback('set', self.cut_levels_cb) settings.set(autozoom='off', autocuts='override', autocenter='override') # make color bar, with color maps shared from ginga canvas rgbmap = self.viewer.get_rgbmap() self.colorbar = ColorBar.ColorBar(self.logger) rgbmap.add_callback('changed', self.rgbmap_cb, self.viewer) self.colorbar.set_rgbmap(rgbmap) # make coordinates/value readout self.readout = Readout.Readout(-1, 20) self.roi_tag = None super(GingaWidget, self).__init__(session, parent) @staticmethod def _get_default_tools(): return [] def make_client(self): return GingaClient(self._data, self.viewer, self._layer_artist_container) def make_central_widget(self): topw = QtWidgets.QWidget() layout = QtWidgets.QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) layout.addWidget(self.viewer.get_widget(), stretch=1) cbar_w = self.colorbar.get_widget() if not isinstance(cbar_w, QtWidgets.QWidget): # ginga wrapped widget cbar_w = cbar_w.get_widget() layout.addWidget(cbar_w, stretch=0) readout_w = self.readout.get_widget() if not isinstance(readout_w, QtWidgets.QWidget): # ginga wrapped widget readout_w = readout_w.get_widget() layout.addWidget(readout_w, stretch=0) topw.setLayout(layout) return topw def match_colorbar(self, canvas, colorbar): rgbmap = self.viewer.get_rgbmap() loval, hival = self.viewer.get_cut_levels() colorbar.set_range(loval, hival) colorbar.set_rgbmap(rgbmap) def rgbmap_cb(self, rgbmap, canvas): self.match_colorbar(canvas, self.colorbar) def cut_levels_cb(self, setting, tup): (loval, hival) = tup self.colorbar.set_range(loval, hival) def make_toolbar(self): tb = QtWidgets.QToolBar(parent=self) tb.setIconSize(QtCore.QSize(25, 25)) tb.layout().setSpacing(1) tb.setFocusPolicy(Qt.StrongFocus) agroup = QtWidgets.QActionGroup(tb) agroup.setExclusive(True) for (mode_text, mode_icon, mode_cb) in self._mouse_modes(): # TODO: add icons similar to the Matplotlib toolbar action = tb.addAction(mode_icon, mode_text) action.setCheckable(True) action.toggled.connect(mode_cb) agroup.addAction(action) action = tb.addAction(get_icon('glue_move'), "Pan") self.mode_actns['pan'] = action action.setCheckable(True) action.toggled.connect(lambda tf: self.mode_cb('pan', tf)) agroup.addAction(action) icon = QtGui.QIcon(os.path.join(ginga_icon_dir, 'hand_48.png')) action = tb.addAction(icon, "Free Pan") self.mode_actns['freepan'] = action action.setCheckable(True) action.toggled.connect(lambda tf: self.mode_cb('freepan', tf)) agroup.addAction(action) icon = QtGui.QIcon(os.path.join(ginga_icon_dir, 'rotate_48.png')) action = tb.addAction(icon, "Rotate") self.mode_actns['rotate'] = action action.setCheckable(True) action.toggled.connect(lambda tf: self.mode_cb('rotate', tf)) agroup.addAction(action) action = tb.addAction(get_icon('glue_contrast'), "Contrast") self.mode_actns['contrast'] = action action.setCheckable(True) action.toggled.connect(lambda tf: self.mode_cb('contrast', tf)) agroup.addAction(action) icon = QtGui.QIcon(os.path.join(ginga_icon_dir, 'cuts_48.png')) action = tb.addAction(icon, "Cuts") self.mode_actns['cuts'] = action action.setCheckable(True) action.toggled.connect(lambda tf: self.mode_cb('cuts', tf)) agroup.addAction(action) cmap_w = _colormap_mode(self, self.client.set_cmap) tb.addWidget(cmap_w) return tb def _mouse_modes(self): modes = [] modes.append(("Rectangle", get_icon('glue_square'), lambda tf: self._set_roi_mode('rectangle', tf))) modes.append(("Circle", get_icon('glue_circle'), lambda tf: self._set_roi_mode('circle', tf))) modes.append(("Polygon", get_icon('glue_lasso'), lambda tf: self._set_roi_mode('polygon', tf))) for tool in self._tools: modes += tool._get_modes(self.viewer) add_callback(self.client, 'display_data', tool._display_data_hook) return modes def _set_roi_mode(self, name, tf): self.canvas.enable_draw(True) # XXX need better way of setting draw contexts self.canvas.draw_context = self self.canvas.set_drawtype(name, color='cyan', linestyle='dash') bm = self.viewer.get_bindmap() bm.set_mode('draw', mode_type='locked') def _clear_roi_cb(self, canvas, *args): try: self.canvas.deleteObjectByTag(self.roi_tag) except: pass def _apply_roi_cb(self, canvas, tag): if self.canvas.draw_context is not self: return self.roi_tag = tag obj = self.canvas.getObjectByTag(self.roi_tag) roi = ginga_graphic_to_roi(obj) # delete outline self.canvas.deleteObject(obj, redraw=False) self.apply_roi(roi) def _tweak_geometry(self): super(GingaWidget, self)._tweak_geometry() # rgb mode not supported yet, so hide option self.ui.monochrome.hide() self.ui.rgb.hide() def motion_readout(self, canvas, button, data_x, data_y): """This method is called when the user moves the mouse around the Ginga canvas. """ d = self.client.point_details(data_x, data_y) # Get the value under the data coordinates try: # value = fitsimage.get_data(data_x, data_y) # We report the value across the pixel, even though the coords # change halfway across the pixel value = self.viewer.get_data(int(data_x + 0.5), int(data_y + 0.5)) except Exception: value = None x_lbl, y_lbl = d['labels'][0], d['labels'][1] # x_txt, y_txt = d['world'][0], d['world'][1] text = "%s %s X=%.2f Y=%.2f Value=%s" % (x_lbl, y_lbl, data_x, data_y, value) self.readout.set_text(text) def mode_cb(self, modname, tf): """This method is called when a toggle button in the toolbar is pressed selecting one of the modes. """ bm = self.viewer.get_bindmap() if not tf: bm.reset_mode(self.viewer) return bm.set_mode(modname, mode_type='locked') return True def mode_set_cb(self, bm, modname, mtype): """This method is called when a mode is selected in the viewer widget. NOTE: it may be called when mode_cb() is not called (for example, when a keypress initiates a mode); however, the converse is not true: calling mode_cb() will always result in this method also being called as a result. This logic is to insure that the toggle buttons are left in a sane state that reflects the current mode, however it was initiated. """ if modname in self.mode_actns: if self.mode_w and (self.mode_w != self.mode_actns[modname]): self.mode_w.setChecked(False) self.mode_w = self.mode_actns[modname] self.mode_w.setChecked(True) elif self.mode_w: # keystroke turned on a mode for which we have no GUI button # and a GUI button is selected--unselect it self.mode_w.setChecked(False) self.mode_w = None return True
class GingaWidget(ImageWidgetBase): LABEL = "Ginga Viewer" _toolbar_cls = BasicToolbar tools = ['ginga:rectangle', 'ginga:circle', 'ginga:polygon', 'ginga:lasso', 'ginga:xrange', 'ginga:yrange', 'ginga:pan', 'ginga:freepan', 'ginga:rotate', 'ginga:contrast', 'ginga:cuts', 'ginga:dist', 'ginga:colormap', 'ginga:spectrum', 'ginga:slicer'] def __init__(self, session, parent=None): self.logger = log.get_logger(name='ginga', level=20, # switch commenting for debugging null=True, log_stderr=False, #null=False, log_stderr=True ) # load binding preferences if available cfgfile = os.path.join(ginga_home, "bindings.cfg") bindprefs = SettingGroup(name='bindings', logger=self.logger, preffile=cfgfile) bindprefs.load(onError='silent') bd = ImageViewBindings(self.logger, settings=bindprefs) # make Ginga viewer self.viewer = ImageViewCanvas(self.logger, render='widget', bindings=bd) self.canvas = self.viewer # prevent widget from grabbing focus self.viewer.set_enter_focus(False) self.viewer.set_desired_size(300, 300) # enable interactive features bindings = self.viewer.get_bindings() bindings.enable_all(True) self.canvas.add_callback('none-move', self.motion_readout) self.canvas.register_for_cursor_drawing(self.viewer) self.canvas.add_callback('draw-event', self._apply_roi_cb) self.canvas.add_callback('edit-event', self._update_roi_cb) self.canvas.add_callback('draw-down', self._clear_roi_cb) self.canvas.enable_draw(False) self.canvas.enable_edit(False) self.viewer.enable_autozoom('off') self.viewer.set_zoom_algorithm('rate') self.viewer.set_zoomrate(1.4) self.viewer.set_fg(*colors.lookup_color("#D0F0E0")) bm = self.viewer.get_bindmap() bm.add_callback('mode-set', self.mode_set_cb) self.mode_w = None self.mode_actns = {} # Create settings and set defaults settings = self.viewer.get_settings() self.settings = settings settings.getSetting('cuts').add_callback('set', self.cut_levels_cb) settings.set(autozoom='off', autocuts='override', autocenter='override') # make color bar, with color maps shared from ginga canvas rgbmap = self.viewer.get_rgbmap() self.colorbar = ColorBar.ColorBar(self.logger) rgbmap.add_callback('changed', self.rgbmap_cb, self.viewer) self.colorbar.set_rgbmap(rgbmap) # make coordinates/value readout self.readout = Readout.Readout(-1, 20) self.roi_tag = None self.opn_obj = None super(GingaWidget, self).__init__(session, parent) def make_client(self): return GingaClient(self._data, self.viewer, self._layer_artist_container) def make_central_widget(self): topw = QtWidgets.QWidget() layout = QtWidgets.QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) layout.addWidget(self.viewer.get_widget(), stretch=1) cbar_w = self.colorbar.get_widget() if not isinstance(cbar_w, QtWidgets.QWidget): # ginga wrapped widget cbar_w = cbar_w.get_widget() layout.addWidget(cbar_w, stretch=0) readout_w = self.readout.get_widget() if not isinstance(readout_w, QtWidgets.QWidget): # ginga wrapped widget readout_w = readout_w.get_widget() layout.addWidget(readout_w, stretch=0) topw.setLayout(layout) return topw def match_colorbar(self, canvas, colorbar): rgbmap = self.viewer.get_rgbmap() loval, hival = self.viewer.get_cut_levels() colorbar.set_range(loval, hival) colorbar.set_rgbmap(rgbmap) def rgbmap_cb(self, rgbmap, canvas): self.match_colorbar(canvas, self.colorbar) def cut_levels_cb(self, setting, tup): (loval, hival) = tup self.colorbar.set_range(loval, hival) def _set_roi_mode(self, opn_obj, name, mode, **kwargs): self.opn_obj = opn_obj en_draw = (mode == 'draw') self.canvas.enable_draw(en_draw) self.canvas.set_draw_mode(mode) # XXX need better way of setting draw contexts self.canvas.draw_context = self self.canvas.set_drawtype(name, **kwargs) ## bm = self.viewer.get_bindmap() ## bm.set_mode('draw', mode_type='locked') def _clear_roi_cb(self, canvas, *args): if self.opn_obj is not None: self.opn_obj.opn_init(self, self.roi_tag) else: try: self.canvas.delete_object_by_tag(self.roi_tag) except: pass def _apply_roi_cb(self, canvas, tag): if self.canvas.draw_context is not self: return self.roi_tag = tag obj = self.canvas.get_object_by_tag(tag) if self.opn_obj is None: # delete outline self.canvas.delete_object(obj) self.roi_tag = None return self.opn_obj.opn_exec(self, tag, obj) def _update_roi_cb(self, canvas, obj): if self.canvas.draw_context is not self: return if self.opn_obj is None: return self.opn_obj.opn_update(self, obj) def _tweak_geometry(self): super(GingaWidget, self)._tweak_geometry() # rgb mode not supported yet, so hide option self.ui.monochrome.hide() self.ui.rgb.hide() def motion_readout(self, canvas, button, data_x, data_y): """This method is called when the user moves the mouse around the Ginga canvas. """ d = self.client.point_details(data_x, data_y) # Get the value under the data coordinates try: # value = fitsimage.get_data(data_x, data_y) # We report the value across the pixel, even though the coords # change halfway across the pixel value = self.viewer.get_data(int(data_x + 0.5), int(data_y + 0.5)) except Exception: value = None x_lbl, y_lbl = d['labels'][0], d['labels'][1] # x_txt, y_txt = d['world'][0], d['world'][1] text = "%s %s X=%.2f Y=%.2f Value=%s" % ( x_lbl, y_lbl, data_x, data_y, value) self.readout.set_text(text) def mode_cb(self, modname, tf): """This method is called when a toggle button in the toolbar is pressed selecting one of the modes. """ bm = self.viewer.get_bindmap() if not tf: bm.reset_mode(self.viewer) return bm.set_mode(modname, mode_type='locked') return True def mode_set_cb(self, bm, modname, mtype): """This method is called when a mode is selected in the viewer widget. NOTE: it may be called when mode_cb() is not called (for example, when a keypress initiates a mode); however, the converse is not true: calling mode_cb() will always result in this method also being called as a result. This logic is to insure that the toggle buttons are left in a sane state that reflects the current mode, however it was initiated. """ if modname in self.mode_actns: if self.mode_w and (self.mode_w != self.mode_actns[modname]): self.mode_w.setChecked(False) self.mode_w = self.mode_actns[modname] self.mode_w.setChecked(True) elif self.mode_w: # keystroke turned on a mode for which we have no GUI button # and a GUI button is selected--unselect it self.mode_w.setChecked(False) self.mode_w = None return True