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

Generated on 28 Feb 2012 for UVES Pipeline Reference Manual by  doxygen 1.6.1