GRAVI Pipeline Reference Manual  0.9.6
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  /* Snr */
202  gravi_parameter_add_compute_snr (recipe->parameters, isCalib);
203 
204  /* Rejection */
205  gravi_parameter_add_rejection (recipe->parameters, isCalib);
206 
207  /* Parameters for gravi_compute_vis */
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, * 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  goto cleanup;
393  }
394 
395  /* Insert calibration frame into the used frameset */
396  used_frameset = cpl_frameset_new();
397 
398  /*
399  * Identify the DARK in the input frameset
400  */
401 
402  if (!cpl_frameset_is_empty (dark_frameset)) {
403 
404  frame = cpl_frameset_get_position (dark_frameset, 0);
405  data = gravi_data_load_rawframe (frame, used_frameset);
406  gravi_data_detector_cleanup (data, parlist);
407 
408  /* Compute dark */
409  dark_map = gravi_compute_dark (data);
410  FREE (gravi_data_delete, data);
411 
412  CPLCHECK_CLEAN ("Could not compute the DARK map");
413 
414  /* Save the dark map */
415  gravi_data_save_new (dark_map, frameset, NULL, parlist,
416  NULL, frame, "gravity_vis",
417  NULL, GRAVI_DARK_MAP);
418 
419  CPLCHECK_CLEAN ("Could not save the DARK map");
420  }
421  else if (!cpl_frameset_is_empty (darkcalib_frameset)) {
422 
423  frame = cpl_frameset_get_position (darkcalib_frameset, 0);
424  dark_map = gravi_data_load_frame (frame, used_frameset);
425 
426  CPLCHECK_CLEAN ("Could not load the DARK map");
427  }
428  else
429  cpl_msg_info (cpl_func, "There is no DARK in the frame set");
430 
431  /* Identify the BAD in the input frameset */
432  frame = cpl_frameset_get_position (badcalib_frameset, 0);
433  badpix_map = gravi_data_load_frame (frame, used_frameset);
434 
435  /* Identify the FLAT in the input frameset */
436  frame = cpl_frameset_get_position (flatcalib_frameset, 0);
437  profile_map = gravi_data_load_frame (frame, used_frameset);
438 
439  /* Identify the WAVE in the input frameset */
440  frame = cpl_frameset_get_position (wavecalib_frameset, 0);
441  wave_map = gravi_data_load_frame (frame, used_frameset);
442 
443  /* Identify the P2VM in the input frameset */
444  frame = cpl_frameset_get_position (p2vmcalib_frameset, 0);
445  p2vm_map = gravi_data_load_frame (frame, used_frameset);
446 
447  /* Load the DISP_MODEL in the input frameset */
448  if (!cpl_frameset_is_empty (dispcalib_frameset)) {
449  frame = cpl_frameset_get_position (dispcalib_frameset, 0);
450  disp_map = gravi_data_load_frame (frame, used_frameset);
451  }
452  else
453  cpl_msg_info (cpl_func, "There is no DISP_MODEL in the frameset");
454 
455  /* Load the EOP_PARAM */
456  if ( !cpl_frameset_is_empty (eop_frameset) ) {
457  frame = cpl_frameset_get_position (eop_frameset, 0);
458  eop_map = gravi_data_load_frame (frame, used_frameset);
459  }
460  else
461  cpl_msg_info (cpl_func, "There is no EOP_PARAM in the frameset");
462 
463  /* Load the DIAMETER_CAT */
464  if ( !cpl_frameset_is_empty (diamcat_frameset) ) {
465  frame = cpl_frameset_get_position (diamcat_frameset, 0);
466  diamcat_data = gravi_data_load_frame (frame, used_frameset);
467  }
468  else
469  cpl_msg_info (cpl_func, "There is no DIAMETER_CAT in the frameset");
470 
471 
472  CPLCHECK_CLEAN ("Error while loading the calibration maps");
473 
474  /*
475  * Select the PRO CATG (based on first frame)
476  */
477 
478  frame_tag = cpl_frame_get_tag (cpl_frameset_get_position (recipe_frameset, 0));
479 
480  if ((strcmp(frame_tag, GRAVI_DUAL_CALIB_RAW) == 0)) {
481  redCatg = cpl_sprintf (GRAVI_P2VMRED_DUAL_CALIB);
482  proCatg = cpl_sprintf (GRAVI_VIS_DUAL_CALIB);
483  skyCatg = cpl_sprintf (GRAVI_DUAL_SKY_MAP);
484  mode = cpl_sprintf ("gravi_dual");
485  }
486  else if ((strcmp(frame_tag, GRAVI_DUAL_SCIENCE_RAW) == 0)) {
487  redCatg = cpl_sprintf (GRAVI_P2VMRED_DUAL_SCIENCE);
488  proCatg = cpl_sprintf (GRAVI_VIS_DUAL_SCIENCE);
489  skyCatg = cpl_sprintf (GRAVI_DUAL_SKY_MAP);
490  mode = cpl_sprintf ("gravi_dual");
491  }
492  else if ((strcmp(frame_tag, GRAVI_SINGLE_CALIB_RAW) == 0)) {
493  redCatg = cpl_sprintf (GRAVI_P2VMRED_SINGLE_CALIB);
494  proCatg = cpl_sprintf (GRAVI_VIS_SINGLE_CALIB);
495  skyCatg = cpl_sprintf (GRAVI_SINGLE_SKY_MAP);
496  mode = cpl_sprintf ("gravi_single");
497  }
498  else if ((strcmp(frame_tag, GRAVI_SINGLE_SCIENCE_RAW) == 0)) {
499  redCatg = cpl_sprintf (GRAVI_P2VMRED_SINGLE_SCIENCE);
500  proCatg = cpl_sprintf (GRAVI_VIS_SINGLE_SCIENCE);
501  skyCatg = cpl_sprintf (GRAVI_SINGLE_SKY_MAP);
502  mode = cpl_sprintf ("gravi_single");
503  }
504  else {
505  cpl_error_set_message (cpl_func, CPL_ERROR_ILLEGAL_INPUT,
506  "Cannot recognize the input DO.CATG");
507  goto cleanup;
508  }
509 
510  cpl_msg_info (cpl_func,"Mode of the first frame is: %s (will be used for all frames)", mode);
511 
512  /*
513  * Mode for the SKY
514  */
515  int averageSky = gravi_param_get_bool (parlist,"gravity.preproc.average-sky");
516 
517  /*
518  * Loop on input SKY frames to be reduced
519  */
520  nb_sky = cpl_frameset_get_size (sky_frameset);
521  sky_maps = cpl_calloc (CPL_MAX(nb_sky,1), sizeof(gravi_data*));
522 
523  for (int isky = 0; isky < nb_sky; isky++){
524 
525  /* Load the raw SKY */
526  cpl_msg_info (cpl_func, " ***** SKY %d over %d ***** ", isky+1, nb_sky);
527  frame = cpl_frameset_get_position (sky_frameset, isky);
528  data = gravi_data_load_rawframe (frame, used_frameset);
529  gravi_data_detector_cleanup (data, parlist);
530 
531  /* Compute the SKY map */
532  sky_maps[isky] = gravi_compute_dark (data);
533  FREE (gravi_data_delete, data);
534 
535  CPLCHECK_CLEAN ("Error while computing the sky_map");
536 
537  /* Save the SKY map */
538  if (averageSky == 0) {
539  gravi_data_save_new (sky_maps[isky], frameset, NULL, parlist,
540  NULL, frame, "gravity_vis",
541  NULL, skyCatg);
542  CPLCHECK_CLEAN ("Could not save the sky");
543  }
544  }
545 
546  /*
547  * Average the sky if requested
548  */
549 
550  if (averageSky == 1) {
551  cpl_msg_info (cpl_func, "Do a MASTER SKY from the %d skys", nb_sky);
552 
553  gravi_data * msky_map;
554  msky_map = gravi_average_dark (sky_maps, nb_sky);
555  CPLCHECK_CLEAN ("Cannot do master sky");
556 
557  gravi_data_save_new (msky_map, frameset, NULL, parlist, sky_frameset,
558  cpl_frameset_get_position (sky_frameset, 0),
559  "gravity_vis", NULL, skyCatg);
560  CPLCHECK_CLEAN ("Cannot save master sky");
561 
562  /* Add all sky to used_frameset, and move pointers */
563  cpl_frameset_join (used_frameset, sky_frameset);
564  for (int isky = 0; isky < nb_sky; isky++)
565  FREE (gravi_data_delete, sky_maps[isky]);
566  sky_maps[0] = msky_map;
567  nb_sky = 1;
568  }
569 
570  /*
571  * Loop on input RAW frames to be reduced
572  */
573 
574  nb_frame = cpl_frameset_get_size (recipe_frameset);
575 
576  for (int ivis = 0; ivis < nb_frame; ivis++){
577  current_frameset = cpl_frameset_duplicate (used_frameset);
578 
579  cpl_msg_info (cpl_func, " ***** OBJECT %d over %d ***** ", ivis+1, nb_frame);
580 
581  /*
582  * Identify the SKY for this OBJECT
583  */
584  isky = nb_sky>0 ? ivis % nb_sky : 0;
585 
586  if (nb_sky == 0) {
587  /* No SKY */
588  cpl_msg_info (cpl_func, "There is no SKY in the frameset");
589  }
590  else if (averageSky) {
591  /* Use master SKY already computed, already in frameset */
592  cpl_msg_info (cpl_func, "Use MASTER SKY (already reduced)");
593  }
594  else {
595  /* SKY already computed, add in the used_frameset */
596  cpl_msg_info (cpl_func, "Use SKY %i over %i (already reduced)", isky+1, nb_sky);
597  frame = cpl_frameset_get_position (sky_frameset, isky);
598 
599  /* Add this frame to the current_frameset as well */
600  cpl_frameset_insert (current_frameset, cpl_frame_duplicate (frame));
601  }
602 
603  /*
604  * Reduce the OBJECT
605  */
606 
607  frame = cpl_frameset_get_position (recipe_frameset, ivis);
608  data = gravi_data_load_rawframe (frame, current_frameset);
609  gravi_data_detector_cleanup (data, parlist);
610 
611  /* Option save the preproc file */
612  if (gravi_param_get_bool (parlist,"gravity.dfs.bias-subtracted-file")) {
613 
614  gravi_data_save_new (data, frameset, NULL, parlist,
615  current_frameset, frame, "gravity_vis",
616  NULL, "BIAS_SUBTRACTED");
617 
618  CPLCHECK_CLEAN ("Cannot save the BIAS_SUBTRACTED product");
619  }
620 
621 
622  /* Check the shutters */
623  if ( !gravi_data_check_shutter_open (data) ) {
624  cpl_msg_warning (cpl_func, "Shutter problem in the OBJECT");
625  }
626 
627  /* Extract spectrum */
628  preproc_data = gravi_extract_spectrum (data, profile_map, dark_map, badpix_map, sky_maps[isky]);
629  CPLCHECK_CLEAN ("Cannot extract spectrum");
630 
631  /* Option save the spectrum file */
632  if (gravi_param_get_bool (parlist,"gravity.dfs.spectrum-file")) {
633  gravi_data_save_new (preproc_data, frameset, NULL, parlist,
634  current_frameset, frame, "gravity_vis",
635  NULL, GRAVI_SPECTRUM);
636  CPLCHECK_CLEAN ("Cannot save the SPECTRUM product");
637  }
638 
639  /* Rescale to common wavelength */
640  gravi_align_spectrum (preproc_data, wave_map, p2vm_map);
641  CPLCHECK_CLEAN ("Cannot re-interpolate spectrum");
642 
643  /* Option save the preproc file */
644  if (gravi_param_get_bool (parlist,"gravity.dfs.preproc-file")) {
645  gravi_data_save_new (preproc_data, frameset, NULL, parlist,
646  current_frameset, frame, "gravity_vis",
647  NULL, GRAVI_PREPROC);
648  CPLCHECK_CLEAN ("Cannot save the PREPROC product");
649  }
650 
651  /* Move extensions from raw_data and delete it */
652  gravi_data_move_ext (preproc_data, data, GRAVI_ARRAY_GEOMETRY_EXT);
653  gravi_data_move_ext (preproc_data, data, GRAVI_OPTICAL_TRAIN_EXT);
654  gravi_data_move_ext (preproc_data, data, GRAVI_OPDC_EXT);
655  gravi_data_move_ext (preproc_data, data, GRAVI_FDDL_EXT);
656  gravi_data_move_ext (preproc_data, data, GRAVI_METROLOGY_EXT);
657  FREE (gravi_data_delete, data);
658  CPLCHECK_CLEAN ("Cannot move ext");
659 
660  /* Compute the flux and visibilities for each telescope and
661  * per acquisition with the P2VM applied to preproc_data */
662  p2vmred_data = gravi_compute_p2vmred (preproc_data, p2vm_map, mode, parlist);
663  CPLCHECK_CLEAN ("Cannot apply p2vm to the preproc data");
664 
665  /* Move extensions and delete preproc */
666  gravi_data_move_ext (p2vmred_data, preproc_data, GRAVI_METROLOGY_EXT);
667  gravi_data_move_ext (p2vmred_data, preproc_data, GRAVI_FDDL_EXT);
668  gravi_data_move_ext (p2vmred_data, preproc_data, GRAVI_OPDC_EXT);
669  FREE (gravi_data_delete, preproc_data);
670  CPLCHECK_CLEAN ("Cannot delete preproc");
671 
672  /* Reduce the OPDC table */
673  gravi_compute_opdc_state (p2vmred_data);
674  CPLCHECK_CLEAN ("Cannot reduce OPDC");
675 
676  /* Reduce the metrology into OI_VIS_MET */
677  gravi_metrology_reduce (p2vmred_data);
678  CPLCHECK_CLEAN ("Cannot reduce metrology");
679 
680  /* Compute the uv and pointing directions with ERFA */
681  gravi_compute_uv (p2vmred_data, eop_map);
682  CPLCHECK_CLEAN ("Cannot compute uv");
683 
684  gravi_compute_pointing (p2vmred_data, eop_map);
685  CPLCHECK_CLEAN ("Cannot compute pointing");
686 
687  /* Compute the QC0 about tau0 from piezo signals */
688  gravi_compute_tau0 (p2vmred_data);
689 
690  /* Compute the SNR_BOOT and GDELAY_BOOT */
691  gravi_compute_snr (p2vmred_data, parlist);
692  CPLCHECK_MSG ("Cannot compute SNR");
693 
694  /* Compute the signals for averaging */
695  gravi_compute_signals (p2vmred_data, disp_map, parlist);
696  CPLCHECK_MSG ("Cannot compute signals");
697 
698  /* Compute rejection flags for averaging */
699  gravi_compute_rejection (p2vmred_data, parlist);
700  CPLCHECK_MSG ("Cannot compute rejection flags signals");
701 
702  /* Visibility and flux are averaged and the followings
703  * are saved in Visibility data in tables VIS, VIS2 and T3 */
704  tmpvis_data = gravi_compute_vis (p2vmred_data, parlist);
705  CPLCHECK_CLEAN ("Cannot average the P2VMRED frames into VIS");
706 
707  /* Merge with already existing */
708  if (ivis == 0) {
709  vis_data = tmpvis_data; tmpvis_data = NULL;
710  }
711  else {
712  cpl_msg_info (cpl_func,"Merge with previous OI_VIS");
713  gravi_data_append (vis_data, tmpvis_data, 1);
714  FREE (gravi_data_delete, tmpvis_data);
715  }
716 
717  /* Save the p2vmreduced file */
718  if (gravi_param_get_bool (parlist,"gravity.dfs.p2vmred-file")) {
719 
720  gravi_data_save_new (p2vmred_data, frameset, NULL, parlist,
721  current_frameset, frame, "gravity_vis", NULL, redCatg);
722 
723  CPLCHECK_CLEAN ("Cannot save the P2VMREDUCED product");
724  }
725 
726  /* Save the astro file, which is a lighter version of the p2vmreduced */
727  if (gravi_param_get_bool (parlist,"gravity.dfs.astro-file")) {
728 
729  gravi_data_clean_for_astro (p2vmred_data);
730  gravi_data_save_new (p2vmred_data, frameset, NULL, parlist,
731  current_frameset, frame, "gravity_vis",
732  NULL, GRAVI_ASTROREDUCED);
733 
734  CPLCHECK_CLEAN ("Cannot save the ASTROREDUCED product");
735  }
736 
737  cpl_msg_info (cpl_func,"Free the p2vmreduced");
738  FREE (cpl_frameset_delete, current_frameset);
739  FREE (gravi_data_delete, p2vmred_data);
740 
741  }
742  /* End loop on the input files to reduce */
743 
744  /* Compute the QC parameters of the TF
745  * FIXME: compute QC TF only for CALIB star */
746  gravi_compute_tf_qc (vis_data, diamcat_data);
747 
748  /* Compute the pointing directions with ERFA in the averaged data */
749  gravi_compute_pointing (vis_data, eop_map);
750 
751  /* Eventually flatten the OI_FLUX */
752  if (gravi_param_get_bool (parlist, "gravity.vis.flat-flux")) {
753 
754  cpl_msg_info (cpl_func, "Flatten the FLUX with the internal P2VM spectrum");
755  gravi_flat_flux (vis_data, p2vm_map);
756  CPLCHECK_CLEAN ("Cannot flat the OI_FLUX");
757 
758  } else {
759  cpl_msg_info (cpl_func, "Don't flatten the FLUX with the internal P2VM spectrum");
760  }
761 
762  /* Perform the normalisation of the SC vis2 and visamp
763  * to match those of the FT */
764  if (!strcmp (gravi_param_get_string (parlist, "gravity.vis.vis-correction"), "FORCE")) {
765 
766  cpl_msg_info (cpl_func, "Align the SC visibilities on the FT");
767  gravi_normalize_sc_to_ft (vis_data);
768 
769  } else {
770  cpl_msg_info (cpl_func, "Don't align the SC visibilities on the FT");
771  }
772 
773  /* Co-add the observations if requested */
774  if (gravi_param_get_bool (parlist, "gravity.postprocess.average-vis")) {
775 
776  gravi_msg_fixme ("Average the different observation (if any) = EXPERIMENTAL");
777  gravi_average_vis (vis_data);
778 
779  } else {
780  cpl_msg_info (cpl_func, "Don't average the different observation (if any)");
781  }
782 
783  /* Recompute the TIME column from the MJD column
784  * in all OIFITS tables to follow standard */
785  gravi_vis_mjd_to_time (vis_data);
786 
787  /* Save the output data file based on the first frame of the frameset */
788  cpl_frameset_join (used_frameset, recipe_frameset);
789  frame = cpl_frameset_get_position (recipe_frameset, 0);
790 
791  gravi_data_save_new (vis_data, frameset, NULL, parlist,
792  used_frameset, frame, "gravity_vis", NULL, proCatg);
793 
794  CPLCHECK_CLEAN ("Cannot save the VIS product");
795 
796  /* Terminate the function */
797  goto cleanup;
798 
799 cleanup:
800  /* Deallocation of all variables */
801  cpl_msg_info(cpl_func,"Memory cleanup");
802 
803  FREELOOP (gravi_data_delete,sky_maps,nb_sky);
804  FREE (gravi_data_delete,dark_map);
805  FREE (gravi_data_delete,data);
806  FREE (gravi_data_delete,preproc_data);
807  FREE (gravi_data_delete,profile_map);
808  FREE (gravi_data_delete,disp_map);
809  FREE (gravi_data_delete,wave_map);
810  FREE (gravi_data_delete,badpix_map);
811  FREE (gravi_data_delete,p2vm_map);
812  FREE (gravi_data_delete,p2vmred_data);
813  FREE (gravi_data_delete,vis_data);
814  FREE (gravi_data_delete,tmpvis_data);
815  FREE (gravi_data_delete,diamcat_data);
816  FREE (gravi_data_delete,eop_map);
817  FREE (cpl_frameset_delete,darkcalib_frameset);
818  FREE (cpl_frameset_delete,wavecalib_frameset);
819  FREE (cpl_frameset_delete,flatcalib_frameset);
820  FREE (cpl_frameset_delete,badcalib_frameset);
821  FREE (cpl_frameset_delete,p2vmcalib_frameset);
822  FREE (cpl_frameset_delete,dark_frameset);
823  FREE (cpl_frameset_delete,diamcat_frameset);
824  FREE (cpl_frameset_delete,sky_frameset);
825  FREE (cpl_frameset_delete,dispcalib_frameset);
826  FREE (cpl_frameset_delete,eop_frameset);
827  FREE (cpl_frameset_delete,recipe_frameset);
828  FREE (cpl_frameset_delete,current_frameset);
829  FREE (cpl_frameset_delete,used_frameset);
830  FREE (cpl_free,proCatg);
831  FREE (cpl_free,redCatg);
832  FREE (cpl_free,skyCatg);
833  FREE (cpl_free,mode);
834 
835  gravi_msg_function_exit(1);
836  return (int)cpl_error_get_code();
837 }