IIINSTRUMENT Pipeline Reference Manual  0.0.9
rrrecipe_calib.c
00001 /* $Id: rrrecipe_calib.c,v 1.6 2013-03-26 17:17:32 jtaylor Exp $
00002  *
00003  * This file is part of the IIINSTRUMENT 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  02110-1301  USA
00019  */
00020 
00021 /*
00022  * $Author: jtaylor $
00023  * $Date: 2013-03-26 17:17:32 $
00024  * $Revision: 1.6 $
00025  * $Name: not supported by cvs2svn $
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 /*-----------------------------------------------------------------------------
00033                                 Includes
00034  -----------------------------------------------------------------------------*/
00035 
00036 #include "iiinstrument_utils.h"
00037 #include "iiinstrument_pfits.h"
00038 #include "iiinstrument_dfs.h"
00039 #include <cpl.h>
00040 #include <string.h>
00041 
00042 /*-----------------------------------------------------------------------------
00043                               Plugin registration
00044  -----------------------------------------------------------------------------*/
00045 
00046 int cpl_plugin_get_info(cpl_pluginlist * list);
00047 
00048 /*-----------------------------------------------------------------------------
00049                             Private function prototypes
00050  -----------------------------------------------------------------------------*/
00051 
00052 static int rrrecipe_calib_create(cpl_plugin *);
00053 static int rrrecipe_calib_exec(cpl_plugin *);
00054 static int rrrecipe_calib_destroy(cpl_plugin *);
00055 static int rrrecipe_calib(cpl_frameset *, const cpl_parameterlist *);
00056 
00057 /*-----------------------------------------------------------------------------
00058                             Static variables
00059  -----------------------------------------------------------------------------*/
00060 
00061 static char rrrecipe_calib_description[] =
00062 "This example text is used to describe the recipe.\n"
00063 "The description should include the required FITS-files and\n"
00064 "their associated tags, e.g.\n"
00065 "IIINSTRUMENT-RRRECIPE-CALIB-raw-file.fits " RRRECIPE_CALIB_RAW "\n"
00066 "\n"
00067 "Additionally, it should describe functionality of the expected output."
00068 "\n";
00069 
00070 /*-----------------------------------------------------------------------------
00071                                 Function code
00072  -----------------------------------------------------------------------------*/
00073 
00074 /*----------------------------------------------------------------------------*/
00084 /*----------------------------------------------------------------------------*/
00085 int cpl_plugin_get_info(cpl_pluginlist * list)
00086 {
00087     cpl_recipe  *   recipe = cpl_calloc(1, sizeof *recipe );
00088     cpl_plugin  *   plugin = &recipe->interface;
00089 
00090     if (cpl_plugin_init(plugin,
00091                     CPL_PLUGIN_API,
00092                     IIINSTRUMENT_BINARY_VERSION,
00093                     CPL_PLUGIN_TYPE_RECIPE,
00094                     "rrrecipe_calib",
00095                     "Short description of rrrecipe_calib",
00096                     rrrecipe_calib_description,
00097                     "Firstname Lastname",
00098                     PACKAGE_BUGREPORT,
00099                     iiinstrument_get_license(),
00100                     rrrecipe_calib_create,
00101                     rrrecipe_calib_exec,
00102                     rrrecipe_calib_destroy)) {    
00103         cpl_msg_error(cpl_func, "Plugin initialization failed");
00104         (void)cpl_error_set_where(cpl_func);                          
00105         return 1;                                               
00106     }                                                    
00107 
00108     if (cpl_pluginlist_append(list, plugin)) {                 
00109         cpl_msg_error(cpl_func, "Error adding plugin to list");
00110         (void)cpl_error_set_where(cpl_func);                         
00111         return 1;                                              
00112     }                                                          
00113     
00114     return 0;
00115 }
00116 
00117 /*----------------------------------------------------------------------------*/
00125 /*----------------------------------------------------------------------------*/
00126 static int rrrecipe_calib_create(cpl_plugin * plugin)
00127 {
00128     cpl_recipe    * recipe;                                               
00129     cpl_parameter * p;
00130                                                                        
00131     /* Do not create the recipe if an error code is already set */     
00132     if (cpl_error_get_code() != CPL_ERROR_NONE) {                      
00133         cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
00134                       cpl_func, __LINE__, cpl_error_get_where());      
00135         return (int)cpl_error_get_code();                              
00136     }                                                                  
00137                                                                        
00138     if (plugin == NULL) {                                              
00139         cpl_msg_error(cpl_func, "Null plugin");                        
00140         cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);                 
00141     }                                                                  
00142                                                                        
00143     /* Verify plugin type */                                           
00144     if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {       
00145         cpl_msg_error(cpl_func, "Plugin is not a recipe");             
00146         cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);              
00147     }                                                                  
00148                                                                        
00149     /* Get the recipe */                                               
00150     recipe = (cpl_recipe *)plugin;                                     
00151                                                                        
00152     /* Create the parameters list in the cpl_recipe object */          
00153     recipe->parameters = cpl_parameterlist_new();                      
00154     if (recipe->parameters == NULL) {                                  
00155         cpl_msg_error(cpl_func, "Parameter list allocation failed");   
00156         cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);             
00157     }                                                                  
00158 
00159     /* Fill the parameters list */
00160     /* --stropt */
00161     p = cpl_parameter_new_value("iiinstrument.rrrecipe_calib.str_option", 
00162             CPL_TYPE_STRING, "the string option", 
00163             "iiinstrument.rrrecipe_calib",NULL);
00164     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "stropt");
00165     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00166     cpl_parameterlist_append(recipe->parameters, p);
00167 
00168     /* --boolopt */
00169     p = cpl_parameter_new_value("iiinstrument.rrrecipe_calib.bool_option", 
00170             CPL_TYPE_BOOL, "a flag", "iiinstrument.rrrecipe_calib", TRUE);
00171     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "boolopt");
00172     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00173     cpl_parameterlist_append(recipe->parameters, p);
00174  
00175     return 0;
00176 }
00177 
00178 /*----------------------------------------------------------------------------*/
00184 /*----------------------------------------------------------------------------*/
00185 static int rrrecipe_calib_exec(cpl_plugin * plugin)
00186 {
00187 
00188     cpl_recipe * recipe;                                                   
00189     int recipe_status;                                                     
00190     cpl_errorstate initial_errorstate = cpl_errorstate_get();              
00191                                                                            
00192     /* Return immediately if an error code is already set */               
00193     if (cpl_error_get_code() != CPL_ERROR_NONE) {                          
00194         cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",    
00195                       cpl_func, __LINE__, cpl_error_get_where());          
00196         return (int)cpl_error_get_code();                                  
00197     }                                                                      
00198                                                                            
00199     if (plugin == NULL) {                                                  
00200         cpl_msg_error(cpl_func, "Null plugin");                            
00201         cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);                     
00202     }                                                                      
00203                                                                            
00204     /* Verify plugin type */                                               
00205     if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {           
00206         cpl_msg_error(cpl_func, "Plugin is not a recipe");                 
00207         cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);                  
00208     }                                                                      
00209                                                                            
00210     /* Get the recipe */                                                   
00211     recipe = (cpl_recipe *)plugin;                                         
00212                                                                            
00213     /* Verify parameter and frame lists */                                 
00214     if (recipe->parameters == NULL) {                                      
00215         cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
00216         cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);                     
00217     }                                                                      
00218     if (recipe->frames == NULL) {                                          
00219         cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");     
00220         cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);                     
00221     }                                                                      
00222                                                                            
00223     /* Invoke the recipe */                                                
00224     recipe_status = rrrecipe_calib(recipe->frames, recipe->parameters);
00225                                                                            
00226     /* Ensure DFS-compliance of the products */                            
00227     if (cpl_dfs_update_product_header(recipe->frames)) {                   
00228         if (!recipe_status) recipe_status = (int)cpl_error_get_code();                         
00229     }                                                                      
00230                                                                            
00231     if (!cpl_errorstate_is_equal(initial_errorstate)) {                    
00232         /* Dump the error history since recipe execution start.            
00233            At this point the recipe cannot recover from the error */       
00234         cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);          
00235     }                                                                      
00236                                                                            
00237     return recipe_status;                                                  
00238 }
00239 
00240 /*----------------------------------------------------------------------------*/
00246 /*----------------------------------------------------------------------------*/
00247 static int rrrecipe_calib_destroy(cpl_plugin * plugin)
00248 {
00249     cpl_recipe * recipe;                                          
00250                                                                   
00251     if (plugin == NULL) {                                         
00252         cpl_msg_error(cpl_func, "Null plugin");                   
00253         cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);            
00254     }                                                             
00255                                                                   
00256     /* Verify plugin type */                                      
00257     if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {  
00258         cpl_msg_error(cpl_func, "Plugin is not a recipe");        
00259         cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);         
00260     }                                                             
00261                                                                   
00262     /* Get the recipe */                                          
00263     recipe = (cpl_recipe *)plugin;                                
00264                                                                   
00265     cpl_parameterlist_delete(recipe->parameters);             
00266                                                                   
00267     return 0;                                                    
00268 }
00269 
00270 /*----------------------------------------------------------------------------*/
00277 /*----------------------------------------------------------------------------*/
00278 static int rrrecipe_calib(cpl_frameset            * frameset,
00279                     const cpl_parameterlist * parlist)
00280 {
00281     const cpl_parameter *   param;
00282     const char          *   str_option;
00283     int                     bool_option;
00284     cpl_frameset        *   rawframes;
00285     const cpl_frame     *   firstframe;
00286     double                  qc_param;
00287     cpl_propertylist    *   plist;
00288     cpl_propertylist    *   applist;
00289     cpl_image           *   image;
00290     int                     nraw;
00291     int                     i;
00292 
00293     /* Use the errorstate to detect an error in a function that does not
00294        return an error code. */
00295     cpl_errorstate          prestate = cpl_errorstate_get();
00296 
00297     /* HOW TO RETRIEVE INPUT PARAMETERS */
00298     /* --stropt */
00299     param = cpl_parameterlist_find_const(parlist,
00300                                      "iiinstrument.rrrecipe_calib.str_option");
00301     str_option = cpl_parameter_get_string(param);
00302 
00303     /* --boolopt */
00304     param = cpl_parameterlist_find_const(parlist,
00305                                     "iiinstrument.rrrecipe_calib.bool_option");
00306     bool_option = cpl_parameter_get_bool(param);
00307   
00308     if (!cpl_errorstate_is_equal(prestate)) {
00309         return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
00310                                           "Could not retrieve the input "
00311                                           "parameters");
00312     }
00313     
00314     /* Identify the RAW and CALIB frames in the input frameset */
00315     cpl_ensure_code(iiinstrument_dfs_set_groups(frameset) == CPL_ERROR_NONE,
00316                     cpl_error_get_code());
00317  
00318     /* HOW TO ACCESS INPUT DATA */
00319     /*  - A required file */
00320     rawframes = cpl_frameset_new();
00321     nraw = 0;
00322     for (i = 0; i<cpl_frameset_get_size(frameset); i++) {
00323         const cpl_frame * current_frame;
00324         current_frame = cpl_frameset_get_position_const(frameset, i);
00325         if(!strcmp(cpl_frame_get_tag(current_frame), RRRECIPE_CALIB_RAW)) {
00326             cpl_frame * new_frame = cpl_frame_duplicate(current_frame);
00327             cpl_frameset_insert(rawframes, new_frame);
00328             nraw++;
00329         }
00330     }
00331     if (nraw == 0) {
00332         return (int)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
00333                                           "SOF does not have any file tagged "
00334                                           "with %s", RRRECIPE_CALIB_RAW);
00335     }
00336     
00337 
00338     /* HOW TO GET THE FIRST FRAME OF A FRAME */ 
00339     firstframe = cpl_frameset_get_first_const(rawframes);
00340 
00341     /* HOW TO GET THE VALUE OF A FITS KEYWORD */
00342     /*  - Load only DETector related keys */
00343     plist = cpl_propertylist_load_regexp(cpl_frame_get_filename(firstframe),
00344                                          0, "ESO DET ", 0);
00345     if (plist == NULL) {
00346         /* In this case an error message is added to the error propagation */
00347         return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
00348                                           "Could not read the FITS header");
00349     }
00350 
00351     qc_param = iiinstrument_pfits_get_dit(plist);
00352     cpl_propertylist_delete(plist);
00353 
00354     /* Check for a change in the CPL error state */
00355     /* - if it did change then propagate the error and return */
00356     cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
00357     
00358     /* NOW PERFORMING THE DATA REDUCTION */
00359     /* Let's just load an image for the example */
00360     image = cpl_image_load(cpl_frame_get_filename(firstframe), CPL_TYPE_FLOAT, 0,
00361                            0);
00362     if (image == NULL) {
00363         return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
00364                                      "Could not load the image");
00365     }
00366 
00367     applist = cpl_propertylist_new();
00368 
00369     /* Add the product category  */
00370     cpl_propertylist_append_string(applist, CPL_DFS_PRO_CATG,
00371                                    RRRECIPE_OUT_CALIB_PROCATG);
00372 
00373     /* Add a QC parameter  */
00374     cpl_propertylist_append_double(applist, "ESO QC QCPARAM", qc_param);
00375     
00376     /* HOW TO SAVE A DFS-COMPLIANT PRODUCT TO DISK  */
00377     if (cpl_dfs_save_image(frameset, NULL, parlist, frameset, NULL, image,
00378                            CPL_BPP_IEEE_FLOAT, "rrrecipe_calib", applist,
00379                            NULL, PACKAGE "/" PACKAGE_VERSION,
00380                            "rrrecipe_calib.fits")) {
00381         /* Propagate the error */
00382         (void)cpl_error_set_where(cpl_func);
00383     }
00384 
00385     cpl_image_delete(image);
00386     cpl_propertylist_delete(applist);
00387 
00388     return (int)cpl_error_get_code();
00389 }