00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 #ifdef HAVE_CONFIG_H
00129 # include <config.h>
00130 #endif
00131
00132
00140
00141
00142
00143
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
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
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
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
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
00367
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,
00384 -1, INT_MAX);
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;
00436
00437
00438
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
00444
00445
00446 check( list = cpl_pluginlist_new(),
00447 "Error allocating plugin list");
00448
00449
00450 status = get_info(list);
00451
00452 assure( status == 0, CPL_ERROR_ILLEGAL_INPUT,
00453 "Could not get info about recipe");
00454
00455
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
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
00473
00474
00475
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
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 }
00574
00575 cpl_free(parent_name); parent_name = NULL;
00576
00577 }
00578
00579
00580 recipe->frames = frames;
00581
00582
00583
00584
00585
00586
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
00599
00600 uves_msg_set_domain(domain);
00601
00602
00603
00604
00605 uves_msg_add_warnings(warnings_in_caller);
00606 }
00607
00608
00609
00610
00611
00612
00613 if (cpl_error_get_code() != CPL_ERROR_NONE)
00614 {
00615
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
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
00719 if (get_info == NULL)
00720 {
00721 FAIL(-1, CPL_ERROR_NULL_INPUT, "Null function pointer");
00722 }
00723
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
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
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
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;
00878
00879
00880
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
00896
00897
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
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
00931
00932
00933
00934
00935
00936
00937
00938
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
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 }
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
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 }
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
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 }
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
01428
01429
01430
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
01445
01446
01447
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
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
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
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 }
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);
01499 new_context = uves_sprintf("%s", parent_id);
01500 if (alias != NULL)
01501 {
01502 new_alias = uves_sprintf("%s.%s", substep_id, alias);
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
01513 new_context = uves_sprintf("%s.%s", parent_id, context);
01514
01515 if (alias != NULL)
01516 {
01517 new_alias = uves_sprintf("%s.%s.%s",
01518 context, substep_id, alias);
01519
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
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
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 }
01599
01600 break;
01601
01602 case CPL_PARAMETER_CLASS_RANGE:
01603
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;
01637
01638 case CPL_PARAMETER_CLASS_ENUM:
01639 enum_size = cpl_parameter_get_enum_size(p);
01640
01641
01642 switch (type)
01643 {
01644 int *values_int;
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;
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;
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;
01728
01729 default:
01730 break;
01731
01732 }
01733
01734 break;
01735
01736 default:
01737 break;
01738
01739 }
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
01752 if (alias != NULL)
01753 {
01754 cpl_parameter_set_alias(new_par, CPL_PARAMETER_MODE_CLI, new_alias);
01755 }
01756
01757
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 }
01765
01766 }
01767
01768 return (cpl_error_get_code() != CPL_ERROR_NONE);
01769 }
01770
01771