naco_spc_lampflat.c

00001 /* $Id: naco_spc_lampflat.c,v 1.18 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.18 $
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 #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             skip_if(naco_spc_lampflat_save(framelist, parlist, qclist, paflist,
00172                                            lamp_flat, i+1, f_one));
00173             cpl_image_delete(lamp_flat);
00174             lamp_flat = NULL;
00175             nb_good++;
00176         }
00177         cpl_propertylist_empty(qclist);
00178         cpl_propertylist_empty(paflist);
00179         irplib_framelist_delete(f_one);
00180         f_one = NULL;
00181     }
00182 
00183     irplib_ensure(nb_good > 0, CPL_ERROR_DATA_NOT_FOUND,
00184                   "None of the %d sets could be reduced", nsets);
00185     
00186     end_skip;
00187 
00188     cpl_free(taglist);
00189     cpl_image_delete(lamp_flat);
00190     irplib_framelist_delete(f_one);
00191     irplib_framelist_delete(allframes);
00192     irplib_framelist_delete(rawframes);
00193     cpl_propertylist_delete(qclist);
00194     cpl_propertylist_delete(paflist);
00195 
00196     return cpl_error_get_code();
00197 }
00198 
00199 /*----------------------------------------------------------------------------*/
00207 /*----------------------------------------------------------------------------*/
00208 static cpl_image * naco_spc_lampflat_reduce(cpl_propertylist * qclist,
00209                                             const irplib_framelist * framelist,
00210                                             const cpl_parameterlist * parlist)
00211 {
00212     cpl_image     * self = NULL;
00213     cpl_imagelist * difflist = cpl_imagelist_new();
00214     cpl_mask      * bpm = NULL;
00215     cpl_vector    * medians = NULL;
00216     const double    hot_thresh
00217         = naco_parameterlist_get_double(parlist, RECIPE_STRING,
00218                                         NACO_PARAM_HOT_LIM);
00219     const double    cold_thresh = 1.0 /
00220         naco_parameterlist_get_double(parlist, RECIPE_STRING,
00221                                       NACO_PARAM_COLD_LIM);
00222     const char    * rej_bord
00223         = naco_parameterlist_get_string(parlist, RECIPE_STRING,
00224                                         NACO_PARAM_REJBORD);
00225     cpl_propertylist * lampkeys = cpl_propertylist_new();
00226     int             rej_left, rej_right, rej_bottom, rej_top;
00227     int             nflat, nbad;
00228     int             ndiff, idiff;
00229 
00230 
00231     skip_if (0);
00232     bug_if (qclist    == NULL);
00233     bug_if (framelist == NULL);
00234     bug_if (parlist == NULL);
00235 
00236     skip_if(cold_thresh <= 0.0);
00237     skip_if(cold_thresh >= 1.0);
00238     skip_if(hot_thresh  <= 1.0);
00239 
00240     skip_if (sscanf(rej_bord, "%d %d %d %d",
00241                     &rej_left, &rej_right, &rej_bottom, &rej_top) != 4);
00242 
00243     /* On-frames have lamp2 on and lamp1 off */
00244     bug_if(cpl_propertylist_append_int(lampkeys, NACO_PFITS_INT_LAMP2,  1));
00245     bug_if(cpl_propertylist_append_int(lampkeys, NACO_PFITS_BOOL_LAMP1, 0));
00246   
00247     skip_if(naco_imagelist_load_diff(difflist, framelist, lampkeys));
00248 
00249     ndiff = cpl_imagelist_get_size(difflist);
00250 
00251     medians = cpl_vector_new(ndiff);
00252 
00253     bug_if(0);
00254 
00255     for (idiff = 0, nflat = 0; idiff < ndiff; idiff++) {
00256         cpl_image       * diff = cpl_imagelist_get(difflist, nflat);
00257         const int         nx   = cpl_image_get_size_x(diff);
00258         const int         ny   = cpl_image_get_size_y(diff);
00259 
00260         double            median;
00261         const double      mean
00262             = cpl_image_get_mean_window(diff,
00263                                         rej_left,   nx - rej_right,
00264                                         rej_bottom, ny - rej_top);
00265 
00266         skip_if(0);
00267 
00268         if (mean <= 0.0) {
00269             cpl_msg_warning(cpl_func, "Ignoring difference image %d with an "
00270                             "invalid mean: %g", 1+idiff, mean);
00271             cpl_image_delete(cpl_imagelist_unset(difflist, nflat));
00272             continue;
00273         }
00274 
00275         /* Get the median of the central region */
00276         median = cpl_image_get_median_window(diff, 
00277                                              (nx-NACO_SPC_MEDIAN_XSIZE)/2,
00278                                              (ny-NACO_SPC_MEDIAN_YSIZE)/2,
00279                                              (nx+NACO_SPC_MEDIAN_XSIZE)/2,
00280                                              (ny+NACO_SPC_MEDIAN_YSIZE)/2);
00281         skip_if(0);
00282 
00283         /* Normalize the difference image */
00284         bug_if(cpl_image_divide_scalar(diff, mean));
00285 
00286         /* Find non-hot/cold pixels */
00287         bpm = cpl_mask_threshold_image_create(diff, cold_thresh, hot_thresh);
00288         bug_if(bpm == NULL);
00289 
00290         if (cpl_mask_is_empty(bpm)) {
00291             cpl_msg_warning(cpl_func, "Ignoring difference image %d with no "
00292                             "good pixels", 1+idiff);
00293             cpl_mask_delete(bpm);
00294             bpm = NULL;
00295             cpl_image_delete(cpl_imagelist_unset(difflist, nflat));
00296             continue;
00297         }
00298 
00299         bug_if(cpl_mask_not(bpm));
00300 
00301         cpl_msg_info(cpl_func, "Difference image %d has %d bad pixels", 1+idiff,
00302                      cpl_mask_count(bpm));
00303 
00304         /* Reject hot and cold pixels */
00305         bug_if(cpl_mask_or(cpl_image_get_bpm(diff), bpm));
00306 
00307         cpl_mask_delete(bpm);
00308         bpm = NULL;
00309 
00310         bug_if (cpl_vector_set(medians, nflat, median));
00311 
00312         nflat++;
00313     }
00314 
00315     bug_if(nflat != cpl_imagelist_get_size(difflist));
00316 
00317     error_if(nflat == 0, CPL_ERROR_DATA_NOT_FOUND,
00318              "The %d difference images are all invalid", ndiff);
00319 
00320     self = cpl_imagelist_collapse_create(difflist);
00321     bug_if(0);
00322 
00323     nbad =  cpl_image_count_rejected(self);
00324     bug_if(0);
00325 
00326     if (nbad > 0) {
00327         cpl_msg_info(cpl_func, "Setting %d bad pixels in master flat to 1.0",
00328                      nbad);
00329         bug_if(cpl_image_fill_rejected(self, 1.0));
00330     }
00331 
00332     bug_if(cpl_vector_set_size(medians, nflat));
00333 
00334     bug_if(cpl_propertylist_append_double(qclist, "ESO QC SPECFLAT NCOUNTS",
00335                                           cpl_vector_get_mean(medians)));
00336     bug_if(cpl_propertylist_append_double(qclist, "ESO QC SPECFLAT STDEV",
00337                                           cpl_vector_get_stdev(medians)));
00338 
00339     end_skip;
00340 
00341     if (cpl_error_get_code()) {
00342         cpl_image_delete(self);
00343         self = NULL;
00344     }
00345 
00346     cpl_propertylist_delete(lampkeys);
00347     cpl_imagelist_delete(difflist);
00348     cpl_mask_delete(bpm);
00349     cpl_vector_delete(medians);
00350 
00351     return self;
00352 }
00353 
00354 
00355 /*----------------------------------------------------------------------------*/
00363 /*----------------------------------------------------------------------------*/
00364 static cpl_error_code naco_spc_lampflat_qc(cpl_propertylist       * qclist,
00365                                            cpl_propertylist       * paflist,
00366                                            const irplib_framelist * rawframes)
00367 {
00368 
00369     const cpl_propertylist * reflist
00370         = irplib_framelist_get_propertylist_const(rawframes, 0);
00371     const char pafcopy[] = "^(" NACO_PFITS_REGEXP_SPCFLAT_PAF ")$";
00372 
00373 
00374     bug_if (0);
00375 
00376 
00377     /* THE PAF FILE FOR QC PARAMETERS */
00378     skip_if (cpl_propertylist_copy_property_regexp(paflist, reflist, pafcopy,
00379                                                    0));
00380     skip_if (cpl_propertylist_append(paflist, qclist));
00381 
00382     bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist, "^("
00383                                                   IRPLIB_PFITS_REGEXP_RECAL_LAMP
00384                                                   ")$", 0));
00385 
00386     end_skip;
00387 
00388     return cpl_error_get_code();
00389 }
00390 
00391 /*----------------------------------------------------------------------------*/
00403 /*----------------------------------------------------------------------------*/
00404 static cpl_error_code naco_spc_lampflat_save(cpl_frameset            * set_tot,
00405                                              const cpl_parameterlist * parlist,
00406                                              const cpl_propertylist  * qclist,
00407                                              const cpl_propertylist  * paflist,
00408                                              const cpl_image         * flat,
00409                                              int                       set_nb,
00410                                              const irplib_framelist  * rawframes)
00411 {
00412     cpl_frameset * proframes = irplib_frameset_cast(rawframes);
00413     char         * filename  = NULL;
00414 
00415 
00416 
00417     /* This will catch rawframes == NULL */
00418     bug_if (0);
00419 
00420     /* SAVE THE COMBINED IMAGE */
00421     filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_FITS, set_nb);
00422     skip_if (irplib_dfs_save_image(set_tot, parlist, proframes, flat,
00423                                CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
00424                                NACO_CALIB_SPCFLAT, qclist, NULL,
00425                                naco_pipe_id, filename));
00426 
00427     cpl_free(filename);
00428     filename = cpl_sprintf(RECIPE_STRING "_set%02d" CPL_DFS_PAF, set_nb);
00429     skip_if (cpl_dfs_save_paf("NACO", RECIPE_STRING, paflist, filename));
00430 
00431     end_skip;
00432 
00433     cpl_free(filename);
00434     cpl_frameset_delete(proframes);
00435 
00436     return cpl_error_get_code();
00437 
00438 }

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