FORS Pipeline Reference Manual  5.0.9
montecarlo.c
1 /* $Id: montecarlo.c,v 1.5 2013-04-24 14:14:13 cgarcia Exp $
2  *
3  * This file is part of the FORS Data Reduction Pipeline
4  * Copyright (C) 2002-2010 European Southern Observatory
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /*
22  * $Author: cgarcia $
23  * $Date: 2013-04-24 14:14:13 $
24  * $Revision: 1.5 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 #include <string.h>
33 #include <cpl.h>
34 #include <moses.h>
35 #include <fors_dfs.h>
36 
37 static int montecarlo_create(cpl_plugin *);
38 static int montecarlo_exec(cpl_plugin *);
39 static int montecarlo_destroy(cpl_plugin *);
40 static int montecarlo(cpl_parameterlist *, cpl_frameset *);
41 
42 static char montecarlo_description[] =
43 "This recipe is used to test the mos_montecarlo_polyfit() function.\n"
44 "It accepts a table with columns x, y, y_err, derives the best polynomial\n"
45 "fit y = p(x), and produces a table with the polynomial 1-sigma accuracy\n"
46 "on the given set of x coordinates.\n"
47 "Input files:\n\n"
48 " DO category: Type: Explanation: Required:\n"
49 " TABLE Raw Table to evaluate Y\n\n"
50 "Output files:\n\n"
51 " DO category: Data type: Explanation:\n"
52 " MODEL_ERROR FITS image Model error at different x\n\n";
53 
54 #define montecarlo_exit(message) \
55 { \
56 if ((const char *)message != NULL) cpl_msg_error(recipe, message); \
57 cpl_table_delete(table); \
58 cpl_table_delete(points); \
59 cpl_table_delete(model_error); \
60 cpl_polynomial_delete(p); \
61 cpl_msg_indent_less(); \
62 return -1; \
63 }
64 
65 #define montecarlo_exit_memcheck(message) \
66 { \
67 if ((const char *)message != NULL) cpl_msg_info(recipe, message); \
68 cpl_table_delete(table); \
69 cpl_table_delete(points); \
70 cpl_table_delete(model_error); \
71 cpl_polynomial_delete(p); \
72 cpl_msg_indent_less(); \
73 return 0; \
74 }
75 
76 
88 int cpl_plugin_get_info(cpl_pluginlist *list)
89 {
90  cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe );
91  cpl_plugin *plugin = &recipe->interface;
92 
93  cpl_plugin_init(plugin,
94  CPL_PLUGIN_API,
95  FORS_BINARY_VERSION,
96  CPL_PLUGIN_TYPE_RECIPE,
97  "montecarlo",
98  "Test function mos_montecarlo_polyfit()",
99  montecarlo_description,
100  "Carlo Izzo",
101  PACKAGE_BUGREPORT,
102  "This file is currently part of the FORS Instrument Pipeline\n"
103  "Copyright (C) 2002-2010 European Southern Observatory\n\n"
104  "This program is free software; you can redistribute it and/or modify\n"
105  "it under the terms of the GNU General Public License as published by\n"
106  "the Free Software Foundation; either version 2 of the License, or\n"
107  "(at your option) any later version.\n\n"
108  "This program is distributed in the hope that it will be useful,\n"
109  "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
110  "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
111  "GNU General Public License for more details.\n\n"
112  "You should have received a copy of the GNU General Public License\n"
113  "along with this program; if not, write to the Free Software Foundation,\n"
114  "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n",
115  montecarlo_create,
116  montecarlo_exec,
117  montecarlo_destroy);
118 
119  cpl_pluginlist_append(list, plugin);
120 
121  return 0;
122 }
123 
124 
135 static int montecarlo_create(cpl_plugin *plugin)
136 {
137  cpl_recipe *recipe;
138  cpl_parameter *p;
139 
140 
141  /*
142  * Check that the plugin is part of a valid recipe
143  */
144 
145  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
146  recipe = (cpl_recipe *)plugin;
147  else
148  return -1;
149 
150  /*
151  * Create the parameters list in the cpl_recipe object
152  */
153 
154  recipe->parameters = cpl_parameterlist_new();
155 
156 
157  /*
158  * Name of input table columns
159  */
160 
161  p = cpl_parameter_new_value("fors.montecarlo.x",
162  CPL_TYPE_STRING,
163  "Name of independent variable column",
164  "fors.montecarlo",
165  "x");
166  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "x");
167  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
168  cpl_parameterlist_append(recipe->parameters, p);
169 
170  p = cpl_parameter_new_value("fors.montecarlo.y",
171  CPL_TYPE_STRING,
172  "Name of dependent variable column",
173  "fors.montecarlo",
174  "y");
175  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "y");
176  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
177  cpl_parameterlist_append(recipe->parameters, p);
178 
179  p = cpl_parameter_new_value("fors.montecarlo.sigma",
180  CPL_TYPE_STRING,
181  "Name of error column on dependent variable",
182  "fors.montecarlo",
183  "");
184  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sigma");
185  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
186  cpl_parameterlist_append(recipe->parameters, p);
187 
188  /*
189  * Order of fitting polynomial
190  */
191 
192  p = cpl_parameter_new_value("fors.montecarlo.order",
193  CPL_TYPE_INT,
194  "Order of fitting polynomial",
195  "fors.montecarlo",
196  1);
197  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "order");
198  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
199  cpl_parameterlist_append(recipe->parameters, p);
200 
201  /*
202  * Origin of x for fit
203  */
204 
205  p = cpl_parameter_new_value("fors.montecarlo.zero",
206  CPL_TYPE_DOUBLE,
207  "Origin of x for fit",
208  "fors.montecarlo",
209  0.0);
210  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "zero");
211  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
212  cpl_parameterlist_append(recipe->parameters, p);
213 
214  /*
215  * Start x for evaluation
216  */
217 
218  p = cpl_parameter_new_value("fors.montecarlo.start",
219  CPL_TYPE_DOUBLE,
220  "Start x for evaluation",
221  "fors.montecarlo",
222  0.0);
223  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "start");
224  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
225  cpl_parameterlist_append(recipe->parameters, p);
226 
227  /*
228  * End x for evaluation
229  */
230 
231  p = cpl_parameter_new_value("fors.montecarlo.end",
232  CPL_TYPE_DOUBLE,
233  "End x for evaluation",
234  "fors.montecarlo",
235  0.0);
236  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "end");
237  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
238  cpl_parameterlist_append(recipe->parameters, p);
239 
240  /*
241  * Evaluation sampling
242  */
243 
244  p = cpl_parameter_new_value("fors.montecarlo.step",
245  CPL_TYPE_DOUBLE,
246  "x sampling interval",
247  "fors.montecarlo",
248  0.0);
249  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "step");
250  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
251  cpl_parameterlist_append(recipe->parameters, p);
252 
253  /*
254  * Statistical sample
255  */
256 
257  p = cpl_parameter_new_value("fors.montecarlo.trials",
258  CPL_TYPE_INT,
259  "Size of statistical sample",
260  "fors.montecarlo",
261  100);
262  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "trials");
263  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
264  cpl_parameterlist_append(recipe->parameters, p);
265 
266  return 0;
267 }
268 
269 
278 static int montecarlo_exec(cpl_plugin *plugin)
279 {
280  cpl_recipe *recipe;
281 
282  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
283  recipe = (cpl_recipe *)plugin;
284  else
285  return -1;
286 
287  return montecarlo(recipe->parameters, recipe->frames);
288 }
289 
290 
299 static int montecarlo_destroy(cpl_plugin *plugin)
300 {
301  cpl_recipe *recipe;
302 
303  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
304  recipe = (cpl_recipe *)plugin;
305  else
306  return -1;
307 
308  cpl_parameterlist_delete(recipe->parameters);
309 
310  return 0;
311 }
312 
313 
323 static int montecarlo(cpl_parameterlist *parlist, cpl_frameset *frameset)
324 {
325 
326  const char *recipe = "montecarlo";
327 
328 
329  /*
330  * Input parameters
331  */
332 
333  const char *x;
334  const char *y;
335  const char *sigma;
336  int order;
337  double start;
338  double end;
339  double step;
340  int trials;
341  double zero;
342 
343  /*
344  * CPL objects
345  */
346 
347  cpl_table *table = NULL;
348  cpl_table *model_error = NULL;
349  cpl_table *points = NULL;
350  cpl_polynomial *p = NULL;
351 
352  /*
353  * Auxiliary variables
354  */
355 
356  char *version = "0.1";
357  char *table_tag = "TABLE";
358  char *model_error_tag = "MODEL_ERROR";
359  double *xdata;
360  int ntables;
361  int i, count;
362 
363 
364  cpl_msg_set_indentation(2);
365 
366 
367  /*
368  * Get configuration parameters
369  */
370 
371  cpl_msg_info(recipe, "Recipe %s configuration parameters:", recipe);
372  cpl_msg_indent_more();
373 
374  x = dfs_get_parameter_string(parlist, "fors.montecarlo.x", NULL);
375  y = dfs_get_parameter_string(parlist, "fors.montecarlo.y", NULL);
376  sigma = dfs_get_parameter_string(parlist, "fors.montecarlo.sigma", NULL);
377  order = dfs_get_parameter_int(parlist, "fors.montecarlo.order", NULL);
378  if (order < 0)
379  montecarlo_exit("Invalid polynomial order");
380  start = dfs_get_parameter_double(parlist, "fors.montecarlo.start", NULL);
381  end = dfs_get_parameter_double(parlist, "fors.montecarlo.end", NULL);
382  if (end <= start)
383  montecarlo_exit("Invalid interval");
384  step = dfs_get_parameter_double(parlist, "fors.montecarlo.step", NULL);
385  if (step >= end - start || step <= 0.0)
386  montecarlo_exit("Invalid step");
387  trials = dfs_get_parameter_int(parlist, "fors.montecarlo.trials", NULL);
388  if (trials < 2)
389  montecarlo_exit("At least 2 trials should be performed");
390  zero = dfs_get_parameter_double(parlist, "fors.montecarlo.zero", NULL);
391 
392  if (cpl_error_get_code())
393  montecarlo_exit("Failure getting the configuration parameters");
394 
395  ntables = cpl_frameset_count_tags(frameset, table_tag);
396  if (ntables == 0) {
397  cpl_msg_error(recipe, "Missing required input: %s", table_tag);
398  montecarlo_exit(NULL);
399  }
400  if (ntables > 1) {
401  cpl_msg_error(recipe, "Too many in input: %s", table_tag);
402  montecarlo_exit(NULL);
403  }
404 
405  table = dfs_load_table(frameset, table_tag, 1);
406  points = cpl_table_new(cpl_table_get_nrow(table));
407 
408  if (cpl_table_has_column(table, x)) {
409  cpl_table_move_column(points, x, table);
410  if (!cpl_table_has_column(points, "x")) {
411  cpl_table_name_column(points, x, "x");
412  }
413  }
414  else {
415  cpl_msg_error(recipe, "Missing column: %s", x);
416  montecarlo_exit(NULL);
417  }
418 
419  cpl_table_subtract_scalar(points, "x", zero);
420 
421  if (cpl_table_has_column(table, y)) {
422  cpl_table_move_column(points, y, table);
423  if (!cpl_table_has_column(points, "y")) {
424  cpl_table_name_column(points, y, "y");
425  }
426  }
427  else {
428  cpl_msg_error(recipe, "Missing column: %s", y);
429  montecarlo_exit(NULL);
430  }
431 
432  if (sigma[0] != '\0') {
433  if (cpl_table_has_column(table, sigma)) {
434  cpl_table_move_column(points, sigma, table);
435  if (!cpl_table_has_column(points, "y_err")) {
436  cpl_table_name_column(points, sigma, "y_err");
437  }
438  }
439  else {
440  cpl_msg_error(recipe, "Missing column: %s", sigma);
441  montecarlo_exit(NULL);
442  }
443  }
444 
445  cpl_table_delete(table); table = NULL;
446  cpl_table_erase_invalid(points);
447 
448  count = 1;
449  while (start + step*count <= end)
450  count++;
451 
452  model_error = cpl_table_new(count);
453  cpl_table_new_column(model_error, "x", CPL_TYPE_DOUBLE);
454  cpl_table_fill_column_window_double(model_error, "x", 0, count, 0.0);
455  xdata = cpl_table_get_data_double(model_error, "x");
456 
457  for (i = 0; i < count; i++)
458  xdata[i] = start + step*i - zero;
459 
460  p = mos_montecarlo_polyfit(points, model_error, trials, order);
461 
462  if (cpl_error_get_code() != CPL_ERROR_NONE) {
463  cpl_msg_error(recipe, "%s", cpl_error_get_message());
464  montecarlo_exit(NULL);
465  }
466 
467  for (i = 0; i < count; i++)
468  xdata[i] += zero;
469 
470  cpl_polynomial_delete(p); p = NULL;
471  cpl_table_delete(points); points = NULL;
472 
473  if (dfs_save_table(frameset, model_error, model_error_tag, NULL,
474  parlist, recipe, version))
475  montecarlo_exit(NULL);
476 
477  cpl_table_delete(model_error); model_error = NULL;
478 
479  return 0;
480 }
int cpl_plugin_get_info(cpl_pluginlist *list)
Build the list of available plugins, for this module.
Definition: fors_bias.c:62
const char * dfs_get_parameter_string(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe string parameter value.
Definition: fors_dfs.c:602
cpl_table * dfs_load_table(cpl_frameset *frameset, const char *category, int ext)
Loading table data of given category.
Definition: fors_dfs.c:916
int dfs_get_parameter_int(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe integer parameter value.
Definition: fors_dfs.c:407
int dfs_save_table(cpl_frameset *frameset, const cpl_table *table, const char *category, cpl_propertylist *header, const cpl_parameterlist *parlist, const char *recipename, const char *version)
Saving table data of given category.
Definition: fors_dfs.c:1575
Definition: list.c:74
double dfs_get_parameter_double(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe double parameter value.
Definition: fors_dfs.c:504