GRAVI Pipeline Reference Manual 0.1.1
gravi_all_flat.c
00001 /* $Id: gravi_all_flat.c,v 1.29 2009/02/10 09:16:12 llundin Exp $
00002  *
00003  * This file is part of the GRAVI 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00021 /*
00022  * $Author: llundin $
00023  * $Date: 2009/02/10 09:16:12 $
00024  * $Revision: 1.29 $
00025  * $Name:  $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                 Includes
00034  -----------------------------------------------------------------------------*/
00035 
00036 #include <cpl.h>
00037 #include <stdio.h>
00038 #include <string.h>
00039 
00040 #include "gravi_calib.h"
00041 #include "gravi_utils.h"
00042 #include "gravi_pfits.h"
00043 #include "gravi_dfs.h"
00044 
00045 #include "gravi_data.h"
00046 
00047 
00048 /*-----------------------------------------------------------------------------
00049                             Private function prototypes
00050  -----------------------------------------------------------------------------*/
00051 
00052 static int gravi_all_flat_create(cpl_plugin *);
00053 static int gravi_all_flat_exec(cpl_plugin *);
00054 static int gravi_all_flat_destroy(cpl_plugin *);
00055 static int gravi_all_flat(cpl_frameset *, const cpl_parameterlist *);
00056 
00057 /*-----------------------------------------------------------------------------
00058                             Static variables
00059  -----------------------------------------------------------------------------*/
00060 
00061 static char gravi_all_flat_description[] =
00062 "This recipe is used to compute the flat matrix.\n"
00063 "The given output FITS file contain a flat table with "
00064 "the values of the transmission, phase and coherence extract "
00065 "using the flat matrix \n"
00066 "The description should include the required FITS-files and\n"
00067 "their associated tags, e.g.\n"
00068 "GRAVI-GRAVI_ALL_flat-raw-file.fits " GRAVI_FT_FLAT "\n"
00069 "and any optional files, e.g.\n"
00070 "GRAVI-GRAVI_ALL_flat-flat-file.fits " FLAT_FT "\n"
00071 "\n"
00072 "Additionally, it should describe functionality of the expected output."
00073 "\n";
00074 
00075 /*-----------------------------------------------------------------------------
00076                                 Function code
00077  -----------------------------------------------------------------------------*/
00078 
00079 /*----------------------------------------------------------------------------*/
00089 /*----------------------------------------------------------------------------*/
00090 int cpl_plugin_get_info(cpl_pluginlist * list)
00091 {
00092     cpl_recipe  *   recipe = cpl_calloc(1, sizeof *recipe );
00093     cpl_plugin  *   plugin = &recipe->interface;
00094 
00095     if (cpl_plugin_init(plugin,
00096                     CPL_PLUGIN_API,
00097                     GRAVI_BINARY_VERSION,
00098                     CPL_PLUGIN_TYPE_RECIPE,
00099                     "gravi_all_flat",
00100                     "This recipe is used to compute flat matrix",
00101                     gravi_all_flat_description,
00102                     "Firstname Lastname",
00103                     PACKAGE_BUGREPORT,
00104                     gravi_get_license(),
00105                     gravi_all_flat_create,
00106                     gravi_all_flat_exec,
00107                     gravi_all_flat_destroy)) {    
00108         cpl_msg_error(cpl_func, "Plugin initialization failed");
00109         (void)cpl_error_set_where(cpl_func);                          
00110         return 1;                                               
00111     }                                                    
00112 
00113     if (cpl_pluginlist_append(list, plugin)) {                 
00114         cpl_msg_error(cpl_func, "Error adding plugin to list");
00115         (void)cpl_error_set_where(cpl_func);                         
00116         return 1;                                              
00117     }                                                          
00118     
00119     return 0;
00120 }
00121 
00122 /*----------------------------------------------------------------------------*/
00130 /*----------------------------------------------------------------------------*/
00131 static int gravi_all_flat_create(cpl_plugin * plugin)
00132 {
00133     cpl_recipe    * recipe;                                               
00134     cpl_parameter * p;
00135                                                                        
00136     /* Do not create the recipe if an error code is already set */     
00137     if (cpl_error_get_code() != CPL_ERROR_NONE) {                      
00138         cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
00139                       cpl_func, __LINE__, cpl_error_get_where());      
00140         return (int)cpl_error_get_code();                              
00141     }                                                                  
00142                                                                        
00143     if (plugin == NULL) {                                              
00144         cpl_msg_error(cpl_func, "Null plugin");                        
00145         cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);                 
00146     }                                                                  
00147                                                                        
00148     /* Verify plugin type */                                           
00149     if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {       
00150         cpl_msg_error(cpl_func, "Plugin is not a recipe");             
00151         cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);              
00152     }                                                                  
00153                                                                        
00154     /* Get the recipe */                                               
00155     recipe = (cpl_recipe *)plugin;                                     
00156                                                                        
00157     /* Create the parameters list in the cpl_recipe object */          
00158     recipe->parameters = cpl_parameterlist_new();                      
00159     if (recipe->parameters == NULL) {                                  
00160         cpl_msg_error(cpl_func, "Parameter list allocation failed");   
00161         cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);             
00162     }                                                                  
00163 
00164     /* Fill the parameters list */
00165     /* -- */
00166     p = cpl_parameter_new_value("gravi.gravi_all_flat."
00167                 "profile_width", CPL_TYPE_INT, "profile width option",
00168                                         "gravi.gravi_all_flat", 5);
00169     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "profile_width");
00170     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00171     cpl_parameterlist_append(recipe->parameters, p);
00172 
00173     p = cpl_parameter_new_value("gravi."
00174             "flat_param.Bad_dark_threshold", CPL_TYPE_INT, "the rms factor for "
00175                     "dark bad pixel threshold", "gravi.gravi_all_flat", 5);
00176     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "Bad_dark_threshold");
00177     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00178     cpl_parameterlist_append(recipe->parameters, p);
00179 
00180  
00181     return 0;
00182 }
00183 
00184 /*----------------------------------------------------------------------------*/
00190 /*----------------------------------------------------------------------------*/
00191 static int gravi_all_flat_exec(cpl_plugin * plugin)
00192 {
00193 
00194     cpl_recipe * recipe;                                                   
00195     int recipe_status;                                                     
00196     cpl_errorstate initial_errorstate = cpl_errorstate_get();              
00197                                                                            
00198     /* Return immediately if an error code is already set */               
00199     if (cpl_error_get_code() != CPL_ERROR_NONE) {                          
00200         cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",    
00201                       cpl_func, __LINE__, cpl_error_get_where());          
00202         return (int)cpl_error_get_code();                                  
00203     }                                                                      
00204                                                                            
00205     if (plugin == NULL) {                                                  
00206         cpl_msg_error(cpl_func, "Null plugin");                            
00207         cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);                     
00208     }                                                                      
00209                                                                            
00210     /* Verify plugin type */                                               
00211     if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {           
00212         cpl_msg_error(cpl_func, "Plugin is not a recipe");                 
00213         cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);                  
00214     }                                                                      
00215                                                                            
00216     /* Get the recipe */                                                   
00217     recipe = (cpl_recipe *)plugin;                                         
00218                                                                            
00219     /* Verify parameter and frame lists */                                 
00220     if (recipe->parameters == NULL) {
00221         cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
00222         cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
00223     }
00224     if (recipe->frames == NULL) {                                          
00225         cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");     
00226         cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);                     
00227     }                                                                      
00228                                                                            
00229     /* Invoke the recipe */                                                
00230     recipe_status = gravi_all_flat(recipe->frames, recipe->parameters);
00231                                                                            
00232     /* Ensure DFS-compliance of the products */                            
00233     if (cpl_dfs_update_product_header(recipe->frames)) {                   
00234         if (!recipe_status) recipe_status = (int)cpl_error_get_code();                         
00235     }                                                                      
00236                                                                            
00237     if (!cpl_errorstate_is_equal(initial_errorstate)) {                    
00238         /* Dump the error history since recipe execution start.            
00239            At this point the recipe cannot recover from the error */       
00240         cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);          
00241     }                                                                      
00242                                                                            
00243     return recipe_status;                                                  
00244 }
00245 
00246 /*----------------------------------------------------------------------------*/
00252 /*----------------------------------------------------------------------------*/
00253 static int gravi_all_flat_destroy(cpl_plugin * plugin)
00254 {
00255     cpl_recipe * recipe;                                          
00256                                                                   
00257     if (plugin == NULL) {                                         
00258         cpl_msg_error(cpl_func, "Null plugin");                   
00259         cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);            
00260     }                                                             
00261                                                                   
00262     /* Verify plugin type */                                      
00263     if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {  
00264         cpl_msg_error(cpl_func, "Plugin is not a recipe");        
00265         cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);         
00266     }                                                             
00267                                                                   
00268     /* Get the recipe */                                          
00269     recipe = (cpl_recipe *)plugin;                                
00270                                                                   
00271     cpl_parameterlist_delete(recipe->parameters);             
00272                                                                   
00273     return 0;                                                    
00274 }
00275 
00276 
00277 /*----------------------------------------------------------------------------*/
00284 /*----------------------------------------------------------------------------*/
00285 static int gravi_all_flat(cpl_frameset            * frameset,
00286                           const cpl_parameterlist * parlist)
00287 {
00288     cpl_frameset * flat_frameset, * dark_frameset, * darkcalib_frameset;
00289     cpl_propertylist * applist, * primary_hdr, * bad_primary_hdr;
00290     cpl_frame * frame, *_frame;
00291     char * output;
00292     const char * filename, * frame_tag;
00293     gravi_data * profile_map, * dark_file, * dark_map, * bad_map;
00294     gravi_data ** flat_data;
00295     double gain;
00296     int nb_frame, i, badpix;
00297 
00298     /* Identify the RAW and CALIB frames in the input frameset */
00299     cpl_ensure_code(gravi_dfs_set_groups(frameset) == CPL_ERROR_NONE,
00300                         cpl_error_get_code()) ;
00301 
00302     /*  - Extract a set of frame flat */
00303 
00304     flat_frameset = gravi_frameset_extract_flat(frameset);
00305 
00306     darkcalib_frameset = gravi_frameset_extract_dark_file(frameset);
00307 
00308     dark_frameset = gravi_frameset_extract_dark(frameset);
00309 
00310     if (cpl_frameset_is_empty(flat_frameset) ||
00311                         ((cpl_frameset_is_empty(dark_frameset)) &&
00312                                 cpl_frameset_is_empty(darkcalib_frameset))) {
00313        /* To use this recipe the frameset must contain at least
00314         * one flat frame. */
00315         cpl_frameset_delete(flat_frameset);
00316         cpl_frameset_delete(dark_frameset);
00317         cpl_frameset_delete(darkcalib_frameset);
00318        return (int)cpl_error_set_message(cpl_func,  CPL_ERROR_ILLEGAL_INPUT,
00319                                "No dark or flat frame on the inputs frameset") ;
00320     }
00321 
00322     /* Get the number of the flat frame contained in the frameset */
00323 
00324     nb_frame = cpl_frameset_get_size(flat_frameset);
00325     /* Check that the number of flat frames is upper than 4 */
00326     if (nb_frame < 4){
00327         cpl_frameset_delete(flat_frameset);
00328         cpl_frameset_delete(dark_frameset);
00329         cpl_frameset_delete(darkcalib_frameset);
00330         return (int)cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
00331                             "The number of flat frames must be more than 4");
00332     }
00333 
00334     /* Extract the gravi datas from the flat frame set and the dark map from
00335      * the dark frame set */
00336     frame = cpl_frameset_get_first(flat_frameset);
00337     frame_tag = cpl_frame_get_tag(frame);
00338     flat_data = cpl_malloc(nb_frame * sizeof(gravi_data *));
00339 
00340     for(i = 0; i < nb_frame; i++){
00341         filename = cpl_frame_get_filename(frame);
00342 
00343         flat_data[i] = gravi_data_load(filename);
00344         frame = cpl_frameset_get_next(flat_frameset);
00345     }
00346 
00347     /* Extract the dark map */
00348     if (cpl_frameset_is_empty(darkcalib_frameset)){
00349         _frame = cpl_frameset_get_first(dark_frameset);
00350         filename = cpl_frame_get_filename(_frame);
00351 
00352         dark_file = gravi_data_load(filename);
00353         dark_map = gravi_compute_dark(dark_file);
00354         gravi_data_delete(dark_file);
00355     }
00356     else if (cpl_frameset_is_empty(dark_frameset)){
00357         _frame = cpl_frameset_get_first(darkcalib_frameset);
00358         filename = cpl_frame_get_filename(_frame);
00359 
00360         dark_map = gravi_data_load(filename);
00361     }
00362     else {
00363         cpl_frameset_delete(flat_frameset);
00364         cpl_frameset_delete(dark_frameset);
00365         cpl_frameset_delete(darkcalib_frameset);
00366         for(i = 0; i < nb_frame; i++){
00367             gravi_data_delete(flat_data[i]);
00368         }
00369         cpl_free(flat_data);
00370         gravi_data_delete(dark_map);
00371         return (int)cpl_error_set_message(cpl_func,  CPL_ERROR_ILLEGAL_INPUT,
00372                                   "No dark frames in the frameset");
00373     }
00374 
00375     /* Compute the flat calib data of a set of flat frames */
00376 
00377     /* Compute the profile map */
00378     if (!strcmp(frame_tag, GRAVI_SC_FLAT))
00379         profile_map = gravi_compute_profile(flat_data, dark_map,
00380                                                     nb_frame, parlist);
00381     else if (!strcmp(frame_tag, GRAVI_FT_FLAT)){
00382         profile_map = gravi_data_duplicate(dark_map);
00383         gravi_data_erase(profile_map, GRAVI_IMAGING_DATA_NAME_EXT);
00384     }
00385 
00386     if (profile_map == NULL) {
00387         gravi_data_delete(dark_map);
00388         gravi_data_delete(profile_map);
00389         for(i = 0; i < nb_frame; i++){
00390             gravi_data_delete(flat_data[i]);
00391         }
00392         cpl_free(flat_data);
00393         cpl_frameset_delete(flat_frameset);
00394         cpl_frameset_delete(dark_frameset);
00395         cpl_frameset_delete(darkcalib_frameset);
00396         return (int)cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT,
00397                                   "Error while computing the profile map");
00398     }
00399 
00400     /* Compute the gain */
00401     gain = gravi_compute_gain(flat_data, nb_frame, dark_map);
00402 
00403     if (cpl_error_get_code()) {
00404         gravi_data_delete(dark_map);
00405         gravi_data_delete(profile_map);
00406         for(i = 0; i < nb_frame; i++){
00407             gravi_data_delete(flat_data[i]);
00408         }
00409         cpl_free(flat_data);
00410         cpl_frameset_delete(flat_frameset);
00411         cpl_frameset_delete(dark_frameset);
00412         cpl_frameset_delete(darkcalib_frameset);
00413         return (int)cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT,
00414                                   "Error while computing the gain map");
00415     }
00416 
00417     primary_hdr = gravi_data_get_propertylist(profile_map,
00418                                                 GRAVI_PRIMARY_HDR_NAME_EXT);
00419 
00420     cpl_propertylist_append_double (primary_hdr, QC_MEANGAIN, gain);
00421 
00422     bad_map = gravi_compute_badpix(dark_map, parlist);
00423 
00424     if (bad_map == NULL) {
00425         gravi_data_delete(dark_map);
00426         gravi_data_delete(profile_map);
00427         gravi_data_delete(bad_map);
00428         for(i = 0; i < nb_frame; i++){
00429             gravi_data_delete(flat_data[i]);
00430         }
00431         cpl_free(flat_data);
00432         cpl_frameset_delete(flat_frameset);
00433         cpl_frameset_delete(dark_frameset);
00434         cpl_frameset_delete(darkcalib_frameset);
00435         return (int)cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT,
00436                                   "Error while computing the bad pixel map");
00437     }
00438 
00439     /* Create product frame, add DataFlow keywords, save the file, log the
00440      * saved file in the input frameset*/
00441     applist = cpl_propertylist_new();
00442     cpl_propertylist_append_double (applist, QC_MEANGAIN, gain);
00443     frame = cpl_frameset_get_first(flat_frameset);
00444     frame_tag = cpl_frame_get_tag(frame) ;
00445     if (!strcmp(frame_tag, GRAVI_FT_FLAT))
00446         cpl_propertylist_append_string(applist, CPL_DFS_PRO_CATG, PROFILE_FT);
00447     else if (!strcmp(frame_tag, GRAVI_SC_FLAT))
00448         cpl_propertylist_append_string(applist, CPL_DFS_PRO_CATG, PROFILE_SC);
00449     else{
00450         gravi_data_delete(bad_map);
00451         gravi_data_delete(dark_map);
00452         gravi_data_delete(profile_map);
00453         for(i = 0; i < nb_frame; i++){
00454             gravi_data_delete(flat_data[i]);
00455         }
00456         cpl_free(flat_data);
00457         cpl_frameset_delete(flat_frameset);
00458         cpl_frameset_delete(dark_frameset);
00459         cpl_frameset_delete(darkcalib_frameset);
00460         cpl_propertylist_delete(applist);
00461         return (int)cpl_error_set_message(cpl_func, CPL_ERROR_INVALID_TYPE,
00462                                                "Invalid type of flat tag");
00463     }
00464 
00465     if (gravi_data_save (profile_map, frameset, "gravi_profile_map.fits", parlist,
00466                               frameset, "gravi_all_flat", applist)
00467                                                       != CPL_ERROR_NONE){
00468         gravi_data_delete(bad_map);
00469         gravi_data_delete(profile_map);
00470         for(i = 0; i < nb_frame; i++){
00471             gravi_data_delete(flat_data[i]);
00472         }
00473         cpl_free(flat_data);
00474         gravi_data_delete(dark_map);
00475         cpl_frameset_delete(flat_frameset);
00476         cpl_frameset_delete(dark_frameset);
00477         cpl_frameset_delete(darkcalib_frameset);
00478         cpl_propertylist_delete(applist);
00479         return (int) cpl_error_set_message(cpl_func,
00480                 CPL_ERROR_ILLEGAL_OUTPUT, "Could not save the profile_map");
00481     }
00482     cpl_propertylist_delete(applist);
00483 
00484     /* Save the pad pixel map */
00485     bad_primary_hdr = gravi_data_get_propertylist (bad_map,
00486                                                 GRAVI_PRIMARY_HDR_NAME_EXT);
00487     applist = cpl_propertylist_new();
00488     badpix = cpl_propertylist_get_int(bad_primary_hdr,
00489                                                     QC_BADPIX);
00490     cpl_propertylist_append_int (applist, QC_BADPIX, badpix);
00491     frame = cpl_frameset_get_first(flat_frameset);
00492     frame_tag = cpl_frame_get_tag(frame) ;
00493     if (!strcmp(frame_tag, GRAVI_FT_FLAT))
00494         cpl_propertylist_append_string(applist, CPL_DFS_PRO_CATG, BAD_FT);
00495     else if (!strcmp(frame_tag, GRAVI_SC_FLAT))
00496         cpl_propertylist_append_string(applist, CPL_DFS_PRO_CATG, BAD_SC);
00497     else{
00498         gravi_data_delete(bad_map);
00499         gravi_data_delete(dark_map);
00500         gravi_data_delete(profile_map);
00501         for(i = 0; i < nb_frame; i++){
00502             gravi_data_delete(flat_data[i]);
00503         }
00504         cpl_free(flat_data);
00505         cpl_frameset_delete(flat_frameset);
00506         cpl_frameset_delete(dark_frameset);
00507         cpl_frameset_delete(darkcalib_frameset);
00508         cpl_propertylist_delete(applist);
00509         return (int)cpl_error_set_message(cpl_func, CPL_ERROR_INVALID_TYPE,
00510                                                "Invalid type of flat tag");
00511     }
00512 
00513     if (gravi_data_save (bad_map, frameset, "gravi_bad_map.fits", parlist,
00514                               frameset, "gravi_all_flat", applist)
00515                                                       != CPL_ERROR_NONE){
00516 
00517         gravi_data_delete(profile_map);
00518         gravi_data_delete(bad_map);
00519         for(i = 0; i < nb_frame; i++){
00520             gravi_data_delete(flat_data[i]);
00521         }
00522         cpl_free(flat_data);
00523         gravi_data_delete(dark_map);
00524         cpl_frameset_delete(flat_frameset);
00525         cpl_frameset_delete(dark_frameset);
00526         cpl_frameset_delete(darkcalib_frameset);
00527         cpl_propertylist_delete(applist);
00528         return (int) cpl_error_set_message(cpl_func,
00529                 CPL_ERROR_ILLEGAL_OUTPUT, "Could not save the bad pixel map");
00530     }
00531 
00532 
00533 
00534     /* Deallocation of all variables */
00535 
00536 
00537     gravi_data_delete(bad_map);
00538     gravi_data_delete(profile_map);
00539     for(i = 0; i < nb_frame; i++){
00540         gravi_data_delete(flat_data[i]);
00541     }
00542     cpl_free(flat_data);
00543     gravi_data_delete(dark_map);
00544     cpl_frameset_delete(flat_frameset);
00545     cpl_frameset_delete(darkcalib_frameset);
00546     cpl_frameset_delete(dark_frameset);
00547     cpl_propertylist_delete(applist);
00548 
00549     return (int)cpl_error_get_code();
00550 }
00551 
00552