IIINSTRUMENT Pipeline Reference Manual  0.0.8
rrrecipe.c
00001 /* $Id: rrrecipe.c,v 1.33 2013-03-26 17:00:45 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:00:45 $
00024  * $Revision: 1.33 $
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 
00040 #include <cpl.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_create(cpl_plugin *);
00053 static int rrrecipe_exec(cpl_plugin *);
00054 static int rrrecipe_destroy(cpl_plugin *);
00055 static int rrrecipe(cpl_frameset *, const cpl_parameterlist *);
00056 
00057 /*-----------------------------------------------------------------------------
00058                             Static variables
00059  -----------------------------------------------------------------------------*/
00060 
00061 static char rrrecipe_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-raw-file.fits " RRRECIPE_RAW "\n"
00066 "and any optional files, e.g.\n"
00067 "IIINSTRUMENT-RRRECIPE-flat-file.fits " IIINSTRUMENT_CALIB_FLAT "\n"
00068 "\n"
00069 "Additionally, it should describe functionality of the expected output."
00070 "\n";
00071 
00072 /*-----------------------------------------------------------------------------
00073                                 Function code
00074  -----------------------------------------------------------------------------*/
00075 
00076 /*----------------------------------------------------------------------------*/
00086 /*----------------------------------------------------------------------------*/
00087 int cpl_plugin_get_info(cpl_pluginlist * list)
00088 {
00089     cpl_recipe  *   recipe = cpl_calloc(1, sizeof *recipe );
00090     cpl_plugin  *   plugin = &recipe->interface;
00091 
00092     if (cpl_plugin_init(plugin,
00093                     CPL_PLUGIN_API,
00094                     IIINSTRUMENT_BINARY_VERSION,
00095                     CPL_PLUGIN_TYPE_RECIPE,
00096                     "rrrecipe",
00097                     "Short description of rrrecipe",
00098                     rrrecipe_description,
00099                     "Firstname Lastname",
00100                     PACKAGE_BUGREPORT,
00101                     iiinstrument_get_license(),
00102                     rrrecipe_create,
00103                     rrrecipe_exec,
00104                     rrrecipe_destroy)) {    
00105         cpl_msg_error(cpl_func, "Plugin initialization failed");
00106         (void)cpl_error_set_where(cpl_func);                          
00107         return 1;                                               
00108     }                                                    
00109 
00110     if (cpl_pluginlist_append(list, plugin)) {                 
00111         cpl_msg_error(cpl_func, "Error adding plugin to list");
00112         (void)cpl_error_set_where(cpl_func);                         
00113         return 1;                                              
00114     }                                                          
00115     
00116     return 0;
00117 }
00118 
00119 /*----------------------------------------------------------------------------*/
00127 /*----------------------------------------------------------------------------*/
00128 static int rrrecipe_create(cpl_plugin * plugin)
00129 {
00130     cpl_recipe    * recipe;                                               
00131     cpl_parameter * p;
00132                                                                        
00133     /* Do not create the recipe if an error code is already set */     
00134     if (cpl_error_get_code() != CPL_ERROR_NONE) {                      
00135         cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
00136                       cpl_func, __LINE__, cpl_error_get_where());      
00137         return (int)cpl_error_get_code();                              
00138     }                                                                  
00139                                                                        
00140     if (plugin == NULL) {                                              
00141         cpl_msg_error(cpl_func, "Null plugin");                        
00142         cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);                 
00143     }                                                                  
00144                                                                        
00145     /* Verify plugin type */                                           
00146     if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {       
00147         cpl_msg_error(cpl_func, "Plugin is not a recipe");             
00148         cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);              
00149     }                                                                  
00150                                                                        
00151     /* Get the recipe */                                               
00152     recipe = (cpl_recipe *)plugin;                                     
00153                                                                        
00154     /* Create the parameters list in the cpl_recipe object */          
00155     recipe->parameters = cpl_parameterlist_new();                      
00156     if (recipe->parameters == NULL) {                                  
00157         cpl_msg_error(cpl_func, "Parameter list allocation failed");   
00158         cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);             
00159     }                                                                  
00160 
00161     /* Fill the parameters list */
00162     /* --stropt */
00163     p = cpl_parameter_new_value("iiinstrument.rrrecipe.str_option",
00164                                 CPL_TYPE_STRING, "the string option",
00165                                 "iiinstrument.rrrecipe", "NONE");
00166     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "stropt");
00167     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00168     cpl_parameterlist_append(recipe->parameters, p);
00169 
00170     p = cpl_parameter_new_value("iiinstrument.rrrecipe.file_option",
00171                                 CPL_TYPE_STRING, "the string option",
00172                                 "iiinstrument.rrrecipe", "NONE");
00173     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fileopt");
00174     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00175     cpl_parameterlist_append(recipe->parameters, p);
00176 
00177     /* --boolopt */
00178     p = cpl_parameter_new_value("iiinstrument.rrrecipe.bool_option",
00179                                 CPL_TYPE_BOOL, "a flag",
00180                                 "iiinstrument.rrrecipe", TRUE);
00181     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "boolopt");
00182     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00183     cpl_parameterlist_append(recipe->parameters, p);
00184 
00185     p = cpl_parameter_new_value("iiinstrument.rrrecipe.int_option",
00186                                 CPL_TYPE_INT, "a flag",
00187                                 "iiinstrument.rrrecipe", 3);
00188     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "intopt");
00189     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00190     cpl_parameterlist_append(recipe->parameters, p);
00191 
00192     p = cpl_parameter_new_range("iiinstrument.rrrecipe.range_option", CPL_TYPE_DOUBLE,
00193                                 "This is a value range of type double",
00194                                 "Example", 0.5, 0.0, 1.0);
00195     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rangeopt");
00196     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00197     cpl_parameterlist_append(recipe->parameters, p);
00198 
00199     p = cpl_parameter_new_enum("iiinstrument.rrrecipe.enum_option", CPL_TYPE_STRING,
00200                                "This is an enumeration of type " "string",
00201                                "Example", "first", 3, "first", "second", "third");
00202     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "enumopt");
00203     cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
00204     cpl_parameterlist_append(recipe->parameters, p);
00205 
00206  
00207     return 0;
00208 }
00209 
00210 /*----------------------------------------------------------------------------*/
00216 /*----------------------------------------------------------------------------*/
00217 static int rrrecipe_exec(cpl_plugin * plugin)
00218 {
00219 
00220     cpl_recipe * recipe;                                                   
00221     int recipe_status;                                                     
00222     cpl_errorstate initial_errorstate = cpl_errorstate_get();              
00223                                                                            
00224     /* Return immediately if an error code is already set */               
00225     if (cpl_error_get_code() != CPL_ERROR_NONE) {                          
00226         cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",    
00227                       cpl_func, __LINE__, cpl_error_get_where());          
00228         return (int)cpl_error_get_code();                                  
00229     }                                                                      
00230                                                                            
00231     if (plugin == NULL) {                                                  
00232         cpl_msg_error(cpl_func, "Null plugin");                            
00233         cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);                     
00234     }                                                                      
00235                                                                            
00236     /* Verify plugin type */                                               
00237     if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {           
00238         cpl_msg_error(cpl_func, "Plugin is not a recipe");                 
00239         cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);                  
00240     }                                                                      
00241                                                                            
00242     /* Get the recipe */                                                   
00243     recipe = (cpl_recipe *)plugin;                                         
00244                                                                            
00245     /* Verify parameter and frame lists */                                 
00246     if (recipe->parameters == NULL) {                                      
00247         cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
00248         cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);                     
00249     }                                                                      
00250     if (recipe->frames == NULL) {                                          
00251         cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");     
00252         cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);                     
00253     }                                                                      
00254                                                                            
00255     /* Invoke the recipe */                                                
00256     recipe_status = rrrecipe(recipe->frames, recipe->parameters);
00257                                                                            
00258     /* Ensure DFS-compliance of the products */                            
00259     if (cpl_dfs_update_product_header(recipe->frames)) {                   
00260         if (!recipe_status) recipe_status = (int)cpl_error_get_code();                         
00261     }                                                                      
00262                                                                            
00263     if (!cpl_errorstate_is_equal(initial_errorstate)) {                    
00264         /* Dump the error history since recipe execution start.            
00265            At this point the recipe cannot recover from the error */       
00266         cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);          
00267     }                                                                      
00268                                                                            
00269     return recipe_status;                                                  
00270 }
00271 
00272 /*----------------------------------------------------------------------------*/
00278 /*----------------------------------------------------------------------------*/
00279 static int rrrecipe_destroy(cpl_plugin * plugin)
00280 {
00281     cpl_recipe * recipe;                                          
00282                                                                   
00283     if (plugin == NULL) {                                         
00284         cpl_msg_error(cpl_func, "Null plugin");                   
00285         cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);            
00286     }                                                             
00287                                                                   
00288     /* Verify plugin type */                                      
00289     if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {  
00290         cpl_msg_error(cpl_func, "Plugin is not a recipe");        
00291         cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);         
00292     }                                                             
00293                                                                   
00294     /* Get the recipe */                                          
00295     recipe = (cpl_recipe *)plugin;                                
00296                                                                   
00297     cpl_parameterlist_delete(recipe->parameters);             
00298                                                                   
00299     return 0;                                                    
00300 }
00301 
00302 /*----------------------------------------------------------------------------*/
00309 /*----------------------------------------------------------------------------*/
00310 static int rrrecipe(cpl_frameset            * frameset,
00311                     const cpl_parameterlist * parlist)
00312 {
00313     const cpl_parameter *   param;
00314     const char          *   str_option;
00315     int                     bool_option;
00316     const cpl_frame     *   rawframe;
00317     const cpl_frame     *   flat;
00318     double                  qc_param;
00319     cpl_propertylist    *   plist;
00320     cpl_propertylist    *   applist;
00321     cpl_image           *   image;
00322 
00323     /* Use the errorstate to detect an error in a function that does not
00324        return an error code. */
00325     cpl_errorstate          prestate = cpl_errorstate_get();
00326 
00327     /* HOW TO RETRIEVE INPUT PARAMETERS */
00328     /* --stropt */
00329     param = cpl_parameterlist_find_const(parlist,
00330                                          "iiinstrument.rrrecipe.str_option");
00331     str_option = cpl_parameter_get_string(param);
00332 
00333     /* --boolopt */
00334     param = cpl_parameterlist_find_const(parlist,
00335                                          "iiinstrument.rrrecipe.bool_option");
00336     bool_option = cpl_parameter_get_bool(param);
00337   
00338     if (!cpl_errorstate_is_equal(prestate)) {
00339         return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
00340                                           "Could not retrieve the input "
00341                                           "parameters");
00342     }
00343     
00344     /* Identify the RAW and CALIB frames in the input frameset */
00345     cpl_ensure_code(iiinstrument_dfs_set_groups(frameset) == CPL_ERROR_NONE,
00346                     cpl_error_get_code());
00347  
00348     /* HOW TO ACCESS INPUT DATA */
00349     /*  - A required file */
00350     rawframe = cpl_frameset_find_const(frameset, RRRECIPE_RAW);
00351     if (rawframe == NULL) {
00352         /* cpl_frameset_find_const() does not set an error code, when a frame
00353            is not found, so we will set one here. */
00354         return (int)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
00355                                           "SOF does not have any file tagged "
00356                                           "with %s", RRRECIPE_RAW);
00357     }
00358     /* - A recommended file */
00359     flat = cpl_frameset_find(frameset, IIINSTRUMENT_CALIB_FLAT);
00360     if (flat == NULL) {
00361         cpl_msg_warning(cpl_func, "SOF does not have any file tagged with %s",
00362                         IIINSTRUMENT_CALIB_FLAT);
00363     }
00364     
00365     /* HOW TO GET THE VALUE OF A FITS KEYWORD */
00366     /*  - Load only DETector related keys */
00367     plist = cpl_propertylist_load_regexp(cpl_frame_get_filename(rawframe),
00368                                          0, "ESO DET ", 0);
00369     if (plist == NULL) {
00370         /* In this case an error message is added to the error propagation */
00371         return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
00372                                           "Could not read the FITS header");
00373     }
00374 
00375     qc_param = iiinstrument_pfits_get_dit(plist);
00376     cpl_propertylist_delete(plist);
00377 
00378     /* Check for a change in the CPL error state */
00379     /* - if it did change then propagate the error and return */
00380     cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
00381     
00382     /* NOW PERFORMING THE DATA REDUCTION */
00383     /* Let's just load an image for the example */
00384     image = cpl_image_load(cpl_frame_get_filename(rawframe), CPL_TYPE_FLOAT, 0,
00385                            0);
00386     if (image == NULL) {
00387         return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
00388                                      "Could not load the image");
00389     }
00390 
00391     applist = cpl_propertylist_new();
00392 
00393     /* Add the product category  */
00394     cpl_propertylist_append_string(applist, CPL_DFS_PRO_CATG,
00395                                    RRRECIPE_OUT_PROCATG);
00396 
00397     /* Add a QC parameter  */
00398     cpl_propertylist_append_double(applist, "ESO QC QCPARAM", qc_param);
00399     
00400     /* HOW TO SAVE A DFS-COMPLIANT PRODUCT TO DISK  */
00401     if (cpl_dfs_save_image(frameset, NULL, parlist, frameset, NULL, image,
00402                            CPL_BPP_IEEE_FLOAT, "rrrecipe", applist,
00403                            NULL, PACKAGE "/" PACKAGE_VERSION,
00404                            "rrrecipe.fits")) {
00405         /* Propagate the error */
00406         (void)cpl_error_set_where(cpl_func);
00407     }
00408 
00409     cpl_image_delete(image);
00410     cpl_propertylist_delete(applist);
00411 
00412     return (int)cpl_error_get_code();
00413 }