GRAVI Pipeline Reference Manual  0.9.6
gravity_image.c
1 /* $Id: gravity_image.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 gravity_image_create(cpl_plugin *);
48 static int gravity_image_exec(cpl_plugin *);
49 static int gravity_image_destroy(cpl_plugin *);
50 static int gravity_image(cpl_frameset *, const cpl_parameterlist *);
51 
52 /*-----------------------------------------------------------------------------
53  Static variables
54  -----------------------------------------------------------------------------*/
55 static char gravity_image_short[] = GRAVI_UNOFFERED"Reconstruct an image from visibilities.";
56 static char gravity_image_description[] = GRAVI_UNOFFERED
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  "gravity_image",
89  gravity_image_short,
90  gravity_image_description,
91  "Vincent Lapeyrere",
92  PACKAGE_BUGREPORT,
93  gravi_get_license(),
94  gravity_image_create,
95  gravity_image_exec,
96  gravity_image_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 gravity_image_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.gravity_image.isotropic_option",
156  CPL_TYPE_BOOL, "a flag", "gravi.gravity_image", 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.gravity_image.pixelsize",
164  CPL_TYPE_DOUBLE, "size of the pixel (milliarcseconds)",
165  "gravi.gravity_image", 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.gravity_image.dim",
172  CPL_TYPE_INT, "number of pixels per side of the image",
173  "gravi.gravity_image", 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.gravity_image.regul",
180  CPL_TYPE_STRING, "name of regularization method",
181  "gravi.gravity_image", "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.gravity_image.regul_mu",
188  CPL_TYPE_DOUBLE, "global regularization weight",
189  "gravi.gravity_image", 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.gravity_image.maxeval",
196  CPL_TYPE_INT, "maximum number of evaluations of the objective function",
197  "gravi.gravity_image", 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.gravity_image.timeout",
204  CPL_TYPE_DOUBLE, "Maximum execution time of Mira process (s)",
205  "gravi.gravity_image", 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 gravity_image_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 = gravity_image(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 gravity_image_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 gravity_image(cpl_frameset * frameset,
314  const cpl_parameterlist * parlist)
315 {
316  const cpl_frame * rawframe;
317  double qc_param = 0.0;
318  cpl_propertylist * applist;
319  cpl_image * image;
320  cpl_frameset * usedframes;
321 
322  /* Use the errorstate to detect an error in a function that does not
323  return an error code. */
324  cpl_errorstate prestate = cpl_errorstate_get();
325 
326  /* RETRIEVE INPUT PARAMETERS */
327  /* No input param to retrieve */
328  if (!cpl_errorstate_is_equal(prestate)) {
329  return (int)cpl_error_set_message(cpl_func, cpl_error_get_code(),
330  "Could not retrieve the input "
331  "parameters");
332  }
333 
334  /* Identify the RAW and CALIB frames in the input frameset */
335  cpl_ensure_code(gravi_dfs_set_groups(frameset) == CPL_ERROR_NONE,
336  cpl_error_get_code());
337 
338  /* ACCESS INPUT DATA */
339  /* Get the image reconstruction INPUT file */
340  rawframe = cpl_frameset_find_const(frameset, GRAVI_MIRA_INPUT_PROCATG);
341  if (rawframe == NULL) {
342  /* cpl_frameset_find_const() does not set an error code, when a frame
343  is not found, so we will set one here. */
344  return (int)cpl_error_set_message(cpl_func, CPL_ERROR_DATA_NOT_FOUND,
345  "SOF does not have any file tagged "
346  "with %s", GRAVI_MIRA_INPUT_PROCATG);
347  }
348 
349  /* Check for a change in the CPL error state */
350  /* - if it did change then propagate the error and return */
351  cpl_ensure_code(cpl_errorstate_is_equal(prestate), cpl_error_get_code());
352 
353  cpl_msg_set_component_on();
354 
355  /* NOW PERFORMING THE DATA REDUCTION */
356  /* Execute the gravi_image function */
357  image=gravi_image(rawframe, parlist);
358  if (image == NULL) {
359  /* cpl_frameset_find_const() does not set an error code, when a frame
360  is not found, so we will set one here. */
361  return (int)cpl_error_set_message(cpl_func, CPL_ERROR_NULL_INPUT,
362  "The gravi_image function return NULL pointer");
363  }
364 
365  applist = cpl_propertylist_new();
366 
367  /* Add the product category */
368  cpl_propertylist_append_string(applist, CPL_DFS_PRO_CATG,
369  GRAVI_MIRA_OUTPUT_PROCATG);
370 
371  /* Add a QC parameter */
372  cpl_propertylist_append_double(applist, "ESO QC QCPARAM", qc_param);
373 
374  /* SAVE A DFS-COMPLIANT PRODUCT TO DISK*/
375  gravi_dfs_set_groups(frameset);
376 
377  /* create product */
378  usedframes = cpl_frameset_new();
379  cpl_frameset_insert(usedframes, cpl_frame_duplicate(rawframe));
380 
381  cpl_msg_info(cpl_func, "Writing image_out.fits");
382 
383 /* if (cpl_dfs_save_propertylist (frameset, NULL, parlist, usedframes,
384  rawframe, "gravity_image", applist, NULL,
385  PACKAGE "/" PACKAGE_VERSION , "image_out.fits" ) != CPL_ERROR_NONE){
386  cpl_error_set_message(cpl_func, cpl_error_get_code(),
387  "Cannot save the first extension primary header");
388  cpl_image_delete(image);
389  cpl_propertylist_delete(applist);
390  cpl_frameset_delete(usedframes);
391  return cpl_error_get_code();
392  }
393 */
394  /* Save the image extensions */
395 /* if (cpl_image_save(image, "image_out.fits", CPL_BPP_IEEE_DOUBLE,
396  applist, CPL_IO_EXTEND) != CPL_ERROR_NONE){
397  cpl_error_set_message(cpl_func, cpl_error_get_code(),
398  "Cannot save the image extension");
399  cpl_image_delete(image);
400  cpl_propertylist_delete(applist);
401  cpl_frameset_delete(usedframes);
402  return cpl_error_get_code();
403  }
404 */
405 
406  cpl_dfs_save_image(frameset, NULL, parlist, usedframes,
407  rawframe, image, CPL_BPP_IEEE_DOUBLE,
408  "gravity_image", applist, NULL,
409  PACKAGE "/" PACKAGE_VERSION , "image_out.fits" );
410  cpl_msg_info(cpl_func, "Reconstructed image saved in image_out.fits");
411 
412  /* free memory */
413  cpl_image_delete(image);
414  cpl_propertylist_delete(applist);
415  cpl_frameset_delete(usedframes);
416 
417  return (int)cpl_error_get_code();
418 }