def createbadpixel(inhdu, bphdu, sci_ext, bp_ext): """Create the bad pixel hdu from a bad pixel hdu""" if bphdu is None: data=inhdu[sci_ext].data*0.0 else: try: infile=inhdu._HDUList__file.name bpfile=bphdu._HDUList__file.name except: infile=inhdu.filename bpfile=bphdu.filename if not saltkey.compare(inhdu[0], bphdu[0], 'INSTRUME', infile, bpfile): message = '%s and %s are not the same %s' % (infile,bpfile, 'INSTRUME') raise SaltError(message) for k in ['CCDSUM', 'NAXIS1', 'NAXIS2']: if not saltkey.compare(inhdu[sci_ext], bphdu[sci_ext], k, infile, bpfile): message = '%s and %s are not the same %s' % (infile,bpfile, k) raise SaltError(message) data=bphdu[sci_ext].data.copy() header=inhdu[sci_ext].header.copy() header['EXTVER']=bp_ext header['SCIEXT']=(sci_ext,'Extension of science frame') return fits.ImageHDU(data=data, header=header, name='BPM')
def saltprepare(images,outimages,outpref,createvar=False, badpixelimage=None, clobber=True,logfile='salt.log',verbose=True): with logging(logfile,debug) as log: # Check the input images infiles = saltio.argunpack ('Input',images) # create list of output files outfiles=saltio.listparse('Outfile', outimages, outpref,infiles,'') #verify that the input and output lists are the same length saltio.comparelists(infiles,outfiles,'Input','output') # open the badpixel image if saltio.checkfornone(badpixelimage) is None: badpixelstruct=None else: try: badpixelstruct = saltio.openfits(badpixelimage) except saltio.SaltIOError,e: msg='badpixel image must be specificied\n %s' % e raise SaltError(msg) # open each raw image file for img, oimg, in zip(infiles, outfiles): #open the fits file struct=saltio.openfits(img) #if createvar, throw a warning if it is using slotmode if saltkey.fastmode(saltkey.get('DETMODE', struct[0])) and createvar: msg='Creating variance frames for slotmode data in %s' % img log.warning(msg) # identify instrument instrume,keyprep,keygain,keybias,keyxtalk,keyslot = saltkey.instrumid(struct) # has file been prepared already? try: key = struct[0].header[keyprep] message = 'ERROR -- SALTPREPARE: File ' + infile message += ' has already been prepared' raise SaltError(message) except: pass # prepare file struct=prepare(struct,createvar=createvar, badpixelstruct=badpixelstruct) # housekeeping keywords fname, hist=history(level=1, wrap=False, exclude=['images', 'outimages', 'outpref']) saltkey.housekeeping(struct[0],keyprep, 'File prepared for IRAF', hist) # write FITS file saltio.writefits(struct,oimg, clobber=clobber) saltio.closefits(struct) message = 'SALTPREPARE -- %s => %s' % (img, oimg) log.message(message, with_header=False)
def get_values(dblist, gainset, rospeed, amp): """Get values for gain and rdnoise from the dblist. The input of the dblist should be: dblist should have the following lists: speed, rate, gain, noise, bias, amp """ #default values in case none are found gain = 1 rdnoise = 5 found = False dbspeed, dbrate, dbgain, dbnoise, dbbias, dbamp = dblist #checkf or the gain if gainset not in dbrate: raise SaltError('GAINSET=%s does not match any vaue in gaindb file' % gainset) if rospeed not in dbspeed: raise SaltError('ROSPEED=%s does not match any vaue in gaindb file' % rospeed) #loop through the values and find the corresponding gain/rdnoise for i in range(len(dbspeed)): if dbspeed[i].strip().upper() == rospeed.strip().upper(): if dbrate[i].strip().upper() == gainset.strip().upper(): if int(dbamp[i]) == int(amp): gain = float(dbgain[i]) rdnoise = float(dbnoise[i]) found = True return gain, rdnoise if not found: msg='Could not find a corresponding setting in the gaindb file for gainset=%s, rospeed=%s, amp=%i' \ % (gainset, rospeed, amp) raise SaltError(msg) return rdnoise, gain
def calculate_realexptime(id_arr, utc_arr, dsec_arr, diff_arr, req_texp, utc_list): """Calculates the real exposure time. This makes the following assumptions: #. That the measurement after the turn of the second is a fiducial #. That there is an integer number of frames between each fiducial exposure #. We then set up a metric which is Y=np.sum(i-int(i)) where i=dt/t_exp #. Then the minimum of Y is found between the requested exposure time and the median time difference #. And the best exposure time is the time at that minimum returns median exposure time and real exposure time """ t_exp = 0 # calculate the median time try: t_wrong = np.median(diff_arr) except: raise SaltError('Unable to calculate median time difference') # Compress the arrays to find those closest to the second mark mask = (dsec_arr < t_wrong) * (diff_arr > 0) t = np.compress(mask, utc_arr) s = np.compress(mask, dsec_arr) id = np.compress(mask, id_arr) # Now set up the components in the equation try: t_start = t[0] dt = t[1:] - t[0] except Exception, e: msg = 'Unable to set up necessary arrays because %s' % e raise SaltError(msg)
def prepare(struct,createvar=False, badpixelstruct=None, namps=2): #set up the file name infile=saltkey.getimagename(struct[0]) #include information about which headers are science extensoisn #and check to make sure each array is a data array nextend=len(struct)-1 nsciext=nextend for i in range(1,nextend+1): try: struct[i].header['XTENSION'] == 'IMAGE' except: msg='Extension %i in %s is not an image data' raise SaltError(msg) saltkey.new('EXTNAME','SCI','Extension name',struct[i]) saltkey.new('EXTVER',i,'Extension number',struct[i]) #check the number of amplifiers #TODO: This is current hardwired at a value of 2 nccds = saltkey.get('NCCDS',struct[0]) if (nextend%(nccds*namps) != 0): message = 'ERROR -- SALTPREPARE: Number of file extensions and ' message += 'number of amplifiers are not consistent in ' + infile raise SaltError(message) #Add the inv. variance frame if requested--assumes no variance frame #and the science frames are in the first n frames if createvar: #create the inv. variance frames for i in range(1, nsciext+1): try: hdu=CreateVariance(struct[i], i, nextend+i) except Exception, e: msg='Cannot create variance frame in extension %i of %s because %s' % (nextend+i, infile, e) raise SaltError(msg) struct[i].header.update('VAREXT',nextend+i, comment='Extension for Variance Frame') struct.append(hdu) nextend+=nsciext #create the badpixelframes for i in range(1, nsciext+1): try: hdu=createbadpixel(struct, badpixelstruct, i, nextend+i) except Exception, e: msg='Could not create bad pixel extension in ext %i of %s because %s' % (nextend+i, infile, e) raise SaltError(msg) struct[i].header.update('BPMEXT',nextend+i, comment='Extension for Bad Pixel Mask') struct.append(hdu)
def cleancosmicrays(arr, crtype='fast', thresh=5, mbox=3, bbox=5, bthresh=5, flux_ratio=0.2, gain=1, \ rdnoise=5, b_factor=2, fthresh=3, gbin=0, max_iter=1): """Clean the cosmic rays from an input array using three different types of methods """ niter = 0 npix = 1 onpix = 0 #makesure the data array is in floating point try: arr = arr * 1.0 except: message = 'Array cannot be convert to the correct data type' raise SaltError(message) #measure the mean values for the image--leaving this outside #because it doesn't need to be done on each iter loop if crtype == 'fast': mean, midpt, bsigma = saltstat.iterstat(arr, bthresh, max_iter) #set up the array crarr = arr * 0.0 while niter < max_iter and npix > onpix: #apply the correct function to idenitfy cosmic rays if crtype == 'median': crarr += crmedian(arr, thresh, mbox, bbox) elif crtype == 'fast': crarr += crfast(arr, mean, bsigma, thresh, mbox, flux_ratio) elif crtype == 'edge': crarr += credge(arr, thresh, gain, rdnoise, b_factor, fthresh) else: message = 'CRTYPE %s is not a valid value' % crtype raise SaltError(message) #update the array mask = (crarr > 0) arr[mask] = crarr[mask] #count the number of cosmic rays identified onpix = npix npix = crarr.sum() niter += 1 #grow the result if gbin > 0: crarr = crgrow(crarr, grad=gbin) return crarr
def saltgain(images, outimages, outpref, gaindb=None, usedb=False, mult=True, clobber=True, logfile='salt.log', verbose=True): #start logging with logging(logfile, debug) as log: # Check the input images infiles = saltio.argunpack('Input', images) # create list of output files outfiles = saltio.listparse('Outfile', outimages, outpref, infiles, '') #verify that the input and output lists are the same length saltio.comparelists(infiles, outfiles, 'Input', 'output') # read in the database file if usedb is true if usedb: gaindb = gaindb.strip() dblist = saltio.readgaindb(gaindb) else: dblist = [] for img, oimg in zip(infiles, outfiles): #open the fits file struct = saltio.openfits(img) # identify instrument instrume, keyprep, keygain, keybias, keyxtalk, keyslot = saltkey.instrumid( struct) # has file been prepared already? if saltkey.found(keygain, struct[0]): message = 'SALTGAIN: %s has already been gain-corrected' % img raise SaltError(message) # gain correct the data struct = gain(struct, mult=mult, usedb=usedb, dblist=dblist, log=log, verbose=verbose) # housekeeping keywords fname, hist = history(level=1, wrap=False, exclude=['images', 'outimages', 'outpref']) saltkey.housekeeping(struct[0], keygain, 'Images have been gain corrected', hist) # write FITS file saltio.writefits(struct, oimg, clobber=clobber) saltio.closefits(struct)
def CalculateScale(arr, scale=None, statsec=None): """Caculate the scale according to different methods Input Variables: arr: Input data array scale: Method for calculating the scacle -average: calculate the average -median: calculate the median statsec: Section over which to calculate the scale """ if statsec is None: y1, y2, x1, x2 = [0, len(arr), 0, len(arr[0])] data = arr[y1:y2, x1:x2] else: data = arr if scale == 'average': return np.mean(data) if scale == 'median': return np.median(data) else: msg = '%s is not a type of scale' % scale raise SaltError(msg)
def CombineArray(arr, method='average', ivar=None, bpm=None): """Combine--Combine an array of arrays. The method: type of combination--either average or median ivar: inverse variance array bpm: bad pixel mask array """ if bpm is None: bpm = arr * 0.0 + 1.0 wei = None else: # correct the weights for the bad pixel mask if ivar is None: ivar = arr * 0.0 + 1.0 wei = ivar * (1 - bpm) #TODO: need to add a check to make sure that there are is a place #to make sure that one of the weights is at least zero check_wei = wei.sum(axis=0) wei[0][check_wei == 0] = wei.min() if method == 'average': c_arr, s_arr = np.average(arr, axis=0, weights=wei, returned=True) return c_arr, s_arr elif method == 'median': return np.median(arr, axis=0), bpm.sum(axis=0) else: msg = '%s is not a method for combining arrays' % method raise SaltError(msg)
def saltfirst(obsdate, imdir, prodir, server='smtp.saao.ac.za', readme='readme.fast.template', sdbhost='sdb.salt', sdbname='sdb', sdbuser='', password='',imreduce=True, sexfile='/home/ccd/tools/qred.sex', update=True, clobber=False,logfile='salt.log',verbose=True): #Move into the working directory if os.path.isdir(prodir): if clobber: shutil.rmtree(prodir) os.mkdir(prodir) else: os.mkdir(prodir) os.chdir(prodir) with logging(logfile,debug) as log: #create GUI App = QtGui.QApplication([]) #Add information to gui aw=FirstWindow(obsdate, imdir, prodir, server=server, readme=readme, sdbhost=sdbhost, sdbname=sdbname, sdbuser=sdbuser, password=password, imreduce=imreduce, sexfile=sexfile, update=update, clobber=clobber, log=log, verbose=verbose) aw.setMinimumHeight(800) aw.setMinimumWidth(500) aw.show() # Start application event loop exit=App.exec_() # Check if GUI was executed succesfully if exit!=0: raise SaltError('SALTFIRST GUI has unexpected exit status '+str(exit))
def findrawfilename(infits): i = -1 try: i = infits.index("S") except: message = infits + ' is not a SALT File \n' try: i = infits.index("P") except: message = infits + ' is not a SALT File \n' try: i = infits.index("H") except: message = infits + ' is not a SALT File \n' try: i = infits.index("R") except: message = infits + ' is not a SALT File \n' if i >= 0: inname = infits[i:] else: inname = '' message = 'SALTSDBLOADFITS -- ERROR : ' + message raise SaltError(message) return inname
def checksdbforfits(inname, sdb, log, verbose): """ Check to see if the image is in the database returns FileData_Id, status """ FileData_Id = -1 #check to see if the name is the FileName logic = "FileName='%s'" % inname records = saltmysql.select(sdb, 'FileData_Id', 'FileData', logic) if not records: FileData_Id = -1 message = 'SALTSDBLOADFITS: Adding %s to database' % inname elif len(records[0]) == 1: FileData_Id = records[0][0] message = 'SALTSDBLOADFITS: Updating %s in database' % inname elif len(records[0]) > 1: message = 'SALTLOADSDBFITS -- ERROR: Ambigous record for %s' % inname raise SaltError(message) if verbose: log.message(message, with_header=False) return FileData_Id
def redophot(self, i): """Redo the photometry for a single frame""" self.id = i x = {} y = {} x['target'] = self.tx[self.id] y['target'] = self.ty[self.id] x['comparison'] = self.cx[self.id] y['comparison'] = self.cy[self.id] image = self.struct[int(self.pid[self.id])].data #these will need to be changed gain = 1 rdnoise = 1 verbose = False try: tflux, tflux_err, cflux, cflux_err, ratio, ratio_err = \ st.dophot(self. phottype, image, x, y, self.r, self.br1, self.br2, \ gain, rdnoise, self.naxis1, self.naxis2) except: msg = "SLOTVIEW--ERROR: Could not measure photometry in frame %i" % i raise SaltError(msg) self.tflux[self.id] = tflux self.cflux[self.id] = cflux self.ratio[self.id] = ratio
def capphot(array, xc, yc, rc, br1, br2, gain, rdnoise, naxis1, naxis2): """Perform circular aperture photometry return flux, flux_err """ # calculate the flux try: i = len(array) j = len(array[0]) y, x = np.indices((i, j)) r = np.sqrt((x - xc)**2 + (y - yc)**2) mask = (r < rc) area = mask.sum() except: area = 0 if area == 0: flux = 0 flux_err = 0 raise SaltError('No data in the specified array') flux = (array * mask).sum() # calculate the background flux bflux, berr, npix = calcstarbackground(array, xc, yc, br1, br2, gain, rdnoise, naxis1, naxis2) # calculate the flux flux = flux - area * bflux flux_err = np.sqrt( abs(flux) + area * rdnoise**2 + area * berr**2 + area**2 * berr**2 / npix) return flux, flux_err
def sqapphot(array, xc, yc, rc, br1, br2, gain, rdnoise, naxis1, naxis2): """Perform square aperture photometry returns flux, flux_err """ #first calculate the flux x1 = checkedge(xc - rc, 0, naxis1) x2 = checkedge(xc + rc, 0, naxis1) y1 = checkedge(yc - rc, 0, naxis2) y2 = checkedge(yc + rc, 0, naxis2) area = np.size(array[y1:y2, x1:x2]) if area == 0: flux = 0 flux_err = 0 raise SaltError('No data in the specified array') flux = array[y1:y2, x1:x2].sum() # calculate the background flux bflux, berr, npix = calcstarbackground(array, xc, yc, br1, br2, gain, rdnoise, naxis1, naxis2) # calculate the flux flux = flux - area * bflux flux_err = np.sqrt( abs(flux) + area * rdnoise**2 + area * berr**2 + area**2 * berr**2 / npix) return flux, flux_err
def stack(hdu): """Convert MEF HRS data into a single extension. """ #set the detector detname = saltkey.get('DETNAM', hdu[0]) print detname if detname == '08443-03-01' or detname == 'HRDET': detector = 'hrdet' elif detname == '04434-23-02' or detname == 'HBDET': detector = 'hbdet' else: raise SaltError('%s is not an HRS detector' % detnam) print detector #get key parameters try: nccd = saltkey.get('CCDAMPS', hdu[0]) except: nccd = saltkey.get('CCDNAMPS', hdu[0]) #determine the shape of the CCD if detector == 'hbdet': toty = hdu[1].shape[0] totx = hdu[1].shape[1] + hdu[2].shape[1] elif detector == 'hrdet': toty = hdu[1].shape[0] + hdu[3].shape[0] totx = hdu[1].shape[1] + hdu[2].shape[1] data = np.zeros((toty, totx), np.float32) #embed the ccds for j in range(nccd): i = j + 1 y2, x2 = hdu[i].data.shape if detector == 'hbdet': if i == 1: y1 = 0 x1 = 0 y2 = y2 x2 = x2 else: y1 = 0 x1 = x2 x2 = x1 + x2 elif detector == 'hrdet': y1 = 0 if i % 2 == 1: x1 = 0 if i % 2 == 0: x1 = x2 x2 = x1 + x2 if i > 2: y1 = y2 y2 = y1 + y2 data[y1:y2, x1:x2] = hdu[i].data ihdu = pyfits.ImageHDU(data) nhdu = pyfits.HDUList([hdu[0], ihdu]) return nhdu
def median_image(arr, nbin): """Median smooth an image with a filter size set by bin returns arr """ from scipy.ndimage.filters import median_filter try: arr=median_filter(arr,size=(nbin,nbin)) except Exception, e: raise SaltError('Could not median filter image because %s' % e)
def median(x,logfile=None): """calculate median of numeric list logfile--depreciated variable """ try: return np.median(x) except Exception, e: message = 'Cannont calculate median because %s' % e raise SaltError(message)
def flatnormalize(data, minflat, fmean=1): """Calculate the mean of the data and return a normalized data array """ try: mask = (data < minflat) + (data == numpy.nan) + (data == numpy.inf) data[mask]=minflat data=data/fmean except Exception, e: message='ERROR--FLATNORMALIZE: Data could not be normalized because %s' % e raise SaltError(message)
def saltslot(images, outimages, outpref, gaindb='', xtalkfile='', usedb=False, clobber=False, logfile='salt.log', verbose=True): #start logging with logging(logfile, debug) as log: # Check the input images infiles = saltio.argunpack('Input', images) # create list of output files outfiles = saltio.listparse('Outfile', outimages, outpref, infiles, '') # are input and output lists the same length? saltio.comparelists(infiles, outfiles, 'Input', 'output') # does crosstalk coefficient data exist if usedb: dblist = saltio.readgaindb(gaindb) xtalkfile = xtalkfile.strip() xdict = saltio.readxtalkcoeff(xtalkfile) else: dblist = [] xdict = None for img, oimg in zip(infiles, outfiles): #open the fits file struct = saltio.openfits(img) # identify instrument instrume, keyprep, keygain, keybias, keyxtalk, keyslot = saltkey.instrumid( struct) # has file been prepared already? if saltkey.found(keygain, struct[0]): message = '%s has already been reduced' % img raise SaltError(message) # housekeeping keywords fname, hist = history(level=1, wrap=False, exclude=['images', 'outimages', 'outpref']) saltkey.housekeeping(struct[0], keyslot, 'Images have been slotmode reduced', hist) # write FITS file saltio.writefits(struct, oimg, clobber=clobber) saltio.closefits(struct)
def updateheaders(struct, ext, tdiff, real_expt, utc, infile): # exit if tdiff wasn't updated if tdiff == real_expt: msg = 'No adequate correction found for frame %i in file %s' % (ext, infile) raise SaltError(msg) return struct # calculate the new utc value try: ntime = salttime.sex2dec(utc) ntime = ntime - tdiff / 3600.0 newutc = salttime.dec2sex(ntime) except Exception, e: msg = 'Could not update UTC in %i header of image %s because %s' % ( ext, infile, e) raise SaltError(msg) return struct
def saltarith(operand1, op, operand2, result, outpref, divzero=0, clobber=False, \ logfile='salt.log',verbose=True): with logging(logfile, debug) as log: # Check the input images infiles = saltio.argunpack('Input', operand1) # create list of output files outfiles = saltio.listparse('Outfile', result, outpref, infiles, '') #verify that the input and output lists are the same length saltio.comparelists(infiles, outfiles, 'Input', 'output') #let's keep track of whether operand2 is an image or not is_image = False #load in operand2, or, if it's not an image, assume it's a number try: operand2struct = float(operand2) except ValueError: operand2struct = saltio.openfits(operand2) is_image = True #open the input image files for infile, outfile in zip(infiles, outfiles): struct = saltio.openfits(infile) #do some math! outstruct = arith(struct, op, operand2struct, is_image, divzero) try: pass except Exception, e: msg = 'Unable to do math %s because %s' % (infile, e) raise SaltError(msg) #update header stuff fname, hist = history(level=1, wrap=False) saltkey.housekeeping(struct[0], 'SARITH', 'Some arithmatic was performed', hist) #write it. close it. saltio.writefits(outstruct, outfile, clobber=clobber) saltio.closefits(struct) #output the information log.message('imarith: %s %s %s %s' % (infile, op, operand2, outfile), with_header=False, with_stdout=verbose) #close the operand2 image if is_image: saltio.closefits(operand2struct)
def med_row_image(arr): """Calculate the median value for each row in the array returns arr """ nrows=len(arr) try: marr=np.zeros((nrows,1),dtype=float) for i in range(nrows): marr[i]=np.median(arr[i]) except Exception, e: raise SaltError('Could not calculate median row values ' + e)
def readspectrum(specfile, stype='continuum', error=True, cols=None, ftype=None): """Given a specfile, read in the spectra and return a spectrum object specfile--file containing the input spectra error--include an error column in the creation of the spectrum object cols--columns or column names for the wavelength, flux, and/or flux error ftype--type of file (ascii or fits) """ # set the ftype for a fits file if ftype is None: if specfile[-5] == '.fits': ftype = 'fits' else: ftype = 'ascii' if ftype == 'ascii': if error: if cols is None: cols = (0, 1, 2) warr, farr, farr_err = np.loadtxt( specfile, usecols=cols, unpack=True) spectra = Spectrum.Spectrum(warr, farr, farr_err, stype=stype) else: if cols is None: cols = (0, 1) warr, farr = np.loadtxt(specfile, usecols=cols, unpack=True) spectra = Spectrum.Spectrum(warr, farr, stype=stype) elif ftype == 'fits': message = 'Support for FITS files not provided yet' raise SaltError(message) else: message = 'Support for %s files is not provided' raise SaltError(message) return spectra
def median2d(arrays,logfile=None): """calculate median of 2d array logfile--depreciated variable """ try: arrays = arrays.ravel() median = np.median(arrays) except Exception, e: median=None message = 'ERROR -- SALTSTAT.MEDIAN2D: Cannot median image arrays because %s' % e raise SaltError(message)
def median_combine(arrays, logfile=None, axis=0): """Median combine a set of arrays logfile--depreciated variable """ status = 0 try: median = np.median(arrays, axis=axis) except Exception, e: median=None message = 'ERROR -- SALTSTAT.MEDIAN_COMBINE: Cannot median combine arrays because %s' % e raise SaltError(message)
def calc_zpcoef(calfile, fpcoef): """Given the values given in the calibraiton file, calculate the offset to the FPA value and FPE value that would give an appropriate calibration values to the frame The task returns the zeropoint coefficient and the initial start time """ #read in the values for the calfile--assumes the format for the file #r,r_err,z,t,w,img=np.loadtxt(calfile, usecols=(0,1,4,5,6,8), unpack=True, dtype={8,str}) data=np.loadtxt(calfile, dtype={'names': ('r','r_err', 'x', 'y', 'z', 't', 'w', 'dn', 'image'),'formats':('f4', 'f4', 'f4', 'f4', 'f4', 'f4', 'f4', 'f4','S30')}) #set the start time and convert the time to a date time unit time_list=[] time_start=None if data.size==0: raise SaltError('%s needs to have at least one entry' % calfile) elif data.size==1: img_list=[str(data['image'])] else: img_list=data['image'] for img in img_list: if not os.path.isfile(img): raise SaltError('%s needs to be available to open' % img) t=get_datetime(saltio.openfits(img)) if time_start is None: time_start=t time_list.append((t-time_start).seconds) time_arr=np.array(time_list) #calculate the coefficients wf=fpfunc(data['z'], data['r'], time_arr, coef=fpcoef) if data.size==1: coef=np.array([0, data['w']-wf]) else: coef=np.polyfit(time_arr, data['w']-wf, 1) return coef, time_start
def slotreadtimefix(images, outimages, outpref, clobber=False, logfile='slot.log', verbose=True): with logging(logfile, debug) as log: # Check the input images infiles = saltio.argunpack('Input', images) # create list of output files outfiles = saltio.listparse('Outfile', outimages, outpref, infiles, '') #verify that the input and output lists are the same length saltio.comparelists(infiles, outfiles, 'Input', 'output') for img, oimg in zip(infiles, outfiles): #check to see if the out image already exists if not clobber and os.path.isfile(oimg): raise SaltIOError('%s alraedy exists' % oimg) #open the file struct = saltio.openfits(img) #log the message log.message('Updateing times in %s' % img, with_header=False, with_stdout=verbose) #now for each science frame, corrent the readtime #Assumes SALT format and that the first extension #is empty for i in range(1, len(struct)): try: struct[i] = readtimefix(struct[i]) except SaltIOError, e: raise SaltError('%s %s' % (img, e)) #Add history keywords # housekeeping keywords fname, hist = history(level=1, wrap=False, exclude=['images', 'outimages', 'outpref']) saltkey.housekeeping(struct[0], "SLOTREAD", 'READTIME added', hist) #write to the output saltio.writefits(struct, oimg, clobber) return
def getpiptemail(sdb, username): #log into database and determine username from proposer name state_select = 'Email' state_from = 'Investigator join PiptUser using (PiptUser_Id)' state_logic = "Username='******'" % username record = select(sdb, state_select, state_from, state_logic) #check to see if it was successful and raise an error if not if len(record) < 1: message = 'SALTFTP--Unable to find username for %s' % pid raise SaltError(message) #only returns the first one return record[0][0]
def getpiptusername(sdb, pid): #log into database and determine username from proposer name state_select = 'distinct p.Username' state_from = 'ProposalCode as c join ProposalContact as pc using (ProposalCode_Id) join Investigator as i on (pc.Contact_Id=i.Investigator_Id) join PiptUser as p using (PiptUser_Id)' state_logic = "c.Proposal_Code='%s'" % pid record = select(sdb, state_select, state_from, state_logic) #check to see if it was successful and raise an error if not if len(record) < 1: message = 'SALTFTP--Unable to find username for %s' % pid raise SaltError(message) #only returns the first one return record[0][0]