uves_mdark_impl.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 02110-1301 USA          *
00018  */
00019  
00020 /*
00021  * $Author: jmlarsen $
00022  * $Date: 2007/06/11 13:28:26 $
00023  * $Revision: 1.31 $
00024  * $Name: uves-3_3_1 $
00025  * $Log: uves_mdark_impl.c,v $
00026  * Revision 1.31  2007/06/11 13:28:26  jmlarsen
00027  * Changed recipe contact address to cpl at eso.org
00028  *
00029  * Revision 1.30  2007/06/08 13:06:16  jmlarsen
00030  * Send bug reports to Andrea
00031  *
00032  * Revision 1.29  2007/06/06 08:17:33  amodigli
00033  * replace tab with 4 spaces
00034  *
00035  * Revision 1.28  2007/05/16 09:50:40  jmlarsen
00036  * Do not threshold to zero after bias subtraction
00037  *
00038  * Revision 1.27  2007/04/24 12:50:29  jmlarsen
00039  * Replaced cpl_propertylist -> uves_propertylist which is much faster
00040  *
00041  * Revision 1.26  2007/02/09 13:37:47  jmlarsen
00042  * Enable calling from uves_cal_mkmaster
00043  *
00044  * Revision 1.25  2007/02/09 08:57:44  jmlarsen
00045  * Include <float.h>
00046  *
00047  * Revision 1.24  2007/02/09 08:14:16  jmlarsen
00048  * Do not use CPL_PIXEL_MAXVAL which works only for integer images
00049  *
00050  * Revision 1.23  2006/12/07 08:23:23  jmlarsen
00051  * uves_load_raw_imagelist: support FLAMES
00052  *
00053  * Revision 1.22  2006/11/15 15:02:14  jmlarsen
00054  * Implemented const safe workarounds for CPL functions
00055  *
00056  * Revision 1.20  2006/11/15 14:04:08  jmlarsen
00057  * Removed non-const version of parameterlist_get_first/last/next which is
00058  * already in CPL, added const-safe wrapper, unwrapper and deallocator functions
00059  *
00060  * Revision 1.19  2006/11/06 15:19:41  jmlarsen
00061  * Removed unused include directives
00062  *
00063  * Revision 1.18  2006/10/17 12:33:02  jmlarsen
00064  * Added semicolon at UVES_RECIPE_DEFINE invocation
00065  *
00066  * Revision 1.17  2006/10/09 13:01:13  jmlarsen
00067  * Use macro to define recipe interface functions
00068  *
00069  * Revision 1.16  2006/09/19 14:31:17  jmlarsen
00070  * uves_insert_frame(): use bitmap to specify which image statistics keywords must be computed
00071  *
00072  * Revision 1.15  2006/09/19 06:55:55  jmlarsen
00073  * Changed interface of uves_frameset to optionally write image statistics kewwords
00074  *
00075  * Revision 1.14  2006/08/24 11:36:37  jmlarsen
00076  * Write recipe start/stop time to header
00077  *
00078  * Revision 1.13  2006/08/17 13:56:53  jmlarsen
00079  * Reduced max line length
00080  *
00081  * Revision 1.12  2006/08/11 14:56:05  amodigli
00082  * removed Doxygen warnings
00083  *
00084  * Revision 1.11  2006/07/14 12:19:28  jmlarsen
00085  * Support multiple QC tests per product
00086  *
00087  * Revision 1.10  2006/07/03 13:02:18  jmlarsen
00088  * Threshold to zero after bias subtraction
00089  *
00090  * Revision 1.9  2006/06/28 13:29:06  amodigli
00091  * removed TEST ID from QC log
00092  *
00093  * Revision 1.8  2006/06/16 08:25:45  jmlarsen
00094  * Manually propagate ESO.DET. keywords from 1st/2nd input header
00095  *
00096  * Revision 1.7  2006/06/13 11:57:02  jmlarsen
00097  * Check that calibration frames are from the same chip ID
00098  *
00099  * Revision 1.6  2006/06/01 14:43:17  jmlarsen
00100  * Added missing documentation
00101  *
00102  * Revision 1.5  2006/05/09 07:42:18  amodigli
00103  * added QC-LOG
00104  *
00105  * Revision 1.4  2006/04/06 12:57:22  jmlarsen
00106  * Added support for PDARK, MASTER_PDARK frames
00107  *
00108  * Revision 1.3  2006/04/06 09:48:15  amodigli
00109  * changed uves_frameset_insert interface to have QC log
00110  *
00111  * Revision 1.2  2006/04/06 08:37:33  jmlarsen
00112  * Removed memory leak
00113  *
00114  * Revision 1.1  2006/02/03 07:46:30  jmlarsen
00115  * Moved recipe implementations to ./uves directory
00116  *
00117  * Revision 1.27  2006/01/19 08:47:24  jmlarsen
00118  * Inserted missing doxygen end tag
00119  *
00120  * Revision 1.26  2005/12/19 16:17:55  jmlarsen
00121  * Replaced bool -> int
00122  *
00123  */
00124 
00125 #ifdef HAVE_CONFIG_H
00126 #  include <config.h>
00127 #endif
00128 
00129 /*----------------------------------------------------------------------------*/
00136 /*----------------------------------------------------------------------------*/
00137 
00138 /*-----------------------------------------------------------------------------
00139                                 Includes
00140  -----------------------------------------------------------------------------*/
00141 #include <uves_mdark_impl.h>
00142 
00143 #include <uves_parameters.h>
00144 #include <uves_utils.h>
00145 #include <uves.h>
00146 #include <uves_dfs.h>
00147 #include <uves_pfits.h>
00148 #include <uves_qclog.h>
00149 #include <uves_recipe.h>
00150 #include <uves_utils_wrappers.h>
00151 #include <uves_error.h>
00152 
00153 #include <irplib_access.h>
00154 #include <cpl.h>
00155 #include <float.h>
00156 
00157 /*-----------------------------------------------------------------------------
00158                             Functions prototypes
00159  -----------------------------------------------------------------------------*/
00160 
00161 static void uves_mdark_qclog(cpl_imagelist* raw_images,
00162                      cpl_table* qclog);
00163 /*-----------------------------------------------------------------------------
00164                             Recipe standard code
00165  -----------------------------------------------------------------------------*/
00166 #define cpl_plugin_get_info uves_mdark_get_info
00167 UVES_RECIPE_DEFINE(
00168     UVES_MDARK_ID, UVES_MDARK_DOM, 
00169     /* Warning: if more parameters are added to this recipe, they 
00170        need to be propagated to uves_cal_mkmaster! */
00171     uves_define_global_parameters,
00172     "Jonas M. Larsen", "cpl@eso.org",
00173     "Creates the master dark frame",
00174     "This recipe creates a master dark frame by taking the median of all\n"
00175     "input frames which should have identical exposure times. Symbolically,\n"
00176     "   masterdark = median( dark_i ) - masterbias\n"
00177     "\n"
00178     "The input dark frames must have same tag and size and must be either\n"
00179     "(P)DARK_BLUE or (P)DARK_RED. Also, a master bias (MASTER_BIAS_xxxx) must\n"
00180     "be provided for each chip (xxxx = BLUE, REDL, REDU).\n"
00181     "\n"
00182     "On blue input the recipe computes one master dark frame; on red input the\n"
00183     "recipe produces a master dark frame for each chip (MASTER_(P)DARK_xxxx).\n");
00184 
00186 /*-----------------------------------------------------------------------------
00187                             Functions code
00188  -----------------------------------------------------------------------------*/
00189 /*----------------------------------------------------------------------------*/
00209 /*----------------------------------------------------------------------------*/
00210 static cpl_image *
00211 uves_mdark_process_chip(const cpl_imagelist *raw_images, uves_propertylist **raw_headers, 
00212             const cpl_image *master_bias,
00213             uves_propertylist *mdark_header)
00214 {
00215     cpl_image *master_dark        = NULL; /* Result */
00216     cpl_image *current_dark       = NULL;
00217     cpl_imagelist *preproc_images = NULL;
00218     double min_exptime = 0;
00219     double max_exptime = 0;
00220     int i;
00221     
00222     /* First process each input image and store the results in a new image list */
00223 
00224     preproc_images = cpl_imagelist_new();
00225     for (i = 0; i < cpl_imagelist_get_size(raw_images); i++)
00226     {
00227         double exposure_time = 0.0;
00228         const uves_propertylist *current_header;
00229         
00230         current_dark = cpl_image_duplicate(irplib_imagelist_get_const(raw_images, i));
00231         current_header = raw_headers[i];
00232                 
00233         /* Subtract master bias */
00234         if (master_bias != NULL)
00235         {
00236             uves_msg("Subtracting master bias");
00237             check( uves_subtract_bias(current_dark, master_bias), 
00238                "Error subtracting master bias");
00239 
00240                     if (false) {
00241             uves_msg_debug("Thresholding to non-negative values");
00242             check( cpl_image_threshold(current_dark, 
00243                            0, DBL_MAX,     /* Interval */
00244                            0, DBL_MAX),    /* New values */
00245                "Error thresholding image");
00246                     }
00247         }
00248         else
00249         {
00250             uves_msg("Skipping bias subtraction");
00251         }
00252         
00253         check( exposure_time = uves_pfits_get_exptime(current_header), 
00254            "Error reading exposure time");
00255         
00256         /* Initialize/update min/max exposure time*/
00257         if (i == 0 || exposure_time < min_exptime)
00258         {
00259             min_exptime = exposure_time;
00260         }
00261         if (i == 0 || exposure_time > max_exptime)
00262         {
00263             max_exptime = exposure_time;
00264         }
00265 
00266         /* Do not normalize to unit exposure time */
00267 /*        If this is uncommented, then remember to also calculate the
00268         correct master dark exposure time below.
00269             uves_msg("Normalizing from %f s to unit exposure time", exposure_time);
00270         check( cpl_image_divide_scalar(current_dark, exposure_time), 
00271         "Error normalizing dark frame");   */        
00272 
00273         /* Append to imagelist */
00274         check( cpl_imagelist_set(preproc_images,
00275                      current_dark,  
00276                      i),            /* Position (number_of_images=>append) */
00277            "Could not insert image into image list");
00278         
00279         /* Don't deallocate the image. It will be deallocated when
00280            the image list is deallocated */
00281         current_dark = NULL;
00282     }
00283 
00284     /* Check exposure times */
00285     uves_msg("Exposure times range from %e s to %e s (%e %% variation)", 
00286             min_exptime,
00287             max_exptime,
00288             100 * (max_exptime - min_exptime) / min_exptime);
00289 
00290     if ((max_exptime - min_exptime) / min_exptime > .001)
00291     {
00292         uves_msg_warning("Exposure times differ by %e %%", 
00293                  100 * (max_exptime - min_exptime) / min_exptime);
00294     }
00295     
00296     /* Get median stack of input darks */
00297     uves_msg("Calculating stack median");
00298     check( master_dark = cpl_imagelist_collapse_median_create(preproc_images), 
00299        "Error computing median");
00300 
00301     check( uves_pfits_set_exptime(mdark_header, (max_exptime + min_exptime)/2),
00302        "Error setting master dark exposure time");
00303     
00304   cleanup:
00305     uves_free_image(&current_dark);
00306     uves_free_imagelist(&preproc_images);
00307     if (cpl_error_get_code() != CPL_ERROR_NONE)
00308     {
00309         uves_free_image(&master_dark);
00310     }
00311     
00312     return master_dark;
00313 }
00314 
00315 /*----------------------------------------------------------------------------*/
00322 /*----------------------------------------------------------------------------*/
00323 static void
00324 IRPLIB_CONCAT2X(UVES_MDARK_ID,exe)(cpl_frameset *frames, 
00325                    const cpl_parameterlist *parameters,
00326                    const char *starttime)
00327 {
00328     uves_mdark_exe_body(frames, parameters, starttime, make_str(UVES_MDARK_ID));
00329     return;
00330 }
00331 
00332 /*----------------------------------------------------------------------------*/
00344 /*----------------------------------------------------------------------------*/
00345 void
00346 uves_mdark_exe_body(cpl_frameset *frames, 
00347             const cpl_parameterlist *parameters,
00348             const char *starttime,
00349             const char *recipe_id)
00350 {
00351     /* Function id */
00352     /*
00353      * Variables that will contain the values of the recipe parameters 
00354      */
00355     /* None */
00356 
00357     /* CPL objects */
00358     /* Input */
00359     cpl_imagelist *raw_images[2]       = {NULL, NULL};
00360     uves_propertylist  **raw_headers[2] = {NULL, NULL};    /* Two arrays of pointers */
00361 
00362     /* Master bias */
00363     cpl_image *master_bias               = NULL;
00364     uves_propertylist *master_bias_header = NULL;
00365     
00366     /* Output */
00367     cpl_table* qclog[2] = {NULL, NULL};
00368     cpl_image *master_dark              = NULL;
00369     uves_propertylist *product_header[2] = {NULL, NULL};
00370     
00371     /* Local variables */
00372     char *product_filename = NULL;
00373     const char *product_tag[2] = {NULL, NULL};
00374     bool blue;
00375     enum uves_chip chip;
00376 
00377     /* Load and check raw dark images and headers, identify arm (blue/red) */
00378     /* On success, 'raw_headers' will be an array with the same size as 'raw_images' */
00379     if (irplib_frameset_find(frames, UVES_DARK(true )) != NULL ||
00380     irplib_frameset_find(frames, UVES_DARK(false)) != NULL)
00381     {
00382         check( uves_load_raw_imagelist(frames, 
00383                        false,    /* FLAMES format? */
00384                        UVES_DARK(true), UVES_DARK(false),
00385                        CPL_TYPE_DOUBLE,
00386                        raw_images, raw_headers, product_header, 
00387                        &blue), "Error loading raw dark frames");
00388         
00389         for (chip = uves_chip_get_first(blue); 
00390          chip != UVES_CHIP_INVALID; 
00391          chip = uves_chip_get_next(chip))
00392         {
00393             product_tag[uves_chip_get_index(chip)] = UVES_MASTER_DARK(chip);
00394         }
00395     }
00396     else if (irplib_frameset_find(frames, UVES_PDARK(true )) != NULL ||
00397          irplib_frameset_find(frames, UVES_PDARK(false)) != NULL)
00398     {
00399         check( uves_load_raw_imagelist(frames, 
00400                        false,  /* FLAMES format? */
00401                        UVES_PDARK(true), UVES_PDARK(false),
00402                        CPL_TYPE_DOUBLE,
00403                        raw_images, raw_headers, product_header, 
00404                        &blue), "Error loading raw dark frames");
00405         
00406         for (chip = uves_chip_get_first(blue);
00407          chip != UVES_CHIP_INVALID;
00408          chip = uves_chip_get_next(chip))
00409         {
00410             product_tag[uves_chip_get_index(chip)] = UVES_MASTER_PDARK(chip);
00411         }
00412     }
00413     else
00414     {
00415         assure(false, CPL_ERROR_DATA_NOT_FOUND,
00416            "Missing input dark frame: %s, %s, %s or %s expected",
00417            UVES_DARK(true) , UVES_DARK(false),
00418            UVES_PDARK(true), UVES_PDARK(false));
00419     }
00420 
00421     /* Loop over one or two chips */
00422     for (chip = uves_chip_get_first(blue); 
00423      chip != UVES_CHIP_INVALID; 
00424      chip = uves_chip_get_next(chip))
00425     {
00426         const char *master_bias_filename = "";
00427         const char *chip_name = "";
00428         
00429         int raw_index = uves_chip_get_index(chip);
00430         
00431         uves_msg("Processing %s chip",
00432              uves_chip_tostring_upper(chip));
00433 
00434         /* Get chip name of first input frame */
00435         check_nomsg( chip_name = uves_pfits_get_chipid(raw_headers[raw_index][0], chip));
00436 
00437         /* Load master bias, set pointer to NULL if not present */
00438         uves_free_image(&master_bias);
00439         uves_free_propertylist(&master_bias_header);
00440         if (irplib_frameset_find(frames, UVES_MASTER_BIAS(chip)) != NULL)
00441         {
00442             check( uves_load_mbias(frames, chip_name,
00443                        &master_bias_filename, &master_bias, 
00444                        &master_bias_header, chip), 
00445                "Error loading master bias");
00446             
00447             uves_msg_low("Using master bias in '%s'", master_bias_filename);
00448         }
00449         else
00450         {
00451             uves_msg_low("No master bias in SOF. Bias subtraction not done");
00452         }
00453         
00454         /* Process chip */
00455         uves_free_image(&master_dark);
00456         check( master_dark = uves_mdark_process_chip(raw_images[raw_index], 
00457                              raw_headers[raw_index], 
00458                              master_bias,
00459                              product_header[raw_index]),
00460            "Error processing chip");
00461         
00462         /* Finished. Save */
00463                 /* Finished. Calculate QC parameters and save */
00464         uves_msg("Calculating QC parameters");
00465             uves_qclog_delete(&qclog[0]);
00466             qclog[0] = uves_qclog_init(raw_headers[raw_index][0], chip);
00467             check(uves_mdark_qclog(raw_images[raw_index],
00468                    qclog[0]),"error computing qclog");
00469         /* Insert into frame set */
00470         uves_msg("Saving product");
00471         
00472         cpl_free(product_filename);
00473         check( product_filename = uves_masterdark_filename(chip), "Error getting filename");
00474 
00475 
00476         check( uves_frameset_insert(frames,
00477                     master_dark,
00478                     CPL_FRAME_GROUP_PRODUCT,
00479                     CPL_FRAME_TYPE_IMAGE,
00480                     CPL_FRAME_LEVEL_INTERMEDIATE,
00481                     product_filename,
00482                     product_tag[raw_index],
00483                     raw_headers[raw_index][0],
00484                     product_header[raw_index],
00485                     NULL,
00486                     parameters,
00487                     recipe_id,
00488                     PACKAGE "/" PACKAGE_VERSION,qclog,
00489                     starttime, true, 
00490                     UVES_ALL_STATS), 
00491            "Could not add master dark %s to frameset", product_filename);
00492         uves_msg("Master dark %s added to frameset", product_filename);
00493         uves_qclog_delete(&qclog[0]);
00494         
00495     }/* For each chip */
00496 
00497   cleanup:
00498     /* Input */
00499     if (raw_images[0] != NULL)
00500     {
00501         int i;
00502         for (i = 0; i < cpl_imagelist_get_size(raw_images[0]); i++) 
00503         {
00504             if (raw_headers[0] != NULL) uves_free_propertylist(&raw_headers[0][i]);
00505             if (raw_headers[1] != NULL) uves_free_propertylist(&raw_headers[1][i]);
00506         }
00507 
00508         cpl_free(raw_headers[0]); raw_headers[0] = NULL;
00509         cpl_free(raw_headers[1]); raw_headers[1] = NULL;
00510     }
00511 
00512     uves_free_imagelist(&raw_images[0]);
00513     uves_free_imagelist(&raw_images[1]);
00514 
00515     /* Master bias */
00516     uves_free_image(&master_bias);
00517     uves_free_propertylist(&master_bias_header);
00518 
00519     /* Output */
00520     uves_qclog_delete(&qclog[0]);
00521     uves_free_image(&master_dark);
00522     uves_free_propertylist(&product_header[0]);
00523     uves_free_propertylist(&product_header[1]);
00524     cpl_free(product_filename);
00525 
00526     return;
00527 }
00528 
00529 
00530 static void uves_mdark_qclog(cpl_imagelist* raw_images,
00531                      cpl_table* qclog)
00532 {
00533   int nraw=0;
00534   /* Temporally commented out as missing also in UVES-MIDAS pipeline
00535   check_nomsg(uves_qclog_add_string(qclog,
00536                         "QC TEST1 ID",
00537                         "Test-on-Master-Dark",
00538                         "Name of QC test",
00539                         "%s"));
00540   */
00541   check_nomsg(nraw=cpl_imagelist_get_size(raw_images));
00542   check_nomsg(uves_qclog_add_int(qclog,
00543                         "PRO DATANCOM",
00544                         nraw,
00545                         "Number of frames combined",
00546                         "%d"));
00547  cleanup:
00548   return;
00549 }
00550 
00551 

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