def getflat(self, chip, flat_file=None, flat_ext=None): """ Method for retrieving a detector's flat field. Parameters ---------- chip : int Chip number. Same as FITS ``EXTVER``. flat_file : str, None Flat field file name. If not specified, it will be determined automatically from image header. flat_ext : str, None Flat field extension name (same as FITS ``EXTNAME``). Specifies extension name containing flat field data. Returns ------- flat : numpy.ndarray The flat-field array in the same shape as the input image. """ # For the WFPC2 flat we need to invert # for use in Multidrizzle if flat_file is None: filename = fileutil.osfn( self._image["PRIMARY"].header[self.flatkey]) if filename in WFPC2InputImage.flat_file_map: flat_file, mef_flat_ext = WFPC2InputImage.flat_file_map[ filename] else: h = fileutil.openImage(filename, mode='readonly', memmap=False) flat_file = h.filename() mef_flat_ext = h[0].header.get('FILETYPE', '') mef_flat_ext = h[1].header.get('EXTNAME', mef_flat_ext) h.close() WFPC2InputImage.flat_file_map[filename] = (flat_file, mef_flat_ext) if flat_ext is None: flat_ext = mef_flat_ext elif flat_ext is None: h = fileutil.openImage(flat_file, mode='readonly', memmap=False, writefits=False) flat_ext = h[0].header.get('FILETYPE', '') flat_ext = h[1].header.get('EXTNAME', flat_ext) h.close() flat = 1.0 / super().getflat(chip, flat_file, flat_ext) return flat
def getHeaderHandle(self): """ Sets up the PyFITS image handle and Primary header as self.image_handle and self.header. When Pattern being used for output product, filename will be set to None and this returns None for header and image_handle. """ _numsci = 0 if self.name: _handle = fileutil.openImage(self.name,mode='readonly',memmap=self.pars['memmap']) _fname,_extn = fileutil.parseFilename(self.name) _hdr = _handle['PRIMARY'].header.copy() # Count number of SCI extensions for _fext in _handle: if 'extname' in _fext.header and _fext.header['extname'] == 'SCI': _numsci += 1 if _extn and _extn > 0: # Append correct extension/chip/group header to PRIMARY... for _card in fileutil.getExtn(_handle,_extn).header.ascard: _hdr.ascard.append(_card) else: # Default to None _handle = None _hdr = None # Set attribute to point to these products self.image_handle = None self.header = _hdr self.nmembers = _numsci return _handle
def getdarkimg(self, chip): """ Return an array representing the dark image for the detector. Returns ------- dark: array Dark image array in the same shape as the input image with **units of cps** """ sci_chip = self._image[self.scienceExt, chip] # First attempt to get the dark image specified by the "DARKFILE" # keyword in the primary keyword of the science data. try: filename = self.header["DARKFILE"] handle = fileutil.openImage(filename, mode='readonly', memmap=False) hdu = fileutil.getExtn(handle, extn="sci,1") darkobj = hdu.data[sci_chip.ltv2:sci_chip.size2, sci_chip.ltv1:sci_chip.size1] # If the darkfile cannot be located, create the dark image from # what we know about the detector dark current and assume a # constant dark current for the whole image. except: darkobj = ( np.ones(sci_chip.image_shape, dtype=sci_chip.image_dtype) * self.getdarkcurrent()) return darkobj
def isSupportedFilter(hdr): idc = hdr['idctab'] idcname = fileutil.osfn(idc) filter1 = hdr['FILTNAM1'] filter2 = hdr['FILTNAM2'] try: idctab = fileutil.openImage(idcname) except: raise IOError if idctab[1].columns.names.count( 'FILTER1') > 0 and idctab[1].columns.names.count('FILTER2') > 0: # 2 filter IDCTAB, all filter modes should be supported val = True else: # 1 filter IDCTAB, check to see whether it is a supported filter and # that input is not a 2 filter observation filters = idctab[1].data.field('FILTER') if filter1 not in filters or filter2.strip(): val = False else: val = True idctab.close() return val
def getData(self,exten=None): """ Return just the data array from the specified extension fileutil is used instead of fits to account for non- FITS input images. openImage returns a fits object. """ if exten.lower().find('sci') > -1: # For SCI extensions, the current file will have the data fname = self._filename else: # otherwise, the data being requested may need to come from a # separate file, as is the case with WFPC2 DQ data. # # convert exten to 'sci',extver to get the DQ info for that chip extn = exten.split(',') sci_chip = self._image[self.scienceExt,int(extn[1])] fname = sci_chip.dqfile extnum = self._interpretExten(exten) if self._image[extnum].data is None: if os.path.exists(fname): _image=fileutil.openImage(fname,clobber=False,memmap=0) _data=fileutil.getExtn(_image,extn=exten).data _image.close() del _image self._image[extnum].data = _data else: _data = None else: _data = self._image[extnum].data return _data
def getdarkimg(self,chip): """ Return an array representing the dark image for the detector. Returns ------- dark: array Dark image array in the same shape as the input image with **units of cps** """ sci_chip = self._image[self.scienceExt,chip] # First attempt to get the dark image specified by the "DARKFILE" # keyword in the primary keyword of the science data. try: filename = self.header["DARKFILE"] handle = fileutil.openImage(filename, mode='readonly', memmap=False) hdu = fileutil.getExtn(handle,extn="sci,1") darkobj = hdu.data[sci_chip.ltv2:sci_chip.size2,sci_chip.ltv1:sci_chip.size1] # If the darkfile cannot be located, create the dark image from # what we know about the detector dark current and assume a # constant dark current for the whole image. except: darkobj = np.ones(sci_chip.image_shape,dtype=sci_chip.image_dtype)*self.getdarkcurrent() return darkobj
def _addDefaultSkyKW(imageObjList): """Add MDRIZSKY keyword to "commanded" SCI headers of all input images, if that keyword does not already exist. """ skyKW = "MDRIZSKY" Value = 0.0 for imageSet in imageObjList: fname = imageSet._filename numchips = imageSet._numchips sciExt = imageSet.scienceExt fobj = fileutil.openImage(fname, mode='update', memmap=False) for chip in range(1, numchips + 1, 1): ext = (sciExt, chip) if not imageSet[ext].group_member: # skip over extensions not used in processing continue if skyKW not in fobj[ext].header: fobj[ext].header[skyKW] = ( Value, 'Sky value computed by AstroDrizzle') log.info( "MDRIZSKY keyword not found in the %s[%s,%d] header." % (fname, sciExt, chip)) log.info( " Adding MDRIZSKY to header with default value of 0.") fobj.close()
def doUnitConversions(self): """Convert the data to electrons. This converts all science data extensions and saves the results back to disk. We need to make sure the data inside the chips already in memory is altered as well. """ # Image information #_handle = fileutil.openImage(self._filename,mode='update',memmap=0) _handle = fileutil.openImage(self._filename,mode='readonly') for det in range(1,self._numchips+1,1): chip=self._image[self.scienceExt,det] if chip._gain != None: conversionFactor = chip._gain chip._effGain = chip._gain #1. chip._conversionFactor = conversionFactor #1. else: msg = "Invalid gain value for data, no conversion done" print(msg) raise ValueError(msg) # Close the files and clean-up _handle.close() self._effGain = conversionFactor # 1.0
def doUnitConversions(self): """Convert the data to electrons. This converts all science data extensions and saves the results back to disk. We need to make sure the data inside the chips already in memory is altered as well. """ # Image information _handle = fileutil.openImage(self._filename, mode='readonly', memmap=False) for det in range(1, self._numchips + 1, 1): chip = self._image[self.scienceExt, det] if chip._gain is not None: conversionFactor = chip._gain chip._effGain = chip._gain #1. chip._conversionFactor = conversionFactor #1. else: msg = "Invalid gain value for data, no conversion done" print(msg) raise ValueError(msg) # Close the files and clean-up _handle.close() self._effGain = conversionFactor # 1.0
def fromcalfile(filename): """ fromcalfile: function that returns a darkobject instance given the name of a cal.fits file as input. If there is no TEMPFILE keyword in the primary header of the cal.fits file or if the file specified by TEMPFILE cannot be found, a None object is returned. """ hdulist = fileutil.openImage(filename) if 'TEMPFILE' in hdulist[0].header: if tddfile == 'N/A': return None else: tddfile = hdulist[0].header['TEMPFILE'] tddhdulist = fileutil.openImage(tddfile) return darkobject(tddhdulist) else: return None
def doUnitConversions(self): """Convert the data to electrons This converts all science data extensions and saves the results back to disk. We need to make sure the data inside the chips already in memory is altered as well. """ # Image information _handle = fileutil.openImage(self._filename, mode='readonly', memmap=False) for det in range(1, self._numchips + 1, 1): chip = self._image[self.scienceExt, det] if chip._gain is not None: #conversionFactor = (self.getExpTime() * self.getGain()) conversionFactor = chip._gain if self.isCountRate(): conversionFactor *= chip._exptime counts_str = 'COUNTS/S' else: counts_str = 'COUNTS' # Multiply the values of the sci extension pixels by the gain. print("Converting %s[%s,%d] from %s to ELECTRONS" % (self._filename, self.scienceExt, det, counts_str)) """ # If the exptime is 0 the science image will be zeroed out. np.multiply(_handle[self.scienceExt,det].data,conversionFactor,_handle[self.scienceExt,det].data) #chip.data=_handle[self.scienceExt,det].data.copy() # Set the BUNIT keyword to 'electrons' chip.header.update('BUNIT','ELECTRONS') _handle[0].header.update('BUNIT','ELECTRONS') # Update the PHOTFLAM value photflam = _handle[0].header['PHOTFLAM'] _handle[0].header.update('PHOTFLAM',(photflam/chip._gain)) chip._effGain = 1.0 """ chip._effGain = chip._gain chip._conversionFactor = conversionFactor else: msg = "Invalid gain value for data, no conversion done" print(msg) raise ValueError(msg) # Close the files and clean-up _handle.close() self._effGain = conversionFactor #1.0
def fromcalfile(filename): """ fromcalfile: function that returns a darkobject instance given the name of a cal.fits file as input. If there is no TEMPFILE keyword in the primary header of the cal.fits file or if the file specified by TEMPFILE cannot be found, a None object is returned. """ hdulist = openImage(filename) if 'TEMPFILE' in hdulist[0].header: if tddfile == 'N/A': return None else: tddfile = hdulist[0].header['TEMPFILE'] tddhdulist = openImage(tddfile) return darkobject(tddhdulist) else: return None
def updateData(self,exten,data): """ Write out updated data and header to the original input file for this object. """ _extnum=self._interpretExten(exten) fimg = fileutil.openImage(self._filename,mode='update') fimg[_extnum].data = data fimg[_extnum].header = self._image[_extnum].header fimg.close()
def getHeader(self,exten=None): """ Return just the specified header extension fileutil is used instead of fits to account for non-FITS input images. openImage returns a fits object. """ _image=fileutil.openImage(self._filename,clobber=False,memmap=0) _header=fileutil.getExtn(_image,extn=exten).header _image.close() del _image return _header
def convert(file): newfilename = fileutil.buildNewRootname(file, extn='_c0h.fits') try: newimage = fileutil.openImage(file,writefits=True, fitsname=newfilename,clobber=True) del newimage return newfilename except IOError: print 'Warning: File %s could not be found' % file return None
def convert(file): newfilename = fileutil.buildFITSName(file) try: newimage = fileutil.openImage(file,writefits=True, fitsname=newfilename, clobber=True) del newimage return newfilename except IOError: print('Warning: File %s could not be found' % file) return None
def getflat(self, chip): """ Method for retrieving a detector's flat field. For STIS there are three. This method will return an array the same shape as the image. """ sci_chip = self._image[self.scienceExt, chip] exten = self.errExt + ',' + str(chip) # The keyword for STIS flat fields in the primary header of the flt lflatfile = fileutil.osfn(self._image["PRIMARY"].header['LFLTFILE']) pflatfile = fileutil.osfn(self._image["PRIMARY"].header['PFLTFILE']) # Try to open the file in the location specified by LFLTFILE. try: handle = fileutil.openImage(lflatfile, mode='readonly', memmap=False) hdu = fileutil.getExtn(handle, extn=exten) lfltdata = hdu.data if lfltdata.shape != self.full_shape: lfltdata = interp2d.expand2d(lfltdata, self.full_shape) except IOError: lfltdata = np.ones(self.full_shape, dtype=sci_chip.data.dtype) print("Cannot find file '{:s}'. Treating flatfield constant value " "of '1'.\n".format(lflatfile)) # Try to open the file in the location specified by PFLTFILE. try: handle = fileutil.openImage(pflatfile, mode='readonly', memmap=False) hdu = fileutil.getExtn(handle, extn=exten) pfltdata = hdu.data except IOError: pfltdata = np.ones(self.full_shape, dtype=sci_chip.data.dtype) print("Cannot find file '{:s}'. Treating flatfield constant value " "of '1'.\n".format(pflatfile)) flat = lfltdata * pfltdata return flat
def update_wfpc2_d2geofile(filename, fhdu=None): """ Creates a D2IMFILE from the DGEOFILE for a WFPC2 image (input), and modifies the header to reflect the new usage. Parameters ---------- filename: string Name of WFPC2 file to be processed. This file will be updated to delete any reference to a DGEOFILE and add a D2IMFILE to replace that correction when running updatewcs. fhdu: object FITS object for WFPC2 image. If user has already opened the WFPC2 file, they can simply pass that FITS object in for direct processing. Returns ------- d2imfile: string Name of D2IMFILE created from DGEOFILE. The D2IMFILE keyword in the image header will be updated/added to point to this newly created file. """ if isinstance(filename, fits.HDUList): fhdu = filename filename = fhdu.filename() close_fhdu = False else: fhdu = fileutil.openImage(filename, mode='update') close_fhdu = True dgeofile = fhdu['PRIMARY'].header.get('DGEOFILE', None) already_converted = dgeofile not in [None, "N/A", "", " "] if already_converted or 'ODGEOFIL' in fhdu['PRIMARY'].header: if not already_converted: dgeofile = fhdu['PRIMARY'].header.get('ODGEOFIL', None) logger.info('Converting DGEOFILE %s into D2IMFILE...' % dgeofile) rootname = filename[:filename.find('.fits')] d2imfile = convert_dgeo_to_d2im(dgeofile, rootname) fhdu['PRIMARY'].header['ODGEOFIL'] = dgeofile fhdu['PRIMARY'].header['DGEOFILE'] = 'N/A' fhdu['PRIMARY'].header['D2IMFILE'] = d2imfile else: d2imfile = None fhdu['PRIMARY'].header['DGEOFILE'] = 'N/A' if 'D2IMFILE' not in fhdu['PRIMARY'].header: fhdu['PRIMARY'].header['D2IMFILE'] = 'N/A' # Only close the file handle if opened in this function if close_fhdu: fhdu.close() # return the d2imfile name so that calling routine can keep # track of the new file created and delete it later if necessary # (multidrizzle clean=True mode of operation) return d2imfile
def doUnitConversions(self): """Convert the data to electrons This converts all science data extensions and saves the results back to disk. We need to make sure the data inside the chips already in memory is altered as well. """ # Image information #_handle = fileutil.openImage(self._filename,mode='update',memmap=0) _handle = fileutil.openImage(self._filename,mode='readonly') for det in range(1,self._numchips+1,1): chip=self._image[self.scienceExt,det] if chip._gain != None: #conversionFactor = (self.getExpTime() * self.getGain()) conversionFactor = chip._gain if self.isCountRate(): conversionFactor *= chip._exptime counts_str = 'COUNTS/S' else: counts_str = 'COUNTS' # Multiply the values of the sci extension pixels by the gain. print("Converting %s[%s,%d] from %s to ELECTRONS"%(self._filename,self.scienceExt,det,counts_str)) """ # If the exptime is 0 the science image will be zeroed out. np.multiply(_handle[self.scienceExt,det].data,conversionFactor,_handle[self.scienceExt,det].data) #chip.data=_handle[self.scienceExt,det].data.copy() # Set the BUNIT keyword to 'electrons' chip.header.update('BUNIT','ELECTRONS') _handle[0].header.update('BUNIT','ELECTRONS') # Update the PHOTFLAM value photflam = _handle[0].header['PHOTFLAM'] _handle[0].header.update('PHOTFLAM',(photflam/chip._gain)) chip._effGain = 1.0 """ chip._effGain = chip._gain chip._conversionFactor = conversionFactor else: msg = "Invalid gain value for data, no conversion done" print(msg) raise ValueError(msg) # Close the files and clean-up _handle.close() self._effGain = conversionFactor #1.0
def updateInputDQArray(dqfile,dq_extn,chip, crmaskname,cr_bits_value): if not isinstance(crmaskname, fits.HDUList) and not os.path.exists(crmaskname): log.warning('No CR mask file found! Input DQ array not updated.') return if cr_bits_value is None: log.warning('Input DQ array not updated!') return if isinstance(crmaskname, fits.HDUList): # in_memory case crmask = crmaskname else: crmask = fileutil.openImage(crmaskname, memmap=False) if os.path.exists(dqfile): fullext=dqfile+"["+dq_extn+str(chip)+"]" infile = fileutil.openImage(fullext, mode='update', memmap=False) __bitarray = np.logical_not(crmask[0].data).astype(np.int16) * cr_bits_value np.bitwise_or(infile[dq_extn,chip].data,__bitarray,infile[dq_extn,chip].data) infile.close() crmask.close()
def get_data(filename): fileroot,extn = fileutil.parseFilename(filename) extname = fileutil.parseExtn(extn) if extname[0] == '': extname = "PRIMARY" if os.path.exists(fileroot): handle = fileutil.openImage(filename) data = handle[extname].data handle.close() else: data = None return data
def updateInputDQArray(dqfile,dq_extn,chip, crmaskname,cr_bits_value): if not isinstance(crmaskname, fits.HDUList) and not os.path.exists(crmaskname): log.warning('No CR mask file found! Input DQ array not updated.') return if cr_bits_value == None: log.warning('Input DQ array not updated!') return if isinstance(crmaskname, fits.HDUList): # in_memory case crmask = crmaskname else: crmask = fileutil.openImage(crmaskname) if os.path.exists(dqfile): fullext=dqfile+"["+dq_extn+str(chip)+"]" infile = fileutil.openImage(fullext,mode='update') __bitarray = np.logical_not(crmask[0].data).astype(np.int16) * cr_bits_value np.bitwise_or(infile[dq_extn,chip].data,__bitarray,infile[dq_extn,chip].data) infile.close() crmask.close()
def get_data(filename): fileroot, extn = fileutil.parseFilename(filename) extname = fileutil.parseExtn(extn) if extname[0] == '': extname = "PRIMARY" if os.path.exists(fileroot): handle = fileutil.openImage(filename, memmap=False) data = handle[extname].data handle.close() else: data = None return data
def getflat(self,chip): """ Method for retrieving a detector's flat field. For STIS there are three. This method will return an array the same shape as the image. """ sci_chip = self._image[self.scienceExt,chip] exten = self.errExt+','+str(chip) # The keyword for STIS flat fields in the primary header of the flt lflatfile = fileutil.osfn(self._image["PRIMARY"].header['LFLTFILE']) pflatfile = fileutil.osfn(self._image["PRIMARY"].header['PFLTFILE']) # Try to open the file in the location specified by LFLTFILE. try: handle = fileutil.openImage(lflatfile,mode='readonly',memmap=0) hdu = fileutil.getExtn(handle,extn=exten) lfltdata = hdu.data if lfltdata.shape != self.full_shape: lfltdata = interp2d.expand2d(lfltdata,self.full_shape) except: lfltdata = np.ones(self.full_shape,dtype=sci_chip.image_dtype) str = "Cannot find file "+filename+". Treating flatfield constant value of '1'.\n" print(str) # Try to open the file in the location specified by PFLTFILE. try: handle = fileutil.openImage(pflatfile,mode='readonly',memmap=0) hdu = fileutil.getExtn(handle,extn=exten) pfltdata = hdu.data except: pfltdata = np.ones(self.image_shape,dtype=sci_chip.image_dtype) str = "Cannot find file "+filename+". Treating flatfield constant value of '1'.\n" print(str) print("lfltdata shape: ",lfltdata.shape) print("pfltdata shape: ",pfltdata.shape) flat = lfltdata * pfltdata return flat
def convert(file): newfilename = fileutil.buildFITSName(file) try: newimage = fileutil.openImage(file, writefits=True, fitsname=newfilename, clobber=True) del newimage return newfilename except IOError: print('Warning: File %s could not be found' % file) return None
def count_sci_extensions(filename): """ Return the number of SCI extensions and the EXTNAME from a input MEF file. """ num_sci = 0 extname = 'SCI' for extn in fileutil.openImage(filename): if 'extname' in extn.header and extn.header['extname'] == extname: num_sci += 1 if num_sci == 0: extname = 'PRIMARY' num_sci = 1 return num_sci, extname
def get_numsci(image): """ Find the number of SCI extensions in the image. Input: image - name of single input image """ handle = fileutil.openImage(image) num_sci = 0 for extn in handle: if 'extname' in extn.header: if extn.header['extname'].lower() == 'sci': num_sci += 1 handle.close() return num_sci
def doUnitConversions(self): """ Apply unit conversions to all the chips, ignoring the group parameter. This insures that all the chips get the same conversions when this gets done, even if only 1 chip was specified to be processed. """ # Image information _handle = fileutil.openImage(self._filename, mode='readonly', memmap=False) # Now convert the SCI array(s) units for det in range(1, self._numchips + 1): chip = self._image[self.scienceExt, det] conversionFactor = 1.0 # add D2IMFILE to outputNames for removal by 'clean()' method later if 'D2IMFILE' in _handle[0].header and _handle[0].header[ 'D2IMFILE'] not in ["", "N/A"]: chip.outputNames['d2imfile'] = _handle[0].header['D2IMFILE'] if chip._gain is not None: """ # Multiply the values of the sci extension pixels by the gain. print "Converting %s[%d] from COUNTS to ELECTRONS"%(self._filename,det) # If the exptime is 0 the science image will be zeroed out. np.multiply(_handle[self.scienceExt,det].data,chip._gain,_handle[self.scienceExt,det].data) chip.data=_handle[self.scienceExt,det].data # Set the BUNIT keyword to 'electrons' chip._bunit = 'ELECTRONS' chip.header.update('BUNIT','ELECTRONS') _handle[self.scienceExt,det].header.update('BUNIT','ELECTRONS') # Update the PHOTFLAM value photflam = _handle[self.scienceExt,det].header['PHOTFLAM'] _handle[self.scienceExt,det].header.update('PHOTFLAM',(photflam/chip._gain)) """ conversionFactor = chip._gain chip._effGain = chip._gain #1. chip._conversionFactor = conversionFactor #1. else: msg = "Invalid gain value for data, no conversion done" print(msg) raise ValueError(msg) # Close the files and clean-up _handle.close() self._effGain = conversionFactor # 1.
def convert_dgeo_to_d2im(dgeofile, output, clobber=True): """ Routine that converts the WFPC2 DGEOFILE into a D2IMFILE. """ dgeo = fileutil.openImage(dgeofile) outname = output + '_d2im.fits' removeFileSafely(outname) data = np.array([dgeo['dy', 1].data[:, 0]]) scihdu = fits.ImageHDU(data=data) dgeo.close() # add required keywords for D2IM header scihdu.header['EXTNAME'] = ('DY', 'Extension name') scihdu.header['EXTVER'] = (1, 'Extension version') fits_str = 'PYFITS Version ' + str(astropy.__version__) scihdu.header['ORIGIN'] = (fits_str, 'FITS file originator') scihdu.header['INHERIT'] = (False, 'Inherits global header') dnow = datetime.datetime.now() scihdu.header['DATE'] = (str(dnow).replace(' ', 'T'), 'Date FITS file was generated') scihdu.header['CRPIX1'] = (0, 'Distortion array reference pixel') scihdu.header['CDELT1'] = (1, 'Grid step size in first coordinate') scihdu.header['CRVAL1'] = (0, 'Image array pixel coordinate') scihdu.header['CRPIX2'] = (0, 'Distortion array reference pixel') scihdu.header['CDELT2'] = (1, 'Grid step size in second coordinate') scihdu.header['CRVAL2'] = (0, 'Image array pixel coordinate') phdu = fits.PrimaryHDU() phdu.header['INSTRUME'] = 'WFPC2' d2imhdu = fits.HDUList() d2imhdu.append(phdu) scihdu.header['DETECTOR'] = (1, 'CCD number of the detector: PC 1, WFC 2-4 ') d2imhdu.append(scihdu.copy()) scihdu.header['EXTVER'] = (2, 'Extension version') scihdu.header['DETECTOR'] = (2, 'CCD number of the detector: PC 1, WFC 2-4 ') d2imhdu.append(scihdu.copy()) scihdu.header['EXTVER'] = (3, 'Extension version') scihdu.header['DETECTOR'] = (3, 'CCD number of the detector: PC 1, WFC 2-4 ') d2imhdu.append(scihdu.copy()) scihdu.header['EXTVER'] = (4, 'Extension version') scihdu.header['DETECTOR'] = (4, 'CCD number of the detector: PC 1, WFC 2-4 ') d2imhdu.append(scihdu.copy()) d2imhdu.writeto(outname) d2imhdu.close() return outname
def getflat(self, chip): """ Method for retrieving a detector's flat field. Returns ------- flat: array This method will return an array the same shape as the image in **units of electrons**. """ sci_chip = self._image[self.scienceExt, chip] # The keyword for ACS flat fields in the primary header of the flt # file is pfltfile. This flat file is already in the required # units of electrons. # The use of fileutil.osfn interprets any environment variable, such as # jref$, used in the specification of the reference filename filename = fileutil.osfn(self._image["PRIMARY"].header[self.flatkey]) hdulist = None try: hdulist = fileutil.openImage(filename, mode='readonly', memmap=False) data = hdulist[(self.scienceExt, chip)].data if data.shape[0] != sci_chip.image_shape[0]: ltv2 = int(np.round(sci_chip.ltv2)) else: ltv2 = 0 size2 = sci_chip.image_shape[0] + ltv2 if data.shape[1] != sci_chip.image_shape[1]: ltv1 = int(np.round(sci_chip.ltv1)) else: ltv1 = 0 size1 = sci_chip.image_shape[1] + ltv1 flat = data[ltv2:size2, ltv1:size1] except FileNotFoundError: flat = np.ones(sci_chip.image_shape, dtype=sci_chip.image_dtype) log.warning("Cannot find flat field file '{}'".format(filename)) log.warning("Treating flatfield as a constant value of '1'.") finally: if hdulist is not None: hdulist.close() return flat
def _updateKW(image, filename, exten, skyKW, Value): """update the header with the kw,value""" # Update the value in memory image.header[skyKW] = Value # Now update the value on disk if isinstance(exten,tuple): strexten = '[%s,%s]'%(exten[0],str(exten[1])) else: strexten = '[%s]'%(exten) log.info('Updating keyword %s in %s' % (skyKW, filename + strexten)) fobj = fileutil.openImage(filename, mode='update') fobj[exten].header[skyKW] = (Value, 'Sky value computed by AstroDrizzle') fobj.close()
def _updateKW(image, filename, exten, skyKW, Value): """update the header with the kw,value""" # Update the value in memory image.header[skyKW] = Value # Now update the value on disk if isinstance(exten, tuple): strexten = '[%s,%s]' % (exten[0], str(exten[1])) else: strexten = '[%s]' % (exten) log.info('Updating keyword %s in %s' % (skyKW, filename + strexten)) fobj = fileutil.openImage(filename, mode='update', memmap=False) fobj[exten].header[skyKW] = (Value, 'Sky value computed by AstroDrizzle') fobj.close()
def doUnitConversions(self): """ Apply unit conversions to all the chips, ignoring the group parameter. This insures that all the chips get the same conversions when this gets done, even if only 1 chip was specified to be processed. """ # Image information #_handle = fileutil.openImage(self._filename,mode='update',memmap=0) _handle = fileutil.openImage(self._filename,mode='readonly') # Now convert the SCI array(s) units for det in range(1,self._numchips+1): chip=self._image[self.scienceExt,det] conversionFactor = 1.0 # add D2IMFILE to outputNames for removal by 'clean()' method later if 'D2IMFILE' in _handle[0].header and _handle[0].header['D2IMFILE'] not in ["","N/A"]: chip.outputNames['d2imfile'] = _handle[0].header['D2IMFILE'] if chip._gain != None: """ # Multiply the values of the sci extension pixels by the gain. print "Converting %s[%d] from COUNTS to ELECTRONS"%(self._filename,det) # If the exptime is 0 the science image will be zeroed out. np.multiply(_handle[self.scienceExt,det].data,chip._gain,_handle[self.scienceExt,det].data) chip.data=_handle[self.scienceExt,det].data # Set the BUNIT keyword to 'electrons' chip._bunit = 'ELECTRONS' chip.header.update('BUNIT','ELECTRONS') _handle[self.scienceExt,det].header.update('BUNIT','ELECTRONS') # Update the PHOTFLAM value photflam = _handle[self.scienceExt,det].header['PHOTFLAM'] _handle[self.scienceExt,det].header.update('PHOTFLAM',(photflam/chip._gain)) """ conversionFactor = chip._gain chip._effGain = chip._gain #1. chip._conversionFactor = conversionFactor #1. else: msg = "Invalid gain value for data, no conversion done" print(msg) raise ValueError(msg) # Close the files and clean-up _handle.close() self._effGain = conversionFactor # 1.
def buildIVMmask(self,chip,dqarr,scale): """ Builds a weight mask from an input DQ array and either an IVM array provided by the user or a self-generated IVM array derived from the flat-field reference file associated with the input image. """ sci_chip = self._image[self.scienceExt,chip] ivmname = self.outputNames['ivmFile'] if ivmname != None: log.info("Applying user supplied IVM files for chip %s" % chip) #Parse the input file name to get the extension we are working on extn = "IVM,{}".format(chip) #Open the mask image for updating and the IVM image ivm = fileutil.openImage(ivmname, mode='readonly') ivmfile = fileutil.getExtn(ivm, extn) # Multiply the IVM file by the input mask in place. ivmarr = ivmfile.data * dqarr ivm.close() else: log.info("Automatically creating IVM files for chip %s" % chip) # If no IVM files were provided by the user we will # need to automatically generate them based upon # instrument specific information. flat = self.getflat(chip) RN = self.getReadNoiseImage(chip) darkimg = self.getdarkimg(chip) skyimg = self.getskyimg(chip) #exptime = self.getexptimeimg(chip) #exptime = sci_chip._exptime #ivm = (flat*exptime)**2/(darkimg+(skyimg*flat)+RN**2) ivm = (flat)**2/(darkimg+(skyimg*flat)+RN**2) # Multiply the IVM file by the input mask in place. ivmarr = ivm * dqarr # Update 'wt_scl' parameter to match use of IVM file sci_chip._wtscl = pow(sci_chip._exptime,2)/pow(scale,4) #sci_chip._wtscl = 1.0/pow(scale,4) return ivmarr.astype(np.float32)
def convertImageToSFITS(fname): """ Convert the input filename (possibly with extensions already specified) into a separate simple FITS file for each SCI extension. If fname refers to a simple FITS file already, list will only contain fname. """ flist = [] # Extract any extension specifications rootname, extn = fileutil.parseFilename(fname) if extn == None: # Check to see if file is multi-extension fimg = fileutil.openImage(fname) if len(fimg) > 1: # We have multiextension FITS, so write out # each SCI extension as a separate simple # FITS file. for hdu in fimg: if 'extname' in hdu.header and hdu.header['extname'] == 'SCI': extname = hdu.header['extname'].lower() + str( hdu.header['extver']) new_fname = rootname[:rootname.rfind( '.fits')] + '_extract_' + extname + '.fits' removeFile(new_fname) flist.append([new_fname, fname]) phdu = pyfits.PrimaryHDU(header=hdu.header, data=hdu.data) phdu.writeto(new_fname) del phdu else: # We already have a simple FITS, just record its name flist.append([None, fname]) fimg.close() del fimg else: # We have an image with a SCI extension specified split_extn = extn.split(',') extname = str(split_extn[0]) + str(split_extn[1]) new_fname = rootname[:rootname. rfind('.fits')] + '_extract_' + extname + '.fits' removeFile(new_fname) iraf.imcopy(fname, new_fname, verbose=no) flist.append([new_fname, fname]) return flist
def getflat(self, chip): """ Method for retrieving a detector's flat field. Returns ------- flat: array This method will return an array the same shape as the image in **units of electrons**. """ sci_chip = self._image[self.scienceExt, chip] exten = '%s,%d' % (self.scienceExt, chip) # The keyword for ACS flat fields in the primary header of the flt # file is pfltfile. This flat file is already in the required # units of electrons. # The use of fileutil.osfn interprets any environment variable, such as jref$, # used in the specification of the reference filename filename = fileutil.osfn(self._image["PRIMARY"].header[self.flatkey]) try: handle = fileutil.openImage(filename, mode='readonly', memmap=False) hdu = fileutil.getExtn(handle, extn=exten) if hdu.data.shape[0] != sci_chip.image_shape[0]: _ltv2 = np.round(sci_chip.ltv2) else: _ltv2 = 0 _size2 = sci_chip.image_shape[0] + _ltv2 if hdu.data.shape[1] != sci_chip.image_shape[1]: _ltv1 = np.round(sci_chip.ltv1) else: _ltv1 = 0 _size1 = sci_chip.image_shape[1] + _ltv1 data = hdu.data[_ltv2:_size2, _ltv1:_size1] handle.close() except: data = np.ones(sci_chip.image_shape, dtype=sci_chip.image_dtype) log.warning("Cannot find file %s.\n Treating flatfield " "constant value of '1'." % filename) flat = data return flat
def getflat(self, chip): """ Method for retrieving a detector's flat field. Returns ------- flat: array This method will return an array the same shape as the image in **units of electrons**. """ sci_chip = self._image[self.scienceExt, chip] exten = '%s,%d' % (self.scienceExt, chip) # The keyword for ACS flat fields in the primary header of the flt # file is pfltfile. This flat file is already in the required # units of electrons. # The use of fileutil.osfn interprets any environment variable, such as jref$, # used in the specification of the reference filename filename = fileutil.osfn(self._image["PRIMARY"].header[self.flatkey]) try: handle = fileutil.openImage(filename, mode='readonly', memmap=0) hdu = fileutil.getExtn(handle,extn=exten) if hdu.data.shape[0] != sci_chip.image_shape[0]: _ltv2 = np.round(sci_chip.ltv2) else: _ltv2 = 0 _size2 = sci_chip.image_shape[0]+_ltv2 if hdu.data.shape[1] != sci_chip.image_shape[1]: _ltv1 = np.round(sci_chip.ltv1) else: _ltv1 = 0 _size1 = sci_chip.image_shape[1]+_ltv1 data = hdu.data[_ltv2:_size2, _ltv1:_size1] handle.close() except: data = np.ones(sci_chip.image_shape, dtype=sci_chip.image_dtype) log.warning("Cannot find file %s.\n Treating flatfield " "constant value of '1'." % filename) flat = data return flat
def getDGEOArrays(self): """ Return numpy objects for the distortion correction image arrays. If no DGEOFILE is specified, it will return empty 2x2 arrays. """ # Instantiate array objects for distortion correction image arrays if self.xgeoim == '': # No distortion image specified. # Defaulting to empty 2x2 array. xgdim = ygdim = 2 _pxg = np.zeros((ygdim,xgdim),dtype=np.float32) _pyg = np.zeros((ygdim,xgdim),dtype=np.float32) else: # Open distortion correction FITS file _xgfile = fileutil.openImage(self.xgeoim) #_xgfile.info() # Access the extensions which correspond to this Exposure _xgname,_xgext = fileutil.parseFilename(self.xgeoim) _ygname,_ygext = fileutil.parseFilename(self.ygeoim) _pxgext = fileutil.getExtn(_xgfile,extn=_xgext) _pygext = fileutil.getExtn(_xgfile,extn=_ygext) # Copy out the numpy objects for output _ltv1 = int(self.geometry.wcs.offset_x) _ltv2 = int(self.geometry.wcs.offset_y) if _ltv1 != 0. or _ltv2 != 0.: # subarray section only _pxg = _pxgext.data[_ltv2:_ltv2+self.naxis2,_ltv1:_ltv1+self.naxis1].copy() _pyg = _pygext.data[_ltv2:_ltv2+self.naxis2,_ltv1:_ltv1+self.naxis1].copy() else: # full array _pxg = _pxgext.data.copy() _pyg = _pygext.data.copy() # Close file handles now... _xgfile.close() del _xgfile return _pxg,_pyg
def count_sci_extensions(filename): """ Return the number of SCI extensions and the EXTNAME from a input MEF file. """ num_sci = 0 extname = 'SCI' hdu_list = fileutil.openImage(filename, memmap=False) for extn in hdu_list: if 'extname' in extn.header and extn.header['extname'] == extname: num_sci += 1 if num_sci == 0: extname = 'PRIMARY' num_sci = 1 hdu_list.close() return num_sci, extname
def count_sci_extensions(filename): """ Return the number of SCI extensions and the EXTNAME from a input MEF file. """ num_sci = 0 extname = 'SCI' hdu_list = fileutil.openImage(filename, memmap=False) for extn in hdu_list: if 'extname' in extn.header and extn.header['extname'] == extname: num_sci += 1 if num_sci == 0: extname = 'PRIMARY' num_sci = 1 hdu_list.close() return num_sci,extname
def doUnitConversions(self): """WF3 IR data come out in electrons, and I imagine the photometry keywords will be calculated as such, so no image manipulation needs be done between native and electrons """ # Image information _handle = fileutil.openImage(self._filename, mode='readonly', memmap=False) for chip in self.returnAllChips(extname=self.scienceExt): conversionFactor = 1.0 if '/S' in chip._bunit: conversionFactor = chip._exptime else: print("Input %s[%s,%d] already in units of ELECTRONS" %(self._filename,self.scienceExt,chip._chip)) chip._effGain = 1.0# chip._gain #1. chip._conversionFactor = conversionFactor #1. _handle.close() self._effGain= 1.0 #conversionFactor #1.0
def mergeDQarray(maskname, dqarr): """ Merge static or CR mask with mask created from DQ array on-the-fly here. """ maskarr = None if maskname is not None: if isinstance(maskname, str): # working with file on disk (default case) if os.path.exists(maskname): mask = fileutil.openImage(maskname, memmap=False) maskarr = mask[0].data.astype(bool) mask.close() else: if isinstance(maskname, fits.HDUList): # working with a virtual input file maskarr = maskname[0].data.astype(bool) else: maskarr = maskname.data.astype(bool) if maskarr is not None: # merge array with dqarr now np.bitwise_and(dqarr, maskarr, dqarr)
def getNrefchip(image,instrument='WFPC2'): """ This handles the fact that WFPC2 subarray observations may not include chip 3 which is the default reference chip for full observations. Also for subarrays chip 3 may not be the third extension in a MEF file. It is a kludge but this whole module is one big kludge. ND """ hdu = fileutil.openImage(image) if instrument == 'WFPC2': detectors = [img.header['DETECTOR'] for img in hdu[1:]] if 3 not in detectors: Nrefchip=detectors[0] Nrefext = 1 else: Nrefchip = 3 Nrefext = detectors.index(3) + 1 hdu.close() return Nrefchip, Nrefext
def mergeDQarray(maskname,dqarr): """ Merge static or CR mask with mask created from DQ array on-the-fly here. """ maskarr = None if maskname is not None: if isinstance(maskname, str): # working with file on disk (default case) if os.path.exists(maskname): mask = fileutil.openImage(maskname) maskarr = mask[0].data.astype(np.bool) mask.close() else: if isinstance(maskname, fits.HDUList): # working with a virtual input file maskarr = maskname[0].data.astype(np.bool) else: maskarr = maskname.data.astype(np.bool) if maskarr is not None: # merge array with dqarr now np.bitwise_and(dqarr,maskarr,dqarr)
def getDGEOExtn(self): """ Builds filename with extension to access distortion correction image extension appropriate to each chip. """ # If no DGEOFILE has been given, then simply return blanks # and 'drizzle' will not use any. if not self.dgeoname or self.dgeoname == 'N/A': return '','' # Open file for introspection. fimg = fileutil.openImage(self.dgeoname) dx_extver = None dy_extver = None # Find which extensions match this chip ID # We need to identify both a DX and DY EXTNAME extension for hdu in fimg: hdr = hdu.header if 'CCDCHIP' not in hdr: _chip = 1 else: _chip = int(hdr['CCDCHIP']) if 'EXTNAME' in hdr: _extname = hdr['EXTNAME'].lower() if _chip == int(self.chip): if _extname == 'dx': dx_extver = hdr['EXTVER'] if _extname == 'dy': dy_extver = hdr['EXTVER'] fimg.close() del fimg # Set the name for each extension here... _dxgeo = self.dgeoname+'[DX,'+str(dx_extver)+']' _dygeo = self.dgeoname+'[DY,'+str(dy_extver)+']' return _dxgeo,_dygeo
def _addDefaultSkyKW(imageObjList): """Add MDRIZSKY keyword to "commanded" SCI headers of all input images, if that keyword does not already exist. """ skyKW = "MDRIZSKY" Value = 0.0 for imageSet in imageObjList: fname = imageSet._filename numchips=imageSet._numchips sciExt=imageSet.scienceExt fobj = fileutil.openImage(fname, mode='update') for chip in range(1,numchips+1,1): ext = (sciExt,chip) if not imageSet[ext].group_member: # skip over extensions not used in processing continue if skyKW not in fobj[ext].header: fobj[ext].header[skyKW] = (Value, 'Sky value computed by AstroDrizzle') log.info("MDRIZSKY keyword not found in the %s[%s,%d] header."%( fname,sciExt,chip)) log.info(" Adding MDRIZSKY to header with default value of 0.") fobj.close()
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 __init__(self,filename,group=None,inmemory=False): baseImageObject.__init__(self,filename) #filutil open returns a fits object try: self._image=fileutil.openImage(filename,clobber=False,memmap=0) except IOError: raise IOError("Unable to open file: %s" % filename) #populate the global attributes which are good for all the chips in the file #self._rootname=self._image['PRIMARY'].header["ROOTNAME"] self._rootname=fileutil.buildNewRootname(filename) self.outputNames=self._setOutputNames(self._rootname) # flag to indicate whether or not to write out intermediate products # to disk (default) or keep everything in memory self.inmemory = inmemory self._initVirtualOutputs() #self._exptime=self._image["PRIMARY"].header["EXPTIME"] #exptime should be set in the image subclass code since it's kept in different places # if(self._exptime == 0): self._exptime =1. #to avoid divide by zero # print "Setting exposure time to 1. to avoid div/0!" #this is the number of science chips to be processed in the file self._numchips=self._countEXT(extname=self.scienceExt) self.proc_unit = None #self._nextend=self._image["PRIMARY"].header["NEXTEND"] self._nextend = self._countEXT(extname=None) if (self._numchips == 0): #the simple fits image contains the data in the primary extension, #this will help us deal with the rest of the code that looks #and acts on chips :) #self._nextend=1 self._numchips=1 self.scienceExt="PRIMARY" self.maskExt=None self._image["PRIMARY"].header["EXTNAME"] = "PRIMARY" self._image["PRIMARY"].header["EXTVER"] = 1 self._image["PRIMARY"].extnum = 0 self._isSimpleFits = False # Clean out any stray MDRIZSKY keywords from PRIMARY headers fimg = fileutil.openImage(filename,mode='update') if 'MDRIZSKY' in fimg['PRIMARY'].header: del fimg['PRIMARY'].header['MDRIZSKY'] fimg.close() del fimg if group not in [None,'']: # Only use selected chip if ',' in group: group_id = group.split(',') if group_id[0].isalpha(): # user specified a specific extname,extver self.group = [int(group_id[1])] else: # user specified a list of extension numbers to process self.group = [] for grp in group_id: # find extname/extver which corresponds to this extension number group_extname = self._image[int(grp)].header['EXTNAME'] group_extver = self._image[int(grp)].header['EXTVER'] self.group.append(group_extver) else: # find extname/extver which corresponds to this extension number group_extver = self._image[int(group)].header['EXTVER'] self.group = [int(group_extver)] else: # Use all chips self.group = None if not self._isSimpleFits: #assign chip specific information for chip in range(1,self._numchips+1,1): self._assignRootname(chip) sci_chip = self._image[self.scienceExt,chip] # Set a flag to indicate whether this chip should be included # or not, based on user input from the 'group' parameter. if self.group is None or (self.group is not None and chip in self.group): sci_chip.group_member = True self._nmembers += 1 else: sci_chip.group_member = False sci_chip.signature = None sci_chip.dqname = None sci_chip.dqmaskname = None sci_chip.dqfile,sci_chip.dq_extn = self.find_DQ_extension() #self.maskExt = sci_chip.dq_extn if(sci_chip.dqfile != None): sci_chip.dqname = sci_chip.dqfile +'['+sci_chip.dq_extn+','+str(chip)+']' # build up HSTWCS object for each chip, which will be necessary for drizzling operations sci_chip.wcs=wcs_functions.get_hstwcs(self._filename,self._image,sci_chip.extnum) sci_chip.detnum,sci_chip.binned = util.get_detnum(sci_chip.wcs,self._filename,chip) sci_chip.wcslin_pscale = 1.0 #assuming all the chips don't have the same dimensions in the file sci_chip._naxis1=sci_chip.header["NAXIS1"] sci_chip._naxis2=sci_chip.header["NAXIS2"] # record the exptime values for this chip so that it can be # easily used to generate the composite value for the final output image sci_chip._expstart,sci_chip._expend = util.get_expstart(sci_chip.header,self._image['PRIMARY'].header) sci_chip.outputNames=self._setChipOutputNames(sci_chip.rootname,chip).copy() #this is a dictionary # Set the units: both bunit and in_units self.set_units(chip) #initialize gain, readnoise, and exptime attributes # the actual values will be set by each instrument based on # keyword names specific to that instrument by 'setInstrumentParamters()' sci_chip._headergain = 1 # gain value read from header sci_chip._gain = 1.0 # calibrated gain value sci_chip._rdnoise = 1.0 # calibrated readnoise sci_chip._exptime = 1.0 sci_chip._effGain = 1.0 sci_chip._conversionFactor = 1.0 sci_chip._wtscl = 1.0 # Keep track of the sky value that should be subtracted from this chip # Read in value from image header, in case user has already # determined the sky level if "MDRIZSKY" in sci_chip.header: subsky = sci_chip.header['MDRIZSKY'] log.info('Reading in MDRIZSKY of %s' % subsky) else: subsky = 0.0 # .computedSky: value to be applied by the # adrizzle/ablot steps. # .subtractedSky: value already (or will be by adrizzle/ablot) # subtracted from the image sci_chip.subtractedSky = subsky sci_chip.computedSky = subsky sci_chip.darkcurrent = 0.0 # The following attributes are used when working with sub-arrays # and get reference file arrays for auto-generation of IVM masks try: sci_chip.ltv1 = sci_chip.header['LTV1'] * -1 sci_chip.ltv2 = sci_chip.header['LTV2'] * -1 except KeyError: sci_chip.ltv1 = 0 sci_chip.ltv2 = 0 if sci_chip.ltv1 < 0: sci_chip.ltv1 = 0 if sci_chip.ltv2 < 0: sci_chip.ltv2 = 0 sci_chip.size1 = sci_chip.header['NAXIS1'] + np.round(sci_chip.ltv1) sci_chip.size2 = sci_chip.header['NAXIS2'] + np.round(sci_chip.ltv2) #sci_chip.image_shape = (sci_chip.size2,sci_chip.size1) sci_chip.image_shape = (sci_chip.header['NAXIS2'],sci_chip.header['NAXIS1']) # Interpret the array dtype by translating the IRAF BITPIX value for dtype in IRAF_DTYPES.keys(): if sci_chip.header['BITPIX'] == IRAF_DTYPES[dtype]: sci_chip.image_dtype = dtype break if self.inmemory: # read image data array into memory shape = sci_chip.data.shape
def run_blot(imageObjectList, output_wcs, paramDict, wcsmap=wcs_functions.WCSMap): """ run_blot(imageObjectList, output_wcs, paramDict, wcsmap=wcs_functions.WCSMap) Perform the blot operation on the list of images. """ # Insure that input imageObject is a list if not isinstance(imageObjectList, list): imageObjectList = [imageObjectList] # # Setup the versions info dictionary for output to PRIMARY header # The keys will be used as the name reported in the header, as-is # _versions = { 'AstroDrizzle': __version__, 'PyFITS': util.__fits_version__, 'Numpy': util.__numpy_version__ } _hdrlist = [] for img in imageObjectList: for chip in img.returnAllChips(extname=img.scienceExt): print(' Blot: creating blotted image: ', chip.outputNames['data']) #### Check to see what names need to be included here for use in _hdrlist chip.outputNames['driz_version'] = _versions['AstroDrizzle'] outputvals = chip.outputNames.copy() outputvals.update(img.outputValues) outputvals['blotnx'] = chip.wcs.naxis1 outputvals['blotny'] = chip.wcs.naxis2 _hdrlist.append(outputvals) plist = outputvals.copy() plist.update(paramDict) # PyFITS can be used here as it will always operate on # output from PyDrizzle (which will always be a FITS file) # Open the input science file medianPar = 'outMedian' outMedianObj = img.getOutputName(medianPar) if img.inmemory: outMedian = img.outputNames[medianPar] _fname, _sciextn = fileutil.parseFilename(outMedian) _inimg = outMedianObj else: outMedian = outMedianObj _fname, _sciextn = fileutil.parseFilename(outMedian) _inimg = fileutil.openImage(_fname, memmap=False) # Return the PyFITS HDU corresponding to the named extension _scihdu = fileutil.getExtn(_inimg, _sciextn) _insci = _scihdu.data.copy() _inimg.close() del _inimg, _scihdu _outsci = do_blot(_insci, output_wcs, chip.wcs, chip._exptime, coeffs=paramDict['coeffs'], interp=paramDict['blot_interp'], sinscl=paramDict['blot_sinscl'], wcsmap=wcsmap) # Apply sky subtraction and unit conversion to blotted array to # match un-modified input array if paramDict['blot_addsky']: skyval = chip.computedSky else: skyval = paramDict['blot_skyval'] _outsci /= chip._conversionFactor if skyval is not None: _outsci += skyval log.info('Applying sky value of %0.6f to blotted image %s' % (skyval, chip.outputNames['data'])) # Write output Numpy objects to a PyFITS file # Blotting only occurs from a drizzled SCI extension # to a blotted SCI extension... _outimg = outputimage.OutputImage(_hdrlist, paramDict, build=False, wcs=chip.wcs, blot=True) _outimg.outweight = None _outimg.outcontext = None outimgs = _outimg.writeFITS(plist['data'], _outsci, None, versions=_versions, blend=False, virtual=img.inmemory) img.saveVirtualOutputs(outimgs) #_buildOutputFits(_outsci,None,plist['outblot']) _hdrlist = [] del _outsci del _outimg
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 getSingleTemplate(fname, extlist=['SCI', 'ERR', 'DQ']): """ # Obtain default headers for output file based on a single input file # (Copied from outputimage module.) # Returns ------- headers : tuple of `astropy.io.fits.Header` objects, not HDU objects! headers """ if fname is None: raise ValueError('No data files for creating FITS output.') froot, fextn = fileutil.parseFilename(fname) if fextn is not None: fnum = fileutil.parseExtn(fextn)[1] ftemplate = fileutil.openImage(froot, mode='readonly') prihdr = ftemplate['PRIMARY'].header.copy() try: del prihdr['pcount'] del prihdr['gcount'] except KeyError: pass if fname.find('.fits') > 0 and len(ftemplate) > 1: # Setup which keyword we will use to select each # extension... _extkey = 'EXTNAME' defnum = fileutil.findKeywordExtn(ftemplate, _extkey, extlist[0]) # # Now, extract the headers necessary for output (as copies) # 1. Find the SCI extension in the template image # 2. Make a COPY of the extension header for use in new output file if fextn is None: extnum = fileutil.findKeywordExtn(ftemplate, _extkey, extlist[0]) else: extnum = (extlist[0], fnum) #scihdr = fits.Header(cards=ftemplate[extnum].header.ascard.copy()) scihdr = fits.Header(ftemplate[extnum].header.copy()) #scihdr.update('extver',1) extnum_sci = extnum # Extract the header for additional extensions if len(extlist) > 1 and extlist[1] not in [ None, '', ' ', 'INDEF', 'None' ]: if fextn is None: extnum = fileutil.findKeywordExtn(ftemplate, _extkey, extlist[1]) else: # there may or may not be a second type of extension in the template count = 0 for f in ftemplate: if 'extname' in f.header and f.header[ 'extname'] == extlist[1]: count += 1 if count > 0: extnum = (extlist[1], fnum) else: # Use science header for remaining headers extnum = (extlist[0], fnum) else: extnum = extnum_sci #errhdr = fits.Header(cards=ftemplate[extnum].header.ascard.copy()) errhdr = fits.Header(ftemplate[extnum].header.copy()) #errhdr.update('extver',1) errhdr['bunit'] = 'UNITLESS' if len(extlist) > 2 and extlist[2] not in [ None, '', ' ', 'INDEF', 'None' ]: if fextn is None: extnum = fileutil.findKeywordExtn(ftemplate, _extkey, extlist[2]) else: count = 0 for f in ftemplate: if 'extname' in f.header and f.header[ 'extname'] == extlist[2]: count += 1 if count > 0: extnum = (extlist[2], fnum) else: # Use science header for remaining headers extnum = (extlist[0], fnum) else: extnum = extnum_sci #dqhdr = fits.Header(cards=ftemplate[extnum].header.ascard.copy()) dqhdr = fits.Header(ftemplate[extnum].header.copy()) #dqhdr.update('extver',1) dqhdr['bunit'] = 'UNITLESS' else: # Create default headers from scratch scihdr = None errhdr = None dqhdr = None ftemplate.close() del ftemplate return prihdr, scihdr, errhdr, dqhdr