GRAVI Pipeline Reference Manual  1.2.3
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 averages the real-time data of 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_FLOW"\n"
70  "* Load the input file (loop on input files)\n"
71  "* Update the selection flag\n"
72  "* Average the real-time visibilities\n"
73  "* Write the product\n"
74  GRAVI_RECIPE_INPUT"\n"
75  GRAVI_P2VMRED_SINGLE_SCIENCE" : Input intermediate product\n"
76  GRAVI_RECIPE_OUTPUT"\n"
77  GRAVI_VIS_SINGLE_SCIENCE" : OIFITS with uncalibrated visibilities\n"
78  "";
79 
80 /*-----------------------------------------------------------------------------
81  Function code
82  -----------------------------------------------------------------------------*/
83 
84 /*----------------------------------------------------------------------------*/
94 /*----------------------------------------------------------------------------*/
95 int cpl_plugin_get_info(cpl_pluginlist * list)
96 {
97  cpl_recipe * recipe = cpl_calloc(1, sizeof *recipe );
98  cpl_plugin * plugin = &recipe->interface;
99 
100  if (cpl_plugin_init(plugin,
101  CPL_PLUGIN_API,
102  GRAVI_BINARY_VERSION,
103  CPL_PLUGIN_TYPE_RECIPE,
104  "gravity_vis_from_p2vmred",
105  gravity_vis_from_p2vmred_short,
106  gravity_vis_from_p2vmred_description,
107  "JB. Le Bouquin, Vincent Lapeyrere, ",
108  PACKAGE_BUGREPORT,
110  gravity_vis_from_p2vmred_create,
111  gravity_vis_from_p2vmred_exec,
112  gravity_vis_from_p2vmred_destroy)) {
113  cpl_msg_error(cpl_func, "Plugin initialization failed");
114  (void)cpl_error_set_where(cpl_func);
115  return 1;
116  }
117 
118  if (cpl_pluginlist_append(list, plugin)) {
119  cpl_msg_error(cpl_func, "Error adding plugin to list");
120  (void)cpl_error_set_where(cpl_func);
121  return 1;
122  }
123 
124  return 0;
125 }
126 
127 /*----------------------------------------------------------------------------*/
135 /*----------------------------------------------------------------------------*/
136 static int gravity_vis_from_p2vmred_create(cpl_plugin * plugin)
137 {
138  cpl_recipe * recipe;
139  cpl_parameter * p;
140 
141  /* Do not create the recipe if an error code is already set */
142  if (cpl_error_get_code() != CPL_ERROR_NONE) {
143  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
144  cpl_func, __LINE__, cpl_error_get_where());
145  return (int)cpl_error_get_code();
146  }
147 
148  if (plugin == NULL) {
149  cpl_msg_error(cpl_func, "Null plugin");
150  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
151  }
152 
153  /* Verify plugin type */
154  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
155  cpl_msg_error(cpl_func, "Plugin is not a recipe");
156  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
157  }
158 
159  /* Get the recipe */
160  recipe = (cpl_recipe *)plugin;
161 
162  /* Create the parameters list in the cpl_recipe object */
163  recipe->parameters = cpl_parameterlist_new();
164  if (recipe->parameters == NULL) {
165  cpl_msg_error(cpl_func, "Parameter list allocation failed");
166  cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);
167  }
168 
169  /* Fill the parameters list */
170  int isCalib = 0;
171 
172  /* Use static names (output_procatg.fits) */
173  gravi_parameter_add_static_name (recipe->parameters);
174 
175  /* Averaging */
176  gravi_parameter_add_average_vis (recipe->parameters);
177 
178  /* Snr */
179  gravi_parameter_add_compute_snr (recipe->parameters, isCalib);
180 
181  /* Rejection */
182  gravi_parameter_add_rejection (recipe->parameters, isCalib);
183 
184  /* Parameters for gravi_compute_vis */
185  gravi_parameter_add_compute_vis (recipe->parameters, isCalib);
186 
187  /* --Use existing selection */
188  p = cpl_parameter_new_value ("gravity.signal.use-existing-rejection", CPL_TYPE_BOOL,
189  "Use existing rejection flags (ignore related options)",
190  "gravity.signal", FALSE);
191  cpl_parameter_set_alias (p, CPL_PARAMETER_MODE_CLI, "use-existing-rejection");
192  cpl_parameter_disable (p, CPL_PARAMETER_MODE_ENV);
193  cpl_parameterlist_append (recipe->parameters, p);
194 
195  return 0;
196 }
197 
198 /*----------------------------------------------------------------------------*/
204 /*----------------------------------------------------------------------------*/
205 static int gravity_vis_from_p2vmred_exec(cpl_plugin * plugin)
206 {
207 
208  cpl_recipe * recipe;
209  int recipe_status;
210  cpl_errorstate initial_errorstate = cpl_errorstate_get();
211 
212 
213  /* Return immediately if an error code is already set */
214  if (cpl_error_get_code() != CPL_ERROR_NONE) {
215  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
216  cpl_func, __LINE__, cpl_error_get_where());
217  return (int)cpl_error_get_code();
218  }
219 
220  if (plugin == NULL) {
221  cpl_msg_error(cpl_func, "Null plugin");
222  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
223  }
224 
225  /* Verify plugin type */
226  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
227  cpl_msg_error(cpl_func, "Plugin is not a recipe");
228  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
229  }
230 
231  /* Get the recipe */
232  recipe = (cpl_recipe *)plugin;
233 
234  /* Verify parameter and frame lists */
235  if (recipe->parameters == NULL) {
236  cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
237  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
238  }
239  if (recipe->frames == NULL) {
240  cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");
241  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
242  }
243 
244  /* Invoke the recipe */
245  recipe_status = gravity_vis_from_p2vmred(recipe->frames, recipe->parameters);
246 
247  /* Ensure DFS-compliance of the products */
248  if (cpl_dfs_update_product_header(recipe->frames)) {
249  if (!recipe_status){
250  recipe_status = (int)cpl_error_get_code();
251  }
252  }
253 
254  if (!cpl_errorstate_is_equal(initial_errorstate)) {
255  /* Dump the error history since recipe execution start.
256  At this point the recipe cannot recover from the error */
257  cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);
258  }
259 
260  return recipe_status;
261 }
262 
263 /*----------------------------------------------------------------------------*/
269 /*----------------------------------------------------------------------------*/
270 static int gravity_vis_from_p2vmred_destroy(cpl_plugin * plugin)
271 {
272  cpl_recipe * recipe;
273 
274  if (plugin == NULL) {
275  cpl_msg_error(cpl_func, "Null plugin");
276  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
277  }
278 
279  /* Verify plugin type */
280  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
281  cpl_msg_error(cpl_func, "Plugin is not a recipe");
282  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
283  }
284 
285  /* Get the recipe */
286  recipe = (cpl_recipe *)plugin;
287 
288  cpl_parameterlist_delete(recipe->parameters);
289 
290  return 0;
291 }
292 
293 
294 /*----------------------------------------------------------------------------*/
302 /*----------------------------------------------------------------------------*/
303 static int gravity_vis_from_p2vmred(cpl_frameset * frameset,
304  const cpl_parameterlist * parlist)
305 {
306  cpl_frameset * recipe_frameset=NULL, *used_frameset=NULL;
307 
308  cpl_frame * frame=NULL;
309 
310  const char * frame_tag=NULL;
311  char * proCatg = NULL, * mode=NULL;
312 
313  gravi_data * p2vmred_data=NULL, * vis_data=NULL, * tmpvis_data=NULL;
314 
315  int nb_frame;
316 
317  /* Message */
318  gravity_print_banner ();
319  cpl_msg_set_time_on();
320  cpl_msg_set_component_on();
321  gravi_msg_function_start(1);
322 
323  cpl_ensure_code(gravi_dfs_set_groups(frameset) == CPL_ERROR_NONE,
324  cpl_error_get_code()) ;
325 
326  /* Dispatch the frameset */
327  recipe_frameset = gravi_frameset_extract_p2vmred_data (frameset);
328 
329  /* To use this recipe the frameset must contain a P2VMREDUCED file. */
330  if ( cpl_frameset_get_size (recipe_frameset) < 1 ) {
331  cpl_error_set_message (cpl_func, CPL_ERROR_ILLEGAL_INPUT,
332  "Illegal number of P2VMREDUCED file on the frameset");
333  goto cleanup;
334  }
335 
336  /* Insert calibration frame into the used frameset */
337  used_frameset = cpl_frameset_new();
338 
339  /*
340  * Select the PRO CATG (based on first frame)
341  */
342 
343  frame_tag = cpl_frame_get_tag (cpl_frameset_get_position (recipe_frameset, 0));
344 
345  if ((strcmp(frame_tag, GRAVI_P2VMRED_DUAL_CALIB) == 0)) {
346  proCatg = cpl_sprintf (GRAVI_VIS_DUAL_CALIB);
347  mode = cpl_sprintf ("gravi_dual");
348  }
349  else if ((strcmp(frame_tag, GRAVI_P2VMRED_DUAL_SCIENCE) == 0)) {
350  proCatg = cpl_sprintf (GRAVI_VIS_DUAL_SCIENCE);
351  mode = cpl_sprintf ("gravi_dual");
352  }
353  else if ((strcmp(frame_tag, GRAVI_P2VMRED_SINGLE_CALIB) == 0)) {
354  proCatg = cpl_sprintf (GRAVI_VIS_SINGLE_CALIB);
355  mode = cpl_sprintf ("gravi_single");
356  }
357  else if ((strcmp(frame_tag, GRAVI_P2VMRED_SINGLE_SCIENCE) == 0)) {
358  proCatg = cpl_sprintf (GRAVI_VIS_SINGLE_SCIENCE);
359  mode = cpl_sprintf ("gravi_single");
360  }
361  else {
362  proCatg = cpl_sprintf ("UNKNOWN");
363  mode = cpl_sprintf ("gravi_single");
364  }
365 
366  cpl_msg_info (cpl_func,"Mode of the first frame is: %s (will be used for all frames)", mode);
367 
368  /*
369  * Loop on input RAW frames to be reduced
370  */
371 
372  nb_frame = cpl_frameset_get_size (recipe_frameset);
373  for (int ivis = 0; ivis < nb_frame; ivis++){
374 
375  cpl_msg_info (cpl_func, " ***** P2VMREDUCED %d over %d ***** ", ivis+1, nb_frame);
376 
377  frame = cpl_frameset_get_position (recipe_frameset, ivis);
378  p2vmred_data = gravi_data_load_frame (frame, used_frameset);
379 
380  /* Compute rejection flags for averaging */
381  if (gravi_param_get_bool (parlist, "gravity.signal.use-existing-rejection")) {
382  cpl_msg_info (cpl_func,"Don't recompute SNR and selection, use the existing one");
383  } else {
384  /* Compute the SNR/GDELAY */
385  gravi_compute_snr (p2vmred_data, parlist);
386  CPLCHECK_MSG ("Cannot compute SNR");
387 
388  /* Compute rejection flags for averaging */
389  gravi_compute_rejection (p2vmred_data, parlist);
390  CPLCHECK_MSG ("Cannot recompute rejection flags signals");
391  }
392 
393  /* Loop on the wanted sub-integration */
394  cpl_size current_frame = 0;
395  while (current_frame >= 0)
396  {
397 
398  /* Visibility and flux are averaged and the followings
399  * are saved in Visibility data in tables VIS, VIS2 and T3 */
400  tmpvis_data = gravi_compute_vis (p2vmred_data, parlist, &current_frame);
401  CPLCHECK_CLEAN ("Cannot average the P2VMRED frames into VIS");
402 
403  /* Set the mean TIME and mean MJD if required */
404  if (gravi_param_get_bool (parlist, "gravity.vis.force-same-time") ) {
405  cpl_msg_info (cpl_func,"Force same time for all quantities/baselines");
406  gravi_vis_force_time (tmpvis_data);
407  CPLCHECK_CLEAN ("Cannot average the TIME in OI_VIS");
408  }
409 
410  /* Merge with already existing */
411  if (vis_data == NULL) {
412  vis_data = tmpvis_data; tmpvis_data = NULL;
413  }
414  else {
415  cpl_msg_info (cpl_func,"Merge with previous OI_VIS");
416  gravi_data_append (vis_data, tmpvis_data, 1);
417  FREE (gravi_data_delete, tmpvis_data);
418  }
419  CPLCHECK_CLEAN ("Cannot merge the visibilities");
420 
421  }
422 
423  cpl_msg_info (cpl_func,"Free the p2vmreduced");
424  FREE (gravi_data_delete, p2vmred_data);
425  }
426  /* End loop on the input files to reduce */
427 
428  /* Compute QC parameters */
429  gravi_compute_vis_qc (vis_data);
430 
431  /* Perform the normalisation of the SC vis2 and visamp
432  * to match those of the FT */
433  if (!strcmp (gravi_param_get_string (parlist, "gravity.vis.vis-correction-sc"), "FORCE")) {
434 
435  cpl_msg_info (cpl_func, "Align the SC visibilities on the FT");
436  gravi_normalize_sc_to_ft (vis_data);
437 
438  } else {
439  cpl_msg_info (cpl_func, "Don't align the SC visibilities on the FT");
440  }
441 
442  /* Co-add the observations if requested */
443  if (gravi_param_get_bool (parlist, "gravity.postprocess.average-vis")) {
444 
445  cpl_msg_warning (cpl_func, "Average the different observation (if any) = EXPERIMENTAL");
446  gravi_average_vis (vis_data);
447 
448  } else {
449  cpl_msg_info (cpl_func, "Don't average the different observation (if any)");
450  }
451 
452  /* Recompute the TIME column from the MJD column
453  * in all OIFITS tables to follow standard */
454  gravi_vis_mjd_to_time (vis_data);
455 
456  /* Save the output data file based on the first frame of the frameset */
457  frame = cpl_frameset_get_position (recipe_frameset, 0);
458 
459  gravi_data_save_new (vis_data, frameset, NULL, NULL, parlist,
460  used_frameset, frame, "gravity_vis_from_p2vmred",
461  NULL, proCatg);
462 
463  CPLCHECK_CLEAN ("Cannot save the VIS product");
464 
465  /* Terminate the function */
466  goto cleanup;
467 
468 cleanup:
469  /* Deallocation of all variables */
470  cpl_msg_info(cpl_func,"Memory cleanup");
471 
472  FREE (gravi_data_delete,p2vmred_data);
473  FREE (gravi_data_delete,vis_data);
474  FREE (gravi_data_delete,tmpvis_data);
475  FREE (cpl_frameset_delete,recipe_frameset);
476  FREE (cpl_frameset_delete,used_frameset);
477  FREE (cpl_free,proCatg);
478  FREE (cpl_free,mode);
479 
480  gravi_msg_function_exit(1);
481  return (int)cpl_error_get_code();
482 }
gravi_data * gravi_data_load_frame(cpl_frame *frame, cpl_frameset *used_frameset)
Load a FITS file and create a gravi_data.
Definition: gravi_data.c:573
cpl_error_code gravi_compute_vis_qc(gravi_data *vis_data)
The function compute the QC parameters for a VIS (averaged) data.
Definition: gravi_vis.c:2048
cpl_error_code gravi_compute_snr(gravi_data *p2vmred_data, const cpl_parameterlist *parlist)
Compute real-time SNR and Group-Delay of the observation.
Definition: gravi_signal.c:511
gravi_data * gravi_compute_vis(gravi_data *p2vmred_data, const cpl_parameterlist *parlist, cpl_size *current_frame)
The function average the individual frames of a P2VMREDUCED file into a final, single observation per...
Definition: gravi_vis.c:1509
cpl_error_code gravi_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
Definition: gravi_dfs.c:78
cpl_error_code gravi_vis_mjd_to_time(gravi_data *vis_data)
Recompute the TIME column of all OIFITS extension from the MJD column, following the OIFITS standard ...
Definition: gravi_vis.c:2403
cpl_error_code gravi_compute_rejection(gravi_data *p2vmred_data, const cpl_parameterlist *parlist)
Create rejection flags P2VMREDUCED file.
const char * gravi_get_license(void)
Get the pipeline copyright and license.
Definition: gravi_utils.c:104
cpl_error_code gravi_parameter_add_rejection(cpl_parameterlist *self, int isCalib)
Add rejection parameters to the input parameter list.
Definition: gravi_dfs.c:593
cpl_error_code gravi_data_save_new(gravi_data *self, cpl_frameset *allframes, const char *filename, const char *suffix, const cpl_parameterlist *parlist, cpl_frameset *usedframes, cpl_frame *frame, const char *recipe, cpl_propertylist *applist, const char *proCatg)
Save a gravi data in a CPL-complian FITS file.
Definition: gravi_data.c:896
cpl_error_code gravi_average_vis(gravi_data *oi_data)
Coadd the observations together.
Definition: gravi_vis.c:2750
cpl_error_code gravi_vis_force_time(gravi_data *oi_data)
Force all data in OI_TABLE to have the same TIME and MJD.
Definition: gravi_vis.c:3761
cpl_error_code gravi_normalize_sc_to_ft(gravi_data *vis_data)
Align the SC visibilities on the FT visibilities.
Definition: gravi_vis.c:2317
void gravi_data_delete(gravi_data *self)
Delete a gravi data.
Definition: gravi_data.c:137
cpl_error_code gravi_data_append(gravi_data *first, const gravi_data *second, int force)
Append a gravi_data into another existing one.
Definition: gravi_data.c:290