uves_parameters.c

00001 /*                                                                              *
00002  *   This file is part of the ESO UVES Pipeline                                 *
00003  *   Copyright (C) 2004,2005 European Southern Observatory                      *
00004  *                                                                              *
00005  *   This library is free software; you can redistribute it and/or modify       *
00006  *   it under the terms of the GNU General Public License as published by       *
00007  *   the Free Software Foundation; either version 2 of the License, or          *
00008  *   (at your option) any later version.                                        *
00009  *                                                                              *
00010  *   This program is distributed in the hope that it will be useful,            *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of             *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
00013  *   GNU General Public License for more details.                               *
00014  *                                                                              *
00015  *   You should have received a copy of the GNU General Public License          *
00016  *   along with this program; if not, write to the Free Software                *
00017  *   Foundation, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA       *
00018  *                                                                              */
00019 
00020 /*
00021  * $Author: amodigli $
00022  * $Date: 2008/04/02 14:03:51 $
00023  * $Revision: 1.48 $
00024  * $Name: uves-3_9_0 $
00025  * $Log: uves_parameters.c,v $
00026  * Revision 1.48  2008/04/02 14:03:51  amodigli
00027  * fixed compilation warnings
00028  *
00029  * Revision 1.47  2008/03/04 15:21:23  amodigli
00030  * fixed redchain problem with clean_traps parameter
00031  *
00032  * Revision 1.46  2008/03/03 16:34:52  amodigli
00033  * added parameter to control trap column correction
00034  *
00035  * Revision 1.45  2008/02/15 12:43:49  amodigli
00036  * allow lower/upper chip for parameter process_chip
00037  *
00038  * Revision 1.44  2007/10/29 08:11:31  amodigli
00039  * cleaned output
00040  *
00041  * Revision 1.43  2007/10/05 08:27:34  amodigli
00042  * added process_chip parameter
00043  *
00044  * Revision 1.42  2007/08/22 11:17:58  amodigli
00045  * fixed typo
00046  *
00047  * Revision 1.41  2007/08/21 13:08:26  jmlarsen
00048  * Removed irplib_access module, largely deprecated by CPL-4
00049  *
00050  * Revision 1.40  2007/08/17 10:08:12  amodigli
00051  * added case UVES_QCDARK_ID
00052  *
00053  * Revision 1.39  2007/06/26 13:34:55  jmlarsen
00054  * Exported function for FLAMES
00055  *
00056  * Revision 1.38  2007/06/14 11:12:00  jmlarsen
00057  * Expanded description of plotter parameter
00058  *
00059  * Revision 1.37  2007/06/06 08:17:33  amodigli
00060  * replace tab with 4 spaces
00061  *
00062  * Revision 1.36  2007/05/22 11:37:49  jmlarsen
00063  * Removed image plotting functionality
00064  *
00065  * Revision 1.35  2007/03/05 10:17:30  jmlarsen
00066  * Disabled strange msginfolevel parameter
00067  *
00068  * Revision 1.34  2007/02/09 13:39:31  jmlarsen
00069  * Use defines for recipe id
00070  *
00071  * Revision 1.33  2007/02/09 08:58:18  jmlarsen
00072  * Use define's rather than hard-coded recipe names
00073  *
00074  * Revision 1.32  2007/01/15 08:46:45  jmlarsen
00075  * Shortened lines
00076  *
00077  * Revision 1.31  2006/11/15 15:02:14  jmlarsen
00078  * Implemented const safe workarounds for CPL functions
00079  *
00080  * Revision 1.29  2006/11/15 14:04:08  jmlarsen
00081  * Removed non-const version of parameterlist_get_first/last/next which is
00082  * already in CPL, added const-safe wrapper, unwrapper and deallocator functions
00083  *
00084  * Revision 1.28  2006/11/13 14:23:55  jmlarsen
00085  * Removed workarounds for CPL const bugs
00086  *
00087  * Revision 1.27  2006/11/06 15:19:41  jmlarsen
00088  * Removed unused include directives
00089  *
00090  * Revision 1.26  2006/09/27 15:08:45  jmlarsen
00091  * Fixed doc. bug
00092  *
00093  * Revision 1.25  2006/09/20 12:53:57  jmlarsen
00094  * Replaced stringcat functions with uves_sprintf()
00095  *
00096  * Revision 1.24  2006/09/01 13:57:42  jmlarsen
00097  * Fixed bug that causing parameter class to change during propagation
00098  *
00099  * Revision 1.23  2006/08/18 07:07:43  jmlarsen
00100  * Switched order of cpl_calloc arguments
00101  *
00102  * Revision 1.22  2006/08/17 13:56:53  jmlarsen
00103  * Reduced max line length
00104  *
00105  * Revision 1.21  2006/08/14 15:21:08  jmlarsen
00106  * Update to CPL3
00107  *
00108  * Revision 1.20  2006/08/11 11:29:26  jmlarsen
00109  * Added explicit void at function definition
00110  *
00111  * Revision 1.19  2006/08/07 11:35:35  jmlarsen
00112  * Disabled parameter environment variable mode
00113  *
00114  * Revision 1.18  2006/07/03 13:17:12  jmlarsen
00115  * Changed order of global parameters
00116  *
00117  * Revision 1.17  2006/06/06 08:40:10  jmlarsen
00118  * Shortened max line length
00119  *
00120  * Revision 1.16  2006/06/01 14:43:17  jmlarsen
00121  * Added missing documentation
00122  *
00123  * Revision 1.15  2005/12/19 16:17:56  jmlarsen
00124  * Replaced bool -> int
00125  *
00126  */
00127 
00128 #ifdef HAVE_CONFIG_H
00129 #  include <config.h>
00130 #endif
00131 
00132 /*----------------------------------------------------------------------------*/
00140 /*----------------------------------------------------------------------------*/
00141 
00142 /*-----------------------------------------------------------------------------
00143                                 Includes
00144  -----------------------------------------------------------------------------*/
00145 
00146 #include <uves.h>
00147 #include <uves_parameters.h>
00148 #include <uves_dump.h>
00149 #include <uves_backsub.h>
00150 #include <uves_extract.h>
00151 #include <uves_rebin.h>
00152 #include <uves_mdark_impl.h>
00153 #include <uves_corrbadpix.h>
00154 #include <uves_reduce.h>
00155 #include <uves_utils_wrappers.h>
00156 #include <uves_error.h>
00157 #include <uves_msg.h>
00158 
00159 #include <cpl.h>
00160 
00161 /*-----------------------------------------------------------------------------
00162                             Functions prototypes
00163  -----------------------------------------------------------------------------*/
00164 static int propagate(const char *substep_id, const cpl_parameterlist *sub_parameters, 
00165              cpl_parameterlist *parent_parameters,
00166              const char *parent_id, const char *context);
00167 static cpl_parameter *
00168 create_parameter_enum_int   (const char *name, cpl_type type,
00169                  const char *description, const char *context, 
00170                  int default_value, int size, int *values);
00171 static cpl_parameter *
00172 create_parameter_enum_double(const char *name, cpl_type type, const char *description,
00173                  const char *context, double default_value, 
00174                  int size, double *values);
00175 static cpl_parameter *
00176 create_parameter_enum_string(const char *name, cpl_type type, const char *description,
00177                  const char *context, const char *default_value, 
00178                  int size, const char **values);
00179 /*-----------------------------------------------------------------------------
00180                             Defines
00181  -----------------------------------------------------------------------------*/
00182 #define FAIL(return_code, error_code, ...) do {       \
00183         cpl_msg_error(__func__, __VA_ARGS__);         \
00184         if (cpl_error_get_code() == CPL_ERROR_NONE) { \
00185           cpl_error_set(__func__, error_code);        \
00186         }                                             \
00187         return return_code;                           \
00188         } while(false)
00189 
00192 /*-----------------------------------------------------------------------------
00193                             Implementation
00194  -----------------------------------------------------------------------------*/
00195 
00196 /*---------------------------------------------------------------------------*/
00206 /*---------------------------------------------------------------------------*/
00207 
00208 cpl_error_code
00209 uves_corr_traps_define_parameters(cpl_parameterlist * parameters,
00210                                   const char *recipe_id)
00211 {
00212 
00213    //const char *context = "clean";
00214    const char *name = "";
00215    char *full_name = NULL;
00216    cpl_parameter *p;
00217 
00218     
00219    //
00220    name = "clean_traps";
00221    full_name = uves_sprintf("%s.%s",recipe_id,name);
00222 
00223    if((strcmp(recipe_id,"uves_obs_scired") == 0) ||
00224       (strcmp(recipe_id,"uves_obs_spatred") == 0) ||
00225       (strcmp(recipe_id,"uves_cal_tflat") == 0) ) {
00226 
00227       uves_parameter_new_value(p, full_name,
00228                                CPL_TYPE_BOOL,
00229                                "Detector traps clean. "
00230                                "If TRUE detector traps are corrected."
00231                                "The bad pixels are replaced by the average of "
00232                                "nearest good pixels in the same column, or simply marked "
00233                                "as bad. The positions of bad pixels are hard-coded "
00234                                "(as function of UVES chip).",
00235                                recipe_id,
00236                                CPL_FALSE);
00237  
00238 
00239       cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00240       cpl_parameterlist_append(parameters, p);
00241       cpl_free(full_name);
00242    } else if((strcmp(recipe_id,"uves_cal_mbias") == 0) ||
00243              (strcmp(recipe_id,"uves_cal_mkmaster") == 0) ) {
00244 
00245       uves_parameter_new_value(p, full_name,
00246                                CPL_TYPE_BOOL,
00247                                "Detector traps clean. "
00248                                "If TRUE detector traps are corrected."
00249                                "The bad pixels are replaced by the average of "
00250                                "nearest good pixels in the same column, or simply marked "
00251                                "as bad. The positions of bad pixels are hard-coded "
00252                                "(as function of UVES chip).",
00253                                recipe_id,
00254                                CPL_TRUE);
00255 
00256  
00257       cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00258       cpl_parameterlist_append(parameters, p);
00259       cpl_free(full_name);
00260 
00261    } else {
00262 
00263       uves_msg("Creation of trap not supported for recipe: '%s'",
00264                recipe_id);
00265 
00266    }
00267 
00268  
00269 
00270 
00271    if (cpl_error_get_code() != CPL_ERROR_NONE)
00272    {
00273       cpl_msg_error(__func__, 
00274                     "Creation of trap column parameters failed: '%s'",
00275                     cpl_error_get_where());
00276    }
00277     
00278    return cpl_error_get_code();
00279 
00280 
00281 }
00282 
00283 
00284 
00285 
00286 
00287 
00288 /*----------------------------------------------------------------------------*/
00297 /*----------------------------------------------------------------------------*/
00298 cpl_error_code
00299 uves_define_global_parameters(cpl_parameterlist *parlist)
00300 {
00301     const char *context = "uves";
00302     const char *name = "";
00303     char *full_name = NULL;
00304     cpl_parameter *p;
00305 
00306     {
00307     name = "debug";
00308     full_name = uves_sprintf("%s.%s", context, name);
00309     uves_parameter_new_value(p, full_name,
00310                     CPL_TYPE_BOOL,
00311                     "Whether or not to save intermediate "
00312                     "results to local directory",
00313                     context,
00314                     false);
00315     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00316     cpl_parameterlist_append(parlist, p);
00317     cpl_free(full_name);
00318     }
00319 
00320 
00321     {
00322         name = "plotter";
00323         full_name = uves_sprintf("%s.%s", context, name);
00324         uves_parameter_new_value(
00325             p, full_name,
00326             CPL_TYPE_STRING,
00327             "Any plots produced by the recipe "
00328             "are redirected to the command specified "
00329             "by this parameter. The plotting command "
00330             "must contain the substring 'gnuplot' and "
00331             "must be able to parse gnuplot syntax on its "
00332             "standard input. "
00333             "Valid examples of such a command may include "
00334             "'gnuplot -persist' and 'cat > mygnuplot$$.gp'. "
00335             "A finer control of the plotting options can "
00336             "be obtained by writing an "
00337             "executable script, e.g. my_gnuplot.pl, that "
00338             "executes gnuplot after setting the desired gnuplot "
00339             "options (e.g. set terminal pslatex color). "
00340             "To turn off plotting, set this parameter to 'no'",
00341             context,
00342             "no");
00343 
00344         cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00345         cpl_parameterlist_append(parlist, p);
00346         cpl_free(full_name);
00347     }
00348 
00349 
00350 
00351    {
00352     name = "process_chip";
00353     full_name = uves_sprintf("%s.%s", context, name);
00354     uves_parameter_new_enum(p, full_name,
00355                     CPL_TYPE_STRING,
00356                     "In case of RED arm data allow to proces the "
00357                  "redl, redu, or both chip(s)",
00358                     context,
00359                             "both",5,"both","redl","redu","REDL","REDU");
00360     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00361     cpl_parameterlist_append(parlist, p);
00362     cpl_free(full_name);
00363     }
00364 
00365     if (0)
00366         /* The meaning of this parameter often escapes the developers,
00367            so let's not expose it to the users */
00368         {
00369         name = "msginfolevel";
00370     full_name = uves_sprintf("%s.%s", context, name);
00371     uves_parameter_new_range(p, full_name,
00372                     CPL_TYPE_INT,
00373                     "This parameter controls the subdivision "
00374                     "of the 'info' message level (set e.g. with "
00375                     "esorex' --msg-level). The higher the value "
00376                     "of this parameter, the more messages are "
00377                     "printed at the info level. For minimum "
00378                     "output, set to zero. Increase the level "
00379                     "(to 1, 2, 3, ...) for more output. The "
00380                     "value -1 is a special value meaning maximum "
00381                     "output",
00382                     context,
00383                     -1,                 /* Default */
00384                     -1, INT_MAX);       /* Range   */
00385     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00386     cpl_parameterlist_append(parlist, p);
00387     cpl_free(full_name);
00388     }
00389 
00390     if (cpl_error_get_code() != CPL_ERROR_NONE)
00391     {
00392         cpl_msg_error(__func__, "Creation of global parameters failed: '%s'",
00393               cpl_error_get_where());
00394     }
00395     
00396     return cpl_error_get_code();
00397 }
00398 
00399 
00400 
00401 /*----------------------------------------------------------------------------*/
00416 /*----------------------------------------------------------------------------*/
00417 
00418 int
00419 uves_exec_recipe(int (*get_info)(cpl_pluginlist *), 
00420                  const char *recipe_domain,
00421                  const cpl_parameterlist *parameters, 
00422                  cpl_frameset *frames,
00423                  const char *caller_id, const char *context)
00424 {
00425     cpl_pluginlist *list  = NULL;
00426     cpl_plugin *plugin    = NULL;
00427     cpl_recipe *recipe    = NULL;
00428 
00429     const char *recipe_id = NULL;
00430     cpl_parameter *p      = NULL;
00431     char *parent_name     = NULL;
00432     char *sub_domain      = NULL;
00433     int status = 0;
00434 
00435     bool must_destroy_plugin = false;   /* Indicates if recipe_create() 
00436                        has been called */
00437 
00438     /* Check input */
00439     assure(recipe_domain != NULL, CPL_ERROR_NULL_INPUT, "Null recipe message domain");
00440     assure(parameters != NULL, CPL_ERROR_NULL_INPUT, "Null parameter list");
00441     assure(frames != NULL, CPL_ERROR_NULL_INPUT, "Null frame set");
00442     assure(caller_id != NULL, CPL_ERROR_NULL_INPUT, "Null caller recipe name");
00443     /* 'context' may be NULL */    
00444 
00445     /* Get the sub-recipe plugin */
00446     check( list = cpl_pluginlist_new(),
00447        "Error allocating plugin list");
00448 
00449     /* Get info about recipe */
00450     status = get_info(list);
00451 
00452     assure( status == 0, CPL_ERROR_ILLEGAL_INPUT, 
00453         "Could not get info about recipe");
00454 
00455     /* Get default parameter list */
00456     check( plugin = cpl_pluginlist_get_first(list), "Error getting plugin");
00457     assure( plugin != NULL, CPL_ERROR_ILLEGAL_INPUT,
00458             "Plugin '%s' returned empty plugin list", recipe_id);
00459     assure( cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE, 
00460             CPL_ERROR_TYPE_MISMATCH, "Plugin is not a recipe");
00461     recipe = (cpl_recipe *) plugin;
00462     
00463     recipe_id = cpl_strdup(cpl_plugin_get_name(plugin));
00464 
00465     /* Call initializer function */
00466     must_destroy_plugin = true;
00467     assure( cpl_plugin_get_init(plugin)(plugin) == 0, CPL_ERROR_ILLEGAL_INPUT,
00468         "Error initializing recipe");
00469     assure( recipe->parameters != NULL, CPL_ERROR_ILLEGAL_INPUT,
00470         "Recipe '%s' returned NULL parameter list", recipe_id);
00471 
00472     /* For each recipe parameter x:
00473        Set to value of C.x (from argument parameter list)
00474 
00475        Parameters in 'uves' context are simply overwritten
00476     */
00477     for (p = cpl_parameterlist_get_first(recipe->parameters); 
00478      p != NULL;
00479      p = cpl_parameterlist_get_next(recipe->parameters) )
00480     {
00481         const char *name          = cpl_parameter_get_name(p);   
00482         const char *subcontext    = cpl_parameter_get_context(p);
00483         cpl_type type             = cpl_parameter_get_type(p);
00484         
00485         const cpl_parameter *parent;
00486         
00487         if (strcmp(subcontext, "uves") == 0)
00488         {
00489             parent_name = uves_sprintf("%s", name);
00490         }
00491         else
00492         {
00493             if (context != NULL)
00494             {
00495                 parent_name = uves_sprintf("%s.%s.%s", caller_id, context, name);
00496             }
00497             else
00498             {
00499                 parent_name = uves_sprintf("%s.%s", caller_id, name);
00500             }
00501         }
00502         
00503         /* Const cast, we don't change the parameter list, parent is declared const */
00504         check( parent = cpl_parameterlist_find_const(parameters, parent_name),
00505            "Could not get parameter '%s' from provided parameter list", parent_name);
00506         
00507         assure( parent != NULL, CPL_ERROR_DATA_NOT_FOUND,
00508             "Missing parameter '%s' needed to define '%s' in context '%s'",
00509             parent_name, name, context);
00510         
00511         assure( cpl_parameter_get_type(parent) == type, CPL_ERROR_TYPE_MISMATCH,
00512             "Parameter '%s' type is %s. Type %s needed for recipe parameter '%s'",
00513             parent_name, 
00514             uves_tostring_cpl_type(cpl_parameter_get_type(parent)),
00515             uves_tostring_cpl_type(type),
00516             name);
00517             
00518         switch (type)
00519         {
00520             int value_int;  
00521             bool value_bool;
00522             double value_double;
00523             const char *value_string;
00524 
00525         case CPL_TYPE_BOOL:
00526             check( value_bool = cpl_parameter_get_bool(parent), 
00527                "Error reading parameter '%s'", parent_name);
00528         
00529             check( cpl_parameter_set_bool(p, value_bool),
00530                "Error setting parameter '%s'", name);
00531             
00532             uves_msg_debug("Setting parameter '%s' <- '%s' = %s",
00533                    name, parent_name, (value_bool) ? "true" : "false");
00534             break;
00535 
00536         case CPL_TYPE_INT:
00537             check( value_int = cpl_parameter_get_int(parent),
00538                "Error reading parameter '%s'", parent_name);
00539         
00540             check( cpl_parameter_set_int(p, value_int),
00541                "Error setting parameter '%s'", name);
00542             
00543             uves_msg_debug("Setting parameter '%s' <- '%s' = %d", 
00544                    name, parent_name, value_int);
00545             break;
00546             
00547         case CPL_TYPE_DOUBLE:
00548             check( value_double = cpl_parameter_get_double(parent),
00549                "Error reading parameter '%s'", parent_name);
00550         
00551             check( cpl_parameter_set_double(p, value_double),
00552                "Error setting parameter '%s'", name);
00553             
00554             uves_msg_debug("Setting parameter '%s' <- '%s' = %e", 
00555                    name, parent_name, value_double);
00556             break;
00557             
00558         case CPL_TYPE_STRING:
00559             check( value_string = cpl_parameter_get_string(parent),
00560                "Error reading parameter '%s'", parent_name);
00561             
00562             check( cpl_parameter_set_string(p, value_string), 
00563                "Error setting parameter '%s'", name);
00564             
00565             uves_msg_debug("Setting parameter '%s' <- '%s' = '%s'", 
00566                    name, parent_name, value_string);
00567             break;
00568             
00569         default:
00570             assure(false, CPL_ERROR_UNSUPPORTED_MODE,
00571                "Parameter '%s' has type %s",
00572                name, uves_tostring_cpl_type(type));
00573         }  /* switch type */
00574         
00575         cpl_free(parent_name); parent_name = NULL;
00576         
00577     } /* Set each recipe parameter */
00578 
00579     /* Pass frame set without touching */
00580     recipe->frames = frames;
00581 
00582     /* 
00583      * Invoke recipe 
00584      *
00585      *  Remember message domain of caller,
00586      *   and number of warnings in caller.
00587      */
00588 
00589     {
00590     const char *domain = uves_msg_get_domain();
00591     int warnings_in_caller = uves_msg_get_warnings();
00592 
00593     sub_domain = uves_sprintf("%s.%s", domain, recipe_domain);
00594     uves_msg_set_domain(sub_domain);
00595 
00596     status = cpl_plugin_get_exec(plugin)(plugin);
00597 
00598     /* Reset state (domain+warnings) */
00599 
00600     uves_msg_set_domain(domain);
00601 
00602     /* Total number of warnings in caller is not
00603      * (previous warnings) + (subrecipe warnings)
00604      */
00605     uves_msg_add_warnings(warnings_in_caller);
00606     }
00607     
00608     /* On recipe failure: The recipe is responsible 
00609      *  for printing any error messages.
00610      *  A failing recipe is an unrecoverable error.
00611      */
00612 
00613     if (cpl_error_get_code() != CPL_ERROR_NONE)
00614     {
00615         /* Reset error stack but keep error code */
00616         cpl_error_code ec = cpl_error_get_code();
00617         uves_error_reset();
00618         assure( false, ec, "Recipe '%s' failed", recipe_id);
00619     }
00620     
00621     assure( status == 0, CPL_ERROR_ILLEGAL_OUTPUT,
00622         "Recipe '%s' failed with exit status %d", recipe_id, status);
00623     
00624     /* Call recipe_destroy */
00625     must_destroy_plugin = false;
00626     assure( cpl_plugin_get_deinit(plugin)(plugin) == 0, 
00627         CPL_ERROR_ILLEGAL_OUTPUT,
00628         "Error cleaning up recipe");
00629     
00630     uves_msg("Recipe '%s' succeeded", recipe_id);
00631 
00632   cleanup:
00633     uves_free_string_const(&recipe_id);
00634     cpl_free(parent_name); parent_name = NULL;
00635     cpl_free(sub_domain); sub_domain = NULL;
00636     if (must_destroy_plugin)
00637     {
00638         cpl_plugin_get_deinit(plugin)(plugin);
00639     }
00640 
00641     cpl_pluginlist_delete(list);
00642     
00643     return (cpl_error_get_code() != CPL_ERROR_NONE);
00644 }
00645 
00646 /*----------------------------------------------------------------------------*/
00661 /*----------------------------------------------------------------------------*/
00662 
00663 int
00664 uves_invoke_recipe(const char *recipe_id, const cpl_parameterlist *parameters, 
00665                    cpl_frameset *frames,
00666                    const char *caller_id, const char *context)
00667 {
00668     assure(recipe_id != NULL, CPL_ERROR_NULL_INPUT, "Null recipe name");
00669 
00670     if      (strcmp(recipe_id, make_str(UVES_PHYSMOD_ID) ) == 0) return uves_exec_recipe(&uves_physmod_get_info, UVES_PHYSMOD_DOM, parameters, frames, caller_id, context);
00671     else if (strcmp(recipe_id, make_str(UVES_ORDERPOS_ID)) == 0) return uves_exec_recipe(&uves_orderpos_get_info, UVES_ORDERPOS_DOM, parameters, frames, caller_id, context);
00672     else if (strcmp(recipe_id, make_str(UVES_MBIAS_ID)   ) == 0) return uves_exec_recipe(&uves_mbias_get_info, UVES_MBIAS_DOM, parameters, frames, caller_id, context);
00673     else if (strcmp(recipe_id, make_str(UVES_MDARK_ID)   ) == 0) return uves_exec_recipe(&uves_mdark_get_info, UVES_MDARK_DOM, parameters, frames, caller_id, context);
00674     else if (strcmp(recipe_id, make_str(UVES_MFLAT_ID)   ) == 0) return uves_exec_recipe(&uves_mflat_get_info,  UVES_MFLAT_DOM, parameters, frames, caller_id, context);
00675     else if (strcmp(recipe_id, make_str(UVES_WAVECAL_ID) ) == 0) return uves_exec_recipe(&uves_wavecal_get_info,  UVES_WAVECAL_DOM, parameters, frames, caller_id, context);
00676     else if (strcmp(recipe_id, make_str(UVES_RESPONSE_ID)) == 0) return uves_exec_recipe(&uves_response_get_info, UVES_RESPONSE_DOM, parameters, frames, caller_id, context);
00677     else if (strcmp(recipe_id, make_str(UVES_SCIRED_ID)  ) == 0) return uves_exec_recipe(&uves_scired_get_info, UVES_SCIRED_DOM, parameters, frames, caller_id, context);
00678     else if (strcmp(recipe_id, make_str(UVES_REDCHAIN_ID)) == 0) return uves_exec_recipe(&uves_redchain_get_info, UVES_REDCHAIN_DOM, parameters, frames, caller_id, context);
00679     else
00680         {
00681             assure( false, CPL_ERROR_ILLEGAL_INPUT, "Unknown recipe: '%s'", recipe_id);
00682         }
00683   cleanup:
00684     return (cpl_error_get_code() != CPL_ERROR_NONE);
00685 }
00686 
00687 
00688 /*----------------------------------------------------------------------------*/
00706 /*----------------------------------------------------------------------------*/
00707 int
00708 uves_prop_par(int (*get_info)(cpl_pluginlist *),
00709     cpl_parameterlist *parameters,
00710     const char *recipe_id, const char *context)
00711 {
00712     cpl_plugin *plugin    = NULL;
00713     cpl_pluginlist *list  = NULL;
00714     cpl_recipe *subrecipe = NULL;
00715     const char *name      = NULL;
00716     int status;
00717 
00718     /* Check input */
00719     if (get_info == NULL)
00720     {
00721         FAIL(-1, CPL_ERROR_NULL_INPUT, "Null function pointer");
00722     }
00723     /* context may be NULL */
00724     if (parameters == NULL)
00725     {
00726         FAIL(-1, CPL_ERROR_NULL_INPUT, "Null parameter list");
00727     }
00728     
00729     if (recipe_id == NULL)
00730     {
00731         FAIL(-1, CPL_ERROR_NULL_INPUT, "Null recipe id");
00732     }    
00733 
00734     /* Get the sub-recipe plugin */
00735     list = cpl_pluginlist_new();
00736     status = get_info(list);
00737     
00738     if (status != 0)
00739     {
00740         cpl_pluginlist_delete(list);
00741         FAIL(-1, CPL_ERROR_ILLEGAL_INPUT, "Could not get info about recipe");
00742     }
00743 
00744     /* Get first plugin in plugin list, it must be of type recipe */
00745     if ((plugin = cpl_pluginlist_get_first(list)) == NULL)
00746     {
00747         cpl_pluginlist_delete(list);
00748         FAIL(-1, CPL_ERROR_ILLEGAL_INPUT, "Error getting plugin");
00749     }
00750     if (cpl_plugin_get_name(plugin) == NULL) {
00751         cpl_pluginlist_delete(list);
00752         FAIL(-1, CPL_ERROR_ILLEGAL_INPUT, "Plugin name is NULL");
00753     }
00754     name = cpl_strdup(cpl_plugin_get_name(plugin));
00755     
00756     if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE)
00757         {
00758             cpl_pluginlist_delete(list);
00759             FAIL(-1, CPL_ERROR_TYPE_MISMATCH, "Plugin is not a recipe");
00760         }
00761     subrecipe = (cpl_recipe *) plugin;
00762     
00763     /* Create parameter list by calling subrecipe initializer function */
00764     if( cpl_plugin_get_init(plugin)(plugin) != 0)
00765     {
00766         cpl_plugin_get_deinit(plugin)(plugin);
00767         cpl_pluginlist_delete(list);
00768         FAIL(-1, CPL_ERROR_ILLEGAL_INPUT, "Error getting '%s' parameter list",
00769              name);
00770     }
00771 
00772     if (subrecipe->parameters == NULL)
00773     {
00774         cpl_plugin_get_deinit(plugin)(plugin);
00775         cpl_pluginlist_delete(list);
00776         FAIL(-1, CPL_ERROR_NULL_INPUT, "Recipe '%s' returned NULL parameter list", 
00777              name);
00778     }
00779     
00780     if (propagate(cpl_plugin_get_name(plugin), subrecipe->parameters, parameters, recipe_id, context) != 0)
00781     {
00782         cpl_plugin_get_deinit(plugin)(plugin);
00783         cpl_pluginlist_delete(list);
00784         FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT, "Error propagating parameters from recipe '%s'", 
00785              name);
00786     }
00787     
00788     cpl_plugin_get_deinit(plugin)(plugin);
00789     cpl_pluginlist_delete(list);
00790     
00791     return 0;
00792 }
00793 
00794 /*----------------------------------------------------------------------------*/
00800 /*----------------------------------------------------------------------------*/
00801 int
00802 uves_propagate_parameters(const char *subrecipe,
00803                           cpl_parameterlist *parameters,
00804                           const char *recipe_id, const char *context)
00805 {
00806     if (subrecipe == NULL) {
00807         FAIL(-1, CPL_ERROR_NULL_INPUT, "Null subrecipe id");
00808     }
00809     
00810     if      (strcmp(subrecipe, make_str(UVES_PHYSMOD_ID) ) == 0) return uves_prop_par(&uves_physmod_get_info, parameters, recipe_id, context);
00811     else if (strcmp(subrecipe, make_str(UVES_ORDERPOS_ID)) == 0) return uves_prop_par(&uves_orderpos_get_info, parameters, recipe_id, context);
00812     else if (strcmp(subrecipe, make_str(UVES_MBIAS_ID)   ) == 0) return uves_prop_par(&uves_mbias_get_info, parameters, recipe_id, context);
00813     else if (strcmp(subrecipe, make_str(UVES_MDARK_ID)   ) == 0) return uves_prop_par(&uves_mdark_get_info, parameters, recipe_id, context);
00814     else if (strcmp(subrecipe, make_str(UVES_MFLAT_ID)   ) == 0) return uves_prop_par(&uves_mflat_get_info, parameters, recipe_id, context);
00815     else if (strcmp(subrecipe, make_str(UVES_WAVECAL_ID) ) == 0) return uves_prop_par(&uves_wavecal_get_info, parameters, recipe_id, context);
00816     else if (strcmp(subrecipe, make_str(UVES_RESPONSE_ID)) == 0) return uves_prop_par(&uves_response_get_info, parameters, recipe_id, context);
00817     else if (strcmp(subrecipe, make_str(UVES_SCIRED_ID)  ) == 0) return uves_prop_par(&uves_scired_get_info, parameters, recipe_id, context);
00818     else if (strcmp(subrecipe, make_str(UVES_REDCHAIN_ID)) == 0) return uves_prop_par(&uves_redchain_get_info, parameters, recipe_id, context);
00819     else {
00820         FAIL(-1, CPL_ERROR_DATA_NOT_FOUND, "Unknown recipe: '%s'", subrecipe);
00821     }
00822 }
00823 
00824 /*----------------------------------------------------------------------------*/
00869 /*----------------------------------------------------------------------------*/
00870 
00871 int
00872 uves_propagate_parameters_step(const char *step_id,
00873                    cpl_parameterlist *parameters,
00874                    const char *recipe_id, const char *context)
00875 {
00876     cpl_parameterlist *subparameters = NULL;
00877     cpl_parameterlist *(*get_parameters)(void) = NULL; /* Pointer to function 
00878                               returning parameter list */
00879     
00880     /* Check input */
00881     if (step_id == NULL)
00882     {
00883         FAIL(-1, CPL_ERROR_NULL_INPUT, "Null parameter list");
00884     }
00885     
00886     if (parameters == NULL)
00887     {
00888         FAIL(-1, CPL_ERROR_NULL_INPUT, "Null parameter list");
00889     }
00890     
00891     if (recipe_id == NULL)
00892     {
00893         FAIL(-1, CPL_ERROR_NULL_INPUT, "Null recipe id");
00894     }    
00895     /* context may be NULL */
00896     
00897     /* Define which function to call */
00898            if (strcmp(step_id, UVES_BACKSUB_ID ) == 0) {
00899       get_parameters = uves_backsub_define_parameters;
00900     } else if (strcmp(step_id, UVES_QCDARK_ID ) == 0) {
00901       get_parameters = uves_qcdark_define_parameters;
00902     } else if (strcmp(step_id, UVES_EXTRACT_ID ) == 0) {
00903       get_parameters = uves_extract_define_parameters;
00904     } else if (strcmp(step_id, UVES_REBIN_ID   ) == 0) {
00905       get_parameters = uves_rebin_define_parameters;
00906     } else if (strcmp(step_id, UVES_REDUCE_ID  ) == 0) {
00907       get_parameters = uves_reduce_define_parameters;
00908     } else {
00909       FAIL(-1, CPL_ERROR_DATA_NOT_FOUND, "Unknown sub-step: '%s'", step_id);
00910     }
00911 
00912     /* Get sub-step parameters */
00913     if( (subparameters = get_parameters()) == NULL )
00914     {
00915         FAIL(-1, CPL_ERROR_ILLEGAL_INPUT, "Error getting '%s' parameter list", step_id);
00916     }
00917     
00918     if ( propagate(step_id, subparameters, parameters, recipe_id, context) != 0)
00919     {
00920         cpl_parameterlist_delete(subparameters);
00921         FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT, "Error propagating '%s' parameters", step_id);
00922     }
00923     
00924     cpl_parameterlist_delete(subparameters);
00925     return 0;
00926 }
00927 
00928 
00929 /*
00930  * Create an enumeration parameter.
00931  * One function for each of  int, double, string
00932  *    size of values array must match 'size', returns NULL iff error. 
00933  *
00934  * It would be much nicer to use a cpl_parameter_duplicate(), but that
00935  * doesn't exist
00936  *
00937  * (These three functions could be reduced to one function by use
00938  * of void pointers, but that is also ugly)
00939  */
00940 static cpl_parameter *
00941 create_parameter_enum_int(const char *name, cpl_type type,
00942               const char *description, 
00943               const char *context, 
00944               int default_value, int size,
00945               int *values)
00946 {
00947     /*  This is just ugly */
00948 
00949     cpl_parameter *result = NULL;
00950     
00951     if (! (1 <= size && size <= 10))
00952     {
00953         cpl_msg_error(__func__, "Unsupported enumeration size: %d (max is 10)", size);
00954         return NULL;
00955     }
00956     
00957     switch(size)
00958     {
00959     case 1:
00960         uves_parameter_new_enum(result, name,
00961                        type,
00962                        description,
00963                        context,
00964                        default_value, size,
00965                        values[0]);
00966         break;
00967     case 2:
00968         uves_parameter_new_enum(result, name,
00969                           type,
00970                           description,
00971                           context,
00972                           default_value, size,
00973                           values[0],
00974                           values[1]);
00975         break;
00976     case 3:
00977         uves_parameter_new_enum(result, name,
00978                           type,
00979                           description,
00980                           context,
00981                           default_value, size,
00982                           values[0],
00983                           values[1],
00984                           values[2]);
00985         break;
00986     case 4:
00987         uves_parameter_new_enum(result, name,
00988                           type,
00989                           description,
00990                           context,
00991                           default_value, size,
00992                           values[0], 
00993                           values[1], 
00994                           values[2], 
00995                           values[3]);
00996         break;
00997     case 5:
00998         uves_parameter_new_enum(result, name,
00999                           type,
01000                           description,
01001                           context,
01002                           default_value, size,
01003                           values[0], 
01004                           values[1], 
01005                           values[2], 
01006                           values[3], 
01007                           values[4]);
01008         break;
01009     case 6:
01010         uves_parameter_new_enum(result, name,
01011                           type,
01012                           description,
01013                           context,
01014                           default_value, size,
01015                           values[0], 
01016                           values[1], 
01017                           values[2], 
01018                           values[3], 
01019                           values[4], 
01020                           values[5]);
01021         break;
01022     case 7:
01023         uves_parameter_new_enum(result, name,
01024                           type,
01025                           description,
01026                           context,
01027                           default_value, size,
01028                           values[0], 
01029                           values[1], 
01030                           values[2], 
01031                           values[3], 
01032                           values[4], 
01033                           values[5], 
01034                           values[6]);
01035         break;
01036     case 8:
01037         uves_parameter_new_enum(result, name,
01038                           type,
01039                           description,
01040                           context,
01041                           default_value, size,
01042                           values[0], 
01043                           values[1], 
01044                           values[2], 
01045                           values[3], 
01046                           values[4], 
01047                           values[5], 
01048                           values[6], 
01049                           values[7]);
01050         break;
01051     case 9:
01052         uves_parameter_new_enum(result, name,
01053                           type,
01054                           description,
01055                           context,
01056                           default_value, size,
01057                           values[0], 
01058                           values[1], 
01059                           values[2], 
01060                           values[3], 
01061                           values[4], 
01062                           values[5], 
01063                           values[6], 
01064                           values[7], 
01065                           values[8]);
01066         break;
01067     case 10:
01068         uves_parameter_new_enum(result, name,
01069                        type,
01070                        description,
01071                        context,
01072                        default_value, size,
01073                        values[0], 
01074                        values[1], 
01075                        values[2], 
01076                        values[3], 
01077                        values[4], 
01078                        values[5], 
01079                        values[6], 
01080                        values[7], 
01081                        values[8], 
01082                        values[9]);
01083         break;
01084     } /* Switch size */
01085     return result;
01086 }
01087 static cpl_parameter *
01088 create_parameter_enum_double(const char *name, cpl_type type,
01089                  const char *description, 
01090                  const char *context, double default_value,
01091                  int size, double *values)
01092 {
01093     /*  This is very ugly */
01094     
01095     cpl_parameter *result = NULL; 
01096 
01097     if (! (1 <= size && size <= 10))
01098     {
01099         cpl_msg_error(__func__, "Unsupported enumeration size: %d (max is 10)", size);
01100         return NULL;
01101     }
01102     
01103     switch(size)
01104     {
01105     case 1:
01106         uves_parameter_new_enum(result, name,
01107                        type,
01108                        description,
01109                        context,
01110                        default_value, size,
01111                        values[0]);
01112         break;
01113     case 2:
01114         uves_parameter_new_enum(result, name,
01115                           type,
01116                           description,
01117                           context,
01118                           default_value, size,
01119                           values[0],
01120                           values[1]);
01121         break;
01122     case 3:
01123         uves_parameter_new_enum(result, name,
01124                           type,
01125                           description,
01126                           context,
01127                           default_value, size,
01128                           values[0],
01129                           values[1],
01130                           values[2]);
01131         break;
01132     case 4:
01133         uves_parameter_new_enum(result, name,
01134                           type,
01135                           description,
01136                           context,
01137                           default_value, size,
01138                           values[0], 
01139                           values[1], 
01140                           values[2], 
01141                           values[3]);
01142         break;
01143     case 5:
01144         uves_parameter_new_enum(result, name,
01145                           type,
01146                           description,
01147                           context,
01148                           default_value, size,
01149                           values[0], 
01150                           values[1], 
01151                           values[2], 
01152                           values[3], 
01153                           values[4]);
01154         break;
01155     case 6:
01156         uves_parameter_new_enum(result, name,
01157                           type,
01158                           description,
01159                           context,
01160                           default_value, size,
01161                           values[0], 
01162                           values[1], 
01163                           values[2], 
01164                           values[3], 
01165                           values[4], 
01166                           values[5]);
01167         break;
01168     case 7:
01169         uves_parameter_new_enum(result, name,
01170                           type,
01171                           description,
01172                           context,
01173                           default_value, size,
01174                           values[0], 
01175                           values[1], 
01176                           values[2], 
01177                           values[3], 
01178                           values[4], 
01179                           values[5], 
01180                           values[6]);
01181         break;
01182     case 8:
01183         uves_parameter_new_enum(result, name,
01184                           type,
01185                           description,
01186                           context,
01187                           default_value, size,
01188                           values[0], 
01189                           values[1], 
01190                           values[2], 
01191                           values[3], 
01192                           values[4], 
01193                           values[5], 
01194                           values[6], 
01195                           values[7]);
01196         break;
01197     case 9:
01198         uves_parameter_new_enum(result, name,
01199                           type,
01200                           description,
01201                           context,
01202                           default_value, size,
01203                           values[0], 
01204                           values[1], 
01205                           values[2], 
01206                           values[3], 
01207                           values[4], 
01208                           values[5], 
01209                           values[6], 
01210                           values[7], 
01211                           values[8]);
01212         break;
01213     case 10:
01214         uves_parameter_new_enum(result, name,
01215                        type,
01216                        description,
01217                        context,
01218                        default_value, size,
01219                        values[0], 
01220                        values[1], 
01221                        values[2], 
01222                        values[3], 
01223                        values[4], 
01224                        values[5], 
01225                        values[6], 
01226                        values[7], 
01227                        values[8], 
01228                        values[9]);
01229         break;
01230     } /* Switch size */
01231     return result;
01232 }
01233 static cpl_parameter *
01234 create_parameter_enum_string(const char *name, cpl_type type,
01235                  const char *description, 
01236                  const char *context, 
01237                  const char *default_value, 
01238                  int size, const char **values)
01239 {
01240     /*  This is extremely ugly */
01241     
01242     cpl_parameter *result = NULL;
01243 
01244     if (! (1 <= size && size <= 10))
01245     {
01246         cpl_msg_error(__func__, "Unsupported enumeration size: %d (max is 10)", size);
01247         return NULL;
01248     }
01249     
01250     switch(size)
01251     {
01252     case 1:
01253         uves_parameter_new_enum(result, name,
01254                        type,
01255                        description,
01256                        context,
01257                        default_value, size,
01258                        values[0]);
01259         break;
01260     case 2:
01261         uves_parameter_new_enum(result, name,
01262                           type,
01263                           description,
01264                           context,
01265                           default_value, size,
01266                           values[0],
01267                           values[1]);
01268         break;
01269     case 3:
01270         uves_parameter_new_enum(result, name,
01271                           type,
01272                           description,
01273                           context,
01274                           default_value, size,
01275                           values[0],
01276                           values[1],
01277                           values[2]);
01278         break;
01279     case 4:
01280         uves_parameter_new_enum(result, name,
01281                           type,
01282                           description,
01283                           context,
01284                           default_value, size,
01285                           values[0], 
01286                           values[1], 
01287                           values[2], 
01288                           values[3]);
01289         break;
01290     case 5:
01291         uves_parameter_new_enum(result, name,
01292                           type,
01293                           description,
01294                           context,
01295                           default_value, size,
01296                           values[0], 
01297                           values[1], 
01298                           values[2], 
01299                           values[3], 
01300                           values[4]);
01301         break;
01302     case 6:
01303         uves_parameter_new_enum(result, name,
01304                           type,
01305                           description,
01306                           context,
01307                           default_value, size,
01308                           values[0], 
01309                           values[1], 
01310                           values[2], 
01311                           values[3], 
01312                           values[4], 
01313                           values[5]);
01314         break;
01315     case 7:
01316         uves_parameter_new_enum(result, name,
01317                           type,
01318                           description,
01319                           context,
01320                           default_value, size,
01321                           values[0], 
01322                           values[1], 
01323                           values[2], 
01324                           values[3], 
01325                           values[4], 
01326                           values[5], 
01327                           values[6]);
01328         break;
01329     case 8:
01330         uves_parameter_new_enum(result, name,
01331                           type,
01332                           description,
01333                           context,
01334                           default_value, size,
01335                           values[0], 
01336                           values[1], 
01337                           values[2], 
01338                           values[3], 
01339                           values[4], 
01340                           values[5], 
01341                           values[6], 
01342                           values[7]);
01343         break;
01344     case 9:
01345         uves_parameter_new_enum(result, name,
01346                           type,
01347                           description,
01348                           context,
01349                           default_value, size,
01350                           values[0], 
01351                           values[1], 
01352                           values[2], 
01353                           values[3], 
01354                           values[4], 
01355                           values[5], 
01356                           values[6], 
01357                           values[7], 
01358                           values[8]);
01359         break;
01360     case 10:
01361         uves_parameter_new_enum(result, name,
01362                        type,
01363                        description,
01364                        context,
01365                        default_value, size,
01366                        values[0], 
01367                        values[1], 
01368                        values[2], 
01369                        values[3], 
01370                        values[4], 
01371                        values[5], 
01372                        values[6], 
01373                        values[7], 
01374                        values[8], 
01375                        values[9]);
01376         break;
01377     } /* Switch size */
01378     return result;
01379 }
01380 
01381 
01382 /*----------------------------------------------------------------------------*/
01418 /*----------------------------------------------------------------------------*/
01419 
01420 static int
01421 propagate(const char *substep_id, const cpl_parameterlist *sub_parameters, 
01422       cpl_parameterlist *parent_parameters,
01423       const char *parent_id, const char *context)
01424 {
01425     const cpl_parameter *p = NULL;
01426     
01427     /* For each sub-recipe parameter:
01428        prefix with context and insert in parent parameter list
01429 
01430        Set (overwrite) default value as current value
01431     */
01432     for (p = cpl_parameterlist_get_first_const(sub_parameters);
01433          p != NULL;
01434          p = cpl_parameterlist_get_next_const(sub_parameters) )
01435     {
01436         const char *name          = cpl_parameter_get_name(p);   
01437         const char *description   = cpl_parameter_get_help(p);
01438         const char *subcontext    = cpl_parameter_get_context(p);
01439         const char *alias         = cpl_parameter_get_alias(p, 
01440                                                             CPL_PARAMETER_MODE_CLI);
01441         cpl_parameter_class class = cpl_parameter_get_class(p);
01442         cpl_type type             = cpl_parameter_get_type(p);
01443         
01444         /* Check that S <= name
01445          * and S <= c and c <= name,
01446          * where S is either subrecipe id or 'uves', c is the context,
01447          * and "<=" means "is substring of"
01448          */
01449 
01450         {
01451         const char *S;
01452 
01453         if (strstr(name, "uves.") == name)
01454             {
01455             S = "uves";
01456             }
01457         else
01458             {
01459             S = substep_id;
01460 
01461             /* Check S <= name */
01462             if (strstr(name, S) != name)
01463                 {
01464                 FAIL(-1, CPL_ERROR_ILLEGAL_INPUT,
01465                      "Recipe id '%s' is not prefix of parameter name '%s'",
01466                      S, name);
01467                 }
01468             }
01469         
01470         /* Check S <= c */
01471         if (strstr(subcontext, S) != subcontext)
01472             {
01473             FAIL(-1, CPL_ERROR_ILLEGAL_INPUT, 
01474                  "Recipe id '%s' is not prefix of parameter context '%s'", 
01475                  S, subcontext);
01476             }
01477         
01478         /* Check c <= name */
01479         if (strstr(name, subcontext) != name)
01480             {
01481             FAIL(-1, CPL_ERROR_ILLEGAL_INPUT,
01482                  "Parameter context '%s' is not prefix of parameter name '%s'", 
01483                  subcontext, name);
01484             }
01485         }/* End check parameter format */
01486         
01487         if (strcmp(subcontext, "uves") != 0)
01488         {
01489             int enum_size;
01490             
01491             cpl_parameter *new_par  = NULL;
01492             char *new_name;
01493             char *new_context;
01494             char *new_alias;
01495             
01496             if (context == NULL)
01497             {
01498                 new_name     = uves_sprintf("%s.%s", parent_id, name);     /* R.S.x */
01499                 new_context  = uves_sprintf("%s", parent_id);              /* R     */
01500                 if (alias != NULL)
01501                 {
01502                     new_alias = uves_sprintf("%s.%s", substep_id, alias); /* S.A */
01503                 }
01504                 else
01505                 {
01506                     new_alias = NULL;
01507                 }
01508             }
01509             else
01510             {
01511                 new_name     = uves_sprintf("%s.%s.%s", parent_id, context, name);  
01512                 /* R.c.Sx */
01513                 new_context  = uves_sprintf("%s.%s", parent_id, context); 
01514                 /* R.c    */
01515                 if (alias != NULL)
01516                 {
01517                     new_alias = uves_sprintf("%s.%s.%s", 
01518                                  context, substep_id, alias); 
01519                     /* c.S.A */
01520                 }
01521                 else
01522                 {
01523                     new_alias = NULL;
01524                 }
01525             }
01526             
01527             if (new_name == NULL || new_context == NULL)
01528             {
01529                 if (new_name    != NULL) cpl_free(new_name);
01530                 if (new_context != NULL) cpl_free(new_context);
01531                 if (new_alias   != NULL) cpl_free(new_alias);
01532                 FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT, "Memory allocation failed");
01533             }
01534             
01535             
01536             /* Check for legal class/type before switch */
01537             if (class != CPL_PARAMETER_CLASS_VALUE &&
01538             class != CPL_PARAMETER_CLASS_RANGE &&
01539             class != CPL_PARAMETER_CLASS_ENUM)
01540             {
01541                 cpl_free(new_name);
01542                 cpl_free(new_context);
01543                 if (new_alias != NULL) cpl_free(new_alias);
01544                 FAIL(-1, CPL_ERROR_TYPE_MISMATCH,
01545                  "Unrecognized class of parameter '%s'", name);
01546             }
01547             
01548             if (type != CPL_TYPE_BOOL   &&
01549             type != CPL_TYPE_INT    &&
01550             type != CPL_TYPE_DOUBLE &&
01551             type != CPL_TYPE_STRING)
01552             {
01553                 cpl_free(new_name);
01554                 cpl_free(new_context);
01555                 if (new_alias != NULL) cpl_free(new_alias);
01556                 FAIL(-1, CPL_ERROR_UNSUPPORTED_MODE, "Unsupported type: %s",
01557                  uves_tostring_cpl_type(type));
01558             }
01559             
01560             /* Create a new parameter from the sub-parameter */
01561             switch (class)
01562             {
01563             case CPL_PARAMETER_CLASS_VALUE:
01564                 switch (type)
01565                 {
01566                 case CPL_TYPE_BOOL:
01567                     uves_parameter_new_value(new_par, new_name,
01568                                  type,
01569                                  description,
01570                                  new_context,
01571                                  cpl_parameter_get_default_bool(p));
01572                     break;
01573                     
01574                 case CPL_TYPE_INT:
01575                     uves_parameter_new_value(new_par, new_name,
01576                                  type,
01577                                  description,
01578                                  new_context,
01579                                  cpl_parameter_get_default_int(p));
01580                     break;
01581                     
01582                 case CPL_TYPE_DOUBLE:
01583                     uves_parameter_new_value(new_par, new_name,
01584                                  type,
01585                                  description,
01586                                  new_context,
01587                                  cpl_parameter_get_default_double(p));
01588                     break;
01589                 case CPL_TYPE_STRING:
01590                     uves_parameter_new_value(new_par, new_name,
01591                                  type,
01592                                  description,
01593                                  new_context,
01594                                  cpl_parameter_get_default_string(p));
01595                     break;
01596                 default:
01597                     break; 
01598                 }       /* switch type */
01599                 
01600                 break;   /* CLASS_VALUE */
01601                 
01602             case CPL_PARAMETER_CLASS_RANGE:
01603                 /* Range is either int or double */
01604                 switch (type)
01605                 {
01606                     int min_int, max_int;
01607                     double min_double, max_double;
01608                     
01609                 case CPL_TYPE_INT:
01610                     min_int = cpl_parameter_get_range_min_int(p);
01611                     max_int = cpl_parameter_get_range_max_int(p);
01612                     
01613                     uves_parameter_new_range(new_par, new_name,
01614                                  type,
01615                                  description,
01616                                  new_context,
01617                                  cpl_parameter_get_default_int(p),
01618                                  min_int, max_int);
01619                     break;
01620                     
01621                 case CPL_TYPE_DOUBLE:
01622                     min_double = cpl_parameter_get_range_min_double(p);
01623                     max_double = cpl_parameter_get_range_max_double(p);
01624                     
01625                     uves_parameter_new_range(new_par, new_name,
01626                                  type,
01627                                  description,
01628                                  new_context,
01629                                  cpl_parameter_get_default_double(p),
01630                                  min_double, max_double);
01631                     break;
01632                 default:
01633                     break;
01634                 }
01635         
01636                 break;   /* CLASS_RANGE */
01637         
01638             case CPL_PARAMETER_CLASS_ENUM:
01639                 enum_size = cpl_parameter_get_enum_size(p);
01640             
01641                 /* Enum type is either int, double or string */
01642                 switch (type)
01643                 {
01644                     int        *values_int;        /* Arrays to hold enum values */
01645                     double     *values_double;
01646                     const char **values_string;
01647                     int i;
01648                     
01649                 case CPL_TYPE_INT:
01650                     if ( (values_int = cpl_malloc(sizeof(int) * enum_size))
01651                      == NULL)
01652                     {
01653                         cpl_free(new_name);
01654                         cpl_free(new_context);
01655                         if (new_alias != NULL) cpl_free(new_alias);
01656                         FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT, 
01657                          "Memory allocation failed");
01658                     }
01659                     for (i = 0; i < enum_size; i++)
01660                     {
01661                         values_int[i] = cpl_parameter_get_enum_int(p, i);
01662                     }
01663                 
01664                     new_par = create_parameter_enum_int(
01665                     new_name,
01666                     type,
01667                     description,
01668                     new_context,
01669                     cpl_parameter_get_default_int(p),
01670                     enum_size,
01671                     values_int);
01672                     cpl_free(values_int);
01673                     break;  /* Enum type int */
01674                     
01675                 case CPL_TYPE_DOUBLE:
01676                     if ( (values_double = 
01677                       cpl_malloc(sizeof(double) * enum_size)) == NULL)
01678                     {
01679                         cpl_free(new_name);
01680                         cpl_free(new_context);
01681                         if (new_alias != NULL) cpl_free(new_alias);
01682                         FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT,
01683                          "Memory allocation failed");
01684                     }
01685                     for (i = 0; i < enum_size; i++)
01686                     {
01687                         values_double[i] = cpl_parameter_get_enum_double(p, i);
01688                     }
01689                 
01690                     new_par = create_parameter_enum_double(
01691                     new_name,
01692                     type,
01693                     description,
01694                     new_context,
01695                     cpl_parameter_get_default_double(p),
01696                     enum_size,
01697                     values_double);
01698                     cpl_free(values_double);
01699 
01700                     break;  /* Enum type double */
01701             
01702                 case CPL_TYPE_STRING:
01703                     if ( (values_string = 
01704                       cpl_malloc(sizeof(char *) * enum_size)) == NULL)
01705                     {
01706                         cpl_free(new_name);
01707                         cpl_free(new_context);
01708                         if (new_alias != NULL) cpl_free(new_alias);
01709                         FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT, 
01710                          "Memory allocation failed");
01711                     }
01712                     for (i = 0; i < enum_size; i++)
01713                     {
01714                         values_string[i] = cpl_parameter_get_enum_string(p, i);
01715                     }
01716                 
01717                     new_par = create_parameter_enum_string(
01718                     new_name,
01719                     type,
01720                     description,
01721                     new_context,
01722                     cpl_parameter_get_default_string(p),
01723                     enum_size,
01724                     values_string);
01725                     cpl_free(values_string);
01726                     
01727                     break;  /* Enum type string */
01728                 
01729                 default:
01730                     break;
01731                 
01732                 } /* Switch enum type */
01733             
01734                 break;   /* CLASS_ENUM */
01735 
01736             default:
01737                 break;
01738             
01739             } /* Switch class */
01740 
01741             if (new_par == NULL)
01742             {
01743                 cpl_free(new_name);
01744                 cpl_free(new_context);
01745                 if (new_alias != NULL) cpl_free(new_alias);
01746                 FAIL(-1, CPL_ERROR_ILLEGAL_OUTPUT,
01747                  "Propagation of parameter '%s' failed", 
01748                  name);
01749             }
01750         
01751             /* Also propagate alias */
01752             if (alias != NULL)
01753             {
01754                 cpl_parameter_set_alias(new_par, CPL_PARAMETER_MODE_CLI, new_alias);
01755             }
01756 
01757             /* Insert parameter in parent parameter list */
01758             cpl_parameterlist_append(parent_parameters, new_par);
01759             
01760             cpl_free(new_name);
01761             cpl_free(new_context);
01762             if (new_alias != NULL) cpl_free(new_alias);
01763             
01764         }  /* If parameter context was not 'uves' */
01765         
01766     } /* For each sub-recipe parameter */
01767     
01768     return (cpl_error_get_code() != CPL_ERROR_NONE);
01769 }
01770 
01771 

Generated on Fri Apr 18 14:11:42 2008 for UVES Pipeline Reference Manual by  doxygen 1.5.1