GRAVI Pipeline Reference Manual  0.7.12
gravi_image_reconstruct.c
1 /* $Id: gravi_image_reconstruct.c,v 1.29 2009/02/10 09:16:12 llundin Exp $
2  *
3  * This file is part of the GRAVI 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 /*
22  * $Author: llundin $
23  * $Date: 2009/02/10 09:16:12 $
24  * $Revision: 1.29 $
25  * $Name: HEAD $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 /*-----------------------------------------------------------------------------
33  Includes
34  -----------------------------------------------------------------------------*/
35 
36 #include <cpl.h>
37 
38 #include "gravi_utils.h"
39 #include "gravi_pfits.h"
40 #include "gravi_dfs.h"
41 #include "gravi_image.h"
42 
43 /*-----------------------------------------------------------------------------
44  Private function prototypes
45  -----------------------------------------------------------------------------*/
46 
47 static int gravi_image_reconstruct_create(cpl_plugin *);
48 static int gravi_image_reconstruct_exec(cpl_plugin *);
49 static int gravi_image_reconstruct_destroy(cpl_plugin *);
50 static int gravi_image_reconstruct(cpl_frameset *, const cpl_parameterlist *);
51 
52 /*-----------------------------------------------------------------------------
53  Static variables
54  -----------------------------------------------------------------------------*/
55 
56 static char gravi_image_reconstruct_description[] =
57 "This recipe launch a Yorick batch executing mira-script.i to process an\n"
58 "input OIFITS file to produce an image in fits file.\n"
59 "The input frame is an OIFITS file :\n"
60 "GRAVI-GRAVI_MIRA-input-file.oifits " GRAVI_MIRA_INPUT_PROCATG "\n"
61 "and the recipe generates a fits image\n"
62 "GRAVI-GRAVI_MIRA-image-file.fits " GRAVI_MIRA_OUTPUT_PROCATG "\n";
63 
64 /*-----------------------------------------------------------------------------
65  Function code
66  -----------------------------------------------------------------------------*/
67 
68 /*----------------------------------------------------------------------------*/
78 /*----------------------------------------------------------------------------*/
79 int cpl_plugin_get_info(cpl_pluginlist * list)
80 {
81  cpl_recipe * recipe = cpl_calloc(1, sizeof *recipe );
82  cpl_plugin * plugin = &recipe->interface;
83 
84  if (cpl_plugin_init(plugin,
85  CPL_PLUGIN_API,
86  GRAVI_BINARY_VERSION,
87  CPL_PLUGIN_TYPE_RECIPE,
88  "gravi_image_reconstruct",
89  "Processess an OIFITS file to reconstruct an image",
90  gravi_image_reconstruct_description,
91  "Vincent Lapeyrere",
92  PACKAGE_BUGREPORT,
93  gravi_get_license(),
94  gravi_image_reconstruct_create,
95  gravi_image_reconstruct_exec,
96  gravi_image_reconstruct_destroy)) {
97  cpl_msg_error(cpl_func, "Plugin initialization failed");
98  (void)cpl_error_set_where(cpl_func);
99  return 1;
100  }
101 
102  if (cpl_pluginlist_append(list, plugin)) {
103  cpl_msg_error(cpl_func, "Error adding plugin to list");
104  (void)cpl_error_set_where(cpl_func);
105  return 1;
106  }
107 
108  return 0;
109 }
110 
111 /*----------------------------------------------------------------------------*/
119 /*----------------------------------------------------------------------------*/
120 static int gravi_image_reconstruct_create(cpl_plugin * plugin)
121 {
122  cpl_recipe * recipe;
123  cpl_parameter * p;
124 
125  /* Do not create the recipe if an error code is already set */
126  if (cpl_error_get_code() != CPL_ERROR_NONE) {
127  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
128  cpl_func, __LINE__, cpl_error_get_where());
129  return (int)cpl_error_get_code();
130  }
131 
132  if (plugin == NULL) {
133  cpl_msg_error(cpl_func, "Null plugin");
134  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
135  }
136 
137  /* Verify plugin type */
138  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
139  cpl_msg_error(cpl_func, "Plugin is not a recipe");
140  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
141  }
142 
143  /* Get the recipe */
144  recipe = (cpl_recipe *)plugin;
145 
146  /* Create the parameters list in the cpl_recipe object */
147  recipe->parameters = cpl_parameterlist_new();
148  if (recipe->parameters == NULL) {
149  cpl_msg_error(cpl_func, "Parameter list allocation failed");
150  cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);
151  }
152 
153  /* Fill the parameters list */
154  /* --isotropic */
155 /* p = cpl_parameter_new_value("gravi.gravi_image_reconstruct.isotropic_option",
156  CPL_TYPE_BOOL, "a flag", "gravi.gravi_image_reconstruct", FALSE);
157  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "isotropic");
158  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
159  cpl_parameterlist_append(recipe->parameters, p);
160 */
161 
162  /* --pixelsize */
163  p = cpl_parameter_new_value("gravi.gravi_image_reconstruct.pixelsize",
164  CPL_TYPE_DOUBLE, "size of the pixel (milliarcseconds)",
165  "gravi.gravi_image_reconstruct", 0.2);
166  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "pixelsize");
167  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
168  cpl_parameterlist_append(recipe->parameters, p);
169 
170  /* --dim */
171  p = cpl_parameter_new_value("gravi.gravi_image_reconstruct.dim",
172  CPL_TYPE_INT, "number of pixels per side of the image",
173  "gravi.gravi_image_reconstruct", 100);
174  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dim");
175  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
176  cpl_parameterlist_append(recipe->parameters, p);
177 
178  /* --regul */
179  p = cpl_parameter_new_value("gravi.gravi_image_reconstruct.regul",
180  CPL_TYPE_STRING, "name of regularization method",
181  "gravi.gravi_image_reconstruct", "totvar");
182  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "regul");
183  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
184  cpl_parameterlist_append(recipe->parameters, p);
185 
186  /* --regul_mu */
187  p = cpl_parameter_new_value("gravi.gravi_image_reconstruct.regul_mu",
188  CPL_TYPE_DOUBLE, "global regularization weight",
189  "gravi.gravi_image_reconstruct", 1E4);
190  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "regul_mu");
191  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
192  cpl_parameterlist_append(recipe->parameters, p);
193 
194  /* --maxeval */
195  p = cpl_parameter_new_value("gravi.gravi_image_reconstruct.maxeval",
196  CPL_TYPE_INT, "maximum number of evaluations of the objective function",
197  "gravi.gravi_image_reconstruct", 2000);
198  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "maxeval");
199  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
200  cpl_parameterlist_append(recipe->parameters, p);
201 
202  /* --timeout */
203  p = cpl_parameter_new_value("gravi.gravi_image_reconstruct.timeout",
204  CPL_TYPE_DOUBLE, "Maximum execution time of Mira process (s)",
205  "gravi.gravi_image_reconstruct", 60.);
206  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "timeout");
207  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
208  cpl_parameterlist_append(recipe->parameters, p);
209 
210  return 0;
211 }
212 
213 /*----------------------------------------------------------------------------*/
219 /*----------------------------------------------------------------------------*/
220 static int gravi_image_reconstruct_exec(cpl_plugin * plugin)
221 {
222 
223  cpl_recipe * recipe;
224  int recipe_status;
225  cpl_errorstate initial_errorstate = cpl_errorstate_get();
226 
227  /* Return immediately if an error code is already set */
228  if (cpl_error_get_code() != CPL_ERROR_NONE) {
229  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
230  cpl_func, __LINE__, cpl_error_get_where());
231  return (int)cpl_error_get_code();
232  }
233 
234  if (plugin == NULL) {
235  cpl_msg_error(cpl_func, "Null plugin");
236  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
237  }
238 
239  /* Verify plugin type */
240  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
241  cpl_msg_error(cpl_func, "Plugin is not a recipe");
242  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
243  }
244 
245  /* Get the recipe */
246  recipe = (cpl_recipe *)plugin;
247 
248  /* Verify parameter and frame lists */
249  if (recipe->parameters == NULL) {
250  cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
251  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
252  }
253  if (recipe->frames == NULL) {
254  cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");
255  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
256  }
257 
258  /* Invoke the recipe */
259  recipe_status = gravi_image_reconstruct(recipe->frames, recipe->parameters);
260 
261  /* Ensure DFS-compliance of the products */
262  if (cpl_dfs_update_product_header(recipe->frames)) {
263  if (!recipe_status) recipe_status = (int)cpl_error_get_code();
264  }
265 
266  if (!cpl_errorstate_is_equal(initial_errorstate)) {
267  /* Dump the error history since recipe execution start.
268  At this point the recipe cannot recover from the error */
269  cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);
270  }
271 
272  return recipe_status;
273 }
274 
275 /*----------------------------------------------------------------------------*/
281 /*----------------------------------------------------------------------------*/
282 static int gravi_image_reconstruct_destroy(cpl_plugin * plugin)
283 {
284  cpl_recipe * recipe;
285 
286  if (plugin == NULL) {
287  cpl_msg_error(cpl_func, "Null plugin");
288  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
289  }
290 
291  /* Verify plugin type */
292  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
293  cpl_msg_error(cpl_func, "Plugin is not a recipe");
294  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
295  }
296 
297  /* Get the recipe */
298  recipe = (cpl_recipe *)plugin;
299 
300  cpl_parameterlist_delete(recipe->parameters);
301 
302  return 0;
303 }
304 
305 /*----------------------------------------------------------------------------*/
312 /*----------------------------------------------------------------------------*/
313 static int gravi_image_reconstruct(cpl_frameset * frameset,
314  const cpl_parameterlist * parlist)
315 {
316  const cpl_frame * rawframe;
317  double qc_param;
318  cpl_propertylist * plist;
319  cpl_propertylist * applist;
320  cpl_image * image;
321  cpl_frameset * usedframes;
322 
323  /* Use the errorstate to detect an error in a function that does not
324  return an error code. */
325  cpl_errorstate prestate = cpl_errorstate_get();
326 
327  /* RETRIEVE INPUT PARAMETERS */
328  /* No input param to retrieve */
329  if (!cpl_errorstate_is_equal(prestate)) {
330  return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
331  "Could not retrieve the input "
332  "parameters");
333  }
334 
335  /* Identify the RAW and CALIB frames in the input frameset */
336  cpl_ensure_code(gravi_dfs_set_groups(frameset) == CPL_ERROR_NONE,
337  cpl_error_get_code());
338 
339  /* ACCESS INPUT DATA */
340  /* Get the image reconstruction INPUT file */
341  rawframe = cpl_frameset_find_const(frameset, GRAVI_MIRA_INPUT_PROCATG);
342  if (rawframe == NULL) {
343  /* cpl_frameset_find_const() does not set an error code, when a frame
344  is not found, so we will set one here. */
345  return (int)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
346  "SOF does not have any file tagged "
347  "with %s", GRAVI_MIRA_INPUT_PROCATG);
348  }
349 
350  /* Check for a change in the CPL error state */
351  /* - if it did change then propagate the error and return */
352  cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
353 
354  cpl_msg_set_component_on();
355 
356  /* NOW PERFORMING THE DATA REDUCTION */
357  /* Execute the gravi_image function */
358  image=gravi_image(rawframe, parlist);
359  if (image == NULL) {
360  /* cpl_frameset_find_const() does not set an error code, when a frame
361  is not found, so we will set one here. */
362  return (int)cpl_error_set_message(cpl_func, CPL_ERROR_NULL_INPUT,
363  "The gravi_image function return NULL pointer");
364  }
365 
366  applist = cpl_propertylist_new();
367 
368  /* Add the product category */
369  cpl_propertylist_append_string(applist, CPL_DFS_PRO_CATG,
370  GRAVI_MIRA_OUTPUT_PROCATG);
371 
372  /* Add a QC parameter */
373  cpl_propertylist_append_double(applist, "ESO QC QCPARAM", qc_param);
374 
375  /* SAVE A DFS-COMPLIANT PRODUCT TO DISK*/
376  gravi_dfs_set_groups(frameset);
377 
378  /* create product */
379  usedframes = cpl_frameset_new();
380  cpl_frameset_insert(usedframes, cpl_frame_duplicate(rawframe));
381 
382  cpl_msg_info(cpl_func, "Writing image_out.fits");
383 
384 /* if (cpl_dfs_save_propertylist (frameset, NULL, parlist, usedframes,
385  rawframe, "gravi_image_reconstruct", applist, NULL,
386  PACKAGE "/" PACKAGE_VERSION , "image_out.fits" ) != CPL_ERROR_NONE){
387  cpl_error_set_message(cpl_func, cpl_error_get_code(),
388  "Cannot save the first extension primary header");
389  cpl_image_delete(image);
390  cpl_propertylist_delete(applist);
391  cpl_frameset_delete(usedframes);
392  return cpl_error_get_code();
393  }
394 */
395  /* Save the image extensions */
396 /* if (cpl_image_save(image, "image_out.fits", CPL_BPP_IEEE_DOUBLE,
397  applist, CPL_IO_EXTEND) != CPL_ERROR_NONE){
398  cpl_error_set_message(cpl_func, cpl_error_get_code(),
399  "Cannot save the image extension");
400  cpl_image_delete(image);
401  cpl_propertylist_delete(applist);
402  cpl_frameset_delete(usedframes);
403  return cpl_error_get_code();
404  }
405 */
406 
407  cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
408  rawframe, image, CPL_BPP_IEEE_DOUBLE,
409  "gravi_image_reconstruct", applist, NULL,
410  PACKAGE "/" PACKAGE_VERSION , "image_out.fits" );
411  cpl_msg_info(cpl_func, "Reconstructed image saved in image_out.fits");
412 
413  /* free memory */
414  cpl_image_delete(image);
415  cpl_propertylist_delete(applist);
416  cpl_frameset_delete(usedframes);
417 
418  return (int)cpl_error_get_code();
419 }