def checkNGOODPIX(filelist): """ Only for ACS, WFC3 and STIS, check NGOODPIX If all pixels are 'bad' on all chips, exclude this image from further processing. Similar checks requiring comparing 'driz_sep_bits' against WFPC2 c1f.fits arrays and NICMOS DQ arrays will need to be done separately (and later). """ removed_files = [] supported_instruments = ['ACS', 'STIS', 'WFC3'] for inputfile in filelist: if fileutil.getKeyword(inputfile, 'instrume') in supported_instruments: file = fits.open(inputfile) ngood = 0 for extn in file: if 'EXTNAME' in extn.header and extn.header['EXTNAME'] == 'SCI': ngood += extn.header['NGOODPIX'] file.close() if (ngood == 0): removed_files.append(inputfile) if removed_files != []: print( "Warning: Files without valid pixels detected: keyword NGOODPIX = 0.0" ) print("Warning: Removing the following files from input list") for f in removed_files: print('\t', f) return removed_files
def checkNGOODPIX(filelist): """ Only for ACS, WFC3 and STIS, check NGOODPIX If all pixels are 'bad' on all chips, exclude this image from further processing. Similar checks requiring comparing 'driz_sep_bits' against WFPC2 c1f.fits arrays and NICMOS DQ arrays will need to be done separately (and later). """ removed_files = [] supported_instruments = ['ACS','STIS','WFC3'] for inputfile in filelist: if fileutil.getKeyword(inputfile,'instrume') in supported_instruments: file = fits.open(inputfile) ngood = 0 for extn in file: if 'EXTNAME' in extn.header and extn.header['EXTNAME'] == 'SCI': ngood += extn.header['NGOODPIX'] file.close() if (ngood == 0): removed_files.append(inputfile) if removed_files != []: print("Warning: Files without valid pixels detected: keyword NGOODPIX = 0.0") print("Warning: Removing the following files from input list") for f in removed_files: print('\t',f) return removed_files
def getLTVOffsets(rootname,header=None): _ltv1 = None _ltv2 = None if header: if 'LTV1' in header: _ltv1 = header['LTV1'] if 'LTV2' in header: _ltv2 = header['LTV2'] else: _ltv1 = fileutil.getKeyword(rootname,'LTV1') _ltv2 = fileutil.getKeyword(rootname,'LTV2') if _ltv1 == None: _ltv1 = 0. if _ltv2 == None: _ltv2 = 0. return _ltv1,_ltv2
def findNumExt(filename): # Open the file given by 'rootname' and return the # number of extensions written out for the observation. # It will be up to the Exposure classes to determine how # many IMSETS they have to work with. # # Only look in the primary extension or first group. #_s = iraf.hselect(filename,'NEXTEND',expr='yes',Stdout=1) _s = fileutil.getKeyword(filename,keyword='NEXTEND') if not _s: _s = fileutil.getKeyword(filename,keyword='GCOUNT') # This may need to be changed to support simple image without # extensions (such as simple FITS images). if _s == '': raise ValueError("There are NO extensions to be read in this image!") return _s
def addMembers(self,filename): # The PC chip defines the orientation of the metachip, so use # it for the PARITY as well. self.detector = 'WFPC' _chip1_rot = None # Build rootname here for each SCI extension... if self.pars['section'] == None: self.pars['section'] = [None] * self.nmembers group_indx = list(range(1,self.nmembers+1)) else: group_indx = self.pars['section'] for i in range(self.nmembers): _extname = self.imtype.makeSciName(i+1,section=self.pars['section'][i]) _detnum = fileutil.getKeyword(_extname,self.DETECTOR_NAME) # Start by looking for the corresponding WFPC2 'c1h' files _dqfile, _dqextn = self._findDQFile() # Reset dqfile name in ImType class to point to new file self.imtype.dqfile = _dqfile self.imtype.dq_extn = _dqextn # Build mask file for this member chip _dqname = self.imtype.makeDQName(extver=group_indx[i]) _masklist = [] _masknames = [] if _dqname != None: _maskname = buildmask.buildMaskName(fileutil.buildNewRootname(_dqname),_detnum) else: _maskname = None _masknames.append(_maskname) outmask = buildmask.buildShadowMaskImage(_dqname,_detnum,group_indx[i],_maskname, bitvalue=self.bitvalue[0], binned=self.binned) _masklist.append(outmask) _maskname = _maskname.replace('final_mask','single_mask') _masknames.append(_maskname) outmask = buildmask.buildShadowMaskImage(_dqname,_detnum,group_indx[i],_maskname, bitvalue=self.bitvalue[1], binned=self.binned) _masklist.append(outmask) _masklist.append(_masknames) self.members.append(Exposure(_extname, idckey=self.idckey, dqname=_dqname, mask=_masklist, parity=self.PARITY[str(i+1)], idcdir=self.pars['idcdir'], group_indx = i+1, rot=_chip1_rot, handle=self.image_handle, extver=_detnum, exptime=self.exptime[0], ref_pscale=self.REFDATA['1']['psize'], binned=self.binned)) if self.idckey != 'idctab': _chip1_rot = self.members[0].geometry.def_rot
def _getExposure(img, output, frame, idckey): # setup Exposure object with distortion model and WCS info if frame == 'input': if img.find('[') < 0: img += '[sci]' _val = fileutil.getKeyword(img, 'CD1_1') if _val == None: img[:-7] += '[0]' if fileutil.getKeyword(img, 'CD1_1') == None: print("Input %s not valid!" % img) raise Exception _exp = pydrizzle.Exposure(img, idckey) _wcs = _exp.geometry.wcslin else: # Use output frame for converting pixel shifts # to units of arcseconds... # Make sure we have a recognized file: if not fileutil.findFile(output): if fileutil.findFile(output + '.fits'): output += '.fits' else: print("Can NOT find output file %s!" % output) raise Exception if output.find('[') < 0: output += '[0]' _val = fileutil.getKeyword(output, 'CD1_1') if _val == None: output[:-3] += '[sci,1]' if fileutil.getKeyword(output, 'CD1_1') == None: print("Output %s not valid!" % output) raise Exception _exp = pydrizzle.Exposure(output, idckey) _wcs = _exp.geometry.wcs return _wcs
def check_exptime(filelist): """ Removes files with EXPTIME==0 from filelist. """ removed_files = [] for f in filelist: if fileutil.getKeyword(f, 'EXPTIME') <= 0: removed_files.append(f) return removed_files
def __init__(self, filename, output, pars=None): # Now initialize Pattern with all member exposures... Pattern.__init__(self, filename, output=output, pars=pars) self.instrument = 'WFPC2' self.REFDATA ={'1':{'psize':0.04554,'xoff':354.356,'yoff':343.646,'v2':2.374,'v3':-30.268,'theta':224.8480}, '2':{'psize':0.0996,'xoff':345.7481,'yoff':375.28818,'v2':-51.368,'v3':-5.698,'theta':314.3520}, '3':{'psize':0.0996,'xoff':366.56876,'yoff':354.79435,'v2':0.064,'v3':48.692,'theta':44.67}, '4':{'psize':0.0996,'xoff':355.85016,'yoff':351.29183,'v2':55.044,'v3':-6.098,'theta':135.2210}} self.REFPIX = {'x':400.,'y':400.} gcount = None # build output rootnames here... self.setNames(filename,output) # Set EXPTIME for exposure self.exptime = self.getExptime() _mode = fileutil.getKeyword(filename, 'MODE') if _mode == 'AREA': self.binned = 2 if self.idckey == 'cubic': for l in self.REFPIX.keys(): self.REFPIX[l]= self.REFPIX[l] / self.binned for l in self.REFDATA.keys(): self.REFDATA[l]['psize'] = self.REFDATA[l]['psize'] * self.binned self.REFDATA[l]['xoff'] = self.REFDATA[l]['xoff'] / self.binned self.REFDATA[l]['yoff'] = self.REFDATA[l]['yoff'] / self.binned # Now, build list of members and initialize them self.addMembers(filename) self.setBunit('COUNTS') chips = [int(member.chip) for member in self.members] try: chip_ind = chips.index(self.__refchip) except ValueError: chip_ind = 0 self.refchip = chips[chip_ind] if self.members[0].geometry.ikey != 'idctab': # Correct distortion coefficients to match output pixel scale self.computeCubicCoeffs() else: #self.computeOffsets(refchip=self.__refchip) self.computeOffsets(refchip=self.refchip) # Determine desired orientation of product self.setOrient() # Set up the input members and create the product meta-chip self.buildProduct(filename, output)
def checkNGOODPIX(filelist): """ Only for ACS, and STIS, check NGOODPIX If all pixels are 'bad' on all chips, exclude this image from further processing. Similar checks requiring comparing 'driz_sep_bits' against WFPC2 c1f.fits arrays and NICMOS DQ arrays will need to be done separately (and later). """ removed_files = [] for inputfile in filelist: if (fileutil.getKeyword(inputfile,'instrume') == 'ACS') \ or fileutil.getKeyword(inputfile,'instrume') == 'STIS': _file = fileutil.openImage(inputfile) _ngood = 0 for extn in _file: if 'EXTNAME' in extn.header and extn.header['EXTNAME'] == 'SCI': _ngood += extn.header['NGOODPIX'] _file.close() if (_ngood == 0): removed_files.append(inputfile) return removed_files
def run(configObj, wcsmap=None): """ Run the blot task based on parameters provided interactively by the user. """ # Insure all output filenames specified have .fits extensions if configObj['outdata'][-5:] != '.fits': configObj['outdata'] += '.fits' scale_pars = configObj['Data Scaling Parameters'] user_wcs_pars = configObj['User WCS Parameters'] # PyFITS can be used here as it will always operate on # output from PyDrizzle (which will always be a FITS file) # Open the input (drizzled?) image _fname, _sciextn = fileutil.parseFilename(configObj['data']) _inimg = fileutil.openImage(_fname, memmap=False) _expin = fileutil.getKeyword(configObj['data'], scale_pars['expkey'], handle=_inimg) # Return the PyFITS HDU corresponding to the named extension _scihdu = fileutil.getExtn(_inimg, _sciextn) _insci = _scihdu.data.copy() _inexptime = 1.0 if scale_pars['in_units'] == 'counts': if scale_pars['expkey'] in _inimg['PRIMARY'].header: _inexptime = _inimg['PRIMARY'].header[scale_pars['expkey']] elif 'DRIZEXPT' in _inimg['PRIMARY'].header: # Try keyword written out by new 'drizzle' if no valid 'expkey' was given _inexptime = _inimg['PRIMARY'].header['DRIZEXPT'] else: raise ValueError('No valid exposure time keyword could be found ' 'for input %s' % configObj['data']) # always convert input to 'cps' for blot() algorithm if _inexptime != 0.0 or _inexptime != 1.0: np.divide(_insci, _inexptime, _insci) _inimg.close() del _inimg # read in WCS from source (drizzled) image source_wcs = stwcs.wcsutil.HSTWCS(configObj['data']) if source_wcs.wcs.is_unity(): print( "WARNING: No valid WCS found for input drizzled image: {}!".format( configObj['data'])) # define blot_wcs blot_wcs = None _refname, _refextn = fileutil.parseFilename(configObj['reference']) if os.path.exists(_refname): # read in WCS from pre-existing output image blot_wcs = stwcs.wcsutil.HSTWCS(configObj['reference']) if blot_wcs.wcs.is_unity(): print("WARNING: No valid WCS found for output image: {} !".format( configObj['reference'])) # define blot WCS based on input images or specified reference WCS values if user_wcs_pars['user_wcs']: blot_wcs = wcs_functions.build_hstwcs(user_wcs_pars['raref'], user_wcs_pars['decref'], user_wcs_pars['xrefpix'], user_wcs_pars['yrefpix'], int(user_wcs_pars['outnx']), int(user_wcs_pars['outny']), user_wcs_pars['outscale'], user_wcs_pars['orient']) configObj['coeffs'] = None # If blot_wcs is still not defined at this point, we have a problem... if blot_wcs is None: blot_wcs = stwcs.distortion.utils.output_wcs([source_wcs], undistort=False) out_wcs = blot_wcs.copy() # perform blotting operation now _outsci = do_blot(_insci, source_wcs, out_wcs, _expin, coeffs=configObj['coeffs'], interp=configObj['interpol'], sinscl=configObj['sinscl'], stepsize=configObj['stepsize'], wcsmap=wcsmap) # create output with proper units and exptime-scaling if scale_pars['out_units'] == 'counts': if scale_pars['expout'] == 'input': _outscale = fileutil.getKeyword(configObj['reference'], scale_pars['expkey']) #_outscale = _expin else: _outscale = float(scale_pars['expout']) print( "Output blotted images scaled by exptime of {}".format(_outscale)) np.multiply(_outsci, _outscale, _outsci) # Add sky back in to the blotted image, as specified by the user if configObj['addsky']: skyval = _scihdu.header['MDRIZSKY'] else: skyval = configObj['skyval'] print("Added {} counts back in to blotted image as sky.".format(skyval)) _outsci += skyval del _scihdu # Write output Numpy objects to a PyFITS file # Blotting only occurs from a drizzled SCI extension # to a blotted SCI extension... outputimage.writeSingleFITS(_outsci, blot_wcs, configObj['outdata'], configObj['reference'])
def run(configObj, wcsmap=None): """ Interface for running `wdrizzle` from TEAL or Python command-line. This code performs all file ``I/O`` to set up the use of the drizzle code for a single exposure to replicate the functionality of the original `wdrizzle`. """ # Insure all output filenames specified have .fits extensions if configObj['outdata'][-5:] != '.fits': configObj['outdata'] += '.fits' if not util.is_blank( configObj['outweight']) and configObj['outweight'][-5:] != '.fits': configObj['outweight'] += '.fits' if not util.is_blank(configObj['outcontext'] ) and configObj['outcontext'][-5:] != '.fits': configObj['outcontext'] += '.fits' # Keep track of any files we need to open in_sci_handle = None in_wht_handle = None out_sci_handle = None out_wht_handle = None out_con_handle = None _wcskey = configObj['wcskey'] if util.is_blank(_wcskey): _wcskey = ' ' scale_pars = configObj['Data Scaling Parameters'] user_wcs_pars = configObj['User WCS Parameters'] # Open the SCI (and WHT?) image # read file to get science array insci = get_data(configObj['input']) expin = fileutil.getKeyword(configObj['input'], scale_pars['expkey']) in_sci_phdr = fits.getheader(fileutil.parseFilename(configObj['input'])[0], memmap=False) # we need to read in the input WCS input_wcs = stwcs.wcsutil.HSTWCS(configObj['input'], wcskey=_wcskey) if not util.is_blank(configObj['inweight']): inwht = get_data(configObj['inweight']).astype(np.float32) else: # Generate a default weight map of all good pixels inwht = np.ones(insci.shape, dtype=insci.dtype) output_exists = False outname = fileutil.osfn(fileutil.parseFilename(configObj['outdata'])[0]) if os.path.exists(outname): output_exists = True # Output was specified as a filename, so open it in 'update' mode outsci = get_data(configObj['outdata']) if output_exists: # we also need to read in the output WCS from pre-existing output output_wcs = stwcs.wcsutil.HSTWCS(configObj['outdata']) out_sci_hdr = fits.getheader(outname, memmap=False) outexptime = out_sci_hdr['DRIZEXPT'] if 'ndrizim' in out_sci_hdr: uniqid = out_sci_hdr['ndrizim'] + 1 else: uniqid = 1 else: # otherwise, define the output WCS either from user pars or refimage if util.is_blank(configObj['User WCS Parameters']['refimage']): # Define a WCS based on user provided WCS values # NOTE: # All parameters must be specified, not just one or a few if not util.is_blank(user_wcs_pars['outscale']): output_wcs = wcs_functions.build_hstwcs( user_wcs_pars['raref'], user_wcs_pars['decref'], user_wcs_pars['xrefpix'], user_wcs_pars['yrefpix'], int(user_wcs_pars['outnx']), int(user_wcs_pars['outny']), user_wcs_pars['outscale'], user_wcs_pars['orient']) else: # Define default WCS based on input image applydist = True if input_wcs.sip is None or input_wcs.instrument == 'DEFAULT': applydist = False output_wcs = stwcs.distortion.utils.output_wcs( [input_wcs], undistort=applydist) else: refimage = configObj['User WCS Parameters']['refimage'] refroot, extroot = fileutil.parseFilename(refimage) if extroot is None: fimg = fits.open(refroot, memmap=False) for i, extn in enumerate(fimg): if 'CRVAL1' in extn.header: # Key on CRVAL1 for valid WCS refwcs = stwcs.wcsutil.HSTWCS('{}[{}]'.format( refroot, i)) if refwcs.wcs.has_cd(): extroot = i break fimg.close() # try to find extension with valid WCS refimage = "{}[{}]".format(refroot, extroot) # Define the output WCS based on a user specified reference image WCS output_wcs = stwcs.wcsutil.HSTWCS(refimage) # Initialize values used for combining results outexptime = 0.0 uniqid = 1 # Set up the output data array and insure that the units for that array is 'cps' if outsci is None: # Define a default blank array based on definition of output_wcs outsci = np.empty(output_wcs.array_shape, dtype=np.float32) outsci.fill(np.nan) else: # Convert array to units of 'cps', if needed if outexptime != 0.0: np.divide(outsci, outexptime, outsci) outsci = outsci.astype(np.float32) # Now update output exposure time for additional input file outexptime += expin outwht = None if not util.is_blank(configObj['outweight']): outwht = get_data(configObj['outweight']) if outwht is None: outwht = np.zeros(output_wcs.array_shape, dtype=np.float32) else: outwht = outwht.astype(np.float32) outcon = None keep_con = False if not util.is_blank(configObj['outcontext']): outcon = get_data(configObj['outcontext']) keep_con = True if outcon is None: outcon = np.zeros((1, ) + output_wcs.array_shape, dtype=np.int32) else: outcon = outcon.astype(np.int32) planeid = int((uniqid - 1) / 32) # Add a new plane to the context image if planeid overflows while outcon.shape[0] <= planeid: plane = np.zeros_like(outcon[0]) outcon = np.append(outcon, plane, axis=0) # Interpret wt_scl parameter if configObj['wt_scl'] == 'exptime': wt_scl = expin elif configObj['wt_scl'] == 'expsq': wt_scl = expin * expin else: wt_scl = float(configObj['wt_scl']) # Interpret coeffs parameter to determine whether to apply coeffs or not undistort = True if not configObj[ 'coeffs'] or input_wcs.sip is None or input_wcs.instrument == 'DEFAULT': undistort = False # turn off use of coefficients if undistort is False (coeffs == False) if not undistort: input_wcs.sip = None input_wcs.cpdis1 = None input_wcs.cpdis2 = None input_wcs.det2im = None wcslin = distortion.utils.output_wcs([input_wcs], undistort=undistort) # Perform actual drizzling now... _vers = do_driz(insci, input_wcs, inwht, output_wcs, outsci, outwht, outcon, expin, scale_pars['in_units'], wt_scl, wcslin_pscale=wcslin.pscale, uniqid=uniqid, pixfrac=configObj['pixfrac'], kernel=configObj['kernel'], fillval=scale_pars['fillval'], stepsize=configObj['stepsize'], wcsmap=None) out_sci_handle, outextn = create_output(configObj['outdata']) if not output_exists: # Also, define default header based on input image Primary header out_sci_handle[outextn].header = in_sci_phdr.copy() # Update header of output image with exptime used to scale the output data # if out_units is not counts, this will simply be a value of 1.0 # the keyword 'exptime' will always contain the total exposure time # of all input image regardless of the output units out_sci_handle[outextn].header['EXPTIME'] = outexptime # create CTYPE strings ctype1 = input_wcs.wcs.ctype[0] ctype2 = input_wcs.wcs.ctype[1] if ctype1.find('-SIP'): ctype1 = ctype1.replace('-SIP', '') if ctype2.find('-SIP'): ctype2 = ctype2.replace('-SIP', '') # Update header with WCS keywords out_sci_handle[outextn].header['ORIENTAT'] = output_wcs.orientat out_sci_handle[outextn].header['CD1_1'] = output_wcs.wcs.cd[0][0] out_sci_handle[outextn].header['CD1_2'] = output_wcs.wcs.cd[0][1] out_sci_handle[outextn].header['CD2_1'] = output_wcs.wcs.cd[1][0] out_sci_handle[outextn].header['CD2_2'] = output_wcs.wcs.cd[1][1] out_sci_handle[outextn].header['CRVAL1'] = output_wcs.wcs.crval[0] out_sci_handle[outextn].header['CRVAL2'] = output_wcs.wcs.crval[1] out_sci_handle[outextn].header['CRPIX1'] = output_wcs.wcs.crpix[0] out_sci_handle[outextn].header['CRPIX2'] = output_wcs.wcs.crpix[1] out_sci_handle[outextn].header['CTYPE1'] = ctype1 out_sci_handle[outextn].header['CTYPE2'] = ctype2 out_sci_handle[outextn].header['VAFACTOR'] = 1.0 if scale_pars['out_units'] == 'counts': np.multiply(outsci, outexptime, outsci) out_sci_handle[outextn].header['DRIZEXPT'] = outexptime else: out_sci_handle[outextn].header['DRIZEXPT'] = 1.0 # Update header keyword NDRIZIM to keep track of how many images have # been combined in this product so far out_sci_handle[outextn].header['NDRIZIM'] = uniqid # define keywords to be written out to product header drizdict = outputimage.DRIZ_KEYWORDS.copy() # Update drizdict with current values drizdict['VER']['value'] = _vers[:44] drizdict['DATA']['value'] = configObj['input'][:64] drizdict['DEXP']['value'] = expin drizdict['OUDA']['value'] = configObj['outdata'][:64] drizdict['OUWE']['value'] = configObj['outweight'][:64] drizdict['OUCO']['value'] = configObj['outcontext'][:64] drizdict['MASK']['value'] = configObj['inweight'][:64] drizdict['WTSC']['value'] = wt_scl drizdict['KERN']['value'] = configObj['kernel'] drizdict['PIXF']['value'] = configObj['pixfrac'] drizdict['OUUN']['value'] = scale_pars['out_units'] drizdict['FVAL']['value'] = scale_pars['fillval'] drizdict['WKEY']['value'] = configObj['wcskey'] outputimage.writeDrizKeywords(out_sci_handle[outextn].header, uniqid, drizdict) # add output array to output file out_sci_handle[outextn].data = outsci out_sci_handle.close() if not util.is_blank(configObj['outweight']): out_wht_handle, outwhtext = create_output(configObj['outweight']) out_wht_handle[outwhtext].header = out_sci_handle[outextn].header.copy( ) out_wht_handle[outwhtext].data = outwht out_wht_handle.close() if keep_con: out_con_handle, outconext = create_output(configObj['outcontext']) out_con_handle[outconext].data = outcon out_con_handle.close()
def updateAsnTable(tabname, rootname, xsh=None, ysh=None, form="absolute", rot=None, scale=None, frame="input", units="pixels", output=None, mode="replace"): """ Updates an existing ASN table with shifts in arcseconds of RA and Dec. Parameters: tabname - name of ASN table to be updated rootname - name of image whose pointing needs to be updated xsh - X shift from nominal to be applied ysh - Y shift from nominal to be applied rot - additional rotation to be applied scale - scale factor to be applied form - specifies how shifts are computed: absolute (default) or delta frame - specifies whether xsh/ysh are given in terms of input (default) or output frame units - specifies units of xsh/ysh: pixels (default) or arcseconds output - filename (with or without path) of output image from which output pixels shifts were computed. mode - replace or add shifts to existing values 'replace' (default) or 'sum' The task will: - open the ASN file (tabname) - search for the row matching the rootname provided by the user (img), - convert any pixel shifts to arcseconds - update the XOFFSET, YOFFSET, ROTATION columns (or create them if they don't already exist) This task assumes that the shifts given as 'input' pixels are already distortion-corrected, but not scaled/rotated to output frame. The conversion of shifts given in terms of output pixel coordinates requires the use of the WCS from the output frame in order to correctly take into account the output frame's pixel scale and orientation. Both input and output image specifications assume '.fits' and that the WCS information appropriate for this are in either [0] or [sci,1]. If necessary a different extension can be specified in the filename. Also, the output filename can include a path which will be used. EXAMPLE: 1. Update ASN table 'j8cw03020_asn.fits' for 'j8cw03021_crj.fits' which has pixel shifts of (10.3,4.72) in (undistorted) input frame. >>> updateasn.updateAsnTable('j8cw03020_asn.fits','j8cw03021', xsh=10.3,ysh=4.72,rot=0.14) NOTE: This task still does not correctly work with 'NaN' entries in the table. For those values, it will not change the values at all. """ if frame == 'output' and output == None: print('Please specify output image needed to compute deltas...') return print('updateAsnTable Version ', __version__) _tmpname = 'buildasn_' + tabname # Start by opening the ASN table _asntab = pyfits.open(tabname, 'update') if form == 'absolute' or form == 'relative': # absolute/relative shifts _colx = 'XOFFSET' _coly = 'YOFFSET' else: # delta shifts _colx = 'XDELTA' _coly = 'YDELTA' # # Work out what needs to be done to update ASN table # Do the XOFFSET/YOFFSET/ROTATION columns already exist or not? # _update = no _add_rot = yes _add_scale = yes _colnum = 0 for name in _asntab[1].columns.names: if name == _colx: # Make the assumption that XOFFSET/YOFFSET and ROTATION # are all present if one is present... _update = yes break _colnum += 1 if _update: _tab_units = _asntab[1].columns.units[_colnum] if _tab_units == '' or _tab_units == None: _tab_units = 'pixels' else: _tab_units = units for name in _asntab[1].columns.names: if name == 'ROTATION': _add_rot = no break for name in _asntab[1].columns.names: if name == 'SCALE': _add_scale = no break # Get the shift frame and refimage if present # If keywords don't exist, assume default of 'input' shifts # with no need for refimage. try: _tab_frame = _asntab[0].header['shframe'] except KeyError: _tab_frame = 'input' try: _tab_refimg = _asntab[0].header['refimage'] except KeyError: _tab_refimg = None # Find row which corresponds to input image _rownum = 0 for row in _asntab[1].data: if rootname.find(row.field('MEMNAME')) > -1: _row = row break _rownum += 1 print('Updating table row ', _rownum, ' for image: ', rootname) # # Determine where to get the distortion coefficients # create complete filename from given rootname img = fileutil.buildRootname(rootname) if img == None: print('No valid input image for filename ', rootname) raise ValueError _instrument = fileutil.getKeyword(img, 'instrume') if _instrument not in IDCKEYS: _instrument = 'detector' _key = IDCKEYS[_instrument] if xsh == None: xsh = 0. if ysh == None: ysh = 0. # If we have any trouble computing offsets, abort and # do NOT update table. try: # Start by determining values to be used to update the table. # # Need to compute: _delta_ra, _delta_dec (undistorted arcsec) if units == _tab_units or (xsh == 0. and ysh == 0.): _delta_xoff = xsh _delta_yoff = ysh if rot == None: rot = 0. if scale == None: scale = 1.0 elif units.find('pixels') > -1 and _tab_units.find('arcsec') > -1: # # We need to convert the pixel values to arcseconds # _wcs = _getExposure(img, output, frame, _key) # If there is any additional rotation, account for it first if rot != None: if scale != None: pscale = scale * _wcs.pscale else: pscale = None _wcs.updateWCS(orient=_wcs.orient + rot, pixel_scale=pscale) # determine delta CRVALs from CRPIX+(xsh,ysh) _rd_delta = _wcs.xy2rd((_wcs.crpix1 + xsh, _wcs.crpix2 + ysh)) # Now, convert from degrees to arcseconds #### Do we need to multiply by cos(dec) for delta(RA)??? _delta_xoff = (_rd_delta[0] - _wcs.crval1) * 3600. _delta_yoff = (_rd_delta[1] - _wcs.crval2) * 3600. elif units.find('arcsec') > -1 and _tab_units.find('pixels') > -1: _wcs = _getExposure(img, _tab_refimg, _tab_frame, _key) # If there is any additional rotation, account for it first if rot != None: if scale != None: pscale = scale * _wcs.pscale else: pscale = None _wcs.updateWCS(orient=_wcs.orient + rot, pixel_scale=pscale) _xy_delta = _wcs.rd2xy((_wcs.crval1 + xsh, _wcs.crval2 + ysh)) _delta_xoff = (_xy_delta[0] - _wcs.crpix1) _delta_yoff = (_xy_delta[1] - _wcs.crpix2) except: print('ERROR: Error in updating table ', tabname) print('Closing existing table without updating it...') _asntab.close() return if _update: # Offset columns exist, just update the values in the table if mode == 'sum': _shift_xoff = _asntab[1].data.field(_colx)[_rownum] _shift_yoff = _asntab[1].data.field(_coly)[_rownum] _shift_rot = _asntab[1].data.field('ROTATION')[_rownum] _shift_scale = _asntab[1].data.field('SCALE')[_rownum] # Account for INDEF values in table # Logic: If set to INDEF, adding 1.0 will not change its value if _shift_xoff + 1.0 == _shift_xoff: _shift_xoff = 0. if _shift_yoff + 1.0 == _shift_yoff: _shift_yoff = 0. if _shift_rot + 1.0 == _shift_rot: _shift_rot = 0. if _shift_scale + 1.0 == _shift_scale: _shift_scale = 1.0 else: _shift_xoff = 0. _shift_yoff = 0. _shift_rot = 0. _shift_scale = 1. _asntab[1].data.field(_colx)[_rownum] = _shift_xoff + _delta_xoff _asntab[1].data.field(_coly)[_rownum] = _shift_yoff + _delta_yoff if rot != None: _asntab[1].data.field('ROTATION')[_rownum] = _shift_rot + rot if scale != None: _asntab[1].data.field('SCALE')[_rownum] = _shift_scale * scale else: # We need to add the extra columns to the table # Build arrays for each additional column _numrows = len(_asntab[1].data) _xsh = N.zeros(_numrows, dtype=N.float32) _ysh = N.zeros(_numrows, dtype=N.float32) # Now update entry associated with this particular image _xsh[_rownum] = _delta_xoff _ysh[_rownum] = _delta_yoff # Build the column objects for the table #_xc,_yc,_rc = buildasn._makeOffsetColumns(_xsh,_ysh,_rot) _xc = pyfits.Column(name=_colx, format='E', unit=_tab_units, array=_xsh) _yc = pyfits.Column(name=_coly, format='E', unit=_tab_units, array=_ysh) _newcols = _asntab[1].columns + _xc _newcols += _yc #_asndefs = _asntab[1].get_coldefs() #_asndefs.add_col(_xc) #_asndefs.add_col(_yc) # If rotation column does NOT exist, if _add_rot: _rot = N.zeros(_numrows, dtype=N.float32) if rot != None: _rot[_rownum] = rot _rc = pyfits.Column(name='ROTATION', format='E', unit='degrees', array=_rot) # add newly created column #_asndefs.add_col(_rc) _newcols += _rc else: # else, update column directly. _asntab[1].data.field('ROTATION')[_rownum] = rot # If scaling column does NOT exist, if _add_scale: _scale = N.zeros(_numrows, dtype=N.float32) if scale != None: _scale[_rownum] = scale _sc = pyfits.Column(name='SCALE', format='E', unit='', array=_scale) _newcols += _sc else: # else, update column directly. _asntab[1].data.field('SCALE')[_rownum] = scale _asnhdu = pyfits.new_table(_newcols) _asnhdu.writeto(_tmpname) # remove old data #del _asntab[1] # add table extension with old data and new columns #_asntab.append(_asnhdu) # Close and clean-up _asntab.close() del _asntab if os.path.exists(_tmpname): os.remove(tabname) os.rename(_tmpname, tabname)
def run(configObj, wcsmap=None): """ Interface for running `wdrizzle` from TEAL or Python command-line. This code performs all file ``I/O`` to set up the use of the drizzle code for a single exposure to replicate the functionality of the original `wdrizzle`. """ # Insure all output filenames specified have .fits extensions if configObj['outdata'][-5:] != '.fits': configObj['outdata'] += '.fits' if not util.is_blank(configObj['outweight']) and configObj['outweight'][-5:] != '.fits': configObj['outweight'] += '.fits' if not util.is_blank(configObj['outcontext']) and configObj['outcontext'][-5:] != '.fits': configObj['outcontext'] += '.fits' # Keep track of any files we need to open in_sci_handle = None in_wht_handle = None out_sci_handle = None out_wht_handle = None out_con_handle = None _wcskey = configObj['wcskey'] if util.is_blank(_wcskey): _wcskey = ' ' scale_pars = configObj['Data Scaling Parameters'] user_wcs_pars = configObj['User WCS Parameters'] # Open the SCI (and WHT?) image # read file to get science array insci = get_data(configObj['input']) expin = fileutil.getKeyword(configObj['input'],scale_pars['expkey']) in_sci_phdr = fits.getheader(fileutil.parseFilename(configObj['input'])[0]) # we need to read in the input WCS input_wcs = stwcs.wcsutil.HSTWCS(configObj['input'],wcskey=_wcskey) if not util.is_blank(configObj['inweight']): inwht = get_data(configObj['inweight']).astype(np.float32) else: # Generate a default weight map of all good pixels inwht = np.ones(insci.shape,dtype=insci.dtype) output_exists = False outname = fileutil.osfn(fileutil.parseFilename(configObj['outdata'])[0]) if os.path.exists(outname): output_exists = True # Output was specified as a filename, so open it in 'update' mode outsci = get_data(configObj['outdata']) if output_exists: # we also need to read in the output WCS from pre-existing output output_wcs = stwcs.wcsutil.HSTWCS(configObj['outdata']) out_sci_hdr = fits.getheader(outname) outexptime = out_sci_hdr['DRIZEXPT'] if 'ndrizim' in out_sci_hdr: uniqid = out_sci_hdr['ndrizim']+1 else: uniqid = 1 else: # otherwise, define the output WCS either from user pars or refimage if util.is_blank(configObj['User WCS Parameters']['refimage']): # Define a WCS based on user provided WCS values # NOTE: # All parameters must be specified, not just one or a few if not util.is_blank(user_wcs_pars['outscale']): output_wcs = wcs_functions.build_hstwcs( user_wcs_pars['raref'], user_wcs_pars['decref'], user_wcs_pars['xrefpix'], user_wcs_pars['yrefpix'], user_wcs_pars['outnx'], user_wcs_pars['outny'], user_wcs_pars['outscale'], user_wcs_pars['orient'] ) else: # Define default WCS based on input image applydist = True if input_wcs.sip is None or input_wcs.instrument=='DEFAULT': applydist = False output_wcs = stwcs.distortion.utils.output_wcs([input_wcs],undistort=applydist) else: refimage = configObj['User WCS Parameters']['refimage'] refroot,extroot = fileutil.parseFilename(refimage) if extroot is None: fimg = fits.open(refroot) for i,extn in enumerate(fimg): if 'CRVAL1' in extn.header: # Key on CRVAL1 for valid WCS refwcs = wcsutil.HSTWCS('{}[{}]'.format(refroot,i)) if refwcs.wcs.has_cd(): extroot = i break fimg.close() # try to find extension with valid WCS refimage = "{}[{}]".format(refroot,extroot) # Define the output WCS based on a user specified reference image WCS output_wcs = stwcs.wcsutil.HSTWCS(refimage) # Initialize values used for combining results outexptime = 0.0 uniqid = 1 # Set up the output data array and insure that the units for that array is 'cps' if outsci is None: # Define a default blank array based on definition of output_wcs #outsci = np.zeros((output_wcs._naxis2,output_wcs._naxis1),dtype=np.float32) outsci = np.empty((output_wcs._naxis2,output_wcs._naxis1),dtype=np.float32) outsci.fill(np.nan) else: # Convert array to units of 'cps', if needed if outexptime != 0.0: np.divide(outsci, outexptime, outsci) outsci = outsci.astype(np.float32) # Now update output exposure time for additional input file outexptime += expin outwht = None if not util.is_blank(configObj['outweight']): outwht = get_data(configObj['outweight']) if outwht is None: outwht = np.zeros((output_wcs._naxis2,output_wcs._naxis1),dtype=np.float32) else: outwht = outwht.astype(np.float32) outcon = None keep_con = False if not util.is_blank(configObj['outcontext']): outcon = get_data(configObj['outcontext']) keep_con = True if outcon is None: outcon = np.zeros((1,output_wcs._naxis2,output_wcs._naxis1),dtype=np.int32) else: outcon = outcon.astype(np.int32) planeid = int((uniqid - 1)/ 32) # Add a new plane to the context image if planeid overflows while outcon.shape[0] <= planeid: plane = np.zeros_like(outcon[0]) outcon = np.append(outcon, plane, axis=0) # Interpret wt_scl parameter if configObj['wt_scl'] == 'exptime': wt_scl = expin elif configObj['wt_scl'] == 'expsq': wt_scl = expin*expin else: wt_scl = float(configObj['wt_scl']) # Interpret coeffs parameter to determine whether to apply coeffs or not undistort = True if not configObj['coeffs'] or input_wcs.sip is None or input_wcs.instrument == 'DEFAULT': undistort = False # turn off use of coefficients if undistort is False (coeffs == False) if not undistort: input_wcs.sip = None input_wcs.cpdis1 = None input_wcs.cpdis2 = None input_wcs.det2im = None wcslin = distortion.utils.output_wcs([input_wcs],undistort=undistort) # Perform actual drizzling now... _vers = do_driz(insci, input_wcs, inwht, output_wcs, outsci, outwht, outcon, expin, scale_pars['in_units'], wt_scl, wcslin_pscale=wcslin.pscale ,uniqid=uniqid, pixfrac=configObj['pixfrac'], kernel=configObj['kernel'], fillval=scale_pars['fillval'], stepsize=configObj['stepsize'], wcsmap=None) out_sci_handle,outextn = create_output(configObj['outdata']) if not output_exists: # Also, define default header based on input image Primary header out_sci_handle[outextn].header = in_sci_phdr.copy() # Update header of output image with exptime used to scale the output data # if out_units is not counts, this will simply be a value of 1.0 # the keyword 'exptime' will always contain the total exposure time # of all input image regardless of the output units out_sci_handle[outextn].header['EXPTIME'] = outexptime # create CTYPE strings ctype1 = input_wcs.wcs.ctype[0] ctype2 = input_wcs.wcs.ctype[1] if ctype1.find('-SIP'): ctype1 = ctype1.replace('-SIP','') if ctype2.find('-SIP'): ctype2 = ctype2.replace('-SIP','') # Update header with WCS keywords out_sci_handle[outextn].header['ORIENTAT'] = output_wcs.orientat out_sci_handle[outextn].header['CD1_1'] = output_wcs.wcs.cd[0][0] out_sci_handle[outextn].header['CD1_2'] = output_wcs.wcs.cd[0][1] out_sci_handle[outextn].header['CD2_1'] = output_wcs.wcs.cd[1][0] out_sci_handle[outextn].header['CD2_2'] = output_wcs.wcs.cd[1][1] out_sci_handle[outextn].header['CRVAL1'] = output_wcs.wcs.crval[0] out_sci_handle[outextn].header['CRVAL2'] = output_wcs.wcs.crval[1] out_sci_handle[outextn].header['CRPIX1'] = output_wcs.wcs.crpix[0] out_sci_handle[outextn].header['CRPIX2'] = output_wcs.wcs.crpix[1] out_sci_handle[outextn].header['CTYPE1'] = ctype1 out_sci_handle[outextn].header['CTYPE2'] = ctype2 out_sci_handle[outextn].header['VAFACTOR'] = 1.0 if scale_pars['out_units'] == 'counts': np.multiply(outsci, outexptime, outsci) out_sci_handle[outextn].header['DRIZEXPT'] = outexptime else: out_sci_handle[outextn].header['DRIZEXPT'] = 1.0 # Update header keyword NDRIZIM to keep track of how many images have # been combined in this product so far out_sci_handle[outextn].header['NDRIZIM'] = uniqid #define keywords to be written out to product header drizdict = outputimage.DRIZ_KEYWORDS.copy() # Update drizdict with current values drizdict['VER']['value'] = _vers[:44] drizdict['DATA']['value'] = configObj['input'][:64] drizdict['DEXP']['value'] = expin drizdict['OUDA']['value'] = configObj['outdata'][:64] drizdict['OUWE']['value'] = configObj['outweight'][:64] drizdict['OUCO']['value'] = configObj['outcontext'][:64] drizdict['MASK']['value'] = configObj['inweight'][:64] drizdict['WTSC']['value'] = wt_scl drizdict['KERN']['value'] = configObj['kernel'] drizdict['PIXF']['value'] = configObj['pixfrac'] drizdict['OUUN']['value'] = scale_pars['out_units'] drizdict['FVAL']['value'] = scale_pars['fillval'] drizdict['WKEY']['value'] = configObj['wcskey'] outputimage.writeDrizKeywords(out_sci_handle[outextn].header,uniqid,drizdict) # add output array to output file out_sci_handle[outextn].data = outsci out_sci_handle.close() if not util.is_blank(configObj['outweight']): out_wht_handle,outwhtext = create_output(configObj['outweight']) out_wht_handle[outwhtext].header = out_sci_handle[outextn].header.copy() out_wht_handle[outwhtext].data = outwht out_wht_handle.close() if keep_con: out_con_handle,outconext = create_output(configObj['outcontext']) out_con_handle[outconext].data = outcon out_con_handle.close()
def run(configObj,wcsmap=None): """ Run the blot task based on parameters provided interactively by the user. """ # Insure all output filenames specified have .fits extensions if configObj['outdata'][-5:] != '.fits': configObj['outdata'] += '.fits' scale_pars = configObj['Data Scaling Parameters'] user_wcs_pars = configObj['User WCS Parameters'] # PyFITS can be used here as it will always operate on # output from PyDrizzle (which will always be a FITS file) # Open the input (drizzled?) image _fname,_sciextn = fileutil.parseFilename(configObj['data']) _inimg = fileutil.openImage(_fname) _expin = fileutil.getKeyword(configObj['data'],scale_pars['expkey'],handle=_inimg) # Return the PyFITS HDU corresponding to the named extension _scihdu = fileutil.getExtn(_inimg,_sciextn) _insci = _scihdu.data.copy() _inexptime = 1.0 if scale_pars['in_units'] == 'counts': if scale_pars['expkey'] in _inimg['PRIMARY'].header: _inexptime = _inimg['PRIMARY'].header[scale_pars['expkey']] elif 'DRIZEXPT' in _inimg['PRIMARY'].header: # Try keyword written out by new 'drizzle' if no valid 'expkey' was given _inexptime = _inimg['PRIMARY'].header['DRIZEXPT'] else: raise ValueError('No valid exposure time keyword could be found ' 'for input %s' % configObj['data']) # always convert input to 'cps' for blot() algorithm if _inexptime != 0.0 or _inexptime != 1.0: np.divide(_insci, _inexptime, _insci) _inimg.close() del _inimg # read in WCS from source (drizzled) image source_wcs = stwcs.wcsutil.HSTWCS(configObj['data']) if source_wcs.wcs.is_unity(): print("WARNING: No valid WCS found for input drizzled image: {}!".format(configObj['data'])) # define blot_wcs blot_wcs = None _refname,_refextn = fileutil.parseFilename(configObj['reference']) if os.path.exists(_refname): # read in WCS from pre-existing output image blot_wcs = stwcs.wcsutil.HSTWCS(configObj['reference']) if blot_wcs.wcs.is_unity(): print("WARNING: No valid WCS found for output image: {} !".format(configObj['reference'])) # define blot WCS based on input images or specified reference WCS values if user_wcs_pars['user_wcs']: blot_wcs = wcs_functions.build_hstwcs( user_wcs_pars['raref'], user_wcs_pars['decref'], user_wcs_pars['xrefpix'], user_wcs_pars['yrefpix'], user_wcs_pars['outnx'], user_wcs_pars['outny'], user_wcs_pars['outscale'], user_wcs_pars['orient'] ) configObj['coeffs'] = None # If blot_wcs is still not defined at this point, we have a problem... if blot_wcs is None: blot_wcs = stwcs.distortion.utils.output_wcs([source_wcs],undistort=False) out_wcs = blot_wcs.copy() # perform blotting operation now _outsci = do_blot(_insci, source_wcs, out_wcs, _expin, coeffs=configObj['coeffs'], interp=configObj['interpol'], sinscl=configObj['sinscl'], stepsize=configObj['stepsize'], wcsmap=wcsmap) # create output with proper units and exptime-scaling if scale_pars['out_units'] == 'counts': if scale_pars['expout'] == 'input': _outscale = fileutil.getKeyword(configObj['reference'],scale_pars['expkey']) #_outscale = _expin else: _outscale = float(scale_pars['expout']) print("Output blotted images scaled by exptime of {}".format(_outscale)) np.multiply(_outsci, _outscale, _outsci) # Add sky back in to the blotted image, as specified by the user if configObj['addsky']: skyval = _scihdu.header['MDRIZSKY'] else: skyval = configObj['skyval'] print("Added {} counts back in to blotted image as sky.".format(skyval)) _outsci += skyval del _scihdu # Write output Numpy objects to a PyFITS file # Blotting only occurs from a drizzled SCI extension # to a blotted SCI extension... outputimage.writeSingleFITS(_outsci,blot_wcs, configObj['outdata'],configObj['reference'])
def __init__(self,expname, handle=None, dqname=None, idckey=None, new=no,wcs=None,mask=None,pa_key=None, parity=None, idcdir=None, rot=None, extver=1, exptime=None, ref_pscale=1.0, binned=1, mt_wcs=None, group_indx = None): # This name should be formatted for use in image I/O self.name = fileutil.osfn(expname) # osfn() will expand '.' unnecessarily, potentially # creating a string-length problem for 'drizzle', which # is limited to strings of 80 chars. _path,_name = os.path.split(self.name) # if path for this filename is the same as the current dir, # then there is no need to pass along the path. if _path == os.getcwd(): self.name = _name # Keep track of any associated mask file created for # this exposure from its DQ file, or other mask file. _fname,_extn = fileutil.parseFilename(expname) _open = False # Make sure we have an open file handle to use for getting the # header and data arrays. if not handle and not new: handle = fileutil.openImage(expname) _open = True # If no extension was specified, try to interrogate the file # to find whether the SCI array is in the Primary # (as in Simple FITS) or first extension (as in MEF). if handle and _extn == None: if handle[0].data == None: # Primary extension specified and no data present. # Try looking for data in next extension. if len(handle) > 1 and handle[1].data != None: _extn = 1 expname += '[1]' else: raise IOError("No valid image data in %s.\n"%expname) else: _extn = 0 self.dgeoname = None self.xgeoim = "" self.ygeoim = "" self.exptime = exptime self.group_indx = group_indx if not new: # Read in a copy of the header for this exposure/group/extension _header = fileutil.getHeader(expname,handle=handle) _chip = drutil.getChipId(_header) self.chip = str(_chip) # Keep track of any distortion correction images provided # for this chip self.dgeoname = fileutil.getKeyword(expname,'DGEOFILE',handle=handle) self.xgeoim,self.ygeoim = self.getDGEOExtn() if self.exptime == None: self.exptime = float(_header['EXPTIME']) if self.exptime == 0.: self.exptime = 1.0 # # Extract photometric transformation keywords # If they do not exist, use default values of 0 and 1 # self.plam = float(fileutil.getKeyword(expname,'PHOTPLAM',handle=handle)) / 10. if self.plam == None: # Setup a default value in case this keyword does not exist self.plam = 555. self.photzpt = float(fileutil.getKeyword(expname,'PHOTZPT',handle=handle)) if self.photzpt == None: self.photzpt = 0.0 self.photflam = float(fileutil.getKeyword(expname,'PHOTFLAM',handle=handle)) if self.photflam == None: self.photflam = 1.0 # Read in date-obs from primary header if _header: if 'date-obs' in _header: self.dateobs = _header['date-obs'] elif 'date_obs' in _header: self.dateobs = _header['date_obs'] else: self.dateobs = None else: self.dateobs = None # Initialize the value of BUNIT based on the header information, if # the header has the keyword if 'BUNIT' in _header and _header['BUNIT'].find('ergs') < 0: self.bunit = _header['BUNIT'] else: self.bunit = 'ELECTRONS' else: _chip = 1 _header = None self.chip = str(_chip) # Set a default value for pivot wavelength self.plam = 555. self.photzpt = 0.0 self.photflam = 1.0 self.dateobs = None if self.exptime == None: self.exptime = 1. self.parity = parity self.header = _header self.extver = extver # Create a pointer to the mask file's data array # and the name of the original input DQ file self.maskname = None self.singlemaskname = None self.masklist = None if mask != None: # Specifies filenames to be used if created. self.maskname = mask[0] self.singlemaskname = mask[1] self.masklist = mask[2] self.dqname = dqname # Remember the name of the coeffs file generated for this chip self.coeffs = self.buildCoeffsName() # Read the name of idcfile from image header if not explicitly # provided by user. if idckey != None and idckey.lower() != 'wcs': _indx = expname.find('[') if _indx > -1: _idc_fname = expname[:_indx]+'[0]' else: _idc_fname = expname+'[0]' idcfile, idctype = drutil.getIDCFile(self.header,keyword=idckey, directory=idcdir) else: idcfile = None idctype = None if (idckey != None) and (idckey.lower() == 'header'): idckey = idctype # Get distortion model and WCS info. self.geometry = ObsGeometry(expname, idcfile, idckey=idckey, chip=_chip, new=new, header=self.header, pa_key=pa_key, rot=rot, date=self.dateobs, ref_pscale=ref_pscale, binned=binned, mt_wcs=mt_wcs) # Remember the name and type of the IDC file used... self.idcfile = idcfile self.idctype = idctype # Remember the names of the filters used for the exposure self.filters = self.geometry.filter1+','+self.geometry.filter2 # Define shape here... # nx,ny,pixel scale # if wcs != None: # We have been passed a WCS to use self.geometry.wcs = wcs self.geometry.model.pscale = wcs.pscale if expname != None: self.geometry.wcs.rootname = expname self.naxis1 = self.geometry.wcs.naxis1 self.naxis2 = self.geometry.wcs.naxis2 self.pscale = self.geometry.wcs.pscale self.shape = (self.naxis1,self.naxis2,self.pscale) # Keep track of the positions of the corners of the exposure # both for the RAW image and the # distortion-corrected, unscaled, unrotated image self.corners = {'raw':np.zeros((4,2),dtype=np.float64),'corrected':np.zeros((4,2),dtype=np.float64)} self.setCorners() # Generate BLOT output name specific to this Exposure _blot_extn = '_sci'+repr(extver)+'_blt.fits' self.outblot = fileutil.buildNewRootname(self.name,extn=_blot_extn) # Keep track of undistorted frame's position relative to metachip # Zero-point offset for chip relative to meta-chip product # These values get computed using 'setSingleOffsets' from 'writeCoeffs' # to insure that the final XDELTA/YDELTA values have been computed. self.product_wcs = self.geometry.wcslin self.xzero = 0. self.yzero = 0. self.chip_shape = (0.,0.) self.xsh2 = 0. self.ysh2 = 0. if _open: handle.close() del handle
def run(input,quiet=yes,restore=no,prepend='O', tddcorr=True): print("+ MAKEWCS Version %s" % __version__) _prepend = prepend files = parseinput.parseinput(input)[0] newfiles = [] if files == []: print("No valid input files found.\n") raise IOError for image in files: #find out what the input is imgfits,imgtype = fileutil.isFits(image) # Check for existence of waiver FITS input, and quit if found. if imgfits and imgtype == 'waiver': """ errormsg = '\n\nPyDrizzle does not support waiver fits format.\n' errormsg += 'Convert the input files to GEIS or multiextension FITS.\n\n' raise ValueError, errormsg """ newfilename = fileutil.buildNewRootname(image, extn='_c0h.fits') # Convert GEIS image to MEF file newimage = fileutil.openImage(image,writefits=True,fitsname=newfilename,clobber=True) del newimage # Work with new file image = newfilename newfiles.append(image) # If a GEIS image is provided as input, create a new MEF file with # a name generated using 'buildFITSName()' and update that new MEF file. if not imgfits: # Create standardized name for MEF file newfilename = fileutil.buildFITSName(image) # Convert GEIS image to MEF file newimage = fileutil.openImage(image,writefits=True,fitsname=newfilename,clobber=True) del newimage # Work with new file image = newfilename newfiles.append(image) if not quiet: print("Input files: ",files) # First get the name of the IDC table #idctab = drutil.getIDCFile(_files[0][0],keyword='idctab')[0] idctab = drutil.getIDCFile(image,keyword='idctab')[0] _found = fileutil.findFile(idctab) if idctab == None or idctab == '': print('#\n No IDCTAB specified. No correction can be done for file %s.Quitting makewcs\n' %image) #raise ValueError continue elif not _found: print('#\n IDCTAB: ',idctab,' could not be found. \n') print('WCS keywords for file %s will not be updated.\n' %image) #raise IOError continue _phdu = image + '[0]' _instrument = fileutil.getKeyword(_phdu,keyword='INSTRUME') if _instrument == 'WFPC2': Nrefchip, Nrefext = getNrefchip(image) else: Nrefchip = None Nrefext = None if _instrument not in NUM_PER_EXTN: raise ValueError("Instrument %s not supported yet. Exiting..." \ %_instrument) _detector = fileutil.getKeyword(_phdu, keyword='DETECTOR') _nimsets = get_numsci(image) for i in range(_nimsets): if image.find('.fits') > 0: _img = image+'[sci,'+repr(i+1)+']' else: _img = image+'['+repr(i+1)+']' if not restore: if not quiet: print('Updating image: ', _img) _update(_img,idctab, _nimsets, apply_tdd=False, quiet=quiet,instrument=_instrument,prepend=_prepend, nrchip=Nrefchip, nrext = Nrefext) if _instrument == 'ACS' and _detector == 'WFC': tddswitch = fileutil.getKeyword(_phdu,keyword='TDDCORR') # This logic requires that TDDCORR be in the primary header # and set to PERFORM in order to turn this on at all. It can # be turned off by setting either tddcorr=False or setting # the keyword to anything but PERFORM or by deleting the # keyword altogether. PyDrizzle will rely simply on the # values of alpha and beta as computed here to apply the # correction to the coefficients. if (tddcorr and tddswitch != 'OMIT'): print('Applying time-dependent distortion corrections...') _update(_img,idctab, _nimsets, apply_tdd=True, \ quiet=quiet,instrument=_instrument,prepend=_prepend, nrchip=Nrefchip, nrext = Nrefext) else: if not quiet: print('Restoring original WCS values for',_img) restoreCD(_img,_prepend) #fimg = fileutil.openImage(image,mode='update') #if 'TDDCORR' in fimg[0].header and fimg[0].header['TDDCORR'] == 'PERFORM': # fimg[0].header['TDDCORR'] = 'COMPLETE' #fimg.close() if newfiles == []: return files else: return newfiles