IIINSTRUMENT Pipeline Reference Manual  0.1.5
rrrecipe_calib.c
1 /* $Id: rrrecipe_calib.c,v 1.6 2013-03-26 17:17:32 jtaylor Exp $
2  *
3  * This file is part of the IIINSTRUMENT Pipeline
4  * Copyright (C) 2002,2003 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: jtaylor $
23  * $Date: 2013-03-26 17:17:32 $
24  * $Revision: 1.6 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 /*-----------------------------------------------------------------------------
33  Includes
34  -----------------------------------------------------------------------------*/
35 
36 #include "iiinstrument_utils.h"
37 #include "iiinstrument_pfits.h"
38 #include "iiinstrument_dfs.h"
39 #include <cpl.h>
40 #include <string.h>
41 
42 /*-----------------------------------------------------------------------------
43  Plugin registration
44  -----------------------------------------------------------------------------*/
45 
46 int cpl_plugin_get_info(cpl_pluginlist * list);
47 
48 /*-----------------------------------------------------------------------------
49  Private function prototypes
50  -----------------------------------------------------------------------------*/
51 
52 static int rrrecipe_calib_create(cpl_plugin *);
53 static int rrrecipe_calib_exec(cpl_plugin *);
54 static int rrrecipe_calib_destroy(cpl_plugin *);
55 static int rrrecipe_calib(cpl_frameset *, const cpl_parameterlist *);
56 
57 /*-----------------------------------------------------------------------------
58  Static variables
59  -----------------------------------------------------------------------------*/
60 
61 static char rrrecipe_calib_description[] =
62 "This example text is used to describe the recipe.\n"
63 "The description should include the required FITS-files and\n"
64 "their associated tags, e.g.\n"
65 "IIINSTRUMENT-RRRECIPE-CALIB-raw-file.fits " RRRECIPE_CALIB_RAW "\n"
66 "\n"
67 "Additionally, it should describe functionality of the expected output."
68 "\n";
69 
70 /*-----------------------------------------------------------------------------
71  Function code
72  -----------------------------------------------------------------------------*/
73 
74 /*----------------------------------------------------------------------------*/
84 /*----------------------------------------------------------------------------*/
85 int cpl_plugin_get_info(cpl_pluginlist * list)
86 {
87  cpl_recipe * recipe = cpl_calloc(1, sizeof *recipe );
88  cpl_plugin * plugin = &recipe->interface;
89 
90  if (cpl_plugin_init(plugin,
91  CPL_PLUGIN_API,
92  IIINSTRUMENT_BINARY_VERSION,
93  CPL_PLUGIN_TYPE_RECIPE,
94  "rrrecipe_calib",
95  "Short description of rrrecipe_calib",
96  rrrecipe_calib_description,
97  "Firstname Lastname",
98  PACKAGE_BUGREPORT,
99  iiinstrument_get_license(),
100  rrrecipe_calib_create,
101  rrrecipe_calib_exec,
102  rrrecipe_calib_destroy)) {
103  cpl_msg_error(cpl_func, "Plugin initialization failed");
104  (void)cpl_error_set_where(cpl_func);
105  return 1;
106  }
107 
108  if (cpl_pluginlist_append(list, plugin)) {
109  cpl_msg_error(cpl_func, "Error adding plugin to list");
110  (void)cpl_error_set_where(cpl_func);
111  return 1;
112  }
113 
114  return 0;
115 }
116 
117 /*----------------------------------------------------------------------------*/
125 /*----------------------------------------------------------------------------*/
126 static int rrrecipe_calib_create(cpl_plugin * plugin)
127 {
128  cpl_recipe * recipe;
129  cpl_parameter * p;
130 
131  /* Do not create the recipe if an error code is already set */
132  if (cpl_error_get_code() != CPL_ERROR_NONE) {
133  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
134  cpl_func, __LINE__, cpl_error_get_where());
135  return (int)cpl_error_get_code();
136  }
137 
138  if (plugin == NULL) {
139  cpl_msg_error(cpl_func, "Null plugin");
140  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
141  }
142 
143  /* Verify plugin type */
144  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
145  cpl_msg_error(cpl_func, "Plugin is not a recipe");
146  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
147  }
148 
149  /* Get the recipe */
150  recipe = (cpl_recipe *)plugin;
151 
152  /* Create the parameters list in the cpl_recipe object */
153  recipe->parameters = cpl_parameterlist_new();
154  if (recipe->parameters == NULL) {
155  cpl_msg_error(cpl_func, "Parameter list allocation failed");
156  cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);
157  }
158 
159  /* Fill the parameters list */
160  /* --stropt */
161  p = cpl_parameter_new_value("iiinstrument.rrrecipe_calib.str_option",
162  CPL_TYPE_STRING, "the string option",
163  "iiinstrument.rrrecipe_calib",NULL);
164  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "stropt");
165  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
166  cpl_parameterlist_append(recipe->parameters, p);
167 
168  /* --boolopt */
169  p = cpl_parameter_new_value("iiinstrument.rrrecipe_calib.bool_option",
170  CPL_TYPE_BOOL, "a flag", "iiinstrument.rrrecipe_calib", TRUE);
171  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "boolopt");
172  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
173  cpl_parameterlist_append(recipe->parameters, p);
174 
175  return 0;
176 }
177 
178 /*----------------------------------------------------------------------------*/
184 /*----------------------------------------------------------------------------*/
185 static int rrrecipe_calib_exec(cpl_plugin * plugin)
186 {
187 
188  cpl_recipe * recipe;
189  int recipe_status;
190  cpl_errorstate initial_errorstate = cpl_errorstate_get();
191 
192  /* Return immediately if an error code is already set */
193  if (cpl_error_get_code() != CPL_ERROR_NONE) {
194  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
195  cpl_func, __LINE__, cpl_error_get_where());
196  return (int)cpl_error_get_code();
197  }
198 
199  if (plugin == NULL) {
200  cpl_msg_error(cpl_func, "Null plugin");
201  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
202  }
203 
204  /* Verify plugin type */
205  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
206  cpl_msg_error(cpl_func, "Plugin is not a recipe");
207  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
208  }
209 
210  /* Get the recipe */
211  recipe = (cpl_recipe *)plugin;
212 
213  /* Verify parameter and frame lists */
214  if (recipe->parameters == NULL) {
215  cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
216  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
217  }
218  if (recipe->frames == NULL) {
219  cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");
220  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
221  }
222 
223  /* Invoke the recipe */
224  recipe_status = rrrecipe_calib(recipe->frames, recipe->parameters);
225 
226  /* Ensure DFS-compliance of the products */
227  if (cpl_dfs_update_product_header(recipe->frames)) {
228  if (!recipe_status) recipe_status = (int)cpl_error_get_code();
229  }
230 
231  if (!cpl_errorstate_is_equal(initial_errorstate)) {
232  /* Dump the error history since recipe execution start.
233  At this point the recipe cannot recover from the error */
234  cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);
235  }
236 
237  return recipe_status;
238 }
239 
240 /*----------------------------------------------------------------------------*/
246 /*----------------------------------------------------------------------------*/
247 static int rrrecipe_calib_destroy(cpl_plugin * plugin)
248 {
249  cpl_recipe * recipe;
250 
251  if (plugin == NULL) {
252  cpl_msg_error(cpl_func, "Null plugin");
253  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
254  }
255 
256  /* Verify plugin type */
257  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
258  cpl_msg_error(cpl_func, "Plugin is not a recipe");
259  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
260  }
261 
262  /* Get the recipe */
263  recipe = (cpl_recipe *)plugin;
264 
265  cpl_parameterlist_delete(recipe->parameters);
266 
267  return 0;
268 }
269 
270 /*----------------------------------------------------------------------------*/
277 /*----------------------------------------------------------------------------*/
278 static int rrrecipe_calib(cpl_frameset * frameset,
279  const cpl_parameterlist * parlist)
280 {
281  const cpl_parameter * param;
282  const char * str_option;
283  int bool_option;
284  cpl_frameset * rawframes;
285  const cpl_frame * firstframe;
286  double qc_param;
287  cpl_propertylist * plist;
288  cpl_propertylist * applist;
289  cpl_image * image;
290  int nraw;
291  int i;
292 
293  /* Use the errorstate to detect an error in a function that does not
294  return an error code. */
295  cpl_errorstate prestate = cpl_errorstate_get();
296 
297  /* HOW TO RETRIEVE INPUT PARAMETERS */
298  /* --stropt */
299  param = cpl_parameterlist_find_const(parlist,
300  "iiinstrument.rrrecipe_calib.str_option");
301  str_option = cpl_parameter_get_string(param);
302 
303  /* --boolopt */
304  param = cpl_parameterlist_find_const(parlist,
305  "iiinstrument.rrrecipe_calib.bool_option");
306  bool_option = cpl_parameter_get_bool(param);
307 
308  if (!cpl_errorstate_is_equal(prestate)) {
309  return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
310  "Could not retrieve the input "
311  "parameters");
312  }
313 
314  /* Identify the RAW and CALIB frames in the input frameset */
315  cpl_ensure_code(iiinstrument_dfs_set_groups(frameset) == CPL_ERROR_NONE,
316  cpl_error_get_code());
317 
318  /* HOW TO ACCESS INPUT DATA */
319  /* - A required file */
320  rawframes = cpl_frameset_new();
321  nraw = 0;
322  for (i = 0; i<cpl_frameset_get_size(frameset); i++) {
323  const cpl_frame * current_frame;
324  current_frame = cpl_frameset_get_position_const(frameset, i);
325  if(!strcmp(cpl_frame_get_tag(current_frame), RRRECIPE_CALIB_RAW)) {
326  cpl_frame * new_frame = cpl_frame_duplicate(current_frame);
327  cpl_frameset_insert(rawframes, new_frame);
328  nraw++;
329  }
330  }
331  if (nraw == 0) {
332  return (int)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
333  "SOF does not have any file tagged "
334  "with %s", RRRECIPE_CALIB_RAW);
335  }
336 
337 
338  /* HOW TO GET THE FIRST FRAME OF A FRAME */
339  firstframe = cpl_frameset_get_first_const(rawframes);
340 
341  /* HOW TO GET THE VALUE OF A FITS KEYWORD */
342  /* - Load only DETector related keys */
343  plist = cpl_propertylist_load_regexp(cpl_frame_get_filename(firstframe),
344  0, "ESO DET ", 0);
345  if (plist == NULL) {
346  /* In this case an error message is added to the error propagation */
347  return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
348  "Could not read the FITS header");
349  }
350 
351  qc_param = iiinstrument_pfits_get_dit(plist);
352  cpl_propertylist_delete(plist);
353 
354  /* Check for a change in the CPL error state */
355  /* - if it did change then propagate the error and return */
356  cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
357 
358  /* NOW PERFORMING THE DATA REDUCTION */
359  /* Let's just load an image for the example */
360  image = cpl_image_load(cpl_frame_get_filename(firstframe), CPL_TYPE_FLOAT, 0,
361  0);
362  if (image == NULL) {
363  return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
364  "Could not load the image");
365  }
366 
367  applist = cpl_propertylist_new();
368 
369  /* Add the product category */
370  cpl_propertylist_append_string(applist, CPL_DFS_PRO_CATG,
371  RRRECIPE_OUT_CALIB_PROCATG);
372 
373  /* Add a QC parameter */
374  cpl_propertylist_append_double(applist, "ESO QC QCPARAM", qc_param);
375 
376  /* HOW TO SAVE A DFS-COMPLIANT PRODUCT TO DISK */
377  if (cpl_dfs_save_image(frameset, NULL, parlist, frameset, NULL, image,
378  CPL_BPP_IEEE_FLOAT, "rrrecipe_calib", applist,
379  NULL, PACKAGE "/" PACKAGE_VERSION,
380  "rrrecipe_calib.fits")) {
381  /* Propagate the error */
382  (void)cpl_error_set_where(cpl_func);
383  }
384 
385  cpl_image_delete(image);
386  cpl_propertylist_delete(applist);
387 
388  return (int)cpl_error_get_code();
389 }