Source code for drizzlepac.updatenpol

#!/usr/bin/env python

# $Id: updatenpol.py 8609 2010-01-19 16:22:48Z hack $

"""
`updatenpol`: Update the header of ACS file(s) with the names of new
``NPOLFILE`` and ``D2IMFILE`` reference files for use with the
C version of MultiDrizzle (astrodrizzle).

:Authors: Warren Hack

:License: :doc:`LICENSE`


:Usage:
    This task can be run from the operating system command line with::

        updatenpol [options] input [refdir]

:Command-line Options:
    `input`
        The specification of the files to be updated, either as a single filename,
        an ASN table name, or wild-card specification
        of a list of files.
    `refdir`
        The name of the directory containing all the new reference files
        (``*_npl.fits`` and ``*_d2i.fits`` files).
        If no directory is given, it will look in `jref$` by default.

    ``-h``
        Print the help (this text).

    ``-l``
        If specified, copy NPOLFILEs and D2IMFILEs to local directory
        for use with the input files.

    ``-i``
        If specified, the program will interactively request the exact
        names of the ``NPOLFILE`` and ``D2IMFILE`` reference files to be used
        for updating the header of each file. The value of 'refdir'
        will be ignored in interactive mode.


.. warning:: It will ask for the names of the ``NPOLFILE`` and ``D2IMFILE`` for
             EACH separate INPUT file when the option `-i` has been specified.

:Example:
    1. This command will update all the FLT files in the current directory
    with the new ``NPOLFILE`` and ``D2IMFILE`` reference files found in the 'myjref'
    directory as defined in the environment::

        updatenpol *flt.fits myjref$


:Compatability with MultiDrizzle:
    The new version of ``MultiDrizzle`` (``AstroDrizzle``) and `updatewcs`
    only work with the new ``NPOLFILE`` reference file for the ``DGEO`` correction
    (to replace the use of DGEOFILE).
    In fact, ``AstroDrizzle`` has been extensively modified to
    prompt the user with a very lengthy explanation on whether it should
    stop and allow the user to update the header or continue without
    applying the ``DGEO`` correction under circumstances when the ``NPOLFILE``
    keyword can not be found for ACS.

"""
__docformat__ = 'restructuredtext'

__taskname__ = "updatenpol"

# This is specifically NOT intended to match the package-wide version information.
__version__ = '1.1.0'
__version_date__ = '16-Aug-2011'

import os,sys,shutil

from astropy.io import fits
from stsci.tools import fileutil as fu
from stsci.tools import parseinput
from stsci.tools import teal

from stwcs import updatewcs
from . import util


[docs]def update(input,refdir="jref$",local=None,interactive=False,wcsupdate=True): """ Updates headers of files given as input to point to the new reference files NPOLFILE and D2IMFILE required with the new C version of MultiDrizzle. Parameters ----------- input : string or list Name of input file or files acceptable forms: - single filename with or without directory - @-file - association table - python list of filenames - wildcard specification of filenames refdir : string Path to directory containing new reference files, either environment variable or full path. local : boolean Specifies whether or not to copy new reference files to local directory for use with the input files. interactive : boolean Specifies whether or not to interactively ask the user for the exact names of the new reference files instead of automatically searching a directory for them. updatewcs : boolean Specifies whether or not to update the WCS information in this file to use the new reference files. Examples -------- 1. A set of associated images specified by an ASN file can be updated to use the NPOLFILEs and D2IMFILE found in the local directory defined using the `myjref$` environment variable under PyRAF using:: >>>import updatenpol >>>updatenpol.update('j8bt06010_asn.fits', 'myref$') 2. Another use under Python would be to feed it a specific list of files to be updated using:: >>> updatenpol.update(['file1_flt.fits','file2_flt.fits'],'myjref$') 3. Files in another directory can also be processed using:: >>> updatenpol.update('data$*flt.fits','../new/ref/') Notes ----- .. warning:: This program requires access to the `jref$` directory in order to evaluate the DGEOFILE specified in the input image header. This evaluation allows the program to get the information it needs to identify the correct NPOLFILE. The use of this program now requires that a directory be set up with all the new NPOLFILE and D2IMFILE reference files for ACS (a single directory for all files for all ACS detectors will be fine, much like jref). Currently, all the files generated by the ACS team has initially been made available at:: /grp/hst/acs/lucas/new-npl/ The one known limitation to how this program works comes from confusion if more than 1 file could possibly be used as the new reference file. This would only happen when NPOLFILE reference files have been checked into CDBS multiple times, and there are several versions that apply to the same detector/filter combination. However, that can be sorted out later if we get into that situation at all. """ print('UPDATENPOL Version',__version__+'('+__version_date__+')') # expand (as needed) the list of input files files,fcol = parseinput.parseinput(input) if not interactive: # expand reference directory name (if necessary) to # interpret IRAF or environment variable names rdir = fu.osfn(refdir) ngeofiles,ngcol = parseinput.parseinput(os.path.join(rdir,'*npl.fits')) # Find D2IMFILE in refdir for updating input file header as well d2ifiles,d2col = parseinput.parseinput(os.path.join(rdir,"*d2i.fits")) # Now, build a matched list of input files and DGEOFILE reference files # to use for selecting the appropriate new reference file from the # refdir directory. for f in files: print('Updating: ',f) fdir = os.path.split(f)[0] # Open each file... fimg = fits.open(f, mode='update', memmap=False) phdr = fimg['PRIMARY'].header fdet = phdr['detector'] # get header of DGEOFILE dfile = phdr.get('DGEOFILE','') if dfile in ['N/A','',' ',None]: npolname = '' else: dhdr = fits.getheader(fu.osfn(dfile), memmap=False) if not interactive: # search all new NPOLFILEs for one that matches current DGEOFILE config npol = find_npolfile(ngeofiles,fdet,[phdr['filter1'],phdr['filter2']]) else: if sys.version_info[0] >= 3: npol = input("Enter name of NPOLFILE for %s:"%f) else: npol = raw_input("Enter name of NPOLFILE for %s:"%f) if npol == "": npol = None if npol is None: errstr = "No valid NPOLFILE found in "+rdir+" for detector="+fdet+"\n" errstr += " filters = "+phdr['filter1']+","+phdr['filter2'] raise ValueError(errstr) npolname = os.path.split(npol)[1] if local: npolname = os.path.join(fdir,npolname) # clobber any previous copies of this reference file if os.path.exists(npolname): os.remove(npolname) shutil.copy(npol,npolname) else: if '$' in refdir: npolname = refdir+npolname else: npolname = os.path.join(refdir,npolname) phdr.set('NPOLFILE', value=npolname, comment="Non-polynomial corrections in Paper IV LUT", after='DGEOFILE') # Now find correct D2IFILE if not interactive: d2i = find_d2ifile(d2ifiles,fdet) else: if sys.version_info[0] >= 3: d2i = input("Enter name of D2IMFILE for %s:"%f) else: d2i = raw_input("Enter name of D2IMFILE for %s:"%f) if d2i == "": d2i = None if d2i is None: print('=============\nWARNING:') print(" No valid D2IMFILE found in "+rdir+" for detector ="+fdet) print(" D2IMFILE correction will not be applied.") print('=============\n') d2iname = "" else: d2iname = os.path.split(d2i)[1] if local: # Copy D2IMFILE to local data directory alongside input file as well d2iname = os.path.join(fdir,d2iname) # clobber any previous copies of this reference file if os.path.exists(d2iname): os.remove(d2iname) shutil.copy(d2i,d2iname) else: if '$' in refdir: d2iname = refdir+d2iname else: d2iname = os.path.join(refdir,d2iname) phdr.set('D2IMFILE', value=d2iname, comment="Column correction table", after='DGEOFILE') # Close this input file header and go on to the next fimg.close() if wcsupdate: updatewcs.updatewcs(f)
[docs]def find_d2ifile(flist,detector): """ Search a list of files for one that matches the detector specified. """ d2ifile = None for f in flist: fdet = fits.getval(f, 'detector', memmap=False) if fdet == detector: d2ifile = f return d2ifile
[docs]def find_npolfile(flist,detector,filters): """ Search a list of files for one that matches the configuration of detector and filters used. """ npolfile = None for f in flist: fdet = fits.getval(f, 'detector', memmap=False) if fdet == detector: filt1 = fits.getval(f, 'filter1', memmap=False) filt2 = fits.getval(f, 'filter2', memmap=False) fdate = fits.getval(f, 'date', memmap=False) if filt1 == 'ANY' or \ (filt1 == filters[0] and filt2 == filters[1]): npolfile = f return npolfile
# #### Interfaces used by TEAL #
[docs]def run(configobj=None,editpars=False): """ Teal interface for running this code. """ if configobj is None: configobj =teal.teal(__taskname__,loadOnly=(not editpars)) update(configobj['input'],configobj['refdir'], local=configobj['local'],interactive=configobj['interactive'], wcsupdate=configobj['wcsupdate'])
def main(): import getopt try: optlist, args = getopt.getopt(sys.argv[1:], 'hli') except getopt.error as e: print(str(e)) print(__doc__) print("\t", __version__) # initialize default values help = 0 local = False interactive = False # read options for opt, value in optlist: if opt == "-h": help = 1 if opt == "-l": local = True if opt == "-i": interactive = True if len(args) < 2: args.append('jref$') if (help): print(__doc__) print("\t", __version__+'('+__version_date__+')') else: update(args[:-1],args[-1],local=local,interactive=interactive) if __name__ == "__main__": main() """ Copyright (C) 2003 Association of Universities for Research in Astronomy (AURA) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of AURA and its representatives may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """
[docs]def help(file=None): """ Print out syntax help for running astrodrizzle Parameters ---------- file : str (Default = None) If given, write out help to the filename specified by this parameter Any previously existing file with this name will be deleted before writing out the help. """ helpstr = getHelpAsString(docstring=True, show_ver = True) if file is None: print(helpstr) else: if os.path.exists(file): os.remove(file) f = open(file, mode = 'w') f.write(helpstr) f.close()
[docs]def getHelpAsString(docstring = False, show_ver = True): """ return useful help from a file in the script directory called __taskname__.help """ install_dir = os.path.dirname(__file__) taskname = util.base_taskname(__taskname__, '') htmlfile = os.path.join(install_dir, 'htmlhelp', taskname + '.html') helpfile = os.path.join(install_dir, taskname + '.help') if docstring or (not docstring and not os.path.exists(htmlfile)): if show_ver: helpString = os.linesep + \ ' '.join([__taskname__, 'Version', __version__, ' updated on ', __version_date__]) + 2*os.linesep else: helpString = '' if os.path.exists(helpfile): helpString += teal.getHelpFileAsString(taskname, __file__) else: if __doc__ is not None: helpString += __doc__ + os.linesep else: helpString = 'file://' + htmlfile return helpString