uves_flatfield.c

00001 /*                                                                              *
00002  *   This file is part of the ESO UVES Pipeline                                 *
00003  *   Copyright (C) 2004,2005 European Southern Observatory                      *
00004  *                                                                              *
00005  *   This library is free software; you can redistribute it and/or modify       *
00006  *   it under the terms of the GNU General Public License as published by       *
00007  *   the Free Software Foundation; either version 2 of the License, or          *
00008  *   (at your option) any later version.                                        *
00009  *                                                                              *
00010  *   This program is distributed in the hope that it will be useful,            *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of             *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
00013  *   GNU General Public License for more details.                               *
00014  *                                                                              *
00015  *   You should have received a copy of the GNU General Public License          *
00016  *   along with this program; if not, write to the Free Software                *
00017  *   Foundation, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA       *
00018  *                                                                              */
00019 
00020 /*
00021  * $Author: amodigli $
00022  * $Date: 2007/06/06 08:17:33 $
00023  * $Revision: 1.26 $
00024  * $Name: uves-3_3_1 $
00025  * $Log: uves_flatfield.c,v $
00026  * Revision 1.26  2007/06/06 08:17:33  amodigli
00027  * replace tab with 4 spaces
00028  *
00029  * Revision 1.25  2007/05/24 13:07:46  jmlarsen
00030  * Fail if the provided flat-field has unreasonable (zero, nan or inf) mean value
00031  *
00032  * Revision 1.24  2007/05/22 11:36:37  jmlarsen
00033  * Removed MIDAS flag for good
00034  *
00035  * Revision 1.23  2006/11/15 15:02:14  jmlarsen
00036  * Implemented const safe workarounds for CPL functions
00037  *
00038  * Revision 1.21  2006/11/15 14:04:08  jmlarsen
00039  * Removed non-const version of parameterlist_get_first/last/next which is already
00040  * in CPL, added const-safe wrapper, unwrapper and deallocator functions
00041  *
00042  * Revision 1.20  2006/11/13 14:23:55  jmlarsen
00043  * Removed workarounds for CPL const bugs
00044  *
00045  * Revision 1.19  2006/11/06 15:19:41  jmlarsen
00046  * Removed unused include directives
00047  *
00048  * Revision 1.18  2006/08/17 13:56:53  jmlarsen
00049  * Reduced max line length
00050  *
00051  * Revision 1.17  2006/08/17 09:16:40  jmlarsen
00052  * Removed CPL2 code
00053  *
00054  * Revision 1.16  2006/08/10 10:49:57  jmlarsen
00055  * Removed workaround for cpl_image_get_bpm
00056  *
00057  * Revision 1.15  2006/06/16 08:23:31  jmlarsen
00058  * Changed 0 -> false
00059  *
00060  * Revision 1.14  2006/04/24 09:20:12  jmlarsen
00061  * Always use the MIDAS normalization
00062  *
00063  * Revision 1.13  2006/03/24 14:16:43  jmlarsen
00064  * Changed order of for loops for efficiency
00065  *
00066  * Revision 1.12  2006/03/03 13:54:11  jmlarsen
00067  * Changed syntax of check macro
00068  *
00069  * Revision 1.11  2006/02/21 14:26:54  jmlarsen
00070  * Minor changes
00071  *
00072  * Revision 1.10  2006/02/03 07:46:30  jmlarsen
00073  * Moved recipe implementations to ./uves directory
00074  *
00075  * Revision 1.9  2006/01/31 08:24:16  jmlarsen
00076  * Wrapper for cpl_image_get_bpm
00077  *
00078  * Revision 1.8  2006/01/25 16:13:20  jmlarsen
00079  * Changed interface of gauss.fitting routine
00080  *
00081  * Revision 1.7  2005/12/19 16:17:56  jmlarsen
00082  * Replaced bool -> int
00083  *
00084  * Revision 1.6  2005/12/16 14:22:23  jmlarsen
00085  * Removed midas test data; Added sof files
00086  *
00087  * Revision 1.5  2005/12/02 10:41:49  jmlarsen
00088  * Minor update
00089  *
00090  * Revision 1.4  2005/11/28 08:18:12  jmlarsen
00091  * Replaced cpl_mask_get_bpm -> cpl_image_get_bpm
00092  *
00093  * Revision 1.3  2005/11/25 09:27:00  jmlarsen
00094  * Switched off time component
00095  *
00096  * Revision 1.2  2005/11/24 11:54:46  jmlarsen
00097  * Added support for CPL 3 interface
00098  *
00099  * Revision 1.1  2005/11/11 13:18:54  jmlarsen
00100  * Reorganized code, renamed source files
00101  *
00102  */
00103 
00104 #ifdef HAVE_CONFIG_H
00105 #  include <config.h>
00106 #endif
00107 
00108 /*----------------------------------------------------------------------------*/
00115 /*----------------------------------------------------------------------------*/
00118 /*-----------------------------------------------------------------------------
00119                                 Includes
00120  -----------------------------------------------------------------------------*/
00121 
00122 #include <uves_flatfield.h>
00123 #include <uves_utils.h>
00124 #include <uves_utils_wrappers.h>
00125 #include <uves_error.h>
00126 
00127 #include <irplib_access.h>
00128 
00129 #include <cpl.h>
00130 
00131 /*-----------------------------------------------------------------------------
00132                             Functions prototypes
00133  -----------------------------------------------------------------------------*/
00134 
00135 /*-----------------------------------------------------------------------------
00136                             Implementation
00137  -----------------------------------------------------------------------------*/
00138 
00139 
00140 /*----------------------------------------------------------------------------*/
00161 /*----------------------------------------------------------------------------*/
00162 cpl_error_code
00163 uves_flatfielding(cpl_image *image, cpl_image *noise, 
00164           const cpl_image *master_flat, const cpl_image *mflat_noise)
00165 {
00166     double     *image_data   = NULL;      /* We have to get direct pointers because of the slow */
00167     cpl_mask   *image_mask   = NULL;      /*  bad pix handling in cpl_image_get()  CPLv2-3      */
00168     cpl_binary *image_bad    = NULL;  
00169 
00170     double     *noise_data   = NULL;   
00171     cpl_mask   *noise_mask   = NULL;   
00172     cpl_binary *noise_bad    = NULL;
00173 
00174     const double     *mf_data      = NULL;   
00175     const cpl_mask   *mf_mask      = NULL;   
00176     const cpl_binary *mf_bad       = NULL;  
00177 
00178     const double     *mfnoise_data = NULL;   
00179     const cpl_mask   *mfnoise_mask = NULL;   
00180     const cpl_binary *mfnoise_bad  = NULL;  
00181 
00182 
00183     double ff_mean;
00184     int nx, ny;
00185     int x, y;
00186     
00187     passure( image != NULL, " ");
00188     passure( master_flat != NULL, " ");
00189     passure( noise == NULL || mflat_noise != NULL, " ");
00190 
00191     passure( cpl_image_get_type(image) == CPL_TYPE_DOUBLE, 
00192          "Image must be double");
00193     passure( noise == NULL || cpl_image_get_type(noise) == CPL_TYPE_DOUBLE, 
00194          "Image must be double");
00195     passure( cpl_image_get_type(master_flat) == CPL_TYPE_DOUBLE, 
00196          "Image must be double");
00197     passure( mflat_noise == NULL || cpl_image_get_type(mflat_noise) == CPL_TYPE_DOUBLE,
00198          "Image must be double");
00199 
00200     nx = cpl_image_get_size_x(image);
00201     ny = cpl_image_get_size_y(image);
00202     
00203     assure( nx == cpl_image_get_size_x(master_flat),
00204         CPL_ERROR_INCOMPATIBLE_INPUT,
00205         "Input image and master flat field image have different widths: "
00206         "%d and %d (pixels)",
00207         nx, cpl_image_get_size_x(master_flat));
00208     
00209     assure( ny == cpl_image_get_size_y(master_flat),
00210         CPL_ERROR_INCOMPATIBLE_INPUT,
00211         "Input image and master flat field image have different heights: "
00212         "%d and %d (pixels)",
00213         ny, cpl_image_get_size_y(master_flat));
00214 
00215     /* Get all pointers */
00216     image_data = irplib_image_get_data(image);
00217     image_mask = irplib_image_get_bpm(image);
00218     image_bad  = irplib_mask_get_data(image_mask);
00219 
00220     mf_data = irplib_image_get_data_const(master_flat);
00221     mf_mask = irplib_image_get_bpm_const(master_flat);
00222     mf_bad  = irplib_mask_get_data_const(mf_mask);
00223 
00224     if (noise != NULL)
00225     {
00226         noise_data = irplib_image_get_data(noise);
00227             noise_mask = irplib_image_get_bpm(noise);
00228         noise_bad  = irplib_mask_get_data(noise_mask);
00229 
00230         mfnoise_data = irplib_image_get_data_const(mflat_noise);
00231         mfnoise_mask = irplib_image_get_bpm_const(mflat_noise);
00232         mfnoise_bad  = irplib_mask_get_data_const(mfnoise_mask);
00233     }
00234 
00235     if (false)
00236     {
00237         /* This would actually be the proper thing to do (take bad
00238            pixels into account), but for backwards compatibility
00239            with MIDAS, pretend bad pixels have value zero.
00240            This is done in order to get the same normalization and
00241            be able to use response curves produces by the MIDAS pipeline.
00242 
00243            (The difference in normalization is usually ~10% or so)
00244         */
00245         check( ff_mean = cpl_image_get_mean(master_flat),
00246            "Could not read average flux of master flat image");
00247     }
00248     else
00249     {
00250         /* To get same normalization as MIDAS (which doesn't take bad pixels
00251          * into account), calculate 'ff_mean' while assuming that bad pixels
00252          * have value zero.
00253          */
00254         check( ff_mean = cpl_image_get_flux(master_flat) / (nx * ny),
00255            "Could not read average flux of master flat image");
00256     }
00257     
00258     assure( ff_mean != 0 && !irplib_isnan(ff_mean) &&
00259             !irplib_isinf(ff_mean), CPL_ERROR_ILLEGAL_INPUT,
00260             "Flat-field mean value is %g! Please provide a better flat-field",
00261             ff_mean );
00262     
00263     /* Divide by normalized master flat */
00264     for (y = 0; y < ny; y++)
00265     {
00266         for (x = 0; x < nx; x++)
00267         {
00268             double mf, mf_noise = 0;
00269             double flux, flux_noise = 0, flux_corrected = 0;
00270             double noise_corrected = 0;
00271             cpl_binary pis_rejected;
00272             bool is_bad = false;
00273             
00274             mf           = mf_data[x + y*nx];
00275             pis_rejected = mf_bad [x + y*nx];
00276             is_bad = is_bad || (pis_rejected == CPL_BINARY_1);
00277             /* Slow: mf = cpl_image_get(master_flat, x, y, &pis_rejected);
00278                is_bad = is_bad || pis_rejected; */
00279 
00280             if (noise != NULL)
00281             {
00282                 flux_noise   = noise_data[x + y*nx];
00283                 pis_rejected = noise_bad [x + y*nx];
00284                 is_bad = is_bad || (pis_rejected == CPL_BINARY_1);
00285                 /* Slow: flux_noise = 
00286                    cpl_image_get(image_noise, x, y, &pis_rejected); 
00287                    is_bad = is_bad || pis_rejected; */
00288                 
00289                 mf_noise     = mfnoise_data[x + y*nx];
00290                 pis_rejected = mfnoise_bad [x + y*nx];
00291                 is_bad = is_bad || (pis_rejected == CPL_BINARY_1);
00292                 /* Slow: mf_noise = 
00293                    cpl_image_get(mflat_noise, x, y, &pis_rejected); 
00294                    is_bad = is_bad || pis_rejected; */
00295             }
00296             
00297             flux         = image_data[x + y*nx];
00298             pis_rejected = image_bad [x + y*nx];
00299             is_bad = is_bad || (pis_rejected == CPL_BINARY_1);
00300             /* Slow: flux = cpl_image_get(image, x, y, &pis_rejected); 
00301                is_bad = is_bad || pis_rejected; */
00302             
00303 
00304 
00305 
00306             if (mf > 0)
00307             {
00308                 flux_corrected = (flux / mf) * ff_mean;
00309             }
00310             else
00311             {
00312                 /* Some mf frames (produced by MIDAS) have have
00313                    negative flux values because of improper
00314                    background subtraction */
00315                 is_bad = true;
00316             }
00317 
00318             if (noise != NULL)
00319             {
00320                 noise_corrected = uves_error_fraction(
00321                 flux, mf, flux_noise, mf_noise)
00322                 * ff_mean;
00323             }
00324             
00325             if (is_bad) 
00326             {
00327                 image_bad[x + nx*y] = CPL_BINARY_1;
00328                 /* Slow: cpl_image_reject(image, x, y);*/
00329                 if (noise != NULL)
00330                 {
00331                     noise_bad[x + nx*y] = CPL_BINARY_1;
00332                     /* Slow: cpl_image_reject(noise, x, y);*/
00333                 }
00334             }
00335             else
00336             {
00337                 image_data[x + nx*y] = flux_corrected;
00338                 /* Slow: cpl_image_set(image, x, y, flux_corrected); */
00339                 if (noise != NULL)
00340                 {
00341                     noise_data[x + nx*y] = noise_corrected;
00342                     /* Slow: cpl_image_set(noise, x, y, noise_corrected); */
00343                 }
00344             }
00345         }
00346     }
00347     
00348   cleanup:
00349     return cpl_error_get_code();
00350 }
00351 
00352 /*----------------------------------------------------------------------------*/
00362 /*----------------------------------------------------------------------------*/
00363 flatfielding_method
00364 uves_get_flatfield_method(const cpl_parameterlist *parameters, 
00365               const char *context, const char *subcontext)
00366 {
00367     const char *ff = "";
00368     flatfielding_method result = 0;
00369 
00370     check( uves_get_parameter(parameters, context, subcontext, "ffmethod", CPL_TYPE_STRING, &ff),
00371        "Could not read parameter");
00372     
00373     if      (strcmp(ff, "pixel"  ) == 0) result = FF_PIXEL;
00374     else if (strcmp(ff, "extract") == 0) result = FF_EXTRACT;
00375     else if (strcmp(ff, "no"     ) == 0) result = FF_NO;
00376     else
00377     {
00378         assure(false, CPL_ERROR_ILLEGAL_INPUT, "No such flat-fielding method: '%s'", ff);
00379     }
00380     
00381   cleanup:
00382     return result;
00383 }
00384 

Generated on Tue Jun 19 14:39:16 2007 for UVES Pipeline Reference Manual by  doxygen 1.4.6