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 forget_masks(self): """Forget all loaded coordinates.""" self._seqno = 1 self._maskobjs = [] self._treepaths = [] self.tree_dict = Bunch.caselessDict() self.redo()
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 add_image_cb(self, viewer, chname, image, image_info): """Add an image to the mosaic.""" self._recreate_fp = True header = image.get_header() # Do not add mosaic to another mosaic if header.get('OBJECT', 'N/A') == 'MOSAIC': return True imname = image.get('name', 'NoName') impath = image.get('path') msg = 'Adding {0} to mosaic'.format(imname) new_mosaic = self.settings.get('drop_creates_new_mosaic', False) self.fitsimage.onscreen_message(msg, delay=2.0) self.fv.nongui_do(self.fv.error_wrap, self.mosaic, [impath], new_mosaic=new_mosaic) self.fitsimage.auto_levels() # Calculate image footprint, counter-clockwise from bottom-left. # Format is [[X1, Y1], ..., [X4, Y4]] footprint = image.wcs.wcs.calc_footprint() self._imlist[imname] = Bunch.Bunch(footprint=footprint, path=impath) self._create_footprint_obj() # Update table listing treedict = Bunch.caselessDict() treedict[imname] = Bunch.Bunch(IMAGE=imname) self.treeview.add_tree(treedict) self.logger.info('{0} added to mosaic'.format(imname)) return True
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 get_vars(plist, include_dirs): """Build substitution dictionary from the <Parameter_List> section of an OPE file.""" lines = plist.split('\n') substDict = Bunch.caselessDict() while len(lines) > 0: line = lines.pop(0) line = line.strip() # as of Jun 16 2018, disable prm written in an ope file # match = load_regex.match(line) # if match: # prepend_prm(lines, match.group(1), include_dirs) # continue # convert to uc line = toupper(line) if line.startswith('#') or line.startswith('*') or (len(line) == 0): continue if '=' in line: idx = line.find('=') var = line[0:idx].strip() val = line[idx+1:].strip() substDict[var] = val print("SUBSTDICT: {}".format(substDict)) return substDict
def auto_mosaic(self): """Create new mosaic using image list from Contents.""" astroimage_obj = AstroImage() self._imlist = {} self._recreate_fp = True self.treeview.clear() self.treeviewsel.clear() # Get image list from Contents, excluding other mosaics file_dict = self.list_plugin_obj.name_dict[self.chname] for bnch in six.itervalues(file_dict): if ((not isinstance(bnch, Bunch.Bunch)) or ('mosaic' in bnch.NAME.lower())): continue # Calculate image footprint, counter-clockwise from # bottom-left. Format is [[X1, Y1], ..., [X4, Y4]] imname = bnch.NAME impath = bnch.path datasrc = self.chinfo.datasrc if imname in datasrc: image = datasrc[imname] else: image = astroimage_obj image.load_file(impath) footprint = image.wcs.wcs.calc_footprint() # Astropy only? self._imlist[imname] = Bunch.Bunch(footprint=footprint, path=impath) if len(self._imlist) == 0: s = 'No images available for mosaic' self.logger.error(s) self.update_status(s) return True # Always start a new mosaic. # Remove duplicates in case an image have multiple extensions opened. images = list(set([bnch.path for bnch in six.itervalues(self._imlist)])) self.fv.nongui_do(self.fv.error_wrap, self.mosaic, images, new_mosaic=True) self.fitsimage.auto_levels() # Only allow this to happen once, otherwise footprint highlighting # gets confusing. self.w.create_mosaic.set_enabled(False) self.w.select_all.set_enabled(True) self.w.deselect_all.set_enabled(True) # Populate table listing. treedict = Bunch.caselessDict() for imname in self._imlist: treedict[imname] = Bunch.Bunch(IMAGE=imname) self.treeview.set_tree(treedict) return True
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 __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.create_category('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.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 __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 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 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, 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 __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 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, 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 __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.create_category('plugin_ChangeHistory') self.settings.add_defaults(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.clear_selected_history() self.recreate_toc()
def clear(self): self.name_dict = Bunch.caselessDict() self.recreate_toc()
def clear(self): self.name_dict = Bunch.caselessDict() self._hl_path = set([]) 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_channel(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
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))
# # 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
# # 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 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 # Name of the coordinate system defined by the keywords in # the header. "raw" means no system that ginga understands. # See types returned by get_coord_system_name()