GRAVI Pipeline Reference Manual  0.9.10
gravity_vis.c
1 /* $Id: gravity_vis.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 /*
22  * $Author: nazouaoui $
23  * $Date: 2011/12/3 09:16:12 $
24  * $Revision: 1.29 $
25  * $Name: $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 /*-----------------------------------------------------------------------------
33  Includes
34  -----------------------------------------------------------------------------*/
35 
36 #include <cpl.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <time.h>
40 
41 #include "gravi_data.h"
42 #include "gravi_pfits.h"
43 #include "gravi_dfs.h"
44 
45 #include "gravi_utils.h"
46 
47 #include "gravi_calib.h"
48 #include "gravi_p2vmred.h"
49 #include "gravi_eop.h"
50 #include "gravi_metrology.h"
51 
52 #include "gravi_signal.h"
53 #include "gravi_vis.h"
54 #include "gravi_tf.h"
55 
56 #include "gravi_preproc.h"
57 
58 /*-----------------------------------------------------------------------------
59  Private function prototypes
60  -----------------------------------------------------------------------------*/
61 
62 static int gravity_vis_create(cpl_plugin *);
63 static int gravity_vis_exec(cpl_plugin *);
64 static int gravity_vis_destroy(cpl_plugin *);
65 static int gravity_vis(cpl_frameset *, const cpl_parameterlist *);
66 
67 /*-----------------------------------------------------------------------------
68  Static variables
69  -----------------------------------------------------------------------------*/
70 static char gravity_vis_short[] = "Compute the visibilities from raw observation of OBJECT.";
71 static char gravity_vis_description[] =
72  "This recipe is associated to the observing template. Its reduces the raw data acquired on calibrator or science targets and computes the uncalibrated visibilities, saved in an OIFITS file. If several OBJECT are provided, the recipe will reduce all of them and merge the resulting data into a single OIFITS. If several SKY_RAW are provided, the recipe reduces the first OBJECT with the first SKY. Then each new OBJECT with the next SKY. When the number of sky is reached, the recipe loops back to first sky (so if the number of SKYs is larger than the number of OBJECTs, the last SKY won't be used). The recipe will reduce the data even if no SKY or no DARK is provided. However this will lead to wrong estimate of the visibility and square visibility of the object. If the DIAMETER_CAT is not provided, the recipe will use the diameter provided in the header to compute the transfer function QC parameters."
73  "\n"
74  "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"
75  GRAVI_RECIPE_INPUT"\n"
76  GRAVI_FLAT_MAP" : flat calibration (PRO.CATG="GRAVI_FLAT_MAP")\n"
77  GRAVI_BAD_MAP" : badpixel calibration (PRO.CATG="GRAVI_BAD_MAP") \n"
78  GRAVI_WAVE_MAP" : wave calibration (PRO.CATG="GRAVI_WAVE_MAP")\n"
79  GRAVI_P2VM_MAP" : p2vm calibration (PRO.CATG="GRAVI_P2VM_MAP")\n"
80  GRAVI_DARK_MAP" : dark calibration (PRO.CATG="GRAVI_DARK_MAP")\n"
81  GRAVI_SINGLE_SCIENCE_RAW" : raw object (DPR.TYPE=OBJECT,SINGLE)\n"
82  GRAVI_SINGLE_SKY_RAW" : raw sky (DPR.TYPE=SKY,SINGLE)\n"
83  GRAVI_DISP_MODEL" (opt) : fiber dispersion model (PRO.CATG="GRAVI_DISP_MODEL")\n"
84  GRAVI_DIAMETER_CAT" (opt) : catalog of diameter (PRO.CATG="GRAVI_DIAMETER_CAT")\n"
85  GRAVI_RECIPE_OUTPUT"\n"
86  GRAVI_VIS_SINGLE_SCIENCE" : OIFITS with uncalibrated visibilities\n"
87  GRAVI_SINGLE_SKY_MAP" (opt) : sky map\n"
88  GRAVI_P2VMRED_SINGLE_SCIENCE" (opt) : intermediate product\n"
89  GRAVI_SPECTRUM" (opt) : intermediate product\n"
90  GRAVI_PREPROC" (opt) : intermediate product\n"
91  "";
92 
93 /*-----------------------------------------------------------------------------
94  Function code
95  -----------------------------------------------------------------------------*/
96 
97 /*----------------------------------------------------------------------------*/
107 /*----------------------------------------------------------------------------*/
108 int cpl_plugin_get_info(cpl_pluginlist * list)
109 {
110  cpl_recipe * recipe = cpl_calloc(1, sizeof *recipe );
111  cpl_plugin * plugin = &recipe->interface;
112 
113  if (cpl_plugin_init(plugin,
114  CPL_PLUGIN_API,
115  GRAVI_BINARY_VERSION,
116  CPL_PLUGIN_TYPE_RECIPE,
117  "gravity_vis",
118  gravity_vis_short,
119  gravity_vis_description,
120  "Nabih Azouaoui, Vincent Lapeyrere, JB. Le Bouquin",
121  PACKAGE_BUGREPORT,
122  gravi_get_license(),
123  gravity_vis_create,
124  gravity_vis_exec,
125  gravity_vis_destroy)) {
126  cpl_msg_error(cpl_func, "Plugin initialization failed");
127  (void)cpl_error_set_where(cpl_func);
128  return 1;
129  }
130 
131  if (cpl_pluginlist_append(list, plugin)) {
132  cpl_msg_error(cpl_func, "Error adding plugin to list");
133  (void)cpl_error_set_where(cpl_func);
134  return 1;
135  }
136 
137  return 0;
138 }
139 
140 /*----------------------------------------------------------------------------*/
148 /*----------------------------------------------------------------------------*/
149 static int gravity_vis_create(cpl_plugin * plugin)
150 {
151  cpl_recipe * recipe;
152  cpl_parameter * p;
153 
154  /* Do not create the recipe if an error code is already set */
155  if (cpl_error_get_code() != CPL_ERROR_NONE) {
156  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
157  cpl_func, __LINE__, cpl_error_get_where());
158  return (int)cpl_error_get_code();
159  }
160 
161  if (plugin == NULL) {
162  cpl_msg_error(cpl_func, "Null plugin");
163  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
164  }
165 
166  /* Verify plugin type */
167  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
168  cpl_msg_error(cpl_func, "Plugin is not a recipe");
169  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
170  }
171 
172  /* Get the recipe */
173  recipe = (cpl_recipe *)plugin;
174 
175  /* Create the parameters list in the cpl_recipe object */
176  recipe->parameters = cpl_parameterlist_new();
177  if (recipe->parameters == NULL) {
178  cpl_msg_error(cpl_func, "Parameter list allocation failed");
179  cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);
180  }
181 
182  /* Fill the parameters list */
183  int isCalib = 0;
184 
185  /* Use static names (output_procatg.fits) */
186  gravi_parameter_add_static_name (recipe->parameters);
187 
188  /* Intermediate files */
189  gravi_parameter_add_biassub_file (recipe->parameters);
190  gravi_parameter_add_spectrum_file (recipe->parameters);
191  gravi_parameter_add_preproc_file (recipe->parameters);
192  gravi_parameter_add_p2vmred_file (recipe->parameters);
193  gravi_parameter_add_astro_file (recipe->parameters);
194 
195  /* Averaging */
196  gravi_parameter_add_average_vis (recipe->parameters);
197 
198  /* Bias-method */
199  gravi_parameter_add_biasmethod (recipe->parameters);
200 
201  /* Extraction */
202  gravi_parameter_add_extract (recipe->parameters);
203 
204  /* Snr, signal, rejectio flags, vis */
205  gravi_parameter_add_compute_snr (recipe->parameters, isCalib);
206  gravi_parameter_add_compute_signal (recipe->parameters, isCalib);
207  gravi_parameter_add_rejection (recipe->parameters, isCalib);
208  gravi_parameter_add_compute_vis (recipe->parameters, isCalib);
209 
210  /* Correct from internal transmission */
211  p = cpl_parameter_new_value ("gravity.vis.flat-flux", CPL_TYPE_BOOL,
212  "Flat the OI_FLUX with instrument transmission recorded in the\n"
213  " input P2VM calibration map. Thus flux is the spectrum recorded\n"
214  " at the detector (FALSE); or the spectrum at the instrument entrance (TRUE).",
215  "gravity.vis", FALSE);
216  cpl_parameter_set_alias (p, CPL_PARAMETER_MODE_CLI, "flat-flux");
217  cpl_parameter_disable (p, CPL_PARAMETER_MODE_ENV);
218  cpl_parameterlist_append (recipe->parameters, p);
219 
220  /* Average sky */
221  p = cpl_parameter_new_value ("gravity.preproc.average-sky", CPL_TYPE_BOOL,
222  "Average the SKYs into a master SKY. If FALSE, the recipe loops\n "
223  "over the SKY to reduce each OBJECT with a different SKY",
224  "gravity.preproc", FALSE);
225  cpl_parameter_set_alias (p, CPL_PARAMETER_MODE_CLI, "average-sky");
226  cpl_parameter_disable (p, CPL_PARAMETER_MODE_ENV);
227  cpl_parameterlist_append (recipe->parameters, p);
228 
229  return 0;
230 }
231 
232 /*----------------------------------------------------------------------------*/
238 /*----------------------------------------------------------------------------*/
239 static int gravity_vis_exec(cpl_plugin * plugin)
240 {
241 
242  cpl_recipe * recipe;
243  int recipe_status;
244  cpl_errorstate initial_errorstate = cpl_errorstate_get();
245 
246 
247  /* Return immediately if an error code is already set */
248  if (cpl_error_get_code() != CPL_ERROR_NONE) {
249  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
250  cpl_func, __LINE__, cpl_error_get_where());
251  return (int)cpl_error_get_code();
252  }
253 
254  if (plugin == NULL) {
255  cpl_msg_error(cpl_func, "Null plugin");
256  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
257  }
258 
259  /* Verify plugin type */
260  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
261  cpl_msg_error(cpl_func, "Plugin is not a recipe");
262  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
263  }
264 
265  /* Get the recipe */
266  recipe = (cpl_recipe *)plugin;
267 
268  /* Verify parameter and frame lists */
269  if (recipe->parameters == NULL) {
270  cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
271  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
272  }
273  if (recipe->frames == NULL) {
274  cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");
275  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
276  }
277 
278  /* Invoke the recipe */
279  recipe_status = gravity_vis(recipe->frames, recipe->parameters);
280 
281  /* Ensure DFS-compliance of the products */
282  if (cpl_dfs_update_product_header(recipe->frames)) {
283  if (!recipe_status){
284  recipe_status = (int)cpl_error_get_code();
285  }
286  }
287 
288  if (!cpl_errorstate_is_equal(initial_errorstate)) {
289  /* Dump the error history since recipe execution start.
290  At this point the recipe cannot recover from the error */
291  cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);
292  }
293 
294  return recipe_status;
295 }
296 
297 /*----------------------------------------------------------------------------*/
303 /*----------------------------------------------------------------------------*/
304 static int gravity_vis_destroy(cpl_plugin * plugin)
305 {
306  cpl_recipe * recipe;
307 
308  if (plugin == NULL) {
309  cpl_msg_error(cpl_func, "Null plugin");
310  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
311  }
312 
313  /* Verify plugin type */
314  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
315  cpl_msg_error(cpl_func, "Plugin is not a recipe");
316  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
317  }
318 
319  /* Get the recipe */
320  recipe = (cpl_recipe *)plugin;
321 
322  cpl_parameterlist_delete(recipe->parameters);
323 
324  return 0;
325 }
326 
327 
328 /*----------------------------------------------------------------------------*/
336 /*----------------------------------------------------------------------------*/
337 static int gravity_vis(cpl_frameset * frameset,
338  const cpl_parameterlist * parlist)
339 {
340  cpl_frameset * recipe_frameset=NULL, * wavecalib_frameset=NULL, * dark_frameset=NULL,
341  * darkcalib_frameset=NULL, * sky_frameset=NULL, * flatcalib_frameset=NULL, * p2vmcalib_frameset=NULL,
342  * badcalib_frameset=NULL, *used_frameset=NULL, * current_frameset=NULL, * dispcalib_frameset=NULL,
343  * diamcat_frameset = NULL, *eop_frameset = NULL;
344 
345  cpl_frame * frame=NULL;
346 
347  const char * frame_tag=NULL;
348  char * proCatg = NULL, * mode=NULL, * redCatg = NULL, * skyCatg = NULL;
349 
350  gravi_data * p2vm_map=NULL, * data=NULL, * wave_map=NULL, * dark_map=NULL,
351  * profile_map=NULL, * badpix_map=NULL, * preproc_data=NULL, * p2vmred_data=NULL, * tmpvis_data=NULL,
352  * vis_data=NULL, * disp_map=NULL, * diamcat_data=NULL, *eop_map=NULL;
353  gravi_data ** sky_maps = NULL;
354 
355  int nb_frame, nb_sky, isky;
356 
357  /* Message */
358  gravity_print_banner ();
359  cpl_msg_set_time_on();
360  cpl_msg_set_component_on();
361  gravi_msg_function_start(1);
362 
363  cpl_ensure_code(gravi_dfs_set_groups(frameset) == CPL_ERROR_NONE,
364  cpl_error_get_code()) ;
365 
366  /* Dispatch the frameset */
367  p2vmcalib_frameset = gravi_frameset_extract_p2vm_map (frameset);
368  darkcalib_frameset = gravi_frameset_extract_dark_map (frameset);
369  wavecalib_frameset = gravi_frameset_extract_wave_map (frameset);
370  dark_frameset = gravi_frameset_extract_dark_data (frameset);
371  flatcalib_frameset = gravi_frameset_extract_flat_map (frameset);
372  badcalib_frameset = gravi_frameset_extract_bad_map (frameset);
373  dispcalib_frameset = gravi_frameset_extract_disp_map (frameset);
374  diamcat_frameset = gravi_frameset_extract_diamcat_map (frameset);
375  eop_frameset = gravi_frameset_extract_eop_map (frameset);
376 
377  recipe_frameset = gravi_frameset_extract_fringe_data (frameset);
378  sky_frameset = gravi_frameset_extract_sky_data (frameset);
379 
380  /* To use this recipe the frameset must contain the p2vm, wave and
381  * gain calibration file. */
382  if ( cpl_frameset_get_size (p2vmcalib_frameset) !=1 ||
383  cpl_frameset_get_size (wavecalib_frameset) !=1 ||
384  cpl_frameset_get_size (flatcalib_frameset) !=1 ||
385  cpl_frameset_get_size (badcalib_frameset) != 1 ||
386  cpl_frameset_get_size (recipe_frameset) < 1 ||
387  (cpl_frameset_is_empty (dark_frameset) &&
388  cpl_frameset_is_empty (darkcalib_frameset) &&
389  cpl_frameset_is_empty (sky_frameset)) ) {
390  cpl_error_set_message (cpl_func, CPL_ERROR_ILLEGAL_INPUT,
391  "Illegal number of P2VM, FLAT, WAVE, BAD, DARK or SKY, OBJECT file on the frameset");
392  cpl_error_set_message (cpl_func, CPL_ERROR_ILLEGAL_INPUT,
393  "See online help: esorex --man gravity_vis");
394  goto cleanup;
395  }
396 
397  /* Insert calibration frame into the used frameset */
398  used_frameset = cpl_frameset_new();
399 
400  /*
401  * Identify the DARK in the input frameset
402  */
403 
404  if (!cpl_frameset_is_empty (dark_frameset)) {
405 
406  frame = cpl_frameset_get_position (dark_frameset, 0);
407  data = gravi_data_load_rawframe (frame, used_frameset);
408  gravi_data_detector_cleanup (data, parlist);
409 
410  /* Compute dark */
411  dark_map = gravi_compute_dark (data);
412  FREE (gravi_data_delete, data);
413 
414  CPLCHECK_CLEAN ("Could not compute the DARK map");
415 
416  /* Save the dark map */
417  gravi_data_save_new (dark_map, frameset, NULL, parlist,
418  NULL, frame, "gravity_vis",
419  NULL, GRAVI_DARK_MAP);
420 
421  CPLCHECK_CLEAN ("Could not save the DARK map");
422  }
423  else if (!cpl_frameset_is_empty (darkcalib_frameset)) {
424 
425  frame = cpl_frameset_get_position (darkcalib_frameset, 0);
426  dark_map = gravi_data_load_frame (frame, used_frameset);
427 
428  CPLCHECK_CLEAN ("Could not load the DARK map");
429  }
430  else
431  cpl_msg_info (cpl_func, "There is no DARK in the frame set");
432 
433  /* Identify the BAD in the input frameset */
434  frame = cpl_frameset_get_position (badcalib_frameset, 0);
435  badpix_map = gravi_data_load_frame (frame, used_frameset);
436 
437  /* Identify the FLAT in the input frameset */
438  frame = cpl_frameset_get_position (flatcalib_frameset, 0);
439  profile_map = gravi_data_load_frame (frame, used_frameset);
440 
441  /* Identify the WAVE in the input frameset */
442  frame = cpl_frameset_get_position (wavecalib_frameset, 0);
443  wave_map = gravi_data_load_frame (frame, used_frameset);
444 
445  /* Identify the P2VM in the input frameset */
446  frame = cpl_frameset_get_position (p2vmcalib_frameset, 0);
447  p2vm_map = gravi_data_load_frame (frame, used_frameset);
448 
449  /* Load the DISP_MODEL in the input frameset */
450  if (!cpl_frameset_is_empty (dispcalib_frameset)) {
451  frame = cpl_frameset_get_position (dispcalib_frameset, 0);
452  disp_map = gravi_data_load_frame (frame, used_frameset);
453  }
454  else
455  cpl_msg_info (cpl_func, "There is no DISP_MODEL in the frameset");
456 
457  /* Load the EOP_PARAM */
458  if ( !cpl_frameset_is_empty (eop_frameset) ) {
459  frame = cpl_frameset_get_position (eop_frameset, 0);
460  eop_map = gravi_data_load_frame (frame, used_frameset);
461  }
462  else
463  cpl_msg_info (cpl_func, "There is no EOP_PARAM in the frameset");
464 
465  /* Load the DIAMETER_CAT */
466  if ( !cpl_frameset_is_empty (diamcat_frameset) ) {
467  frame = cpl_frameset_get_position (diamcat_frameset, 0);
468  diamcat_data = gravi_data_load_frame (frame, used_frameset);
469  }
470  else
471  cpl_msg_info (cpl_func, "There is no DIAMETER_CAT in the frameset");
472 
473 
474  CPLCHECK_CLEAN ("Error while loading the calibration maps");
475 
476  /*
477  * Select the PRO CATG (based on first frame)
478  */
479 
480  frame_tag = cpl_frame_get_tag (cpl_frameset_get_position (recipe_frameset, 0));
481 
482  if ((strcmp(frame_tag, GRAVI_DUAL_CALIB_RAW) == 0)) {
483  redCatg = cpl_sprintf (GRAVI_P2VMRED_DUAL_CALIB);
484  proCatg = cpl_sprintf (GRAVI_VIS_DUAL_CALIB);
485  skyCatg = cpl_sprintf (GRAVI_DUAL_SKY_MAP);
486  mode = cpl_sprintf ("gravi_dual");
487  }
488  else if ((strcmp(frame_tag, GRAVI_DUAL_SCIENCE_RAW) == 0)) {
489  redCatg = cpl_sprintf (GRAVI_P2VMRED_DUAL_SCIENCE);
490  proCatg = cpl_sprintf (GRAVI_VIS_DUAL_SCIENCE);
491  skyCatg = cpl_sprintf (GRAVI_DUAL_SKY_MAP);
492  mode = cpl_sprintf ("gravi_dual");
493  }
494  else if ((strcmp(frame_tag, GRAVI_SINGLE_CALIB_RAW) == 0)) {
495  redCatg = cpl_sprintf (GRAVI_P2VMRED_SINGLE_CALIB);
496  proCatg = cpl_sprintf (GRAVI_VIS_SINGLE_CALIB);
497  skyCatg = cpl_sprintf (GRAVI_SINGLE_SKY_MAP);
498  mode = cpl_sprintf ("gravi_single");
499  }
500  else if ((strcmp(frame_tag, GRAVI_SINGLE_SCIENCE_RAW) == 0)) {
501  redCatg = cpl_sprintf (GRAVI_P2VMRED_SINGLE_SCIENCE);
502  proCatg = cpl_sprintf (GRAVI_VIS_SINGLE_SCIENCE);
503  skyCatg = cpl_sprintf (GRAVI_SINGLE_SKY_MAP);
504  mode = cpl_sprintf ("gravi_single");
505  }
506  else {
507  cpl_error_set_message (cpl_func, CPL_ERROR_ILLEGAL_INPUT,
508  "Cannot recognize the input DO.CATG");
509  goto cleanup;
510  }
511 
512  cpl_msg_info (cpl_func,"Mode of the first frame is: %s (will be used for all frames)", mode);
513 
514  /*
515  * Mode for the SKY
516  */
517  int averageSky = gravi_param_get_bool (parlist,"gravity.preproc.average-sky");
518 
519  /*
520  * Loop on input SKY frames to be reduced
521  */
522  nb_sky = cpl_frameset_get_size (sky_frameset);
523  sky_maps = cpl_calloc (CPL_MAX(nb_sky,1), sizeof(gravi_data*));
524 
525  for (int isky = 0; isky < nb_sky; isky++){
526 
527  /* Load the raw SKY */
528  cpl_msg_info (cpl_func, " ***** SKY %d over %d ***** ", isky+1, nb_sky);
529  frame = cpl_frameset_get_position (sky_frameset, isky);
530  data = gravi_data_load_rawframe (frame, used_frameset);
531  gravi_data_detector_cleanup (data, parlist);
532 
533  /* Compute the SKY map */
534  sky_maps[isky] = gravi_compute_dark (data);
535  FREE (gravi_data_delete, data);
536 
537  CPLCHECK_CLEAN ("Error while computing the sky_map");
538 
539  /* Save the SKY map */
540  if (averageSky == 0) {
541  gravi_data_save_new (sky_maps[isky], frameset, NULL, parlist,
542  NULL, frame, "gravity_vis",
543  NULL, skyCatg);
544  CPLCHECK_CLEAN ("Could not save the sky");
545  }
546  }
547 
548  /*
549  * Average the sky if requested
550  */
551 
552  if (averageSky == 1) {
553  cpl_msg_info (cpl_func, "Do a MASTER SKY from the %d skys", nb_sky);
554 
555  gravi_data * msky_map;
556  msky_map = gravi_average_dark (sky_maps, nb_sky);
557  CPLCHECK_CLEAN ("Cannot do master sky");
558 
559  gravi_data_save_new (msky_map, frameset, NULL, parlist, sky_frameset,
560  cpl_frameset_get_position (sky_frameset, 0),
561  "gravity_vis", NULL, skyCatg);
562  CPLCHECK_CLEAN ("Cannot save master sky");
563 
564  /* Add all sky to used_frameset, and move pointers */
565  cpl_frameset_join (used_frameset, sky_frameset);
566  for (int isky = 0; isky < nb_sky; isky++)
567  FREE (gravi_data_delete, sky_maps[isky]);
568  sky_maps[0] = msky_map;
569  nb_sky = 1;
570  }
571 
572  /*
573  * Loop on input RAW frames to be reduced
574  */
575 
576  nb_frame = cpl_frameset_get_size (recipe_frameset);
577 
578  for (int ivis = 0; ivis < nb_frame; ivis++){
579  current_frameset = cpl_frameset_duplicate (used_frameset);
580 
581  cpl_msg_info (cpl_func, " ***** OBJECT %d over %d ***** ", ivis+1, nb_frame);
582 
583  /*
584  * Identify the SKY for this OBJECT
585  */
586  isky = nb_sky>0 ? ivis % nb_sky : 0;
587 
588  if (nb_sky == 0) {
589  /* No SKY */
590  cpl_msg_info (cpl_func, "There is no SKY in the frameset");
591  }
592  else if (averageSky) {
593  /* Use master SKY already computed, already in frameset */
594  cpl_msg_info (cpl_func, "Use MASTER SKY (already reduced)");
595  }
596  else {
597  /* SKY already computed, add in the used_frameset */
598  cpl_msg_info (cpl_func, "Use SKY %i over %i (already reduced)", isky+1, nb_sky);
599  frame = cpl_frameset_get_position (sky_frameset, isky);
600 
601  /* Add this frame to the current_frameset as well */
602  cpl_frameset_insert (current_frameset, cpl_frame_duplicate (frame));
603  }
604 
605  /*
606  * Reduce the OBJECT
607  */
608 
609  frame = cpl_frameset_get_position (recipe_frameset, ivis);
610  data = gravi_data_load_rawframe (frame, current_frameset);
611  gravi_data_detector_cleanup (data, parlist);
612 
613  /* Option save the preproc file */
614  if (gravi_param_get_bool (parlist,"gravity.dfs.bias-subtracted-file")) {
615 
616  gravi_data_save_new (data, frameset, NULL, parlist,
617  current_frameset, frame, "gravity_vis",
618  NULL, "BIAS_SUBTRACTED");
619 
620  CPLCHECK_CLEAN ("Cannot save the BIAS_SUBTRACTED product");
621  }
622 
623 
624  /* Check the shutters */
625  if ( !gravi_data_check_shutter_open (data) ) {
626  cpl_msg_warning (cpl_func, "Shutter problem in the OBJECT");
627  }
628 
629  /* Extract spectrum */
630  preproc_data = gravi_extract_spectrum (data, profile_map, dark_map, badpix_map,
631  sky_maps[isky], parlist);
632  CPLCHECK_CLEAN ("Cannot extract spectrum");
633 
634  /* Option save the spectrum file */
635  if (gravi_param_get_bool (parlist,"gravity.dfs.spectrum-file")) {
636  gravi_data_save_new (preproc_data, frameset, NULL, parlist,
637  current_frameset, frame, "gravity_vis",
638  NULL, GRAVI_SPECTRUM);
639  CPLCHECK_CLEAN ("Cannot save the SPECTRUM product");
640  }
641 
642  /* Rescale to common wavelength */
643  gravi_align_spectrum (preproc_data, wave_map, p2vm_map);
644  CPLCHECK_CLEAN ("Cannot re-interpolate spectrum");
645 
646  /* Option save the preproc file */
647  if (gravi_param_get_bool (parlist,"gravity.dfs.preproc-file")) {
648  gravi_data_save_new (preproc_data, frameset, NULL, parlist,
649  current_frameset, frame, "gravity_vis",
650  NULL, GRAVI_PREPROC);
651  CPLCHECK_CLEAN ("Cannot save the PREPROC product");
652  }
653 
654  /* Move extensions from raw_data and delete it */
655  gravi_data_move_ext (preproc_data, data, GRAVI_ARRAY_GEOMETRY_EXT);
656  gravi_data_move_ext (preproc_data, data, GRAVI_OPTICAL_TRAIN_EXT);
657  gravi_data_move_ext (preproc_data, data, GRAVI_OPDC_EXT);
658  gravi_data_move_ext (preproc_data, data, GRAVI_FDDL_EXT);
659  gravi_data_move_ext (preproc_data, data, GRAVI_METROLOGY_EXT);
660  FREE (gravi_data_delete, data);
661  CPLCHECK_CLEAN ("Cannot move ext");
662 
663  /* Compute the flux and visibilities for each telescope and
664  * per acquisition with the P2VM applied to preproc_data */
665  p2vmred_data = gravi_compute_p2vmred (preproc_data, p2vm_map, mode, parlist);
666  CPLCHECK_CLEAN ("Cannot apply p2vm to the preproc data");
667 
668  /* Move extensions and delete preproc */
669  gravi_data_move_ext (p2vmred_data, preproc_data, GRAVI_METROLOGY_EXT);
670  gravi_data_move_ext (p2vmred_data, preproc_data, GRAVI_FDDL_EXT);
671  gravi_data_move_ext (p2vmred_data, preproc_data, GRAVI_OPDC_EXT);
672  FREE (gravi_data_delete, preproc_data);
673  CPLCHECK_CLEAN ("Cannot delete preproc");
674 
675  /* Reduce the OPDC table */
676  gravi_compute_opdc_state (p2vmred_data);
677  CPLCHECK_CLEAN ("Cannot reduce OPDC");
678 
679  /* Reduce the metrology into OI_VIS_MET */
680  gravi_metrology_reduce (p2vmred_data);
681  CPLCHECK_CLEAN ("Cannot reduce metrology");
682 
683  /* Compute the uv and pointing directions with ERFA */
684  gravi_compute_uv (p2vmred_data, eop_map);
685  CPLCHECK_CLEAN ("Cannot compute uv");
686 
687  gravi_compute_pointing (p2vmred_data, eop_map);
688  CPLCHECK_CLEAN ("Cannot compute pointing");
689 
690  /* Compute the QC0 about tau0 from piezo signals */
691  gravi_compute_tau0 (p2vmred_data);
692 
693  /* Compute the SNR_BOOT and GDELAY_BOOT */
694  gravi_compute_snr (p2vmred_data, parlist);
695  CPLCHECK_MSG ("Cannot compute SNR");
696 
697  /* Compute the signals for averaging */
698  gravi_compute_signals (p2vmred_data, disp_map, parlist);
699  CPLCHECK_MSG ("Cannot compute signals");
700 
701  /* Compute rejection flags for averaging */
702  gravi_compute_rejection (p2vmred_data, parlist);
703  CPLCHECK_MSG ("Cannot compute rejection flags signals");
704 
705  /* Save the p2vmreduced file */
706  if (gravi_param_get_bool (parlist,"gravity.dfs.p2vmred-file")) {
707 
708  gravi_data_save_new (p2vmred_data, frameset, NULL, parlist,
709  current_frameset, frame, "gravity_vis", NULL, redCatg);
710 
711  CPLCHECK_CLEAN ("Cannot save the P2VMREDUCED product");
712  }
713 
714  /* Visibility and flux are averaged and the followings
715  * are saved in Visibility data in tables VIS, VIS2 and T3 */
716  tmpvis_data = gravi_compute_vis (p2vmred_data, parlist);
717  CPLCHECK_CLEAN ("Cannot average the P2VMRED frames into VIS");
718 
719  /* Save the astro file, which is a lighter version of the p2vmreduced */
720  if (gravi_param_get_bool (parlist,"gravity.dfs.astro-file")) {
721 
722  gravi_data_clean_for_astro (p2vmred_data);
723  gravi_data_save_new (p2vmred_data, frameset, NULL, parlist,
724  current_frameset, frame, "gravity_vis",
725  NULL, GRAVI_ASTROREDUCED);
726 
727  CPLCHECK_CLEAN ("Cannot save the ASTROREDUCED product");
728  }
729 
730 
731  /* Merge with already existing */
732  if (ivis == 0) {
733  vis_data = tmpvis_data; tmpvis_data = NULL;
734  }
735  else {
736  cpl_msg_info (cpl_func,"Merge with previous OI_VIS");
737  gravi_data_append (vis_data, tmpvis_data, 1);
738  FREE (gravi_data_delete, tmpvis_data);
739  }
740 
741  cpl_msg_info (cpl_func,"Free the p2vmreduced");
742  FREE (cpl_frameset_delete, current_frameset);
743  FREE (gravi_data_delete, p2vmred_data);
744 
745  }
746  /* End loop on the input files to reduce */
747 
748  /* Compute the QC parameters of the TF
749  * FIXME: compute QC TF only for CALIB star */
750  gravi_compute_tf_qc (vis_data, diamcat_data);
751 
752  /* Eventually flatten the OI_FLUX */
753  if (gravi_param_get_bool (parlist, "gravity.vis.flat-flux")) {
754 
755  cpl_msg_info (cpl_func, "Flatten the FLUX with the internal P2VM spectrum");
756  gravi_flat_flux (vis_data, p2vm_map);
757  CPLCHECK_CLEAN ("Cannot flat the OI_FLUX");
758 
759  } else {
760  cpl_msg_info (cpl_func, "Don't flatten the FLUX with the internal P2VM spectrum");
761  }
762 
763  /* Perform the normalisation of the SC vis2 and visamp
764  * to match those of the FT */
765  if (!strcmp (gravi_param_get_string (parlist, "gravity.vis.vis-correction-sc"), "FORCE")) {
766 
767  cpl_msg_info (cpl_func, "Align the SC visibilities on the FT");
768  gravi_normalize_sc_to_ft (vis_data);
769 
770  } else {
771  cpl_msg_info (cpl_func, "Don't align the SC visibilities on the FT");
772  }
773 
774  /* Co-add the observations if requested */
775  if (gravi_param_get_bool (parlist, "gravity.postprocess.average-vis")) {
776  gravi_average_vis (vis_data);
777 
778  } else {
779  cpl_msg_info (cpl_func, "Don't average the different observation (if any)");
780  }
781 
782  /* Recompute the TIME column from the MJD column
783  * in all OIFITS tables to follow standard */
784  gravi_vis_mjd_to_time (vis_data);
785 
786  /* Save the output data file based on the first frame of the frameset */
787  cpl_frameset_join (used_frameset, recipe_frameset);
788  frame = cpl_frameset_get_position (recipe_frameset, 0);
789 
790  gravi_data_save_new (vis_data, frameset, NULL, parlist,
791  used_frameset, frame, "gravity_vis", NULL, proCatg);
792 
793  CPLCHECK_CLEAN ("Cannot save the VIS product");
794 
795  /* Terminate the function */
796  goto cleanup;
797 
798 cleanup:
799  /* Deallocation of all variables */
800  cpl_msg_info(cpl_func,"Memory cleanup");
801 
802  FREELOOP (gravi_data_delete,sky_maps,nb_sky);
803  FREE (gravi_data_delete,dark_map);
804  FREE (gravi_data_delete,data);
805  FREE (gravi_data_delete,preproc_data);
806  FREE (gravi_data_delete,profile_map);
807  FREE (gravi_data_delete,disp_map);
808  FREE (gravi_data_delete,wave_map);
809  FREE (gravi_data_delete,badpix_map);
810  FREE (gravi_data_delete,p2vm_map);
811  FREE (gravi_data_delete,p2vmred_data);
812  FREE (gravi_data_delete,vis_data);
813  FREE (gravi_data_delete,tmpvis_data);
814  FREE (gravi_data_delete,diamcat_data);
815  FREE (gravi_data_delete,eop_map);
816  FREE (cpl_frameset_delete,darkcalib_frameset);
817  FREE (cpl_frameset_delete,wavecalib_frameset);
818  FREE (cpl_frameset_delete,flatcalib_frameset);
819  FREE (cpl_frameset_delete,badcalib_frameset);
820  FREE (cpl_frameset_delete,p2vmcalib_frameset);
821  FREE (cpl_frameset_delete,dark_frameset);
822  FREE (cpl_frameset_delete,diamcat_frameset);
823  FREE (cpl_frameset_delete,sky_frameset);
824  FREE (cpl_frameset_delete,dispcalib_frameset);
825  FREE (cpl_frameset_delete,eop_frameset);
826  FREE (cpl_frameset_delete,recipe_frameset);
827  FREE (cpl_frameset_delete,current_frameset);
828  FREE (cpl_frameset_delete,used_frameset);
829  FREE (cpl_free,proCatg);
830  FREE (cpl_free,redCatg);
831  FREE (cpl_free,skyCatg);
832  FREE (cpl_free,mode);
833 
834  gravi_msg_function_exit(1);
835  return (int)cpl_error_get_code();
836 }