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