naco_img_lampflat.c

00001 /* $Id: naco_img_lampflat.c,v 1.60 2010/03/04 15:57:20 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: 2010/03/04 15:57:20 $
00024  * $Revision: 1.60 $
00025  * $Name: naco-4_3_0 $
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             /* PRO.CATG */
00176             bug_if(cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
00177                                                   NACO_IMG_LAMPFLAT_RES));
00178             skip_if(naco_img_lampflat_save(framelist, parlist, qclist, paflist,
00179                                            lamp_flat, i+1, f_one));
00180             cpl_image_delete(lamp_flat);
00181             lamp_flat = NULL;
00182             nb_good++;
00183         }
00184         cpl_propertylist_empty(qclist);
00185         cpl_propertylist_empty(paflist);
00186         irplib_framelist_delete(f_one);
00187         f_one = NULL;
00188     }
00189 
00190     irplib_ensure(nb_good > 0, CPL_ERROR_DATA_NOT_FOUND,
00191                   "None of the %d sets could be reduced", nsets);
00192     
00193     end_skip;
00194 
00195     cpl_free(taglist);
00196     cpl_image_delete(lamp_flat);
00197     irplib_framelist_delete(f_one);
00198     irplib_framelist_delete(allframes);
00199     irplib_framelist_delete(rawframes);
00200     cpl_propertylist_delete(qclist);
00201     cpl_propertylist_delete(paflist);
00202 
00203     return cpl_error_get_code();
00204 }
00205 
00206 /*----------------------------------------------------------------------------*/
00217 /*----------------------------------------------------------------------------*/
00218 static cpl_image * naco_img_lampflat_reduce(cpl_propertylist * qclist,
00219                                             const irplib_framelist * framelist,
00220                                             int rej_left, int rej_right,
00221                                             int rej_bottom, int rej_top)
00222 {
00223     int                     nfiles;
00224     cpl_image           *   image = NULL;
00225     cpl_image           *   aver = NULL;
00226     cpl_image           *   diff = NULL;
00227     cpl_image           *   prev = NULL;
00228     cpl_image           *   image0= NULL;
00229     double                  gain, fp_noise;
00230     double                  lamp_flux = DBL_MAX; /* Avoid uninit warning */
00231     double                  std_diff[3];
00232     double                  mean = DBL_MAX; /* Avoid uninit warning */
00233     double                  square;
00234     int                     i;
00235 
00236 
00237     bug_if (framelist == NULL);
00238 
00239     nfiles = irplib_framelist_get_size(framelist);
00240  
00241     /* At least 4 frames are requested for the gain computation */
00242     skip_if_lt(nfiles, 4, "frames");
00243 
00244     /* Verify that the number of frames is even */
00245     irplib_ensure (nfiles % 2 == 0, CPL_ERROR_ILLEGAL_INPUT,
00246                    "The number of frames must be even, not %d", nfiles);
00247 
00248     skip_if (irplib_framelist_contains(framelist, NACO_PFITS_DOUBLE_DIT,
00249                                        CPL_TYPE_DOUBLE, CPL_TRUE, 1e-5));
00250    
00251     skip_if (irplib_framelist_contains(framelist, NACO_PFITS_INT_LAMP2,
00252                                        CPL_TYPE_INT, CPL_FALSE, 0.0));
00253    
00254     /* Print out the file names */
00255     /* Verify that the frame sequence is lamp on - lamp off */
00256     for (i=0 ; i < nfiles ; i++) {
00257         const cpl_frame * frame = irplib_framelist_get_const(framelist, i);
00258         const char * name = cpl_frame_get_filename(frame);
00259         const cpl_propertylist * plist
00260             = irplib_framelist_get_propertylist_const(framelist, i);
00261         int ival;
00262 
00263         skip_if(name == NULL);
00264         skip_if(plist == NULL);
00265 
00266         if (i == 0) {
00267             /* Print out the filter used in this set of frames */
00268             const char * sval = naco_pfits_get_filter(plist);
00269 
00270             skip_if (0);
00271             cpl_msg_info(cpl_func, "Filter: [%s]", sval);
00272 
00273             /* Copy the required keys to the list of QC parameters */
00274             skip_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER OBS",
00275                                                    sval));
00276             sval = naco_pfits_get_opti3_name(plist);
00277             skip_if (0);
00278             skip_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER NDENS",
00279                                                    sval));
00280             sval = naco_pfits_get_opti4_name(plist);
00281             skip_if (0);
00282             skip_if(cpl_propertylist_append_string(qclist, "ESO QC FILTER POL",
00283                                                    sval));
00284         }
00285 
00286         cpl_msg_info(cpl_func, "File %02d: %s", i+1, name);
00287 
00288         /* Get lamp info from frame 2*i */
00289         ival = naco_pfits_get_lamp2(plist);
00290         if (i % 2) {
00291             irplib_ensure (ival == 0, CPL_ERROR_ILLEGAL_INPUT,
00292                            "Frame number %d must have %s set to zero, not %d",
00293                             i+1, NACO_PFITS_INT_LAMP2, ival);
00294         } else {
00295             irplib_ensure (ival != 0, CPL_ERROR_ILLEGAL_INPUT,
00296                            "Frame number %d must have a non-zero %s",
00297                             i+1, NACO_PFITS_INT_LAMP2);
00298         }
00299 
00300         irplib_check(image = cpl_image_load(name, CPL_TYPE_FLOAT, 0, 0),
00301                      "Could not load FITS-image from %s", name);
00302 
00303         if (i == 0) {
00304             irplib_check(mean = cpl_image_get_mean(image),
00305                 "Could not compute mean");
00306             image0 = image; image = NULL;
00307         } else if (i <= 3) {
00308             const int ifirst = i == 3 ? 1 : 0;
00309             double noise;
00310             /* Compute noise on : on1 - off1 */
00311             /* Compute noise on : on1 - on2 */
00312             /* Compute noise on : off1 - off2 */
00313             irplib_check(diff = cpl_image_subtract_create(image0, image),
00314                          "Could not subtract the images %d and %d",
00315                           ifirst+1, i+1);
00316 
00317             irplib_check(cpl_flux_get_noise_window(diff, NULL, -1, -1,
00318                                                    &noise, NULL),
00319                          "Could not compute noise on difference between"
00320                           " images %d and %d", ifirst+1, i+1);
00321 
00322             std_diff[i-1] = noise * noise;
00323 
00324             if (i == 1) {
00325                 /* LAMPFLUX */
00326                 /* Print out the filter used in this set of frames */
00327                 const double median = cpl_image_get_median(diff);
00328                 const double ditval = naco_pfits_get_dit(plist);
00329 
00330                 skip_if (cpl_error_get_code());
00331                 skip_if (ditval <= 0.0);
00332 
00333                 lamp_flux = median / ditval;
00334 
00335                 /* The 1st contribution to the average of differences */
00336                 aver = diff;
00337 
00338             } else {
00339                 cpl_image_delete(diff);
00340                 diff = NULL;
00341                  /* Finished with image[i-2] */
00342                 cpl_image_delete(image0);
00343                 /* Update image0 - to either image[i-1] or none */
00344                 image0 = i == 2 ? prev : NULL;
00345             }
00346 
00347         }
00348 
00349         if (i > 1 && i % 2 != 0) {
00350             /* Compute the dark subtraction */
00351             irplib_check(cpl_image_subtract(prev, image),
00352                          "Could not correct for the dark");
00353 
00354             /* Sum up the dark corrected frames */
00355             irplib_check(cpl_image_add(aver, prev),
00356                          "Could not sum up the dark corrected images");
00357 
00358             cpl_image_delete(image);
00359             cpl_image_delete(prev);
00360             prev = NULL;
00361         } else {
00362             prev = image;
00363         }
00364         image = NULL;
00365     }
00366 
00367     /* Compute the QC parameters */
00368     cpl_msg_info(cpl_func, "Computing the QC parameters");
00369 
00370     /* Deduce GAIN */
00371     square = std_diff[1] - std_diff[2];
00372     if (square != 0.0) square = 2.0*mean/square;
00373     gain = square > 0.0 ? sqrt(square) : 0.0;
00374     
00375     /* Deduce FPNOISE */
00376     square = std_diff[0] - std_diff[1] - std_diff[2];
00377     fp_noise = square > 0.0 ? sqrt(square) : 0.0;
00378 
00379     /* Print results */
00380     cpl_msg_info(cpl_func, "Gain:      %g", gain);
00381     cpl_msg_info(cpl_func, "Noise:     %g", fp_noise);
00382     cpl_msg_info(cpl_func, "Lamp flux: %g", lamp_flux);
00383 
00384     /* Average the dark corrected frames */
00385     cpl_msg_info(cpl_func, "Average the dark corrected frames");
00386     irplib_check(cpl_image_divide_scalar(aver, (double)(nfiles/2)),
00387                  "Could not average the %d dark corrected frames", nfiles/2);
00388 
00389     /* Normalize the flat */
00390     irplib_check(mean
00391                  = cpl_image_get_mean_window(aver, rej_left,
00392                                              cpl_image_get_size_x(aver)
00393                                              -rej_right,
00394                                              rej_bottom,
00395                                              cpl_image_get_size_y(aver)
00396                                              -rej_top);
00397                  cpl_image_divide_scalar(aver, mean),
00398                  "Could not average the %d dark corrected frames", nfiles/2);
00399 
00400     /* Add QC parameters */
00401     skip_if(cpl_propertylist_append_double(qclist, "ESO QC GAIN", gain));
00402     skip_if(cpl_propertylist_append_double(qclist, "ESO QC FPNOISE", fp_noise));
00403     skip_if(cpl_propertylist_append_double(qclist, "ESO QC LAMPFLUX",
00404                                            lamp_flux));
00405 
00406     end_skip;
00407 
00408     if (cpl_error_get_code()) {
00409         cpl_image_delete(aver);
00410         aver = NULL;
00411     }
00412 
00413     cpl_image_delete(image);
00414     cpl_image_delete(diff);
00415     cpl_image_delete(prev);
00416     cpl_image_delete(image0);
00417 
00418     return aver;
00419 }
00420 
00421 
00422 /*----------------------------------------------------------------------------*/
00430 /*----------------------------------------------------------------------------*/
00431 static cpl_error_code naco_img_lampflat_qc(cpl_propertylist       * qclist,
00432                                            cpl_propertylist       * paflist,
00433                                            const irplib_framelist * rawframes)
00434 {
00435 
00436     const cpl_propertylist * reflist
00437         = irplib_framelist_get_propertylist_const(rawframes, 0);
00438     const char pafcopy[] = "^(" NACO_PFITS_REGEXP_LAMPFLAT_PAF ")$";
00439 
00440 
00441     bug_if (0);
00442 
00443 
00444     /* THE PAF FILE FOR QC PARAMETERS */
00445     skip_if (cpl_propertylist_copy_property_regexp(paflist, reflist, pafcopy,
00446                                                    0));
00447     skip_if (cpl_propertylist_append(paflist, qclist));
00448 
00449     bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist, "^("
00450                                                   IRPLIB_PFITS_REGEXP_RECAL 
00451                                                   ")$", 0));
00452 
00453     bug_if (irplib_pfits_set_airmass(qclist, rawframes));
00454 
00455     end_skip;
00456 
00457     return cpl_error_get_code();
00458 }
00459 
00460 /*----------------------------------------------------------------------------*/
00472 /*----------------------------------------------------------------------------*/
00473 static cpl_error_code naco_img_lampflat_save(cpl_frameset            * set_tot,
00474                                              const cpl_parameterlist * parlist,
00475                                              const cpl_propertylist  * qclist,
00476                                              const cpl_propertylist  * paflist,
00477                                              const cpl_image         * flat,
00478                                              int                       set_nb,
00479                                              const irplib_framelist  * rawframes)
00480 {
00481     cpl_frameset * proframes = irplib_frameset_cast(rawframes);
00482     char         * filename  = NULL;
00483 
00484 
00485 
00486     /* This will catch rawframes == NULL */
00487     bug_if (0);
00488 
00489     /* SAVE THE COMBINED IMAGE */
00490     filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_FITS, set_nb);
00491     skip_if (irplib_dfs_save_image(set_tot, parlist, proframes, flat,
00492                                CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
00493                                NACO_IMG_LAMPFLAT_RES, qclist, NULL,
00494                                naco_pipe_id, filename));
00495 
00496 #ifdef NACO_SAVE_PAF
00497     cpl_free(filename);
00498     filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_PAF, set_nb);
00499     skip_if (cpl_dfs_save_paf("NACO", RECIPE_STRING, paflist, filename));
00500 #else
00501     bug_if(paflist == NULL);
00502 #endif
00503 
00504     end_skip;
00505 
00506     cpl_free(filename);
00507     cpl_frameset_delete(proframes);
00508 
00509     return cpl_error_get_code();
00510 
00511 }
00512 
00513 
00514 /*----------------------------------------------------------------------------*/
00524 /*----------------------------------------------------------------------------*/
00525 static char * naco_img_lampflat_make_tag(const cpl_frame* self,
00526                                          const cpl_propertylist * plist,
00527                                          int dummy)
00528 {
00529 
00530     char       * tag = NULL;
00531     const char * filter;
00532     const char * opti3;
00533     const char * opti7;
00534     const char * rom;
00535     const char * mode;
00536     double       dit;
00537 
00538 
00539     skip_if (cpl_error_get_code());
00540 
00541     skip_if(self  == NULL);
00542     skip_if(plist == NULL);
00543     skip_if(dummy < 0); /* Avoid warning of unused variable */
00544 
00545 
00546     /* filters */
00547     filter = naco_pfits_get_filter(plist);
00548     skip_if(cpl_error_get_code());
00549  
00550     /* the objective */
00551     opti7 = naco_pfits_get_opti7_name(plist);
00552     skip_if(cpl_error_get_code());
00553  
00554     /* the OPTI3_NAME */
00555     opti3 = naco_pfits_get_opti3_name(plist);
00556     skip_if(cpl_error_get_code());
00557 
00558     /* the ROM */
00559     rom = naco_pfits_get_rom_name(plist);
00560     skip_if(cpl_error_get_code());
00561 
00562     /* the mode */
00563     mode = naco_pfits_get_mode(plist);
00564     skip_if(cpl_error_get_code());
00565 
00566     /* Compare the DIT */
00567     dit  = naco_pfits_get_dit(plist);
00568     skip_if(cpl_error_get_code());
00569 
00570 
00571     tag = cpl_sprintf("%s:%s:%s:%s:%s:%.5f", filter,
00572                                         opti7, opti3, rom, mode, dit);
00573     bug_if(tag == NULL);
00574 
00575     end_skip;
00576 
00577     if (cpl_error_get_code()) {
00578         cpl_free(tag);
00579         tag = NULL;
00580     }
00581 
00582     return tag;
00583 
00584 }

Generated on Mon Feb 6 14:42:07 2012 for NACO Pipeline Reference Manual by  doxygen 1.5.8