combDither (version 1.34)
index
/acs/science/pipeline/lib/python/apsis/combDither.py

# $Id: combDither.py,v 1.34 2003/04/02 15:20:46 jpb Exp $
# ---------------------------------------------------------------------
# $Log: combDither.py,v $
# Revision 1.34  2003/04/02 15:20:46  jpb
# Updates to doc string.
#
# Revision 1.33  2003/03/25 14:13:38  jpb
# Added 'nopad' option, to make output images slightly smaller.
#
# Revision 1.32  2003/03/07 14:51:23  jpb
# Fix a bug in new _get_refAsn() method for choosing reference association.
#
# Revision 1.31  2003/03/05 20:08:17  jpb
# Added a method for choosing the association with the largest range of
# shifts as the reference for defining the output image size.
#
# Revision 1.30  2003/02/26 16:01:02  anderson
# made Lanczos3 kernel the default kernel for the final drizzle task.
#
# Revision 1.29  2003/02/12 16:26:21  anderson
# updated messaging for Bugzilla bug #2245 - Markup drizzle parameters...
# drizzle configuration pars now appear in the module message.
# Also, updated parsing of file names due to Grouper naming patterns in
# the making flag and rms images.
#
# Revision 1.28  2003/02/10 19:14:34  anderson
# fixes Bugzilla bug # 2245 - Markup drizzle parameters in combdither message
#
# Revision 1.27  2003/01/31 17:03:31  jpb
# Added call to and handling of augmask.py, for making the edge mask.
#
# Revision 1.26  2002/12/13 16:20:31  jpb
# Added a 'noRej' flag to run_All, to allow the pipeline to skip the
# CR rejection.
#
# Revision 1.25  2002/11/26 14:22:14  jpb
# Added the 'kernel' option to allow setting of drizzle.kernel.
#
# Revision 1.24  2002/11/21 18:30:33  jpb
# Modified to send the logfile to pyblot.
#
# Revision 1.23  2002/11/19 22:25:40  jpb
# Decreased the size of the output padding factors (_padx,_pady) by 1%.
#
# Revision 1.22  2002/09/20 16:58:57  jpb
# Modification to increase output image size to accommodate relative rotations.
#
# Revision 1.21  2002/09/10 16:32:47  jpb
# Long awaited fix to CD matrices in drizzled images; also ensure that
# all the WCS information is the same for all images.  The new _makeWCS()
# function assembles the information into a 'wcstuples' list which is
# sent as the new optional 'addCards' parameter to fixDrzHeader for all
# the drizzled images, thus ensuring consistency.  The CD matrix is
# calculated by matutil.targroll/matutil.makeCDdict.
#
# Revision 1.20  2002/08/20 20:22:45  anderson
# Revision to add some robustness to the call to fixDrzHeader in the
# event that pyfits/numarray are not well-behaved (which happens often).
# A try/except clause now only _tries_ to fix the header if it can.
# If it cannot, chances are pyfits/numarray are the problem.
#
# Revision 1.19  2002/07/26 13:50:11  jpb
# Added inNsci=NumSci in pyblot call; cleaned up the run_drizzle code a bit;
# make it use all images for calculating the zeropoint (center) of the shifts,
# not just images in the first association; fixed spurious problem with
# exposure times from pydrizzle by explicitly deleting the 'exptime' attribute
# of the skyField object before creating the new pydrizzle object (this was
# a tough bug to track down).
#
# Revision 1.18  2002/07/23 21:11:20  jpb
# Made run_drizzle delete the individual weight images immediately after
# the first pass drizzling, since they're not used for anything.
#
# Revision 1.17  2002/07/16 17:23:19  jpb
# Fixed the 'texptime' value in the pydrizzle parlist for the case of
# separDriz = 1 (i.e., the first pass drizzling).  The newest pydrizzle
# uses the texptime to correct the drizzle exposure time value, and the
# values in the pydrizzle parlist were not appropriate when drizzling
# to separate output images.
#
# Revision 1.16  2002/07/09 22:41:32  jpb
# Aded the run_drizzle/run_all flags 'asecpix' and 'pixfrac' which get
# sent to pydrizzle/drizzle for changing output pixel scale and the
# drizzle dropsize parameter.
#
# Revision 1.15  2002/06/27 20:30:36  anderson
# update to include pyfits and numarray in the
# module message markup.
#
# Revision 1.14  2002/06/25 21:25:28  anderson
# Revision addresses Bugzilla bug #1411
# - Discontinue use of '&' (ampersand) character
#
# Revision 1.13  2002/06/20 21:07:43  anderson
# Revision to provide consistent filenames in messages with relative
# pathnames from the path described in the <root> element of each
# module message.  This was an update to this module's mkMsg method.
#
# Revision 1.12  2002/06/19 19:01:01  anderson
# removed the import pydrizzle26 as pydrizzle as this was
# breaking the import cycle due to cyclic import within
# pydrizzle. eg.,
#
# __init__:
# import drutil
#
# drutil.py:
# import pydrizzle
#
# This really ought to be reported as deprecated behaviour
#
# Revision 1.11  2002/06/18 22:37:08  jpb
# Added the post-drizzle exposure time fix for Numsci > 1 back in for
# the weight and context images.  Only the sci image exposure time is
# corrected by the new pydrizzle.
#
# Revision 1.10  2002/06/16 01:04:05  jpb
# Made the run_all method transmit the "clean_up" flag to pyblot.blotter.
#
# Revision 1.9  2002/06/13 23:22:16  jpb
# Fixed a typo in deleting the "EXTEND" card of the FLAG image header.
#
# Revision 1.8  2002/06/13 23:06:45  anderson
# added a try/except clause around the deletion of the EXTEND
# ascard which the current pyfits now creates.  Just in case that
# behaviour ever changes.
#
# Revision 1.7  2002/06/12 19:02:49  jpb
# Several changes:  (1) move to the latest (version 2.6) pydrizzle release;
# (2) move from Numeric/fits to numarray/pyfits, which mainly affects the
# makeRmsImage and makeFlagImage methods; (3) make it correctly get the
# drizzle version by calling drizzle with dummy input/output before
# constructor and trapping the STDOUT; (4) FLAG image now made from the
# drizzled weight image, rather than context image, since the latter
# becomes 3-d if there are more than 32 input arrays (16 WFC images).
# I've also update the lengthy drizzleImage class docstring to reflect
# the recent changes.
#
# Revision 1.6  2002/06/10 21:38:23  jpb
# Upgrade to use pydrizzle 2.5!  Also, delete makeAsn and _computeDeltaShifts
# methods; the code now just uses the original association tables.
#
# Revision 1.5  2002/06/06 17:57:48  anderson
# Revision to fix Bugzilla issues:
# # 1333 - Remove invalid or redundant keywords
# # 1352 - include medriz_?.fits files in messages
#
# Revision 1.4  2002/05/21 22:05:48  anderson
# various fixes adressing a bug in align
# - initialisation of self.sci dictionaries.
# - fix to bug # 1303: MIME type correction in
#   combDither
# - fix to bug # 1298: ingest message error in
#   asn input files.
#
# Revision 1.3  2002/05/16 18:46:12  anderson
# Bringing all apsis modules to a common rev level.
# K Anderson
#
# Revision 1.1.1.1  2002/05/03 17:39:34  anderson
# initial revision and release of the ACS Science pipeline, apsis
#
# ---------------------------------------------------------------------
# jpb changes, starting 10-10-01
#  - fixes the size of the output image to be same in all filters
#  - modifies shifts across filters to make sure images are aligned
#  - the latter modification requires access to the MatchDict produced
#      by align, so now we send it to the constructor
#
#  - recent changes include cosmic-ray rejection with pyblot
#      and updating ALIGNSKY values in image headers.
#  - now also makes RMS image for sextractor
#

 
Modules
            
augmask
fUtil
glob
math
matutil
numarray
numinclude
os
pyblot
pydrizzle
pyfits
string
xmlUtil
 
Classes
            
drizzleImage
 
class drizzleImage
      Some notes on the combDither module and its implementation of pydrizzle.
 
combDither currently contains one class, drizzleImage, which defines
methods for drizzling dithered image associations to a final images,
including cosmic ray rejection, etc.  The original intention was to
create other classes with methods for combining the images using other
routines (e.g., SWARP, or something based on python numerical arrays).
 
The basic procedure for processing a dataset through drizzle:
 
    drob = drizzleImage(obs,al.MatchDict) - create instance of this class
    drob.run_all()          -   run the drizzle/blot/drizzle sequence
    drob.makeFlagImage()    -   create Sextractor flag image for each asn
    drob.makeRmsImage()     -   create Sextractor rms image for each asn
 
Alternatively, the user can replace run_all() with run_drizzle() if no
cosmic ray rejection is desired.  This module no longer makes its own
association tables, but just uses the original ones that are given as
inputs to the pipeline.
 
The run_all method does three things:
 
    1. run_drizzle() drizzles images onto separate output images
    2. runs pyblot (median stacks, blots, derivs, cr_rej) which
        returns the list of cr masks for 2nd drizzling
    3. run_drizzle() to drizzles images all together using CR masks
        from pyblot
 
run_drizzle() is the heart of the drizzleImage class.  It runs pydrizzle
on all of the association tables in the asnTableList and takes a number
of optional parameters (outshape=None, deltmp=1, units='counts',
bits=_goodBits_, separDriz=0, crmasks=None, exptimePyDrKludge=0).
Here's what the params are for
 
     outshape:  x,y sizes of output drizzled image (def: determined 'otf')
     deltmp:    delete temporary (masks, coeffs) files? (def: 1 [yes])
     units:     units of output pixel values (def: counts)
     bits:      sum of all possible good-pixel values in dq array
                  ('None' means don't use masks).
                  The default value bits=8450 is the sum of the pix values
                  that we accept as being good, bits = 0+2+256+8192 = 8450,
                  which includes 'good', 'replaced', 'saturated',and
                  'CR-repaired', but NOTE THAT THESE VALUES ARE PARTICULAR 
                  TO CALACS! [ISR ACS-99-03]
 
     The remainder of the params relate to pyblot setup and results:
     crmasks:            List of (mask,nzap) tuples from pyblot
     separDriz:          Drizzle onto separate output images?
 
run_drizzle loops over all associations and runs pydrizzle on them.  
It measures the shift 'zeropoint' based on the mean of all the measured
shifts and then sets the relative shifts accordingly, ensuring that all
associations will have the same absolute shift zeropoint, as well as the
same image size.  This *seems* to be ok, although the output WCS may then
disagree with pydrizzle's idea of the WCS of the output product, but drizzle
itself constructs the WCS image in the output product from the input and
whatever image headers it gets.
 
For each association, run_drizzle creates the pydrizzle object, then
goes through the parlist (list of dictionaries holding input drizzle
parameters).  It modifies these parlists in various way, e.g., it makes
the output images different if 'separDriz' has been set.  It also sets
the x,y shifts and rotations to whatever is in the MatchDict (thus,
making delta shifts in the asn tables no longer necessary).  The list of
modified parlists is saved as a class attribute.  It then runs drizzle.
 
After the 2nd drizzle (separdriz = 0), the code checks if:
(1) the number of science extensions in the multi-extension FITS (mef)
file is greater than 1 and units='counts' (the default); if so, it
divides the count levels by the number of extensions.
(2) if the pydrizzle version is less than 1.4; if so and Nsci>1, then it
divides the output exposure times by the number of science extensions.
 
If it's the final drizzle, then it also goes through all the input images
and sums the alignSky values in the headers and writes the sum to the
science image header.  That's it.  The makeFlagImage and makeRmsImage
methods are pretty straightforward.
 
The drizzle kernel, for the *final drizzle only* can now be set when
run_drizzle or run_all is called. The drizzle-default linear ('square')
kernel is the fastest, and tends to smooth over bad pixels better,
but the psf is not as tight and the noise correlation is much worse.
 
The damped sinc interpolant ('lanczos3') is sometimes called the
optimal kernel, though beware that you may get holes (negative
pixels) in the output.  These holes can happen anywhere, though more
commonly near stars, etc.  Because of the masking of bad pixels and
columns (based on the DQ array), occasionally a pixel in the output
image will have very little data from the input image, and by a
quirk of the interpolation kernel with its negative sidelobes, will
end up with a negative value.  Richard Hook said to check the
drizzle weight image to make sure that those negative pixels are
given very little weight; if they have low weight, just don't use
them, but if their weight is high, then there might be a problem.
I checked several of these pixels, and found they were given low
weight, about 1/10 of the median, so it seems ok.  Of course, if
there are multiple dithered images, these negative pixels get filled
in quickly by other pixels with much higher weight.  For the linear
kernel you don't get this effect because there are no negative
sidelobes.
 
One caveat: run_drizzle overwrites shifts, rotations, and output product
names in the pydrizzle parlist rather than setting them through methods.
This was historically necessary for the shifts (and *still* the most
straightforward way), and it's still necessary for drizzling onto
separate outputs for blotting.  So, I wouldn't recommend changing it,
but we have to be careful in case later pydrizzles change the parlist
elements or their meanings.
 
   Methods defined here:
__init__(self, obs, MatchDict, alignSky='ALIGNSKY', hdrGain=0, suppInstVar=1, crlower=None, notrim=0, nopad=0)
_clean_driz(self)
_get_refAsn(self)
choose the reference association for the output image size
_makeWCS(self, template=None)
 Make a list of tuples containing all the WCS and closely
related info to be written to each output image header.
_rotateRect(self, _maxAng, nx, ny)
 rotate a rectangle and return ratio of new x,y sizes to old
_sumSubSkyNcombine(self, parlist, doSky)
 Sum the sky values in the input images and put the
total in the output drizzled image header.
help(self)
makeFlagImage(self)
turns the weight images produced by drizzle into flag images that
SExtractor will use.
makeRmsImage(self)
turns the drizzled weight images into RMS images that
SExtractor will use.
mkMsg(self)
create and write module level message for this class.
Most of this is just compiling the info. meta in a dictionary
of lists where each list is a list of tuples describing the
tag lines for the particular section of the message.  This tuple 
format conforms to that used by the xmlMessage class which is
modeled on basic python argument passing, i.e. (key,*value,**attr).
printParlist(self, parlist)
 takes a PyDrizzle parlist and prints out the contents
run_all(self, clean_up=1, units='counts', asecpix=None, pixfrac=None, kernel=None, noRej=None)
 Run_all()
This is it, the whole enchilada: drizzle, blot, drizzle again.
run_drizzle(self, outshape=None, deltmp=1, units='counts', bits=8578, separDriz=0, crmasks=None, asecpix=None, pixfrac=None, kernel='square', delwght=0)
 run_drizzle():
Run drizzle on all asn tables in the obsAsnDict.keys()
   Input parameters (all optional) include:
     outshape: x,y sizes of output drizzled image (def: determined 'otf')
     deltmp:   delete temporary (masks, coeffs) files (def: 1 [yes])
     units:    units of output pixel values (def: counts)
     bits:     sum of possible good-pixel values in dq array (None => don't use masks).
               The default bits=8578 is the sum of the pix values that we accept
               as being good, bits = 0+2+256+8192+128 = 8578, which includes
               'good', 'replaced', 'saturated', 'CR-repaired' and 'bias-level pixel' but
               NOTE THAT THESE VALUES ARE PARTICULAR TO CALACS! [ISR ACS-99-03]
     The remainder of the params relate to pyblot setup and results:
     crmasks:      List of masks from pyblot
     separDriz:    Drizzle onto separate output images
     asecpix:      Scale in arsec/pix of final drizzled images.
     pixfrac:      Drizzle 'pixfrac' or 'dropsize' parameter.
     kernel:       interpolation kernel used by drizzle.
writeXml(self)
mark up products as xml.

Data and non-method functions defined here:
__doc__ = 'Some notes on the combDither module and its imp...parlist\n elements or their meanings.\n\n '
__module__ = 'combDither'
 
Data
             __author__ = 'J Blakeslee '
__file__ = '/acs/science/pipeline/lib/python/apsis/combDither.pyc'
__ii = 5
__name__ = 'combDither'
__version__ = '1.34'
__version_date__ = '2003/04/02 15:20:46'
_exVarPerSec_ = 0.02222
_goodBits_ = 8578
_rnVarSuppFac_ = 1.3799999999999999
drversion = '2.9'
iraf = <module 'pyraf.iraf' from '/usr/local/lib/python2.2/site-packages/pyraf/iraf.pyc'>
pydriz_version = '2.6.1 (11-Feb-2003)'
pyversion = '2.2 (#2, Feb 6 2002, 17:02:39) \n[GCC 2.96 20000731 (Red Hat Linux 7.1 2.96-98)]'
version = '2.2 (#2, Feb 6 2002, 17:02:39) \n[GCC 2.96 20000731 (Red Hat Linux 7.1 2.96-98)]'
 
Author
             J Blakeslee <jpb@pha.jhu.edu>