def irafglob(inlist, atfile=None): """ Returns a list of filenames based on the type of IRAF input. Handles lists, wild-card characters, and at-files. For special at-files, use the atfile keyword to process them. This function is recursive, so IRAF lists can also contain at-files and wild-card characters, e.g. `a.fits`, `@file.lst`, `*flt.fits`. """ # Sanity check if inlist == None or len(inlist) == 0: return [] # Determine which form of input was provided: if isinstance(inlist, list): # python list flist = [] for f in inlist: flist += irafglob(f) elif ',' in inlist: # comma-separated string list flist = [] for f in inlist.split(','): f = f.strip() flist += irafglob(f) elif inlist[0] == '@': # file list flist = [] for f in open(inlist[1:], 'r').readlines(): f = f.rstrip() # hook for application specific atfiles. if atfile: f = atfile(f) flist += irafglob(f) else: # shell globbing if osfn: inlist = osfn(inlist) flist = glob.glob(inlist) return flist
def readASNTable(fname, output=None, prodonly=False): """ Given a fits filename repesenting an association table reads in the table as a dictionary which can be used by pydrizzle and multidrizzle. :Algorithm: An association table is a FITS binary table with 2 required columns: 'MEMNAME', 'MEMTYPE'. It checks 'MEMPRSNT' column and removes all files for which its value is 'no'. Examples ======== An association table can be read from a file using the following commands:: >>> from stsci.tools import asnutil >>> asntab = asnutil.readASNTable('j8bt06010_shifts_asn.fits', prodonly=False) The `asntab` object can now be passed to other code to provide relationships between input and output images defined by the association table. Parameters ========== `fname`: string name of association table `output`: string name of output product - if not specified by the user, the first PROD-DTH name is used if present, if not, the first PROD-RPT name is used if present, if not, the rootname of the input association table is used. `prodonly`: bool what files should be considered as input if True - select only MEMTYPE=PROD* as input if False - select only MEMTYPE=EXP as input Returns ======= `asndict`: dict-object A dictionary-like object with all the association information """ try: f = fits.open(fu.osfn(fname)) except: raise IOError, "Can't open file %s\n" % fname colnames = f[1].data.names try: colunits = f[1].data.units except AttributeError: pass hdr = f[0].header if 'MEMNAME' not in colnames or 'MEMTYPE' not in colnames: msg = 'Association table incomplete: required column(s) MEMNAME/MEMTYPE NOT found!' raise ValueError, msg d = {} for n in colnames: d[n]=f[1].data.field(n) f.close() valid_input = d['MEMPRSNT'].copy() memtype = d['MEMTYPE'].copy() prod_dth = (memtype.find('PROD-DTH')==0).nonzero()[0] prod_rpt = (memtype.find('PROD-RPT')==0).nonzero()[0] prod_crj = (memtype.find('PROD-CRJ')==0).nonzero()[0] # set output name if output == None: if prod_dth: output = d['MEMNAME'][prod_dth[0]] elif prod_rpt: output = d['MEMNAME'][prod_rpt[0]] elif prod_crj: output = d['MEMNAME'][prod_crj[0]] else: output = fname.split('_')[0] if prodonly: input = d['MEMTYPE'].find('PROD')==0 if prod_dth: input[prod_dth] = False else: input = (d['MEMTYPE'].find('EXP')==0) valid_input *= input for k in d.keys(): d[k] = d[k][valid_input] infiles = list(d['MEMNAME'].lower()) if not infiles: print "No valid input specified" return None if ('XOFFSET' in colnames and d['XOFFSET'].any()) or ('YOFFSET' in colnames and d['YOFFSET'].any()): abshift = True dshift = False try: units=colunits[colnames.index('XOFFSET')] except: units='pixels' xshifts = list(d['XOFFSET']) yshifts = list(d['YOFFSET']) elif ('XDELTA' in colnames and d['XDELTA'].any()) or ('YDELTA' in colnames and d['YDELTA'].any()): abshift = False dshift = True try: units=colunits[colnames.index('XDELTA')] except: units='pixels' xshifts = list(d['XDELTA']) yshifts = list(d['YDELTA']) else: abshift = False dshift = False members = {} if not abshift and not dshift: asndict = ASNTable(infiles,output=output) asndict.create() return asndict else: try: refimage = hdr['refimage'] except KeyError: refimage = None try: frame = hdr['shframe'] except KeyError: frame = 'input' if 'ROTATION' in colnames: rots = list(d['ROTATION']) if 'SCALE' in colnames: scales = list(d['SCALE']) for r in range(len(infiles)): row = r xshift = xshifts[r] yshift = yshifts[r] if rots: rot = rots[r] if scales: scale = scales[r] members[infiles[r]] = ASNMember(row=row, dshift=dshift, abshift=abshift, rot=rot, xshift=xshift, yshift=yshift, scale=scale, refimage=refimage, shift_frame=frame, shift_units=units) asndict= ASNTable(infiles, output=output) asndict.create() asndict['members'].update(members) return asndict
def __init__(self, rootname,header=None,shape=None,pa_key='PA_V3',new=no,prefix=None): # Initialize wcs dictionaries: # wcsdef - default values for new images # wcstrans - translation table from header keyword to attribute # wcskeys - keywords in the order they should appear in the header self.wcsdef = {'crpix1':0.0,'crpix2':0.0,'crval1':0.0,'crval2':0.0,'cd11':1.0, 'cd12':1.0,'cd21':1.0,'cd22':1.0,'orient':1.0,'naxis1':0,'naxis2':0,'pscale':1.0, 'postarg1':0.0,'postarg2':0.0,'pa_obs':0.0, 'ctype1':'RA---TAN','ctype2':'DEC--TAN'} self.wcstrans = {'CRPIX1':'crpix1','CRPIX2':'crpix2','CRVAL1':'crval1','CRVAL2':'crval2', 'CD1_1':'cd11','CD1_2':'cd12','CD2_1':'cd21','CD2_2':'cd22', 'ORIENTAT':'orient', 'NAXIS1':'naxis1','NAXIS2':'naxis2', 'pixel scale':'pscale','CTYPE1':'ctype1','CTYPE2':'ctype2'} self.wcskeys = ['NAXIS1','NAXIS2','CRPIX1','CRPIX2', 'CRVAL1','CRVAL2','CTYPE1','CTYPE2', 'CD1_1','CD1_2','CD2_1','CD2_2', 'ORIENTAT'] # Now, read in the CRPIX1/2, CRVAL1/2, CD1/2_1/2 keywords. # Simplistic, but easy to understand what you are asking for. _exists = yes if rootname != None: self.rootname = rootname else: self.rootname = 'New' new = yes _exists = no # Initialize attribute for GEIS image name, just in case... self.geisname = None # Look for extension specification in rootname _indx = _section = string.find(self.rootname,'[') # If none are found, use entire rootname if _indx < 0: _indx = len(self.rootname) # Determine whether we are working with a new image or not. _dir,_rootname = os.path.split(fileutil.osfn(self.rootname[:_indx])) if _dir: _filename = _dir+os.sep+_rootname else: _filename = _rootname self.filename = _filename if not new: _exists = fileutil.checkFileExists(_rootname,directory=_dir) else: _exists = no # If no header has been provided, get the PRIMARY and the # specified extension header... This call uses the fully # expanded version of the filename, plus any sections listed by # by the user in the original rootname. if not header and _exists: _hdr_file = _filename+self.rootname[_indx:] _header = fileutil.getHeader(_hdr_file) else: # Otherwise, simply use the header already read into memory # for this exposure/chip. _header = header if _exists or header: # Initialize WCS object with keyword values... try: _dkey = 'orientat' if 'orientat' in _header: self.orient = _header['orientat'] else: self.orient = None if _header['naxis'] == 0 and 'pixvalue' in _header: # Check for existence of NPIX/PIXVALUE keywords # which represent a constant array extension _dkey = 'npix1' self.naxis1 = _header['npix1'] _dkey = 'npix2' self.naxis2 = _header['npix2'] _dkey = 'pixvalue' self.pixvalue = _header['pixvalue'] else: _dkey = 'naxis1' self.naxis1 = _header['naxis1'] _dkey = 'naxis2' self.naxis2 = _header['naxis2'] self.pixvalue = None self.npix1 = self.naxis1 self.npix2 = self.naxis2 for key in self.wcstrans.keys(): _dkey = self.wcstrans[key] if _dkey not in ['pscale','orient','naxis1','naxis2']: self.__dict__[_dkey] = _header[key] self.new = no except: print 'Could not find WCS keyword: ',_dkey raise IOError,'Image %s does not contain all required WCS keywords!' % self.rootname # Now, try to read in POSTARG keyword values, if they exist... try: self.postarg1 = _header['postarg1'] self.postarg2 = _header['postarg2'] except: # If these keywords, don't exist set defaults... self.postarg1 = 0.0 self.postarg2 = 0.0 try: self.pa_obs = _header[pa_key] except: # If no such keyword exists, use orientat value later self.pa_obs = None else: # or set default values... self.new = yes for key in self.wcsdef.keys(): self.__dict__[key] = self.wcsdef[key] if shape != None: # ... and update with user values. self.naxis1 = int(shape[0]) self.naxis2 = int(shape[1]) self.pscale = float(shape[2]) # Make sure reported 'orient' is consistent with CD matrix # while preserving the original 'ORIENTAT' keyword value self.orientat = self.orient self.orient = RADTODEG(N.arctan2(self.cd12,self.cd22)) # If no keyword provided pa_obs value (PA_V3), then default to # image orientation from CD matrix. if self.pa_obs == None: self.pa_obs = self.orient if shape == None: self.set_pscale() #self.pscale = N.sqrt(N.power(self.cd11,2)+N.power(self.cd21,2)) * 3600. # Use Jacobian determination of pixel scale instead of X or Y separately... #self.pscale = N.sqrt(abs(self.cd11*self.cd22 - self.cd12*self.cd21))*3600. # Establish an attribute for the linearized orient # defined as the orientation of the CD after applying the default # distortion correction. self._orient_lin = 0. # attribute to define format for printing WCS self.__format__=yes # Keep track of the keyword names used as the backup keywords # for the original WCS values # backup - dict relating active keywords with backup keywords # prepend - string prepended to active keywords to create backup keywords # orig_wcs - dict containing orig keywords and values self.backup = {} self.revert = {} self.prepend = None self.orig_wcs = {} # Read in any archived WCS keyword values, if they exist self.read_archive(_header,prepend=prefix)