示例#1
0
def create_output(filename):
    fileroot, extn = fileutil.parseFilename(filename)
    extname = fileutil.parseExtn(extn)
    if extname[0] == '': extname = "PRIMARY"

    if not os.path.exists(fileroot):
        # We need to create the new file
        pimg = fits.HDUList()
        phdu = fits.PrimaryHDU()
        phdu.header['NDRIZIM'] = 1
        pimg.append(phdu)
        if extn is not None:
            # Create a MEF file with the specified extname
            ehdu = fits.ImageHDU(data=arr)
            ehdu.header['EXTNAME'] = extname[0]
            ehdu.header['EXTVER'] = extname[1]
            pimg.append(ehdu)
        log.info('Creating new output file: %s' % fileroot)
        pimg.writeto(fileroot)
        del pimg
    else:
        log.info('Updating existing output file: %s' % fileroot)

    handle = fits.open(fileroot, mode='update', memmap=False)

    return handle, extname
示例#2
0
def create_output(filename):
    fileroot,extn = fileutil.parseFilename(filename)
    extname = fileutil.parseExtn(extn)
    if extname[0] == '': extname = "PRIMARY"

    if not os.path.exists(fileroot):
        # We need to create the new file
        pimg = fits.HDUList()
        phdu = fits.PrimaryHDU()
        phdu.header['NDRIZIM'] = 1
        pimg.append(phdu)
        if extn is not None:
            # Create a MEF file with the specified extname
            ehdu = fits.ImageHDU(data=arr)
            ehdu.header['EXTNAME'] = extname[0]
            ehdu.header['EXTVER'] = extname[1]
            pimg.append(ehdu)
        log.info('Creating new output file: %s' % fileroot)
        pimg.writeto(fileroot)
        del pimg
    else:
        log.info('Updating existing output file: %s' % fileroot)

    handle = fits.open(fileroot, mode='update')

    return handle,extname
示例#3
0
    def getHeaderHandle(self):
        """ Sets up the PyFITS image handle and Primary header
            as self.image_handle and self.header.

            When Pattern being used for output product, filename will be
            set to None and this returns None for header and image_handle.
        """

        _numsci = 0
        if self.name:
            _handle = fileutil.openImage(self.name,mode='readonly',memmap=self.pars['memmap'])
            _fname,_extn = fileutil.parseFilename(self.name)
            _hdr = _handle['PRIMARY'].header.copy()
            # Count number of SCI extensions
            for _fext in _handle:
                if 'extname' in _fext.header and _fext.header['extname'] == 'SCI':
                    _numsci += 1

            if _extn and _extn > 0:
                # Append correct extension/chip/group header to PRIMARY...
                for _card in fileutil.getExtn(_handle,_extn).header.ascard:
                    _hdr.ascard.append(_card)
        else:
            # Default to None
            _handle = None
            _hdr = None

        # Set attribute to point to these products
        self.image_handle = None
        self.header = _hdr
        self.nmembers = _numsci

        return _handle
示例#4
0
    def getDGEOArrays(self):
        """ Return numpy objects for the distortion correction
            image arrays.

            If no DGEOFILE is specified, it will return
            empty 2x2 arrays.
        """

        # Instantiate array objects for distortion correction image arrays
        if self.xgeoim == '':
            # No distortion image specified.
            # Defaulting to empty 2x2 array.
            xgdim = ygdim = 2
            _pxg = np.zeros((ygdim,xgdim),dtype=np.float32)
            _pyg = np.zeros((ygdim,xgdim),dtype=np.float32)
        else:
            # Open distortion correction FITS file
            _xgfile = fileutil.openImage(self.xgeoim)
            #_xgfile.info()

            # Access the extensions which correspond to this Exposure
            _xgname,_xgext = fileutil.parseFilename(self.xgeoim)
            _ygname,_ygext = fileutil.parseFilename(self.ygeoim)

            _pxgext = fileutil.getExtn(_xgfile,extn=_xgext)
            _pygext = fileutil.getExtn(_xgfile,extn=_ygext)

            # Copy out the numpy objects for output
            _ltv1 = int(self.geometry.wcs.offset_x)
            _ltv2 = int(self.geometry.wcs.offset_y)
            if _ltv1 != 0. or _ltv2 != 0.:
                # subarray section only
                _pxg = _pxgext.data[_ltv2:_ltv2+self.naxis2,_ltv1:_ltv1+self.naxis1].copy()
                _pyg = _pygext.data[_ltv2:_ltv2+self.naxis2,_ltv1:_ltv1+self.naxis1].copy()
            else:
                # full array
                _pxg = _pxgext.data.copy()
                _pyg = _pygext.data.copy()

            # Close file handles now...
            _xgfile.close()
            del _xgfile

        return _pxg,_pyg
示例#5
0
def get_data(filename):
    fileroot,extn = fileutil.parseFilename(filename)
    extname = fileutil.parseExtn(extn)
    if extname[0] == '': extname = "PRIMARY"
    if os.path.exists(fileroot):
        handle = fileutil.openImage(filename)
        data = handle[extname].data
        handle.close()
    else:
        data = None
    return data
示例#6
0
def get_data(filename):
    fileroot, extn = fileutil.parseFilename(filename)
    extname = fileutil.parseExtn(extn)
    if extname[0] == '': extname = "PRIMARY"
    if os.path.exists(fileroot):
        handle = fileutil.openImage(filename, memmap=False)
        data = handle[extname].data
        handle.close()
    else:
        data = None
    return data
示例#7
0
def generate_headerlet(outwcs, template, wcsname, outname=None):
    """ Create a headerlet based on the updated HSTWCS object

        This function uses 'template' as the basis for the headerlet.
        This file can either be the original wcspars['refimage'] or
        wcspars['coeffsfile'], in this order of preference.

        If 'template' is None, then a simple Headerlet will be
        generated with a single SIPWCS extension and no distortion
    """
    # Create header object from HSTWCS object
    siphdr = True
    if outwcs.sip is None:
        siphdr = False
    outwcs_hdr = outwcs.wcs2header(sip2hdr=siphdr)
    outwcs_hdr['NPIX1'] = outwcs._naxis1
    outwcs_hdr['NPIX2'] = outwcs._naxis2

    # create headerlet object in memory; either from a file or from scratch
    if template is not None and siphdr:
        print('Creating headerlet from template...')
        fname, extn = fileutil.parseFilename(template)
        extnum = fileutil.parseExtn(extn)
        extname = ('sipwcs', extnum[1])
        hdrlet = headerlet.createHeaderlet(fname, wcsname)
        # update hdrlet with header values from outwcs
        for kw in outwcs_hdr.items():
            hdrlet[extname].header[kw[0]] = kw[1]
        hdrlet[extname].header['WCSNAME'] = wcsname
    else:
        print('Creating headerlet from scratch...')
        hdrlet = fits.HDUList()
        hdrlet.append(fits.PrimaryHDU())
        siphdr = fits.ImageHDU(header=outwcs_hdr)
        siphdr.header['EXTNAME'] = 'SIPWCS'
        siphdr.header['WCSNAME'] = wcsname
        hdrlet.append(siphdr)

    # Write out header to a file as the final product
    if outname is not None:
        if outname.find('_hdr.fits') < 0:
            outname += '_hdr.fits'
        if os.path.exists(outname):
            print('Overwrite existing file "%s"' % outname)
            os.remove(outname)
        hdrlet.writeto(outname)
        print('Wrote out headerlet :', outname)
示例#8
0
def generate_headerlet(outwcs,template,wcsname,outname=None):
    """ Create a headerlet based on the updated HSTWCS object

        This function uses 'template' as the basis for the headerlet.
        This file can either be the original wcspars['refimage'] or
        wcspars['coeffsfile'], in this order of preference.

        If 'template' is None, then a simple Headerlet will be
        generated with a single SIPWCS extension and no distortion
    """
    # Create header object from HSTWCS object
    siphdr = True
    if outwcs.sip is None:
        siphdr = False
    outwcs_hdr = outwcs.wcs2header(sip2hdr=siphdr)
    outwcs_hdr['NPIX1'] = outwcs._naxis1
    outwcs_hdr['NPIX2'] = outwcs._naxis2

    # create headerlet object in memory; either from a file or from scratch
    if template is not None and siphdr:
        print('Creating headerlet from template...')
        fname,extn = fileutil.parseFilename(template)
        extnum = fileutil.parseExtn(extn)
        extname = ('sipwcs',extnum[1])
        hdrlet = headerlet.createHeaderlet(fname,wcsname)
        # update hdrlet with header values from outwcs
        for kw in outwcs_hdr.items():
            hdrlet[extname].header[kw[0]] = kw[1]
        hdrlet[extname].header['WCSNAME'] = wcsname
    else:
        print('Creating headerlet from scratch...')
        hdrlet = fits.HDUList()
        hdrlet.append(fits.PrimaryHDU())
        siphdr = fits.ImageHDU(header=outwcs_hdr)
        siphdr.header['EXTNAME'] = 'SIPWCS'
        siphdr.header['WCSNAME'] = wcsname
        hdrlet.append(siphdr)

    # Write out header to a file as the final product
    if outname is not None:
        if outname.find('_hdr.fits') < 0:
            outname += '_hdr.fits'
        if os.path.exists(outname):
            print('Overwrite existing file "%s"'%outname)
            os.remove(outname)
        hdrlet.writeto(outname)
        print('Wrote out headerlet :',outname)
示例#9
0
def convertImageToSFITS(fname):
    """ Convert the input filename (possibly with
        extensions already specified) into a separate
        simple FITS file for each SCI extension.
        
        If fname refers to a simple FITS file already,
        list will only contain fname. 
    """
    flist = []

    # Extract any extension specifications
    rootname, extn = fileutil.parseFilename(fname)
    if extn == None:
        # Check to see if file is multi-extension
        fimg = fileutil.openImage(fname)
        if len(fimg) > 1:
            # We have multiextension FITS, so write out
            # each SCI extension as a separate simple
            # FITS file.
            for hdu in fimg:
                if 'extname' in hdu.header and hdu.header['extname'] == 'SCI':
                    extname = hdu.header['extname'].lower() + str(
                        hdu.header['extver'])
                    new_fname = rootname[:rootname.rfind(
                        '.fits')] + '_extract_' + extname + '.fits'
                    removeFile(new_fname)
                    flist.append([new_fname, fname])
                    phdu = pyfits.PrimaryHDU(header=hdu.header, data=hdu.data)
                    phdu.writeto(new_fname)
                    del phdu
        else:
            # We already have a simple FITS, just record its name
            flist.append([None, fname])
        fimg.close()
        del fimg
    else:
        # We have an image with a SCI extension specified
        split_extn = extn.split(',')
        extname = str(split_extn[0]) + str(split_extn[1])
        new_fname = rootname[:rootname.
                             rfind('.fits')] + '_extract_' + extname + '.fits'
        removeFile(new_fname)
        iraf.imcopy(fname, new_fname, verbose=no)
        flist.append([new_fname, fname])

    return flist
示例#10
0
def buildName(fname, keepext=no, coord_suffix='.coord'):
    """ For a given filename, build filename for the coords file. """

    froot, fext = fileutil.parseFilename(fname)
    froot_name = froot[:froot.rfind('.')]

    if keepext == no:
        fcoord_name = froot_name + coord_suffix
    else:
        if fext != None:
            fext = fext.replace(',', '')
        else:
            fext = ''
        fcoord_name = froot_name + '_' + fext + coord_suffix

    removeFile(fcoord_name)

    return fcoord_name
示例#11
0
def parseSingleInput(f=None, ext=None):
    if isinstance(f, str):
        # create an HSTWCS object from a filename
        if ext is not None:
            filename = f
            if isinstance(ext, tuple):
                if ext[0] == '':
                    extnum = ext[1]  # handle ext=('',1)
                else:
                    extnum = ext
            else:
                extnum = int(ext)
        elif ext is None:
            filename, ext = fileutil.parseFilename(f)
            ext = fileutil.parseExtn(ext)
            if ext[0] == '':
                extnum = int(ext[1])  # handle ext=('',extnum)
            else:
                extnum = ext
        phdu = fits.open(filename)
        hdr0 = phdu[0].header
        try:
            ehdr = phdu[extnum].header
        except (IndexError, KeyError) as e:
            raise e.__class__('Unable to get extension %s.' % extnum)

    elif isinstance(f, fits.HDUList):
        phdu = f
        if ext is None:
            extnum = 0
        else:
            extnum = ext
        ehdr = f[extnum].header
        hdr0 = f[0].header
        filename = hdr0.get('FILENAME', "")

    else:
        raise ValueError('Input must be a file name string or a'
                         '`astropy.io.fits.HDUList` object')

    return filename, hdr0, ehdr, phdu
示例#12
0
def findWCSExtn(filename):
    """ Return new filename with extension that points to an extension with a
        valid WCS.

        Returns
        =======
        extnum : str, None
            Value of extension name as a string either as provided by the user
            or based on the extension number for the first extension which
            contains a valid HSTWCS object.  Returns None if no extension can be
            found with a valid WCS.

        Notes
        =====
        The return value from this function can be used as input to
            create another HSTWCS with the syntax::

                `HSTWCS('{}[{}]'.format(filename,extnum))

    """
    rootname,extroot = fileutil.parseFilename(filename)
    extnum = None
    if extroot is None:
        fimg = fits.open(rootname, memmap=False)
        for i,extn in enumerate(fimg):
            if 'crval1' in extn.header:
                refwcs = wcsutil.HSTWCS('{}[{}]'.format(rootname,i))
                if refwcs.wcs.has_cd():
                    extnum = '{}'.format(i)
                    break
        fimg.close()
    else:
        try:
            refwcs = wcsutil.HSTWCS(filename)
            if refwcs.wcs.has_cd():
                extnum = extroot
        except:
            extnum = None

    return extnum
示例#13
0
def findWCSExtn(filename):
    """ Return new filename with extension that points to an extension with a
        valid WCS.

        Returns
        =======
        extnum : str, None
            Value of extension name as a string either as provided by the user
            or based on the extension number for the first extension which
            contains a valid HSTWCS object.  Returns None if no extension can be
            found with a valid WCS.

        Notes
        =====
        The return value from this function can be used as input to
            create another HSTWCS with the syntax::

                `HSTWCS('{}[{}]'.format(filename,extnum))

    """
    rootname, extroot = fileutil.parseFilename(filename)
    extnum = None
    if extroot is None:
        fimg = fits.open(rootname, memmap=False)
        for i, extn in enumerate(fimg):
            if 'crval1' in extn.header:
                refwcs = wcsutil.HSTWCS('{}[{}]'.format(rootname, i))
                if refwcs.wcs.has_cd():
                    extnum = '{}'.format(i)
                    break
        fimg.close()
    else:
        try:
            refwcs = wcsutil.HSTWCS(filename)
            if refwcs.wcs.has_cd():
                extnum = extroot
        except:
            extnum = None

    return extnum
示例#14
0
def verifyRefimage(refimage):
    """
    Verify that the value of refimage specified by the user points to an
    extension with a proper WCS defined. It starts by making sure an extension gets
    specified by the user when using a MEF file. The final check comes by looking
    for a CD matrix in the WCS object itself. If either test fails, it returns
    a value of False.
    """
    valid = True

    # start by trying to see whether the code can even find the file
    if is_blank(refimage):
        return True

    if isinstance(refimage, astropy.wcs.WCS):
        return True

    refroot, extroot = fileutil.parseFilename(refimage)
    if not os.path.exists(refroot):
        return False

    # if a MEF has been specified, make sure extension contains a valid WCS
    if valid:
        if extroot is None:
            extn = findWCSExtn(refimage)
            if extn is None:
                valid = False
            else:
                valid = True
        else:
            # check for CD matrix in WCS object
            refwcs = wcsutil.HSTWCS(refimage)
            if not refwcs.wcs.has_cd():
                valid = False
            else:
                valid = True
            del refwcs

    return valid
示例#15
0
def verifyRefimage(refimage):
    """
    Verify that the value of refimage specified by the user points to an
    extension with a proper WCS defined. It starts by making sure an extension gets
    specified by the user when using a MEF file. The final check comes by looking
    for a CD matrix in the WCS object itself. If either test fails, it returns
    a value of False.
    """
    valid = True

    # start by trying to see whether the code can even find the file
    if is_blank(refimage):
        valid=True
        return valid

    refroot,extroot = fileutil.parseFilename(refimage)
    if not os.path.exists(refroot):
        valid = False
        return valid

    # if a MEF has been specified, make sure extension contains a valid WCS
    if valid:
        if extroot is None:
            extn = findWCSExtn(refimage)
            if extn is None:
                valid = False
            else:
                valid = True
        else:
            # check for CD matrix in WCS object
            refwcs = wcsutil.HSTWCS(refimage)
            if not refwcs.wcs.has_cd():
                valid = False
            else:
                valid = True
            del refwcs

    return valid
示例#16
0
def run_blot(imageObjectList,
             output_wcs,
             paramDict,
             wcsmap=wcs_functions.WCSMap):
    """
    run_blot(imageObjectList, output_wcs, paramDict, wcsmap=wcs_functions.WCSMap)

    Perform the blot operation on the list of images.
    """
    # Insure that input imageObject is a list
    if not isinstance(imageObjectList, list):
        imageObjectList = [imageObjectList]
    #
    # Setup the versions info dictionary for output to PRIMARY header
    # The keys will be used as the name reported in the header, as-is
    #
    _versions = {
        'AstroDrizzle': __version__,
        'PyFITS': util.__fits_version__,
        'Numpy': util.__numpy_version__
    }

    _hdrlist = []

    for img in imageObjectList:

        for chip in img.returnAllChips(extname=img.scienceExt):

            print('    Blot: creating blotted image: ',
                  chip.outputNames['data'])

            #### Check to see what names need to be included here for use in _hdrlist
            chip.outputNames['driz_version'] = _versions['AstroDrizzle']
            outputvals = chip.outputNames.copy()
            outputvals.update(img.outputValues)
            outputvals['blotnx'] = chip.wcs.naxis1
            outputvals['blotny'] = chip.wcs.naxis2
            _hdrlist.append(outputvals)

            plist = outputvals.copy()
            plist.update(paramDict)

            # PyFITS can be used here as it will always operate on
            # output from PyDrizzle (which will always be a FITS file)
            # Open the input science file
            medianPar = 'outMedian'
            outMedianObj = img.getOutputName(medianPar)
            if img.inmemory:
                outMedian = img.outputNames[medianPar]
                _fname, _sciextn = fileutil.parseFilename(outMedian)
                _inimg = outMedianObj
            else:
                outMedian = outMedianObj
                _fname, _sciextn = fileutil.parseFilename(outMedian)
                _inimg = fileutil.openImage(_fname, memmap=False)

            # Return the PyFITS HDU corresponding to the named extension
            _scihdu = fileutil.getExtn(_inimg, _sciextn)
            _insci = _scihdu.data.copy()
            _inimg.close()
            del _inimg, _scihdu

            _outsci = do_blot(_insci,
                              output_wcs,
                              chip.wcs,
                              chip._exptime,
                              coeffs=paramDict['coeffs'],
                              interp=paramDict['blot_interp'],
                              sinscl=paramDict['blot_sinscl'],
                              wcsmap=wcsmap)
            # Apply sky subtraction and unit conversion to blotted array to
            # match un-modified input array
            if paramDict['blot_addsky']:
                skyval = chip.computedSky
            else:
                skyval = paramDict['blot_skyval']
            _outsci /= chip._conversionFactor
            if skyval is not None:
                _outsci += skyval
                log.info('Applying sky value of %0.6f to blotted image %s' %
                         (skyval, chip.outputNames['data']))

            # Write output Numpy objects to a PyFITS file
            # Blotting only occurs from a drizzled SCI extension
            # to a blotted SCI extension...

            _outimg = outputimage.OutputImage(_hdrlist,
                                              paramDict,
                                              build=False,
                                              wcs=chip.wcs,
                                              blot=True)
            _outimg.outweight = None
            _outimg.outcontext = None
            outimgs = _outimg.writeFITS(plist['data'],
                                        _outsci,
                                        None,
                                        versions=_versions,
                                        blend=False,
                                        virtual=img.inmemory)

            img.saveVirtualOutputs(outimgs)
            #_buildOutputFits(_outsci,None,plist['outblot'])
            _hdrlist = []

            del _outsci

        del _outimg
示例#17
0
def run(configObj, wcsmap=None):
    """ Interface for running `wdrizzle` from TEAL or Python command-line.

    This code performs all file ``I/O`` to set up the use of the drizzle code for
    a single exposure to replicate the functionality of the original `wdrizzle`.
    """

    # Insure all output filenames specified have .fits extensions
    if configObj['outdata'][-5:] != '.fits': configObj['outdata'] += '.fits'
    if not util.is_blank(
            configObj['outweight']) and configObj['outweight'][-5:] != '.fits':
        configObj['outweight'] += '.fits'
    if not util.is_blank(configObj['outcontext']
                         ) and configObj['outcontext'][-5:] != '.fits':
        configObj['outcontext'] += '.fits'

    # Keep track of any files we need to open
    in_sci_handle = None
    in_wht_handle = None
    out_sci_handle = None
    out_wht_handle = None
    out_con_handle = None

    _wcskey = configObj['wcskey']
    if util.is_blank(_wcskey):
        _wcskey = ' '

    scale_pars = configObj['Data Scaling Parameters']
    user_wcs_pars = configObj['User WCS Parameters']

    # Open the SCI (and WHT?) image
    # read file to get science array
    insci = get_data(configObj['input'])
    expin = fileutil.getKeyword(configObj['input'], scale_pars['expkey'])
    in_sci_phdr = fits.getheader(fileutil.parseFilename(configObj['input'])[0],
                                 memmap=False)

    # we need to read in the input WCS
    input_wcs = stwcs.wcsutil.HSTWCS(configObj['input'], wcskey=_wcskey)

    if not util.is_blank(configObj['inweight']):
        inwht = get_data(configObj['inweight']).astype(np.float32)
    else:
        # Generate a default weight map of all good pixels
        inwht = np.ones(insci.shape, dtype=insci.dtype)

    output_exists = False
    outname = fileutil.osfn(fileutil.parseFilename(configObj['outdata'])[0])
    if os.path.exists(outname):
        output_exists = True
    # Output was specified as a filename, so open it in 'update' mode
    outsci = get_data(configObj['outdata'])

    if output_exists:
        # we also need to read in the output WCS from pre-existing output
        output_wcs = stwcs.wcsutil.HSTWCS(configObj['outdata'])

        out_sci_hdr = fits.getheader(outname, memmap=False)
        outexptime = out_sci_hdr['DRIZEXPT']
        if 'ndrizim' in out_sci_hdr:
            uniqid = out_sci_hdr['ndrizim'] + 1
        else:
            uniqid = 1

    else:  # otherwise, define the output WCS either from user pars or refimage
        if util.is_blank(configObj['User WCS Parameters']['refimage']):
            # Define a WCS based on user provided WCS values
            # NOTE:
            #   All parameters must be specified, not just one or a few
            if not util.is_blank(user_wcs_pars['outscale']):
                output_wcs = wcs_functions.build_hstwcs(
                    user_wcs_pars['raref'], user_wcs_pars['decref'],
                    user_wcs_pars['xrefpix'], user_wcs_pars['yrefpix'],
                    int(user_wcs_pars['outnx']), int(user_wcs_pars['outny']),
                    user_wcs_pars['outscale'], user_wcs_pars['orient'])
            else:
                # Define default WCS based on input image
                applydist = True
                if input_wcs.sip is None or input_wcs.instrument == 'DEFAULT':
                    applydist = False
                output_wcs = stwcs.distortion.utils.output_wcs(
                    [input_wcs], undistort=applydist)
        else:
            refimage = configObj['User WCS Parameters']['refimage']
            refroot, extroot = fileutil.parseFilename(refimage)
            if extroot is None:
                fimg = fits.open(refroot, memmap=False)
                for i, extn in enumerate(fimg):
                    if 'CRVAL1' in extn.header:  # Key on CRVAL1 for valid WCS
                        refwcs = stwcs.wcsutil.HSTWCS('{}[{}]'.format(
                            refroot, i))
                        if refwcs.wcs.has_cd():
                            extroot = i
                            break
                fimg.close()
                # try to find extension with valid WCS
                refimage = "{}[{}]".format(refroot, extroot)
            # Define the output WCS based on a user specified reference image WCS
            output_wcs = stwcs.wcsutil.HSTWCS(refimage)
        # Initialize values used for combining results
        outexptime = 0.0
        uniqid = 1

    # Set up the output data array and insure that the units for that array is 'cps'
    if outsci is None:
        # Define a default blank array based on definition of output_wcs
        outsci = np.empty(output_wcs.array_shape, dtype=np.float32)
        outsci.fill(np.nan)
    else:
        # Convert array to units of 'cps', if needed
        if outexptime != 0.0:
            np.divide(outsci, outexptime, outsci)
        outsci = outsci.astype(np.float32)

    # Now update output exposure time for additional input file
    outexptime += expin

    outwht = None
    if not util.is_blank(configObj['outweight']):
        outwht = get_data(configObj['outweight'])

    if outwht is None:
        outwht = np.zeros(output_wcs.array_shape, dtype=np.float32)
    else:
        outwht = outwht.astype(np.float32)

    outcon = None
    keep_con = False

    if not util.is_blank(configObj['outcontext']):
        outcon = get_data(configObj['outcontext'])
        keep_con = True
        if outcon is None:
            outcon = np.zeros((1, ) + output_wcs.array_shape, dtype=np.int32)
        else:
            outcon = outcon.astype(np.int32)
            planeid = int((uniqid - 1) / 32)

            # Add a new plane to the context image if planeid overflows
            while outcon.shape[0] <= planeid:
                plane = np.zeros_like(outcon[0])
                outcon = np.append(outcon, plane, axis=0)

    # Interpret wt_scl parameter
    if configObj['wt_scl'] == 'exptime':
        wt_scl = expin
    elif configObj['wt_scl'] == 'expsq':
        wt_scl = expin * expin
    else:
        wt_scl = float(configObj['wt_scl'])

    # Interpret coeffs parameter to determine whether to apply coeffs or not
    undistort = True
    if not configObj[
            'coeffs'] or input_wcs.sip is None or input_wcs.instrument == 'DEFAULT':
        undistort = False
    # turn off use of coefficients if undistort is False (coeffs == False)
    if not undistort:
        input_wcs.sip = None
        input_wcs.cpdis1 = None
        input_wcs.cpdis2 = None
        input_wcs.det2im = None

    wcslin = distortion.utils.output_wcs([input_wcs], undistort=undistort)

    # Perform actual drizzling now...
    _vers = do_driz(insci,
                    input_wcs,
                    inwht,
                    output_wcs,
                    outsci,
                    outwht,
                    outcon,
                    expin,
                    scale_pars['in_units'],
                    wt_scl,
                    wcslin_pscale=wcslin.pscale,
                    uniqid=uniqid,
                    pixfrac=configObj['pixfrac'],
                    kernel=configObj['kernel'],
                    fillval=scale_pars['fillval'],
                    stepsize=configObj['stepsize'],
                    wcsmap=None)

    out_sci_handle, outextn = create_output(configObj['outdata'])
    if not output_exists:
        # Also, define default header based on input image Primary header
        out_sci_handle[outextn].header = in_sci_phdr.copy()

    # Update header of output image with exptime used to scale the output data
    # if out_units is not counts, this will simply be a value of 1.0
    # the keyword 'exptime' will always contain the total exposure time
    # of all input image regardless of the output units
    out_sci_handle[outextn].header['EXPTIME'] = outexptime

    # create CTYPE strings
    ctype1 = input_wcs.wcs.ctype[0]
    ctype2 = input_wcs.wcs.ctype[1]
    if ctype1.find('-SIP'): ctype1 = ctype1.replace('-SIP', '')
    if ctype2.find('-SIP'): ctype2 = ctype2.replace('-SIP', '')

    # Update header with WCS keywords
    out_sci_handle[outextn].header['ORIENTAT'] = output_wcs.orientat
    out_sci_handle[outextn].header['CD1_1'] = output_wcs.wcs.cd[0][0]
    out_sci_handle[outextn].header['CD1_2'] = output_wcs.wcs.cd[0][1]
    out_sci_handle[outextn].header['CD2_1'] = output_wcs.wcs.cd[1][0]
    out_sci_handle[outextn].header['CD2_2'] = output_wcs.wcs.cd[1][1]
    out_sci_handle[outextn].header['CRVAL1'] = output_wcs.wcs.crval[0]
    out_sci_handle[outextn].header['CRVAL2'] = output_wcs.wcs.crval[1]
    out_sci_handle[outextn].header['CRPIX1'] = output_wcs.wcs.crpix[0]
    out_sci_handle[outextn].header['CRPIX2'] = output_wcs.wcs.crpix[1]
    out_sci_handle[outextn].header['CTYPE1'] = ctype1
    out_sci_handle[outextn].header['CTYPE2'] = ctype2
    out_sci_handle[outextn].header['VAFACTOR'] = 1.0

    if scale_pars['out_units'] == 'counts':
        np.multiply(outsci, outexptime, outsci)
        out_sci_handle[outextn].header['DRIZEXPT'] = outexptime

    else:
        out_sci_handle[outextn].header['DRIZEXPT'] = 1.0

    # Update header keyword NDRIZIM to keep track of how many images have
    # been combined in this product so far
    out_sci_handle[outextn].header['NDRIZIM'] = uniqid

    # define keywords to be written out to product header
    drizdict = outputimage.DRIZ_KEYWORDS.copy()

    # Update drizdict with current values
    drizdict['VER']['value'] = _vers[:44]
    drizdict['DATA']['value'] = configObj['input'][:64]
    drizdict['DEXP']['value'] = expin
    drizdict['OUDA']['value'] = configObj['outdata'][:64]
    drizdict['OUWE']['value'] = configObj['outweight'][:64]
    drizdict['OUCO']['value'] = configObj['outcontext'][:64]
    drizdict['MASK']['value'] = configObj['inweight'][:64]
    drizdict['WTSC']['value'] = wt_scl
    drizdict['KERN']['value'] = configObj['kernel']
    drizdict['PIXF']['value'] = configObj['pixfrac']
    drizdict['OUUN']['value'] = scale_pars['out_units']
    drizdict['FVAL']['value'] = scale_pars['fillval']
    drizdict['WKEY']['value'] = configObj['wcskey']
    outputimage.writeDrizKeywords(out_sci_handle[outextn].header, uniqid,
                                  drizdict)

    # add output array to output file
    out_sci_handle[outextn].data = outsci
    out_sci_handle.close()

    if not util.is_blank(configObj['outweight']):
        out_wht_handle, outwhtext = create_output(configObj['outweight'])
        out_wht_handle[outwhtext].header = out_sci_handle[outextn].header.copy(
        )
        out_wht_handle[outwhtext].data = outwht
        out_wht_handle.close()

    if keep_con:
        out_con_handle, outconext = create_output(configObj['outcontext'])
        out_con_handle[outconext].data = outcon
        out_con_handle.close()
示例#18
0
def tran(inimage,
         outimage,
         direction='forward',
         x=None,
         y=None,
         coordfile=None,
         colnames=None,
         separator=None,
         precision=6,
         output=None,
         verbose=True):
    """ Primary interface to perform coordinate transformations in pixel
        coordinates between 2 images using STWCS and full distortion models
        read from each image's header.
    """
    single_coord = False

    if coordfile is None:
        if isinstance(x, np.ndarray):
            xlist = x.tolist()
            ylist = y.tolist()
        elif not isinstance(x, list):
            xlist = [x]
            ylist = [y]
            single_coord = True
        else:
            xlist = x
            ylist = y

    else:
        if colnames in util.blank_list:
            colnames = ['c1', 'c2']

        # Determine columns which contain pixel positions
        cols = util.parse_colnames(colnames, coordfile)
        # read in columns from input coordinates file
        xyvals = np.loadtxt(coordfile, usecols=cols, delimiter=separator)

        if xyvals.ndim == 1:  # only 1 entry in coordfile
            xlist = [xyvals[0].copy()]
            ylist = [xyvals[1].copy()]
        else:
            xlist = xyvals[:, 0].copy()
            ylist = xyvals[:, 1].copy()

    # start by reading in WCS+distortion info for each image
    im1wcs = wcsutil.HSTWCS(inimage)
    if im1wcs.wcs.is_unity():
        print("####\nNo valid input WCS found in '{}'."
              "\n  Results may be invalid.\n####\n".format(inimage))

    if util.is_blank(outimage):
        fname, fextn = fileutil.parseFilename(inimage)
        numsci = fileutil.countExtn(fname)
        chips = [
            wcsutil.HSTWCS(fname, ext=('sci', e + 1)) for e in range(numsci)
        ]
        if len(chips) == 0:
            chips = [im1wcs]
        im2wcs = distortion.utils.output_wcs(chips)

    else:
        im2wcs = wcsutil.HSTWCS(outimage)

    if im2wcs.wcs.is_unity():
        print("####\nNo valid output WCS found in '{}'."
              "\n  Results may be invalid.\n####\n".format(outimage))

    # Setup the transformation
    p2p = wcs_functions.WCSMap(im1wcs, im2wcs)

    if direction[0].lower() == 'f':
        outx, outy = p2p.forward(xlist, ylist)
    else:
        outx, outy = p2p.backward(xlist, ylist)

    if isinstance(outx, np.ndarray):
        outx = outx.tolist()
        outy = outy.tolist()

    # add formatting based on precision here...
    xstr = []
    ystr = []
    for ox, oy in zip(outx, outy):
        xstr.append('{0:.{1}f}'.format(ox, precision))
        ystr.append('{0:.{1}f}'.format(oy, precision))

    if verbose:
        print('# Coordinate transformations for ', inimage)
        print('# X(in)      Y(in)             X(out)         Y(out)\n')
        for xs, ys, a, b in zip(xlist, ylist, xstr, ystr):
            print("%.4f  %.4f    %s  %s" % (xs, ys, a, b))

    # Create output file, if specified
    if output:
        with open(output, mode='w') as f:
            f.write("# Coordinates converted from %s\n" % inimage)
            for xs, ys in zip(xstr, ystr):
                f.write('%s    %s\n' % (xs, ys))
        print('Wrote out results to: ', output)

    if single_coord:
        outx = outx[0]
        outy = outy[0]

    return outx, outy
示例#19
0
def tran(inimage,
         outimage,
         direction='forward',
         x=None,
         y=None,
         coords=None,
         coordfile=None,
         colnames=None,
         separator=None,
         precision=6,
         output=None,
         verbose=True):
    """ Primary interface to perform coordinate transformations in pixel
        coordinates between 2 images using STWCS and full distortion models
        read from each image's header.
    """
    single_coord = False

    # Only use value provided in `coords` if nothing has been specified for coordfile
    if coords is not None and coordfile is None:
        coordfile = coords
        warnings.simplefilter('always', DeprecationWarning)
        warnings.warn(
            "Please update calling code to pass in `coordfile` instead of `coords`.",
            category=DeprecationWarning)
        warnings.simplefilter('default', DeprecationWarning)

    if coordfile is not None:
        if colnames in util.blank_list:
            colnames = ['c1', 'c2']
        # Determine columns which contain pixel positions
        cols = util.parse_colnames(colnames, coordfile)
        # read in columns from input coordinates file
        xyvals = np.loadtxt(coordfile, usecols=cols, delimiter=separator)
        if xyvals.ndim == 1:  # only 1 entry in coordfile
            xlist = [xyvals[0].copy()]
            ylist = [xyvals[1].copy()]
        else:
            xlist = xyvals[:, 0].copy()
            ylist = xyvals[:, 1].copy()
        del xyvals
    else:
        if isinstance(x, np.ndarray):
            xlist = x.tolist()
            ylist = y.tolist()
        elif not isinstance(x, list):
            xlist = [x]
            ylist = [y]
            single_coord = True
        else:
            xlist = x
            ylist = y

    # start by reading in WCS+distortion info for each image
    im1wcs = wcsutil.HSTWCS(inimage)
    if im1wcs.wcs.is_unity():
        print(
            "####\nNo valid input WCS found in {}.\n  Results may be invalid.\n####\n"
            .format(inimage))

    if util.is_blank(outimage):
        fname, fextn = fileutil.parseFilename(inimage)
        numsci = fileutil.countExtn(fname)
        chips = []
        for e in range(1, numsci + 1):
            chips.append(wcsutil.HSTWCS(fname, ext=('sci', e)))
        if len(chips) == 0:
            chips = [im1wcs]
        im2wcs = distortion.utils.output_wcs(chips)
    else:
        im2wcs = wcsutil.HSTWCS(outimage)

    if im2wcs.wcs.is_unity():
        print(
            "####\nNo valid output WCS found in {}.\n  Results may be invalid.\n####\n"
            .format(outimage))

    # Setup the transformation
    p2p = wcs_functions.WCSMap(im1wcs, im2wcs)

    if direction[0].lower() == 'f':
        outx, outy = p2p.forward(xlist, ylist)
    else:
        outx, outy = p2p.backward(xlist, ylist)

    if isinstance(outx, np.ndarray):
        outx = outx.tolist()
        outy = outy.tolist()

    # add formatting based on precision here...
    xstr = []
    ystr = []
    fmt = "%." + repr(precision) + "f"
    for ox, oy in zip(outx, outy):
        xstr.append(fmt % ox)
        ystr.append(fmt % oy)

    if verbose or (not verbose and util.is_blank(output)):
        print('# Coordinate transformations for ', inimage)
        print('# X(in)      Y(in)             X(out)         Y(out)\n')
        for xs, ys, a, b in zip(xlist, ylist, xstr, ystr):
            print("%.4f  %.4f    %s  %s" % (xs, ys, a, b))

    # Create output file, if specified
    if output:
        f = open(output, mode='w')
        f.write("# Coordinates converted from %s\n" % inimage)
        for xs, ys in zip(xstr, ystr):
            f.write('%s    %s\n' % (xs, ys))
        f.close()
        print('Wrote out results to: ', output)

    if single_coord:
        outx = outx[0]
        outy = outy[0]
    return outx, outy
示例#20
0
def getTemplates(fname,extlist):
    # Obtain default headers for output file
    # If the output file already exists, use it
    # If not, use an input file for this information.
    #
    # NOTE: Returns 'pyfits.Header' objects, not HDU objects!
    #
    if fname == None:
        print('No data files for creating FITS output.')
        raise Exception

    froot,fextn = fileutil.parseFilename(fname)
    if fextn is not None:
        fnum = fileutil.parseExtn(fextn)[1]
    ftemplate = fileutil.openImage(froot,mode='readonly')
    prihdr = pyfits.Header(cards=ftemplate['PRIMARY'].header.ascard.copy())
    del prihdr['pcount']
    del prihdr['gcount']

    if fname.find('.fits') > 0 and len(ftemplate) > 1:

        # Setup which keyword we will use to select each
        # extension...
        _extkey = 'EXTNAME'

        defnum = fileutil.findKeywordExtn(ftemplate,_extkey,extlist[0])
        #
        # Now, extract the headers necessary for output (as copies)
        # 1. Find the SCI extension in the template image
        # 2. Make a COPY of the extension header for use in new output file
        if fextn in [None,1]:
            extnum = fileutil.findKeywordExtn(ftemplate,_extkey,extlist[0])
        else:
            extnum = (extlist[0],fnum)
        scihdr = pyfits.Header(cards=ftemplate[extnum].header.ascard.copy())
        scihdr.update('extver',1)

        if fextn in [None,1]:
            extnum = fileutil.findKeywordExtn(ftemplate,_extkey,extlist[1])
        else:
            # there may or may not be a second type of extension in the template
            count = 0
            for f in ftemplate:
                if 'extname' in f.header and f.header['extname'] == extlist[1]:
                    count += 1
            if count > 0:
                extnum = (extlist[1],fnum)
            else:
                # Use science header for remaining headers
                extnum = (extlist[0],fnum)
        errhdr = pyfits.Header(cards=ftemplate[extnum].header.ascard.copy())
        errhdr.update('extver',1)

        if fextn in [None,1]:
            extnum = fileutil.findKeywordExtn(ftemplate,_extkey,extlist[2])
        else:
            count = 0
            for f in ftemplate:
                if 'extname' in f.header and f.header['extname'] == extlist[2]:
                    count += 1
            if count > 0:
                extnum = (extlist[2],fnum)
            else:
                # Use science header for remaining headers
                extnum = (extlist[0],fnum)
        dqhdr = pyfits.Header(cards=ftemplate[extnum].header.ascard.copy())
        dqhdr.update('extver',1)

    else:
        # Create default headers from scratch
        scihdr = None
        errhdr = None
        dqhdr = None

    ftemplate.close()
    del ftemplate

    # Now, safeguard against having BSCALE and BZERO
    try:
        del scihdr['bscale']
        del scihdr['bzero']
        del errhdr['bscale']
        del errhdr['bzero']
        del dqhdr['bscale']
        del dqhdr['bzero']
    except:
        # If these don't work, they didn't exist to start with...
        pass


    # At this point, check errhdr and dqhdr to make sure they
    # have all the requisite keywords (as listed in updateDTHKeywords).
    # Simply copy them from scihdr if they don't exist...
    if errhdr != None and dqhdr != None:
        for keyword in DTH_KEYWORDS:
            if keyword not in errhdr:
                errhdr.update(keyword,scihdr[keyword])
            if keyword not in dqhdr:
                dqhdr.update(keyword,scihdr[keyword])

    return prihdr,scihdr,errhdr,dqhdr
示例#21
0
    def runDriz(self,pixfrac=1.0,kernel='turbo',fillval='INDEF'):
        """ Runs the 'drizzle' algorithm on this specific chip to create
            a numpy object of the undistorted image.

            The resulting drizzled image gets returned as a numpy object.
        """
        #
        # Perform drizzling...
        #
        _wcs = self.geometry.wcs
        _wcsout = self.product_wcs

        # Rigorously compute the orientation changes from WCS
        # information using algorithm provided by R. Hook from WDRIZZLE.
        abxt,cdyt = drutil.wcsfit(self.geometry, self.product_wcs)

        # Compute the rotation and shifts between input and reference WCS.
        xsh = abxt[2]
        ysh = cdyt[2]
        rot = fileutil.RADTODEG(np.arctan2(abxt[1],cdyt[0]))
        scale = self.product_wcs.pscale / self.geometry.wcslin.pscale

        # Now, trim the final output to only match this chip
        _out_naxis1,_out_naxis2 = self.chip_shape

        #
        # Insure that the coeffs file was created
        #
        if not os.path.exists(self.coeffs):
            self.writeCoeffs()

        # A image buffer needs to be setup for converting the input
        # arrays (sci and wht) from FITS format to native format
        # with respect to byteorder and byteswapping.
        # This buffer should be reused for each input.
        #
        _outsci = np.zeros((_out_naxis2,_out_naxis1),dtype=np.float32)
        _outwht = np.zeros((_out_naxis2,_out_naxis1),dtype=np.float32)
        _inwcs = np.zeros([8],dtype=np.float64)

        # Only one chip will ever be drizzled using this method, so
        # the context image will only ever contain 1 bit-plane
        _outctx = np.zeros((_out_naxis2,_out_naxis1),dtype=np.int32)

        # Read in the distortion correction arrays, if specifij8cw08n4q_raw.fitsed
        _pxg,_pyg = self.getDGEOArrays()

        # Open the SCI image
        _expname = self.name
        _handle = fileutil.openImage(_expname,mode='readonly',memmap=0)
        _fname,_extn = fileutil.parseFilename(_expname)
        _sciext = fileutil.getExtn(_handle,extn=_extn)

        # Make a local copy of SCI array and WCS info
        #_insci = _sciext.data.copy()
        _inwcs = drutil.convertWCS(wcsutil.WCSObject(_fname,header=_sciext.header),_inwcs)

        # Compute what plane of the context image this input would
        # correspond to:
        _planeid = 1

        # Select which mask needs to be read in for drizzling
        _inwht = np.ones((self.naxis2,self.naxis1),dtype=np.float32)

        # Default case: wt_scl = exptime
        _wtscl = self.exptime

        # Set additional parameters needed by 'drizzle'
        _expin = self.exptime
        #_in_un = 'counts'
        #_shift_fr = 'output'
        #_shift_un = 'output'
        _uniqid = 1
        ystart = 0
        nmiss = 0
        nskip = 0
        _vers = ''

        #
        # This call to 'arrdriz.tdriz' uses the F2C syntax
        #
        _dny = self.naxis2
        # Call 'drizzle' to perform image combination
        _vers,nmiss,nskip = arrdriz.tdriz(_sciext.data.copy(),_inwht,
                    _outsci, _outwht, _outctx,
                    _uniqid, ystart, 1, 1, _dny,
                    xsh,ysh, 'output','output', rot,scale,
                    self.xsh2,self.ysh2, 1.0, 1.0, 0.0, 'output',
                    _pxg,_pyg,
                    'center', pixfrac, kernel,
                    self.coeffs, 'counts', _expin,_wtscl,
                    fillval, _inwcs, nmiss, nskip, 1,0.,0.)
        #
        # End of F2C syntax
        #

        if nmiss > 0:
            print('! Warning, ',nmiss,' points were outside the output image.')
        if nskip > 0:
            print('! Note, ',nskip,' input lines were skipped completely.')

        # Close image handle
        _handle.close()
        del _handle,_fname,_extn,_sciext
        del _inwht

        del _pxg,_pyg

        del _outwht,_outctx

        return _outsci
示例#22
0
def updateShifts(tabname, shiftfile, mode='replace', clean=no):
    """ Update an ASN table with shifts provided in shiftfile.
        The 'units', 'frame', and 'reference' will all be derived
        from the shiftfile itself, with defaults set by 'readShiftFile'.

        If 'clean' == yes, then remove the shiftfile and any
        reference WCS file after they have been used
        to update the ASN table.
    """

    # Read in the shifts from the shiftfile
    sdict = asnutil.ShiftFile(shiftfile)

    # Apply user-specified values
    # Values from shiftfile ALWAYS take precedence
    if 'units' in sdict:
        _units = sdict['units']
    else:
        _units = None

    if 'frame' in sdict:
        _frame = sdict['frame']
    else:
        _frame = None

    _reference = sdict['refimage']

    if _frame == 'output' and _reference == None:
        # No reference frame specified, yet shifts given in
        # output units, so raise an Exception
        print("No reference image provided for shifts given in output units!")
        raise ValueError

    # Extract list of rootnames from ASN table
    ftab = pyfits.open(tabname)
    fnames = ftab[1].data.field('memname')
    ftab.close()
    del ftab

    # For each rootname in ASN table, apply shifts from shiftfile
    for mname in fnames:
        _lname = mname.lower()
        for key in sdict.keys():
            # Is this key the one that goes with 'mname'?
            if key.find(_lname) > -1:
                _s = sdict[key]

                updateAsnTable(tabname,
                               mname,
                               xsh=_s[0],
                               ysh=_s[1],
                               rot=_s[2],
                               scale=_s[3],
                               form=sdict['form'],
                               frame=_frame,
                               units=_units,
                               output=_reference,
                               mode=mode)

    # If we have a new reference image, update header keyword to point
    # to appended WCS object
    if _reference != None:
        # Append reference WCS to ASN table
        whdu = wcsutil.WCSObject(_reference)
        whdu.createReferenceWCS(tabname, overwrite=no)
        # Now update ASN header to point to new reference WCS
        ftab = pyfits.open(tabname, mode='update')
        ftab['primary'].header.update('refimage', tabname + "[wcs]")
        ftab.close()
        del ftab
        del whdu

    # If user specifies, remove shiftfile and reference WCS
    # after it has been appended to ASN table.
    if clean == yes:
        os.remove(shiftfile)
        if _reference != None:
            _refname, _refextn = fileutil.parseFilename(_reference)
            os.remove(_refname)
示例#23
0
def writeSingleFITS(data,wcs,output,template,clobber=True,verbose=True):
    """ Write out a simple FITS file given a numpy array and the name of another
    FITS file to use as a template for the output image header.
    """
    outname,outextn = fileutil.parseFilename(output)
    outextname,outextver = fileutil.parseExtn(outextn)

    if fileutil.findFile(outname):
        if clobber:
            log.info('Deleting previous output product: %s' % outname)
            fileutil.removeFile(outname)

        else:
            log.warning('Output file %s already exists and overwrite not '
                        'specified!' % outname)
            log.error('Quitting... Please remove before resuming operations.')
            raise IOError

    # Now update WCS keywords with values from provided WCS
    if hasattr(wcs.sip,'a_order'):
        siphdr = True
    else:
        siphdr = False
    wcshdr = wcs.wcs2header(sip2hdr=siphdr)

    if template is not None:
        # Get default headers from multi-extension FITS file
        # If input data is not in MEF FITS format, it will return 'None'
        # NOTE: These are HEADER objects, not HDUs
        (prihdr,scihdr,errhdr,dqhdr),newtab = getTemplates(template,EXTLIST)

        if scihdr is None:
            scihdr = fits.Header()
            indx = 0
            for c in prihdr.cards:
                if c.keyword not in ['INHERIT','EXPNAME']: indx += 1
                else: break
            for i in range(indx,len(prihdr)):
                scihdr.append(prihdr.cards[i])
            for i in range(indx, len(prihdr)):
                del prihdr[indx]
    else:
        scihdr = fits.Header()
        prihdr = fits.Header()
        # Start by updating PRIMARY header keywords...
        prihdr.set('EXTEND', value=True, after='NAXIS')
        prihdr['FILENAME'] = outname

    if outextname == '':
        outextname = 'sci'
    if outextver == 0: outextver = 1
    scihdr['EXTNAME'] = outextname.upper()
    scihdr['EXTVER'] = outextver

    for card in wcshdr.cards:
        scihdr[card.keyword] = (card.value, card.comment)

    # Create PyFITS HDUList for all extensions
    outhdu = fits.HDUList()
    # Setup primary header as an HDU ready for appending to output FITS file
    prihdu = fits.PrimaryHDU(header=prihdr)
    scihdu = fits.ImageHDU(header=scihdr,data=data)

    outhdu.append(prihdu)
    outhdu.append(scihdu)
    outhdu.writeto(outname)

    if verbose:
        print('Created output image: %s' % outname)
示例#24
0
def run_blot(imageObjectList,output_wcs,paramDict,wcsmap=wcs_functions.WCSMap):
    """
    run_blot(imageObjectList, output_wcs, paramDict, wcsmap=wcs_functions.WCSMap)

    Perform the blot operation on the list of images.
    """
    # Insure that input imageObject is a list
    if not isinstance(imageObjectList, list):
        imageObjectList = [imageObjectList]
    #
    # Setup the versions info dictionary for output to PRIMARY header
    # The keys will be used as the name reported in the header, as-is
    #
    _versions = {'AstroDrizzle':__version__,
                 'PyFITS':util.__fits_version__,
                 'Numpy':util.__numpy_version__}

    _hdrlist = []

    for img in imageObjectList:

        for chip in img.returnAllChips(extname=img.scienceExt):

            print('    Blot: creating blotted image: ',chip.outputNames['data'])

            #### Check to see what names need to be included here for use in _hdrlist
            chip.outputNames['driz_version'] = _versions['AstroDrizzle']
            outputvals = chip.outputNames.copy()
            outputvals.update(img.outputValues)
            outputvals['blotnx'] = chip.wcs.naxis1
            outputvals['blotny'] = chip.wcs.naxis2
            _hdrlist.append(outputvals)

            plist = outputvals.copy()
            plist.update(paramDict)

            # PyFITS can be used here as it will always operate on
            # output from PyDrizzle (which will always be a FITS file)
            # Open the input science file
            medianPar = 'outMedian'
            outMedianObj = img.getOutputName(medianPar)
            if img.inmemory:
                outMedian = img.outputNames[medianPar]
                _fname,_sciextn = fileutil.parseFilename(outMedian)
                _inimg = outMedianObj
            else:
                outMedian = outMedianObj
                _fname,_sciextn = fileutil.parseFilename(outMedian)
                _inimg = fileutil.openImage(_fname)

            # Return the PyFITS HDU corresponding to the named extension
            _scihdu = fileutil.getExtn(_inimg,_sciextn)
            _insci = _scihdu.data.copy()
            _inimg.close()
            del _inimg, _scihdu

            _outsci = do_blot(_insci, output_wcs,
                   chip.wcs, chip._exptime, coeffs=paramDict['coeffs'],
                   interp=paramDict['blot_interp'], sinscl=paramDict['blot_sinscl'],
                   wcsmap=wcsmap)
            # Apply sky subtraction and unit conversion to blotted array to
            # match un-modified input array
            if paramDict['blot_addsky']:
                skyval = chip.computedSky
            else:
                skyval = paramDict['blot_skyval']
            _outsci /= chip._conversionFactor
            _outsci += skyval
            log.info('Applying sky value of %0.6f to blotted image %s'%
                        (skyval,chip.outputNames['data']))

            # Write output Numpy objects to a PyFITS file
            # Blotting only occurs from a drizzled SCI extension
            # to a blotted SCI extension...

            _outimg = outputimage.OutputImage(_hdrlist, paramDict, build=False, wcs=chip.wcs, blot=True)
            _outimg.outweight = None
            _outimg.outcontext = None
            outimgs = _outimg.writeFITS(plist['data'],_outsci,None,
                                versions=_versions,blend=False,
                                virtual=img.inmemory)

            img.saveVirtualOutputs(outimgs)
            #_buildOutputFits(_outsci,None,plist['outblot'])
            _hdrlist = []

            del _outsci

        del _outimg
示例#25
0
def run(configObj, wcsmap=None):
    """ Interface for running `wdrizzle` from TEAL or Python command-line.

    This code performs all file ``I/O`` to set up the use of the drizzle code for
    a single exposure to replicate the functionality of the original `wdrizzle`.
    """

    # Insure all output filenames specified have .fits extensions
    if configObj['outdata'][-5:] != '.fits': configObj['outdata'] += '.fits'
    if not util.is_blank(configObj['outweight']) and configObj['outweight'][-5:] != '.fits': configObj['outweight'] += '.fits'
    if not util.is_blank(configObj['outcontext']) and configObj['outcontext'][-5:] != '.fits': configObj['outcontext'] += '.fits'

    # Keep track of any files we need to open
    in_sci_handle = None
    in_wht_handle = None
    out_sci_handle = None
    out_wht_handle = None
    out_con_handle = None

    _wcskey = configObj['wcskey']
    if util.is_blank(_wcskey):
        _wcskey = ' '

    scale_pars = configObj['Data Scaling Parameters']
    user_wcs_pars = configObj['User WCS Parameters']

    # Open the SCI (and WHT?) image
    # read file to get science array
    insci = get_data(configObj['input'])
    expin = fileutil.getKeyword(configObj['input'],scale_pars['expkey'])
    in_sci_phdr = fits.getheader(fileutil.parseFilename(configObj['input'])[0])

    # we need to read in the input WCS
    input_wcs = stwcs.wcsutil.HSTWCS(configObj['input'],wcskey=_wcskey)

    if not util.is_blank(configObj['inweight']):
        inwht = get_data(configObj['inweight']).astype(np.float32)
    else:
        # Generate a default weight map of all good pixels
        inwht = np.ones(insci.shape,dtype=insci.dtype)

    output_exists = False
    outname = fileutil.osfn(fileutil.parseFilename(configObj['outdata'])[0])
    if os.path.exists(outname):
        output_exists = True
    # Output was specified as a filename, so open it in 'update' mode
    outsci = get_data(configObj['outdata'])

    if output_exists:
        # we also need to read in the output WCS from pre-existing output
        output_wcs = stwcs.wcsutil.HSTWCS(configObj['outdata'])

        out_sci_hdr = fits.getheader(outname)
        outexptime = out_sci_hdr['DRIZEXPT']
        if 'ndrizim' in out_sci_hdr:
            uniqid = out_sci_hdr['ndrizim']+1
        else:
            uniqid = 1

    else:  # otherwise, define the output WCS either from user pars or refimage
        if util.is_blank(configObj['User WCS Parameters']['refimage']):
            # Define a WCS based on user provided WCS values
            # NOTE:
            #   All parameters must be specified, not just one or a few
            if not util.is_blank(user_wcs_pars['outscale']):
                output_wcs = wcs_functions.build_hstwcs(
                    user_wcs_pars['raref'], user_wcs_pars['decref'],
                    user_wcs_pars['xrefpix'], user_wcs_pars['yrefpix'],
                    user_wcs_pars['outnx'], user_wcs_pars['outny'],
                    user_wcs_pars['outscale'], user_wcs_pars['orient'] )
            else:
                # Define default WCS based on input image
                applydist = True
                if input_wcs.sip is None or input_wcs.instrument=='DEFAULT':
                    applydist = False
                output_wcs = stwcs.distortion.utils.output_wcs([input_wcs],undistort=applydist)
        else:
            refimage = configObj['User WCS Parameters']['refimage']
            refroot,extroot = fileutil.parseFilename(refimage)
            if extroot is None:
                fimg = fits.open(refroot)
                for i,extn in enumerate(fimg):
                    if 'CRVAL1' in extn.header: # Key on CRVAL1 for valid WCS
                        refwcs = wcsutil.HSTWCS('{}[{}]'.format(refroot,i))
                        if refwcs.wcs.has_cd():
                            extroot = i
                            break
                fimg.close()
                # try to find extension with valid WCS
                refimage = "{}[{}]".format(refroot,extroot)
            # Define the output WCS based on a user specified reference image WCS
            output_wcs = stwcs.wcsutil.HSTWCS(refimage)
        # Initialize values used for combining results
        outexptime = 0.0
        uniqid = 1

    # Set up the output data array and insure that the units for that array is 'cps'
    if outsci is None:
        # Define a default blank array based on definition of output_wcs
        #outsci = np.zeros((output_wcs._naxis2,output_wcs._naxis1),dtype=np.float32)
        outsci = np.empty((output_wcs._naxis2,output_wcs._naxis1),dtype=np.float32)
        outsci.fill(np.nan)
    else:
        # Convert array to units of 'cps', if needed
        if outexptime != 0.0:
            np.divide(outsci, outexptime, outsci)
        outsci = outsci.astype(np.float32)

    # Now update output exposure time for additional input file
    outexptime += expin

    outwht = None
    if not util.is_blank(configObj['outweight']):
        outwht = get_data(configObj['outweight'])

    if outwht is None:
        outwht = np.zeros((output_wcs._naxis2,output_wcs._naxis1),dtype=np.float32)
    else:
        outwht = outwht.astype(np.float32)

    outcon = None
    keep_con = False

    if not util.is_blank(configObj['outcontext']):
        outcon = get_data(configObj['outcontext'])
        keep_con = True
        if outcon is None:
            outcon = np.zeros((1,output_wcs._naxis2,output_wcs._naxis1),dtype=np.int32)
        else:
            outcon = outcon.astype(np.int32)
            planeid = int((uniqid - 1)/ 32)

            # Add a new plane to the context image if planeid overflows
            while outcon.shape[0] <= planeid:
                plane = np.zeros_like(outcon[0])
                outcon = np.append(outcon, plane, axis=0)

    # Interpret wt_scl parameter
    if configObj['wt_scl'] == 'exptime':
        wt_scl = expin
    elif configObj['wt_scl'] == 'expsq':
        wt_scl = expin*expin
    else:
        wt_scl = float(configObj['wt_scl'])

    # Interpret coeffs parameter to determine whether to apply coeffs or not
    undistort = True
    if not configObj['coeffs'] or input_wcs.sip is None or input_wcs.instrument == 'DEFAULT':
        undistort = False
    # turn off use of coefficients if undistort is False (coeffs == False)
    if not undistort:
        input_wcs.sip = None
        input_wcs.cpdis1 = None
        input_wcs.cpdis2 = None
        input_wcs.det2im = None

    wcslin = distortion.utils.output_wcs([input_wcs],undistort=undistort)

    # Perform actual drizzling now...
    _vers = do_driz(insci, input_wcs, inwht,
            output_wcs, outsci, outwht, outcon,
            expin, scale_pars['in_units'],
            wt_scl, wcslin_pscale=wcslin.pscale ,uniqid=uniqid,
            pixfrac=configObj['pixfrac'], kernel=configObj['kernel'],
            fillval=scale_pars['fillval'], stepsize=configObj['stepsize'],
            wcsmap=None)

    out_sci_handle,outextn = create_output(configObj['outdata'])
    if not output_exists:
        # Also, define default header based on input image Primary header
        out_sci_handle[outextn].header = in_sci_phdr.copy()

    # Update header of output image with exptime used to scale the output data
    # if out_units is not counts, this will simply be a value of 1.0
    # the keyword 'exptime' will always contain the total exposure time
    # of all input image regardless of the output units
    out_sci_handle[outextn].header['EXPTIME'] = outexptime

    # create CTYPE strings
    ctype1 = input_wcs.wcs.ctype[0]
    ctype2 = input_wcs.wcs.ctype[1]
    if ctype1.find('-SIP'): ctype1 = ctype1.replace('-SIP','')
    if ctype2.find('-SIP'): ctype2 = ctype2.replace('-SIP','')

    # Update header with WCS keywords
    out_sci_handle[outextn].header['ORIENTAT'] = output_wcs.orientat
    out_sci_handle[outextn].header['CD1_1'] = output_wcs.wcs.cd[0][0]
    out_sci_handle[outextn].header['CD1_2'] = output_wcs.wcs.cd[0][1]
    out_sci_handle[outextn].header['CD2_1'] = output_wcs.wcs.cd[1][0]
    out_sci_handle[outextn].header['CD2_2'] = output_wcs.wcs.cd[1][1]
    out_sci_handle[outextn].header['CRVAL1'] = output_wcs.wcs.crval[0]
    out_sci_handle[outextn].header['CRVAL2'] = output_wcs.wcs.crval[1]
    out_sci_handle[outextn].header['CRPIX1'] = output_wcs.wcs.crpix[0]
    out_sci_handle[outextn].header['CRPIX2'] = output_wcs.wcs.crpix[1]
    out_sci_handle[outextn].header['CTYPE1'] = ctype1
    out_sci_handle[outextn].header['CTYPE2'] = ctype2
    out_sci_handle[outextn].header['VAFACTOR'] = 1.0


    if scale_pars['out_units'] == 'counts':
        np.multiply(outsci, outexptime, outsci)
        out_sci_handle[outextn].header['DRIZEXPT'] = outexptime

    else:
        out_sci_handle[outextn].header['DRIZEXPT'] = 1.0

    # Update header keyword NDRIZIM to keep track of how many images have
    # been combined in this product so far
    out_sci_handle[outextn].header['NDRIZIM'] = uniqid

    #define keywords to be written out to product header
    drizdict = outputimage.DRIZ_KEYWORDS.copy()

    # Update drizdict with current values
    drizdict['VER']['value'] = _vers[:44]
    drizdict['DATA']['value'] = configObj['input'][:64]
    drizdict['DEXP']['value'] = expin
    drizdict['OUDA']['value'] = configObj['outdata'][:64]
    drizdict['OUWE']['value'] = configObj['outweight'][:64]
    drizdict['OUCO']['value'] = configObj['outcontext'][:64]
    drizdict['MASK']['value'] = configObj['inweight'][:64]
    drizdict['WTSC']['value'] = wt_scl
    drizdict['KERN']['value'] = configObj['kernel']
    drizdict['PIXF']['value'] = configObj['pixfrac']
    drizdict['OUUN']['value'] = scale_pars['out_units']
    drizdict['FVAL']['value'] = scale_pars['fillval']
    drizdict['WKEY']['value'] = configObj['wcskey']
    outputimage.writeDrizKeywords(out_sci_handle[outextn].header,uniqid,drizdict)

    # add output array to output file
    out_sci_handle[outextn].data = outsci
    out_sci_handle.close()

    if not util.is_blank(configObj['outweight']):
        out_wht_handle,outwhtext = create_output(configObj['outweight'])
        out_wht_handle[outwhtext].header = out_sci_handle[outextn].header.copy()
        out_wht_handle[outwhtext].data = outwht
        out_wht_handle.close()

    if keep_con:
        out_con_handle,outconext = create_output(configObj['outcontext'])
        out_con_handle[outconext].data = outcon
        out_con_handle.close()
示例#26
0
def writeSingleFITS(data,
                    wcs,
                    output,
                    template,
                    clobber=True,
                    verbose=True,
                    rules_file=None):
    """ Write out a simple FITS file given a numpy array and the name of another
    FITS file to use as a template for the output image header.
    """
    outname, outextn = fileutil.parseFilename(output)
    outextname, outextver = fileutil.parseExtn(outextn)

    if fileutil.findFile(outname):
        if clobber:
            log.info('Deleting previous output product: %s' % outname)
            fileutil.removeFile(outname)

        else:
            log.warning('Output file %s already exists and overwrite not '
                        'specified!' % outname)
            log.error('Quitting... Please remove before resuming operations.')
            raise IOError

    # Now update WCS keywords with values from provided WCS
    if hasattr(wcs.sip, 'a_order'):
        siphdr = True
    else:
        siphdr = False
    wcshdr = wcs.wcs2header(sip2hdr=siphdr)

    if template is not None:
        # Get default headers from multi-extension FITS file
        # If input data is not in MEF FITS format, it will return 'None'
        # NOTE: These are HEADER objects, not HDUs
        (prihdr, scihdr, errhdr,
         dqhdr), newtab = getTemplates(template,
                                       EXTLIST,
                                       rules_file=rules_file)

        if scihdr is None:
            scihdr = fits.Header()
            indx = 0
            for c in prihdr.cards:
                if c.keyword not in ['INHERIT', 'EXPNAME']: indx += 1
                else: break
            for i in range(indx, len(prihdr)):
                scihdr.append(prihdr.cards[i])
            for i in range(indx, len(prihdr)):
                del prihdr[indx]
    else:
        scihdr = fits.Header()
        prihdr = fits.Header()
        # Start by updating PRIMARY header keywords...
        prihdr.set('EXTEND', value=True, after='NAXIS')
        prihdr['FILENAME'] = outname

    if outextname == '':
        outextname = 'sci'
    if outextver == 0: outextver = 1
    scihdr['EXTNAME'] = outextname.upper()
    scihdr['EXTVER'] = outextver
    scihdr.update(wcshdr)

    # Create PyFITS HDUList for all extensions
    outhdu = fits.HDUList()
    # Setup primary header as an HDU ready for appending to output FITS file
    prihdu = fits.PrimaryHDU(header=prihdr)
    scihdu = fits.ImageHDU(header=scihdr, data=data)

    outhdu.append(prihdu)
    outhdu.append(scihdu)
    outhdu.writeto(outname)

    if verbose:
        print('Created output image: %s' % outname)
示例#27
0
def getSingleTemplate(fname, extlist=['SCI', 'ERR', 'DQ']):
    """
    # Obtain default headers for output file based on a single input file
    # (Copied from outputimage module.)
    #
    Returns
    -------
    headers :  tuple of `astropy.io.fits.Header` objects, not HDU objects!
        headers
    """

    if fname is None:
        raise ValueError('No data files for creating FITS output.')

    froot,fextn = fileutil.parseFilename(fname)
    if fextn is not None:
        fnum = fileutil.parseExtn(fextn)[1]
    ftemplate = fileutil.openImage(froot,mode='readonly')
    prihdr = ftemplate['PRIMARY'].header.copy()
    try:
        del prihdr['pcount']
        del prihdr['gcount']
    except KeyError:
        pass

    if fname.find('.fits') > 0 and len(ftemplate) > 1:

        # Setup which keyword we will use to select each
        # extension...
        _extkey = 'EXTNAME'

        defnum = fileutil.findKeywordExtn(ftemplate,_extkey,extlist[0])
        #
        # Now, extract the headers necessary for output (as copies)
        # 1. Find the SCI extension in the template image
        # 2. Make a COPY of the extension header for use in new output file
        if fextn is None:
            extnum = fileutil.findKeywordExtn(ftemplate,_extkey,extlist[0])
        else:
            extnum = (extlist[0],fnum)
        #scihdr = fits.Header(cards=ftemplate[extnum].header.ascard.copy())
        scihdr = fits.Header(ftemplate[extnum].header.copy())
        #scihdr.update('extver',1)
        extnum_sci = extnum

        # Extract the header for additional extensions
        if len(extlist) > 1 and extlist[1] not in [None,'',' ','INDEF','None']:
            if fextn is None:
                extnum = fileutil.findKeywordExtn(ftemplate,_extkey,extlist[1])
            else:
                # there may or may not be a second type of extension in the template
                count = 0
                for f in ftemplate:
                    if 'extname' in f.header and f.header['extname'] == extlist[1]:
                        count += 1
                if count > 0:
                    extnum = (extlist[1],fnum)
                else:
                    # Use science header for remaining headers
                    extnum = (extlist[0],fnum)
        else:
            extnum = extnum_sci

        #errhdr = fits.Header(cards=ftemplate[extnum].header.ascard.copy())
        errhdr = fits.Header(ftemplate[extnum].header.copy())
        #errhdr.update('extver',1)
        errhdr['bunit'] = 'UNITLESS'

        if len(extlist) > 2 and extlist[2] not in [None,'',' ','INDEF','None']:

            if fextn is None:
                extnum = fileutil.findKeywordExtn(ftemplate,_extkey,extlist[2])
            else:
                count = 0
                for f in ftemplate:
                    if 'extname' in f.header and f.header['extname'] == extlist[2]:
                        count += 1
                if count > 0:
                    extnum = (extlist[2],fnum)
                else:
                    # Use science header for remaining headers
                    extnum = (extlist[0],fnum)
        else:
            extnum = extnum_sci

        #dqhdr = fits.Header(cards=ftemplate[extnum].header.ascard.copy())
        dqhdr = fits.Header(ftemplate[extnum].header.copy())
        #dqhdr.update('extver',1)
        dqhdr['bunit'] = 'UNITLESS'

    else:
        # Create default headers from scratch
        scihdr = None
        errhdr = None
        dqhdr = None

    ftemplate.close()
    del ftemplate

    return prihdr, scihdr, errhdr, dqhdr
示例#28
0
    def __init__(self,expname, handle=None, dqname=None, idckey=None,
                    new=no,wcs=None,mask=None,pa_key=None, parity=None,
                    idcdir=None, rot=None, extver=1, exptime=None,
                    ref_pscale=1.0, binned=1, mt_wcs=None, group_indx = None):

        # This name should be formatted for use in image I/O
        self.name = fileutil.osfn(expname)

        # osfn() will expand '.' unnecessarily, potentially
        # creating a string-length problem for 'drizzle', which
        # is limited to strings of 80 chars.
        _path,_name = os.path.split(self.name)
        # if path for this filename is the same as the current dir,
        # then there is no need to pass along the path.
        if _path == os.getcwd(): self.name = _name


        # Keep track of any associated mask file created for
        # this exposure from its DQ file, or other mask file.
        _fname,_extn = fileutil.parseFilename(expname)
        _open = False

        # Make sure we have an open file handle to use for getting the
        # header and data arrays.
        if not handle and not new:
            handle = fileutil.openImage(expname)
            _open = True

        # If no extension was specified, try to interrogate the file
        # to find whether the SCI array is in the Primary
        # (as in Simple FITS) or first extension (as in MEF).
        if handle and _extn == None:
            if handle[0].data == None:
                # Primary extension specified and no data present.
                # Try looking for data in next extension.
                if len(handle) > 1 and handle[1].data != None:
                    _extn = 1
                    expname += '[1]'
                else:
                    raise IOError("No valid image data in %s.\n"%expname)
            else:
                _extn = 0

        self.dgeoname = None
        self.xgeoim = ""
        self.ygeoim = ""
        self.exptime = exptime
        self.group_indx = group_indx
        if not new:
            # Read in a copy of the header for this exposure/group/extension
            _header = fileutil.getHeader(expname,handle=handle)
            _chip = drutil.getChipId(_header)
            self.chip = str(_chip)
            # Keep track of any distortion correction images provided
            # for this chip
            self.dgeoname = fileutil.getKeyword(expname,'DGEOFILE',handle=handle)
            self.xgeoim,self.ygeoim = self.getDGEOExtn()
            if self.exptime == None:
                self.exptime = float(_header['EXPTIME'])
                if self.exptime == 0.: self.exptime = 1.0
            #
            # Extract photometric transformation keywords
            #    If they do not exist, use default values of 0 and 1
            #
            self.plam = float(fileutil.getKeyword(expname,'PHOTPLAM',handle=handle)) / 10.
            if self.plam == None:
                # Setup a default value in case this keyword does not exist
                self.plam = 555.
            self.photzpt = float(fileutil.getKeyword(expname,'PHOTZPT',handle=handle))
            if self.photzpt == None: self.photzpt = 0.0
            self.photflam = float(fileutil.getKeyword(expname,'PHOTFLAM',handle=handle))
            if self.photflam == None: self.photflam = 1.0

            # Read in date-obs from primary header
            if _header:
                if 'date-obs' in _header:
                    self.dateobs = _header['date-obs']
                elif 'date_obs' in _header:
                    self.dateobs = _header['date_obs']
                else:
                    self.dateobs = None
            else:
                self.dateobs = None

            # Initialize the value of BUNIT based on the header information, if
            # the header has the keyword
            if 'BUNIT' in _header and _header['BUNIT'].find('ergs') < 0:
                self.bunit = _header['BUNIT']
            else:
                self.bunit = 'ELECTRONS'

        else:
            _chip = 1
            _header = None
            self.chip = str(_chip)
            # Set a default value for pivot wavelength
            self.plam = 555.
            self.photzpt = 0.0
            self.photflam = 1.0
            self.dateobs = None
            if self.exptime == None:
                self.exptime = 1.

        self.parity = parity
        self.header = _header
        self.extver = extver

        # Create a pointer to the mask file's data array
        # and the name of the original input DQ file
        self.maskname = None
        self.singlemaskname = None
        self.masklist = None
        if mask != None:
            # Specifies filenames to be used if created.
            self.maskname = mask[0]
            self.singlemaskname = mask[1]
            self.masklist = mask[2]

        self.dqname = dqname

        # Remember the name of the coeffs file generated for this chip
        self.coeffs = self.buildCoeffsName()

        # Read the name of idcfile from image header if not explicitly
        # provided by user.
        if idckey != None and idckey.lower() != 'wcs':
            _indx = expname.find('[')
            if  _indx > -1:
                _idc_fname = expname[:_indx]+'[0]'
            else: _idc_fname = expname+'[0]'

            idcfile, idctype = drutil.getIDCFile(self.header,keyword=idckey,
                                        directory=idcdir)
        else:
            idcfile = None
            idctype = None

        if (idckey != None)  and (idckey.lower() == 'header'):
            idckey = idctype

        # Get distortion model and WCS info.
        self.geometry = ObsGeometry(expname, idcfile, idckey=idckey,
                chip=_chip, new=new, header=self.header,
                pa_key=pa_key, rot=rot, date=self.dateobs,
                ref_pscale=ref_pscale, binned=binned, mt_wcs=mt_wcs)

        # Remember the name and type of the IDC file used...
        self.idcfile = idcfile
        self.idctype = idctype

        # Remember the names of the filters used for the exposure
        self.filters = self.geometry.filter1+','+self.geometry.filter2

        # Define shape here...
        # nx,ny,pixel scale
        #
        if wcs != None:
            # We have been passed a WCS to use
            self.geometry.wcs = wcs
            self.geometry.model.pscale = wcs.pscale
            if expname != None:
                self.geometry.wcs.rootname = expname

        self.naxis1 = self.geometry.wcs.naxis1
        self.naxis2 = self.geometry.wcs.naxis2
        self.pscale = self.geometry.wcs.pscale
        self.shape = (self.naxis1,self.naxis2,self.pscale)

        # Keep track of the positions of the corners of the exposure
        # both for the RAW image and the
        # distortion-corrected, unscaled, unrotated image
        self.corners = {'raw':np.zeros((4,2),dtype=np.float64),'corrected':np.zeros((4,2),dtype=np.float64)}
        self.setCorners()

        # Generate BLOT output name specific to this Exposure
        _blot_extn = '_sci'+repr(extver)+'_blt.fits'
        self.outblot = fileutil.buildNewRootname(self.name,extn=_blot_extn)

        # Keep track of undistorted frame's position relative to metachip
        # Zero-point offset for chip relative to meta-chip product
        # These values get computed using 'setSingleOffsets' from 'writeCoeffs'
        # to insure that the final XDELTA/YDELTA values have been computed.
        self.product_wcs = self.geometry.wcslin
        self.xzero = 0.
        self.yzero = 0.
        self.chip_shape = (0.,0.)
        self.xsh2 = 0.
        self.ysh2 = 0.

        if _open:
            handle.close()
            del handle
示例#29
0
def _update(image,idctab,nimsets,apply_tdd=False,
            quiet=None,instrument=None,prepend=None,nrchip=None, nrext=None):

    tdd_xyref = {1: [2048, 3072], 2:[2048, 1024]}
    _prepend = prepend
    _dqname = None
    # Make a copy of the header for keyword access
    # This copy includes both Primary header and
    # extension header
    hdr = fileutil.getHeader(image)

    # Try to get the instrument if we don't have it already
    instrument = readKeyword(hdr,'INSTRUME')

    binned = 1
    # Read in any specified OFFTAB, if present (WFPC2)
    offtab = readKeyword(hdr,'OFFTAB')
    dateobs = readKeyword(hdr,'DATE-OBS')
    if not quiet:
        print("OFFTAB, DATE-OBS: ",offtab,dateobs)

    print("-Updating image ",image)

    if not quiet:
        print("-Reading IDCTAB file ",idctab)

    # Get telescope orientation from image header
    # If PA_V# is not present of header, try to get it from the spt file
    pvt = readKeyword(hdr,'PA_V3')
    if pvt == None:
        sptfile = fileutil.buildNewRootname(image, extn='_spt.fits')
        if os.path.exists(sptfile):
            spthdr = fileutil.getHeader(sptfile)
            pvt = readKeyword(spthdr,'PA_V3')
    if pvt != None:
        pvt = float(pvt)
    else:
        print('PA_V3 keyword not found, WCS cannot be updated. Quitting ...')
        raise ValueError

    # Find out about instrument, detector & filters
    detector = readKeyword(hdr,'DETECTOR')

    Nrefchip=1
    if instrument == 'WFPC2':
        filter1 = readKeyword(hdr,'FILTNAM1')
        filter2 = readKeyword(hdr,'FILTNAM2')
        mode = readKeyword(hdr,'MODE')
        if os.path.exists(fileutil.buildNewRootname(image, extn='_c1h.fits')):
            _dqname = fileutil.buildNewRootname(image, extn='_c1h.fits')
            dqhdr = pyfits.getheader(_dqname,1)
            dqext = readKeyword(dqhdr, 'EXTNAME')
        if mode == 'AREA':
            binned = 2
        Nrefchip=nrchip
    elif instrument == 'NICMOS':
        filter1 = readKeyword(hdr,'FILTER')
        filter2 = None
    elif instrument == 'WFC3':
        filter1 = readKeyword(hdr,'FILTER')
        filter2 = None
        # use value of 'BINAXIS' keyword to set binning value for WFC3 data
        binned = readKeyword(hdr,'BINAXIS1')
    else:
        filter1 = readKeyword(hdr,'FILTER1')
        filter2 = readKeyword(hdr,'FILTER2')

    if filter1 == None or filter1.strip() == '': filter1 = 'CLEAR'
    else: filter1 = filter1.strip()
    if filter2 == None or filter2.strip() == '': filter2 = 'CLEAR'
    else: filter2 = filter2.strip()

    if filter1.find('CLEAR') == 0: filter1 = 'CLEAR'
    if filter2.find('CLEAR') == 0: filter2 = 'CLEAR'

    # Set up parity matrix for chip
    if instrument == 'WFPC2' or instrument =='STIS' or instrument == 'NICMOS':
        parity = PARITY[instrument]
    elif detector in PARITY:
        parity = PARITY[detector]
    else:
        raise ValueError('Detector ',detector,
                         ' Not supported at this time. Exiting...')

    # Get the VAFACTOR keyword if it exists, otherwise set to 1.0
    # we also need the reference pointing position of the target
    # as this is where
    _va_key = readKeyword(hdr,'VAFACTOR')
    if _va_key != None:
        VA_fac = float(_va_key)
    else:
        VA_fac=1.0

    if not quiet:
        print('VA factor: ',VA_fac)

    #ra_targ = float(readKeyword(hdr,'RA_TARG'))
    #dec_targ = float(readKeyword(hdr,'DEC_TARG'))

    # Get the chip number
    _c = readKeyword(hdr,'CAMERA')
    _s = readKeyword(hdr,'CCDCHIP')
    _d = readKeyword(hdr,'DETECTOR')
    if _c != None and str(_c).isdigit():
        chip = int(_c)
    elif _s == None and _d == None:
        chip = 1
    else:
        if _s:
            chip = int(_s)
        elif str(_d).isdigit():
            chip = int(_d)
        else:
            chip = 1
    # For the ACS/WFC case the chip number doesn't match the image
    # extension
    nr = 1
    if (instrument == 'ACS' and detector == 'WFC') or (instrument == 'WFC3' and detector == 'UVIS'):
        if nimsets > 1:
            Nrefchip = 2
        else:
            Nrefchip = chip
    elif instrument == 'NICMOS':
        Nrefchip = readKeyword(hdr,'CAMERA')
    elif instrument == 'WFPC2':
        nr = nrext
    else:
        if nimsets > 1:
            nr = Nrefchip

    if not quiet:
        print("-PA_V3 : ",pvt," CHIP #",chip)


    # Extract the appropriate information from the IDCTAB
    #fx,fy,refpix,order=fileutil.readIDCtab(idctab,chip=chip,direction='forward',
    #            filter1=filter1,filter2=filter2,offtab=offtab,date=dateobs)
    idcmodel = models.IDCModel(idctab,
                               chip=chip, direction='forward', date=dateobs,
                               filter1=filter1, filter2=filter2, offtab=offtab, binned=binned,
                               tddcorr=apply_tdd)
    fx = idcmodel.cx
    fy = idcmodel.cy
    refpix = idcmodel.refpix
    order = idcmodel.norder

    # Determine whether to perform time-dependent correction
    # Construct matrices neded to correct the zero points for TDD
    if apply_tdd:
        #alpha,beta = mutil.compute_wfc_tdd_coeffs(dateobs,skew_coeffs)
        alpha = refpix['TDDALPHA']
        beta = refpix['TDDBETA']
        tdd = N.array([[beta, alpha], [alpha, -beta]])
        mrotp = fileutil.buildRotMatrix(2.234529)/2048.

    else:
        alpha = 0.0
        beta = 0.0

    # Get the original image WCS
    Old=wcsutil.WCSObject(image,prefix=_prepend)

    # Reset the WCS keywords to original archived values.
    Old.restore()

    #
    # Look for any subarray offset
    #
    ltv1,ltv2 = drutil.getLTVOffsets(image)
    #
    # If reference point is not centered on distortion model
    # shift coefficients to be applied relative to observation
    # reference position
    #
    offsetx = Old.crpix1 - ltv1 - refpix['XREF']
    offsety = Old.crpix2 - ltv2 - refpix['YREF']
    shiftx = refpix['XREF'] + ltv1
    shifty = refpix['YREF'] + ltv2
    if ltv1 != 0. or ltv2 != 0.:
        ltvoffx = ltv1 + offsetx
        ltvoffy = ltv2 + offsety
        offshiftx = offsetx + shiftx
        offshifty = offsety + shifty
    else:
        ltvoffx = 0.
        ltvoffy = 0.
        offshiftx = 0.
        offshifty = 0.

    if ltv1 != 0. or ltv2 != 0.:
        fx,fy = idcmodel.shift(idcmodel.cx,idcmodel.cy,offsetx,offsety)

    # Extract the appropriate information for reference chip

    ridcmodel = models.IDCModel(idctab,
                                chip=Nrefchip, direction='forward', date=dateobs,
                                filter1=filter1, filter2=filter2, offtab=offtab, binned=binned,
                                tddcorr=apply_tdd)
    rfx = ridcmodel.cx
    rfy = ridcmodel.cy
    rrefpix = ridcmodel.refpix
    rorder = ridcmodel.norder
    """
    rfx,rfy,rrefpix,rorder=mutil.readIDCtab(idctab,chip=Nrefchip,
        direction='forward', filter1=filter1,filter2=filter2,offtab=offtab,
        date=dateobs,tddcorr=apply_tdd)
    """
    # Create the reference image name
    rimage = image.split('[')[0]+"[sci,%d]" % nr
    if not quiet:
        print("Reference image: ",rimage)

    # Create the tangent plane WCS on which the images are defined
    # This is close to that of the reference chip
    R=wcsutil.WCSObject(rimage)
    R.write_archive(rimage)
    R.restore()

    # Reacd in declination of target (for computing orientation at aperture)
    # Note that this is from the reference image
    #dec = float(fileutil.getKeyword(rimage,'CRVAL2'))
    #crval1 = float(fileutil.getKeyword(rimage,'CRVAL1'))
    #crval1 = float(R.crval1)
    #crval2 = dec
    dec = float(R.crval2)

    # Get an approximate reference position on the sky
    rref = (rrefpix['XREF']+ltvoffx, rrefpix['YREF']+ltvoffy)

    crval1,crval2=R.xy2rd(rref)

    if apply_tdd:
        # Correct zero points for TDD
        tddscale = (R.pscale/fx[1][1])
        rxy0 = N.array([[tdd_xyref[Nrefchip][0]-2048.],[ tdd_xyref[Nrefchip][1]-2048.]])
        xy0 = N.array([[tdd_xyref[chip][0]-2048.], [tdd_xyref[chip][1]-2048.]])
        rv23_corr = N.dot(mrotp,N.dot(tdd,rxy0))*tddscale
        v23_corr = N.dot(mrotp,N.dot(tdd,xy0))*tddscale
    else:
        rv23_corr = N.array([[0],[0]])
        v23_corr = N.array([[0],[0]])

    # Convert the PA_V3 orientation to the orientation at the aperture
    # This is for the reference chip only - we use this for the
    # reference tangent plane definition
    # It has the same orientation as the reference chip
    v2ref = rrefpix['V2REF'] +  rv23_corr[0][0]*0.05
    v3ref = rrefpix['V3REF'] - rv23_corr[1][0]*0.05
    v2 = refpix['V2REF'] + v23_corr[0][0]*0.05
    v3 = refpix['V3REF'] - v23_corr[1][0] *0.05

    pv = wcsutil.troll(pvt,dec,v2ref,v3ref)

    # Add the chip rotation angle
    if rrefpix['THETA']:
        pv += rrefpix['THETA']


    # Set values for the rest of the reference WCS
    R.crval1=crval1
    R.crval2=crval2
    R.crpix1=0.0 + offshiftx
    R.crpix2=0.0 + offshifty

    R_scale=rrefpix['PSCALE']/3600.0
    R.cd11=parity[0][0] *  cos(pv*pi/180.0)*R_scale
    R.cd12=parity[0][0] * -sin(pv*pi/180.0)*R_scale
    R.cd21=parity[1][1] *  sin(pv*pi/180.0)*R_scale
    R.cd22=parity[1][1] *  cos(pv*pi/180.0)*R_scale

    ##print R
    R_cdmat = N.array([[R.cd11,R.cd12],[R.cd21,R.cd22]])

    if not quiet:
        print("  Reference Chip Scale (arcsec/pix): ",rrefpix['PSCALE'])

    # Offset and angle in V2/V3 from reference chip to
    # new chip(s) - converted to reference image pixels

    off = sqrt((v2-v2ref)**2 + (v3-v3ref)**2)/(R_scale*3600.0)

    # Here we must include the PARITY
    if v3 == v3ref:
        theta=0.0
    else:
        theta = atan2(parity[0][0]*(v2-v2ref),parity[1][1]*(v3-v3ref))

    if rrefpix['THETA']: theta += rrefpix['THETA']*pi/180.0

    dX=(off*sin(theta)) + offshiftx
    dY=(off*cos(theta)) + offshifty

    # Check to see whether we are working with GEIS or FITS input
    _fname,_iextn = fileutil.parseFilename(image)

    if _fname.find('.fits') < 0:
        # Input image is NOT a FITS file, so
        #     build a FITS name for it's copy.
        _fitsname = fileutil.buildFITSName(_fname)
    else:
        _fitsname = None
    # Create a new instance of a WCS
    if _fitsname == None:
        _new_name = image
    else:
        _new_name = _fitsname+'['+str(_iextn)+']'

    #New=wcsutil.WCSObject(_new_name,new=yes)
    New = Old.copy()

    # Calculate new CRVALs and CRPIXs
    New.crval1,New.crval2=R.xy2rd((dX,dY))
    New.crpix1=refpix['XREF'] + ltvoffx
    New.crpix2=refpix['YREF'] + ltvoffy

    # Account for subarray offset
    # Angle of chip relative to chip
    if refpix['THETA']:
        dtheta = refpix['THETA'] - rrefpix['THETA']
    else:
        dtheta = 0.0

    # Create a small vector, in reference image pixel scale
    # There is no parity effect here ???
    delXX=fx[1,1]/R_scale/3600.
    delYX=fy[1,1]/R_scale/3600.
    delXY=fx[1,0]/R_scale/3600.
    delYY=fy[1,0]/R_scale/3600.

    # Convert to radians
    rr=dtheta*pi/180.0

    # Rotate the vectors
    dXX= cos(rr)*delXX - sin(rr)*delYX
    dYX= sin(rr)*delXX + cos(rr)*delYX

    dXY= cos(rr)*delXY - sin(rr)*delYY
    dYY= sin(rr)*delXY + cos(rr)*delYY

    # Transform to sky coordinates
    a,b=R.xy2rd((dX+dXX,dY+dYX))
    c,d=R.xy2rd((dX+dXY,dY+dYY))

    # Calculate the new CDs and convert to degrees
    New.cd11=diff_angles(a,New.crval1)*cos(New.crval2*pi/180.0)
    New.cd12=diff_angles(c,New.crval1)*cos(New.crval2*pi/180.0)
    New.cd21=diff_angles(b,New.crval2)
    New.cd22=diff_angles(d,New.crval2)

    # Apply the velocity aberration effect if applicable
    if VA_fac != 1.0:

        # First shift the CRVALs apart
#       New.crval1 = ra_targ + VA_fac*(New.crval1 - ra_targ)
#       New.crval2 = dec_targ + VA_fac*(New.crval2 - dec_targ)
        # First shift the CRVALs apart
        # This is now relative to the reference chip, not the
        # target position.
        New.crval1 = R.crval1 + VA_fac*diff_angles(New.crval1, R.crval1)
        New.crval2 = R.crval2 + VA_fac*diff_angles(New.crval2, R.crval2)

        # and scale the CDs
        New.cd11 = New.cd11*VA_fac
        New.cd12 = New.cd12*VA_fac
        New.cd21 = New.cd21*VA_fac
        New.cd22 = New.cd22*VA_fac

    New_cdmat = N.array([[New.cd11,New.cd12],[New.cd21,New.cd22]])

    # Store new one
    # archive=yes specifies to also write out archived WCS keywords
    # overwrite=no specifies do not overwrite any pre-existing archived keywords

    New.write(fitsname=_new_name,overwrite=no,quiet=quiet,archive=yes)
    if _dqname:
        _dq_iextn = _iextn.replace('sci', dqext.lower())
        _new_dqname = _dqname +'['+_dq_iextn+']'
        dqwcs = wcsutil.WCSObject(_new_dqname)
        dqwcs.write(fitsname=_new_dqname, wcs=New,overwrite=no,quiet=quiet, archive=yes)

    """ Convert distortion coefficients into SIP style
        values and write out to image (assumed to be FITS).
    """
    #First the CD matrix:
    f = refpix['PSCALE']/3600.0
    a = fx[1,1]/3600.0
    b = fx[1,0]/3600.0
    c = fy[1,1]/3600.0
    d = fy[1,0]/3600.0
    det = (a*d - b*c)*refpix['PSCALE']

    # Write to header
    fimg = fileutil.openImage(_new_name,mode='update')
    _new_root,_nextn = fileutil.parseFilename(_new_name)
    _new_extn = fileutil.getExtn(fimg,_nextn)


    # Transform the higher-order coefficients
    for n in range(order+1):
        for m in range(order+1):
            if n >= m and n>=2:

                # Form SIP-style keyword names
                Akey="A_%d_%d" % (m,n-m)
                Bkey="B_%d_%d" % (m,n-m)

                # Assign them values
                Aval= f*(d*fx[n,m]-b*fy[n,m])/det
                Bval= f*(a*fy[n,m]-c*fx[n,m])/det

                _new_extn.header.update(Akey,Aval)
                _new_extn.header.update(Bkey,Bval)

    # Update the SIP flag keywords as well
    #iraf.hedit(image,"CTYPE1","RA---TAN-SIP",verify=no,show=no)
    #iraf.hedit(image,"CTYPE2","DEC--TAN-SIP",verify=no,show=no)
    _new_extn.header.update("CTYPE1","RA---TAN-SIP")
    _new_extn.header.update("CTYPE2","DEC--TAN-SIP")

    # Finally we also need the order
    #iraf.hedit(image,"A_ORDER","%d" % order,add=yes,verify=no,show=no)
    #iraf.hedit(image,"B_ORDER","%d" % order,add=yes,verify=no,show=no)
    _new_extn.header.update("A_ORDER",order)
    _new_extn.header.update("B_ORDER",order)

    # Update header with additional keywords required for proper
    # interpretation of SIP coefficients by PyDrizzle.

    _new_extn.header.update("IDCSCALE",refpix['PSCALE'])
    _new_extn.header.update("IDCV2REF",refpix['V2REF'])
    _new_extn.header.update("IDCV3REF",refpix['V3REF'])
    _new_extn.header.update("IDCTHETA",refpix['THETA'])
    _new_extn.header.update("OCX10",fx[1][0])
    _new_extn.header.update("OCX11",fx[1][1])
    _new_extn.header.update("OCY10",fy[1][0])
    _new_extn.header.update("OCY11",fy[1][1])
    #_new_extn.header.update("TDDXOFF",rv23_corr[0][0] - v23_corr[0][0])
    #_new_extn.header.update("TDDYOFF",-(rv23_corr[1][0] - v23_corr[1][0]))

    # Report time-dependent coeffs, if computed
    if instrument == 'ACS' and detector == 'WFC':
        _new_extn.header.update("TDDALPHA",alpha)
        _new_extn.header.update("TDDBETA",beta)


    # Close image now
    fimg.close()
    del fimg
示例#30
0
def run(configObj, wcsmap=None):
    """
    Run the blot task based on parameters provided interactively by the user.

    """

    # Insure all output filenames specified have .fits extensions
    if configObj['outdata'][-5:] != '.fits': configObj['outdata'] += '.fits'

    scale_pars = configObj['Data Scaling Parameters']
    user_wcs_pars = configObj['User WCS Parameters']

    # PyFITS can be used here as it will always operate on
    # output from PyDrizzle (which will always be a FITS file)
    # Open the input (drizzled?) image
    _fname, _sciextn = fileutil.parseFilename(configObj['data'])
    _inimg = fileutil.openImage(_fname, memmap=False)
    _expin = fileutil.getKeyword(configObj['data'],
                                 scale_pars['expkey'],
                                 handle=_inimg)

    # Return the PyFITS HDU corresponding to the named extension
    _scihdu = fileutil.getExtn(_inimg, _sciextn)
    _insci = _scihdu.data.copy()

    _inexptime = 1.0
    if scale_pars['in_units'] == 'counts':
        if scale_pars['expkey'] in _inimg['PRIMARY'].header:
            _inexptime = _inimg['PRIMARY'].header[scale_pars['expkey']]
        elif 'DRIZEXPT' in _inimg['PRIMARY'].header:
            # Try keyword written out by new 'drizzle' if no valid 'expkey' was given
            _inexptime = _inimg['PRIMARY'].header['DRIZEXPT']
        else:
            raise ValueError('No valid exposure time keyword could be found '
                             'for input %s' % configObj['data'])
    # always convert input to 'cps' for blot() algorithm
    if _inexptime != 0.0 or _inexptime != 1.0:
        np.divide(_insci, _inexptime, _insci)

    _inimg.close()
    del _inimg

    # read in WCS from source (drizzled) image
    source_wcs = stwcs.wcsutil.HSTWCS(configObj['data'])
    if source_wcs.wcs.is_unity():
        print(
            "WARNING: No valid WCS found for input drizzled image: {}!".format(
                configObj['data']))

    # define blot_wcs
    blot_wcs = None
    _refname, _refextn = fileutil.parseFilename(configObj['reference'])
    if os.path.exists(_refname):
        # read in WCS from pre-existing output image
        blot_wcs = stwcs.wcsutil.HSTWCS(configObj['reference'])
        if blot_wcs.wcs.is_unity():
            print("WARNING: No valid WCS found for output image: {} !".format(
                configObj['reference']))

    # define blot WCS based on input images or specified reference WCS values
    if user_wcs_pars['user_wcs']:
        blot_wcs = wcs_functions.build_hstwcs(user_wcs_pars['raref'],
                                              user_wcs_pars['decref'],
                                              user_wcs_pars['xrefpix'],
                                              user_wcs_pars['yrefpix'],
                                              int(user_wcs_pars['outnx']),
                                              int(user_wcs_pars['outny']),
                                              user_wcs_pars['outscale'],
                                              user_wcs_pars['orient'])
        configObj['coeffs'] = None

    # If blot_wcs is still not defined at this point, we have a problem...
    if blot_wcs is None:
        blot_wcs = stwcs.distortion.utils.output_wcs([source_wcs],
                                                     undistort=False)

    out_wcs = blot_wcs.copy()
    # perform blotting operation now
    _outsci = do_blot(_insci,
                      source_wcs,
                      out_wcs,
                      _expin,
                      coeffs=configObj['coeffs'],
                      interp=configObj['interpol'],
                      sinscl=configObj['sinscl'],
                      stepsize=configObj['stepsize'],
                      wcsmap=wcsmap)
    # create output with proper units and exptime-scaling
    if scale_pars['out_units'] == 'counts':
        if scale_pars['expout'] == 'input':
            _outscale = fileutil.getKeyword(configObj['reference'],
                                            scale_pars['expkey'])
            #_outscale = _expin
        else:
            _outscale = float(scale_pars['expout'])
        print(
            "Output blotted images scaled by exptime of {}".format(_outscale))
        np.multiply(_outsci, _outscale, _outsci)

    # Add sky back in to the blotted image, as specified by the user
    if configObj['addsky']:
        skyval = _scihdu.header['MDRIZSKY']
    else:
        skyval = configObj['skyval']
    print("Added {} counts back in to blotted image as sky.".format(skyval))
    _outsci += skyval

    del _scihdu

    # Write output Numpy objects to a PyFITS file
    # Blotting only occurs from a drizzled SCI extension
    # to a blotted SCI extension...
    outputimage.writeSingleFITS(_outsci, blot_wcs, configObj['outdata'],
                                configObj['reference'])
示例#31
0
def make_outputwcs(imageObjectList, output, configObj=None, perfect=False):
    """ Computes the full output WCS based on the set of input imageObjects
        provided as input, along with the pre-determined output name from
        process_input.  The user specified output parameters are then used to
        modify the default WCS to produce the final desired output frame.
        The input imageObjectList has the outputValues dictionary
        updated with the information from the computed output WCS.
        It then returns this WCS as a WCSObject(imageObject)
        instance.

    """
    if not isinstance(imageObjectList, list):
        imageObjectList = [imageObjectList]

    # Compute default output WCS, replace later if user specifies a refimage
    hstwcs_list = []
    undistort = True
    for img in imageObjectList:
        chip_wcs = copy.deepcopy(img.getKeywordList('wcs'))
        # IF the user turned off use of coeffs (coeffs==False)
        if not configObj['coeffs']:
            for cw in chip_wcs:
                # Turn off distortion model for each input
                cw.sip = None
                cw.cpdis1 = None
                cw.cpdis2 = None
                cw.det2im = None
            undistort = False
        hstwcs_list += chip_wcs
    if not undistort and len(hstwcs_list) == 1:
        default_wcs = hstwcs_list[0].deepcopy()
    else:
        default_wcs = utils.output_wcs(hstwcs_list, undistort=undistort)

    if perfect:
        default_wcs.wcs.cd = make_perfect_cd(default_wcs)

    # Turn WCS instances into WCSObject instances
    outwcs = createWCSObject(output, default_wcs, imageObjectList)

    # Merge in user-specified attributes for the output WCS
    # as recorded in the input configObj object.
    final_pars = DEFAULT_WCS_PARS.copy()

    # More interpretation of the configObj needs to be done here to translate
    # the input parameter names to those understood by 'mergeWCS' as defined
    # by the DEFAULT_WCS_PARS dictionary.
    single_step = configObj[util.getSectionName(configObj, 3)]
    singleParDict = configObj[util.getSectionName(configObj, '3a')].copy()
    if single_step['driz_separate'] and singleParDict['driz_sep_wcs']:
        single_pars = DEFAULT_WCS_PARS.copy()
        del singleParDict['driz_sep_wcs']
        keyname = 'driz_sep_'
        for key in singleParDict:
            k = key[len(keyname):]
            if k != 'refimage':
                single_pars[k] = singleParDict[key]

        # Now, account for any user-specified reference image
        def_wcs = default_wcs.deepcopy()
        single_ref = singleParDict[keyname + 'refimage']
        if single_ref:
            if isinstance(single_ref, wcs.WCS):
                default_wcs = single_ref
            else:
                default_wcs = wcsutil.HSTWCS(singleParDict[keyname + 'refimage'])

        # ## Create single_wcs instance based on user parameters
        outwcs.single_wcs = mergeWCS(default_wcs, single_pars)
        # restore global default WCS to original value so single_drizzle WCS does not
        # influence final_drizzle WCS
        default_wcs = def_wcs.deepcopy()

    final_step = configObj[util.getSectionName(configObj, 7)]
    finalParDict = configObj[util.getSectionName(configObj, '7a')].copy()
    if final_step['driz_combine'] and finalParDict['final_wcs']:
        del finalParDict['final_wcs']
        keyname = 'final_'
        for key in finalParDict:
            k = key[len(keyname):]
            if k != 'refimage':
                final_pars[k] = finalParDict[key]

        # Now, account for any user-specified reference image
        final_ref = finalParDict[keyname + 'refimage']
        if final_ref:
            if isinstance(final_ref, wcs.WCS):
                default_wcs = final_ref
                if hasattr(final_ref, 'filename'):
                    rootname = final_ref.filename
                else:
                    rootname = ""
                print('Creating OUTPUT WCS from WCS object based on {}'.format(rootname))
            else:
                rootname, extnum = fileutil.parseFilename(finalParDict[keyname + 'refimage'])
                extnum = util.findWCSExtn(finalParDict[keyname + 'refimage'])
                print('Creating OUTPUT WCS from {}[{}]'.format(rootname, extnum))
                default_wcs = wcsutil.HSTWCS('{}[{}]'.format(rootname, extnum))

        # ## Create single_wcs instance based on user parameters
        outwcs.final_wcs = mergeWCS(default_wcs, final_pars)
        outwcs.wcs = outwcs.final_wcs.copy()

    # Apply user settings to create custom output_wcs instances
    # for each drizzle step
    updateImageWCS(imageObjectList, outwcs)

    return outwcs
示例#32
0
def tran(inimage,outimage,direction='forward',x=None,y=None,
        coords=None, coordfile=None,colnames=None,separator=None,
        precision=6, output=None,verbose=True):
    """ Primary interface to perform coordinate transformations in pixel
        coordinates between 2 images using STWCS and full distortion models
        read from each image's header.
    """
    single_coord = False

    # Only use value provided in `coords` if nothing has been specified for coordfile
    if coords is not None and coordfile is None:
        coordfile = coords
        warnings.simplefilter('always',DeprecationWarning)
        warnings.warn("Please update calling code to pass in `coordfile` instead of `coords`.",
            category=DeprecationWarning)
        warnings.simplefilter('default',DeprecationWarning)

    if coordfile is not None:
        if colnames in util.blank_list:
            colnames = ['c1','c2']
        # Determine columns which contain pixel positions
        cols = util.parse_colnames(colnames,coordfile)
        # read in columns from input coordinates file
        xyvals = np.loadtxt(coordfile,usecols=cols,delimiter=separator)
        if xyvals.ndim == 1: # only 1 entry in coordfile
            xlist = [xyvals[0].copy()]
            ylist = [xyvals[1].copy()]
        else:
            xlist = xyvals[:,0].copy()
            ylist = xyvals[:,1].copy()
        del xyvals
    else:
        if isinstance(x,np.ndarray):
            xlist = x.tolist()
            ylist = y.tolist()
        elif not isinstance(x,list):
            xlist = [x]
            ylist = [y]
            single_coord = True
        else:
            xlist = x
            ylist = y

    # start by reading in WCS+distortion info for each image
    im1wcs = wcsutil.HSTWCS(inimage)
    if im1wcs.wcs.is_unity():
        print("####\nNo valid input WCS found in {}.\n  Results may be invalid.\n####\n".format(inimage))

    if util.is_blank(outimage):
        fname,fextn = fileutil.parseFilename(inimage)
        numsci = fileutil.countExtn(fname)
        chips = []
        for e in range(1,numsci+1):
            chips.append(wcsutil.HSTWCS(fname,ext=('sci',e)))
        if len(chips) == 0:
            chips = [im1wcs]
        im2wcs = distortion.utils.output_wcs(chips)
    else:
        im2wcs = wcsutil.HSTWCS(outimage)

    if im2wcs.wcs.is_unity():
        print("####\nNo valid output WCS found in {}.\n  Results may be invalid.\n####\n".format(outimage))

    # Setup the transformation
    p2p = wcs_functions.WCSMap(im1wcs,im2wcs)

    if direction[0].lower() == 'f':
        outx,outy = p2p.forward(xlist,ylist)
    else:
        outx,outy = p2p.backward(xlist,ylist)

    if isinstance(outx,np.ndarray):
        outx = outx.tolist()
        outy = outy.tolist()

    # add formatting based on precision here...
    xstr = []
    ystr = []
    fmt = "%."+repr(precision)+"f"
    for ox,oy in zip(outx,outy):
        xstr.append(fmt%ox)
        ystr.append(fmt%oy)

    if verbose or (not verbose and util.is_blank(output)):
        print('# Coordinate transformations for ',inimage)
        print('# X(in)      Y(in)             X(out)         Y(out)\n')
        for xs,ys,a,b in zip(xlist,ylist,xstr,ystr):
            print("%.4f  %.4f    %s  %s"%(xs,ys,a,b))

    # Create output file, if specified
    if output:
        f = open(output,mode='w')
        f.write("# Coordinates converted from %s\n"%inimage)
        for xs,ys in zip(xstr,ystr):
            f.write('%s    %s\n'%(xs,ys))
        f.close()
        print('Wrote out results to: ',output)

    if single_coord:
        outx = outx[0]
        outy = outy[0]
    return outx,outy
示例#33
0
def run(configObj,wcsmap=None):
    """
    Run the blot task based on parameters provided interactively by the user.

    """

    # Insure all output filenames specified have .fits extensions
    if configObj['outdata'][-5:] != '.fits': configObj['outdata'] += '.fits'

    scale_pars = configObj['Data Scaling Parameters']
    user_wcs_pars = configObj['User WCS Parameters']

    # PyFITS can be used here as it will always operate on
    # output from PyDrizzle (which will always be a FITS file)
    # Open the input (drizzled?) image
    _fname,_sciextn = fileutil.parseFilename(configObj['data'])
    _inimg = fileutil.openImage(_fname)
    _expin = fileutil.getKeyword(configObj['data'],scale_pars['expkey'],handle=_inimg)

    # Return the PyFITS HDU corresponding to the named extension
    _scihdu = fileutil.getExtn(_inimg,_sciextn)
    _insci = _scihdu.data.copy()

    _inexptime = 1.0
    if scale_pars['in_units'] == 'counts':
        if scale_pars['expkey'] in _inimg['PRIMARY'].header:
            _inexptime = _inimg['PRIMARY'].header[scale_pars['expkey']]
        elif 'DRIZEXPT' in _inimg['PRIMARY'].header:
            # Try keyword written out by new 'drizzle' if no valid 'expkey' was given
            _inexptime = _inimg['PRIMARY'].header['DRIZEXPT']
        else:
            raise ValueError('No valid exposure time keyword could be found '
                             'for input %s' % configObj['data'])
    # always convert input to 'cps' for blot() algorithm
    if _inexptime != 0.0 or _inexptime != 1.0:
        np.divide(_insci, _inexptime, _insci)

    _inimg.close()
    del _inimg

    # read in WCS from source (drizzled) image
    source_wcs = stwcs.wcsutil.HSTWCS(configObj['data'])
    if source_wcs.wcs.is_unity():
        print("WARNING: No valid WCS found for input drizzled image: {}!".format(configObj['data']))

    # define blot_wcs
    blot_wcs = None
    _refname,_refextn = fileutil.parseFilename(configObj['reference'])
    if os.path.exists(_refname):
        # read in WCS from pre-existing output image
        blot_wcs = stwcs.wcsutil.HSTWCS(configObj['reference'])
        if blot_wcs.wcs.is_unity():
            print("WARNING: No valid WCS found for output image: {} !".format(configObj['reference']))

    # define blot WCS based on input images or specified reference WCS values
    if user_wcs_pars['user_wcs']:
        blot_wcs = wcs_functions.build_hstwcs(
            user_wcs_pars['raref'], user_wcs_pars['decref'],
            user_wcs_pars['xrefpix'], user_wcs_pars['yrefpix'],
            user_wcs_pars['outnx'], user_wcs_pars['outny'],
            user_wcs_pars['outscale'], user_wcs_pars['orient'] )
        configObj['coeffs'] = None

    # If blot_wcs is still not defined at this point, we have a problem...
    if blot_wcs is None:
        blot_wcs = stwcs.distortion.utils.output_wcs([source_wcs],undistort=False)

    out_wcs = blot_wcs.copy()
    # perform blotting operation now
    _outsci = do_blot(_insci, source_wcs, out_wcs, _expin, coeffs=configObj['coeffs'],
                    interp=configObj['interpol'], sinscl=configObj['sinscl'],
            stepsize=configObj['stepsize'], wcsmap=wcsmap)
    # create output with proper units and exptime-scaling
    if scale_pars['out_units'] == 'counts':
        if scale_pars['expout'] == 'input':
            _outscale = fileutil.getKeyword(configObj['reference'],scale_pars['expkey'])
            #_outscale = _expin
        else:
            _outscale = float(scale_pars['expout'])
        print("Output blotted images scaled by exptime of {}".format(_outscale))
        np.multiply(_outsci, _outscale, _outsci)

    # Add sky back in to the blotted image, as specified by the user
    if configObj['addsky']:
        skyval = _scihdu.header['MDRIZSKY']
    else:
        skyval = configObj['skyval']
    print("Added {} counts back in to blotted image as sky.".format(skyval))
    _outsci += skyval

    del _scihdu

    # Write output Numpy objects to a PyFITS file
    # Blotting only occurs from a drizzled SCI extension
    # to a blotted SCI extension...
    outputimage.writeSingleFITS(_outsci,blot_wcs, configObj['outdata'],configObj['reference'])
示例#34
0
def getSingleTemplate(fname, extlist=['SCI', 'ERR', 'DQ']):
    """
    # Obtain default headers for output file based on a single input file
    # (Copied from outputimage module.)
    #
    Returns
    -------
    headers :  tuple of `astropy.io.fits.Header` objects, not HDU objects!
        headers
    """

    if fname is None:
        raise ValueError('No data files for creating FITS output.')

    froot, fextn = fileutil.parseFilename(fname)
    if fextn is not None:
        fnum = fileutil.parseExtn(fextn)[1]
    ftemplate = fileutil.openImage(froot, mode='readonly')
    prihdr = ftemplate['PRIMARY'].header.copy()
    try:
        del prihdr['pcount']
        del prihdr['gcount']
    except KeyError:
        pass

    if fname.find('.fits') > 0 and len(ftemplate) > 1:

        # Setup which keyword we will use to select each
        # extension...
        _extkey = 'EXTNAME'

        defnum = fileutil.findKeywordExtn(ftemplate, _extkey, extlist[0])
        #
        # Now, extract the headers necessary for output (as copies)
        # 1. Find the SCI extension in the template image
        # 2. Make a COPY of the extension header for use in new output file
        if fextn is None:
            extnum = fileutil.findKeywordExtn(ftemplate, _extkey, extlist[0])
        else:
            extnum = (extlist[0], fnum)
        #scihdr = fits.Header(cards=ftemplate[extnum].header.ascard.copy())
        scihdr = fits.Header(ftemplate[extnum].header.copy())
        #scihdr.update('extver',1)
        extnum_sci = extnum

        # Extract the header for additional extensions
        if len(extlist) > 1 and extlist[1] not in [
                None, '', ' ', 'INDEF', 'None'
        ]:
            if fextn is None:
                extnum = fileutil.findKeywordExtn(ftemplate, _extkey,
                                                  extlist[1])
            else:
                # there may or may not be a second type of extension in the template
                count = 0
                for f in ftemplate:
                    if 'extname' in f.header and f.header[
                            'extname'] == extlist[1]:
                        count += 1
                if count > 0:
                    extnum = (extlist[1], fnum)
                else:
                    # Use science header for remaining headers
                    extnum = (extlist[0], fnum)
        else:
            extnum = extnum_sci

        #errhdr = fits.Header(cards=ftemplate[extnum].header.ascard.copy())
        errhdr = fits.Header(ftemplate[extnum].header.copy())
        #errhdr.update('extver',1)
        errhdr['bunit'] = 'UNITLESS'

        if len(extlist) > 2 and extlist[2] not in [
                None, '', ' ', 'INDEF', 'None'
        ]:

            if fextn is None:
                extnum = fileutil.findKeywordExtn(ftemplate, _extkey,
                                                  extlist[2])
            else:
                count = 0
                for f in ftemplate:
                    if 'extname' in f.header and f.header[
                            'extname'] == extlist[2]:
                        count += 1
                if count > 0:
                    extnum = (extlist[2], fnum)
                else:
                    # Use science header for remaining headers
                    extnum = (extlist[0], fnum)
        else:
            extnum = extnum_sci

        #dqhdr = fits.Header(cards=ftemplate[extnum].header.ascard.copy())
        dqhdr = fits.Header(ftemplate[extnum].header.copy())
        #dqhdr.update('extver',1)
        dqhdr['bunit'] = 'UNITLESS'

    else:
        # Create default headers from scratch
        scihdr = None
        errhdr = None
        dqhdr = None

    ftemplate.close()
    del ftemplate

    return prihdr, scihdr, errhdr, dqhdr
示例#35
0
def make_outputwcs(imageObjectList, output, configObj=None, perfect=False):
    """ Computes the full output WCS based on the set of input imageObjects
        provided as input, along with the pre-determined output name from
        process_input.  The user specified output parameters are then used to
        modify the default WCS to produce the final desired output frame.
        The input imageObjectList has the outputValues dictionary
        updated with the information from the computed output WCS.
        It then returns this WCS as a WCSObject(imageObject)
        instance.

    """
    if not isinstance(imageObjectList,list):
        imageObjectList = [imageObjectList]

    # Compute default output WCS, replace later if user specifies a refimage
    hstwcs_list = []
    undistort=True
    for img in imageObjectList:
        chip_wcs = copy.deepcopy(img.getKeywordList('wcs'))
        # IF the user turned off use of coeffs (coeffs==False)
        if not configObj['coeffs']:
            for cw in chip_wcs:
                # Turn off distortion model for each input
                cw.sip = None
                cw.cpdis1 = None
                cw.cpdis2 = None
                cw.det2im = None
            undistort=False
        hstwcs_list += chip_wcs
    if not undistort and len(hstwcs_list) == 1:
        default_wcs = hstwcs_list[0].deepcopy()
    else:
        default_wcs = utils.output_wcs(hstwcs_list, undistort=undistort)

    if perfect:
        default_wcs.wcs.cd = make_perfect_cd(default_wcs)

    # Turn WCS instances into WCSObject instances
    outwcs = createWCSObject(output, default_wcs, imageObjectList)

    # Merge in user-specified attributes for the output WCS
    # as recorded in the input configObj object.
    final_pars = DEFAULT_WCS_PARS.copy()

    # More interpretation of the configObj needs to be done here to translate
    # the input parameter names to those understood by 'mergeWCS' as defined
    # by the DEFAULT_WCS_PARS dictionary.
    single_step = configObj[util.getSectionName(configObj, 3)]
    singleParDict = configObj[util.getSectionName(configObj, '3a')].copy()
    if single_step['driz_separate'] and singleParDict['driz_sep_wcs']:
        single_pars = DEFAULT_WCS_PARS.copy()
        del singleParDict['driz_sep_wcs']
        keyname = 'driz_sep_'
        for key in singleParDict:
            k = key[len(keyname):]
            if k != 'refimage':
                single_pars[k] = singleParDict[key]

        # Now, account for any user-specified reference image
        def_wcs = default_wcs.deepcopy()
        if singleParDict[keyname + 'refimage']:
            default_wcs = wcsutil.HSTWCS(singleParDict[keyname + 'refimage'])

        ### Create single_wcs instance based on user parameters
        outwcs.single_wcs = mergeWCS(default_wcs, single_pars)
        # restore global default WCS to original value so single_drizzle WCS does not
        # influence final_drizzle WCS
        default_wcs = def_wcs.deepcopy()

    final_step = configObj[util.getSectionName(configObj,7)]
    finalParDict = configObj[util.getSectionName(configObj,'7a')].copy()
    if final_step['driz_combine'] and finalParDict['final_wcs']:
        del finalParDict['final_wcs']
        keyname = 'final_'
        for key in finalParDict:
            k = key[len(keyname):]
            if k != 'refimage':
                final_pars[k] = finalParDict[key]

        # Now, account for any user-specified reference image
        if finalParDict[keyname + 'refimage']:
            rootname,extnum = fileutil.parseFilename(finalParDict[keyname+'refimage'])
            extnum = util.findWCSExtn(finalParDict[keyname+'refimage'])
            print('Creating OUTPUT WCS from {}[{}]'.format(rootname,extnum))
            default_wcs = wcsutil.HSTWCS('{}[{}]'.format(rootname,extnum))

        ### Create single_wcs instance based on user parameters
        outwcs.final_wcs = mergeWCS(default_wcs, final_pars)
        outwcs.wcs = outwcs.final_wcs.copy()

    # Apply user settings to create custom output_wcs instances
    # for each drizzle step
    updateImageWCS(imageObjectList, outwcs)

    return outwcs