Source code for reduce.calCombineFF

#! /usr/bin/env python
# Copyright (c) 2009-2012 IAA-CSIC  - All rights reserved. 
# Author: Jose M. Ibanez. 
# Instituto de Astrofisica de Andalucia, IAA-CSIC
#
# This file is part of PAPI (PANIC Pipeline)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


################################################################################
#
#
# PAPI (PANIC PIpeline)
#
# calCombineFF.py
#
# Created    : 29/03/2012    jmiguel@iaa.es -
# Last update: #! /usr/bin/env python
################################################################################
"""
A trick to combine domeFF and skyFF :

Often for a run you have dome flats with an accumulated number of
electrons in the millions, but a poor match in illumination and color to the dark
sky. You also have a limited number of twilight flats or dark-sky images that can
be combined to make a dark-sky flat, but the total counts per pixel in either set of
flats is not very high. A fairly standard procedure is to 'median-smooth' dome
and twilight or dark-sky flat. A median smoothing replaces each pixel with the
median of the pixel values in a box of a given size on a side. The result is an 
image that has been smoothed on the scale of the smoothing box size.
A procedure for taking advantage of the facts that the large-scale flat-field
variation of the dark-sky flat match that of the program frames and the dome 
flats have very high S/N in each pixel goes as follows:
 
(a) Median smooth the combined, dark-sky flat -this improves the S/N and
preserves the large-scale features of the flat.

(b) Median smooth the combined dome flats using the same filter size as was
used for the dark-sky flat.

(c) Divide the combined dome flat by it's median smoothed-version. The result is
a frame that is flat on large scales but contains all the high spatial frequency
flat-field information.

(d) Now multiply the smoothed dark-sky frame and the result of the division in
the previous step. You now have a flat-field with the low spatial frequency
properties of the dark-sky flat combined with the high S/N, high spatial
frequency properties of the dome flat.
"""

# Import necessary modules
from optparse import OptionParser
import sys
import astropy.io.fits as fits

# PAPI
from papi.misc.paLog import log
from papi.misc.fileUtils import removefiles
from papi.datahandler.clfits import isaFITS
from papi.misc.version import __version__


# IRAF
from pyraf import iraf
from iraf import noao
from iraf import mscred


[docs]def combineFF(domeFF, skyFF, combinedFF=None): """ Combine a dome FF and a sky FF in order to have a FF with the low frequency proporties of the dark-sky flat combined with the high S/N, high spatial frequency properties of the dome FF. Basically: skyFF' = smooth(skyFF) domeFF' = smooth(domeFF) domeFF'' = domeFF / domeFF' combFF = skyFF' * domeFF'' Parameters ---------- domeFF : str Input filename of dome FF skyFF : str Input filename of the sky FF combinedFF: str Output filename of the combined FF generated Returns ------- If all was successful, the name of the output file is returned """ if not isaFITS(domeFF) or not isaFITS(skyFF): log.error("Some input FF is not a FITS file") raise Exception("Some input FF is not a FITS file") try: #smooth the domeFF log.debug("Doing Median smooth of domeFF ...") removefiles(domeFF.replace(".fits", "_smooth.fits")) iraf.mscmedian( input=domeFF, output=domeFF.replace(".fits", "_smooth.fits"), xwindow=20, ywindow=20, outtype="median", fmedian='no', zloreject=0.2, zhireject=2.0) # Or using scipy ( a bit slower then iraf...) # from scipy import ndimage # filtered = ndimage.gaussian_filter(f[0].data, 20) # smooth the skyFF log.debug("Doing Median smooth of skyFF ...") removefiles(skyFF.replace(".fits", "_smooth.fits")) iraf.mscmedian( input=skyFF, output=skyFF.replace(".fits", "_smooth.fits"), xwindow=20, ywindow=20, outtype="median", fmedian='no', zloreject=0.2, zhireject=2.0 ) # Divide domeFF by smoothed version removefiles(domeFF.replace(".fits", "_div_smooth.fits")) iraf.mscarith(operand1=domeFF, operand2=domeFF.replace(".fits", "_smooth.fits"), op='/', pixtype='real', result=domeFF.replace(".fits", "_div_smooth.fits"), ) # Combine skyFF with domeFF removefiles(combinedFF) iraf.mscarith(operand1=skyFF.replace(".fits", "_smooth.fits"), operand2=domeFF.replace(".fits", "_div_smooth.fits"), op='*', pixtype='real', result=combinedFF, ) fits.setval(combinedFF, keyword="PAPIVERS", value=__version__, comment="PANIC Pipeline version") # Remove all temporal removefiles(domeFF.replace(".fits", "_smooth.fits")) removefiles(skyFF.replace(".fits", "_smooth.fits")) removefiles(domeFF.replace(".fits", "_div_smooth.fits")) except Exception as e: raise e log.info("Combined Flat-Field created : %s", combinedFF) return combinedFF
# main if __name__ == "__main__": description = \ "Module to combine a dome Flat-field and a sky Flat-field. " parser = OptionParser(description = description, #formatter = wider_format, usage = "usage: %prog [options]", version = "%prog 1.x") parser.add_option("-d", "--domeFF", action="store", dest="domeFF", help="input dome Flat-Field ") parser.add_option("-s", "--skyFF", action="store", dest="skyFF", help="input sky Flat-Field ") parser.add_option("-o", "--output", action="store", dest="output_image", help="output filename of combined Flat-Field (default = %default)", default="combinedFF.fits") (options, args) = parser.parse_args() if len(sys.argv[1:])<1: parser.print_help() sys.exit(0) if not options.domeFF or not options.skyFF or len(args) != 0: # args is the leftover positional arguments after all options have been # processed parser.print_help() parser.error("wrong number of arguments ") if not options.output_image: options.output_image = None try: combineFF(options.domeFF, options.skyFF, options.output_image) except Exception as e: log.error("Fail of combineFF procedure") raise e print("\nWell done !")