def restoreWCS(f, ext, wcskey=" ", wcsname=" "): """ Copy a WCS with key "WCSKEY" to the primary WCS Reads in a WCS defined with wcskey and saves it as the primary WCS. Goes sequentially through the list of extensions in ext. Alternatively uses 'fromext' and 'toext'. Parameters ---------- f : str or `astropy.io.fits.HDUList` file name or a file object ext : int, tuple, str, or list of integers or tuples (e.g.('sci',1)) fits extensions to work with If a string is provided, it should specify the EXTNAME of extensions with WCSs to be archived wcskey : str "A"-"Z" - Used for one of 26 alternate WCS definitions. or " " - find a key from WCSNAMe value wcsname : str (optional) if given and wcskey is " ", will try to restore by WCSNAME value See Also -------- archiveWCS - copy the primary WCS as an alternate WCS restore_from_to """ if isinstance(f, str): fobj = fits.open(f, mode='update') else: fobj = f if not _parpasscheck(fobj, ext=ext, wcskey=wcskey): closefobj(f, fobj) raise ValueError("Input parameters problem") # Interpret input 'ext' value to get list of extensions to process ext = _buildExtlist(fobj, ext) # the case of an HDUList object in memory without an associated file wcskeyext = 0 if fu.isFits(fobj)[1] == 'simple' else 1 if wcskey == " ": if wcsname.strip(): wcskey = getKeyFromName(fobj[wcskeyext].header, wcsname) if not wcskey: closefobj(f, fobj) raise KeyError( f"Could not get a key from wcsname '{wcsname}'.") for e in ext: if wcskey in wcskeys(fobj, ext=e): _restore(fobj, wcskey, fromextnum=e, verbose=False) if fobj.filename() is not None: closefobj(f, fobj)
def checkFiles(input): """ Checks that input files are in the correct format. Converts geis and waiver fits files to multiextension fits. """ from stsci.tools.check_files import geis2mef, waiver2mef, checkFiles logger.info("\n\tChecking files %s" % input) removed_files = [] newfiles = [] if not isinstance(input, list): input = [input] for file in input: try: imgfits, imgtype = fileutil.isFits(file) except IOError: logger.warning( "\n\tFile %s could not be found, removing it from the input list.\n" % file) removed_files.append(file) continue # Check for existence of waiver FITS input, and quit if found. # Or should we print a warning and continue but not use that file if imgfits: if imgtype == 'waiver': newfilename = waiver2mef(file, convert_dq=True) if newfilename == None: logger.warning( "\n\tRemoving file %s from input list - could not convert waiver to mef" % file) removed_files.append(file) else: newfiles.append(newfilename) else: newfiles.append(file) # If a GEIS image is provided as input, create a new MEF file with # a name generated using 'buildFITSName()' # Convert the corresponding data quality file if present if not imgfits: newfilename = geis2mef(file, convert_dq=True) if newfilename == None: logger.warning( "\n\tRemoving file %s from input list - could not convert geis to mef" % file) removed_files.append(file) else: newfiles.append(newfilename) if removed_files: logger.warning( '\n\tThe following files will be removed from the list of files to be processed %s' % removed_files) newfiles = checkFiles(newfiles)[0] logger.info( "\n\tThese files passed the input check and will be processed: %s" % newfiles) return newfiles
def countInput(input): files = parseinput.parseinput(input) count = len(files[0]) for f in files[0]: if fileutil.isFits(f)[0]: try: ins = fits.getval(f, 'INSTRUME') except: # allow odd fits files; do not stop the count ins = None if ins == 'STIS': count += (stisObsCount(f)-1) return count
def countInput(input): files = parseinput.parseinput(input) count = len(files[0]) for f in files[0]: if fileutil.isFits(f)[0]: try: ins = fits.getval(f, 'INSTRUME') except: # allow odd fits files; do not stop the count ins = None if ins == 'STIS': count += (stisObsCount(f) - 1) return count
def checkFiles(input): """ Checks that input files are in the correct format. Converts geis and waiver fits files to multiextension fits. """ from stsci.tools.check_files import geis2mef, waiver2mef, checkFiles logger.info("\n\tChecking files %s" % input) removed_files = [] newfiles = [] if not isinstance(input, list): input = [input] for file in input: try: imgfits, imgtype = fileutil.isFits(file) except IOError: logger.warning("File {0} could not be found, removing it from the" "input list.".format(file)) removed_files.append(file) continue # Check for existence of waiver FITS input, and quit if found. # Or should we print a warning and continue but not use that file if imgfits: if imgtype == 'waiver': newfilename = waiver2mef(file, convert_dq=True) if newfilename is None: logger.warning("Could not convert waiver to mef." "Removing file {0} from input list".format(file)) removed_files.append(file) else: newfiles.append(newfilename) else: newfiles.append(file) # If a GEIS image is provided as input, create a new MEF file with # a name generated using 'buildFITSName()' # Convert the corresponding data quality file if present if not imgfits: newfilename = geis2mef(file, convert_dq=True) if newfilename is None: logger.warning("Could not convert file {0} from geis to mef, removing it from input list".format(file)) removed_files.append(file) else: newfiles.append(newfilename) if removed_files: logger.warning('\n\tThe following files will be removed from the list of files', 'to be processed %s' % removed_files) newfiles = checkFiles(newfiles)[0] logger.info("\n\tThese files passed the input check and will be processed: %s" % newfiles) return newfiles
def convert2fits(sci_ivm): """ Checks if a file is in WAIVER of GEIS format and converts it to MEF """ removed_files = [] translated_names = [] newivmlist = [] for file in sci_ivm: #find out what the input is # if science file is not found on disk, add it to removed_files for removal try: imgfits, imgtype = fileutil.isFits(file[0]) except IOError: print("Warning: File %s could not be found" % file[0]) print("Warning: Removing file %s from input list" % file[0]) removed_files.append(file[0]) continue # Check for existence of waiver FITS input, and quit if found. # Or should we print a warning and continue but not use that file if imgfits and imgtype == 'waiver': newfilename = waiver2mef(file[0], convert_dq=True) if newfilename == None: print( "Removing file %s from input list - could not convert WAIVER format to MEF\n" % file[0]) removed_files.append(file[0]) else: removed_files.append(file[0]) translated_names.append(newfilename) newivmlist.append(file[1]) # If a GEIS image is provided as input, create a new MEF file with # a name generated using 'buildFITSName()' # Convert the corresponding data quality file if present if not imgfits: newfilename = geis2mef(file[0], convert_dq=True) if newfilename == None: print( "Removing file %s from input list - could not convert GEIS format to MEF\n" % file[0]) removed_files.append(file[0]) else: removed_files.append(file[0]) translated_names.append(newfilename) newivmlist.append(file[1]) return removed_files, translated_names, newivmlist
def convert2fits(sci_ivm): """ Checks if a file is in WAIVER of GEIS format and converts it to MEF """ removed_files = [] translated_names = [] newivmlist = [] for file in sci_ivm: #find out what the input is # if science file is not found on disk, add it to removed_files for removal try: imgfits,imgtype = fileutil.isFits(file[0]) except IOError: print("Warning: File %s could not be found" %file[0]) print("Warning: Removing file %s from input list" %file[0]) removed_files.append(file[0]) continue # Check for existence of waiver FITS input, and quit if found. # Or should we print a warning and continue but not use that file if imgfits and imgtype == 'waiver': newfilename = waiver2mef(file[0], convert_dq=True) if newfilename is None: print("Removing file %s from input list - could not convert WAIVER format to MEF\n" %file[0]) removed_files.append(file[0]) else: removed_files.append(file[0]) translated_names.append(newfilename) newivmlist.append(file[1]) # If a GEIS image is provided as input, create a new MEF file with # a name generated using 'buildFITSName()' # Convert the corresponding data quality file if present if not imgfits: newfilename = geis2mef(file[0], convert_dq=True) if newfilename is None: print("Removing file %s from input list - could not convert GEIS format to MEF\n" %file[0]) removed_files.append(file[0]) else: removed_files.append(file[0]) translated_names.append(newfilename) newivmlist.append(file[1]) return removed_files, translated_names, newivmlist
def _make_odd_signs(self): """ Determine odd number of pixels """ import math from astropy.io import fits as pyfits # get the x-and y-dimension ftype = fileutil.isFits(self.mdrizzle_image) if ftype[1] == "mef": ext = 1 else: ext = 0 fits_im = pyfits.open(self.mdrizzle_image, 'readonly') x_dim = fits_im[ext].data.shape[1] y_dim = fits_im[ext].data.shape[0] fits_im.close() # return a tuple with odd-signs for x and y return (math.fmod(float(x_dim), 2.0) > 0.0, (math.fmod(float(y_dim), 2.0) > 0.0))
def parse_colnames(colnames, coords=None): """ Convert colnames input into list of column numbers. """ cols = [] if not isinstance(colnames, list): colnames = colnames.split(',') # parse column names from coords file and match to input values if coords is not None and fileutil.isFits(coords)[0]: # Open FITS file with table ftab = fits.open(coords, memmap=False) # determine which extension has the table for extn in ftab: if isinstance(extn, fits.BinTableHDU): # parse column names from table and match to inputs cnames = extn.columns.names if colnames is not None: for c in colnames: for name, i in zip(cnames, list(range(len(cnames)))): if c == name.lower(): cols.append(i) if len(cols) < len(colnames): errmsg = "Not all input columns found in table..." ftab.close() raise ValueError(errmsg) else: cols = cnames[:2] break ftab.close() else: for c in colnames: if isinstance(c, str): if c[0].lower() == 'c': cols.append(int(c[1:]) - 1) else: cols.append(int(c)) else: if isinstance(c, int): cols.append(c) else: errmsg = "Unsupported column names..." raise ValueError(errmsg) return cols
def parse_colnames(colnames,coords=None): """ Convert colnames input into list of column numbers. """ cols = [] if not isinstance(colnames,list): colnames = colnames.split(',') # parse column names from coords file and match to input values if coords is not None and fileutil.isFits(coords)[0]: # Open FITS file with table ftab = fits.open(coords, memmap=False) # determine which extension has the table for extn in ftab: if isinstance(extn, fits.BinTableHDU): # parse column names from table and match to inputs cnames = extn.columns.names if colnames is not None: for c in colnames: for name,i in zip(cnames,list(range(len(cnames)))): if c == name.lower(): cols.append(i) if len(cols) < len(colnames): errmsg = "Not all input columns found in table..." ftab.close() raise ValueError(errmsg) else: cols = cnames[:2] break ftab.close() else: for c in colnames: if isinstance(c, str): if c[0].lower() == 'c': cols.append(int(c[1:])-1) else: cols.append(int(c)) else: if isinstance(c, int): cols.append(c) else: errmsg = "Unsupported column names..." raise ValueError(errmsg) return cols
def rd2xy(input,ra=None,dec=None,coordfile=None,colnames=None, precision=6,output=None,verbose=True): """ Primary interface to perform coordinate transformations from pixel to sky coordinates using STWCS and full distortion models read from the input image header. """ single_coord = False if coordfile is not None: if colnames in blank_list: colnames = ['c1','c2'] elif isinstance(colnames,type('a')): colnames = colnames.split(',') # convert input file coordinates to lists of decimal degrees values xlist,ylist = tweakutils.readcols(coordfile,cols=colnames) else: if isinstance(ra,np.ndarray): ralist = ra.tolist() declist = dec.tolist() elif not isinstance(ra, list): ralist = [ra] declist = [dec] else: ralist = ra declist = dec xlist = [0]*len(ralist) ylist = [0]*len(ralist) if len(xlist) == 1: single_coord = True for i,(r,d) in enumerate(zip(ralist,declist)): # convert input value into decimal degrees value xval,yval = tweakutils.parse_skypos(r,d) xlist[i] = xval ylist[i] = yval # start by reading in WCS+distortion info for input image inwcs = wcsutil.HSTWCS(input) if inwcs.wcs.is_unity(): print("####\nNo valid WCS found in {}.\n Results may be invalid.\n####\n".format(input)) # Now, convert pixel coordinates into sky coordinates try: outx,outy = inwcs.all_world2pix(xlist,ylist,1) except RuntimeError: outx,outy = inwcs.wcs_world2pix(xlist,ylist,1) # add formatting based on precision here... xstr = [] ystr = [] fmt = "%."+repr(precision)+"f" for x,y in zip(outx,outy): xstr.append(fmt%x) ystr.append(fmt%y) if verbose or (not verbose and util.is_blank(output)): print ('# Coordinate transformations for ',input) print('# X Y RA Dec\n') for x,y,r,d in zip(xstr,ystr,xlist,ylist): print("%s %s %s %s"%(x,y,r,d)) # Create output file, if specified if output: f = open(output,mode='w') f.write("# Coordinates converted from %s\n"%input) for x,y in zip(xstr,ystr): f.write('%s %s\n'%(x,y)) f.close() print('Wrote out results to: ',output) if single_coord: outx = outx[0] outy = outy[0] return outx,outy """ Convert colnames input into list of column numbers """ cols = [] if not isinstance(colnames,list): colnames = colnames.split(',') # parse column names from coords file and match to input values if coordfile is not None and fileutil.isFits(coordfile)[0]: # Open FITS file with table ftab = fits.open(coordfile) # determine which extension has the table for extn in ftab: if isinstance(extn, fits.BinTableHDU): # parse column names from table and match to inputs cnames = extn.columns.names if colnames is not None: for c in colnames: for name,i in zip(cnames,list(range(len(cnames)))): if c == name.lower(): cols.append(i) if len(cols) < len(colnames): errmsg = "Not all input columns found in table..." ftab.close() raise ValueError(errmsg) else: cols = cnames[:2] break ftab.close() else: for c in colnames: if isinstance(c, str): if c[0].lower() == 'c': cols.append(int(c[1:])-1) else: cols.append(int(c)) else: if isinstance(c, int): cols.append(c) else: errmsg = "Unsupported column names..." raise ValueError(errmsg) return cols
def checkFiles(filelist, ivmlist = None): """ 1. Converts waiver fits sciece and data quality files to MEF format 2. Converts all GEIS science and data quality files to MEF format 3. Checks for stis association tables 4. Checks if kw idctab exists, if not tries to populate it based on the spt file 5. Removes files with EXPTIME=0 and the corresponding ivm files 6. Removes files with NGOODPIX == 0 (to exclude saturated images) """ #newfilelist = [] removed_files = [] translated_names = [] newivmlist = [] if ivmlist == None: ivmlist = [None for l in filelist] sci_ivm = zip(filelist, ivmlist) for file in sci_ivm: #find out what the input is # if science file is not found on disk, add it to removed_files for removal try: imgfits,imgtype = fileutil.isFits(file[0]) except IOError: print("Warning: File %s could not be found\n" %file[0]) print("Removing file %s from input list" %file[0]) removed_files.append(file) continue if file[1] != None: #If an ivm file is not found on disk # Remove the corresponding science file try: ivmfits,ivmtype = fileutil.isFits(file[1]) except IOError: print("Warning: File %s could not be found\n" %file[1]) print("Removing file %s from input list" %file[0]) removed_files.append(file) # Check for existence of waiver FITS input, and quit if found. # Or should we print a warning and continue but not use that file if imgfits and imgtype == 'waiver': newfilename = waiver2mef(file[0], convert_dq=True) if newfilename == None: print("Removing file %s from input list - could not convert waiver to mef" %file[0]) removed_files.append(file[0]) else: translated_names.append(newfilename) # If a GEIS image is provided as input, create a new MEF file with # a name generated using 'buildFITSName()' # Convert the corresponding data quality file if present if not imgfits: newfilename = geis2mef(file[0], convert_dq=True) if newfilename == None: print("Removing file %s from input list - could not convert geis to mef" %file[0]) removed_files.append(file[0]) else: translated_names.append(newfilename) if file[1] != None: if ivmfits and ivmtype == 'waiver': print("Warning: PyDrizzle does not support waiver fits format.\n") print("Convert the input files to GEIS or multiextension FITS.\n") print("File %s appears to be in waiver fits format \n" %file[1]) print("Removing file %s from input list" %file[0]) removed_files.append(file[0]) if not ivmfits: newfilename = geis2mef(file[1], convert_dq=False) if newfilename == None: print("Removing file %s from input list" %file[0]) removed_files.append(file[0]) else: newivmlist.append(newfilename) newfilelist, ivmlist = update_input(filelist, ivmlist, removed_files) if newfilelist == []: return [], [] """ errormsg = "\n No valid input was found. Quitting ...\n" raise IOError, errormsg """ if translated_names != []: # Since we don't allow input from different instruments # we can abandon the original input list and provide as # input only the translated names removed_expt_files = check_exptime(translated_names) newfilelist, ivmlist = update_input(translated_names, newivmlist, removed_expt_files) else: # check for STIS association files. This must be done before # the check for EXPTIME in order to handle correctly stis # assoc files if pyfits.getval(newfilelist[0], 'INSTRUME') == 'STIS': newfilelist, ivmlist = checkStisFiles(newfilelist, ivmlist) #removed_files = check_exptime(newflist) removed_expt_files = check_exptime(newfilelist) newfilelist, ivmlist = update_input(newfilelist, ivmlist, removed_expt_files) if removed_expt_files: errorstr = "#############################################\n" errorstr += "# #\n" errorstr += "# ERROR: #\n" errorstr += "# #\n" errorstr += "# The following files were excluded from #\n" errorstr += "# Multidrizzle processing because their #\n" errorstr += "# header keyword EXPTIME values were 0.0: #\n" for name in removed_expt_files: errorstr += " "+ str(name) + "\n" errorstr += "# #\n" errorstr += "#############################################\n\n" print(errorstr) removed_ngood_files = checkNGOODPIX(newfilelist) newfilelist, ivmlist = update_input(newfilelist, ivmlist, removed_ngood_files) if removed_ngood_files: msgstr = "####################################\n" msgstr += "# #\n" msgstr += "# WARNING: #\n" msgstr += "# NGOODPIX keyword value of 0 in #\n" for name in removed_ngood_files: msgstr += " "+ str(name) + "\n" msgstr += "# has been detected. Images with #\n" msgstr += "# no valid pixels will not be #\n" msgstr += "# used during processing. If you #\n" msgstr += "# wish this file to be used in #\n" msgstr += "# processing, please check its DQ #\n" msgstr += "# array and reset driz_sep_bits #\n" msgstr += "# and final_bits parameters #\n" msgstr += "# to accept flagged pixels. #\n" msgstr += "# #\n" msgstr += "####################################\n" print(msgstr) return newfilelist, ivmlist
def transform_toflux(self, segm_image): """Transform an image from cps to flux The method creates a flux image for a direct multidrizzled image. The direct image comes directly from multidrizzle, its unit is [cts/s], however the fluxcubes need the information in ergs/cm^2/s/AA. Parameters ---------- segm_image: str the segmentation for the data set Notes ----- Formulas: STmag = -2.5*log10(image) + self.st_zero STmag = -2.5*log10(F_lam) -21.10 F_lam = 10**(-0.4*(st_zero+21.10)) * image """ # get the name of the flux image self.flux_name = self._get_fluxname(self.image_name) # delete the flux image if it already exists if os.path.isfile(self.flux_name): os.unlink(self.flux_name) # the expression to apply to the image data expon = 10.0**(-0.4 * (21.10 + self.st_zero)) _log.info(f" image_name: {self.image_name.split('[')[0]}") _log.info(f" segm_image: {segm_image}") _log.info(f" flux_name: {self.flux_name}") # open the input files and apply the conversion file_a = fits.open(self.image_name.split('[')[0], 'readonly') file_b = fits.open(segm_image, 'readonly') ftype = fileutil.isFits(file_b.filename())[1] if (ftype == 'mef'): bgt1 = file_b[1].data >= 1 # assume in first blt1 = file_b[1].data < 1 # assume in first else: bgt1 = file_b[0].data >= 1 blt1 = file_b[0].data < 1 ftype = fileutil.isFits(file_a.filename())[1] if (ftype == 'mef'): file_a['SCI'].data[bgt1] *= expon file_a['SCI'].data[blt1] = 0.0 else: file_a[0].data[bgt1] *= expon file_a[0].data[blt1] = 0.0 # concatenate the primary and extension headers for output # to a simple FITS file prihdr = file_a[0].header del prihdr['nextend'] if (ftype == 'mef'): scihdr = file_a['SCI'].header scihdr._strip() newhdr = fits.Header(prihdr + scihdr) data = file_a['SCI'].data else: newhdr = fits.Header(prihdr) data = file_a[0].data # write the new flux image in simple fits format # regardless of input format fits.writeto(self.flux_name, data, newhdr) file_a.close() file_b.close() _log.info(f"\n{self.image_name} --> {self.flux_name}")
def _a_blot_segment_image(self, image_to_blot, tempname, x_excess, y_excess, interp): """Blot the segmentation or other nondrizzled image as if it were assume self.grism_image is always used as the source wcs reference Thats just a simple wrapper around the task blot in astrodrizzle Parameters ---------- image_to_blot: str the input image name, either the grism or direct drizzled image tempname: str the name of the output blotted image Notes ----- exposure time is hard coded to 1 since it was made from the drizzled image and we dont want the id numbers rescaled by the exposure time that was used for blotting """ excess_x = 0 excess_y = 0 # the drizzle coeff information for adriz is taken # from the self.data image # use the current data as reference image input_image = (self.data).split("[")[0] flt_header = fits.getheader(input_image) flt_wcs = HSTWCS(self.data) # check to see if this is a simple fits or MEF and grab # the science information. ftype = fileutil.isFits(self.grism_image_name)[1] if (ftype is 'mef'): grism_wcs = HSTWCS(self.grism_image_name, ext=(str(self.fcube_info["ext_nam"]), self.fcube_info["ext_ver"])) elif (ftype is 'simple'): grism_wcs = HSTWCS(self.grism_image_name) else: return IOError("File type of fits image is not " "supported {0:s}".format(image_to_blot)) ftype = fileutil.isFits(image_to_blot)[1] if (ftype is 'mef'): image_data = fits.getdata(image_to_blot, ext=(str(self.fcube_info["ext_nam"]), self.fcube_info["ext_ver"])) elif (ftype is 'simple'): image_data = fits.getdata(image_to_blot) else: return IOError("Input image is not a supported FITS " "type: {0:s}".format(image_to_blot)) # edit the wcs header information to add any dim_info shifts that we # need the segment image needs to be the same sky area cut without # the added pixels type(x_excess) if x_excess > 0: excess_x = int(flt_wcs.naxis1 + x_excess * 2.) flt_wcs.naxis1 = excess_x crpix = flt_wcs.wcs.crpix newx = int(crpix[0]) + x_excess flt_wcs.wcs.crpix = np.array([newx, crpix[1]]) flt_wcs.sip.crpix[0] = newx if y_excess > 0: excess_y = int(flt_wcs.naxis2 + y_excess * 2.) flt_wcs.naxis2 = excess_y crpix = flt_wcs.wcs.crpix newy = int(crpix[1]) + y_excess flt_wcs.wcs.crpix = np.array([int(crpix[0]), newy]) flt_wcs.sip.crpix[1] = newy # returns a numpy.ndarray which is just the data outimage = astrodrizzle.ablot.do_blot(image_data.astype(np.float32), grism_wcs, flt_wcs, 1., interp=interp, sinscl=1., coeffs=True, wcsmap=None, stepsize=10) # update the flt_header with the flt_wcs information I created flt_header['CRPIX1'] = flt_wcs.wcs.crpix[0] flt_header['CRPIX2'] = flt_wcs.wcs.crpix[1] # if the input flt was an MEF we need to write an MEF out try: newimage = fits.PrimaryHDU() newimage.data = outimage newimage.header = flt_header newimage.header.update(flt_wcs.to_header()) newimage.verify('silentfix') newimage.writeto(tempname) except: raise IOError("Problem writing fits image {0:s}".format(tempname))
def _a_blot_image(self, image_to_blot, tempname, x_excess, y_excess, interp): """ Blot one image. Thats just a simple wrapper around the task blot in astrodrizzle Parameters ---------- image_to_blot: str the input image name, either the grism or direct drizzled image tempname: str the name of the output blotted image """ # the drizzle coeff information for adriz is taken # from the self.data image, excess_x = 0 excess_y = 0 # use the current data as reference image for output # self.data comes from the header of the input grism or flux image # and is one of the input images used to make the drizzled # image_to_blot input_image = (self.data).split("[")[0] bunit = fits.getval(image_to_blot, 'BUNIT') flt_header = fits.getheader(input_image) flt_wcs = HSTWCS(self.data) # now look at the image to blot, this is a drizzled image ftype = fileutil.isFits(image_to_blot)[1] if (ftype == 'mef'): blot_wcs = HSTWCS(image_to_blot, ext=(str(self.fcube_info["ext_nam"]), str(self.fcube_info["ext_ver"]))) image_data = fits.getdata(image_to_blot, extname=str(self.fcube_info["ext_nam"]), extver=int(self.fcube_info["ext_nam"])) elif (ftype is 'simple'): blot_wcs = HSTWCS(image_to_blot) # assume simple image_data = fits.getdata(image_to_blot) else: return IOError("File type of fits image is not " "supported {0:s}".format(image_to_blot)) # edit the wcs header information to add any dim_info shifts that # we need, expanding the size of the output image # make sure this gets saved to the output extension header. # The lambda image will be bigger than the segment image if x_excess > 0: excess_x = int(flt_wcs.naxis1 + x_excess * 2.) flt_wcs.naxis1 = excess_x crpix = flt_wcs.wcs.crpix newx = int(crpix[0]) + x_excess flt_wcs.wcs.crpix = np.array([newx, int(crpix[1])]) flt_wcs.sip.crpix[0] = newx if y_excess > 0: excess_y = int(flt_wcs.naxis2 + y_excess * 2.) flt_wcs.naxis2 = excess_y crpix = flt_wcs.wcs.crpix newy = int(crpix[1]) + y_excess flt_wcs.wcs.crpix = np.array([int(crpix[0]), newy]) flt_wcs.sip.crpix[1] = newy # outimage is just the data array outimage = astrodrizzle.ablot.do_blot(image_data.astype(np.float32), blot_wcs, flt_wcs, 1., interp=interp, sinscl=1., coeffs=True, wcsmap=None, stepsize=10) # update the flt_header with the flt_wcs information I created flt_header['CRPIX1'] = flt_wcs.wcs.crpix[0] flt_header['CRPIX2'] = flt_wcs.wcs.crpix[1] try: newimage = fits.PrimaryHDU() newimage.data = outimage newimage.header = flt_header newimage.header['BUNIT'] = bunit newimage.header.update(flt_wcs.to_header()) newimage.verify('silentfix') newimage.writeto(tempname) except: raise IOError("Problem writing fits image {0:s}".format(tempname))
def rd2xy(input, ra=None, dec=None, coordfile=None, colnames=None, precision=6, output=None, verbose=True): """ Primary interface to perform coordinate transformations from pixel to sky coordinates using STWCS and full distortion models read from the input image header. """ single_coord = False if coordfile is not None: if colnames in blank_list: colnames = ['c1', 'c2'] elif isinstance(colnames, type('a')): colnames = colnames.split(',') # convert input file coordinates to lists of decimal degrees values xlist, ylist = tweakutils.readcols(coordfile, cols=colnames) else: if isinstance(ra, np.ndarray): ralist = ra.tolist() declist = dec.tolist() elif not isinstance(ra, list): ralist = [ra] declist = [dec] else: ralist = ra declist = dec xlist = [0] * len(ralist) ylist = [0] * len(ralist) if len(xlist) == 1: single_coord = True for i, (r, d) in enumerate(zip(ralist, declist)): # convert input value into decimal degrees value xval, yval = tweakutils.parse_skypos(r, d) xlist[i] = xval ylist[i] = yval # start by reading in WCS+distortion info for input image inwcs = wcsutil.HSTWCS(input) if inwcs.wcs.is_unity(): print( "####\nNo valid WCS found in {}.\n Results may be invalid.\n####\n" .format(input)) # Now, convert pixel coordinates into sky coordinates try: outx, outy = inwcs.all_world2pix(xlist, ylist, 1) except RuntimeError: outx, outy = inwcs.wcs_world2pix(xlist, ylist, 1) # add formatting based on precision here... xstr = [] ystr = [] fmt = "%." + repr(precision) + "f" for x, y in zip(outx, outy): xstr.append(fmt % x) ystr.append(fmt % y) if verbose or (not verbose and util.is_blank(output)): print('# Coordinate transformations for ', input) print('# X Y RA Dec\n') for x, y, r, d in zip(xstr, ystr, xlist, ylist): print("%s %s %s %s" % (x, y, r, d)) # Create output file, if specified if output: f = open(output, mode='w') f.write("# Coordinates converted from %s\n" % input) for x, y in zip(xstr, ystr): f.write('%s %s\n' % (x, y)) f.close() print('Wrote out results to: ', output) if single_coord: outx = outx[0] outy = outy[0] return outx, outy """ Convert colnames input into list of column numbers """ cols = [] if not isinstance(colnames, list): colnames = colnames.split(',') # parse column names from coords file and match to input values if coordfile is not None and fileutil.isFits(coordfile)[0]: # Open FITS file with table ftab = fits.open(coordfile) # determine which extension has the table for extn in ftab: if isinstance(extn, fits.BinTableHDU): # parse column names from table and match to inputs cnames = extn.columns.names if colnames is not None: for c in colnames: for name, i in zip(cnames, list(range(len(cnames)))): if c == name.lower(): cols.append(i) if len(cols) < len(colnames): errmsg = "Not all input columns found in table..." ftab.close() raise ValueError(errmsg) else: cols = cnames[:2] break ftab.close() else: for c in colnames: if isinstance(c, str): if c[0].lower() == 'c': cols.append(int(c[1:]) - 1) else: cols.append(int(c)) else: if isinstance(c, int): cols.append(c) else: errmsg = "Unsupported column names..." raise ValueError(errmsg) return cols
def restore_from_to(f, fromext=None, toext=None, wcskey=" ", wcsname=" "): """ Copy an alternate WCS from one extension as a primary WCS of another extension Reads in a WCS defined with wcskey and saves it as the primary WCS. Goes sequentially through the list of extensions in ext. Alternatively uses 'fromext' and 'toext'. Parameters ---------- f: string or `astropy.io.fits.HDUList` a file name or a file object fromext: string extname from which to read in the alternate WCS, for example 'SCI' toext: string or python list extname or a list of extnames to which the WCS will be copied as primary, for example ['SCI', 'ERR', 'DQ'] wcskey: a charater "A"-"Z" - Used for one of 26 alternate WCS definitions. or " " - find a key from WCSNAMe value wcsname: string (optional) if given and wcskey is " ", will try to restore by WCSNAME value See Also -------- archiveWCS - copy the primary WCS as an alternate WCS restoreWCS - Copy a WCS with key "WCSKEY" to the primary WCS """ if isinstance(f, str): fobj = fits.open(f, mode='update') else: fobj = f if not _parpasscheck(fobj, ext=None, wcskey=wcskey, fromext=fromext, toext=toext): closefobj(f, fobj) raise ValueError("Input parameters problem") # Interpret input 'ext' value to get list of extensions to process # ext = _buildExtlist(fobj, ext) if isinstance(toext, str): toext = [toext] # the case of an HDUList object in memory without an associated file # if fobj.filename() is not None: # name = fobj.filename() simplefits = fu.isFits(fobj)[1] is 'simple' if simplefits: wcskeyext = 0 else: wcskeyext = 1 if wcskey == " ": if wcsname.strip(): wkey = getKeyFromName(fobj[wcskeyext].header, wcsname) if not wkey: closefobj(f, fobj) raise KeyError("Could not get a key from wcsname %s ." % wcsname) else: if wcskey not in wcskeys(fobj, ext=wcskeyext): print("Could not find alternate WCS with key %s in this file" % wcskey) closefobj(f, fobj) return wkey = wcskey countext = fu.countExtn(fobj, fromext) if not countext: raise KeyError("File does not have extension with extname %s", fromext) else: for i in range(1, countext + 1): for toe in toext: _restore(fobj, fromextnum=i, fromextnam=fromext, toextnum=i, toextnam=toe, ukey=wkey) if fobj.filename() is not None: # fobj.writeto(name) closefobj(f, fobj)
def restoreWCS(f, ext, wcskey=" ", wcsname=" "): """ Copy a WCS with key "WCSKEY" to the primary WCS Reads in a WCS defined with wcskey and saves it as the primary WCS. Goes sequentially through the list of extensions in ext. Alternatively uses 'fromext' and 'toext'. Parameters ---------- f : str or `astropy.io.fits.HDUList` file name or a file object ext : int, tuple, str, or list of integers or tuples (e.g.('sci',1)) fits extensions to work with If a string is provided, it should specify the EXTNAME of extensions with WCSs to be archived wcskey : str "A"-"Z" - Used for one of 26 alternate WCS definitions. or " " - find a key from WCSNAMe value wcsname : str (optional) if given and wcskey is " ", will try to restore by WCSNAME value See Also -------- archiveWCS - copy the primary WCS as an alternate WCS restore_from_to """ if isinstance(f, str): fobj = fits.open(f, mode='update') else: fobj = f if not _parpasscheck(fobj, ext=ext, wcskey=wcskey): closefobj(f, fobj) raise ValueError("Input parameters problem") # Interpret input 'ext' value to get list of extensions to process ext = _buildExtlist(fobj, ext) # the case of an HDUList object in memory without an associated file simplefits = fu.isFits(fobj)[1] is 'simple' if simplefits: wcskeyext = 0 else: wcskeyext = 1 if wcskey == " ": if wcsname.strip(): wcskey = getKeyFromName(fobj[wcskeyext].header, wcsname) if not wcskey: closefobj(f, fobj) raise KeyError("Could not get a key from wcsname %s ." % wcsname) for e in ext: if wcskey not in wcskeys(fobj, ext=e): continue else: _restore(fobj, wcskey, fromextnum=e, verbose=False) if fobj.filename() is not None: closefobj(f, fobj)
def run(input,quiet=yes,restore=no,prepend='O', tddcorr=True): print("+ MAKEWCS Version %s" % __version__) _prepend = prepend files = parseinput.parseinput(input)[0] newfiles = [] if files == []: print("No valid input files found.\n") raise IOError for image in files: #find out what the input is imgfits,imgtype = fileutil.isFits(image) # Check for existence of waiver FITS input, and quit if found. if imgfits and imgtype == 'waiver': """ errormsg = '\n\nPyDrizzle does not support waiver fits format.\n' errormsg += 'Convert the input files to GEIS or multiextension FITS.\n\n' raise ValueError, errormsg """ newfilename = fileutil.buildNewRootname(image, extn='_c0h.fits') # Convert GEIS image to MEF file newimage = fileutil.openImage(image,writefits=True,fitsname=newfilename,clobber=True) del newimage # Work with new file image = newfilename newfiles.append(image) # If a GEIS image is provided as input, create a new MEF file with # a name generated using 'buildFITSName()' and update that new MEF file. if not imgfits: # Create standardized name for MEF file newfilename = fileutil.buildFITSName(image) # Convert GEIS image to MEF file newimage = fileutil.openImage(image,writefits=True,fitsname=newfilename,clobber=True) del newimage # Work with new file image = newfilename newfiles.append(image) if not quiet: print("Input files: ",files) # First get the name of the IDC table #idctab = drutil.getIDCFile(_files[0][0],keyword='idctab')[0] idctab = drutil.getIDCFile(image,keyword='idctab')[0] _found = fileutil.findFile(idctab) if idctab == None or idctab == '': print('#\n No IDCTAB specified. No correction can be done for file %s.Quitting makewcs\n' %image) #raise ValueError continue elif not _found: print('#\n IDCTAB: ',idctab,' could not be found. \n') print('WCS keywords for file %s will not be updated.\n' %image) #raise IOError continue _phdu = image + '[0]' _instrument = fileutil.getKeyword(_phdu,keyword='INSTRUME') if _instrument == 'WFPC2': Nrefchip, Nrefext = getNrefchip(image) else: Nrefchip = None Nrefext = None if _instrument not in NUM_PER_EXTN: raise ValueError("Instrument %s not supported yet. Exiting..." \ %_instrument) _detector = fileutil.getKeyword(_phdu, keyword='DETECTOR') _nimsets = get_numsci(image) for i in range(_nimsets): if image.find('.fits') > 0: _img = image+'[sci,'+repr(i+1)+']' else: _img = image+'['+repr(i+1)+']' if not restore: if not quiet: print('Updating image: ', _img) _update(_img,idctab, _nimsets, apply_tdd=False, quiet=quiet,instrument=_instrument,prepend=_prepend, nrchip=Nrefchip, nrext = Nrefext) if _instrument == 'ACS' and _detector == 'WFC': tddswitch = fileutil.getKeyword(_phdu,keyword='TDDCORR') # This logic requires that TDDCORR be in the primary header # and set to PERFORM in order to turn this on at all. It can # be turned off by setting either tddcorr=False or setting # the keyword to anything but PERFORM or by deleting the # keyword altogether. PyDrizzle will rely simply on the # values of alpha and beta as computed here to apply the # correction to the coefficients. if (tddcorr and tddswitch != 'OMIT'): print('Applying time-dependent distortion corrections...') _update(_img,idctab, _nimsets, apply_tdd=True, \ quiet=quiet,instrument=_instrument,prepend=_prepend, nrchip=Nrefchip, nrext = Nrefext) else: if not quiet: print('Restoring original WCS values for',_img) restoreCD(_img,_prepend) #fimg = fileutil.openImage(image,mode='update') #if 'TDDCORR' in fimg[0].header and fimg[0].header['TDDCORR'] == 'PERFORM': # fimg[0].header['TDDCORR'] = 'COMPLETE' #fimg.close() if newfiles == []: return files else: return newfiles