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: 2010/09/29 09:39:07 $
00023  * $Revision: 1.34 $
00024  * $Name: uves-4_9_1 $
00025  * $Log: uves_flatfield.c,v $
00026  * Revision 1.34  2010/09/29 09:39:07  amodigli
00027  * fixed compiler warnings
00028  *
00029  * Revision 1.33  2010/09/27 07:58:36  amodigli
00030  * fixed mem leak in case a new mask is allocated
00031  *
00032  * Revision 1.32  2010/09/27 06:33:33  amodigli
00033  * fixed mem leaks
00034  *
00035  * Revision 1.31  2010/09/24 09:32:03  amodigli
00036  * put back QFITS dependency to fix problem spot by NRI on FIBER mode (with MIDAS calibs) data
00037  *
00038  * Revision 1.29  2009/07/07 14:26:12  amodigli
00039  * Fixed a problem dealing with images missing a bpm
00040  *
00041  * Revision 1.28  2008/09/29 06:56:10  amodigli
00042  * add #include <string.h>
00043  *
00044  * Revision 1.27  2007/08/21 13:08:26  jmlarsen
00045  * Removed irplib_access module, largely deprecated by CPL-4
00046  *
00047  * Revision 1.26  2007/06/06 08:17:33  amodigli
00048  * replace tab with 4 spaces
00049  *
00050  * Revision 1.25  2007/05/24 13:07:46  jmlarsen
00051  * Fail if the provided flat-field has unreasonable (zero, nan or inf) mean value
00052  *
00053  * Revision 1.24  2007/05/22 11:36:37  jmlarsen
00054  * Removed MIDAS flag for good
00055  *
00056  * Revision 1.23  2006/11/15 15:02:14  jmlarsen
00057  * Implemented const safe workarounds for CPL functions
00058  *
00059  * Revision 1.21  2006/11/15 14:04:08  jmlarsen
00060  * Removed non-const version of parameterlist_get_first/last/next which is already
00061  * in CPL, added const-safe wrapper, unwrapper and deallocator functions
00062  *
00063  * Revision 1.20  2006/11/13 14:23:55  jmlarsen
00064  * Removed workarounds for CPL const bugs
00065  *
00066  * Revision 1.19  2006/11/06 15:19:41  jmlarsen
00067  * Removed unused include directives
00068  *
00069  * Revision 1.18  2006/08/17 13:56:53  jmlarsen
00070  * Reduced max line length
00071  *
00072  * Revision 1.17  2006/08/17 09:16:40  jmlarsen
00073  * Removed CPL2 code
00074  *
00075  * Revision 1.16  2006/08/10 10:49:57  jmlarsen
00076  * Removed workaround for cpl_image_get_bpm
00077  *
00078  * Revision 1.15  2006/06/16 08:23:31  jmlarsen
00079  * Changed 0 -> false
00080  *
00081  * Revision 1.14  2006/04/24 09:20:12  jmlarsen
00082  * Always use the MIDAS normalization
00083  *
00084  * Revision 1.13  2006/03/24 14:16:43  jmlarsen
00085  * Changed order of for loops for efficiency
00086  *
00087  * Revision 1.12  2006/03/03 13:54:11  jmlarsen
00088  * Changed syntax of check macro
00089  *
00090  * Revision 1.11  2006/02/21 14:26:54  jmlarsen
00091  * Minor changes
00092  *
00093  * Revision 1.10  2006/02/03 07:46:30  jmlarsen
00094  * Moved recipe implementations to ./uves directory
00095  *
00096  * Revision 1.9  2006/01/31 08:24:16  jmlarsen
00097  * Wrapper for cpl_image_get_bpm
00098  *
00099  * Revision 1.8  2006/01/25 16:13:20  jmlarsen
00100  * Changed interface of gauss.fitting routine
00101  *
00102  * Revision 1.7  2005/12/19 16:17:56  jmlarsen
00103  * Replaced bool -> int
00104  *
00105  * Revision 1.6  2005/12/16 14:22:23  jmlarsen
00106  * Removed midas test data; Added sof files
00107  *
00108  * Revision 1.5  2005/12/02 10:41:49  jmlarsen
00109  * Minor update
00110  *
00111  * Revision 1.4  2005/11/28 08:18:12  jmlarsen
00112  * Replaced cpl_mask_get_bpm -> cpl_image_get_bpm
00113  *
00114  * Revision 1.3  2005/11/25 09:27:00  jmlarsen
00115  * Switched off time component
00116  *
00117  * Revision 1.2  2005/11/24 11:54:46  jmlarsen
00118  * Added support for CPL 3 interface
00119  *
00120  * Revision 1.1  2005/11/11 13:18:54  jmlarsen
00121  * Reorganized code, renamed source files
00122  *
00123  */
00124 
00125 #ifdef HAVE_CONFIG_H
00126 #  include <config.h>
00127 #endif
00128 
00129 /*----------------------------------------------------------------------------*/
00136 /*----------------------------------------------------------------------------*/
00139 /*-----------------------------------------------------------------------------
00140                                 Includes
00141  -----------------------------------------------------------------------------*/
00142 #include <string.h>
00143 #include <uves_flatfield.h>
00144 #include <uves_utils.h>
00145 #include <uves_utils_wrappers.h>
00146 #include <uves_error.h>
00147 
00148 #include <cpl.h>
00149 
00150 /*-----------------------------------------------------------------------------
00151                             Functions prototypes
00152  -----------------------------------------------------------------------------*/
00153 
00154 /*-----------------------------------------------------------------------------
00155                             Implementation
00156  -----------------------------------------------------------------------------*/
00157 
00158 
00159 /*----------------------------------------------------------------------------*/
00180 /*----------------------------------------------------------------------------*/
00181 cpl_error_code
00182 uves_flatfielding(cpl_image *image, cpl_image *noise, 
00183           const cpl_image *master_flat, const cpl_image *mflat_noise)
00184 {
00185     double     *image_data   = NULL;      /* We have to get direct pointers because of the slow */
00186     cpl_mask   *image_mask   = NULL;      /*  bad pix handling in cpl_image_get()  CPLv2-3      */
00187     cpl_binary *image_bad    = NULL;  
00188 
00189     double     *noise_data   = NULL;   
00190     cpl_mask   *noise_mask   = NULL;   
00191     cpl_binary *noise_bad    = NULL;
00192 
00193     const double     *mf_data      = NULL;   
00194     const cpl_mask   *mf_mask      = NULL;   
00195     const cpl_binary *mf_bad       = NULL;  
00196 
00197     const double     *mfnoise_data = NULL;   
00198     const cpl_mask   *mfnoise_mask = NULL;   
00199     cpl_mask   *mfnoise_mask_own = NULL;   
00200     cpl_mask   *mf_mask_own = NULL;   
00201     const cpl_binary *mfnoise_bad  = NULL;  
00202   
00203 
00204     double ff_mean;
00205     int nx, ny;
00206     int x, y;
00207     
00208     passure( image != NULL, " ");
00209     passure( master_flat != NULL, " ");
00210     passure( noise == NULL || mflat_noise != NULL, " ");
00211 
00212     passure( cpl_image_get_type(image) == CPL_TYPE_DOUBLE, 
00213          "Image must be double");
00214     passure( noise == NULL || cpl_image_get_type(noise) == CPL_TYPE_DOUBLE, 
00215          "Image must be double");
00216     passure( cpl_image_get_type(master_flat) == CPL_TYPE_DOUBLE, 
00217          "Image must be double");
00218     passure( mflat_noise == NULL || cpl_image_get_type(mflat_noise) == CPL_TYPE_DOUBLE,
00219          "Image must be double");
00220 
00221     nx = cpl_image_get_size_x(image);
00222     ny = cpl_image_get_size_y(image);
00223     
00224     assure( nx == cpl_image_get_size_x(master_flat),
00225         CPL_ERROR_INCOMPATIBLE_INPUT,
00226         "Input image and master flat field image have different widths: "
00227         "%d and %d (pixels)",
00228         nx, cpl_image_get_size_x(master_flat));
00229     
00230     assure( ny == cpl_image_get_size_y(master_flat),
00231         CPL_ERROR_INCOMPATIBLE_INPUT,
00232         "Input image and master flat field image have different heights: "
00233         "%d and %d (pixels)",
00234         ny, cpl_image_get_size_y(master_flat));
00235 
00236     /* Get all pointers */
00237     check_nomsg(image_data = cpl_image_get_data(image));
00238     check_nomsg(image_mask = cpl_image_get_bpm(image));
00239     check_nomsg(image_bad  = cpl_mask_get_data(image_mask));
00240 
00241     check_nomsg(mf_data = cpl_image_get_data_const(master_flat));
00242     check_nomsg(mf_mask = cpl_image_get_bpm_const(master_flat));
00243     if(mf_mask==NULL) {
00244           mf_mask_own = cpl_mask_new(nx,ny);
00245           mf_mask = mf_mask_own ;
00246     }
00247     check_nomsg(mf_bad  = cpl_mask_get_data_const(mf_mask));
00248 
00249     if (noise != NULL)
00250     {
00251        check_nomsg(noise_data = cpl_image_get_data(noise));
00252        check_nomsg(noise_mask = cpl_image_get_bpm(noise));
00253        check_nomsg(noise_bad  = cpl_mask_get_data(noise_mask));
00254 
00255        check_nomsg(mfnoise_data = cpl_image_get_data_const(mflat_noise));
00256        check_nomsg(mfnoise_mask = cpl_image_get_bpm_const(mflat_noise));
00257        if(mfnoise_mask==NULL) {
00258           mfnoise_mask_own = cpl_mask_new(nx,ny);
00259           mfnoise_mask = mfnoise_mask_own ;
00260        }
00261        check_nomsg(mfnoise_bad  = cpl_mask_get_data_const(mfnoise_mask));
00262     }
00263 
00264     if (false)
00265     {
00266         /* This would actually be the proper thing to do (take bad
00267            pixels into account), but for backwards compatibility
00268            with MIDAS, pretend bad pixels have value zero.
00269            This is done in order to get the same normalization and
00270            be able to use response curves produces by the MIDAS pipeline.
00271 
00272            (The difference in normalization is usually ~10% or so)
00273         */
00274         check( ff_mean = cpl_image_get_mean(master_flat),
00275            "Could not read average flux of master flat image");
00276     }
00277     else
00278     {
00279         /* To get same normalization as MIDAS (which doesn't take bad pixels
00280          * into account), calculate 'ff_mean' while assuming that bad pixels
00281          * have value zero.
00282          */
00283         check( ff_mean = cpl_image_get_flux(master_flat) / (nx * ny),
00284            "Could not read average flux of master flat image");
00285     }
00286     
00287     assure( ff_mean != 0 && !irplib_isnan(ff_mean) &&
00288             !irplib_isinf(ff_mean), CPL_ERROR_ILLEGAL_INPUT,
00289             "Flat-field mean value is %g! Please provide a better flat-field",
00290             ff_mean );
00291     
00292     /* Divide by normalized master flat */
00293     for (y = 0; y < ny; y++)
00294     {
00295         for (x = 0; x < nx; x++)
00296         {
00297             double mf, mf_noise = 0;
00298             double flux, flux_noise = 0, flux_corrected = 0;
00299             double noise_corrected = 0;
00300             cpl_binary pis_rejected;
00301             bool is_bad = false;
00302             
00303             mf           = mf_data[x + y*nx];
00304             pis_rejected = mf_bad [x + y*nx];
00305             is_bad = is_bad || (pis_rejected == CPL_BINARY_1);
00306             /* Slow: mf = cpl_image_get(master_flat, x, y, &pis_rejected);
00307                is_bad = is_bad || pis_rejected; */
00308 
00309             if (noise != NULL)
00310             {
00311                 flux_noise   = noise_data[x + y*nx];
00312                 pis_rejected = noise_bad [x + y*nx];
00313                 is_bad = is_bad || (pis_rejected == CPL_BINARY_1);
00314                 /* Slow: flux_noise = 
00315                    cpl_image_get(image_noise, x, y, &pis_rejected); 
00316                    is_bad = is_bad || pis_rejected; */
00317                 
00318                 mf_noise     = mfnoise_data[x + y*nx];
00319                 pis_rejected = mfnoise_bad [x + y*nx];
00320                 is_bad = is_bad || (pis_rejected == CPL_BINARY_1);
00321                 /* Slow: mf_noise = 
00322                    cpl_image_get(mflat_noise, x, y, &pis_rejected); 
00323                    is_bad = is_bad || pis_rejected; */
00324             }
00325             
00326             flux         = image_data[x + y*nx];
00327             pis_rejected = image_bad [x + y*nx];
00328             is_bad = is_bad || (pis_rejected == CPL_BINARY_1);
00329             /* Slow: flux = cpl_image_get(image, x, y, &pis_rejected); 
00330                is_bad = is_bad || pis_rejected; */
00331             
00332 
00333 
00334 
00335             if (mf > 0)
00336             {
00337                 flux_corrected = (flux / mf) * ff_mean;
00338             }
00339             else
00340             {
00341                 /* Some mf frames (produced by MIDAS) have have
00342                    negative flux values because of improper
00343                    background subtraction */
00344                 is_bad = true;
00345             }
00346 
00347             if (noise != NULL)
00348             {
00349                 noise_corrected = uves_error_fraction(
00350                 flux, mf, flux_noise, mf_noise)
00351                 * ff_mean;
00352             }
00353             
00354             if (is_bad) 
00355             {
00356                 image_bad[x + nx*y] = CPL_BINARY_1;
00357                 /* Slow: cpl_image_reject(image, x, y);*/
00358                 if (noise != NULL)
00359                 {
00360                     noise_bad[x + nx*y] = CPL_BINARY_1;
00361                     /* Slow: cpl_image_reject(noise, x, y);*/
00362                 }
00363             }
00364             else
00365             {
00366                 image_data[x + nx*y] = flux_corrected;
00367                 /* Slow: cpl_image_set(image, x, y, flux_corrected); */
00368                 if (noise != NULL)
00369                 {
00370                     noise_data[x + nx*y] = noise_corrected;
00371                     /* Slow: cpl_image_set(noise, x, y, noise_corrected); */
00372                 }
00373             }
00374         }
00375     }
00376     
00377   cleanup:
00378     if(mf_mask_own) uves_free_mask(&mf_mask_own);
00379     if(mfnoise_mask_own) uves_free_mask(&mfnoise_mask_own);
00380     return cpl_error_get_code();
00381 }
00382 
00383 /*----------------------------------------------------------------------------*/
00393 /*----------------------------------------------------------------------------*/
00394 flatfielding_method
00395 uves_get_flatfield_method(const cpl_parameterlist *parameters, 
00396               const char *context, const char *subcontext)
00397 {
00398     const char *ff = "";
00399     flatfielding_method result = 0;
00400 
00401     check( uves_get_parameter(parameters, context, subcontext, "ffmethod", CPL_TYPE_STRING, &ff),
00402        "Could not read parameter");
00403     
00404     if      (strcmp(ff, "pixel"  ) == 0) result = FF_PIXEL;
00405     else if (strcmp(ff, "extract") == 0) result = FF_EXTRACT;
00406     else if (strcmp(ff, "no"     ) == 0) result = FF_NO;
00407     else
00408     {
00409         assure(false, CPL_ERROR_ILLEGAL_INPUT, "No such flat-fielding method: '%s'", ff);
00410     }
00411     
00412   cleanup:
00413     return result;
00414 }
00415 

Generated on 8 Mar 2011 for UVES Pipeline Reference Manual by  doxygen 1.6.1