Exemple #1
0
def getMdriztabParameters(files):
    """ Gets entry in MDRIZTAB where task parameters live.
        This method returns a record array mapping the selected
        row.
    """

    # Get the MDRIZTAB table file name from the primary header.
    # It is gotten from the first file in the input list. No
    # consistency checks are performed.
    _fileName = files[0]
    _header = fileutil.getHeader(_fileName)
    if 'MDRIZTAB' in _header:
        _tableName = _header['MDRIZTAB']
    else:
        raise KeyError("No MDRIZTAB found in file " + _fileName)

    _tableName = fileutil.osfn(_tableName)

    # Now get the filters from the primary header.
    _filters = fileutil.getFilterNames(_header)

    # Specifically check to see whether the MDRIZTAB file can be found
    mtab_path = os.path.split(_tableName)[0] # protect against no path given for _tableName
    if mtab_path and not os.path.exists(mtab_path): # check path first, if given
        raise IOError("Directory for MDRIZTAB '%s' could not be accessed!"%mtab_path)
    if not os.path.exists(_tableName): # then check for the table itself
        raise IOError("MDRIZTAB table '%s' could not be found!"%_tableName)

    # Open MDRIZTAB file.
    try:
        _mdriztab = fits.open(_tableName, memmap=False)
    except:
        raise IOError("MDRIZTAB table '%s' not valid!" % _tableName)

    # Look for matching rows based on filter name. If no
    # match, pick up rows for the default filter.
    _rows = _getRowsByFilter(_mdriztab, _filters)
    if _rows == []:
        _rows = _getRowsByFilter(_mdriztab, 'ANY')

    # Now look for the row that matches the number of images.
    # The logic below assumes that rows for a given filter
    # are arranged in ascending order of the 'numimage' field.
    _nimages = len(files)
    _row = 0
    for i in _rows:
        _numimages = _mdriztab[1].data.field('numimages')[i]
        if _nimages >= _numimages:
            _row = i
    print('- MDRIZTAB: AstroDrizzle parameters read from row %s.'%(_row+1))

    mpars = _mdriztab[1].data[_row]
    _mdriztab.close()

    interpreted = _interpretMdriztabPars(mpars)

    if "staticfile" in interpreted:
        interpreted.pop("staticfile")

    return interpreted
def getMdriztabParameters(files):
    """ Gets entry in MDRIZTAB where task parameters live.
        This method returns a record array mapping the selected
        row.
    """

    # Get the MDRIZTAB table file name from the primary header.
    # It is gotten from the first file in the input list. No
    # consistency checks are performed.
    _fileName = files[0]
    _header = fileutil.getHeader(_fileName)
    if 'MDRIZTAB' in _header:
        _tableName = _header['MDRIZTAB']
    else:
        raise KeyError("No MDRIZTAB found in file " + _fileName)

    _tableName = fileutil.osfn(_tableName)

    # Now get the filters from the primary header.
    _filters = fileutil.getFilterNames(_header)

    # Specifically check to see whether the MDRIZTAB file can be found
    mtab_path = os.path.split(_tableName)[0] # protect against no path given for _tableName
    if mtab_path and not os.path.exists(mtab_path): # check path first, if given
        raise IOError("Directory for MDRIZTAB '%s' could not be accessed!"%mtab_path)
    if not os.path.exists(_tableName): # then check for the table itself
        raise IOError("MDRIZTAB table '%s' could not be found!"%_tableName)

    # Open MDRIZTAB file.
    try:
        _mdriztab = fits.open(_tableName)
    except:
        raise IOError("MDRIZTAB table '%s' not valid!" % _tableName)

    # Look for matching rows based on filter name. If no
    # match, pick up rows for the default filter.
    _rows = _getRowsByFilter(_mdriztab, _filters)
    if _rows == []:
        _rows = _getRowsByFilter(_mdriztab, 'ANY')

    # Now look for the row that matches the number of images.
    # The logic below assumes that rows for a given filter
    # are arranged in ascending order of the 'numimage' field.
    _nimages = len(files)
    _row = 0
    for i in _rows:
        _numimages = _mdriztab[1].data.field('numimages')[i]
        if _nimages >= _numimages:
            _row = i
    print('- MDRIZTAB: AstroDrizzle parameters read from row %s.'%(_row+1))

    mpars = _mdriztab[1].data[_row]
    _mdriztab.close()

    interpreted = _interpretMdriztabPars(mpars)

    if "staticfile" in interpreted:
        interpreted.pop("staticfile")

    return interpreted
Exemple #3
0
def getIDCFile(image,keyword="",directory=None):
    # Open the primary header of the file and read the name of
    # the IDCTAB.
    # Parameters:
    #   header -  primary and extension header object to read IDCTAB info
    #
    #   keyword(optional) - header keyword with name of IDCTAB
    #            --OR-- 'HEADER' if need to build IDCTAB name from scratch
    #           (default value: 'IDCTAB')
    #   directory(optional) - directory with default drizzle coeffs tables
    #                   (default value: 'drizzle$coeffs')
    #
    # This function needs to be generalized to support
    # keyword='HEADER', as would be the case for WFPC2 data.
    #


    if type(image) == type(''):
        # We were provided an image name, so read in the header...
        header = fileutil.getHeader(image)
    else:
        # otherwise, we were provided an image header we can work with directly
        header = image

    if keyword.lower() == 'header':
        idcfile,idctype = __getIDCTAB(header)
        if (idcfile == None):
            idcfile,idctype = __buildIDCTAB(header,directory)

    elif keyword.lower() == 'idctab':
        # keyword specifies header keyword with IDCTAB name
        idcfile,idctype = __getIDCTAB(header)

    elif keyword == '':
        idcfile = None
        idctype = None
    else:
        # Need to build IDCTAB filename from scratch
        idcfile,idctype = __buildIDCTAB(header,directory,kw = keyword)

    # Account for possible absence of IDCTAB name in header
    if idcfile == 'N/A':
        idcfile = None

    if idcfile != None and idcfile != '':
        # Now we need to recursively expand any IRAF symbols to full paths...
        #if directory:
        idcfile = fileutil.osfn(idcfile)


    if idcfile == None:
        print('WARNING: No valid distortion coefficients available!')
        print('Using default unshifted, unscaled, unrotated model.')

    return idcfile,idctype
    def getExptime(self):

        header = fileutil.getHeader(self.name+'[sci,1]')
        _exptime = float(header['EXPTIME'])
        if _exptime == 0.: _exptime = 1.0

        if 'EXPSTART' in header:
            _expstart = float(header['EXPSTART'])
            _expend = float(header['EXPEND'])
        else:
            _expstart = 0.
            _expend = _exptime

        return (_exptime,_expstart,_expend)
Exemple #5
0
def check_exptime(filelist):
    """
    Removes files with EXPTIME==0 from filelist.
    """
    removed_files = []
    for f in filelist:
        try:
            exptime = fileutil.getHeader(f+'[sci,1]')['EXPTIME']
        except KeyError:
            removed_files.append(f)
            print("Warning:  There are files without keyword EXPTIME")
            continue
        if exptime <= 0:
            removed_files.append(f)
            print("Warning:  There are files with zero exposure time: keyword EXPTIME = 0.0")

    if removed_files != []:
        print("Warning:  Removing the following files from input list")
        for f in removed_files:
            print('\t',f)
    return removed_files
Exemple #6
0
def check_exptime(filelist):
    """
    Removes files with EXPTIME==0 from filelist.
    """
    removed_files = []
    for f in filelist:
        try:
            exptime = fileutil.getHeader(f + '[sci,1]')['EXPTIME']
        except KeyError:
            removed_files.append(f)
            print("Warning:  There are files without keyword EXPTIME")
            continue
        if exptime <= 0:
            removed_files.append(f)
            print(
                "Warning:  There are files with zero exposure time: keyword EXPTIME = 0.0"
            )

    if removed_files != []:
        print("Warning:  Removing the following files from input list")
        for f in removed_files:
            print('\t', f)
    return removed_files
Exemple #7
0
def _getInputImage (input,group=None):
    """ Factory function to return appropriate imageObject class instance"""
    # extract primary header and SCI,1 header from input image
    sci_ext = 'SCI'
    if group in [None,'']:
        exten = '[sci,1]'
        phdu = fits.getheader(input, memmap=False)
    else:
        # change to use fits more directly here?
        if group.find(',') > 0:
            grp = group.split(',')
            if grp[0].isalpha():
                grp = (grp[0],int(grp[1]))
            else:
                grp = int(grp[0])
        else:
            grp = int(group)
        phdu = fits.getheader(input, memmap=False)
        phdu.extend(fits.getheader(input, ext=grp, memmap=False))

    # Extract the instrument name for the data that is being processed by Multidrizzle
    _instrument = phdu['INSTRUME']

    # Determine the instrument detector in use.  NICMOS is a special case because it does
    # not use the 'DETECTOR' keyword.  It instead used 'CAMERA' to identify which of it's
    # 3 camera's is in use.  All other instruments support the 'DETECTOR' keyword.
    if _instrument == 'NICMOS':
        _detector = phdu['CAMERA']
    else:
        try:
            _detector = phdu['DETECTOR']
        except KeyError:
            # using the phdu as set above (fits.getheader) is MUCH faster and
            # works for the majority of data; but fileutil handles waivered fits
            phdu = fileutil.getHeader(input+exten)
            _detector = phdu['DETECTOR'] # if this fails, let it throw

    del phdu # just to keep clean
    # Match up the instrument and detector with the right class
    # only importing the instrument modules as needed.
    try:
        if _instrument == 'ACS':
            from . import acsData
            if _detector == 'HRC': return acsData.HRCInputImage(input,group=group)
            if _detector == 'WFC': return acsData.WFCInputImage(input,group=group)
            if _detector == 'SBC': return acsData.SBCInputImage(input,group=group)
        if _instrument == 'NICMOS':
            from . import nicmosData
            if _detector == 1: return nicmosData.NIC1InputImage(input)
            if _detector == 2: return nicmosData.NIC2InputImage(input)
            if _detector == 3: return nicmosData.NIC3InputImage(input)


        if _instrument == 'WFPC2':
            from . import wfpc2Data
            return wfpc2Data.WFPC2InputImage(input,group=group)
        """
            if _detector == 1: return wfpc2Data.PCInputImage(input)
            if _detector == 2: return wfpc2Data.WF2InputImage(input)
            if _detector == 3: return wfpc2Data.WF3InputImage(input)
            if _detector == 4: return wfpc2Data.WF4InputImage(input)
        """
        if _instrument == 'STIS':
            from . import stisData
            if _detector == 'CCD': return stisData.CCDInputImage(input,group=group)
            if _detector == 'FUV-MAMA': return stisData.FUVInputImage(input,group=group)
            if _detector == 'NUV-MAMA': return stisData.NUVInputImage(input,group=group)
        if _instrument == 'WFC3':
            from . import wfc3Data
            if _detector == 'UVIS': return wfc3Data.WFC3UVISInputImage(input,group=group)
            if _detector == 'IR': return wfc3Data.WFC3IRInputImage(input,group=group)

    except ImportError:
        msg = 'No module implemented for '+str(_instrument)+'!'
        raise ValueError(msg)
    # If a supported instrument is not detected, print the following error message
    # and raise an exception.
    msg = 'Instrument: ' + str(_instrument) + '/' + str(_detector) + ' not yet supported!'
    raise ValueError(msg)
Exemple #8
0
def _getInputImage(input, output=None, group=None):
    """ Factory function to return appropriate imageObject class instance"""
    # extract primary header and SCI,1 header from input image
    sci_ext = 'SCI'
    if group in [None, '']:
        exten = '[sci,1]'
        phdu = fits.getheader(input, memmap=False)
    else:
        # change to use fits more directly here?
        if group.find(',') > 0:
            grp = group.split(',')
            if grp[0].isalpha():
                grp = (grp[0], int(grp[1]))
            else:
                grp = int(grp[0])
        else:
            grp = int(group)
        phdu = fits.getheader(input, memmap=False)
        phdu.extend(fits.getheader(input, ext=grp, memmap=False))

    # Extract the instrument name for the data that is being processed by Multidrizzle
    _instrument = phdu['INSTRUME']

    # Determine the instrument detector in use.  NICMOS is a special case because it does
    # not use the 'DETECTOR' keyword.  It instead used 'CAMERA' to identify which of it's
    # 3 camera's is in use.  All other instruments support the 'DETECTOR' keyword.
    if _instrument == 'NICMOS':
        _detector = phdu['CAMERA']
    else:
        try:
            _detector = phdu['DETECTOR']
        except KeyError:
            # using the phdu as set above (fits.getheader) is MUCH faster and
            # works for the majority of data; but fileutil handles waivered fits
            phdu = fileutil.getHeader(input + exten)
            _detector = phdu['DETECTOR']  # if this fails, let it throw

    del phdu  # just to keep clean
    # Match up the instrument and detector with the right class
    # only importing the instrument modules as needed.
    try:
        if _instrument == 'ACS':
            from . import acsData
            if _detector == 'HRC':
                return acsData.HRCInputImage(input, output=output, group=group)
            if _detector == 'WFC':
                return acsData.WFCInputImage(input, output=output, group=group)
            if _detector == 'SBC':
                return acsData.SBCInputImage(input, output=output, group=group)
        if _instrument == 'NICMOS':
            from . import nicmosData
            if _detector == 1:
                return nicmosData.NIC1InputImage(input, output=output)
            if _detector == 2:
                return nicmosData.NIC2InputImage(input, output=output)
            if _detector == 3:
                return nicmosData.NIC3InputImage(input, output=output)

        if _instrument == 'WFPC2':
            from . import wfpc2Data
            return wfpc2Data.WFPC2InputImage(input, output=output, group=group)
        """
            if _detector == 1: return wfpc2Data.PCInputImage(input)
            if _detector == 2: return wfpc2Data.WF2InputImage(input)
            if _detector == 3: return wfpc2Data.WF3InputImage(input)
            if _detector == 4: return wfpc2Data.WF4InputImage(input)
        """
        if _instrument == 'STIS':
            from . import stisData
            if _detector == 'CCD':
                return stisData.CCDInputImage(input,
                                              output=output,
                                              group=group)
            if _detector == 'FUV-MAMA':
                return stisData.FUVInputImage(input,
                                              output=output,
                                              group=group)
            if _detector == 'NUV-MAMA':
                return stisData.NUVInputImage(input,
                                              output=output,
                                              group=group)
        if _instrument == 'WFC3':
            from . import wfc3Data
            if _detector == 'UVIS':
                return wfc3Data.WFC3UVISInputImage(input,
                                                   output=output,
                                                   group=group)
            if _detector == 'IR':
                return wfc3Data.WFC3IRInputImage(input,
                                                 output=output,
                                                 group=group)

    except ImportError:
        msg = 'No module implemented for ' + str(_instrument) + '!'
        raise ValueError(msg)
    # If a supported instrument is not detected, print the following error message
    # and raise an exception.
    msg = 'Instrument: ' + str(_instrument) + '/' + str(
        _detector) + ' not yet supported!'
    raise ValueError(msg)
Exemple #9
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
Exemple #10
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