naco_img_lampflat.c

00001 /* $Id: naco_img_lampflat.c,v 1.58 2009/01/29 08:54:58 llundin Exp $
00002  *
00003  * This file is part of the NACO Pipeline
00004  * Copyright (C) 2002,2003 European Southern Observatory
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: llundin $
00023  * $Date: 2009/01/29 08:54:58 $
00024  * $Revision: 1.58 $
00025  * $Name: naco-4_1_2 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                 Includes
00034  -----------------------------------------------------------------------------*/
00035 
00036 #include "naco_recipe.h"
00037 
00038 /*-----------------------------------------------------------------------------
00039                             Recipe defines
00040  -----------------------------------------------------------------------------*/
00041 
00042 #define RECIPE_STRING   "naco_img_lampflat"
00043 
00044 /*-----------------------------------------------------------------------------
00045                             Private Functions prototypes
00046  -----------------------------------------------------------------------------*/
00047 
00048 static cpl_image * naco_img_lampflat_reduce(cpl_propertylist *,
00049                                             const irplib_framelist *,
00050                                             int, int, int, int);
00051 
00052 static cpl_error_code naco_img_lampflat_qc(cpl_propertylist *,
00053                                            cpl_propertylist *,
00054                                            const irplib_framelist *);
00055 
00056 static cpl_error_code naco_img_lampflat_save(cpl_frameset *,
00057                                              const cpl_parameterlist *,
00058                                              const cpl_propertylist *,
00059                                              const cpl_propertylist *,
00060                                              const cpl_image *,
00061                                              int, const irplib_framelist *);
00062 
00063 static char * naco_img_lampflat_make_tag(const cpl_frame*,
00064                                          const cpl_propertylist *, int);
00065 
00066 NACO_RECIPE_DEFINE(naco_img_lampflat, NACO_PARAM_REJBORD,
00067                    "Flat recipe using a lamp",
00068                    RECIPE_STRING " -- NACO imaging flat-field creation from "
00069                    "lamp images.\n" 
00070                    "The files listed in the Set Of Frames (sof-file) "
00071                    "must be tagged:\n" 
00072                    "NACO-raw-file.fits " NACO_IMG_LAMPFLAT_RAW "\n"                    
00073                    "\n"                                                                
00074                    "Furthermore, the input set of frames must have values of "
00075                    "the FITS key " 
00076                    NACO_PFITS_INT_LAMP2 " that alternate between zero and "
00077                    "non-zero (with non-zero for the first frame).\n"         
00078                    "It is further required that the light from the lamp is "
00079                    "in a range without a significant thermal background.");
00080 
00081 
00082 /*----------------------------------------------------------------------------*/
00086 /*----------------------------------------------------------------------------*/
00087 
00088 /*-----------------------------------------------------------------------------
00089                                 Functions code
00090  -----------------------------------------------------------------------------*/
00091 
00092 /*----------------------------------------------------------------------------*/
00099 /*----------------------------------------------------------------------------*/
00100 static int naco_img_lampflat(cpl_frameset            * framelist,
00101                              const cpl_parameterlist * parlist)
00102 {
00103     cpl_errorstate cleanstate = cpl_errorstate_get();
00104     irplib_framelist * allframes = NULL;
00105     irplib_framelist * rawframes = NULL;
00106     irplib_framelist * f_one     = NULL;
00107     const char      ** taglist   = NULL;
00108     const char       * rej_bord;
00109     cpl_image        * lamp_flat = NULL;
00110     cpl_propertylist * qclist  = cpl_propertylist_new();
00111     cpl_propertylist * paflist = cpl_propertylist_new();
00112     int                nb_good = 0;
00113     int                nsets;
00114     int                rej_left, rej_right, rej_bottom, rej_top;
00115     int                i;
00116     
00117 
00118     /* Retrieve input parameters */
00119     rej_bord = naco_parameterlist_get_string(parlist, RECIPE_STRING, NACO_PARAM_REJBORD);
00120     skip_if (0);
00121     skip_if (sscanf(rej_bord, "%d %d %d %d",
00122                     &rej_left, &rej_right, &rej_bottom, &rej_top) != 4);
00123   
00124     /* Identify the RAW and CALIB frames in the input frameset */
00125     skip_if (naco_dfs_set_groups(framelist));
00126 
00127     allframes = irplib_framelist_cast(framelist);
00128     skip_if(allframes == NULL);
00129 
00130     rawframes = irplib_framelist_extract(allframes, NACO_IMG_LAMPFLAT_RAW);
00131     skip_if(rawframes == NULL);
00132     irplib_framelist_empty(allframes);
00133 
00134     skip_if(irplib_framelist_load_propertylist_all(rawframes, 0, "^("
00135                                                    IRPLIB_PFITS_REGEXP_RECAL "|"
00136                                                    NACO_PFITS_REGEXP_LAMPFLAT "|"
00137                                                    NACO_PFITS_REGEXP_LAMPFLAT_PAF
00138                                                    ")$", CPL_FALSE));
00139 
00140     taglist = naco_framelist_set_tag(rawframes, naco_img_lampflat_make_tag,
00141                                      &nsets);
00142     skip_if(taglist == NULL);
00143 
00144     cpl_msg_info(cpl_func, "Identified %d setting(s) in %d frames",
00145                  nsets, irplib_framelist_get_size(rawframes));
00146 
00147     /* Extract settings and reduce each of them */
00148     for (i=0 ; i < nsets ; i++) {
00149 
00150         /* Reduce data set nb i */
00151         cpl_msg_info(cpl_func, "Reducing data set %d of %d", i+1, nsets);
00152 
00153         /* Reduce data set nb i */
00154         f_one = irplib_framelist_extract(rawframes, taglist[i]);
00155 
00156         /* Reset the tag */
00157         skip_if(irplib_framelist_set_tag_all(f_one, NACO_IMG_LAMPFLAT_RAW));
00158 
00159         cpl_msg_info(cpl_func, "Reducing frame set %d of %d (size=%d) with "
00160                      "setting: %s", i+1, nsets,
00161                      irplib_framelist_get_size(f_one), taglist[i]);
00162 
00163         skip_if (f_one == NULL);
00164         
00165         lamp_flat = naco_img_lampflat_reduce(qclist, f_one, rej_left, rej_right,
00166                                              rej_bottom, rej_top);
00167         
00168         /* Save the products */
00169         if (lamp_flat == NULL) {
00170             if (nsets > 1)
00171                 irplib_error_recover(cleanstate, "Could not compute the flat for "
00172                                      "this setting");
00173         } else {
00174             skip_if(naco_img_lampflat_qc(qclist, paflist, f_one));
00175             skip_if(naco_img_lampflat_save(framelist, parlist, qclist, paflist,
00176                                            lamp_flat, i+1, f_one));
00177             cpl_image_delete(lamp_flat);
00178             lamp_flat = NULL;
00179             nb_good++;
00180         }
00181         cpl_propertylist_empty(qclist);
00182         cpl_propertylist_empty(paflist);
00183         irplib_framelist_delete(f_one);
00184         f_one = NULL;
00185     }
00186 
00187     irplib_ensure(nb_good > 0, CPL_ERROR_DATA_NOT_FOUND,
00188                   "None of the %d sets could be reduced", nsets);
00189     
00190     end_skip;
00191 
00192     cpl_free(taglist);
00193     cpl_image_delete(lamp_flat);
00194     irplib_framelist_delete(f_one);
00195     irplib_framelist_delete(allframes);
00196     irplib_framelist_delete(rawframes);
00197     cpl_propertylist_delete(qclist);
00198     cpl_propertylist_delete(paflist);
00199 
00200     return cpl_error_get_code();
00201 }
00202 
00203 /*----------------------------------------------------------------------------*/
00214 /*----------------------------------------------------------------------------*/
00215 static cpl_image * naco_img_lampflat_reduce(cpl_propertylist * qclist,
00216                                             const irplib_framelist * framelist,
00217                                             int rej_left, int rej_right,
00218                                             int rej_bottom, int rej_top)
00219 {
00220     int                     nfiles;
00221     cpl_image           *   image = NULL;
00222     cpl_image           *   aver = NULL;
00223     cpl_image           *   diff = NULL;
00224     cpl_image           *   prev = NULL;
00225     cpl_image           *   image0= NULL;
00226     double                  gain, fp_noise;
00227     double                  lamp_flux = DBL_MAX; /* Avoid uninit warning */
00228     double                  std_diff[3];
00229     double                  mean = DBL_MAX; /* Avoid uninit warning */
00230     double                  square;
00231     int                     i;
00232 
00233 
00234     bug_if (framelist == NULL);
00235 
00236     nfiles = irplib_framelist_get_size(framelist);
00237  
00238     /* At least 4 frames are requested for the gain computation */
00239     skip_if_lt(nfiles, 4, "frames");
00240 
00241     /* Verify that the number of frames is even */
00242     irplib_ensure (nfiles % 2 == 0, CPL_ERROR_ILLEGAL_INPUT,
00243                    "The number of frames must be even, not %d", nfiles);
00244 
00245     skip_if (irplib_framelist_contains(framelist, NACO_PFITS_DOUBLE_DIT,
00246                                        CPL_TYPE_DOUBLE, CPL_TRUE, 1e-5));
00247    
00248     skip_if (irplib_framelist_contains(framelist, NACO_PFITS_INT_LAMP2,
00249                                        CPL_TYPE_INT, CPL_FALSE, 0.0));
00250    
00251     /* Print out the file names */
00252     /* Verify that the frame sequence is lamp on - lamp off */
00253     for (i=0 ; i < nfiles ; i++) {
00254         const cpl_frame * frame = irplib_framelist_get_const(framelist, i);
00255         const char * name = cpl_frame_get_filename(frame);
00256         const cpl_propertylist * plist
00257             = irplib_framelist_get_propertylist_const(framelist, i);
00258         int ival;
00259 
00260         skip_if(name == NULL);
00261         skip_if(plist == NULL);
00262 
00263         if (i == 0) {
00264             /* Print out the filter used in this set of frames */
00265             const char * sval = naco_pfits_get_filter(plist);
00266 
00267             skip_if (0);
00268             cpl_msg_info(cpl_func, "Filter: [%s]", sval);
00269 
00270             /* Copy the required keys to the list of QC parameters */
00271             skip_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER OBS",
00272                                                    sval));
00273             sval = naco_pfits_get_opti3_name(plist);
00274             skip_if (0);
00275             skip_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER NDENS",
00276                                                    sval));
00277             sval = naco_pfits_get_opti4_name(plist);
00278             skip_if (0);
00279             skip_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER POL",
00280                                                    sval));
00281         }
00282 
00283         cpl_msg_info(cpl_func, "File %02d: %s", i+1, name);
00284 
00285         /* Get lamp info from frame 2*i */
00286         ival = naco_pfits_get_lamp2(plist);
00287         if (i % 2) {
00288             irplib_ensure (ival == 0, CPL_ERROR_ILLEGAL_INPUT,
00289                            "Frame number %d must have %s set to zero, not %d",
00290                             i+1, NACO_PFITS_INT_LAMP2, ival);
00291         } else {
00292             irplib_ensure (ival != 0, CPL_ERROR_ILLEGAL_INPUT,
00293                            "Frame number %d must have a non-zero %s",
00294                             i+1, NACO_PFITS_INT_LAMP2);
00295         }
00296 
00297         irplib_check(image = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0),
00298                      "Could not load FITS-image from %s", name);
00299 
00300         if (i == 0) {
00301             irplib_check(mean = cpl_image_get_mean(image),
00302                 "Could not compute mean");
00303             image0 = image;
00304         } else if (i <= 3) {
00305             const int ifirst = i == 3 ? 1 : 0;
00306             double noise;
00307             /* Compute noise on : on1 - off1 */
00308             /* Compute noise on : on1 - on2 */
00309             /* Compute noise on : off1 - off2 */
00310             irplib_check(diff = cpl_image_subtract_create(image0, image),
00311                          "Could not subtract the images %d and %d",
00312                           ifirst+1, i+1);
00313 
00314             irplib_check(cpl_flux_get_noise_window(diff, NULL, -1, -1,
00315                                                    &noise, NULL),
00316                          "Could not compute noise on difference between"
00317                           " images %d and %d", ifirst+1, i+1);
00318 
00319             std_diff[i-1] = noise * noise;
00320 
00321             if (i == 1) {
00322                 /* LAMPFLUX */
00323                 /* Print out the filter used in this set of frames */
00324                 const double median = cpl_image_get_median(diff);
00325                 const double ditval = naco_pfits_get_dit(plist);
00326 
00327                 skip_if (cpl_error_get_code());
00328                 skip_if (ditval <= 0.0);
00329 
00330                 lamp_flux = median / ditval;
00331 
00332                 /* The 1st contribution to the average of differences */
00333                 aver = diff;
00334 
00335             } else {
00336                 cpl_image_delete(diff);
00337                 diff = NULL;
00338                  /* Finished with image[i-2] */
00339                 cpl_image_delete(image0);
00340                 /* Update image0 - to either image[i-1] or none */
00341                 image0 = i == 2 ? prev : NULL;
00342             }
00343 
00344         }
00345 
00346         if (i > 1 && i % 2 != 0) {
00347             /* Compute the dark subtraction */
00348             irplib_check(cpl_image_subtract(prev, image),
00349                          "Could not correct for the dark");
00350 
00351             /* Sum up the dark corrected frames */
00352             irplib_check(cpl_image_add(aver, prev),
00353                          "Could not sum up the dark corrected images");
00354 
00355             cpl_image_delete(image);
00356             cpl_image_delete(prev);
00357             prev = NULL;
00358         } else {
00359             prev = image;
00360         }
00361         image = NULL;
00362     }
00363 
00364     /* Compute the QC parameters */
00365     cpl_msg_info(cpl_func, "Computing the QC parameters");
00366 
00367     /* Deduce GAIN */
00368     square = std_diff[1] - std_diff[2];
00369     if (square != 0.0) square = 2.0*mean/square;
00370     gain = square > 0.0 ? sqrt(square) : 0.0;
00371     
00372     /* Deduce FPNOISE */
00373     square = std_diff[0] - std_diff[1] - std_diff[2];
00374     fp_noise = square > 0.0 ? sqrt(square) : 0.0;
00375 
00376     /* Print results */
00377     cpl_msg_info(cpl_func, "Gain:      %g", gain);
00378     cpl_msg_info(cpl_func, "Noise:     %g", fp_noise);
00379     cpl_msg_info(cpl_func, "Lamp flux: %g", lamp_flux);
00380 
00381     /* Average the dark corrected frames */
00382     cpl_msg_info(cpl_func, "Average the dark corrected frames");
00383     irplib_check(cpl_image_divide_scalar(aver, (double)(nfiles/2)),
00384                  "Could not average the %d dark corrected frames", nfiles/2);
00385 
00386     /* Normalize the flat */
00387     irplib_check(mean
00388                  = cpl_image_get_mean_window(aver, rej_left,
00389                                              cpl_image_get_size_x(aver)
00390                                              -rej_right,
00391                                              rej_bottom,
00392                                              cpl_image_get_size_y(aver)
00393                                              -rej_top);
00394                  cpl_image_divide_scalar(aver, mean),
00395                  "Could not average the %d dark corrected frames", nfiles/2);
00396 
00397     /* Add QC parameters */
00398     skip_if(cpl_propertylist_append_double(qclist, "ESO QC GAIN", gain));
00399     skip_if(cpl_propertylist_append_double(qclist, "ESO QC FPNOISE", fp_noise));
00400     skip_if(cpl_propertylist_append_double(qclist, "ESO QC LAMPFLUX",
00401                                            lamp_flux));
00402 
00403     end_skip;
00404 
00405     if (cpl_error_get_code()) {
00406         cpl_image_delete(aver);
00407         aver = NULL;
00408     }
00409 
00410     cpl_image_delete(image);
00411     cpl_image_delete(diff);
00412     cpl_image_delete(prev);
00413     cpl_image_delete(image0);
00414 
00415     return aver;
00416 }
00417 
00418 
00419 /*----------------------------------------------------------------------------*/
00427 /*----------------------------------------------------------------------------*/
00428 static cpl_error_code naco_img_lampflat_qc(cpl_propertylist       * qclist,
00429                                            cpl_propertylist       * paflist,
00430                                            const irplib_framelist * rawframes)
00431 {
00432 
00433     const cpl_propertylist * reflist
00434         = irplib_framelist_get_propertylist_const(rawframes, 0);
00435     const char pafcopy[] = "^(" NACO_PFITS_REGEXP_LAMPFLAT_PAF ")$";
00436 
00437 
00438     bug_if (0);
00439 
00440 
00441     /* THE PAF FILE FOR QC PARAMETERS */
00442     skip_if (cpl_propertylist_copy_property_regexp(paflist, reflist, pafcopy,
00443                                                    0));
00444     skip_if (cpl_propertylist_append(paflist, qclist));
00445 
00446     bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist, "^("
00447                                                   IRPLIB_PFITS_REGEXP_RECAL 
00448                                                   ")$", 0));
00449 
00450     bug_if (irplib_pfits_set_airmass(qclist, rawframes));
00451 
00452     end_skip;
00453 
00454     return cpl_error_get_code();
00455 }
00456 
00457 /*----------------------------------------------------------------------------*/
00469 /*----------------------------------------------------------------------------*/
00470 static cpl_error_code naco_img_lampflat_save(cpl_frameset            * set_tot,
00471                                              const cpl_parameterlist * parlist,
00472                                              const cpl_propertylist  * qclist,
00473                                              const cpl_propertylist  * paflist,
00474                                              const cpl_image         * flat,
00475                                              int                       set_nb,
00476                                              const irplib_framelist  * rawframes)
00477 {
00478     cpl_frameset * proframes = irplib_frameset_cast(rawframes);
00479     char         * filename  = NULL;
00480 
00481 
00482 
00483     /* This will catch rawframes == NULL */
00484     bug_if (0);
00485 
00486     /* SAVE THE COMBINED IMAGE */
00487     filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_FITS, set_nb);
00488     skip_if (irplib_dfs_save_image(set_tot, parlist, proframes, flat,
00489                                CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
00490                                NACO_IMG_LAMPFLAT_RES, qclist, NULL,
00491                                naco_pipe_id, filename));
00492 
00493     cpl_free(filename);
00494     filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_PAF, set_nb);
00495     skip_if (cpl_dfs_save_paf("NACO", RECIPE_STRING, paflist, filename));
00496 
00497     end_skip;
00498 
00499     cpl_free(filename);
00500     cpl_frameset_delete(proframes);
00501 
00502     return cpl_error_get_code();
00503 
00504 }
00505 
00506 
00507 /*----------------------------------------------------------------------------*/
00517 /*----------------------------------------------------------------------------*/
00518 static char * naco_img_lampflat_make_tag(const cpl_frame* self,
00519                                          const cpl_propertylist * plist,
00520                                          int dummy)
00521 {
00522 
00523     char       * tag = NULL;
00524     const char * filter;
00525     const char * opti3;
00526     const char * opti7;
00527     const char * rom;
00528     const char * mode;
00529     double       dit;
00530 
00531 
00532     skip_if (cpl_error_get_code());
00533 
00534     skip_if(self  == NULL);
00535     skip_if(plist == NULL);
00536     skip_if(dummy < 0); /* Avoid warning of unused variable */
00537 
00538 
00539     /* filters */
00540     filter = naco_pfits_get_filter(plist);
00541     skip_if(cpl_error_get_code());
00542  
00543     /* the objective */
00544     opti7 = naco_pfits_get_opti7_name(plist);
00545     skip_if(cpl_error_get_code());
00546  
00547     /* the OPTI3_NAME */
00548     opti3 = naco_pfits_get_opti3_name(plist);
00549     skip_if(cpl_error_get_code());
00550 
00551     /* the ROM */
00552     rom = naco_pfits_get_rom_name(plist);
00553     skip_if(cpl_error_get_code());
00554 
00555     /* the mode */
00556     mode = naco_pfits_get_mode(plist);
00557     skip_if(cpl_error_get_code());
00558 
00559     /* Compare the DIT */
00560     dit  = naco_pfits_get_dit(plist);
00561     skip_if(cpl_error_get_code());
00562 
00563 
00564     tag = cpl_sprintf("%s:%s:%s:%s:%s:%.5f", filter,
00565                                         opti7, opti3, rom, mode, dit);
00566     bug_if(tag == NULL);
00567 
00568     end_skip;
00569 
00570     if (cpl_error_get_code()) {
00571         cpl_free(tag);
00572         tag = NULL;
00573     }
00574 
00575     return tag;
00576 
00577 }

Generated on Fri Jul 3 11:23:58 2009 for NACO Pipeline Reference Manual by  doxygen 1.5.8