GRAVI Pipeline Reference Manual  0.9.5
gravity_vis_from_p2vmred.c
1 /* $Id: gravity_vis_from_p2vmred.c,v 1.29 2011/12/3 09:16:12 nazouaoui 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 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 
25 /*-----------------------------------------------------------------------------
26  Includes
27  -----------------------------------------------------------------------------*/
28 
29 #include <cpl.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <time.h>
33 
34 #include "gravi_data.h"
35 #include "gravi_pfits.h"
36 #include "gravi_dfs.h"
37 
38 #include "gravi_utils.h"
39 
40 #include "gravi_calib.h"
41 #include "gravi_p2vmred.h"
42 #include "gravi_eop.h"
43 #include "gravi_metrology.h"
44 
45 #include "gravi_signal.h"
46 #include "gravi_vis.h"
47 #include "gravi_tf.h"
48 
49 #include "gravi_preproc.h"
50 // #include "gravi_p2vm.h"
51 
52 /*-----------------------------------------------------------------------------
53  Private function prototypes
54  -----------------------------------------------------------------------------*/
55 
56 static int gravity_vis_from_p2vmred_create(cpl_plugin *);
57 static int gravity_vis_from_p2vmred_exec(cpl_plugin *);
58 static int gravity_vis_from_p2vmred_destroy(cpl_plugin *);
59 static int gravity_vis_from_p2vmred(cpl_frameset *, const cpl_parameterlist *);
60 
61 /*-----------------------------------------------------------------------------
62  Static variables
63  -----------------------------------------------------------------------------*/
64 static char gravity_vis_from_p2vmred_short[] = "Compute the visibilities from P2VMRED intermediate product.";
65 static char gravity_vis_from_p2vmred_description[] =
66  "This recipe average the real-time data from input P2VMRED files into a VIS product. It allows to run the reduction with different parameters (for instance for SNR thresholding) without having to re-reduce the files from scratch. Typically the reduction is 4x faster when started from this intermediate product.\n"
67  "\n"
68  "The tag in the DO category can be SINGLE/DUAL and CAL/SCI. They should reflect the mode (SINGLE or DUAL) and the DPR.CATG of the observation (SCIENCE or CALIB). The tag in the PRO.CATG category will be SINGLE/DUAL and CAL/SCI depending on the input tag.\n"
69  GRAVI_RECIPE_INPUT"\n"
70  GRAVI_P2VMRED_SINGLE_SCIENCE" : Input intermediate product\n"
71  GRAVI_RECIPE_OUTPUT"\n"
72  GRAVI_VIS_SINGLE_SCIENCE" : OIFITS with uncalibrated visibilities\n"
73  "";
74 
75 /*-----------------------------------------------------------------------------
76  Function code
77  -----------------------------------------------------------------------------*/
78 
79 /*----------------------------------------------------------------------------*/
89 /*----------------------------------------------------------------------------*/
90 int cpl_plugin_get_info(cpl_pluginlist * list)
91 {
92  cpl_recipe * recipe = cpl_calloc(1, sizeof *recipe );
93  cpl_plugin * plugin = &recipe->interface;
94 
95  if (cpl_plugin_init(plugin,
96  CPL_PLUGIN_API,
97  GRAVI_BINARY_VERSION,
98  CPL_PLUGIN_TYPE_RECIPE,
99  "gravity_vis_from_p2vmred",
100  gravity_vis_from_p2vmred_short,
101  gravity_vis_from_p2vmred_description,
102  "JB. Le Bouquin, Vincent Lapeyrere, ",
103  PACKAGE_BUGREPORT,
104  gravi_get_license(),
105  gravity_vis_from_p2vmred_create,
106  gravity_vis_from_p2vmred_exec,
107  gravity_vis_from_p2vmred_destroy)) {
108  cpl_msg_error(cpl_func, "Plugin initialization failed");
109  (void)cpl_error_set_where(cpl_func);
110  return 1;
111  }
112 
113  if (cpl_pluginlist_append(list, plugin)) {
114  cpl_msg_error(cpl_func, "Error adding plugin to list");
115  (void)cpl_error_set_where(cpl_func);
116  return 1;
117  }
118 
119  return 0;
120 }
121 
122 /*----------------------------------------------------------------------------*/
130 /*----------------------------------------------------------------------------*/
131 static int gravity_vis_from_p2vmred_create(cpl_plugin * plugin)
132 {
133  cpl_recipe * recipe;
134  cpl_parameter * p;
135 
136  /* Do not create the recipe if an error code is already set */
137  if (cpl_error_get_code() != CPL_ERROR_NONE) {
138  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
139  cpl_func, __LINE__, cpl_error_get_where());
140  return (int)cpl_error_get_code();
141  }
142 
143  if (plugin == NULL) {
144  cpl_msg_error(cpl_func, "Null plugin");
145  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
146  }
147 
148  /* Verify plugin type */
149  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
150  cpl_msg_error(cpl_func, "Plugin is not a recipe");
151  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
152  }
153 
154  /* Get the recipe */
155  recipe = (cpl_recipe *)plugin;
156 
157  /* Create the parameters list in the cpl_recipe object */
158  recipe->parameters = cpl_parameterlist_new();
159  if (recipe->parameters == NULL) {
160  cpl_msg_error(cpl_func, "Parameter list allocation failed");
161  cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);
162  }
163 
164  /* Fill the parameters list */
165  int isCalib = 0;
166 
167  /* Use static names (output_procatg.fits) */
168  gravi_parameter_add_static_name (recipe->parameters);
169 
170  /* Averaging */
171  gravi_parameter_add_average_vis (recipe->parameters);
172 
173  /* Snr */
174  gravi_parameter_add_compute_snr (recipe->parameters, isCalib);
175 
176  /* Rejection */
177  gravi_parameter_add_rejection (recipe->parameters, isCalib);
178 
179  /* Parameters for gravi_compute_vis */
180  gravi_parameter_add_compute_vis (recipe->parameters, isCalib);
181 
182  /* --Use existing selection */
183  p = cpl_parameter_new_value ("gravity.signal.use-existing-rejection", CPL_TYPE_BOOL,
184  "Use existing rejection flags (ignore related options)",
185  "gravity.signal", FALSE);
186  cpl_parameter_set_alias (p, CPL_PARAMETER_MODE_CLI, "use-existing-rejection");
187  cpl_parameter_disable (p, CPL_PARAMETER_MODE_ENV);
188  cpl_parameterlist_append (recipe->parameters, p);
189 
190  return 0;
191 }
192 
193 /*----------------------------------------------------------------------------*/
199 /*----------------------------------------------------------------------------*/
200 static int gravity_vis_from_p2vmred_exec(cpl_plugin * plugin)
201 {
202 
203  cpl_recipe * recipe;
204  int recipe_status;
205  cpl_errorstate initial_errorstate = cpl_errorstate_get();
206 
207 
208  /* Return immediately if an error code is already set */
209  if (cpl_error_get_code() != CPL_ERROR_NONE) {
210  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
211  cpl_func, __LINE__, cpl_error_get_where());
212  return (int)cpl_error_get_code();
213  }
214 
215  if (plugin == NULL) {
216  cpl_msg_error(cpl_func, "Null plugin");
217  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
218  }
219 
220  /* Verify plugin type */
221  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
222  cpl_msg_error(cpl_func, "Plugin is not a recipe");
223  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
224  }
225 
226  /* Get the recipe */
227  recipe = (cpl_recipe *)plugin;
228 
229  /* Verify parameter and frame lists */
230  if (recipe->parameters == NULL) {
231  cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
232  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
233  }
234  if (recipe->frames == NULL) {
235  cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");
236  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
237  }
238 
239  /* Invoke the recipe */
240  recipe_status = gravity_vis_from_p2vmred(recipe->frames, recipe->parameters);
241 
242  /* Ensure DFS-compliance of the products */
243  if (cpl_dfs_update_product_header(recipe->frames)) {
244  if (!recipe_status){
245  recipe_status = (int)cpl_error_get_code();
246  }
247  }
248 
249  if (!cpl_errorstate_is_equal(initial_errorstate)) {
250  /* Dump the error history since recipe execution start.
251  At this point the recipe cannot recover from the error */
252  cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);
253  }
254 
255  return recipe_status;
256 }
257 
258 /*----------------------------------------------------------------------------*/
264 /*----------------------------------------------------------------------------*/
265 static int gravity_vis_from_p2vmred_destroy(cpl_plugin * plugin)
266 {
267  cpl_recipe * recipe;
268 
269  if (plugin == NULL) {
270  cpl_msg_error(cpl_func, "Null plugin");
271  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
272  }
273 
274  /* Verify plugin type */
275  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
276  cpl_msg_error(cpl_func, "Plugin is not a recipe");
277  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
278  }
279 
280  /* Get the recipe */
281  recipe = (cpl_recipe *)plugin;
282 
283  cpl_parameterlist_delete(recipe->parameters);
284 
285  return 0;
286 }
287 
288 
289 /*----------------------------------------------------------------------------*/
297 /*----------------------------------------------------------------------------*/
298 static int gravity_vis_from_p2vmred(cpl_frameset * frameset,
299  const cpl_parameterlist * parlist)
300 {
301  cpl_frameset * recipe_frameset=NULL, *used_frameset=NULL;
302 
303  cpl_frame * frame=NULL;
304 
305  const char * frame_tag=NULL;
306  char * proCatg = NULL, * mode=NULL;
307 
308  gravi_data * p2vmred_data=NULL, * vis_data=NULL, * tmpvis_data=NULL;
309 
310  int nb_frame;
311 
312  /* Message */
313  gravity_print_banner ();
314  cpl_msg_set_time_on();
315  cpl_msg_set_component_on();
316  gravi_msg_function_start(1);
317 
318  cpl_ensure_code(gravi_dfs_set_groups(frameset) == CPL_ERROR_NONE,
319  cpl_error_get_code()) ;
320 
321  /* Dispatch the frameset */
322  recipe_frameset = gravi_frameset_extract_p2vmred_data (frameset);
323 
324  /* To use this recipe the frameset must contain a P2VMREDUCED file. */
325  if ( cpl_frameset_get_size (recipe_frameset) < 1 ) {
326  cpl_error_set_message (cpl_func, CPL_ERROR_ILLEGAL_INPUT,
327  "Illegal number of P2VMREDUCED file on the frameset");
328  goto cleanup;
329  }
330 
331  /* Insert calibration frame into the used frameset */
332  used_frameset = cpl_frameset_new();
333 
334  /*
335  * Select the PRO CATG (based on first frame)
336  */
337 
338  frame_tag = cpl_frame_get_tag (cpl_frameset_get_position (recipe_frameset, 0));
339 
340  if ((strcmp(frame_tag, GRAVI_P2VMRED_DUAL_CALIB) == 0)) {
341  proCatg = cpl_sprintf (GRAVI_VIS_DUAL_CALIB);
342  mode = cpl_sprintf ("gravi_dual");
343  }
344  else if ((strcmp(frame_tag, GRAVI_P2VMRED_DUAL_SCIENCE) == 0)) {
345  proCatg = cpl_sprintf (GRAVI_VIS_DUAL_SCIENCE);
346  mode = cpl_sprintf ("gravi_dual");
347  }
348  else if ((strcmp(frame_tag, GRAVI_P2VMRED_SINGLE_CALIB) == 0)) {
349  proCatg = cpl_sprintf (GRAVI_VIS_SINGLE_CALIB);
350  mode = cpl_sprintf ("gravi_single");
351  }
352  else if ((strcmp(frame_tag, GRAVI_P2VMRED_SINGLE_SCIENCE) == 0)) {
353  proCatg = cpl_sprintf (GRAVI_VIS_SINGLE_SCIENCE);
354  mode = cpl_sprintf ("gravi_single");
355  }
356  else {
357  proCatg = cpl_sprintf ("UNKNOWN");
358  mode = cpl_sprintf ("gravi_single");
359  }
360 
361  cpl_msg_info (cpl_func,"Mode of the first frame is: %s (will be used for all frames)", mode);
362 
363  /*
364  * Loop on input RAW frames to be reduced
365  */
366 
367  nb_frame = cpl_frameset_get_size (recipe_frameset);
368  for (int ivis = 0; ivis < nb_frame; ivis++){
369 
370  cpl_msg_info (cpl_func, " ***** P2VMREDUCED %d over %d ***** ", ivis+1, nb_frame);
371 
372  frame = cpl_frameset_get_position (recipe_frameset, ivis);
373  p2vmred_data = gravi_data_load_frame (frame, used_frameset);
374 
375  /* Compute rejection flags for averaging */
376  if (gravi_param_get_bool (parlist, "gravity.signal.use-existing-rejection")) {
377  cpl_msg_info (cpl_func,"Don't recompute SNR and selection, use the existing one");
378  } else {
379  /* Compute the SNR/GDELAY */
380  gravi_compute_snr (p2vmred_data, parlist);
381  CPLCHECK_MSG ("Cannot compute SNR");
382 
383  /* Compute rejection flags for averaging */
384  gravi_compute_rejection (p2vmred_data, parlist);
385  CPLCHECK_MSG ("Cannot recompute rejection flags signals");
386  }
387 
388  /* Visibility and flux are averaged and the followings
389  * are saved in Visibility data in tables VIS, VIS2 and T3 */
390  tmpvis_data = gravi_compute_vis (p2vmred_data, parlist);
391  CPLCHECK_CLEAN ("Cannot average the P2VMRED frames into VIS");
392 
393  /* Merge with already existing */
394  if (ivis == 0) {
395  vis_data = tmpvis_data; tmpvis_data = NULL;
396  }
397  else {
398  cpl_msg_info (cpl_func,"Merge with previous OI_VIS");
399  gravi_data_append (vis_data, tmpvis_data, 1);
400  FREE (gravi_data_delete, tmpvis_data);
401  }
402  CPLCHECK_CLEAN ("Cannot merge the visibilities");
403 
404 
405  cpl_msg_info (cpl_func,"Free the p2vmreduced");
406  FREE (gravi_data_delete, p2vmred_data);
407  }
408  /* End loop on the input files to reduce */
409 
410  /* Perform the normalisation of the SC vis2 and visamp
411  * to match those of the FT */
412  if (!strcmp (gravi_param_get_string (parlist, "gravity.vis.vis-correction"), "FORCE")) {
413 
414  cpl_msg_info (cpl_func, "Align the SC visibilities on the FT");
415  gravi_normalize_sc_to_ft (vis_data);
416 
417  } else {
418  cpl_msg_info (cpl_func, "Don't align the SC visibilities on the FT");
419  }
420 
421  /* Co-add the observations if requested */
422  if (gravi_param_get_bool (parlist, "gravity.postprocess.average-vis")) {
423 
424  cpl_msg_warning (cpl_func, "Average the different observation (if any) = EXPERIMENTAL");
425  gravi_average_vis (vis_data);
426 
427  } else {
428  cpl_msg_info (cpl_func, "Don't average the different observation (if any)");
429  }
430 
431  /* Recompute the TIME column from the MJD column
432  * in all OIFITS tables to follow standard */
433  gravi_vis_mjd_to_time (vis_data);
434 
435  /* Save the output data file based on the first frame of the frameset */
436  frame = cpl_frameset_get_position (recipe_frameset, 0);
437 
438  gravi_data_save_new (vis_data, frameset, NULL, parlist,
439  used_frameset, frame, "gravity_vis_from_p2vmred",
440  NULL, proCatg);
441 
442  CPLCHECK_CLEAN ("Cannot save the VIS product");
443 
444  /* Terminate the function */
445  goto cleanup;
446 
447 cleanup:
448  /* Deallocation of all variables */
449  cpl_msg_info(cpl_func,"Memory cleanup");
450 
451  FREE (gravi_data_delete,p2vmred_data);
452  FREE (gravi_data_delete,vis_data);
453  FREE (gravi_data_delete,tmpvis_data);
454  FREE (cpl_frameset_delete,recipe_frameset);
455  FREE (cpl_frameset_delete,used_frameset);
456  FREE (cpl_free,proCatg);
457  FREE (cpl_free,mode);
458 
459  gravi_msg_function_exit(1);
460  return (int)cpl_error_get_code();
461 }