Example #1
0
def createobslogfits(headerDict):
   """Create the fits table for the observation log"""
   # define generic columns of output table
   col=[]
   for k, f in zip(headerList, formatList):
       print k,f, headerDict[k]
       col.append(pyfits.Column(name=k, format=f, array=headerDict[k]))
   for k, f in zip(scamheaderList, scamformatList):
       print k,f, headerDict[k]
       col.append(pyfits.Column(name=k, format=f, array=headerDict[k]))
   for k, f in zip(rssheaderList, rssformatList):
       print k,f, headerDict[k]
       col.append(pyfits.Column(name=k, format=f, array=headerDict[k]))
   # construct FITS table from columns
   table = saltio.fitscolumns(col)

   # write FITS table to output file
   struct=saltio.newfitstable(table)

   # name the table extension
   saltkey.new('EXTNAME','OBSLOG','extension name', struct)

   # housekeeping keywords
   saltkey.put('SAL-TLM',time.asctime(time.localtime()), struct)

   return struct
Example #2
0
def addhousekeeping(struct, outhdu, outfile):
    """housekeeping keywords"""

    saltsafekey.put('SAL-TLM', time.asctime(time.localtime()), struct, outfile)
    saltsafekey.new('EXTNAME', 'SCI', 'Extension name', struct, outfile)
    saltsafekey.new('EXTVER', outhdu, 'Extension number', struct, outfile)

    return struct
Example #3
0
def addhousekeeping(struct, outhdu, outfile):
    """housekeeping keywords"""

    saltsafekey.put('SAL-TLM',time.asctime(time.localtime()),struct,outfile)
    saltsafekey.new('EXTNAME','SCI','Extension name',struct,outfile)
    saltsafekey.new('EXTVER',outhdu,'Extension number',struct,outfile)

    return struct
Example #4
0
def saltcrclean(images,outimages,outpref,crtype='fast',thresh=5,mbox=3,         \
                bthresh=3, flux_ratio=0.2, bbox=11, gain=1, rdnoise=5, fthresh=5,\
                bfactor=2, gbox=3, maxiter=5, multithread=False, update=True,
                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')

       #check to see if multithreading is available
       if mp:
          pass
       else:
          multithread=False
          log.warning('multiprocessing module is not available.  Setting multiththread=False')


       # Begin processes each file
       for infile,outfile in zip(infiles,outfiles):

           #open the infile
           struct=saltio.openfits(infile)

           #clean the cosmic rays
           if multithread and len(struct)>1:
               struct=multicrclean(struct, crtype, thresh, mbox, bbox, bthresh, flux_ratio, \
                          gain, rdnoise, bfactor, fthresh, gbox, maxiter, log, verbose=verbose)
           else:
               struct=crclean(struct, crtype, thresh, mbox, bbox, bthresh, flux_ratio, \
                          gain, rdnoise, bfactor, fthresh, gbox, maxiter, update, log, verbose=verbose)
          
           #log the call
           #log.message('Cleaned %i cosmic rays from %s using %s method' % (totcr, infile, crtype), with_header=False)
           log.message('', with_header=False, with_stdout=verbose)

           #add house keeping keywords
           saltkey.put('SAL-TLM',time.asctime(time.localtime()), struct[0])
   
           #add the history keyword
           fname, hist=history(level=1, wrap=False)
           saltkey.history(struct[0],hist)

           #write out the file
           saltio.writefits(struct, outfile, clobber=clobber)

           #close the image
           saltio.closefits(struct)
Example #5
0
def saltcrclean(images,outimages,outpref,crtype='fast',thresh=5,mbox=3,         \
                bthresh=3, flux_ratio=0.2, bbox=11, gain=1, rdnoise=5, fthresh=5,\
                bfactor=2, gbox=3, maxiter=5, multithread=False, update=True,
                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')

        #check to see if multithreading is available
        if mp:
            pass
        else:
            multithread = False
            log.warning(
                'multiprocessing module is not available.  Setting multiththread=False'
            )

        # Begin processes each file
        for infile, outfile in zip(infiles, outfiles):

            #open the infile
            struct = saltio.openfits(infile)

            #clean the cosmic rays
            if multithread and len(struct) > 1:
                struct=multicrclean(struct, crtype, thresh, mbox, bbox, bthresh, flux_ratio, \
                           gain, rdnoise, bfactor, fthresh, gbox, maxiter, log, verbose=verbose)
            else:
                struct=crclean(struct, crtype, thresh, mbox, bbox, bthresh, flux_ratio, \
                           gain, rdnoise, bfactor, fthresh, gbox, maxiter, update, log, verbose=verbose)

            #log the call
            #log.message('Cleaned %i cosmic rays from %s using %s method' % (totcr, infile, crtype), with_header=False)
            log.message('', with_header=False, with_stdout=verbose)

            #add house keeping keywords
            saltkey.put('SAL-TLM', time.asctime(time.localtime()), struct[0])

            #add the history keyword
            fname, hist = history(level=1, wrap=False)
            saltkey.history(struct[0], hist)

            #write out the file
            saltio.writefits(struct, outfile, clobber=clobber)

            #close the image
            saltio.closefits(struct)
Example #6
0
def readtimefix(hdu, dsteps=7, transtime=4e-3):
    """Update the hdu with the correct time for when the exposure started 
       and add the READTIME keyword

       dsteps--the number of readouts to correct for
       transtime--the transfer time between each frame
    """

    #check for if the data has already been processed
    if saltkey.found('READTIME', hdu):
        raise SaltIOError(' has already been processed')

    #determine the UTC time 
    utctime=saltkey.get('UTC-OBS', hdu)
    timeobs=saltkey.get('TIME-OBS', hdu)
    dateobs=saltkey.get('DATE-OBS', hdu)
    exptime=float(saltkey.get('EXPTIME', hdu))

    #add the readtime header
    saltkey.new("READTIME",utctime,'Time of the readout of the frame', hdu)

    #correct the utctime--first switch to datetime to properly handle
    #dates around changes in hours
    y,m,d=dateobs.split('-')
    H,M,S=utctime.split(':')
    s=int(float(S))
    ms=int(1e6*(float(S)-s))
    newtime=datetime.datetime(int(y),int(m),int(d),int(H),int(M),s,ms)

    #correct the datetime
    dtime=dsteps*(exptime+transtime)
    s=int(dtime)
    ms=int(1e6*(dtime-s))
    newtime=newtime-datetime.timedelta(0, s, ms)

    #update the headkeywords
    hdu.header.update("UTC-OBS", str(newtime.time()))
    saltkey.put("UTC-OBS", str(newtime.time()), hdu)
    saltkey.put("TIME-OBS", str(newtime.time()), hdu)
    saltkey.put("DATE-OBS", str(newtime.date()), hdu)

    return hdu
Example #7
0
def readtimefix(hdu, dsteps=7, transtime=4e-3):
    """Update the hdu with the correct time for when the exposure started 
       and add the READTIME keyword

       dsteps--the number of readouts to correct for
       transtime--the transfer time between each frame
    """

    #check for if the data has already been processed
    if saltkey.found('READTIME', hdu):
        raise SaltIOError(' has already been processed')

    #determine the UTC time
    utctime = saltkey.get('UTC-OBS', hdu)
    timeobs = saltkey.get('TIME-OBS', hdu)
    dateobs = saltkey.get('DATE-OBS', hdu)
    exptime = float(saltkey.get('EXPTIME', hdu))

    #add the readtime header
    saltkey.new("READTIME", utctime, 'Time of the readout of the frame', hdu)

    #correct the utctime--first switch to datetime to properly handle
    #dates around changes in hours
    y, m, d = dateobs.split('-')
    H, M, S = utctime.split(':')
    s = int(float(S))
    ms = int(1e6 * (float(S) - s))
    newtime = datetime.datetime(int(y), int(m), int(d), int(H), int(M), s, ms)

    #correct the datetime
    dtime = dsteps * (exptime + transtime)
    s = int(dtime)
    ms = int(1e6 * (dtime - s))
    newtime = newtime - datetime.timedelta(0, s, ms)

    #update the headkeywords
    hdu.header["UTC-OBS"] = str(newtime.time())
    saltkey.put("UTC-OBS", str(newtime.time()), hdu)
    saltkey.put("TIME-OBS", str(newtime.time()), hdu)
    saltkey.put("DATE-OBS", str(newtime.date()), hdu)

    return hdu
Example #8
0
def slotmerge(images, outimages, outpref, geomfile, clobber, logfile, verbose):

    with logging(logfile, debug) as log:
        # are the arguments defined
        saltsafeio.argdefined('images', images)
        saltsafeio.argdefined('geomfile', geomfile)
        saltsafeio.argdefined('logfile', logfile)

        # if the input file is a list, does it exist?
        if images[0] == '@':
            saltsafeio.listexists('Input', images)

        # parse list of input files
        infiles = saltsafeio.listparse('Raw image', images, '', '', '')

        # check input files exist
        saltsafeio.filesexist(infiles, '', 'r')

        # load output name list: @list, * and comma separated
        outimages = outimages.strip()
        outpref = outpref.strip()
        if len(outpref) == 0 and len(outimages) == 0:
            raise SaltIOError('Output file(s) not specified')

        # test output @filelist exists
        if len(outimages) > 0 and outimages[0] == '@':
            saltsafeio.listexists('Output', outimages)

        # parse list of output files
        outfiles = saltsafeio.listparse('Output image', outimages, outpref,
                                        infiles, '')

        # are input and output lists the same length?
        saltsafeio.comparelists(infiles, outfiles, 'Input', 'output')

        # do the output files already exist?
        if not clobber:
            saltsafeio.filesexist(outfiles, '', 'w')

        # does CCD geometry definition file exist
        geomfilefile = geomfile.strip()
        saltsafeio.fileexists(geomfile)

        # read geometry definition file
        gap = 0
        xshift = [0, 0]
        yshift = [0, 0]
        rotation = [0, 0]

        gap, xshift, yshift, rotation = saltsafeio.readccdgeom(geomfile)
        for ro in rotation:
            if ro != 0:
                log.warning('SLOTMERGE currently ignores CCD rotation')

        # Begin processes each file
        for infile, outfile in zip(infiles, outfiles):
            # determine the name for the output file
            outpath = outfile.rstrip(os.path.basename(outfile))
            if (len(outpath) == 0):
                outpath = '.'

            # open each raw image
            struct = saltsafeio.openfits(infile)

            # identify instrument
            instrume, keyprep, keygain, keybias, keyxtalk, keyslot = saltsafekey.instrumid(
                struct, infile)

            # how many amplifiers?
            nccds = saltsafekey.get('NCCDS', struct[0], infile)
            amplifiers = nccds * 2
            #if (nccds != 2):
            #    raise SaltError('Can not currently handle more than two CCDs')

            # CCD geometry coefficients
            if instrume == 'RSS' or instrume == 'PFIS':
                xsh = [xshift[0], 0., xshift[1]]
                ysh = [yshift[0], 0., yshift[1]]
                rot = [rotation[0], 0., rotation[1]]
                refid = 1
            if instrume == 'SALTICAM':
                xsh = [xshift[0], 0.]
                ysh = [yshift[0], 0.]
                rot = [rotation[0], 0]
                refid = 1

            # how many extensions?
            nextend = saltsafekey.get('NEXTEND', struct[0], infile)

            # how many exposures
            exposures = nextend / amplifiers

            # CCD on-chip binning
            xbin, ybin = saltsafekey.ccdbin(struct[0], infile)
            gp = int(gap / xbin)

            # create output hdu structure
            outstruct = [None] * int(exposures + 1)
            outstruct[0] = struct[0]

            # iterate over exposures, stitch them to produce file of CCD images
            for i in range(exposures):
                # Determine the total size of the image
                xsize = 0
                ysize = 0
                for j in range(amplifiers):
                    hdu = i * amplifiers + j + 1
                    try:
                        xsize += len(struct[hdu].data[0])
                        if ysize < len(struct[hdu].data):
                            ysize = len(struct[hdu].data)
                    except:
                        msg = 'Unable to access extension %i ' % hdu
                        raise SaltIOError(msg)
                xsize += gp * (nccds - 1)
                maxxsh, minxsh = determineshifts(xsh)
                maxysh, minysh = determineshifts(ysh)
                xsize += (maxxsh - minxsh)
                ysize += (maxysh - minysh)

                # Determine the x and y origins for each frame
                xdist = 0
                ydist = 0
                shid = 0
                x0 = np.zeros(amplifiers)
                y0 = np.zeros(amplifiers)
                for j in range(amplifiers):
                    x0[j] = xdist + xsh[shid] - minxsh
                    y0[j] = ysh[shid] - minysh
                    hdu = i * amplifiers + j + 1
                    darr = struct[hdu].data
                    xdist += len(darr[0])
                    if j % 2 == 1:
                        xdist += gp
                        shid += 1

                # make the out image
                outarr = np.zeros((ysize, xsize), np.float64)

                # Embed each frame into the output array
                for j in range(amplifiers):
                    hdu = i * amplifiers + j + 1
                    darr = struct[hdu].data
                    outarr = salttran.embed(darr, x0[j], y0[j], outarr)

                # Add the outimage to the output structure
                hdu = i * amplifiers + 1
                outhdu = i + 1
                outstruct[outhdu] = pyfits.ImageHDU(outarr)
                outstruct[outhdu].header = struct[hdu].header

                # Fix the headers in each extension
                datasec = '[1:%4i,1:%4i]' % (xsize, ysize)
                saltsafekey.put('DATASEC', datasec, outstruct[outhdu], outfile)
                saltsafekey.rem('DETSIZE', outstruct[outhdu], outfile)
                saltsafekey.rem('DETSEC', outstruct[outhdu], outfile)
                saltsafekey.rem('CCDSEC', outstruct[outhdu], outfile)
                saltsafekey.rem('AMPSEC', outstruct[outhdu], outfile)

                # add housekeeping key words
                outstruct[outhdu] = addhousekeeping(outstruct[outhdu], outhdu,
                                                    outfile)

            # close input FITS file
            saltsafeio.closefits(struct)

            # housekeeping keywords
            keymosaic = 'SLOTMERG'
            fname, hist = history(level=1, wrap=False)
            saltsafekey.housekeeping(struct[0], keymosaic,
                                     'Amplifiers have been mosaiced', hist)
            #saltsafekey.history(outstruct[0],hist)

            # this is added for later use by
            saltsafekey.put('NCCDS', 0.5, outstruct[0])
            saltsafekey.put('NSCIEXT', exposures, outstruct[0])
            saltsafekey.put('NEXTEND', exposures, outstruct[0])

            # write FITS file of mosaiced image
            outstruct = pyfits.HDUList(outstruct)
            saltsafeio.writefits(outstruct, outfile, clobber=clobber)
Example #9
0
def salteditkey(images,outimages,outpref, keyfile, recfile=None,clobber=False,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')


       #is key file defined
       saltio.argdefined('keyfile',keyfile)
       keyfile = keyfile.strip()
       saltio.fileexists(keyfile)

       # if the data are the same, set up to use update instead of write
       openmode='copyonwrite'
       if (infiles!=outfiles): openmode='copyonwrite'

       # determine the date of the observations
       obsdate=saltstring.makeobsdatestr(infiles, 1,9)
       if len(obsdate)!=8:
           message = 'Either FITS files from multiple dates exist, '
           message += 'or raw FITS files exist with non-standard names.'
           log.warning(message)

       # FITS file columns to record keyword changes
       fitcol = []
       keycol = []
       oldcol = []
       newcol = []

       # Set up the rules to change the files
       keyedits=readkeyfile(keyfile, log=log, verbose=verbose)

       #now step through the images
       for img, oimg in zip(infiles, outfiles):

           #determine the appropriate keyword edits for the image
           klist=[]
           for frange in keyedits:
               if checkfitsfile(img, frange, keyedits[frange]):
                   klist.append(keyedits[frange][3])

           if klist:

               #open up the new files
               struct = saltio.openfits(img,mode=openmode)
               struct.verify('fix')

               for kdict in klist:
                   for keyword in kdict:
                       #record the changes
                       value=kdict[keyword]
                       fitcol.append(img)
                       keycol.append(keyword)
                       newcol.append(value)
                       try:
                           oldcol.append(struct[0].header[keyword].lstrip())
                       except:
                           oldcol.append('None')
                       #update the keyword
                       if saltkey.found(keyword, struct[0]):
                           try:
                               saltkey.put(keyword,value,struct[0])
                               message='\tUpdating %s in %s to %s' % (keyword, os.path.basename(img), value)
                               log.message(message, with_header=False, with_stdout=verbose)
                           except Exception, e:
                               message = 'Could not update %s in %s because %s' % (keyword, img, str(e))
                               raise SaltError(message)
                       else:
                           try:
                               saltkey.new(keyword.strip(),value,'Added Comment',struct[0])
                               message='\tAdding %s in %s to %s' % (keyword, os.path.basename(img), value)
                               log.message(message, with_header=False, with_stdout=verbose)
                           except Exception,e :
                               message = 'Could not update %s in %s because %s' % (keyword, img, str(e))
                               raise SaltError(message)

               #updat the history keywords
               #fname, hist=history(level=1, wrap=False, exclude=['images', 'outimages', 'outpref'])
               #saltkey.housekeeping(struct[0],'SAL-EDT', 'Keywords updated by SALTEDITKEY', hist)

               #write the file out
               if openmode=='update':
                   saltio.updatefits(struct)
                   message = 'Updated file ' + os.path.basename(oimg)
               else:
                   saltio.writefits(struct, oimg, clobber)
                   message = 'Created file ' + os.path.basename(oimg)
               log.message(message, with_header=False, with_stdout=True)

               struct.close()
Example #10
0
        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

    # update the headers
    if utc == saltsafekey.get('UTC-OBS', struct):
        expt_string = '%5.4f' % real_expt
        td_string = '%5.4f' % tdiff
        if not saltsafekey.found('DUTC', struct):
            try:
                saltsafekey.put('UTC-OBS', newutc, struct, infile)
                saltsafekey.put('TIME-OBS', newutc, struct, infile)
                saltsafekey.new('DWETIME', expt_string, 'Dwell Time', struct,
                                infile)
                saltsafekey.new('DUTC', td_string, 'Change in UTC time',
                                struct, infile)
            except Exception, e:
                msg = 'Could not update %i header of image %s because %s' % (
                    ext, infile, e)
                raise SaltIOError(msg)
        else:
            try:
                saltsafekey.put('UTC-OBS', newutc, struct, infile)
                saltsafekey.put('TIME-OBS', newutc, struct, infile)
                saltsafekey.put('DWETIME', real_expt, struct, infile)
                saltsafekey.put('DUTC', tdiff, struct, infile)
Example #11
0
        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

    # update the headers
    if utc==saltsafekey.get('UTC-OBS', struct):
        expt_string='%5.4f' % real_expt
        td_string='%5.4f' % tdiff
        if not saltsafekey.found('DUTC', struct):
            try:
                saltsafekey.put('UTC-OBS', newutc, struct, infile)
                saltsafekey.put('TIME-OBS', newutc, struct, infile)
                saltsafekey.new('DWETIME', expt_string, 'Dwell Time', struct, infile)
                saltsafekey.new('DUTC', td_string, 'Change in UTC time', struct, infile)
            except Exception, e:
                msg='Could not update %i header of image %s because %s' % (ext, infile, e)
                raise SaltIOError(msg)
        else:
            try:
                saltsafekey.put('UTC-OBS', newutc, struct, infile)
                saltsafekey.put('TIME-OBS', newutc, struct, infile)
                saltsafekey.put('DWETIME', real_expt, struct, infile)
                saltsafekey.put('DUTC', tdiff, struct, infile)
            except Exception, e:
                msg='Could not update %i header of image %s because %s' % (ext, infile, e)
                raise SaltError(msg)
Example #12
0
            if saltkey.found('VAREXT', struct[hdu]):
                vhdu = saltkey.get('VAREXT', struct[hdu])
                try:
                    vdata = struct[vhdu].data
                    struct[vhdu].data = vdata * gain * (
                        1 + 2 * gain1 * 1e-6 * data)
                except Exception, e:
                    msg = 'Cannot update the variance frame in %s[%i] because %s' % (
                        infile, vhdu, e)
                    raise SaltError(msg)
        else:
            gainmult = gain

        #update the headers
        if usedb:
            saltkey.put('GAIN', gain, struct[hdu])
            saltkey.put('RDNOISE', rdnoise, struct[hdu])

        #add a keyword indicating what action was taken
        saltkey.new('GAINMULT', gainmult, 'Gain multiplication', struct[hdu])

        #if logging is true, then print out the following information
        if log:
            message = '%25s[%1d] %6s %5s %2s %6.2f %5.2f' \
              % (infile,hdu,gainset,rospeed,amp, gain, rdnoise)
            log.message(message, with_header=False, with_stdout=verbose)

    #just to make it look pretty
    if log:
        log.message('', with_header=False, with_stdout=verbose)
Example #13
0
def slot(struct, infile, dbspeed, dbrate, dbgain, dbnoise, dbbias, dbamp,
         xcoeff, gaindb, xtalkfile, logfile, verbose):

    import saltprint, saltkey, saltio, saltstat, time

    # identify instrument

    instrume, keyprep, keygain, keybias, keyxtalk, keyslot, status = saltkey.instrumid(
        struct, infile, logfile)

    # number of image HDU

    nextend = 0
    while (status == 0):
        try:
            struct[nextend + 1].header['XTENSION']
            nextend += 1
        except:
            break
    nccds, status = saltkey.get('NCCDS', struct[0], infile, logfile)
    amplifiers = nccds * 2
    if (nextend % (amplifiers) != 0):
        message = '\nERROR -- SALTSLOT: Number of image extensions and'
        message += 'number of amplifiers are not consistent'
        status = saltprint.err(saltlog, message)
    status = saltkey.new('NSCIEXT', nextend, 'Number of science extensions',
                         struct[0], infile, logfile)
    status = saltkey.new('NEXTEND', nextend, 'Number of data extensions',
                         struct[0], infile, logfile)

    # check image file and gain database are compatible

    if (status == 0):
        ngains = len(dbgain)
        if (int(max(dbamp)) != amplifiers):
            message = '\nERROR -- SALTGSLOT: ' + infile + ' contains ' + str(
                amplifiers) + ' amplifiers'
            message += ', the gaindb file ' + gaindb + ' contains ' + str(
                max(dbamp)) + ' amplifiers'
            status = saltprint.err(logfile, message)

# check image file and cross talk database are compatible

    if (status == 0):
        if (len(xcoeff) - 1 != amplifiers):
            message = '\nERROR -- SALTSLOT: ' + infile + ' contains ' + str(
                amplifiers) + ' amplifiers'
            message += ', the cross talk file ' + xtalkfile + ' contains ' + str(
                len(xcoeff) - 1) + ' amplifiers'
            status = saltprint.err(logfile, message)

# housekeeping keywords

    if (status == 0):
        status = saltkey.put('SAL-TLM', time.asctime(time.localtime()),
                             struct[0], infile, logfile)
        status = saltkey.new(keyslot, time.asctime(time.localtime()),
                             'Data have been cleaned by SALTSLOT', struct[0],
                             infile, logfile)

# keywords for image extensions

    for i in range(nextend):
        hdu = i + 1
        status = saltkey.new('EXTNAME', 'SCI', 'Extension name', struct[hdu],
                             infile, logfile)
        status = saltkey.new('EXTVER', hdu, 'Extension number', struct[hdu],
                             infile, logfile)

# log coefficent table

    if (status == 0):
        message = '%30s %5s %4s %8s' % ('HDU', 'Gain', 'Bias', 'Xtalk')
        saltprint.log(logfile,
                      '\n     ---------------------------------------------',
                      verbose)
        saltprint.log(logfile, message, verbose)
        saltprint.log(logfile,
                      '     ---------------------------------------------',
                      verbose)

# loop over image extensions

    if (status == 0):
        for i in range(nextend / 2):
            hdu = i * 2 + 1
            amplifier = hdu % amplifiers
            if (amplifier == 0): amplifier = amplifiers
            if (status == 0):
                value, status = saltkey.get('NAXIS1', struct[hdu], infile,
                                            logfile)
                naxis1 = int(value)
            if (status == 0):
                value, status = saltkey.get('NAXIS1', struct[hdu + 1], infile,
                                            logfile)
                naxis2 = int(value)
            if (status == 0 and hdu == 1):
                biassec, status = saltkey.get('BIASSEC', struct[hdu], infile,
                                              logfile)
            if (status == 0 and hdu == 1):
                ranges = biassec.lstrip('[').rstrip(']').split(',')
                x1_1 = int(ranges[0].split(':')[0]) - 1
                x2_1 = int(ranges[0].split(':')[1]) - 1
                y1_1 = int(ranges[1].split(':')[0]) - 1
                y2_1 = int(ranges[1].split(':')[1]) - 1
            if (status == 0 and hdu == 1):
                biassec, status = saltkey.get('BIASSEC', struct[hdu + 1],
                                              infile, logfile)
            if (status == 0 and hdu == 1):
                ranges = biassec.lstrip('[').rstrip(']').split(',')
                x1_2 = int(ranges[0].split(':')[0]) - 1
                x2_2 = int(ranges[0].split(':')[1]) - 1
                y1_2 = int(ranges[1].split(':')[0]) - 1
                y2_2 = int(ranges[1].split(':')[1]) - 1
            if (status == 0 and hdu == 1):
                datasec, status = saltkey.get('DATASEC', struct[hdu], infile,
                                              logfile)
            if (status == 0 and hdu == 1):
                ranges = datasec.lstrip('[').rstrip(']').split(',')
                dx1_1 = int(ranges[0].split(':')[0]) - 1
                dx2_1 = int(ranges[0].split(':')[1])
                dy1_1 = int(ranges[1].split(':')[0]) - 1
                dy2_1 = int(ranges[1].split(':')[1])
            if (status == 0 and hdu == 1):
                datasec, status = saltkey.get('DATASEC', struct[hdu + 1],
                                              infile, logfile)
            if (status == 0 and hdu == 1):
                ranges = datasec.lstrip('[').rstrip(']').split(',')
                dx1_2 = int(ranges[0].split(':')[0]) - 1
                dx2_2 = int(ranges[0].split(':')[1])
                dy1_2 = int(ranges[1].split(':')[0]) - 1
                dy2_2 = int(ranges[1].split(':')[1])
            if (status == 0 and dx2_1 - dx1_1 != dx2_2 - dx1_2):
                message = 'ERROR -- SALTSLOT: HDUs ' + infile
                message += '[' + str(hdu) + '] and ' + infile + '[' + str(
                    hdu + 1) + ']'
                message += ' have different dimensions'
                status = saltprint.err(logfile, message)

# read speed and gain of each exposure

            if (status == 0 and hdu == 1):
                gainset, status = saltkey.get('GAINSET', struct[0], infile,
                                              logfile)
                rospeed, status = saltkey.get('ROSPEED', struct[0], infile,
                                              logfile)
                if (rospeed == 'NONE'):
                    saltprint.log(logfile, " ", verbose)
                    message = "ERROR -- SALTSLOT: Readout speed is 'NONE' in "
                    message += "primary keywords of " + infile
                    status = saltprint.err(logfile, message)

# read raw images

            if (status == 0):
                imagedata1, status = saltio.readimage(struct, hdu, logfile)
                imagedata2, status = saltio.readimage(struct, hdu + 1, logfile)

# gain correction

            if (status == 0):
                for j in range(len(dbgain)):
                    if (gainset == dbrate[j] and rospeed == dbspeed[j]
                            and amplifier == int(dbamp[j])):
                        try:
                            gain1 = float(dbgain[j])
                            imagedata1 *= gain1
                        except:
                            mesage = 'ERROR -- SALTSLOT: Cannot perform gain correction on image '
                            message += infile + '[' + str(hdu) + ']'
                            status = saltprint.err(logfile, message)
                    elif (gainset == dbrate[j] and rospeed == dbspeed[j]
                          and amplifier + 1 == int(dbamp[j])):
                        try:
                            gain2 = float(dbgain[j])
                            imagedata2 *= gain2
                        except:
                            mesage = 'ERROR -- SALTSLOT: Cannot perform gain correction on image '
                            message += infile + '[' + str(hdu + 1) + ']'
                            status = saltprint.err(logfile, message)

# crosstalk correction

            if (status == 0):
                revimage1 = imagedata1 * float(xcoeff[amplifier])
                revimage2 = imagedata2 * float(xcoeff[amplifier + 1])
                for j in range(dx2_1 - dx1_1 + 1):
                    imagedata1[:, j] -= revimage2[:, dx2_2 - j - 1]
                    imagedata2[:, j] -= revimage1[:, dx2_1 - j - 1]

# bias subtraction

            if (status == 0):
                overx_val_1 = []
                overx_val_2 = []
                for x in range(x1_1, x2_1 + 1):
                    list_1 = imagedata1[y1_1:y2_1, x] * 1.0
                    overx_val_1.append(saltstat.median(list_1, logfile))
                    overlevel_1 = saltstat.median(overx_val_1, logfile)
                for x in range(x1_2, x2_2 + 1):
                    list_2 = imagedata2[y1_2:y2_2, x] * 1.0
                    overx_val_2.append(saltstat.median(list_2, logfile))
                    overlevel_2 = saltstat.median(overx_val_2, logfile)
                imagedata1 -= overlevel_1
                imagedata2 -= overlevel_2

# trim overscan

            if (status == 0):
                imagedata1 = imagedata1[dy1_1:dy2_1, dx1_1:dx2_1]
                imagedata2 = imagedata2[dy1_2:dy2_2, dx1_2:dx2_2]
                datasec = '[1:' + str(dx2_1 - dx1_1) + ',1:' + str(dy2_1 -
                                                                   dy1_1) + ']'
                status = saltkey.put('DATASEC', datasec, struct[hdu], infile,
                                     logfile)
                status = saltkey.rem('BIASSEC', struct[hdu], infile, logfile)
                datasec = '[1:' + str(dx2_2 - dx1_2) + ',1:' + str(dy2_2 -
                                                                   dy1_2) + ']'
                status = saltkey.put('DATASEC', datasec, struct[hdu + 1],
                                     infile, logfile)
                status = saltkey.rem('BIASSEC', struct[hdu + 1], infile,
                                     logfile)

# log coefficient table

            if (status == 0):
                infilename = infile.split('/')
                infilename = infilename[len(infilename) - 1]
                message = '%25s[%3d] %5.2f %4d %8.6f' % \
                    (infilename, hdu, gain1, overlevel_1, float(xcoeff[amplifier+1]))
                saltprint.log(logfile, message, verbose)
                message = '%25s[%3d] %5.2f %4d %8.6f' % \
                    (infilename, hdu+1, gain2, overlevel_2,float(xcoeff[amplifier]))
                saltprint.log(logfile, message, verbose)

# update image in HDU structure

            if (status == 0):
                struct, status = saltio.writeimage(struct, hdu, imagedata1,
                                                   logfile)
                struct, status = saltio.writeimage(struct, hdu + 1, imagedata2,
                                                   logfile)

    return struct, status
Example #14
0
def gain(struct,mult=True,usedb=False, dblist=None, ampccd=2, log=None, verbose=True):
   """gain processes a image hduList and gain corrects each amplifier.  It can
      either use gain settings in the header or those supplied in a config file
      which would be suppleid in the dblist (see helpfile for structure of the
      config file).  If variance frames exist, it will update those for changes 
      in the header value as well.   

      In the end, it will update the gain with a value of one signfing the data
      has been transformed into e- from ADU

      The program will look for the non-linear gain settings which are given by:
      e  = GAIN*(1 + GAIN1*E-6*ADU)*ADU

      mult--if true, multiple the gains
      usedb--use the values in the dblist, if false use the header values
      dblist--values for the gain and readnoise from the 
      ampccd--number of amplifiers per ccd

      dblist should have the following lists:  speed, rate, gain, noise, bias, amp
   """
   #get the infile name
   infile=saltkey.getimagename(struct[0])

   #how many science extensions
   nsciext = saltkey.get('NSCIEXT',struct[0])
   #how many data extensions
   nextend = saltkey.get('NSCIEXT',struct[0])

   # how many amplifiers?
   amplifiers = ampccd*saltkey.get('NCCDS',struct[0])

   #read the gain and rospeed for the image
   gainset = saltkey.get('GAINSET',struct[0])
   rospeed = saltkey.get('ROSPEED',struct[0])

   #loop through each amplifier and gain correct it
   if log:
        message = '%28s %6s %5s %3s %5s %5s' \
            % ('HDU','GAIN','SPEED','AMP','GAIN','NOISE')
        log.message('\n      ---------------------------------------------------', \
                    with_header=False, with_stdout=verbose)
        log.message(message, with_header=False, with_stdout=verbose)
        log.message('      ---------------------------------------------------', \
                    with_header=False, with_stdout=verbose)
   for i in range(nsciext):
       hdu = i + 1
       amp = i%amplifiers+1
       #get the gain and rdnoise values for the array 
       if usedb:
           gain, rdnoise=get_values(dblist, gainset, rospeed, amp)
           gain1=0
       else:
           gain = saltkey.get('GAIN',struct[hdu])
           rdnoise = saltkey.get('RDNOISE',struct[hdu])
           try:
               gain1=saltkey.get('GAIN1',struct[hdu])
           except:
               gain1=0
 

       if mult:
           #correct the gain
           gainmult=1
           try:
               data=struct[hdu].data
               struct[hdu].data=gain*data+gain1*data**2
           except Exception as e:
               msg='Cannot gain correct %s[%i] because %s' % (infile, hdu, e)
               raise SaltError(msg)
               
           #correct the variance frame
           if saltkey.found('VAREXT', struct[hdu]):
               vhdu=saltkey.get('VAREXT', struct[hdu])
               try:
                   vdata=struct[vhdu].data
                   struct[vhdu].data=vdata*gain*(1+2*gain1*1e-6*data)
               except Exception as e:
                    msg='Cannot update the variance frame in %s[%i] because %s' % (infile, vhdu, e)
                    raise SaltError(msg)
       else:
           gainmult=gain
 
       #update the headers
       if usedb:
           saltkey.put('GAIN',gain,struct[hdu])
           saltkey.put('RDNOISE',rdnoise,struct[hdu])

       #add a keyword indicating what action was taken
       saltkey.new('GAINMULT',gainmult,'Gain multiplication', struct[hdu])

       #if logging is true, then print out the following information
       if log:
           message = '%25s[%1d] %6s %5s %2s %6.2f %5.2f' \
             % (infile,hdu,gainset,rospeed,amp, gain, rdnoise)
           log.message(message, with_header=False, with_stdout=verbose)

   #just to make it look pretty 
   if log:
       log.message('',  with_header=False, with_stdout=verbose)
          
   return struct
Example #15
0
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 as e:
        msg='Could not update UTC in %i header of image %s because %s' % (ext, infile, e)
        raise SaltError(msg)

        return struct

    # update the headers
    if utc==saltsafekey.get('UTC-OBS', struct):
        expt_string='%5.4f' % real_expt
        td_string='%5.4f' % tdiff
        if not saltsafekey.found('DUTC', struct):
            try:
                saltsafekey.put('UTC-OBS', newutc, struct, infile)
                saltsafekey.put('TIME-OBS', newutc, struct, infile)
                saltsafekey.new('DWETIME', expt_string, 'Dwell Time', struct, infile)
                saltsafekey.new('DUTC', td_string, 'Change in UTC time', struct, infile)
            except Exception as e:
                msg='Could not update %i header of image %s because %s' % (ext, infile, e)
                raise SaltIOError(msg)
        else:
            try:
                saltsafekey.put('UTC-OBS', newutc, struct, infile)
                saltsafekey.put('TIME-OBS', newutc, struct, infile)
                saltsafekey.put('DWETIME', real_expt, struct, infile)
                saltsafekey.put('DUTC', tdiff, struct, infile)
            except Exception as e:
                msg='Could not update %i header of image %s because %s' % (ext, infile, e)
                raise SaltError(msg)
    else:
        raise SaltIOError('Frame missing from list of times')

    return struct
Example #16
0
def bias(struct,
         subover=True,
         trim=True,
         subbias=False,
         bstruct=None,
         median=False,
         function='polynomial',
         order=3,
         rej_lo=3,
         rej_hi=3,
         niter=10,
         plotover=False,
         log=None,
         verbose=True):
    """Bias subtracts the bias levels from a frame.  It will fit and subtract the overscan
      region, trim the images, and subtract a master bias if required.

      struct--image structure 
      subover--subtract the overscan region
      trim--trim the image
      subbias--subtract master bias
      bstruct--master bias image structure
      median--use the median instead of mean in image statistics
      function--form to fit to the overscan region
      order--order for the function
      rej_lo--sigma  of low points to reject in the fit
      rej_hi--sigma of high points to reject in the fit
      niter--number of iterations
      log--saltio log for recording information
      verbose--whether to print to stdout 
   """
    infile = saltkey.getimagename(struct[0])

    # how many extensions?
    nsciext = saltkey.get('NSCIEXT', struct[0])
    nextend = saltkey.get('NEXTEND', struct[0])
    nccd = saltkey.get('NCCDS', struct[0])

    # how many amplifiers?--this is hard wired
    amplifiers = 2 * nccd

    #log the process
    if subover and log:
        message = '%28s %7s %5s %4s %6s' % \
            ('HDU','Overscan','Order','RMS','Niter')
        log.message(
            '\n     --------------------------------------------------',
            with_header=False,
            with_stdout=verbose)
        log.message(message, with_header=False, with_stdout=verbose)
        log.message('     --------------------------------------------------',
                    with_header=False,
                    with_stdout=verbose)

    if (plotover):
        plt.figure(1)
        plt.axes([0.1, 0.1, 0.8, 0.8])
        plt.xlabel('CCD Column')
        plt.ylabel('Pixel Counts (e-)')
        plt.ion()

    #loop through the extensions and subtract the bias
    for i in range(1, nsciext + 1):
        if struct[i].name == 'SCI':

            #get the bias section
            biassec = saltkey.get('BIASSEC', struct[i])
            y1, y2, x1, x2 = saltio.getSection(biassec, iraf_format=True)
            #get the data section
            datasec = saltkey.get('DATASEC', struct[i])
            dy1, dy2, dx1, dx2 = saltio.getSection(datasec, iraf_format=True)

            #setup the overscan region
            if subover:
                yarr = np.arange(y1, y2, dtype=float)
                data = struct[i].data
                odata = struct[i].data[y1:y2, x1:x2]
                if median:
                    odata = np.median((struct[i].data[y1:y2, x1:x2]), axis=1)
                    olevel = np.median((struct[i].data[y1:y2, x1:x2]))
                    saltkey.new('OVERSCAN', '%f' % (olevel),
                                'Overscan median value', struct[i])
                else:
                    odata = np.mean((struct[i].data[y1:y2, x1:x2]), axis=1)
                    olevel = np.mean((struct[i].data[y1:y2, x1:x2]))
                    saltkey.new('OVERSCAN', '%f' % (olevel),
                                'Overscan mean value', struct[i])

                #fit the overscan region
                ifit=saltfit.interfit(yarr, odata, function=function, \
                                      order=order, thresh=rej_hi, niter=niter)
                try:
                    ifit.interfit()
                    coeffs = ifit.coef
                    ofit = ifit(yarr)
                    omean, omed, osigma = saltstat.iterstat((odata - ofit),
                                                            sig=3,
                                                            niter=5)
                except ValueError:
                    #catch the error if it is a zero array
                    ofit = np.array(yarr) * 0.0
                    osigma = 0.0
                except TypeError:
                    #catch the error if it is a zero array
                    ofit = np.array(yarr) * 0.0
                    osigma = 0.0

                #if it hasn't been already, convert image to
                #double format
                struct[i].data = 1.0 * struct[i].data
                try:
                    struct[i].header.remove('BZERO')
                    struct[i].header.remove('BSCALE')
                except:
                    pass

                #subtract the overscan region
                for j in range(len(struct[i].data[0])):
                    struct[i].data[y1:y2, j] -= ofit

                #report the information
                if log:
                    message = '%25s[%1d] %8.2f %3d %7.2f %3d' % \
                        (infile, i, olevel, order, osigma, niter)
                    log.message(message,
                                with_stdout=verbose,
                                with_header=False)

                #add the statistics to the image header
                saltkey.new('OVERRMS', '%f' % (osigma), 'Overscan RMS value',
                            struct[i])

                #update the variance frame
                if saltkey.found('VAREXT', struct[i]):
                    vhdu = saltkey.get('VAREXT', struct[i])
                    try:
                        vdata = struct[vhdu].data
                        #The bias level should not be included in the noise from the signal
                        for j in range(len(struct[i].data[0])):
                            vdata[y1:y2, j] -= ofit
                        #add a bit to make sure that the minimum error is the rednoise
                        rdnoise = saltkey.get('RDNOISE', struct[i])
                        vdata[vdata < rdnoise**2] = rdnoise**2
                        struct[vhdu].data = vdata + osigma**2

                    except Exception, e:
                        msg = 'Cannot update the variance frame in %s[%i] because %s' % (
                            infile, vhdu, e)
                        raise SaltError(msg)

                #plot the overscan region
                if plotover:
                    plt.plot(yarr, odata)
                    plt.plot(yarr, ofit)

            #trim the data and update the headers
            if trim:
                struct[i].data = struct[i].data[dy1:dy2, dx1:dx2]
                datasec = '[1:' + str(dx2 - dx1) + ',1:' + str(dy2 - dy1) + ']'
                saltkey.put('DATASEC', datasec, struct[i])

                #update the variance frame
                if saltkey.found('VAREXT', struct[i]):
                    vhdu = saltkey.get('VAREXT', struct[i])
                    struct[vhdu].data = struct[vhdu].data[dy1:dy2, dx1:dx2]
                    datasec = '[1:' + str(dx2 - dx1) + ',1:' + str(dy2 -
                                                                   dy1) + ']'
                    saltkey.put('DATASEC', datasec, struct[vhdu])
                #update the BPM frame
                if saltkey.found('BPMEXT', struct[i]):
                    bhdu = saltkey.get('BPMEXT', struct[i])
                    struct[bhdu].data = struct[bhdu].data[dy1:dy2, dx1:dx2]
                    datasec = '[1:' + str(dx2 - dx1) + ',1:' + str(dy2 -
                                                                   dy1) + ']'
                    saltkey.put('DATASEC', datasec, struct[bhdu])

            #subtract the master bias if necessary
            if subbias and bstruct:
                struct[i].data -= bstruct[i].data

                #update the variance frame
                if saltkey.found('VAREXT', struct[i]):
                    vhdu = saltkey.get('VAREXT', struct[i])
                    try:
                        vdata = struct[vhdu].data
                        struct[vhdu].data = vdata + bstruct[vhdu].data
                    except Exception, e:
                        msg = 'Cannot update the variance frame in %s[%i] because %s' % (
                            infile, vhdu, e)
                        raise SaltError(msg)
Example #17
0
def make_mosaic(struct,
                gap,
                xshift,
                yshift,
                rotation,
                interp_type='linear',
                boundary='constant',
                constant=0,
                geotran=True,
                fill=False,
                cleanup=True,
                log=None,
                verbose=False):
    """Given a SALT image struct, combine each of the individual amplifiers and
        apply the geometric CCD transformations to the image
    """

    # get the name of the file
    infile = saltkey.getimagename(struct[0], base=True)
    outpath = './'

    # identify instrument
    instrume, keyprep, keygain, keybias, keyxtalk, keyslot = \
        saltkey.instrumid(struct)

    # how many amplifiers?
    nsciext = saltkey.get('NSCIEXT', struct[0])
    nextend = saltkey.get('NEXTEND', struct[0])
    nccds = saltkey.get('NCCDS', struct[0])
    amplifiers = nccds * 2

    if nextend > nsciext:
        varframe = True
    else:
        varframe = False

    # CCD geometry coefficients
    if (instrume == 'RSS' or instrume == 'PFIS'):
        xsh = [0., xshift[0], 0., xshift[1]]
        ysh = [0., yshift[0], 0., yshift[1]]
        rot = [0., rotation[0], 0., rotation[1]]
    elif instrume == 'SALTICAM':
        xsh = [0., xshift[0], 0.]
        ysh = [0., yshift[0], 0.]
        rot = [0., rotation[0], 0]

    # how many extensions?
    nextend = saltkey.get('NEXTEND', struct[0])

    # CCD on-chip binning
    xbin, ybin = saltkey.ccdbin(struct[0])

    # create temporary primary extension
    outstruct = []
    outstruct.append(struct[0])
    # define temporary FITS file store tiled CCDs

    tilefile = saltio.tmpfile(outpath)
    tilefile += 'tile.fits'
    if varframe:
        tilehdu = [None] * (3 * int(nsciext / 2) + 1)
    else:
        tilehdu = [None] * int(nsciext / 2 + 1)
    tilehdu[0] = fits.PrimaryHDU()
    #tilehdu[0].header = struct[0].header

    if log:
        log.message('', with_stdout=verbose)

    # iterate over amplifiers, stich them to produce file of CCD images
    for i in range(int(nsciext / 2)):
        hdu = i * 2 + 1
        # amplifier = hdu%amplifiers
        # if (amplifier == 0): amplifier = amplifiers

        # read DATASEC keywords
        datasec1 = saltkey.get('DATASEC', struct[hdu])
        datasec2 = saltkey.get('DATASEC', struct[hdu + 1])
        xdsec1, ydsec1 = saltstring.secsplit(datasec1)
        xdsec2, ydsec2 = saltstring.secsplit(datasec2)

        # read images
        imdata1 = saltio.readimage(struct, hdu)
        imdata2 = saltio.readimage(struct, hdu + 1)

        # tile 2n amplifiers to yield n CCD images
        outdata = numpy.zeros(
            (int(ydsec1[1] + abs(ysh[i + 1] / ybin)),
             int(xdsec1[1] + xdsec2[1] + abs(xsh[i + 1] / xbin))),
            numpy.float32)

        # set up the variance frame
        if varframe:
            vardata = outdata.copy()
            vdata1 = saltio.readimage(struct, struct[hdu].header['VAREXT'])
            vdata2 = saltio.readimage(struct, struct[hdu + 1].header['VAREXT'])

            bpmdata = outdata.copy()
            bdata1 = saltio.readimage(struct, struct[hdu].header['BPMEXT'])
            bdata2 = saltio.readimage(struct, struct[hdu + 1].header['BPMEXT'])

        x1 = xdsec1[0] - 1
        if x1 != 0:
            msg = 'The data in %s have not been trimmed prior to mosaicking.' \
                  % infile
            log.error(msg)
        if xsh[i + 1] < 0:
            x1 += int(abs(xsh[i + 1] / xbin))
        x2 = x1 + xdsec1[1]
        y1 = ydsec1[0] - 1
        if ysh[i + 1] < 0:
            y1 += int(abs(ysh[i + 1] / ybin))
        y2 = y1 + ydsec1[1]
        outdata[y1:y2, x1:x2] =\
            imdata1[ydsec1[0] - 1:ydsec1[1], xdsec1[0] - 1:xdsec1[1]]

        if varframe:
            vardata[y1:y2, x1:x2] =\
                vdata1[ydsec1[0] - 1:ydsec1[1], xdsec1[0] - 1:xdsec1[1]]
            bpmdata[y1:y2, x1:x2] =\
                bdata1[ydsec1[0] - 1:ydsec1[1], xdsec1[0] - 1:xdsec1[1]]

        x1 = x2
        x2 = x1 + xdsec2[1]
        y1 = ydsec2[0] - 1
        if ysh[i + 1] < 0:
            y1 += abs(ysh[i + 1] / ybin)
        y2 = y1 + ydsec2[1]
        outdata[y1:y2, x1:x2] =\
            imdata2[ydsec1[0] - 1:ydsec1[1], xdsec1[0] - 1:xdsec1[1]]

        if varframe:
            vardata[y1:y2, x1:x2] =\
                vdata2[ydsec1[0] - 1:ydsec1[1], xdsec1[0] - 1:xdsec1[1]]
            bpmdata[y1:y2, x1:x2] =\
                bdata2[ydsec1[0] - 1:ydsec1[1], xdsec1[0] - 1:xdsec1[1]]

        # size of new image
        naxis1 = str(xdsec1[1] + xdsec2[1])
        naxis2 = str(ydsec1[1])

        # add image and keywords to HDU list
        tilehdu[i + 1] = fits.ImageHDU(outdata)
        tilehdu[i + 1].header = struct[hdu].header
        #tilehdu[
        #    i + 1].header['DATASEC'] = '[1:' + naxis1 + ',1:' + naxis2 + ']'

        if varframe:
            vext = i + 1 + int(nsciext / 2.)
            tilehdu[vext] = fits.ImageHDU(vardata)
            #tilehdu[vext].header = struct[struct[hdu].header['VAREXT']].header
            #tilehdu[vext].header[
            #    'DATASEC'] = '[1:' + naxis1 + ',1:' + naxis2 + ']'

            bext = i + 1 + 2 * int(nsciext / 2.)
            tilehdu[bext] = fits.ImageHDU(bpmdata)
            #tilehdu[bext].header = struct[struct[hdu].header['BPMEXT']].header
            #tilehdu[bext].header[
            #    'DATASEC'] = '[1:' + naxis1 + ',1:' + naxis2 + ']'

        # image tile log message #1
        if log:
            message = os.path.basename(infile) + '[' + str(hdu) + ']['
            message += str(xdsec1[0]) + ':' + str(xdsec1[1]) + ','
            message += str(ydsec1[0]) + ':' + str(ydsec1[1]) + '] --> '
            message += os.path.basename(tilefile) + '[' + str(i + 1) + ']['
            message += str(xdsec1[0]) + ':' + str(xdsec1[1]) + ','
            message += str(ydsec1[0]) + ':' + str(ydsec1[1]) + ']'
            log.message(message, with_stdout=verbose, with_header=False)
            message = os.path.basename(infile) + '[' + str(hdu + 1) + ']['
            message += str(xdsec1[0]) + ':' + str(xdsec1[1]) + ','
            message += str(ydsec1[0]) + ':' + str(ydsec1[1]) + '] --> '
            message += os.path.basename(tilefile) + '[' + str(i + 1) + ']['
            message += str(xdsec1[1] + 1) + ':' + \
                str(xdsec1[1] + xdsec2[1]) + ','
            message += str(ydsec2[0]) + ':' + str(ydsec2[1]) + ']'
            log.message(message, with_stdout=verbose, with_header=False)

    # write temporary file of tiled CCDs
    hdulist = fits.HDUList(tilehdu)
    hdulist.writeto(tilefile)

    # iterate over CCDs, transform and rotate images
    yrot = [None] * 4
    xrot = [None] * 4

    tranfile = [' ']
    tranhdu = [0]
    if varframe:
        tranfile = [''] * (3 * int(nsciext / 2) + 1)
        tranhdu = [0] * (3 * int(nsciext / 2) + 1)
    else:
        tranfile = [''] * int(nsciext / 2 + 1)
        tranhdu = [0] * int(nsciext / 2 + 1)

    # this is hardwired for SALT where the second CCD is considered the
    # fiducial
    for hdu in range(1, int(nsciext / 2 + 1)):
        tranfile[hdu] = saltio.tmpfile(outpath)
        tranfile[hdu] += 'tran.fits'
        if varframe:
            tranfile[hdu + nccds] = saltio.tmpfile(outpath) + 'tran.fits'
            tranfile[hdu + 2 * nccds] = saltio.tmpfile(outpath) + 'tran.fits'

        ccd = hdu % nccds
        if (ccd == 0):
            ccd = nccds

        # correct rotation for CCD binning
        yrot[ccd] = rot[ccd] * ybin / xbin
        xrot[ccd] = rot[ccd] * xbin / ybin
        dxshift = xbin * int(float(int(gap) / xbin) + 0.5) - gap

        # transformation using geotran IRAF task
        # if (ccd == 1):
        if (ccd != 2):

            if geotran:
                message = '\nSALTMOSAIC -- geotran ' + tilefile + \
                    '[' + str(ccd) + '] ' + tranfile[hdu]
                message += ' \"\" \"\" xshift=' + \
                    str((xsh[ccd] + (2 - ccd) * dxshift) / xbin) + ' '
                message += 'yshift=' + \
                    str(ysh[ccd] / ybin) + ' xrotation=' + str(xrot[ccd]) + ' '
                message += 'yrotation=' + \
                    str(yrot[ccd]) + ' xmag=1 ymag=1 xmin=\'INDEF\''
                message += 'xmax=\'INDEF\' ymin=\'INDEF\' ymax=\'INDEF\' '
                message += 'ncols=\'INDEF\' '
                message += 'nlines=\'INDEF\' verbose=\'no\' '
                message += 'fluxconserve=\'yes\' nxblock=2048 '
                message += 'nyblock=2048 interpolant=\'' + \
                    interp_type + '\' boundary=\'constant\' constant=0'
                log.message(message, with_stdout=verbose)

                yd, xd = tilehdu[ccd].data.shape
                ncols = 'INDEF'  # ncols=xd+abs(xsh[ccd]/xbin)
                nlines = 'INDEF'  # nlines=yd+abs(ysh[ccd]/ybin)
                geo_xshift = xsh[ccd] + (2 - ccd) * dxshift / xbin
                geo_yshift = ysh[ccd] / ybin
                iraf.images.immatch.geotran(tilefile + "[" + str(ccd) + "]",
                                            tranfile[hdu],
                                            "",
                                            "",
                                            xshift=geo_xshift,
                                            yshift=geo_yshift,
                                            xrotation=xrot[ccd],
                                            yrotation=yrot[ccd],
                                            xmag=1,
                                            ymag=1,
                                            xmin='INDEF',
                                            xmax='INDEF',
                                            ymin='INDEF',
                                            ymax='INDEF',
                                            ncols=ncols,
                                            nlines=nlines,
                                            verbose='no',
                                            fluxconserve='yes',
                                            nxblock=2048,
                                            nyblock=2048,
                                            interpolant="linear",
                                            boundary="constant",
                                            constant=0)
                if varframe:
                    var_infile = tilefile + "[" + str(ccd + nccds) + "]"
                    iraf.images.immatch.geotran(var_infile,
                                                tranfile[hdu + nccds],
                                                "",
                                                "",
                                                xshift=geo_xshift,
                                                yshift=geo_yshift,
                                                xrotation=xrot[ccd],
                                                yrotation=yrot[ccd],
                                                xmag=1,
                                                ymag=1,
                                                xmin='INDEF',
                                                xmax='INDEF',
                                                ymin='INDEF',
                                                ymax='INDEF',
                                                ncols=ncols,
                                                nlines=nlines,
                                                verbose='no',
                                                fluxconserve='yes',
                                                nxblock=2048,
                                                nyblock=2048,
                                                interpolant="linear",
                                                boundary="constant",
                                                constant=0)
                    var2_infile = tilefile + "[" + str(ccd + 2 * nccds) + "]"
                    iraf.images.immatch.geotran(var2_infile,
                                                tranfile[hdu + 2 * nccds],
                                                "",
                                                "",
                                                xshift=geo_xshift,
                                                yshift=geo_yshift,
                                                xrotation=xrot[ccd],
                                                yrotation=yrot[ccd],
                                                xmag=1,
                                                ymag=1,
                                                xmin='INDEF',
                                                xmax='INDEF',
                                                ymin='INDEF',
                                                ymax='INDEF',
                                                ncols=ncols,
                                                nlines=nlines,
                                                verbose='no',
                                                fluxconserve='yes',
                                                nxblock=2048,
                                                nyblock=2048,
                                                interpolant="linear",
                                                boundary="constant",
                                                constant=0)

                # open the file and copy the data to tranhdu
                tstruct = fits.open(tranfile[hdu])
                tranhdu[hdu] = tstruct[0].data
                tstruct.close()
                if varframe:
                    tranhdu[hdu + nccds] = fits.open(tranfile[hdu +
                                                              nccds])[0].data
                    tranhdu[hdu + 2 * nccds] = fits.open(
                        tranfile[hdu + 2 * nccds])[0].data

            else:
                log.message("Transform CCD #%i using dx=%s, dy=%s, rot=%s" %
                            (ccd, xsh[ccd] / 2.0, ysh[ccd] / 2.0, xrot[ccd]),
                            with_stdout=verbose,
                            with_header=False)
                tranhdu[hdu] = geometric_transform(
                    tilehdu[ccd].data,
                    tran_func,
                    prefilter=False,
                    order=1,
                    extra_arguments=(xsh[ccd] / 2, ysh[ccd] / 2, 1, 1,
                                     xrot[ccd], yrot[ccd]))
                tstruct = fits.PrimaryHDU(tranhdu[hdu])
                tstruct.writeto(tranfile[hdu])
                if varframe:
                    tranhdu[hdu + nccds] = geometric_transform(
                        tilehdu[hdu + 3].data,
                        tran_func,
                        prefilter=False,
                        order=1,
                        extra_arguments=(xsh[ccd] / 2, ysh[ccd] / 2, 1, 1,
                                         xrot[ccd], yrot[ccd]))
                    tranhdu[hdu + 2 * nccds] = geometric_transform(
                        tilehdu[hdu + 6].data,
                        tran_func,
                        prefilter=False,
                        order=1,
                        extra_arguments=(xsh[ccd] / 2, ysh[ccd] / 2, 1, 1,
                                         xrot[ccd], yrot[ccd]))

        else:
            log.message("Transform CCD #%i using dx=%s, dy=%s, rot=%s" %
                        (ccd, 0, 0, 0),
                        with_stdout=verbose,
                        with_header=False)
            tranhdu[hdu] = tilehdu[ccd].data
            if varframe:
                tranhdu[hdu + nccds] = tilehdu[ccd + nccds].data
                tranhdu[hdu + 2 * nccds] = tilehdu[ccd + 2 * nccds].data

    # open outfile
    if varframe:
        outlist = 4 * [None]
    else:
        outlist = 2 * [None]

    #outlist[0] = struct[0].copy()
    outlist[0] = fits.PrimaryHDU()
    outlist[0].header = struct[0].header

    naxis1 = int(gap / xbin * (nccds - 1))
    naxis2 = 0
    for i in range(1, nccds + 1):
        yw, xw = tranhdu[i].shape
        naxis1 += xw + int(abs(xsh[ccd] / xbin)) + 1
        naxis2 = max(naxis2, yw)
    outdata = numpy.zeros((naxis2, naxis1), numpy.float32)
    outdata.shape = naxis2, naxis1
    if varframe:
        vardata = outdata * 0
        bpmdata = outdata * 0 + 1

    # iterate over CCDs, stich them to produce a full image
    hdu = 0
    totxshift = 0
    for hdu in range(1, nccds + 1):

        # read DATASEC keywords
        ydsec, xdsec = tranhdu[hdu].shape

        # define size and shape of final image
        # tile CCDs to yield mosaiced image
        x1 = int((hdu - 1) * (xdsec + gap / xbin)) + int(totxshift)
        x2 = xdsec + x1
        y1 = int(0)
        y2 = int(ydsec)
        outdata[y1:y2, x1:x2] = tranhdu[hdu]
        totxshift += int(abs(xsh[hdu] / xbin)) + 1
        if varframe:
            vardata[y1:y2, x1:x2] = tranhdu[hdu + nccds]
            bpmdata[y1:y2, x1:x2] = tranhdu[hdu + 2 * nccds]

    # make sure to cover up all the gaps include bad areas
    if varframe:
        baddata = (outdata == 0)
        baddata = nd.maximum_filter(baddata, size=3)
        bpmdata[baddata] = 1

    # fill in the gaps if requested
    if fill:
        if varframe:
            outdata = fill_gaps(outdata, 0)
        else:
            outdata = fill_gaps(outdata, 0)

    # add to the file
    outlist[1] = fits.ImageHDU(outdata)
    if varframe:
        outlist[2] = fits.ImageHDU(vardata, name='VAR')
        outlist[3] = fits.ImageHDU(bpmdata, name='BPM')

    # create the image structure
    outstruct = fits.HDUList(outlist)

    # update the head informaation
    # housekeeping keywords
    saltkey.put('NEXTEND', 2, outstruct[0])
    saltkey.new('EXTNAME', 'SCI', 'Extension name', outstruct[1])
    saltkey.new('EXTVER', 1, 'Extension number', outstruct[1])
    if varframe:
        saltkey.new('VAREXT', 2, 'Variance frame extension', outstruct[1])
        saltkey.new('BPMEXT', 3, 'BPM Extension', outstruct[1])

    try:
        saltkey.copy(struct[1], outstruct[1], 'CCDSUM')
    except:
        pass

    # Add keywords associated with geometry
    saltkey.new('SGEOMGAP', gap, 'SALT Chip Gap', outstruct[0])
    c1str = '{:3.2f} {:3.2f} {:3.4f}'.format(xshift[0], yshift[0], rotation[0])
    saltkey.new('SGEOM1', c1str, 'SALT Chip 1 Transform', outstruct[0])
    c2str = '{:3.2f} {:3.2f} {:3.4f}'.format(xshift[1], yshift[1], rotation[1])
    saltkey.new('SGEOM2', c2str, 'SALT Chip 2 Transform', outstruct[0])

    # WCS keywords
    saltkey.new('CRPIX1', 0, 'WCS: X reference pixel', outstruct[1])
    saltkey.new('CRPIX2', 0, 'WCS: Y reference pixel', outstruct[1])
    saltkey.new('CRVAL1', float(xbin), 'WCS: X reference coordinate value',
                outstruct[1])
    saltkey.new('CRVAL2', float(ybin), 'WCS: Y reference coordinate value',
                outstruct[1])
    saltkey.new('CDELT1', float(xbin), 'WCS: X pixel size', outstruct[1])
    saltkey.new('CDELT2', float(ybin), 'WCS: Y pixel size', outstruct[1])
    saltkey.new('CTYPE1', 'pixel', 'X type', outstruct[1])
    saltkey.new('CTYPE2', 'pixel', 'Y type', outstruct[1])

    # cleanup temporary files
    if cleanup:
        for tfile in tranfile:
            if os.path.isfile(tfile):
                saltio.delete(tfile)
        if os.path.isfile(tilefile):
            status = saltio.delete(tilefile)

    # return the file
    return outstruct
Example #18
0
def slot(struct,infile,dbspeed,dbrate,dbgain,dbnoise,dbbias,dbamp,xcoeff,gaindb,xtalkfile,
         logfile,verbose):

    import saltprint, saltkey, saltio, saltstat, time

# identify instrument

    instrume,keyprep,keygain,keybias,keyxtalk,keyslot,status = saltkey.instrumid(struct,infile,logfile)

# number of image HDU

    nextend = 0
    while (status == 0):
        try:
            struct[nextend+1].header['XTENSION']
            nextend += 1
        except:
            break
    nccds,status = saltkey.get('NCCDS',struct[0],infile,logfile)
    amplifiers = nccds * 2
    if (nextend%(amplifiers) != 0):
        message = '\nERROR -- SALTSLOT: Number of image extensions and'
        message += 'number of amplifiers are not consistent'
        status = saltprint.err(saltlog,message)
    status = saltkey.new('NSCIEXT',nextend,'Number of science extensions',struct[0],infile,logfile)
    status = saltkey.new('NEXTEND',nextend,'Number of data extensions',struct[0],infile,logfile)

# check image file and gain database are compatible

    if (status == 0):
        ngains = len(dbgain)
        if (int(max(dbamp)) != amplifiers):
            message  = '\nERROR -- SALTGSLOT: ' + infile + ' contains ' + str(amplifiers) + ' amplifiers'
            message += ', the gaindb file ' + gaindb + ' contains ' + str(max(dbamp)) + ' amplifiers'
            status = saltprint.err(logfile,message)

# check image file and cross talk database are compatible

    if (status == 0):
        if (len(xcoeff)-1 != amplifiers):
            message  = '\nERROR -- SALTSLOT: ' + infile + ' contains ' + str(amplifiers) + ' amplifiers'
            message += ', the cross talk file ' + xtalkfile + ' contains ' + str(len(xcoeff)-1) + ' amplifiers'
            status = saltprint.err(logfile,message)

# housekeeping keywords

    if (status == 0):
        status = saltkey.put('SAL-TLM',time.asctime(time.localtime()),struct[0],infile,logfile)
        status = saltkey.new(keyslot,time.asctime(time.localtime()),
                             'Data have been cleaned by SALTSLOT',struct[0],infile,logfile)

# keywords for image extensions

    for i in range(nextend):
        hdu = i + 1
        status = saltkey.new('EXTNAME','SCI','Extension name',struct[hdu],infile,logfile)
        status = saltkey.new('EXTVER',hdu,'Extension number',struct[hdu],infile,logfile)

# log coefficent table

    if (status == 0):
        message = '%30s %5s %4s %8s' % ('HDU','Gain','Bias','Xtalk')
        saltprint.log(logfile,'\n     ---------------------------------------------',verbose)
        saltprint.log(logfile,message,verbose)
        saltprint.log(logfile,'     ---------------------------------------------',verbose)

# loop over image extensions

    if (status == 0):
        for i in range(nextend/2):
            hdu = i * 2 + 1
            amplifier = hdu%amplifiers
            if (amplifier == 0): amplifier = amplifiers
            if (status == 0):
                value,status = saltkey.get('NAXIS1',struct[hdu],infile,logfile)
                naxis1 = int(value)
            if (status == 0):
                value,status = saltkey.get('NAXIS1',struct[hdu+1],infile,logfile)
                naxis2 = int(value)
            if (status == 0 and hdu == 1): biassec, status = saltkey.get('BIASSEC',struct[hdu],infile,logfile)
            if (status == 0 and hdu == 1):
                ranges = biassec.lstrip('[').rstrip(']').split(',')
                x1_1 = int(ranges[0].split(':')[0]) - 1
                x2_1 = int(ranges[0].split(':')[1]) - 1
                y1_1 = int(ranges[1].split(':')[0]) - 1
                y2_1 = int(ranges[1].split(':')[1]) - 1
            if (status == 0 and hdu == 1): biassec, status = saltkey.get('BIASSEC',struct[hdu+1],infile,logfile)
            if (status == 0 and hdu == 1):
                ranges = biassec.lstrip('[').rstrip(']').split(',')
                x1_2 = int(ranges[0].split(':')[0]) - 1
                x2_2 = int(ranges[0].split(':')[1]) - 1
                y1_2 = int(ranges[1].split(':')[0]) - 1
                y2_2 = int(ranges[1].split(':')[1]) - 1
            if (status == 0 and hdu == 1): datasec,status = saltkey.get('DATASEC',struct[hdu],infile,logfile)
            if (status == 0 and hdu == 1):
                ranges = datasec.lstrip('[').rstrip(']').split(',')
                dx1_1 = int(ranges[0].split(':')[0]) - 1
                dx2_1 = int(ranges[0].split(':')[1])
                dy1_1 = int(ranges[1].split(':')[0]) - 1
                dy2_1 = int(ranges[1].split(':')[1])
            if (status == 0 and hdu == 1): datasec,status = saltkey.get('DATASEC',struct[hdu+1],infile,logfile)
            if (status == 0 and hdu == 1):
                ranges = datasec.lstrip('[').rstrip(']').split(',')
                dx1_2 = int(ranges[0].split(':')[0]) - 1
                dx2_2 = int(ranges[0].split(':')[1])
                dy1_2 = int(ranges[1].split(':')[0]) - 1
                dy2_2 = int(ranges[1].split(':')[1])
            if (status == 0 and dx2_1 - dx1_1 != dx2_2 - dx1_2):
                message = 'ERROR -- SALTSLOT: HDUs '+infile
                message += '['+str(hdu)+'] and '+infile+'['+str(hdu+1)+']'
                message += ' have different dimensions'
                status = saltprint.err(logfile,message)

# read speed and gain of each exposure

            if (status == 0 and hdu == 1):
                gainset,status = saltkey.get('GAINSET',struct[0],infile,logfile)
                rospeed,status = saltkey.get('ROSPEED',struct[0],infile,logfile)
                if (rospeed == 'NONE'):
                    saltprint.log(logfile," ",verbose)
                    message = "ERROR -- SALTSLOT: Readout speed is 'NONE' in "
                    message += "primary keywords of " + infile
                    status = saltprint.err(logfile,message)

# read raw images

            if (status == 0):
                imagedata1,status = saltio.readimage(struct,hdu,logfile)
                imagedata2,status = saltio.readimage(struct,hdu+1,logfile)

# gain correction

            if (status == 0):
                for j in range(len(dbgain)):
                    if (gainset == dbrate[j] and rospeed == dbspeed[j] and amplifier == int(dbamp[j])):
                        try:
                            gain1 = float(dbgain[j])
                            imagedata1 *= gain1
                        except:
                            mesage = 'ERROR -- SALTSLOT: Cannot perform gain correction on image '
                            message += infile+'['+str(hdu)+']'
                            status = saltprint.err(logfile,message)
                    elif (gainset == dbrate[j] and rospeed == dbspeed[j] and amplifier + 1 == int(dbamp[j])):
                        try:
                            gain2 = float(dbgain[j])
                            imagedata2 *= gain2
                        except:
                            mesage = 'ERROR -- SALTSLOT: Cannot perform gain correction on image '
                            message += infile+'['+str(hdu+1)+']'
                            status = saltprint.err(logfile,message)

# crosstalk correction

            if (status == 0):
                revimage1 = imagedata1 * float(xcoeff[amplifier])
                revimage2 = imagedata2 * float(xcoeff[amplifier+1])
                for j in range(dx2_1-dx1_1+1):
                    imagedata1[:,j] -= revimage2[:,dx2_2-j-1]
                    imagedata2[:,j] -= revimage1[:,dx2_1-j-1]

# bias subtraction

            if (status == 0):
                overx_val_1 = []
                overx_val_2 = []
                for x in range(x1_1,x2_1+1):
                    list_1 = imagedata1[y1_1:y2_1,x] * 1.0
                    overx_val_1.append(saltstat.median(list_1,logfile))
                    overlevel_1 = saltstat.median(overx_val_1,logfile)
                for x in range(x1_2,x2_2+1):
                    list_2 = imagedata2[y1_2:y2_2,x] * 1.0
                    overx_val_2.append(saltstat.median(list_2,logfile))
                    overlevel_2 = saltstat.median(overx_val_2,logfile)
                imagedata1 -= overlevel_1
                imagedata2 -= overlevel_2

# trim overscan

            if (status == 0):
                imagedata1 = imagedata1[dy1_1:dy2_1,dx1_1:dx2_1]
                imagedata2 = imagedata2[dy1_2:dy2_2,dx1_2:dx2_2]
                datasec = '[1:'+str(dx2_1-dx1_1)+',1:'+str(dy2_1-dy1_1)+']'
                status = saltkey.put('DATASEC',datasec,struct[hdu],infile,logfile)
                status = saltkey.rem('BIASSEC',struct[hdu],infile,logfile)
                datasec = '[1:'+str(dx2_2-dx1_2)+',1:'+str(dy2_2-dy1_2)+']'
                status = saltkey.put('DATASEC',datasec,struct[hdu+1],infile,logfile)
                status = saltkey.rem('BIASSEC',struct[hdu+1],infile,logfile)

# log coefficient table

            if (status == 0):
                infilename = infile.split('/')
                infilename = infilename[len(infilename)-1]
                message = '%25s[%3d] %5.2f %4d %8.6f' % \
                    (infilename, hdu, gain1, overlevel_1, float(xcoeff[amplifier+1]))
                saltprint.log(logfile,message,verbose)
                message = '%25s[%3d] %5.2f %4d %8.6f' % \
                    (infilename, hdu+1, gain2, overlevel_2,float(xcoeff[amplifier]))
                saltprint.log(logfile,message,verbose)

# update image in HDU structure

            if (status == 0):
                struct,status = saltio.writeimage(struct,hdu,imagedata1,logfile)
                struct,status = saltio.writeimage(struct,hdu+1,imagedata2,logfile)

    return struct, status
Example #19
0
def make_mosaic(struct, gap, xshift, yshift, rotation, interp_type='linear',
                boundary='constant', constant=0, geotran=True, fill=False,
                cleanup=True, log=None, verbose=False):
    """Given a SALT image struct, combine each of the individual amplifiers and
        apply the geometric CCD transformations to the image
    """

    # get the name of the file
    infile = saltkey.getimagename(struct[0], base=True)
    outpath = './'

    # identify instrument
    instrume, keyprep, keygain, keybias, keyxtalk, keyslot = \
        saltkey.instrumid(struct)

    # how many amplifiers?
    nsciext = saltkey.get('NSCIEXT', struct[0])
    nextend = saltkey.get('NEXTEND', struct[0])
    nccds = saltkey.get('NCCDS', struct[0])
    amplifiers = nccds * 2

    if nextend > nsciext:
        varframe = True
    else:
        varframe = False

    # CCD geometry coefficients
    if (instrume == 'RSS' or instrume == 'PFIS'):
        xsh = [0., xshift[0], 0., xshift[1]]
        ysh = [0., yshift[0], 0., yshift[1]]
        rot = [0., rotation[0], 0., rotation[1]]
    elif instrume == 'SALTICAM':
        xsh = [0., xshift[0], 0.]
        ysh = [0., yshift[0], 0.]
        rot = [0., rotation[0], 0]

    # how many extensions?
    nextend = saltkey.get('NEXTEND', struct[0])

    # CCD on-chip binning
    xbin, ybin = saltkey.ccdbin(struct[0])

    # create temporary primary extension
    outstruct = []
    outstruct.append(struct[0])
    # define temporary FITS file store tiled CCDs

    tilefile = saltio.tmpfile(outpath)
    tilefile += 'tile.fits'
    if varframe:
        tilehdu = [None] * (3 * int(nsciext / 2) + 1)
    else:
        tilehdu = [None] * int(nsciext / 2 + 1)
    tilehdu[0] = fits.PrimaryHDU()
    #tilehdu[0].header = struct[0].header

    if log:
        log.message('', with_stdout=verbose)

    # iterate over amplifiers, stich them to produce file of CCD images
    for i in range(int(nsciext / 2)):
        hdu = i * 2 + 1
        # amplifier = hdu%amplifiers
        # if (amplifier == 0): amplifier = amplifiers

        # read DATASEC keywords
        datasec1 = saltkey.get('DATASEC', struct[hdu])
        datasec2 = saltkey.get('DATASEC', struct[hdu + 1])
        xdsec1, ydsec1 = saltstring.secsplit(datasec1)
        xdsec2, ydsec2 = saltstring.secsplit(datasec2)

        # read images
        imdata1 = saltio.readimage(struct, hdu)
        imdata2 = saltio.readimage(struct, hdu + 1)

        # tile 2n amplifiers to yield n CCD images
        outdata = numpy.zeros((ydsec1[1] +
                               abs(ysh[i +
                                       1] /
                                   ybin), xdsec1[1] +
                               xdsec2[1] +
                               abs(xsh[i +
                                       1] /
                                   xbin)), numpy.float32)

        # set up the variance frame
        if varframe:
            vardata = outdata.copy()
            vdata1 = saltio.readimage(struct, struct[hdu].header['VAREXT'])
            vdata2 = saltio.readimage(struct, struct[hdu + 1].header['VAREXT'])

            bpmdata = outdata.copy()
            bdata1 = saltio.readimage(struct, struct[hdu].header['BPMEXT'])
            bdata2 = saltio.readimage(struct, struct[hdu + 1].header['BPMEXT'])

        x1 = xdsec1[0] - 1
        if x1 != 0:
            msg = 'The data in %s have not been trimmed prior to mosaicking.' \
                  % infile
            log.error(msg)
        if xsh[i + 1] < 0:
            x1 += abs(xsh[i + 1] / xbin)
        x2 = x1 + xdsec1[1]
        y1 = ydsec1[0] - 1
        if ysh[i + 1] < 0:
            y1 += abs(ysh[i + 1] / ybin)
        y2 = y1 + ydsec1[1]
        outdata[y1:y2, x1:x2] =\
            imdata1[ydsec1[0] - 1:ydsec1[1], xdsec1[0] - 1:xdsec1[1]]

        if varframe:
            vardata[y1:y2, x1:x2] =\
                vdata1[ydsec1[0] - 1:ydsec1[1], xdsec1[0] - 1:xdsec1[1]]
            bpmdata[y1:y2, x1:x2] =\
                bdata1[ydsec1[0] - 1:ydsec1[1], xdsec1[0] - 1:xdsec1[1]]

        x1 = x2
        x2 = x1 + xdsec2[1]
        y1 = ydsec2[0] - 1
        if ysh[i + 1] < 0:
            y1 += abs(ysh[i + 1] / ybin)
        y2 = y1 + ydsec2[1]
        outdata[y1:y2, x1:x2] =\
            imdata2[ydsec1[0] - 1:ydsec1[1], xdsec1[0] - 1:xdsec1[1]]

        if varframe:
            vardata[y1:y2, x1:x2] =\
                vdata2[ydsec1[0] - 1:ydsec1[1], xdsec1[0] - 1:xdsec1[1]]
            bpmdata[y1:y2, x1:x2] =\
                bdata2[ydsec1[0] - 1:ydsec1[1], xdsec1[0] - 1:xdsec1[1]]

        # size of new image
        naxis1 = str(xdsec1[1] + xdsec2[1])
        naxis2 = str(ydsec1[1])

        # add image and keywords to HDU list
        tilehdu[i + 1] = fits.ImageHDU(outdata)
        tilehdu[i + 1].header = struct[hdu].header
        #tilehdu[
        #    i + 1].header['DATASEC'] = '[1:' + naxis1 + ',1:' + naxis2 + ']'

        if varframe:
            vext = i + 1 + int(nsciext / 2.)
            tilehdu[vext] = fits.ImageHDU(vardata)
            #tilehdu[vext].header = struct[struct[hdu].header['VAREXT']].header
            #tilehdu[vext].header[
            #    'DATASEC'] = '[1:' + naxis1 + ',1:' + naxis2 + ']'

            bext = i + 1 + 2 * int(nsciext / 2.)
            tilehdu[bext] = fits.ImageHDU(bpmdata)
            #tilehdu[bext].header = struct[struct[hdu].header['BPMEXT']].header
            #tilehdu[bext].header[
            #    'DATASEC'] = '[1:' + naxis1 + ',1:' + naxis2 + ']'

        # image tile log message #1
        if log:
            message = os.path.basename(infile) + '[' + str(hdu) + ']['
            message += str(xdsec1[0]) + ':' + str(xdsec1[1]) + ','
            message += str(ydsec1[0]) + ':' + str(ydsec1[1]) + '] --> '
            message += os.path.basename(tilefile) + '[' + str(i + 1) + ']['
            message += str(xdsec1[0]) + ':' + str(xdsec1[1]) + ','
            message += str(ydsec1[0]) + ':' + str(ydsec1[1]) + ']'
            log.message(message, with_stdout=verbose, with_header=False)
            message = os.path.basename(infile) + '[' + str(hdu + 1) + ']['
            message += str(xdsec1[0]) + ':' + str(xdsec1[1]) + ','
            message += str(ydsec1[0]) + ':' + str(ydsec1[1]) + '] --> '
            message += os.path.basename(tilefile) + '[' + str(i + 1) + ']['
            message += str(xdsec1[1] + 1) + ':' + \
                str(xdsec1[1] + xdsec2[1]) + ','
            message += str(ydsec2[0]) + ':' + str(ydsec2[1]) + ']'
            log.message(message, with_stdout=verbose, with_header=False)

    # write temporary file of tiled CCDs
    hdulist = fits.HDUList(tilehdu)
    hdulist.writeto(tilefile)

    # iterate over CCDs, transform and rotate images
    yrot = [None] * 4
    xrot = [None] * 4

    tranfile = [' ']
    tranhdu = [0]
    if varframe:
        tranfile = [''] * (3 * int(nsciext / 2) + 1)
        tranhdu = [0] * (3 * int(nsciext / 2) + 1)
    else:
        tranfile = [''] * int(nsciext / 2 + 1)
        tranhdu = [0] * int(nsciext / 2 + 1)

    # this is hardwired for SALT where the second CCD is considered the
    # fiducial
    for hdu in range(1, int(nsciext / 2 + 1)):
        tranfile[hdu] = saltio.tmpfile(outpath)
        tranfile[hdu] += 'tran.fits'
        if varframe:
            tranfile[hdu + nccds] = saltio.tmpfile(outpath) + 'tran.fits'
            tranfile[hdu + 2 * nccds] = saltio.tmpfile(outpath) + 'tran.fits'

        ccd = hdu % nccds
        if (ccd == 0):
            ccd = nccds

        # correct rotation for CCD binning
        yrot[ccd] = rot[ccd] * ybin / xbin
        xrot[ccd] = rot[ccd] * xbin / ybin
        dxshift = xbin * int(float(int(gap) / xbin) + 0.5) - gap

        # transformation using geotran IRAF task
        # if (ccd == 1):
        if (ccd != 2):

            if geotran:
                message = '\nSALTMOSAIC -- geotran ' + tilefile + \
                    '[' + str(ccd) + '] ' + tranfile[hdu]
                message += ' \"\" \"\" xshift=' + \
                    str((xsh[ccd] + (2 - ccd) * dxshift) / xbin) + ' '
                message += 'yshift=' + \
                    str(ysh[ccd] / ybin) + ' xrotation=' + str(xrot[ccd]) + ' '
                message += 'yrotation=' + \
                    str(yrot[ccd]) + ' xmag=1 ymag=1 xmin=\'INDEF\''
                message += 'xmax=\'INDEF\' ymin=\'INDEF\' ymax=\'INDEF\' '
                message += 'ncols=\'INDEF\' '
                message += 'nlines=\'INDEF\' verbose=\'no\' '
                message += 'fluxconserve=\'yes\' nxblock=2048 '
                message += 'nyblock=2048 interpolant=\'' + \
                    interp_type + '\' boundary=\'constant\' constant=0'
                log.message(message, with_stdout=verbose)

                yd, xd = tilehdu[ccd].data.shape
                ncols = 'INDEF'  # ncols=xd+abs(xsh[ccd]/xbin)
                nlines = 'INDEF'  # nlines=yd+abs(ysh[ccd]/ybin)
                geo_xshift = xsh[ccd] + (2 - ccd) * dxshift / xbin
                geo_yshift = ysh[ccd] / ybin
                iraf.images.immatch.geotran(tilefile + "[" + str(ccd) + "]",
                                            tranfile[hdu],
                                            "",
                                            "",
                                            xshift=geo_xshift,
                                            yshift=geo_yshift,
                                            xrotation=xrot[ccd],
                                            yrotation=yrot[ccd],
                                            xmag=1, ymag=1, xmin='INDEF',
                                            xmax='INDEF', ymin='INDEF',
                                            ymax='INDEF', ncols=ncols,
                                            nlines=nlines, verbose='no',
                                            fluxconserve='yes', nxblock=2048,
                                            nyblock=2048, interpolant="linear",
                                            boundary="constant", constant=0)
                if varframe:
                    var_infile = tilefile + "[" + str(ccd + nccds) + "]"
                    iraf.images.immatch.geotran(var_infile,
                                                tranfile[hdu + nccds],
                                                "",
                                                "",
                                                xshift=geo_xshift,
                                                yshift=geo_yshift,
                                                xrotation=xrot[ccd],
                                                yrotation=yrot[ccd],
                                                xmag=1, ymag=1, xmin='INDEF',
                                                xmax='INDEF', ymin='INDEF',
                                                ymax='INDEF', ncols=ncols,
                                                nlines=nlines, verbose='no',
                                                fluxconserve='yes',
                                                nxblock=2048, nyblock=2048,
                                                interpolant="linear",
                                                boundary="constant",
                                                constant=0)
                    var2_infile = tilefile + "[" + str(ccd + 2 * nccds) + "]"
                    iraf.images.immatch.geotran(var2_infile,
                                                tranfile[hdu + 2 * nccds],
                                                "",
                                                "",
                                                xshift=geo_xshift,
                                                yshift=geo_yshift,
                                                xrotation=xrot[ccd],
                                                yrotation=yrot[ccd],
                                                xmag=1, ymag=1, xmin='INDEF',
                                                xmax='INDEF', ymin='INDEF',
                                                ymax='INDEF', ncols=ncols,
                                                nlines=nlines, verbose='no',
                                                fluxconserve='yes',
                                                nxblock=2048, nyblock=2048,
                                                interpolant="linear",
                                                boundary="constant",
                                                constant=0)

                # open the file and copy the data to tranhdu
                tstruct = fits.open(tranfile[hdu])
                tranhdu[hdu] = tstruct[0].data
                tstruct.close()
                if varframe:
                    tranhdu[
                        hdu +
                        nccds] = fits.open(
                        tranfile[
                            hdu +
                            nccds])[0].data
                    tranhdu[
                        hdu +
                        2 *
                        nccds] = fits.open(
                        tranfile[
                            hdu +
                            2 *
                            nccds])[0].data

            else:
                log.message(
                    "Transform CCD #%i using dx=%s, dy=%s, rot=%s" %
                    (ccd,
                     xsh[ccd] /
                        2.0,
                        ysh[ccd] /
                        2.0,
                        xrot[ccd]),
                    with_stdout=verbose,
                    with_header=False)
                tranhdu[hdu] = geometric_transform(
                    tilehdu[ccd].data,
                    tran_func,
                    prefilter=False,
                    order=1,
                    extra_arguments=(
                        xsh[ccd] / 2,
                        ysh[ccd] / 2,
                        1,
                        1,
                        xrot[ccd],
                        yrot[ccd]))
                tstruct = fits.PrimaryHDU(tranhdu[hdu])
                tstruct.writeto(tranfile[hdu])
                if varframe:
                    tranhdu[hdu + nccds] = geometric_transform(
                        tilehdu[hdu + 3].data,
                        tran_func,
                        prefilter=False,
                        order=1,
                        extra_arguments=(
                            xsh[ccd] / 2, ysh[ccd] / 2,
                            1, 1,
                            xrot[ccd], yrot[ccd]))
                    tranhdu[hdu + 2 * nccds] = geometric_transform(
                        tilehdu[hdu + 6].data,
                        tran_func,
                        prefilter=False,
                        order=1,
                        extra_arguments=(
                            xsh[ccd] / 2, ysh[ccd] / 2,
                            1, 1,
                            xrot[ccd], yrot[ccd]))

        else:
            log.message(
                "Transform CCD #%i using dx=%s, dy=%s, rot=%s" %
                (ccd, 0, 0, 0), with_stdout=verbose, with_header=False)
            tranhdu[hdu] = tilehdu[ccd].data
            if varframe:
                tranhdu[hdu + nccds] = tilehdu[ccd + nccds].data
                tranhdu[hdu + 2 * nccds] = tilehdu[ccd + 2 * nccds].data

    # open outfile
    if varframe:
        outlist = 4 * [None]
    else:
        outlist = 2 * [None]

    #outlist[0] = struct[0].copy()
    outlist[0] = fits.PrimaryHDU()
    outlist[0].header = struct[0].header

    naxis1 = int(gap / xbin * (nccds - 1))
    naxis2 = 0
    for i in range(1, nccds + 1):
        yw, xw = tranhdu[i].shape
        naxis1 += xw + int(abs(xsh[ccd] / xbin)) + 1
        naxis2 = max(naxis2, yw)
    outdata = numpy.zeros((naxis2, naxis1), numpy.float32)
    outdata.shape = naxis2, naxis1
    if varframe:
        vardata = outdata * 0
        bpmdata = outdata * 0 + 1

    # iterate over CCDs, stich them to produce a full image
    hdu = 0
    totxshift = 0
    for hdu in range(1, nccds + 1):

        # read DATASEC keywords
        ydsec, xdsec = tranhdu[hdu].shape

        # define size and shape of final image
        # tile CCDs to yield mosaiced image
        x1 = int((hdu - 1) * (xdsec + gap / xbin)) + int(totxshift)
        x2 = xdsec + x1
        y1 = int(0)
        y2 = int(ydsec)
        outdata[y1:y2, x1:x2] = tranhdu[hdu]
        totxshift += int(abs(xsh[hdu] / xbin)) + 1
        if varframe:
            vardata[y1:y2, x1:x2] = tranhdu[hdu + nccds]
            bpmdata[y1:y2, x1:x2] = tranhdu[hdu + 2 * nccds]

    # make sure to cover up all the gaps include bad areas
    if varframe:
        baddata = (outdata == 0)
        baddata = nd.maximum_filter(baddata, size=3)
        bpmdata[baddata] = 1
        

    # fill in the gaps if requested
    if fill:
        if varframe:
            outdata = fill_gaps(outdata, 0)
        else:
            outdata = fill_gaps(outdata, 0)

    # add to the file
    outlist[1] = fits.ImageHDU(outdata)
    if varframe:
        outlist[2] = fits.ImageHDU(vardata,name='VAR')
        outlist[3] = fits.ImageHDU(bpmdata,name='BPM')

    # create the image structure
    outstruct = fits.HDUList(outlist)

    # update the head informaation
    # housekeeping keywords
    saltkey.put('NEXTEND', 2, outstruct[0])
    saltkey.new('EXTNAME', 'SCI', 'Extension name', outstruct[1])
    saltkey.new('EXTVER', 1, 'Extension number', outstruct[1])
    if varframe:
        saltkey.new('VAREXT', 2, 'Variance frame extension', outstruct[1])
        saltkey.new('BPMEXT', 3, 'BPM Extension', outstruct[1])

    try:
        saltkey.copy(struct[1], outstruct[1], 'CCDSUM')
    except:
        pass

    # Add keywords associated with geometry
    saltkey.new('SGEOMGAP', gap, 'SALT Chip Gap', outstruct[0])
    c1str = '{:3.2f} {:3.2f} {:3.4f}'.format(xshift[0],
                                     yshift[0],
                                     rotation[0])
    saltkey.new('SGEOM1', c1str, 'SALT Chip 1 Transform', outstruct[0])
    c2str = '{:3.2f} {:3.2f} {:3.4f}'.format(xshift[1],
                                     yshift[1],
                                     rotation[1])
    saltkey.new('SGEOM2', c2str, 'SALT Chip 2 Transform', outstruct[0])

    # WCS keywords
    saltkey.new('CRPIX1', 0, 'WCS: X reference pixel', outstruct[1])
    saltkey.new('CRPIX2', 0, 'WCS: Y reference pixel', outstruct[1])
    saltkey.new(
        'CRVAL1',
        float(xbin),
        'WCS: X reference coordinate value',
        outstruct[1])
    saltkey.new(
        'CRVAL2',
        float(ybin),
        'WCS: Y reference coordinate value',
        outstruct[1])
    saltkey.new('CDELT1', float(xbin), 'WCS: X pixel size', outstruct[1])
    saltkey.new('CDELT2', float(ybin), 'WCS: Y pixel size', outstruct[1])
    saltkey.new('CTYPE1', 'pixel', 'X type', outstruct[1])
    saltkey.new('CTYPE2', 'pixel', 'Y type', outstruct[1])

    # cleanup temporary files
    if cleanup:
        for tfile in tranfile:
            if os.path.isfile(tfile):
                saltio.delete(tfile)
        if os.path.isfile(tilefile):
            status = saltio.delete(tilefile)

    # return the file
    return outstruct
Example #20
0
def slotmerge(images,outimages,outpref,geomfile,clobber,logfile,verbose):

    with logging(logfile,debug) as log:
        # are the arguments defined
        saltsafeio.argdefined('images',images)
        saltsafeio.argdefined('geomfile',geomfile)
        saltsafeio.argdefined('logfile',logfile)

        # if the input file is a list, does it exist?
        if images[0] == '@':
            saltsafeio.listexists('Input',images)

        # parse list of input files
        infiles=saltsafeio.listparse('Raw image',images,'','','')

        # check input files exist
        saltsafeio.filesexist(infiles,'','r')

        # load output name list: @list, * and comma separated
        outimages = outimages.strip()
        outpref = outpref.strip()
        if len(outpref) == 0 and len(outimages) == 0:
            raise SaltIOError('Output file(s) not specified')

        # test output @filelist exists
        if len(outimages) > 0 and outimages[0] == '@':
            saltsafeio.listexists('Output',outimages)

        # parse list of output files
        outfiles=saltsafeio.listparse('Output image',outimages,outpref,infiles,'')

        # are input and output lists the same length?
        saltsafeio.comparelists(infiles,outfiles,'Input','output')

        # do the output files already exist?
        if not clobber:
            saltsafeio.filesexist(outfiles,'','w')

        # does CCD geometry definition file exist
        geomfilefile = geomfile.strip()
        saltsafeio.fileexists(geomfile)

        # read geometry definition file
        gap = 0
        xshift = [0, 0]
        yshift = [0, 0]
        rotation = [0, 0]

        gap, xshift, yshift, rotation=saltsafeio.readccdgeom(geomfile)
        for ro in rotation:
            if ro!=0:
                log.warning('SLOTMERGE currently ignores CCD rotation')

        # Begin processes each file
        for infile, outfile in zip(infiles, outfiles):
            # determine the name for the output file
            outpath = outfile.rstrip(os.path.basename(outfile))
            if (len(outpath) == 0):
                outpath = '.'

            # open each raw image
            struct=saltsafeio.openfits(infile)

            # identify instrument
            instrume,keyprep,keygain,keybias,keyxtalk,keyslot=saltsafekey.instrumid(struct,infile)

            # how many amplifiers?
            nccds=saltsafekey.get('NCCDS',struct[0],infile)
            amplifiers = nccds * 2
            #if (nccds != 2):
            #    raise SaltError('Can not currently handle more than two CCDs')

            # CCD geometry coefficients
            if instrume == 'RSS' or instrume == 'PFIS':
                xsh = [xshift[0], 0., xshift[1]]
                ysh = [yshift[0], 0., yshift[1]]
                rot = [rotation[0], 0., rotation[1]]
                refid = 1
            if instrume == 'SALTICAM':
                xsh = [xshift[0], 0.]
                ysh = [yshift[0], 0.]
                rot = [rotation[0], 0]
                refid = 1

            # how many extensions?
            nextend=saltsafekey.get('NEXTEND',struct[0],infile)

            # how many exposures
            exposures = nextend/amplifiers

            # CCD on-chip binning
            xbin, ybin=saltsafekey.ccdbin(struct[0],infile)
            gp = int(gap / xbin)

            # create output hdu structure
            outstruct = [None] * int(exposures+1)
            outstruct[0]=struct[0]

            # iterate over exposures, stitch them to produce file of CCD images
            for i in range(exposures):
                # Determine the total size of the image
                xsize=0
                ysize=0
                for j in range(amplifiers):
                    hdu=i*amplifiers+j+1
                    try:
                        xsize += len(struct[hdu].data[0])
                        if ysize < len(struct[hdu].data):
                            ysize=len(struct[hdu].data)
                    except:
                        msg='Unable to access extension %i ' % hdu
                        raise SaltIOError(msg)
                xsize += gp* (nccds-1)
                maxxsh, minxsh = determineshifts(xsh)
                maxysh, minysh = determineshifts(ysh)
                xsize += (maxxsh-minxsh)
                ysize += (maxysh-minysh)

                # Determine the x and y origins for each frame
                xdist=0
                ydist=0
                shid=0
                x0=np.zeros(amplifiers)
                y0=np.zeros(amplifiers)
                for j in range(amplifiers):
                    x0[j]=xdist+xsh[shid]-minxsh
                    y0[j]=ysh[shid]-minysh
                    hdu=i*amplifiers+j+1
                    darr=struct[hdu].data
                    xdist += len(darr[0])
                    if j%2==1:
                        xdist += gp
                        shid += 1

                # make the out image
                outarr=np.zeros((ysize, xsize), np.float64)

                # Embed each frame into the output array
                for j in range(amplifiers):
                    hdu=i*amplifiers+j+1
                    darr=struct[hdu].data
                    outarr=salttran.embed(darr, x0[j], y0[j], outarr)

                # Add the outimage to the output structure
                hdu=i*amplifiers+1
                outhdu=i+1
                outstruct[outhdu] = pyfits.ImageHDU(outarr)
                outstruct[outhdu].header=struct[hdu].header

                # Fix the headers in each extension
                datasec='[1:%4i,1:%4i]' % (xsize, ysize)
                saltsafekey.put('DATASEC',datasec, outstruct[outhdu], outfile)
                saltsafekey.rem('DETSIZE',outstruct[outhdu],outfile)
                saltsafekey.rem('DETSEC',outstruct[outhdu],outfile)
                saltsafekey.rem('CCDSEC',outstruct[outhdu],outfile)
                saltsafekey.rem('AMPSEC',outstruct[outhdu],outfile)

                # add housekeeping key words
                outstruct[outhdu]=addhousekeeping(outstruct[outhdu], outhdu, outfile)

            # close input FITS file
            saltsafeio.closefits(struct)

            # housekeeping keywords
            keymosaic='SLOTMERG'
            fname, hist=history(level=1, wrap=False)
            saltsafekey.housekeeping(struct[0],keymosaic,'Amplifiers have been mosaiced', hist)
            #saltsafekey.history(outstruct[0],hist)

            # this is added for later use by
            saltsafekey.put('NCCDS', 0.5, outstruct[0])
            saltsafekey.put('NSCIEXT', exposures, outstruct[0])
            saltsafekey.put('NEXTEND', exposures, outstruct[0])

            # write FITS file of mosaiced image
            outstruct=pyfits.HDUList(outstruct)
            saltsafeio.writefits(outstruct, outfile, clobber=clobber)
Example #21
0
def bias(struct,subover=True,trim=True, subbias=False, bstruct=None, 
         median=False, function='polynomial',order=3,rej_lo=3,rej_hi=3,niter=10,
         plotover=False, log=None, verbose=True):
   """Bias subtracts the bias levels from a frame.  It will fit and subtract the overscan
      region, trim the images, and subtract a master bias if required.

      struct--image structure 
      subover--subtract the overscan region
      trim--trim the image
      subbias--subtract master bias
      bstruct--master bias image structure
      median--use the median instead of mean in image statistics
      function--form to fit to the overscan region
      order--order for the function
      rej_lo--sigma  of low points to reject in the fit
      rej_hi--sigma of high points to reject in the fit
      niter--number of iterations
      log--saltio log for recording information
      verbose--whether to print to stdout 
   """
   infile=saltkey.getimagename(struct[0])

   # how many extensions?
   nsciext = saltkey.get('NSCIEXT',struct[0])
   nextend = saltkey.get('NEXTEND',struct[0])
   nccd = saltkey.get('NCCDS',struct[0])

   # how many amplifiers?--this is hard wired
   amplifiers = 2 * nccd


   #log the process
   if subover and log:
        message = '%28s %7s %5s %4s %6s' % \
            ('HDU','Overscan','Order','RMS','Niter')
        log.message('\n     --------------------------------------------------', 
                   with_header=False, with_stdout=verbose)
        log.message(message, with_header=False, with_stdout=verbose)
        log.message('     --------------------------------------------------', 
                   with_header=False, with_stdout=verbose)

   if (plotover): 
       plt.figure(1)
       plt.axes([0.1,0.1,0.8,0.8])
       plt.xlabel('CCD Column')
       plt.ylabel('Pixel Counts (e-)')
       plt.ion()


   #loop through the extensions and subtract the bias
   for i in range(1,nsciext+1):
     if struct[i].name=='SCI':

       #get the bias section
       biassec = saltkey.get('BIASSEC',struct[i])
       y1,y2,x1,x2 = saltio.getSection(biassec, iraf_format=True)
       #get the data section
       datasec = saltkey.get('DATASEC',struct[i])
       dy1,dy2, dx1, dx2 = saltio.getSection(datasec, iraf_format=True)
  
       #setup the overscan region
       if subover:
           yarr=np.arange(y1,y2, dtype=float)
           data=struct[i].data
           odata=struct[i].data[y1:y2,x1:x2]
           if median:
              odata=np.median((struct[i].data[y1:y2,x1:x2]),axis=1)
              olevel=np.median((struct[i].data[y1:y2,x1:x2]))
              saltkey.new('OVERSCAN','%f' % (olevel),'Overscan median value', struct[i])
           else:
              odata=np.mean((struct[i].data[y1:y2,x1:x2]),axis=1)
              olevel=np.mean((struct[i].data[y1:y2,x1:x2]))
              saltkey.new('OVERSCAN','%f' % (olevel),'Overscan mean value', struct[i])

           #fit the overscan region
           ifit=saltfit.interfit(yarr, odata, function=function, \
                                 order=order, thresh=rej_hi, niter=niter)
           try:
               ifit.interfit()
               coeffs=ifit.coef
               ofit=ifit(yarr)
               omean, omed, osigma=saltstat.iterstat((odata-ofit), sig=3, niter=5)
           except ValueError:
               #catch the error if it is a zero array
               ofit=np.array(yarr)*0.0
               osigma=0.0
           except TypeError:
               #catch the error if it is a zero array
               ofit=np.array(yarr)*0.0
               osigma=0.0

           #if it hasn't been already, convert image to
           #double format
           struct[i].data = 1.0 * struct[i].data
           try:
               struct[i].header.remove('BZERO')
               struct[i].header.remove('BSCALE')
           except:
               pass


           #subtract the overscan region
           for j in range(len(struct[i].data[0])):
               struct[i].data[y1:y2,j] -= ofit

           #report the information 
           if log:
                message = '%25s[%1d] %8.2f %3d %7.2f %3d' % \
                    (infile, i, olevel, order, osigma, niter)
                log.message(message, with_stdout=verbose, with_header=False)

           #add the statistics to the image header
           saltkey.new('OVERRMS','%f' % (osigma),'Overscan RMS value', struct[i])

           #update the variance frame
           if saltkey.found('VAREXT', struct[i]):
               vhdu=saltkey.get('VAREXT', struct[i])
               try:
                   vdata=struct[vhdu].data
                   #The bias level should not be included in the noise from the signal
                   for j in range(len(struct[i].data[0])):
		       vdata[y1:y2,j] -= ofit
                   #add a bit to make sure that the minimum error is the rednoise
                   rdnoise= saltkey.get('RDNOISE',struct[i])
                   vdata[vdata<rdnoise**2]=rdnoise**2
                   struct[vhdu].data=vdata+osigma**2

               except Exception, e:
                    msg='Cannot update the variance frame in %s[%i] because %s' % (infile, vhdu, e)
                    raise SaltError(msg)


           #plot the overscan region
           if plotover:  
              plt.plot(yarr, odata)
              plt.plot(yarr, ofit)

       #trim the data and update the headers
       if trim:
           struct[i].data=struct[i].data[dy1:dy2,dx1:dx2]
           datasec = '[1:'+str(dx2-dx1)+',1:'+str(dy2-dy1)+']'
           saltkey.put('DATASEC',datasec,struct[i])

           #update the variance frame
           if saltkey.found('VAREXT', struct[i]):
               vhdu=saltkey.get('VAREXT', struct[i])
               struct[vhdu].data=struct[vhdu].data[dy1:dy2,dx1:dx2]
               datasec = '[1:'+str(dx2-dx1)+',1:'+str(dy2-dy1)+']'
               saltkey.put('DATASEC',datasec,struct[vhdu])
           #update the BPM frame
           if saltkey.found('BPMEXT', struct[i]):
               bhdu=saltkey.get('BPMEXT', struct[i])
               struct[bhdu].data=struct[bhdu].data[dy1:dy2,dx1:dx2]
               datasec = '[1:'+str(dx2-dx1)+',1:'+str(dy2-dy1)+']'
               saltkey.put('DATASEC',datasec,struct[bhdu])

       #subtract the master bias if necessary
       if subbias and bstruct:
           struct[i].data -= bstruct[i].data

           #update the variance frame
           if saltkey.found('VAREXT', struct[i]):
               vhdu=saltkey.get('VAREXT', struct[i])
               try:
                   vdata=struct[vhdu].data
                   struct[vhdu].data=vdata+bstruct[vhdu].data
               except Exception, e:
                    msg='Cannot update the variance frame in %s[%i] because %s' % (infile, vhdu, e)
                    raise SaltError(msg)
Example #22
0
               
           #correct the variance frame
           if saltkey.found('VAREXT', struct[hdu]):
               vhdu=saltkey.get('VAREXT', struct[hdu])
               try:
                   vdata=struct[vhdu].data
                   struct[vhdu].data=vdata*gain*(1+2*gain1*1e-6*data)
               except Exception, e:
                    msg='Cannot update the variance frame in %s[%i] because %s' % (infile, vhdu, e)
                    raise SaltError(msg)
       else:
           gainmult=gain
 
       #update the headers
       if usedb:
           saltkey.put('GAIN',gain,struct[hdu])
           saltkey.put('RDNOISE',rdnoise,struct[hdu])

       #add a keyword indicating what action was taken
       saltkey.new('GAINMULT',gainmult,'Gain multiplication', struct[hdu])

       #if logging is true, then print out the following information
       if log:
           message = '%25s[%1d] %6s %5s %2s %6.2f %5.2f' \
             % (infile,hdu,gainset,rospeed,amp, gain, rdnoise)
           log.message(message, with_header=False, with_stdout=verbose)

   #just to make it look pretty 
   if log:
       log.message('',  with_header=False, with_stdout=verbose)