naco_spc_lampflat.c

00001 /* $Id: naco_spc_lampflat.c,v 1.21 2011/12/22 11:21:03 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: 2011/12/22 11:21:03 $
00024  * $Revision: 1.21 $
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 #include "naco_spc.h"
00039 
00040 /*-----------------------------------------------------------------------------
00041                             Recipe defines
00042  -----------------------------------------------------------------------------*/
00043 
00044 #define RECIPE_STRING   "naco_spc_lampflat"
00045 
00046 #ifndef NACO_SPC_MEDIAN_XSIZE
00047 #define NACO_SPC_MEDIAN_XSIZE        200
00048 #endif
00049 
00050 #ifndef NACO_SPC_MEDIAN_YSIZE
00051 #define NACO_SPC_MEDIAN_YSIZE  NACO_SPC_MEDIAN_XSIZE
00052 #endif
00053 
00054 /*-----------------------------------------------------------------------------
00055                             Private Functions prototypes
00056  -----------------------------------------------------------------------------*/
00057 
00058 static cpl_image * naco_spc_lampflat_reduce(cpl_propertylist *,
00059                                             const irplib_framelist *,
00060                                             const cpl_parameterlist *);
00061 
00062 static cpl_error_code naco_spc_lampflat_qc(cpl_propertylist *,
00063                                            cpl_propertylist *,
00064                                            const irplib_framelist *);
00065 
00066 static cpl_error_code naco_spc_lampflat_save(cpl_frameset *,
00067                                              const cpl_parameterlist *,
00068                                              const cpl_propertylist *,
00069                                              const cpl_propertylist *,
00070                                              const cpl_image *,
00071                                              int, const irplib_framelist *);
00072 
00073 NACO_RECIPE_DEFINE(naco_spc_lampflat,
00074                    NACO_PARAM_REJBORD | NACO_PARAM_HOT_LIM | NACO_PARAM_COLD_LIM,
00075                    "Spectrocopic flat recipe using a lamp",
00076                    RECIPE_STRING " -- NACO spectrocopy flat-field creation from "
00077                    "lamp images.\n" 
00078                    "The files listed in the Set Of Frames (sof-file) "
00079                    "must be tagged:\n" 
00080                    "NACO-raw-file.fits " NACO_SPC_LAMPFLAT_RAW "\n"
00081                    "\n"
00082                    NACO_SPC_MAN_MODESPLIT "\n\n"
00083                    "Furthermore, the input set of frames must have values of "
00084                    "the FITS key " 
00085                    NACO_PFITS_INT_LAMP2 " that of zero for off-frames and "
00086                    "non-zero for on-frames.\n");
00087 
00088 
00089 /*----------------------------------------------------------------------------*/
00093 /*----------------------------------------------------------------------------*/
00094 
00095 /*-----------------------------------------------------------------------------
00096                                 Functions code
00097  -----------------------------------------------------------------------------*/
00098 
00099 /*----------------------------------------------------------------------------*/
00106 /*----------------------------------------------------------------------------*/
00107 static int naco_spc_lampflat(cpl_frameset            * framelist,
00108                              const cpl_parameterlist * parlist)
00109 {
00110     cpl_errorstate cleanstate = cpl_errorstate_get();
00111     irplib_framelist * allframes = NULL;
00112     irplib_framelist * rawframes = NULL;
00113     irplib_framelist * f_one     = NULL;
00114     const char      ** taglist   = NULL;
00115     cpl_image        * lamp_flat = NULL;
00116     cpl_propertylist * qclist  = cpl_propertylist_new();
00117     cpl_propertylist * paflist = cpl_propertylist_new();
00118     int                nb_good = 0;
00119     int                nsets;
00120     int                i;
00121     
00122 
00123     /* Identify the RAW and CALIB frames in the input frameset */
00124     skip_if (naco_dfs_set_groups(framelist));
00125 
00126     allframes = irplib_framelist_cast(framelist);
00127     skip_if(allframes == NULL);
00128 
00129     rawframes = irplib_framelist_extract(allframes, NACO_SPC_LAMPFLAT_RAW);
00130     skip_if(rawframes == NULL);
00131     irplib_framelist_empty(allframes);
00132 
00133     skip_if(irplib_framelist_load_propertylist_all(rawframes, 0, "^("
00134                                                    NACO_PFITS_REGEXP_SPCFLAT "|"
00135                                                    NACO_PFITS_REGEXP_SPCFLAT_PAF
00136                                                    ")$", CPL_FALSE));
00137 
00138     taglist = naco_framelist_set_tag(rawframes, naco_spc_make_tag, &nsets);
00139     skip_if(taglist == NULL);
00140 
00141     cpl_msg_info(cpl_func, "Identified %d setting(s) in %d frames",
00142                  nsets, irplib_framelist_get_size(rawframes));
00143 
00144     /* Extract settings and reduce each of them */
00145     for (i=0 ; i < nsets ; i++) {
00146 
00147         /* Reduce data set nb i */
00148         cpl_msg_info(cpl_func, "Reducing data set %d of %d", i+1, nsets);
00149 
00150         /* Reduce data set nb i */
00151         f_one = irplib_framelist_extract(rawframes, taglist[i]);
00152 
00153         /* Reset the tag */
00154         skip_if(irplib_framelist_set_tag_all(f_one, NACO_SPC_LAMPFLAT_RAW));
00155 
00156         cpl_msg_info(cpl_func, "Reducing frame set %d of %d (size=%d) with "
00157                      "setting: %s", i+1, nsets,
00158                      irplib_framelist_get_size(f_one), taglist[i]);
00159 
00160         skip_if (f_one == NULL);
00161         
00162         lamp_flat = naco_spc_lampflat_reduce(qclist, f_one, parlist);
00163         
00164         /* Save the products */
00165         if (lamp_flat == NULL) {
00166             if (nsets > 1)
00167                 irplib_error_recover(cleanstate, "Could not compute the flat for "
00168                                  "this setting");
00169         } else {
00170             skip_if(naco_spc_lampflat_qc(qclist, paflist, f_one));
00171             /* PRO.CATG */
00172             bug_if (cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
00173                                                    NACO_CALIB_SPCFLAT));
00174             skip_if(naco_spc_lampflat_save(framelist, parlist, qclist, paflist,
00175                                            lamp_flat, i+1, f_one));
00176             cpl_image_delete(lamp_flat);
00177             lamp_flat = NULL;
00178             nb_good++;
00179         }
00180         cpl_propertylist_empty(qclist);
00181         cpl_propertylist_empty(paflist);
00182         irplib_framelist_delete(f_one);
00183         f_one = NULL;
00184     }
00185 
00186     irplib_ensure(nb_good > 0, CPL_ERROR_DATA_NOT_FOUND,
00187                   "None of the %d sets could be reduced", nsets);
00188     
00189     end_skip;
00190 
00191     cpl_free(taglist);
00192     cpl_image_delete(lamp_flat);
00193     irplib_framelist_delete(f_one);
00194     irplib_framelist_delete(allframes);
00195     irplib_framelist_delete(rawframes);
00196     cpl_propertylist_delete(qclist);
00197     cpl_propertylist_delete(paflist);
00198 
00199     return cpl_error_get_code();
00200 }
00201 
00202 /*----------------------------------------------------------------------------*/
00210 /*----------------------------------------------------------------------------*/
00211 static cpl_image * naco_spc_lampflat_reduce(cpl_propertylist * qclist,
00212                                             const irplib_framelist * framelist,
00213                                             const cpl_parameterlist * parlist)
00214 {
00215     cpl_image     * self = NULL;
00216     cpl_imagelist * difflist = cpl_imagelist_new();
00217     cpl_mask      * bpm = NULL;
00218     cpl_vector    * medians = NULL;
00219     const double    hot_thresh
00220         = naco_parameterlist_get_double(parlist, RECIPE_STRING,
00221                                         NACO_PARAM_HOT_LIM);
00222     const double    cold_thresh = 1.0 /
00223         naco_parameterlist_get_double(parlist, RECIPE_STRING,
00224                                       NACO_PARAM_COLD_LIM);
00225     const char    * rej_bord
00226         = naco_parameterlist_get_string(parlist, RECIPE_STRING,
00227                                         NACO_PARAM_REJBORD);
00228     cpl_propertylist * lampkeys = cpl_propertylist_new();
00229     int             rej_left, rej_right, rej_bottom, rej_top;
00230     int             nflat, nbad;
00231     int             ndiff, idiff;
00232 
00233 
00234     skip_if (0);
00235     bug_if (qclist    == NULL);
00236     bug_if (framelist == NULL);
00237     bug_if (parlist == NULL);
00238 
00239     skip_if(cold_thresh <= 0.0);
00240     skip_if(cold_thresh >= 1.0);
00241     skip_if(hot_thresh  <= 1.0);
00242 
00243     skip_if (sscanf(rej_bord, "%d %d %d %d",
00244                     &rej_left, &rej_right, &rej_bottom, &rej_top) != 4);
00245 
00246     /* On-frames have lamp2 on and lamp1 off */
00247     bug_if(cpl_propertylist_append_int(lampkeys, NACO_PFITS_INT_LAMP2,  1));
00248     bug_if(cpl_propertylist_append_int(lampkeys, NACO_PFITS_BOOL_LAMP1, 0));
00249   
00250     skip_if(naco_imagelist_load_diff(difflist, framelist, lampkeys));
00251 
00252     ndiff = cpl_imagelist_get_size(difflist);
00253 
00254     medians = cpl_vector_new(ndiff);
00255 
00256     bug_if(0);
00257 
00258     for (idiff = 0, nflat = 0; idiff < ndiff; idiff++) {
00259         cpl_image       * diff = cpl_imagelist_get(difflist, nflat);
00260         const int         nx   = cpl_image_get_size_x(diff);
00261         const int         ny   = cpl_image_get_size_y(diff);
00262 
00263         double            median;
00264         const double      mean
00265             = cpl_image_get_mean_window(diff,
00266                                         rej_left,   nx - rej_right,
00267                                         rej_bottom, ny - rej_top);
00268 
00269         skip_if(0);
00270 
00271         if (mean <= 0.0) {
00272             cpl_msg_warning(cpl_func, "Ignoring difference image %d with an "
00273                             "invalid mean: %g", 1+idiff, mean);
00274             cpl_image_delete(cpl_imagelist_unset(difflist, nflat));
00275             continue;
00276         }
00277 
00278         /* Get the median of the central region */
00279         median = cpl_image_get_median_window(diff, 
00280                                              (nx-NACO_SPC_MEDIAN_XSIZE)/2,
00281                                              (ny-NACO_SPC_MEDIAN_YSIZE)/2,
00282                                              (nx+NACO_SPC_MEDIAN_XSIZE)/2,
00283                                              (ny+NACO_SPC_MEDIAN_YSIZE)/2);
00284         skip_if(0);
00285 
00286         /* Normalize the difference image */
00287         bug_if(cpl_image_divide_scalar(diff, mean));
00288 
00289         /* Find non-hot/cold pixels */
00290         bpm = cpl_mask_threshold_image_create(diff, cold_thresh, hot_thresh);
00291         bug_if(bpm == NULL);
00292 
00293         if (cpl_mask_is_empty(bpm)) {
00294             cpl_msg_warning(cpl_func, "Ignoring difference image %d with no "
00295                             "good pixels", 1+idiff);
00296             cpl_mask_delete(bpm);
00297             bpm = NULL;
00298             cpl_image_delete(cpl_imagelist_unset(difflist, nflat));
00299             continue;
00300         }
00301 
00302         bug_if(cpl_mask_not(bpm));
00303 
00304         cpl_msg_info(cpl_func, "Difference image %d has %d bad pixels", 1+idiff,
00305                      (int)cpl_mask_count(bpm));
00306 
00307         /* Reject hot and cold pixels */
00308         bug_if(cpl_mask_or(cpl_image_get_bpm(diff), bpm));
00309 
00310         cpl_mask_delete(bpm);
00311         bpm = NULL;
00312 
00313         bug_if (cpl_vector_set(medians, nflat, median));
00314 
00315         nflat++;
00316     }
00317 
00318     bug_if(nflat != cpl_imagelist_get_size(difflist));
00319 
00320     error_if(nflat == 0, CPL_ERROR_DATA_NOT_FOUND,
00321              "The %d difference images are all invalid", ndiff);
00322 
00323     self = cpl_imagelist_collapse_create(difflist);
00324     bug_if(0);
00325 
00326     nbad =  cpl_image_count_rejected(self);
00327     bug_if(0);
00328 
00329     if (nbad > 0) {
00330         cpl_msg_info(cpl_func, "Setting %d bad pixels in master flat to 1.0",
00331                      nbad);
00332         bug_if(cpl_image_fill_rejected(self, 1.0));
00333     }
00334 
00335     bug_if(cpl_vector_set_size(medians, nflat));
00336 
00337     bug_if(cpl_propertylist_append_double(qclist, "ESO QC SPECFLAT NCOUNTS",
00338                                           cpl_vector_get_mean(medians)));
00339     bug_if(cpl_propertylist_append_double(qclist, "ESO QC SPECFLAT STDEV",
00340                                           cpl_vector_get_stdev(medians)));
00341 
00342     end_skip;
00343 
00344     if (cpl_error_get_code()) {
00345         cpl_image_delete(self);
00346         self = NULL;
00347     }
00348 
00349     cpl_propertylist_delete(lampkeys);
00350     cpl_imagelist_delete(difflist);
00351     cpl_mask_delete(bpm);
00352     cpl_vector_delete(medians);
00353 
00354     return self;
00355 }
00356 
00357 
00358 /*----------------------------------------------------------------------------*/
00366 /*----------------------------------------------------------------------------*/
00367 static cpl_error_code naco_spc_lampflat_qc(cpl_propertylist       * qclist,
00368                                            cpl_propertylist       * paflist,
00369                                            const irplib_framelist * rawframes)
00370 {
00371 
00372     const cpl_propertylist * reflist
00373         = irplib_framelist_get_propertylist_const(rawframes, 0);
00374     const char pafcopy[] = "^(" NACO_PFITS_REGEXP_SPCFLAT_PAF ")$";
00375 
00376 
00377     bug_if (0);
00378 
00379 
00380     /* THE PAF FILE FOR QC PARAMETERS */
00381     skip_if (cpl_propertylist_copy_property_regexp(paflist, reflist, pafcopy,
00382                                                    0));
00383     skip_if (cpl_propertylist_append(paflist, qclist));
00384 
00385     bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist, "^("
00386                                                   IRPLIB_PFITS_REGEXP_RECAL_LAMP
00387                                                   ")$", 0));
00388 
00389     end_skip;
00390 
00391     return cpl_error_get_code();
00392 }
00393 
00394 /*----------------------------------------------------------------------------*/
00406 /*----------------------------------------------------------------------------*/
00407 static cpl_error_code naco_spc_lampflat_save(cpl_frameset            * set_tot,
00408                                              const cpl_parameterlist * parlist,
00409                                              const cpl_propertylist  * qclist,
00410                                              const cpl_propertylist  * paflist,
00411                                              const cpl_image         * flat,
00412                                              int                       set_nb,
00413                                              const irplib_framelist  * rawframes)
00414 {
00415     cpl_frameset * proframes = irplib_frameset_cast(rawframes);
00416     char         * filename  = NULL;
00417 
00418 
00419 
00420     /* This will catch rawframes == NULL */
00421     bug_if (0);
00422 
00423     /* SAVE THE COMBINED IMAGE */
00424     filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_FITS, set_nb);
00425     skip_if (irplib_dfs_save_image(set_tot, parlist, proframes, flat,
00426                                CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
00427                                NACO_CALIB_SPCFLAT, qclist, NULL,
00428                                naco_pipe_id, filename));
00429 
00430 #ifdef NACO_SAVE_PAF
00431     cpl_free(filename);
00432     filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_PAF, set_nb);
00433     skip_if (cpl_dfs_save_paf("NACO", RECIPE_STRING, paflist, filename));
00434 #else
00435     bug_if(paflist == NULL);
00436 #endif
00437 
00438     end_skip;
00439 
00440     cpl_free(filename);
00441     cpl_frameset_delete(proframes);
00442 
00443     return cpl_error_get_code();
00444 
00445 }

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