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 __getitem__(self,exten): """ Overload getitem to return the data and header these only work on the HDU list already in memory once the data has been zero's in self._image you should use getData or getHeader to re-read the file. """ return fileutil.getExtn(self._image,extn=exten)
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 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 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 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 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 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 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 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 _update(image,idctab,nimsets,apply_tdd=False, quiet=None,instrument=None,prepend=None,nrchip=None, nrext=None): tdd_xyref = {1: [2048, 3072], 2:[2048, 1024]} _prepend = prepend _dqname = None # Make a copy of the header for keyword access # This copy includes both Primary header and # extension header hdr = fileutil.getHeader(image) # Try to get the instrument if we don't have it already instrument = readKeyword(hdr,'INSTRUME') binned = 1 # Read in any specified OFFTAB, if present (WFPC2) offtab = readKeyword(hdr,'OFFTAB') dateobs = readKeyword(hdr,'DATE-OBS') if not quiet: print("OFFTAB, DATE-OBS: ",offtab,dateobs) print("-Updating image ",image) if not quiet: print("-Reading IDCTAB file ",idctab) # Get telescope orientation from image header # If PA_V# is not present of header, try to get it from the spt file pvt = readKeyword(hdr,'PA_V3') if pvt == None: sptfile = fileutil.buildNewRootname(image, extn='_spt.fits') if os.path.exists(sptfile): spthdr = fileutil.getHeader(sptfile) pvt = readKeyword(spthdr,'PA_V3') if pvt != None: pvt = float(pvt) else: print('PA_V3 keyword not found, WCS cannot be updated. Quitting ...') raise ValueError # Find out about instrument, detector & filters detector = readKeyword(hdr,'DETECTOR') Nrefchip=1 if instrument == 'WFPC2': filter1 = readKeyword(hdr,'FILTNAM1') filter2 = readKeyword(hdr,'FILTNAM2') mode = readKeyword(hdr,'MODE') if os.path.exists(fileutil.buildNewRootname(image, extn='_c1h.fits')): _dqname = fileutil.buildNewRootname(image, extn='_c1h.fits') dqhdr = pyfits.getheader(_dqname,1) dqext = readKeyword(dqhdr, 'EXTNAME') if mode == 'AREA': binned = 2 Nrefchip=nrchip elif instrument == 'NICMOS': filter1 = readKeyword(hdr,'FILTER') filter2 = None elif instrument == 'WFC3': filter1 = readKeyword(hdr,'FILTER') filter2 = None # use value of 'BINAXIS' keyword to set binning value for WFC3 data binned = readKeyword(hdr,'BINAXIS1') else: filter1 = readKeyword(hdr,'FILTER1') filter2 = readKeyword(hdr,'FILTER2') if filter1 == None or filter1.strip() == '': filter1 = 'CLEAR' else: filter1 = filter1.strip() if filter2 == None or filter2.strip() == '': filter2 = 'CLEAR' else: filter2 = filter2.strip() if filter1.find('CLEAR') == 0: filter1 = 'CLEAR' if filter2.find('CLEAR') == 0: filter2 = 'CLEAR' # Set up parity matrix for chip if instrument == 'WFPC2' or instrument =='STIS' or instrument == 'NICMOS': parity = PARITY[instrument] elif detector in PARITY: parity = PARITY[detector] else: raise ValueError('Detector ',detector, ' Not supported at this time. Exiting...') # Get the VAFACTOR keyword if it exists, otherwise set to 1.0 # we also need the reference pointing position of the target # as this is where _va_key = readKeyword(hdr,'VAFACTOR') if _va_key != None: VA_fac = float(_va_key) else: VA_fac=1.0 if not quiet: print('VA factor: ',VA_fac) #ra_targ = float(readKeyword(hdr,'RA_TARG')) #dec_targ = float(readKeyword(hdr,'DEC_TARG')) # Get the chip number _c = readKeyword(hdr,'CAMERA') _s = readKeyword(hdr,'CCDCHIP') _d = readKeyword(hdr,'DETECTOR') if _c != None and str(_c).isdigit(): chip = int(_c) elif _s == None and _d == None: chip = 1 else: if _s: chip = int(_s) elif str(_d).isdigit(): chip = int(_d) else: chip = 1 # For the ACS/WFC case the chip number doesn't match the image # extension nr = 1 if (instrument == 'ACS' and detector == 'WFC') or (instrument == 'WFC3' and detector == 'UVIS'): if nimsets > 1: Nrefchip = 2 else: Nrefchip = chip elif instrument == 'NICMOS': Nrefchip = readKeyword(hdr,'CAMERA') elif instrument == 'WFPC2': nr = nrext else: if nimsets > 1: nr = Nrefchip if not quiet: print("-PA_V3 : ",pvt," CHIP #",chip) # Extract the appropriate information from the IDCTAB #fx,fy,refpix,order=fileutil.readIDCtab(idctab,chip=chip,direction='forward', # filter1=filter1,filter2=filter2,offtab=offtab,date=dateobs) idcmodel = models.IDCModel(idctab, chip=chip, direction='forward', date=dateobs, filter1=filter1, filter2=filter2, offtab=offtab, binned=binned, tddcorr=apply_tdd) fx = idcmodel.cx fy = idcmodel.cy refpix = idcmodel.refpix order = idcmodel.norder # Determine whether to perform time-dependent correction # Construct matrices neded to correct the zero points for TDD if apply_tdd: #alpha,beta = mutil.compute_wfc_tdd_coeffs(dateobs,skew_coeffs) alpha = refpix['TDDALPHA'] beta = refpix['TDDBETA'] tdd = N.array([[beta, alpha], [alpha, -beta]]) mrotp = fileutil.buildRotMatrix(2.234529)/2048. else: alpha = 0.0 beta = 0.0 # Get the original image WCS Old=wcsutil.WCSObject(image,prefix=_prepend) # Reset the WCS keywords to original archived values. Old.restore() # # Look for any subarray offset # ltv1,ltv2 = drutil.getLTVOffsets(image) # # If reference point is not centered on distortion model # shift coefficients to be applied relative to observation # reference position # offsetx = Old.crpix1 - ltv1 - refpix['XREF'] offsety = Old.crpix2 - ltv2 - refpix['YREF'] shiftx = refpix['XREF'] + ltv1 shifty = refpix['YREF'] + ltv2 if ltv1 != 0. or ltv2 != 0.: ltvoffx = ltv1 + offsetx ltvoffy = ltv2 + offsety offshiftx = offsetx + shiftx offshifty = offsety + shifty else: ltvoffx = 0. ltvoffy = 0. offshiftx = 0. offshifty = 0. if ltv1 != 0. or ltv2 != 0.: fx,fy = idcmodel.shift(idcmodel.cx,idcmodel.cy,offsetx,offsety) # Extract the appropriate information for reference chip ridcmodel = models.IDCModel(idctab, chip=Nrefchip, direction='forward', date=dateobs, filter1=filter1, filter2=filter2, offtab=offtab, binned=binned, tddcorr=apply_tdd) rfx = ridcmodel.cx rfy = ridcmodel.cy rrefpix = ridcmodel.refpix rorder = ridcmodel.norder """ rfx,rfy,rrefpix,rorder=mutil.readIDCtab(idctab,chip=Nrefchip, direction='forward', filter1=filter1,filter2=filter2,offtab=offtab, date=dateobs,tddcorr=apply_tdd) """ # Create the reference image name rimage = image.split('[')[0]+"[sci,%d]" % nr if not quiet: print("Reference image: ",rimage) # Create the tangent plane WCS on which the images are defined # This is close to that of the reference chip R=wcsutil.WCSObject(rimage) R.write_archive(rimage) R.restore() # Reacd in declination of target (for computing orientation at aperture) # Note that this is from the reference image #dec = float(fileutil.getKeyword(rimage,'CRVAL2')) #crval1 = float(fileutil.getKeyword(rimage,'CRVAL1')) #crval1 = float(R.crval1) #crval2 = dec dec = float(R.crval2) # Get an approximate reference position on the sky rref = (rrefpix['XREF']+ltvoffx, rrefpix['YREF']+ltvoffy) crval1,crval2=R.xy2rd(rref) if apply_tdd: # Correct zero points for TDD tddscale = (R.pscale/fx[1][1]) rxy0 = N.array([[tdd_xyref[Nrefchip][0]-2048.],[ tdd_xyref[Nrefchip][1]-2048.]]) xy0 = N.array([[tdd_xyref[chip][0]-2048.], [tdd_xyref[chip][1]-2048.]]) rv23_corr = N.dot(mrotp,N.dot(tdd,rxy0))*tddscale v23_corr = N.dot(mrotp,N.dot(tdd,xy0))*tddscale else: rv23_corr = N.array([[0],[0]]) v23_corr = N.array([[0],[0]]) # Convert the PA_V3 orientation to the orientation at the aperture # This is for the reference chip only - we use this for the # reference tangent plane definition # It has the same orientation as the reference chip v2ref = rrefpix['V2REF'] + rv23_corr[0][0]*0.05 v3ref = rrefpix['V3REF'] - rv23_corr[1][0]*0.05 v2 = refpix['V2REF'] + v23_corr[0][0]*0.05 v3 = refpix['V3REF'] - v23_corr[1][0] *0.05 pv = wcsutil.troll(pvt,dec,v2ref,v3ref) # Add the chip rotation angle if rrefpix['THETA']: pv += rrefpix['THETA'] # Set values for the rest of the reference WCS R.crval1=crval1 R.crval2=crval2 R.crpix1=0.0 + offshiftx R.crpix2=0.0 + offshifty R_scale=rrefpix['PSCALE']/3600.0 R.cd11=parity[0][0] * cos(pv*pi/180.0)*R_scale R.cd12=parity[0][0] * -sin(pv*pi/180.0)*R_scale R.cd21=parity[1][1] * sin(pv*pi/180.0)*R_scale R.cd22=parity[1][1] * cos(pv*pi/180.0)*R_scale ##print R R_cdmat = N.array([[R.cd11,R.cd12],[R.cd21,R.cd22]]) if not quiet: print(" Reference Chip Scale (arcsec/pix): ",rrefpix['PSCALE']) # Offset and angle in V2/V3 from reference chip to # new chip(s) - converted to reference image pixels off = sqrt((v2-v2ref)**2 + (v3-v3ref)**2)/(R_scale*3600.0) # Here we must include the PARITY if v3 == v3ref: theta=0.0 else: theta = atan2(parity[0][0]*(v2-v2ref),parity[1][1]*(v3-v3ref)) if rrefpix['THETA']: theta += rrefpix['THETA']*pi/180.0 dX=(off*sin(theta)) + offshiftx dY=(off*cos(theta)) + offshifty # Check to see whether we are working with GEIS or FITS input _fname,_iextn = fileutil.parseFilename(image) if _fname.find('.fits') < 0: # Input image is NOT a FITS file, so # build a FITS name for it's copy. _fitsname = fileutil.buildFITSName(_fname) else: _fitsname = None # Create a new instance of a WCS if _fitsname == None: _new_name = image else: _new_name = _fitsname+'['+str(_iextn)+']' #New=wcsutil.WCSObject(_new_name,new=yes) New = Old.copy() # Calculate new CRVALs and CRPIXs New.crval1,New.crval2=R.xy2rd((dX,dY)) New.crpix1=refpix['XREF'] + ltvoffx New.crpix2=refpix['YREF'] + ltvoffy # Account for subarray offset # Angle of chip relative to chip if refpix['THETA']: dtheta = refpix['THETA'] - rrefpix['THETA'] else: dtheta = 0.0 # Create a small vector, in reference image pixel scale # There is no parity effect here ??? delXX=fx[1,1]/R_scale/3600. delYX=fy[1,1]/R_scale/3600. delXY=fx[1,0]/R_scale/3600. delYY=fy[1,0]/R_scale/3600. # Convert to radians rr=dtheta*pi/180.0 # Rotate the vectors dXX= cos(rr)*delXX - sin(rr)*delYX dYX= sin(rr)*delXX + cos(rr)*delYX dXY= cos(rr)*delXY - sin(rr)*delYY dYY= sin(rr)*delXY + cos(rr)*delYY # Transform to sky coordinates a,b=R.xy2rd((dX+dXX,dY+dYX)) c,d=R.xy2rd((dX+dXY,dY+dYY)) # Calculate the new CDs and convert to degrees New.cd11=diff_angles(a,New.crval1)*cos(New.crval2*pi/180.0) New.cd12=diff_angles(c,New.crval1)*cos(New.crval2*pi/180.0) New.cd21=diff_angles(b,New.crval2) New.cd22=diff_angles(d,New.crval2) # Apply the velocity aberration effect if applicable if VA_fac != 1.0: # First shift the CRVALs apart # New.crval1 = ra_targ + VA_fac*(New.crval1 - ra_targ) # New.crval2 = dec_targ + VA_fac*(New.crval2 - dec_targ) # First shift the CRVALs apart # This is now relative to the reference chip, not the # target position. New.crval1 = R.crval1 + VA_fac*diff_angles(New.crval1, R.crval1) New.crval2 = R.crval2 + VA_fac*diff_angles(New.crval2, R.crval2) # and scale the CDs New.cd11 = New.cd11*VA_fac New.cd12 = New.cd12*VA_fac New.cd21 = New.cd21*VA_fac New.cd22 = New.cd22*VA_fac New_cdmat = N.array([[New.cd11,New.cd12],[New.cd21,New.cd22]]) # Store new one # archive=yes specifies to also write out archived WCS keywords # overwrite=no specifies do not overwrite any pre-existing archived keywords New.write(fitsname=_new_name,overwrite=no,quiet=quiet,archive=yes) if _dqname: _dq_iextn = _iextn.replace('sci', dqext.lower()) _new_dqname = _dqname +'['+_dq_iextn+']' dqwcs = wcsutil.WCSObject(_new_dqname) dqwcs.write(fitsname=_new_dqname, wcs=New,overwrite=no,quiet=quiet, archive=yes) """ Convert distortion coefficients into SIP style values and write out to image (assumed to be FITS). """ #First the CD matrix: f = refpix['PSCALE']/3600.0 a = fx[1,1]/3600.0 b = fx[1,0]/3600.0 c = fy[1,1]/3600.0 d = fy[1,0]/3600.0 det = (a*d - b*c)*refpix['PSCALE'] # Write to header fimg = fileutil.openImage(_new_name,mode='update') _new_root,_nextn = fileutil.parseFilename(_new_name) _new_extn = fileutil.getExtn(fimg,_nextn) # Transform the higher-order coefficients for n in range(order+1): for m in range(order+1): if n >= m and n>=2: # Form SIP-style keyword names Akey="A_%d_%d" % (m,n-m) Bkey="B_%d_%d" % (m,n-m) # Assign them values Aval= f*(d*fx[n,m]-b*fy[n,m])/det Bval= f*(a*fy[n,m]-c*fx[n,m])/det _new_extn.header.update(Akey,Aval) _new_extn.header.update(Bkey,Bval) # Update the SIP flag keywords as well #iraf.hedit(image,"CTYPE1","RA---TAN-SIP",verify=no,show=no) #iraf.hedit(image,"CTYPE2","DEC--TAN-SIP",verify=no,show=no) _new_extn.header.update("CTYPE1","RA---TAN-SIP") _new_extn.header.update("CTYPE2","DEC--TAN-SIP") # Finally we also need the order #iraf.hedit(image,"A_ORDER","%d" % order,add=yes,verify=no,show=no) #iraf.hedit(image,"B_ORDER","%d" % order,add=yes,verify=no,show=no) _new_extn.header.update("A_ORDER",order) _new_extn.header.update("B_ORDER",order) # Update header with additional keywords required for proper # interpretation of SIP coefficients by PyDrizzle. _new_extn.header.update("IDCSCALE",refpix['PSCALE']) _new_extn.header.update("IDCV2REF",refpix['V2REF']) _new_extn.header.update("IDCV3REF",refpix['V3REF']) _new_extn.header.update("IDCTHETA",refpix['THETA']) _new_extn.header.update("OCX10",fx[1][0]) _new_extn.header.update("OCX11",fx[1][1]) _new_extn.header.update("OCY10",fy[1][0]) _new_extn.header.update("OCY11",fy[1][1]) #_new_extn.header.update("TDDXOFF",rv23_corr[0][0] - v23_corr[0][0]) #_new_extn.header.update("TDDYOFF",-(rv23_corr[1][0] - v23_corr[1][0])) # Report time-dependent coeffs, if computed if instrument == 'ACS' and detector == 'WFC': _new_extn.header.update("TDDALPHA",alpha) _new_extn.header.update("TDDBETA",beta) # Close image now fimg.close() del fimg
def runDriz(self,pixfrac=1.0,kernel='turbo',fillval='INDEF'): """ Runs the 'drizzle' algorithm on this specific chip to create a numpy object of the undistorted image. The resulting drizzled image gets returned as a numpy object. """ # # Perform drizzling... # _wcs = self.geometry.wcs _wcsout = self.product_wcs # Rigorously compute the orientation changes from WCS # information using algorithm provided by R. Hook from WDRIZZLE. abxt,cdyt = drutil.wcsfit(self.geometry, self.product_wcs) # Compute the rotation and shifts between input and reference WCS. xsh = abxt[2] ysh = cdyt[2] rot = fileutil.RADTODEG(np.arctan2(abxt[1],cdyt[0])) scale = self.product_wcs.pscale / self.geometry.wcslin.pscale # Now, trim the final output to only match this chip _out_naxis1,_out_naxis2 = self.chip_shape # # Insure that the coeffs file was created # if not os.path.exists(self.coeffs): self.writeCoeffs() # A image buffer needs to be setup for converting the input # arrays (sci and wht) from FITS format to native format # with respect to byteorder and byteswapping. # This buffer should be reused for each input. # _outsci = np.zeros((_out_naxis2,_out_naxis1),dtype=np.float32) _outwht = np.zeros((_out_naxis2,_out_naxis1),dtype=np.float32) _inwcs = np.zeros([8],dtype=np.float64) # Only one chip will ever be drizzled using this method, so # the context image will only ever contain 1 bit-plane _outctx = np.zeros((_out_naxis2,_out_naxis1),dtype=np.int32) # Read in the distortion correction arrays, if specifij8cw08n4q_raw.fitsed _pxg,_pyg = self.getDGEOArrays() # Open the SCI image _expname = self.name _handle = fileutil.openImage(_expname,mode='readonly',memmap=0) _fname,_extn = fileutil.parseFilename(_expname) _sciext = fileutil.getExtn(_handle,extn=_extn) # Make a local copy of SCI array and WCS info #_insci = _sciext.data.copy() _inwcs = drutil.convertWCS(wcsutil.WCSObject(_fname,header=_sciext.header),_inwcs) # Compute what plane of the context image this input would # correspond to: _planeid = 1 # Select which mask needs to be read in for drizzling _inwht = np.ones((self.naxis2,self.naxis1),dtype=np.float32) # Default case: wt_scl = exptime _wtscl = self.exptime # Set additional parameters needed by 'drizzle' _expin = self.exptime #_in_un = 'counts' #_shift_fr = 'output' #_shift_un = 'output' _uniqid = 1 ystart = 0 nmiss = 0 nskip = 0 _vers = '' # # This call to 'arrdriz.tdriz' uses the F2C syntax # _dny = self.naxis2 # Call 'drizzle' to perform image combination _vers,nmiss,nskip = arrdriz.tdriz(_sciext.data.copy(),_inwht, _outsci, _outwht, _outctx, _uniqid, ystart, 1, 1, _dny, xsh,ysh, 'output','output', rot,scale, self.xsh2,self.ysh2, 1.0, 1.0, 0.0, 'output', _pxg,_pyg, 'center', pixfrac, kernel, self.coeffs, 'counts', _expin,_wtscl, fillval, _inwcs, nmiss, nskip, 1,0.,0.) # # End of F2C syntax # if nmiss > 0: print('! Warning, ',nmiss,' points were outside the output image.') if nskip > 0: print('! Note, ',nskip,' input lines were skipped completely.') # Close image handle _handle.close() del _handle,_fname,_extn,_sciext del _inwht del _pxg,_pyg del _outwht,_outctx return _outsci
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) # 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 _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 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) _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'])