visir_img_ff.c

00001 /* $Id: visir_img_ff.c,v 1.94 2010/03/09 12:52:18 llundin Exp $
00002  *
00003  * This file is part of the VISIR 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/09 12:52:18 $
00024  * $Revision: 1.94 $
00025  * $Name: visir-3_5_0 $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                 Includes
00034  -----------------------------------------------------------------------------*/
00035 
00036 #include <string.h>
00037 
00038 #include "visir_recipe.h"
00039 #include "irplib_flat.h"
00040 
00041 /*-----------------------------------------------------------------------------
00042                             Defines
00043  -----------------------------------------------------------------------------*/
00044 
00045 #define PAFCOPY "^(DATE-OBS|ARCFILE|ESO TPL ID|ESO DET DIT|MJD-OBS)$"
00046 #define PAF_IMG "^(ESO INS FILT1 NAME|ESO INS PFOV)$"
00047 #define PAF_SPC "^(ESO INS FILT2 NAME|ESO INS RESOL|ESO INS SLIT1 WID" \
00048                  "|ESO INS GRAT1 WLEN|ESO INS GRAT1 NAME)$"
00049 
00050 #ifndef VISIR_IMG_FF_BORDER
00051 #define VISIR_IMG_FF_BORDER 64
00052 #endif
00053 
00054 /* Different powers of two */
00055 #define visir_ff_mode_default (1<<0)
00056 #define visir_ff_mode_spc    (1<<1)
00057 #define visir_ff_mode_tech    (1<<2)
00058 
00059 #define RECIPE_STRING "visir_img_ff"
00060 
00061 /*-----------------------------------------------------------------------------
00062                             Private Functions prototypes
00063  -----------------------------------------------------------------------------*/
00064 
00065 static cpl_imagelist * visir_img_ff_reduce(const irplib_framelist *);
00066 
00067 static cpl_error_code visir_img_ff_qc(cpl_propertylist *,
00068                                       cpl_propertylist *,
00069                                       const irplib_framelist *);
00070 
00071 static cpl_error_code visir_img_ff_save(cpl_frameset *,
00072                                         const cpl_parameterlist *,
00073                                         const cpl_propertylist *,
00074                                         const cpl_propertylist *,
00075                                         const cpl_imagelist *,
00076                                         const cpl_image *);
00077 
00078 VISIR_RECIPE_DEFINE(visir_img_ff, VISIR_PARAM_LOWLIM | VISIR_PARAM_HIGHLIM,
00079                     "Flat field recipe",
00080                     "This recipe computes the flatfield.\n"
00081                     "The files listed in the Set Of Frames (sof-file) must be "
00082                     "tagged either\n"
00083                     "VISIR-flatfield-raw-file.fits " VISIR_IMG_FF_RAW " or\n"
00084                     "VISIR-flatfield-raw-file.fits " VISIR_IMG_TECH_FF_RAW
00085                     " or\n"
00086                     "VISIR-flatfield-raw-file.fits " VISIR_SPC_FF_RAW " or\n"
00087                     "VISIR-flatfield-raw-file.fits " VISIR_SPC_TECH_FF_RAW "\n"
00088                     "\n"
00089                     "The corresponding primary product will have a FITS card\n"
00090                     "'HIERARCH ESO PRO CATG' with a value of\n"
00091                     VISIR_IMG_FF_PROCATG " or\n"
00092                     VISIR_IMG_TECH_FF_PROCATG " or\n"
00093                     VISIR_SPC_FF_PROCATG " or\n"
00094                     VISIR_SPC_TECH_FF_PROCATG
00095                     "\n");
00096 
00097 /*-----------------------------------------------------------------------------
00098                             Static variables
00099  -----------------------------------------------------------------------------*/
00100 
00101 const unsigned visir_img_ff_border = VISIR_IMG_FF_BORDER;
00102 
00103 enum _visir_ff_mode_ {
00104     visir_ff_none     = 0,
00105     visir_ff_img      = visir_ff_mode_default,
00106     visir_ff_spc      = visir_ff_mode_default | visir_ff_mode_spc,
00107     visir_ff_img_tech = visir_ff_mode_default | visir_ff_mode_tech,
00108     visir_ff_spc_tech = visir_ff_mode_default | visir_ff_mode_tech
00109                       | visir_ff_mode_spc
00110 };
00111 
00112 typedef enum _visir_ff_mode_ visir_ff_mode;
00113 
00114 static struct {
00115     /* Inputs */
00116     visir_ff_mode img_mode;
00117     double        bpm_lo_thresh;
00118     double        bpm_hi_thresh;
00119     /* Outputs */
00120     const char  * procatg_ff;
00121     const char  * procatg_bpm;
00122     int           bpm_nb_bad;
00123     cpl_boolean   is_lamp;
00124     double        fp_noise;  /* The Fixed Pattern Noise */
00125     double        lamp_flux; /* The Lamp Flux (intended for a pair of
00126                                 lamp-on/lamp-off images) */
00127 } visir_img_ff_config;
00128 
00129 /*----------------------------------------------------------------------------*/
00133 /*----------------------------------------------------------------------------*/
00134 
00135 /*-----------------------------------------------------------------------------
00136                                 Functions code
00137  -----------------------------------------------------------------------------*/
00138 /*----------------------------------------------------------------------------*/
00145 /*----------------------------------------------------------------------------*/
00146 static int visir_img_ff(cpl_frameset            * framelist,
00147                         const cpl_parameterlist * parlist)
00148 {
00149     irplib_framelist * allframes = NULL;
00150     irplib_framelist * rawframes = NULL;
00151     cpl_propertylist * qclist    = cpl_propertylist_new();
00152     cpl_propertylist * paflist   = cpl_propertylist_new();
00153     cpl_imagelist    * flat      = NULL;
00154     cpl_image        * bpm_int   = NULL;
00155     cpl_mask         * bpm       = NULL;
00156     
00157 
00158     /* Retrieve input parameters */
00159     visir_img_ff_config.bpm_lo_thresh = 
00160         visir_parameterlist_get_double(parlist, RECIPE_STRING, VISIR_PARAM_LOWLIM);
00161     visir_img_ff_config.bpm_hi_thresh = 
00162         visir_parameterlist_get_double(parlist, RECIPE_STRING, VISIR_PARAM_HIGHLIM);
00163 
00164     skip_if (0);
00165 
00166     /* Identify the RAW and CALIB frames in the input frameset */
00167     skip_if (visir_dfs_set_groups(framelist));
00168 
00169     /* Objects observation */
00170     allframes = irplib_framelist_cast(framelist);
00171     skip_if(allframes == NULL);
00172     rawframes = irplib_framelist_extract_regexp(allframes, "^(" VISIR_IMG_FF_RAW
00173                                                 "|" VISIR_IMG_TECH_FF_RAW
00174                                                 "|" VISIR_SPC_TECH_FF_RAW
00175                                                 "|" VISIR_SPC_FF_RAW ")$",
00176                                                 CPL_FALSE);
00177     skip_if (rawframes == NULL);
00178     irplib_framelist_empty(allframes);
00179 
00180     skip_if(irplib_framelist_load_propertylist_all(rawframes, 0,
00181                                                    visir_property_regexp,
00182                                                    CPL_FALSE));
00183 
00184     skip_if(visir_dfs_check_framelist_tag(rawframes));
00185 
00186     /* Verify uniqueness of frame type and determine PRO.CATG */
00187     visir_img_ff_config.img_mode = visir_ff_none;
00188     if (cpl_frameset_find(framelist, VISIR_IMG_FF_RAW)) {
00189         visir_img_ff_config.img_mode    = visir_ff_img;
00190         visir_img_ff_config.procatg_ff  = VISIR_IMG_FF_PROCATG;
00191         visir_img_ff_config.procatg_bpm = VISIR_IMG_FF_BPM_PROCATG;
00192     }
00193     if (cpl_frameset_find(framelist, VISIR_SPC_FF_RAW)) {
00194         skip_if (visir_img_ff_config.img_mode);
00195         visir_img_ff_config.img_mode    = visir_ff_spc;
00196         visir_img_ff_config.procatg_ff  = VISIR_SPC_FF_PROCATG;
00197         visir_img_ff_config.procatg_bpm = VISIR_SPC_FF_BPM_PROCATG;
00198     }
00199     if (cpl_frameset_find(framelist, VISIR_IMG_TECH_FF_RAW)) {
00200         skip_if (visir_img_ff_config.img_mode);
00201         visir_img_ff_config.img_mode    = visir_ff_img_tech;
00202         visir_img_ff_config.procatg_ff  = VISIR_IMG_TECH_FF_PROCATG;
00203         visir_img_ff_config.procatg_bpm = VISIR_IMG_TECH_FF_BPM_PROCATG;
00204     }
00205     if (cpl_frameset_find(framelist, VISIR_SPC_TECH_FF_RAW)) {
00206         skip_if (visir_img_ff_config.img_mode);
00207         visir_img_ff_config.img_mode    = visir_ff_spc_tech;
00208         visir_img_ff_config.procatg_ff  = VISIR_SPC_TECH_FF_PROCATG;
00209         visir_img_ff_config.procatg_bpm = VISIR_SPC_TECH_FF_BPM_PROCATG;
00210     }
00211     
00212     /* Compute the flatfield  */
00213     cpl_msg_info(cpl_func, "Compute the flatfield");
00214     if ((flat = visir_img_ff_reduce(rawframes)) == NULL) {
00215         cpl_msg_error(cpl_func, "Could not compute the flatfield image");
00216         skip_if(1);
00217     }
00218 
00219     /* Compute the bad pixels map */
00220     cpl_msg_info(cpl_func, "Compute the bad pixels map");
00221     bpm = cpl_mask_threshold_image_create(cpl_imagelist_get(flat, 0),
00222                                           visir_img_ff_config.bpm_lo_thresh,
00223                                           visir_img_ff_config.bpm_hi_thresh);
00224     if (bpm == NULL) {
00225         cpl_msg_error(cpl_func, "Could not compute the bad pixel map");
00226         skip_if(1);
00227     }
00228     skip_if (cpl_mask_not(bpm));
00229     visir_img_ff_config.bpm_nb_bad = cpl_mask_count(bpm);
00230     bpm_int = cpl_image_new_from_mask(bpm);
00231     
00232     /* The values <bpm_lo_thresh and >bpm_hi_thresh are set to 1 */
00233     skip_if (cpl_image_threshold(cpl_imagelist_get(flat, 0), 
00234             visir_img_ff_config.bpm_lo_thresh,
00235             visir_img_ff_config.bpm_hi_thresh, 
00236             1.0, 1.0));
00237     
00238     skip_if (visir_img_ff_qc(qclist, paflist, rawframes));
00239     irplib_framelist_empty(rawframes);
00240 
00241     skip_if (visir_img_ff_save(framelist, parlist, qclist, paflist, flat,
00242                                bpm_int));
00243 
00244     end_skip;
00245 
00246     cpl_propertylist_delete(paflist);
00247     cpl_propertylist_delete(qclist);
00248     irplib_framelist_delete(allframes);
00249     irplib_framelist_delete(rawframes);
00250     cpl_imagelist_delete(flat);
00251     cpl_mask_delete(bpm);
00252     cpl_image_delete(bpm_int);
00253 
00254     return cpl_error_get_code();
00255 }
00256 
00257 /*----------------------------------------------------------------------------*/
00263 /*----------------------------------------------------------------------------*/
00264 static cpl_imagelist * visir_img_ff_reduce(const irplib_framelist * rawframes)
00265 {
00266     cpl_imagelist * iset   = NULL;
00267     cpl_imagelist * fitted = NULL;
00268     cpl_image     * diff   = NULL;
00269     cpl_image     * prev   = NULL;
00270     cpl_image     * image  = NULL;
00271     const cpl_propertylist * plist;
00272     const char    * sval;
00273 
00274 
00275     bug_if (0);
00276     bug_if (rawframes == NULL);
00277 
00278     plist = irplib_framelist_get_propertylist_const(rawframes, 0);
00279     bug_if(plist == NULL);
00280 
00281     /* FIXME: Need a separate DO_CATG for lamp flats */
00282     sval = irplib_pfits_get_dpr_type(plist);
00283     skip_if (sval == NULL);
00284     visir_img_ff_config.is_lamp
00285         = strstr(sval, "SKY") == NULL ? CPL_TRUE : CPL_FALSE;
00286 
00287     /* Load the image set */
00288     iset = irplib_imagelist_load_framelist(rawframes, CPL_TYPE_FLOAT, 0, 0);
00289     skip_if (iset == NULL);
00290 
00291     /* Apply the Fit and compute the gain, intercept map and error */
00292     fitted = irplib_flat_fit_set(iset, 1);
00293 
00294     skip_if (fitted == NULL);
00295 
00296     if (visir_img_ff_config.is_lamp) {
00297         /* Copied from naco_img_lampflat.c */
00298         double std_diff[3];
00299         double upright_x, upright_y;
00300         int    i;
00301 
00302         upright_x  = cpl_image_get_size_x(cpl_imagelist_get(iset, 0));
00303         upright_y  = cpl_image_get_size_y(cpl_imagelist_get(iset, 0));
00304         upright_x -= visir_img_ff_border;
00305         upright_y -= visir_img_ff_border;
00306         skip_if(upright_x <= visir_img_ff_border);
00307         skip_if(upright_y <= visir_img_ff_border);
00308 
00309         for (i=0; i < 4 && i < cpl_imagelist_get_size(iset); i++) {
00310 
00311             double noise;
00312 
00313 
00314             cpl_image_delete(prev);
00315             prev = image;
00316             image = cpl_image_extract(cpl_imagelist_get(iset, i),
00317                                       visir_img_ff_border,
00318                                       visir_img_ff_border,
00319                                       upright_x,
00320                                       upright_y);
00321             bug_if (image == NULL);
00322 
00323             if (i == 0) continue;
00324 
00325             diff = cpl_image_subtract_create(prev, image);
00326             bug_if (diff == NULL);
00327 
00328             bug_if(cpl_flux_get_noise_window(diff, NULL, -1, -1,
00329                                              &noise, NULL));
00330 
00331             std_diff[i-1] = noise * noise;
00332 
00333             cpl_msg_debug(cpl_func, "SQ-Noise(%d):     %g", i, std_diff[i-1]);
00334 
00335             if (i == 1) {
00336                 const double median = cpl_image_get_median(diff);
00337                 const double ditval = visir_pfits_get_dit(plist);
00338 
00339                 skip_if (0);
00340                 skip_if (ditval <= 0.0);
00341 
00342                 visir_img_ff_config.lamp_flux = median / ditval;
00343                 cpl_msg_info(cpl_func, "Lamp Flux: %g",
00344                              visir_img_ff_config.lamp_flux);
00345             }
00346 
00347             cpl_image_delete(diff);
00348             diff = NULL;
00349 
00350         }
00351 
00352         if (i == 4) {
00353 
00354             /* Deduce FPNOISE */
00355             const double square = std_diff[0] - std_diff[1] - std_diff[2];
00356             visir_img_ff_config.fp_noise = square > 0.0 ? sqrt(square) : 0.0;
00357 
00358             cpl_msg_info(cpl_func, "Noise:     %g",
00359                          visir_img_ff_config.fp_noise);
00360 
00361         }
00362     }
00363 
00364     end_skip;
00365 
00366     cpl_image_delete(diff);
00367     cpl_image_delete(image);
00368     cpl_image_delete(prev);
00369     cpl_imagelist_delete(iset);
00370 
00371     return fitted;
00372 }
00373 
00374 
00375 /*----------------------------------------------------------------------------*/
00383 /*----------------------------------------------------------------------------*/
00384 static cpl_error_code visir_img_ff_qc(cpl_propertylist       * qclist,
00385                                       cpl_propertylist       * paflist,
00386                                       const irplib_framelist * rawframes)
00387 {
00388 
00389     const cpl_propertylist * reflist
00390         = irplib_framelist_get_propertylist_const(rawframes, 0);
00391 
00392     bug_if (0);
00393 
00394     /* QC.CAPA */
00395     skip_if (visir_qc_append_capa(qclist, rawframes));
00396 
00397     /* QC.NBBADPIX */
00398     bug_if(cpl_propertylist_append_int(qclist, "ESO QC NBBADPIX", 
00399                                        visir_img_ff_config.bpm_nb_bad));
00400 
00401     if (visir_img_ff_config.is_lamp) {
00402         bug_if(cpl_propertylist_append_double(qclist, "ESO QC FPNOISE", 
00403                                               visir_img_ff_config.fp_noise));
00404         bug_if(cpl_propertylist_append_double(qclist, "ESO QC LAMPFLUX", 
00405                                               visir_img_ff_config.lamp_flux));
00406     }
00407 
00408     bug_if (cpl_propertylist_append(paflist, qclist));
00409 
00410     bug_if (cpl_propertylist_copy_property_regexp(paflist, reflist,
00411                               (visir_img_ff_config.img_mode & visir_ff_mode_spc)
00412                                ? PAFCOPY "|" PAF_SPC : PAFCOPY "|" PAF_IMG, 0));
00413 
00414     /* PRO.CATG */
00415     bug_if (cpl_propertylist_append_string(paflist, CPL_DFS_PRO_CATG,
00416                                            visir_img_ff_config.procatg_ff));
00417 
00418     bug_if (cpl_propertylist_copy_property_regexp(qclist, reflist,
00419                                                   "^(" VISIR_PFITS_FF_COPY
00420                                                   ")$", 0));
00421 
00422     bug_if (irplib_pfits_set_airmass(qclist, rawframes));
00423 
00424     end_skip;
00425     
00426     return cpl_error_get_code();
00427 
00428 }
00429  
00430 
00431 /*----------------------------------------------------------------------------*/
00442 /*----------------------------------------------------------------------------*/
00443 static cpl_error_code visir_img_ff_save(cpl_frameset            * set,
00444                                         const cpl_parameterlist * parlist, 
00445                                         const cpl_propertylist  * qclist,
00446                                         const cpl_propertylist  * paflist,
00447                                         const cpl_imagelist     * flat,
00448                                         const cpl_image         * bpm)
00449 {
00450     /* SAVE THE FLAT IMAGE */
00451     skip_if (irplib_dfs_save_image(set, parlist, set,
00452                                 cpl_imagelist_get_const(flat, 0),
00453                                 CPL_BPP_IEEE_FLOAT, RECIPE_STRING,
00454                                 visir_img_ff_config.procatg_ff, qclist, NULL,
00455                                 visir_pipe_id, RECIPE_STRING CPL_DFS_FITS));
00456 
00457     /* SAVE THE BPM IMAGE */
00458     skip_if (irplib_dfs_save_image(set, parlist, set, bpm, CPL_BPP_32_SIGNED,
00459                                 RECIPE_STRING, visir_img_ff_config.procatg_bpm,
00460                                 qclist, NULL, visir_pipe_id,
00461                                 RECIPE_STRING "_bpm" CPL_DFS_FITS));
00462 
00463 #ifdef VISIR_SAVE_PAF
00464     skip_if (cpl_dfs_save_paf("VISIR", RECIPE_STRING, paflist,
00465                               RECIPE_STRING CPL_DFS_PAF));
00466 #else
00467     bug_if(paflist == NULL);
00468 #endif
00469 
00470     end_skip;
00471 
00472     return cpl_error_get_code();
00473 
00474 }

Generated on Mon Feb 6 15:23:49 2012 for VISIR Pipeline Reference Manual by  doxygen 1.5.8