def __init__(self): super(Desktop, self).__init__() # for tabs self.tab = Bunch.caselessDict() self.tabcount = 0 self.notebooks = Bunch.caselessDict() for name in ('page-switch', 'page-select'): self.enable_callback(name)
def __init__(self): super(Desktop, self).__init__() # for tabs self.tab = Bunch.caselessDict() self.tabcount = 0 self.notebooks = Bunch.caselessDict() self.toplevels = [] for name in ('page-switch', 'page-select', 'all-closed'): self.enable_callback(name) self.popmenu = None
def __init__(self, app): super(Desktop, self).__init__() self.app = app # for tabs self.tab = Bunch.caselessDict() self.tabcount = 0 self.workspace = Bunch.caselessDict() self.toplevels = [] self._cur_dialogs = [] for name in ('page-switch', 'all-closed'): self.enable_callback(name)
def __init__(self, fv): # superclass defines some variables for us, like logger super(Contents, self).__init__(fv) columns = [ ('Name', 'NAME'), ('Object', 'OBJECT'), ('Date', 'DATE-OBS'), ('Time UT', 'UT'), ] prefs = self.fv.get_preferences() self.settings = prefs.createCategory('plugin_Contents') self.settings.addDefaults(columns=columns, always_expand=True) self.settings.load(onError='silent') # For table-of-contents pane self.nameDict = Bunch.caselessDict() # TODO: this ought to be customizable by channel self.columns = self.settings.get('columns', columns) self.cell_sort_funcs = [] for hdr, key in self.columns: self.cell_sort_funcs.append(self._mksrtfnN(key)) self.gui_up = False fv.set_callback('add-image', self.add_image) fv.set_callback('remove-image', self.remove_image) fv.set_callback('delete-channel', self.delete_channel)
def __init__(self, fv): # superclass defines some variables for us, like logger super(Contents, self).__init__(fv) columns = [ ('Name', 'NAME'), ('Object', 'OBJECT'), ('Date', 'DATE-OBS'), ('Time UT', 'UT'), ] prefs = self.fv.get_preferences() self.settings = prefs.createCategory('plugin_Contents') self.settings.addDefaults(columns=columns, always_expand=True, highlight_tracks_keyboard_focus=False, color_alternate_rows=True) self.settings.load(onError='silent') # For table-of-contents pane self.name_dict = Bunch.caselessDict() # TODO: this ought to be customizable by channel self.columns = self.settings.get('columns', columns) self.treeview = None # paths of highlighted entries, by channel self._hl_path = {} self.highlight_tracks_keyboard_focus = self.settings.get( 'highlight_tracks_keyboard_focus', False) self.gui_up = False fv.add_callback('add-image', self.add_image) fv.add_callback('remove-image', self.remove_image) fv.add_callback('add-channel', self.add_channel) fv.add_callback('delete-channel', self.delete_channel) if self.highlight_tracks_keyboard_focus: fv.add_callback('active-image', self.focus_cb) self._hl_path['none'] = None
def forget_masks(self): """Forget all loaded coordinates.""" self._seqno = 1 self._maskobjs = [] self._treepaths = [] self.tree_dict = Bunch.caselessDict() self.redo()
def recreate_imlist(self): """Refresh image list for new selection.""" if not self.gui_up: return treedict = Bunch.caselessDict() for imname in self._imlist: treedict[imname] = Bunch.Bunch(IMAGE=imname) self.treeview.set_tree(treedict)
def __init__(self, fv, fitsimage): # superclass defines some variables for us, like logger super(TVMark, self).__init__(fv, fitsimage) self.layertag = 'tvmark-canvas' self.marktag = None self.markhltag = None self._mark_options = ['box', 'circle', 'cross', 'plus', 'point'] self._color_options = self._short_color_list() self._dwidth = 2 # Additional width to highlight selection # User preferences. Some are just default values and can also be # changed by GUI. prefs = self.fv.get_preferences() self.settings = prefs.createCategory('plugin_TVMark') self.settings.load(onError='silent') self.marktype = self.settings.get('marktype', 'circle') self.markcolor = self.settings.get('markcolor', 'green') self.marksize = self.settings.get('marksize', 5) self.markwidth = self.settings.get('markwidth', 1) self.pixelstart = self.settings.get('pixelstart', 1) self.use_radec = self.settings.get('use_radec', True) self.extra_columns = self.settings.get('extra_columns', []) # Display coords info table self.treeview = None self.treeviewsel = None self.treeviewbad = None self.tree_dict = Bunch.caselessDict() self.columns = [('No.', 'MARKID'), ('RA', 'RA'), ('DEC', 'DEC'), ('X', 'X'), ('Y', 'Y')] # Append extra columns to table header self.columns += [(colname, colname) for colname in self.extra_columns] # Store results self.coords_dict = defaultdict(list) self._xarr = [] self._yarr = [] self._treepaths = [] self.dc = self.fv.getDrawClasses() canvas = self.dc.DrawingCanvas() canvas.enable_draw(True) canvas.enable_edit(False) canvas.set_callback('draw-event', self.hl_canvas2table_box) canvas.set_callback('cursor-down', self.hl_canvas2table) canvas.setSurface(self.fitsimage) canvas.set_drawtype('rectangle', color='green', linestyle='dash') self.canvas = canvas fv.add_callback('remove-image', lambda *args: self.redo()) self.gui_up = False
def recreate_pxdq(self, dqparser, dqs, pixval): """Refresh single pixel results table with given data.""" if not self.gui_up: return dqstr = self.settings.get('dqstr', 'long') treedict = Bunch.caselessDict() for row in dqs: flag = row[dqparser._dqcol] val = row[dqstr] treedict[str(flag)] = Bunch.Bunch(FLAG=flag, DESCRIP=val) self.pxdqlist.set_tree(treedict) self.w.dq.set_text(str(pixval))
def __init__(self, logger, fitsview, ds, mm): super(PluginManagerBase, self).__init__() self.logger = logger self.fv = fitsview self.ds = ds self.mm = mm self.lock = threading.RLock() self.plugin = Bunch.caselessDict() self.active = {} self.focus = set([]) self.exclusive = set([]) self.focuscolor = "lightgreen" self.hbox = None
def stop(self): # remove canvas from image p_canvas = self.fitsimage.get_canvas() try: p_canvas.delete_object_by_tag(self.layertag) except Exception: pass # Free some memory, maybe self.tree_dict = Bunch.caselessDict() self._xarr = [] self._yarr = [] self._treepaths = [] self.gui_up = False self.fv.show_status('')
def __init__(self, fv, fitsimage): # superclass defines some variables for us, like logger super(TVMask, self).__init__(fv, fitsimage) self.layertag = 'tvmask-canvas' self.masktag = None self.maskhltag = None self._color_options = self._short_color_list() # User preferences. Some are just default values and can also be # changed by GUI. prefs = self.fv.get_preferences() self.settings = prefs.create_category('plugin_TVMask') self.settings.add_defaults(maskcolor='green', maskalpha=0.5, hlcolor='white', hlalpha=1.0) self.settings.load(onError='silent') self.maskcolor = self.settings.get('maskcolor', 'green') self.maskalpha = self.settings.get('maskalpha', 0.5) self.hlcolor = self.settings.get('hlcolor', 'white') self.hlalpha = self.settings.get('hlalpha', 1.0) # Display coords info table self.treeview = None self.tree_dict = Bunch.caselessDict() self.columns = [('No.', 'ID'), ('Filename', 'MASKFILE')] # Store results self._seqno = 1 self._maskobjs = [] self._treepaths = [] self.dc = self.fv.get_draw_classes() canvas = self.dc.DrawingCanvas() canvas.enable_draw(True) canvas.enable_edit(False) canvas.set_callback('draw-event', self.hl_canvas2table_box) #canvas.set_callback('cursor-down', self.hl_canvas2table) canvas.register_for_cursor_drawing(self.fitsimage) canvas.set_surface(self.fitsimage) canvas.set_drawtype('rectangle', color='green', linestyle='dash') self.canvas = canvas fv.add_callback('remove-image', lambda *args: self.redo()) self.gui_up = False
def __init__(self, logger, fitsview, ds, mm): super(PluginManager, self).__init__() self.logger = logger self.fv = fitsview self.ds = ds self.mm = mm self.lock = threading.RLock() self.plugin = Bunch.caselessDict() self.active = {} self.focus = set([]) self.exclusive = set([]) for name in ('activate-plugin', 'deactivate-plugin', 'focus-plugin', 'unfocus-plugin'): self.enable_callback(name)
def get_keystroke(self): self.logger.info("get_keystroke() called") chinfo = self.fv.get_channelInfo() fitsimage = chinfo.fitsimage # Find out which frame we are looking at #frame = self.current_frame frame = self.channel_to_frame(chinfo.name) image = fitsimage.get_image() self.start_imexamine(fitsimage, chinfo.name) self.keyevent.wait() evt = self.keyqueue.get() self.stop_imexamine(fitsimage, chinfo.name) res = Bunch.Bunch(x=evt.x, y=evt.y, key=evt.key, frame=frame) return res
def get_scaled_cutout(self, x1, y1, x2, y2, scale_x, scale_y, method='basic'): if method == 'basic': return self.get_scaled_cutout_basic(x1, y1, x2, y2, scale_x, scale_y) data = self._get_data() newdata, (scale_x, scale_y) = trcalc.get_scaled_cutout_basic( data, x1, y1, x2, y2, scale_x, scale_y, interpolation=method) res = Bunch.Bunch(data=newdata, scale_x=scale_x, scale_y=scale_y) return res
def register_wcs(name, wrapper_class, coord_types): """Register a custom WCS wrapper. Parameters ---------- name : str The name of the custom WCS wrapper wrapper_class : subclass of `~ginga.util.wcsmod.BaseWCS` The class implementing the WCS wrapper coord_types : list of str List of names of coordinate types supported by the WCS """ global custom_wcs custom_wcs[wcs_name] = Bunch.Bunch(name=name, wrapper_class=wrapper_class, coord_types=coord_types)
def __init__(self, logger, full_name, short_name, survey, description): self.logger = logger self.full_name = full_name self.short_name = short_name self.kind = 'astroquery-image' self.querymod = SkyView self.survey = survey # For compatibility with other Ginga catalog servers self.params = {} count = 0 for label, key in (('RA', 'ra'), ('DEC', 'dec'), ('Width', 'width'), ('Height', 'height')): self.params[key] = Bunch.Bunch(name=key, convert=str, label=label, order=count) count += 1
def select_child_cb(self, layout, event, subwin): ex, ey = event.x_root, event.y_root x, y = self.get_widget_position(subwin.frame) subwin.x, subwin.y = x, y # make this the selected widget idx = self.page_num(subwin.widget) if idx >= 0: self.set_current_page(idx) self.selected_child = Bunch.Bunch(subwin=subwin, action='move', x_origin=x, y_origin=y, dx=ex, dy=ey) return True
def recreate_imdq(self, dqparser): """Refresh image DQ results table with given data.""" if not self.gui_up: return dqstr = self.settings.get('dqstr', 'long') treedict = Bunch.caselessDict() for key in self._curpxmask: if len(self._curpxmask[key][0]) == 0: continue row = dqparser.tab[dqparser.tab[dqparser._dqcol] == key] flag = row[dqparser._dqcol][0] val = row[dqstr][0] treedict[str(flag)] = Bunch.Bunch(FLAG=flag, DESCRIP=val) self.imdqlist.set_tree(treedict)
def __init__(self, logger, full_name, key, url, description): self.logger = logger self.full_name = full_name self.short_name = key self.description = description self.kind = 'pyvo-image' self.url = url # For compatibility with other Ginga catalog servers self.params = {} count = 0 for label, key in (('RA', 'ra'), ('DEC', 'dec'), ('Width', 'width'), ('Height', 'height')): self.params[key] = Bunch.Bunch(name=key, convert=str, label=label, order=count) count += 1
def add_channel(self, viewer, channel): info = Bunch.Bunch(chinfo=channel) channel.extdata._wcsmatch_info = info # Add callbacks to the viewer for all the scale, pan, rotation and # transform settings changes chviewer = channel.fitsimage fitssettings = chviewer.get_settings() fitssettings.get_setting('scale').add_callback('set', self.zoomset_cb, chviewer, info) fitssettings.get_setting('rot_deg').add_callback( 'set', self.rotset_cb, chviewer, info) for name in ('flip_x', 'flip_y', 'swap_xy'): fitssettings.get_setting(name).add_callback( 'set', self.xfmset_cb, chviewer, info) fitssettings.get_setting('pan').add_callback('set', self.panset_cb, chviewer, info) self.fv.gui_do(self._reset_channels_gui)
def get_relative_orientation(image, ref_image): """Computes the relative orientation and scale of an image to a reference image. Parameters ---------- image AstroImage based object ref_image AstroImage based object Returns ------- result Bunch object containing the relative scale in x and y and the relative rotation in degrees. """ # Get reference image rotation and scale header = ref_image.get_header() ((xrot_ref, yrot_ref), (cdelt1_ref, cdelt2_ref)) = get_xy_rotation_and_scale(header) scale_x, scale_y = math.fabs(cdelt1_ref), math.fabs(cdelt2_ref) # Get rotation and scale of image header = image.get_header() ((xrot, yrot), (cdelt1, cdelt2)) = get_xy_rotation_and_scale(header) # Determine relative scale of this image to the reference rscale_x = math.fabs(cdelt1) / scale_x rscale_y = math.fabs(cdelt2) / scale_y # Figure out rotation relative to our orientation rrot_dx, rrot_dy = xrot - xrot_ref, yrot - yrot_ref # Choose Y rotation as default rrot_deg = rrot_dy res = Bunch.Bunch(rscale_x=rscale_x, rscale_y=rscale_y, rrot_deg=rrot_deg) return res
def __init__(self, logger, container): super(CatalogListing, self).__init__() self.logger = logger self.tag = None self.cmap_names = cmap.get_names() self.imap_names = imap.get_names() self.magcmap = 'stairs8' self.magimap = 'ramp' self.mag_field = 'mag' self.mag_max = 25.0 self.mag_min = 0.0 self.color_default = 'skyblue' # keys: are name, ra, dec, mag, flag, b_r, preference, priority, dst # TODO: automate this generation self.columns = [ ('Name', 'name'), ('RA', 'ra'), ('DEC', 'dec'), ('Mag', 'mag'), ('Preference', 'preference'), ('Priority', 'priority'), ('Description', 'description'), ('Index', 'index'), ] self.catalog = None self.cursor = 0 self.color_selected = 'skyblue' self.selection_mode = 'single' self.selected = [] self.moving_cursor = False self.btn = Bunch.Bunch() self.cmap = cmap.get_cmap(self.magcmap) self.imap = imap.get_imap('ramp') self.operation_table = [] self._select_flag = False self._build_gui(container)
def open_file(self, filespec, memmap=None, **kwargs): info = iohelper.get_fileinfo(filespec) if not info.ondisk: raise FITSError("File does not appear to be on disk: %s" % (info.url)) self.fileinfo = info filepath = info.filepath self.logger.debug("Loading file '%s' ..." % (filepath)) fits_f = fitsio.FITS(filepath, memmap=memmap) self.fits_f = fits_f extver_db = {} self.extver_db = extver_db self.hdu_info = [] self.hdu_db = {} for idx in range(len(fits_f)): hdu = fits_f[idx] hduinfo = hdu.get_info() name = hduinfo['extname'] # figure out the EXTVER for this HDU #extver = hduinfo['extver'] extver = extver_db.setdefault(name, 0) extver += 1 extver_db[name] = extver # prepare a record of pertinent info about the HDU for # lookups by numerical index or (NAME, EXTVER) d = Bunch.Bunch(index=idx, name=name, extver=extver) hdutype = self.hdutypes.get(hduinfo['hdutype'], 'UNKNOWN') d.setvals(htype=hdutype, dtype=str(hduinfo.get('img_type', None))) self.hdu_info.append(d) # different ways of accessing this HDU: # by numerical index self.hdu_db[idx] = d # by (hduname, extver) key = (name, extver) if len(name) > 0 and extver >= 0 and key not in self.hdu_db: self.hdu_db[key] = d return self
def add_channel(self, viewer, chinfo): panimage = self._create_pan_image() chname = chinfo.name iw = panimage.get_widget() iw.show() self.nb.append_page(iw, gtk.Label(chname)) index = self.nb.page_num(iw) paninfo = Bunch.Bunch(panimage=panimage, widget=iw, pancompass=None, panrect=None, nbindex=index) self.channel[chname] = paninfo # Extract RGBMap object from main image and attach it to this # pan image fitsimage = chinfo.fitsimage rgbmap = fitsimage.get_rgbmap() panimage.set_rgbmap(rgbmap, redraw=False) rgbmap.add_callback('changed', self.rgbmap_cb, panimage) fitsimage.copy_attributes(panimage, ['cutlevels']) fitsimage.add_callback('image-set', self.new_image_cb, chinfo, paninfo) fitsimage.add_callback('pan-set', self.panset, chinfo, paninfo) fitssettings = fitsimage.get_settings() pansettings = panimage.get_settings() zoomsettings = ['zoom_algorithm', 'zoom_rate', 'scale_x_base', 'scale_y_base'] fitssettings.shareSettings(pansettings, zoomsettings) for key in zoomsettings: pansettings.getSetting(key).add_callback('set', self.zoom_cb, fitsimage, chinfo, paninfo) xfrmsettings = ['flip_x', 'flip_y', 'swap_xy', 'locut', 'hicut'] fitssettings.shareSettings(pansettings, xfrmsettings) for key in xfrmsettings: pansettings.getSetting(key).add_callback('set', self.redraw_cb, fitsimage, chinfo, paninfo, 0.5) fitssettings.shareSettings(pansettings, ['rot_deg']) pansettings.getSetting('rot_deg').add_callback('set', self.redraw_cb, fitsimage, chinfo, paninfo, 0) self.logger.debug("channel %s added." % (chinfo.name))
def __init__(self, fv, fitsimage): # superclass defines some variables for us, like logger super(TVMask, self).__init__(fv, fitsimage) self.layertag = 'tvmask-canvas' self.masktag = None self.maskhltag = None self._color_options = self._short_color_list() # User preferences. Some are just default values and can also be # changed by GUI. prefs = self.fv.get_preferences() self.settings = prefs.create_category('plugin_TVMask') self.settings.load(onError='silent') self.maskcolor = self.settings.get('maskcolor', 'green') self.maskalpha = self.settings.get('maskalpha', 0.5) self.hlcolor = self.settings.get('hlcolor', 'white') self.hlalpha = self.settings.get('hlalpha', 1.0) # Display coords info table self.treeview = None self.tree_dict = Bunch.caselessDict() self.columns = [('No.', 'ID'), ('Filename', 'MASKFILE')] # Store results self._seqno = 1 self._maskobjs = [] self._treepaths = [] self.dc = self.fv.get_draw_classes() canvas = self.dc.DrawingCanvas() canvas.enable_draw(True) canvas.enable_edit(False) canvas.set_callback('draw-event', self.hl_canvas2table_box) canvas.set_callback('cursor-down', self.hl_canvas2table) canvas.set_surface(self.fitsimage) canvas.set_drawtype('rectangle', color='green', linestyle='dash') self.canvas = canvas fv.add_callback('remove-image', lambda *args: self.redo()) self.gui_up = False
def activate(self, pInfo, exclusive=True): name = pInfo.tabname lname = pInfo.name.lower() if lname not in self.active: bnch = Bunch.Bunch(pInfo=pInfo, lblname=None, widget=None, exclusive=exclusive) if pInfo.chinfo is not None: # local plugin tup = name.split(':') bnch.lblname = ' ' + tup[0] + ':\n' + tup[1] + ' ' self.make_callback('activate-plugin', bnch) else: # global plugin bnch.exclusive = False self.active[lname] = bnch if bnch.exclusive: self.exclusive.add(lname)
def info_xy(self, data_x, data_y, settings): # Get the value under the data coordinates try: # We report the value across the pixel, even though the coords # change halfway across the pixel _d_x, _d_y = int(np.floor(data_x + 0.5)), int( np.floor(data_y + 0.5)) value = self.get_data_xy(_d_x, _d_y) except Exception as e: value = None info = Bunch.Bunch(itype='base', data_x=data_x, data_y=data_y, x=data_x, y=data_y, value=value) return info
def get_info(self, path): dirname, filename = os.path.split(path) name, ext = os.path.splitext(filename) ftype = 'file' if os.path.isdir(path): ftype = 'dir' elif os.path.islink(path): ftype = 'link' elif ext.lower() == '.fits': ftype = 'fits' filestat = os.stat(path) bnch = Bunch.Bunch(path=path, name=filename, type=ftype, st_mode=filestat.st_mode, st_size=filestat.st_size, st_mtime=filestat.st_mtime) return bnch
def process_common_params(widget, inparams): params = Bunch.Bunch(name=None, height=-1, width=-1, xpos=-1, ypos=-1) params.update(inparams) if params.name: widgetDict[params.name] = widget if (params.width >= 0) or (params.height >= 0): widget.set_size_request(params.width, params.height) #pass # User wants to place window somewhere if params.xpos >= 0: #widget.show() win = widget.get_window() if win != None: win.move(params.xpos, params.ypos) return params
def get_ruler_distances(image, p1, p2): """Get the distance calculated between two points. A Bunch of results is returned, containing pixel values and distance values if the image contains a valid WCS. """ x1, y1 = p1[:2] x2, y2 = p2[:2] dx, dy = x2 - x1, y2 - y1 res = Bunch.Bunch(x1=x1, y1=y1, x2=x2, y2=y2, theta=np.arctan2(y2 - y1, x2 - x1), dx_pix=dx, dy_pix=dy, dh_pix=np.sqrt(dx**2 + dy**2), ra_org=None, dec_org=None, ra_dst=None, dec_dst=None, ra_heel=None, dec_heel=None, dx_deg=None, dy_deg=None, dh_deg=None) if image is not None and hasattr(image, 'wcs') and image.wcs is not None: # Calculate RA and DEC for the three points try: # origination point ra_org, dec_org = image.pixtoradec(x1, y1) res.ra_org, res.dec_org = ra_org, dec_org # destination point ra_dst, dec_dst = image.pixtoradec(x2, y2) res.ra_dst, res.dec_dst = ra_dst, dec_dst # "heel" point making a right triangle ra_heel, dec_heel = image.pixtoradec(x2, y1) res.ra_heel, res.dec_heel = ra_heel, dec_heel res.dh_deg = deltaStarsRaDecDeg(ra_org, dec_org, ra_dst, dec_dst) res.dx_deg = deltaStarsRaDecDeg(ra_org, dec_org, ra_heel, dec_heel) res.dy_deg = deltaStarsRaDecDeg(ra_heel, dec_heel, ra_dst, dec_dst) except Exception as e: pass return res
def make_thumbs(self): path = self.curpath self.logger.info("Generating thumbnails for '%s'..." % (path)) filelist = glob.glob(path) filelist.sort(key=lambda s: s.lower()) if self.fitsimage is not None: # we were invoked as a local plugin channel = self.channel else: chviewer = self.fv.getfocus_viewer() # find out our channel chname = self.fv.get_channel_name(chviewer) channel = self.fv.get_channel(chname) for path in filelist: name = self.fv.name_image_from_path(path) info = Bunch.Bunch(name=name, path=path) self.fv.nongui_do(channel.add_image_info, info)
def add_image_cb(self, viewer, chname, image, info): # Get any previously stored thumb information in the image info thumb_extra = info.setdefault('thumb_extras', Bunch.Bunch()) # Get metadata for mouse-over tooltip metadata = self._get_tooltip_metadata(info, image) # Update the tooltip, in case of new or changed metadata text = self._mk_tooltip_text(metadata) thumb_extra.tooltip = text if not self.gui_up: return False channel = self.fv.get_channel(chname) if thumb_extra.get('time_update', None) is None: self.fv.gui_do(self.redo_thumbnail_image, channel, image, info)
def window_key_press(self, canvas, keyname): if not self.imexam_active: return self.logger.info("key pressed: %s" % (keyname)) if len(keyname) > 1: if keyname in ('shift_l', 'shift_r'): # ignore these keystrokes return elif keyname in ('control_l', 'control_r'): # control key combination self.ctrldown = True return elif keyname == 'space': self.toggleMode() return keyname = self.keymap.get(keyname, '?') if self.mode != 'iraf': return if self.ctrldown: if keyname == 'd': # User typed ^D keyname = chr(4) # Get cursor position fitsimage = canvas.getSurface() last_x, last_y = fitsimage.get_last_data_xy() # Correct for surrounding framebuffer image = fitsimage.get_image() if isinstance(image, IRAF_AstroImage): last_x, last_y = image.get_corrected_xy(last_x, last_y) # Get frame info #frame = self.current_frame chname = self.fv.get_channelName(fitsimage) chinfo = self.fv.get_channelInfo(chname) frame = self.channel_to_frame(chinfo.name) self.keyqueue.put( Bunch.Bunch(x=last_x, y=last_y, key=keyname, frame=frame)) self.keyevent.set()
def set_table_cb(self, viewer, table): """Display the given table object.""" self.clear() tree_dict = OrderedDict() # Extract data as astropy table a_tab = table.get_data() # Fill masked values, if applicable try: a_tab = a_tab.filled() except Exception: # Just use original table pass # This is to get around table widget not sorting numbers properly i_fmt = '{{0:0{0}d}}'.format(len(str(len(a_tab)))) # Table header with units columns = [('Row', '_DISPLAY_ROW')] for c in itervalues(a_tab.columns): col_str = '{0:^s}\n{1:^s}'.format(c.name, str(c.unit)) columns.append((col_str, c.name)) self.widget.setup_table(columns, 1, '_DISPLAY_ROW') # Table contents for i, row in enumerate(a_tab, 1): bnch = Bunch.Bunch(zip(row.colnames, row.as_void())) i_str = i_fmt.format(i) bnch['_DISPLAY_ROW'] = i_str tree_dict[i_str] = bnch self.widget.set_tree(tree_dict) # Resize column widths n_rows = len(tree_dict) if n_rows < self.settings.get('max_rows_for_col_resize', 5000): self.widget.set_optimal_column_widths() self.logger.debug('Resized columns for {0} row(s)'.format(n_rows)) tablename = table.get('name', 'NoName') self.logger.debug('Displayed {0}'.format(tablename))
def redo_thumbnail_image(self, channel, image, info, save_thumb=None): # image is flagged not to make a thumbnail? nothumb = (image.get('nothumb', False) or not channel.settings.get('genthumb', True)) if nothumb: return self.logger.debug("redoing thumbnail ...") if save_thumb is None: save_thumb = self.settings.get('cache_thumbs', False) # Get any previously stored thumb information in the image info thumb_extra = info.setdefault('thumb_extras', Bunch.Bunch()) # Get metadata for mouse-over tooltip metadata = self._get_tooltip_metadata(info, image) chname = channel.name thumbkey = self.get_thumb_key(chname, info.name, info.path) with self.thmblock: if thumbkey not in self.thumb_dict: # No memory of this thumbnail, so regenerate it self.logger.debug("No memory of %s, adding..." % (str(thumbkey))) self._add_image(self.fv, chname, image) return # Generate new thumbnail self.logger.debug("generating new thumbnail") thmb_image = self._regen_thumb_image(image, channel.fitsimage) thumb_extra.time_update = time.time() # Save a thumbnail for future browsing if save_thumb and info.path is not None: thumbpath = self.get_thumbpath(info.path) if thumbpath is not None: if os.path.exists(thumbpath): os.remove(thumbpath) thmb_image.save_as_file(thumbpath) self.update_thumbnail(thumbkey, thmb_image, metadata) self.fv.update_pending()
def build_info(captions): vbox = gtk.VBox(spacing=2) numrows = len(captions) numcols = reduce(lambda acc, tup: max(acc, len(tup)), captions, 0) table = gtk.Table(rows=numrows, columns=numcols) table.set_row_spacings(2) table.set_col_spacings(4) vbox.pack_start(table, expand=False) wb = Bunch.Bunch() row = 0 for tup in captions: col = 0 while col < numcols: if col < len(tup): tup1 = tup[col:col + 2] w1, w2 = _make_widget(tup1, wb) table.attach(w1, col, col + 1, row, row + 1, xoptions=gtk.FILL, yoptions=gtk.FILL, xpadding=1, ypadding=1) table.attach(w2, col + 1, col + 2, row, row + 1, xoptions=gtk.FILL, yoptions=gtk.FILL, xpadding=1, ypadding=1) col += 2 row += 1 vbox.show_all() return vbox, wb
def add_channel(self, viewer, channel): chname = channel.name info = Bunch.Bunch(chinfo=channel) self.channel[chname] = info # Add callbacks to the viewer for all the scale, pan, rotation and # transform settings changes fitsimage = channel.fitsimage fitssettings = fitsimage.get_settings() fitsimage.add_callback('image-set', self.new_image_cb, info) fitssettings.getSetting('scale').add_callback('set', self.zoomset_cb, fitsimage, info) fitssettings.getSetting('rot_deg').add_callback( 'set', self.rotset_cb, fitsimage, info) for name in ('flip_x', 'flip_y', 'swap_xy'): fitssettings.getSetting(name).add_callback('set', self.xfmset_cb, fitsimage, info) fitssettings.getSetting('pan').add_callback('set', self.panset_cb, fitsimage, info) self.fv.gui_do(self._reset_channels_gui)
def add_schedule(self, schedule): target_list = [] i, j = 0, 0 for slot in schedule.slots: ob = slot.ob if ob != None: if not ob.derived: # not an OB generated to serve another OB i += 1 #txt = "%d [%s]" % (i, ob.target.name) txt = "%d [%s]" % (i, ob.name) #txt = "%d" % (i) color = self.colors[j] j = (j + 1) % len(self.colors) target_list.append( (ob.target, slot.start_time, txt, color)) self.schedules[schedule] = Bunch.Bunch(targets=target_list) return True
def get_scaled_cutout_wdht(self, x1, y1, x2, y2, new_wd, new_ht, method='bicubic'): newdata, (scale_x, scale_y) = trcalc.get_scaled_cutout_wdht( self._get_data(), x1, y1, x2, y2, new_wd, new_ht, interpolation=method) res = Bunch.Bunch(data=newdata, scale_x=scale_x, scale_y=scale_y) return res
def add_channel(self, viewer, channel): if not self.gui_up: return fitsimage = channel.fitsimage panimage = self._create_pan_viewer(fitsimage) iw = Viewers.GingaViewerWidget(panimage) iw.resize(self._wd, self._ht) self.nb.add_widget(iw) #index = self.nb.index_of(iw) paninfo = Bunch.Bunch(panimage=panimage, widget=iw, compass_wcs=None, compass_xy=None, panrect=None) channel.extdata._pan_info = paninfo fitsimage.copy_attributes(panimage, self.copy_attrs) fitsimage.add_callback('redraw', self.redraw_cb, channel) self.logger.debug("channel '%s' added." % (channel.name))
def __init__(self, logger, full_name, key, url, description): if not have_pyvo: raise ImportError('pyvo not found, please install pyvo') self.logger = logger self.full_name = full_name self.short_name = key self.description = description self.kind = 'pyvo-catalog' self.url = url # For compatibility with URL catalog servers self.params = {} count = 0 for label, key in (('RA', 'ra'), ('DEC', 'dec'), ('Radius', 'r')): self.params[key] = Bunch.Bunch(name=key, convert=str, label=label, order=count) count += 1
def __init__(self, fv): # superclass defines some variables for us, like logger super(Toolbar, self).__init__(fv) # active view self.active = None # holds our gui widgets self.w = Bunch.Bunch() self.gui_up = False # get local plugin preferences prefs = self.fv.get_preferences() self.settings = prefs.createCategory('plugin_Toolbar') self.settings.load(onError='silent') self.modetype = self.settings.get('mode_type', 'oneshot') fv.set_callback('add-channel', self.add_channel_cb) fv.set_callback('delete-channel', self.delete_channel_cb) fv.set_callback('channel-change', self.focus_cb)
def __init__(self, fv): # superclass defines some variables for us, like logger super(Contents, self).__init__(fv) columns = [('Name', 'NAME'), ('Object', 'OBJECT'), ('Date', 'DATE-OBS'), ('Time UT', 'UT'), ('Modified', 'MODIFIED')] spec = self.fv.get_plugin_spec(str(self)) prefs = self.fv.get_preferences() self.settings = prefs.create_category('plugin_Contents') self.settings.add_defaults(columns=columns, always_expand=True, highlight_tracks_keyboard_focus=True, color_alternate_rows=True, row_font_color='green', closeable=not spec.get('hidden', False), max_rows_for_col_resize=100) self.settings.load(onError='silent') # For table-of-contents pane self.name_dict = Bunch.caselessDict() # TODO: this ought to be customizable by channel self.columns = self.settings.get('columns', columns) self.treeview = None # paths of highlighted entries, by channel self.highlight_tracks_keyboard_focus = self.settings.get( 'highlight_tracks_keyboard_focus', True) self._hl_path = set([]) self.chnames = [] fv.add_callback('add-image', self.add_image_cb) fv.add_callback('remove-image', self.remove_image_cb) fv.add_callback('add-image-info', self.add_image_info_cb) fv.add_callback('remove-image-info', self.remove_image_info_cb) fv.add_callback('add-channel', self.add_channel_cb) fv.add_callback('delete-channel', self.delete_channel_cb) fv.add_callback('channel-change', self.focus_cb) self.gui_up = False
def __init__(self, fv): # superclass defines some variables for us, like logger super(ChangeHistory, self).__init__(fv) self.columns = [('Timestamp (UTC)', 'MODIFIED'), ('Description', 'DESCRIP'), ] # For table-of-contents pane self.name_dict = Bunch.caselessDict() self.treeview = None prefs = self.fv.get_preferences() self.settings = prefs.createCategory('plugin_ChangeHistory') self.settings.addDefaults(always_expand=True, color_alternate_rows=True, ts_colwidth=250) self.settings.load(onError='silent') fv.add_callback('remove-image', self.remove_image_cb) fv.add_callback('delete-channel', self.delete_channel_cb) self.gui_up = False
def clear(self): self.name_dict = Bunch.caselessDict() self._hl_path = set([]) self.recreate_toc()
# # common.py -- common global functions for WCS calculations. # # This is open-source software licensed under a BSD license. # Please see the file LICENSE.txt for details. # import re import numpy as np from ginga.misc import Bunch # Holds custom WCSes that are registered custom_wcs = Bunch.caselessDict() class WCSError(Exception): pass class BaseWCS(object): """Base class for WCS.""" def __init__(self, logger): self.logger = logger # The header (or WCS parts thereof) that is in a format readable # by the WCS package used by the wrapper. self.header = None # Internal object holding the wrapped WCS object. This should # be None if no valid WCS could be created by the WCS package. self.wcs = None
def clear(self): self.name_dict = Bunch.caselessDict() self.recreate_toc()
def clear(self): self.name_dict = Bunch.caselessDict() self.clear_selected_history() self.recreate_toc()
def redo(self, *args): """Generate listing of images that user can save.""" if not self.gui_up: return mod_only = self.w.modified_only.get_state() treedict = Bunch.caselessDict() self.treeview.clear() self.w.status.set_text('') channel = self.fv.get_channelInfo(self.chname) if channel is None: return # Only list modified images for saving. Scanning Datasrc is enough. if mod_only: all_keys = channel.datasrc.keys(sort='alpha') # List all images in the channel. else: all_keys = channel.get_image_names() # Extract info for listing and saving for key in all_keys: iminfo = channel.get_image_info(key) path = iminfo.get('path') idx = iminfo.get('idx') t = iminfo.get('time_modified') if path is None: # Special handling for generated buffer, eg mosaic infile = key is_fits = True else: infile = os.path.basename(path) infile_ext = os.path.splitext(path)[1] infile_ext = infile_ext.lower() is_fits = False if 'fit' in infile_ext: is_fits = True # Only list FITS files unless it is Ginga generated buffer if not is_fits: continue # Only list modified buffers if mod_only and t is None: continue # More than one ext modified, append to existing entry if infile in treedict: if t is not None: treedict[infile].extlist.add(idx) elist = sorted(treedict[infile].extlist) treedict[infile].MODEXT = ';'.join( map(self._format_extname, elist)) # Add new entry else: if t is None: s = '' extlist = set() else: s = self._format_extname(idx) extlist = set([idx]) treedict[infile] = Bunch.Bunch( IMAGE=infile, MODEXT=s, extlist=extlist, path=path) self.treeview.set_tree(treedict) # Resize column widths n_rows = len(treedict) if n_rows == 0: self.w.status.set_text('Nothing available for saving') elif n_rows < self.settings.get('max_rows_for_col_resize', 5000): self.treeview.set_optimal_column_widths() self.logger.debug('Resized columns for {0} row(s)'.format(n_rows))
def redo(self): """Image or coordinates have changed. Clear and redraw.""" if not self.gui_up: return self.clear_marking() self.tree_dict = Bunch.caselessDict() self.treeviewbad.clear() bad_tree_dict = Bunch.caselessDict() nbad = 0 self._xarr = [] self._yarr = [] self._treepaths = [] image = self.fitsimage.get_image() if image is None: return if not hasattr(image, 'radectopix'): self.logger.error( 'Image as no radectopix() method for coordinates conversion') return objlist = [] seqno = 1 max_x = image.width - 1 max_y = image.height - 1 for key, coords in self.coords_dict.items(): if len(coords) == 0: continue marktype, marksize, markcolor = key kstr = ','.join(map(str, key)) sub_dict = {} bad_sub_dict = {} self.tree_dict[kstr] = sub_dict bad_tree_dict[kstr] = bad_sub_dict for args in coords: ra, dec, x, y = args[:4] # Use X and Y positions directly. Convert to RA and DEC (deg). if ra is None or dec is None: ra, dec = image.pixtoradec(x, y) # RA and DEC already in degrees. Convert to pixel X and Y. else: x, y = image.radectopix(ra, dec) # Display original X/Y (can be 0- or 1-indexed) using # our internal 0-indexed values. xdisp = x + self.pixelstart ydisp = y + self.pixelstart seqstr = '{0:04d}'.format(seqno) # Prepend 0s for proper sort bnch = Bunch.Bunch(zip(self.extra_columns, args[4:])) # Extra bnch.update(Bunch.Bunch(MARKID=seqstr, RA=ra, DEC=dec, X=xdisp, Y=ydisp)) # Do not draw out of bounds if (not np.isfinite(x) or x < 0 or x > max_x or not np.isfinite(y) or y < 0 or y > max_y): self.logger.debug('Ignoring RA={0}, DEC={1} ' '(x={2}, y={3})'.format(ra, dec, x, y)) bad_sub_dict[seqstr] = bnch nbad += 1 # Display point else: obj = self._get_markobj( x, y, marktype, marksize, markcolor, self.markwidth) objlist.append(obj) sub_dict[seqstr] = bnch self._xarr.append(x) self._yarr.append(y) self._treepaths.append((kstr, seqstr)) seqno += 1 n_obj = len(objlist) self.logger.debug('Displaying {0} markings'.format(n_obj)) if nbad > 0: self.treeviewbad.set_tree(bad_tree_dict) if n_obj == 0: return # Convert to Numpy arrays to avoid looping later self._xarr = np.array(self._xarr) self._yarr = np.array(self._yarr) self._treepaths = np.array(self._treepaths) # Display info table self.recreate_toc() # Draw on canvas self.marktag = self.canvas.add(self.dc.CompoundObject(*objlist)) self.fitsimage.redraw() # Force immediate redraw