GRAVI Pipeline Reference Manual  0.9.10
gravity_p2vm.c
1 /* $Id: gravity_p2vm.c,v 1.29 2009/02/10 09:16:12 llundin Exp $
2  *
3  * This file is part of the GRAVI Pipeline
4  * Copyright (C) 2002,2003 European Southern Observatory
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 /*
22  * $Author: llundin $
23  * $Date: 2009/02/10 09:16:12 $
24  * $Revision: 1.29 $
25  * $Name: $
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_metrology.h"
48 #include "gravi_calib.h"
49 #include "gravi_preproc.h"
50 #include "gravi_wave.h"
51 #include "gravi_p2vm.h"
52 
53 #include "gravi_p2vmred.h"
54 
55 
56 /*-----------------------------------------------------------------------------
57  Private function prototypes
58  -----------------------------------------------------------------------------*/
59 
60 static int gravity_p2vm_create(cpl_plugin *);
61 static int gravity_p2vm_exec(cpl_plugin *);
62 static int gravity_p2vm_destroy(cpl_plugin *);
63 static int gravity_p2vm(cpl_frameset *, const cpl_parameterlist *);
64 
65 /*-----------------------------------------------------------------------------
66  Static variables
67  -----------------------------------------------------------------------------*/
68 
69 static char gravity_p2vm_short[] = "Calibrate the instrument bad pixels, wavelength table, interferometric contrast and phase.";
70 static char gravity_p2vm_description[] =
71 "This recipe reduces the internal calibrations. As a special sequence of shutter opening is required, it is advised to always build the SOF with a complete sequence of files obtained within a single execution of the p2vm calibration template. However it is still possible to input a SOF with DARK_RAW only, or DARK_RAW and FLAT_RAW only. It is also possible to input a SOF with some already processed calibration (e.g WAVE).\n"
72  GRAVI_RECIPE_INPUT"\n"
73  GRAVI_DARK_RAW" : raw dark, all shutters closed (DPR.TYPE=DARK)\n"
74  GRAVI_FLAT_RAW" x4 : raw flats, one sutter open (DPR.TYPE=FLAT)\n"
75  GRAVI_P2VM_RAW" x6 : raw p2vms, two sutters open (DPR.TYPE=P2VM)\n"
76  GRAVI_WAVE_RAW" : raw wavelength calibration for FT (DPR.TYPE=WAVE)\n"
77  GRAVI_WAVESC_RAW" : raw wavelength calibration for SC (DPR.TYPE=WAVESC)\n"
78  GRAVI_RECIPE_OUTPUT"\n"
79  GRAVI_DARK_MAP" : dark calibration\n"
80  GRAVI_FLAT_MAP" : flat calibration\n"
81  GRAVI_BAD_MAP" : badpixel calibration\n"
82  GRAVI_WAVE_MAP" : wave calibration\n"
83  GRAVI_P2VM_MAP" : p2vm calibration\n"
84  "";
85 
86 /*-----------------------------------------------------------------------------
87  Function code
88  -----------------------------------------------------------------------------*/
89 
90 /*----------------------------------------------------------------------------*/
100 /*----------------------------------------------------------------------------*/
101 int cpl_plugin_get_info(cpl_pluginlist * list)
102 {
103  cpl_recipe * recipe = cpl_calloc(1, sizeof *recipe );
104  cpl_plugin * plugin = &recipe->interface;
105 
106  if (cpl_plugin_init(plugin,
107  CPL_PLUGIN_API,
108  GRAVI_BINARY_VERSION,
109  CPL_PLUGIN_TYPE_RECIPE,
110  "gravity_p2vm",
111  gravity_p2vm_short,
112  gravity_p2vm_description,
113  "Nabih Azouaoui, Vincent Lapeyrere, JB. Le Bouquin",
114  PACKAGE_BUGREPORT,
115  gravi_get_license(),
116  gravity_p2vm_create,
117  gravity_p2vm_exec,
118  gravity_p2vm_destroy)) {
119  cpl_msg_error(cpl_func, "Plugin initialization failed");
120  (void)cpl_error_set_where(cpl_func);
121  return 1;
122  }
123 
124  if (cpl_pluginlist_append(list, plugin)) {
125  cpl_msg_error(cpl_func, "Error adding plugin to list");
126  (void)cpl_error_set_where(cpl_func);
127  return 1;
128  }
129 
130  return 0;
131 }
132 
133 /*----------------------------------------------------------------------------*/
141 /*----------------------------------------------------------------------------*/
142 static int gravity_p2vm_create(cpl_plugin * plugin)
143 {
144  cpl_recipe * recipe;
145  cpl_parameter * p;
146 
147  /* Do not create the recipe if an error code is already set */
148  if (cpl_error_get_code() != CPL_ERROR_NONE) {
149  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
150  cpl_func, __LINE__, cpl_error_get_where());
151  return (int)cpl_error_get_code();
152  }
153 
154  if (plugin == NULL) {
155  cpl_msg_error(cpl_func, "Null plugin");
156  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
157  }
158 
159  /* Verify plugin type */
160  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
161  cpl_msg_error(cpl_func, "Plugin is not a recipe");
162  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
163  }
164 
165  /* Get the recipe */
166  recipe = (cpl_recipe *)plugin;
167 
168  /* Create the parameters list in the cpl_recipe object */
169  recipe->parameters = cpl_parameterlist_new();
170  if (recipe->parameters == NULL) {
171  cpl_msg_error(cpl_func, "Parameter list allocation failed");
172  cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);
173  }
174 
175  /* Fill the parameters list */
176 
177  /* Use static names (output_procatg.fits) */
178  gravi_parameter_add_static_name (recipe->parameters);
179 
180  /* Debug file */
181  gravi_parameter_add_debug_file (recipe->parameters);
182  gravi_parameter_add_preproc_file (recipe->parameters);
183 
184  /* Badpix and profile */
185  gravi_parameter_add_badpix (recipe->parameters);
186  gravi_parameter_add_profile (recipe->parameters);
187 
188  /* Wave option */
189  gravi_parameter_add_wave (recipe->parameters);
190 
191  /* Phase definition in P2VM */
192  p = cpl_parameter_new_enum ("gravity.calib.phase-calibration", CPL_TYPE_STRING,
193  "The relative phase of the P2VM are defined by \n "
194  "NONE defines phiA(lbd) at zero for all baselines;\n "
195  "CLOSURE defines phiA(lbd) at zero for baselines (01,02,03);\n "
196  "DISP defines phiA(lbd) to have zero mean and minimum GD for baselines (01,02,03);\n "
197  "FULL defines phiA(lbd) to have zero-GD for baselines (01,02,03)",
198  "gravi.p2vm", "CLOSURE", 4, "NONE", "CLOSURE", "DISP", "FULL");
199  cpl_parameter_set_alias (p, CPL_PARAMETER_MODE_CLI, "phase-calibration");
200  cpl_parameter_disable (p, CPL_PARAMETER_MODE_ENV);
201  cpl_parameterlist_append (recipe->parameters, p);
202 
203  return 0;
204 }
205 
206 /*----------------------------------------------------------------------------*/
212 /*----------------------------------------------------------------------------*/
213 static int gravity_p2vm_exec(cpl_plugin * plugin)
214 {
215 
216  cpl_recipe * recipe;
217  int recipe_status;
218  cpl_errorstate initial_errorstate = cpl_errorstate_get();
219 
220  /* Return immediately if an error code is already set */
221  if (cpl_error_get_code() != CPL_ERROR_NONE) {
222  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
223  cpl_func, __LINE__, cpl_error_get_where());
224  return (int)cpl_error_get_code();
225  }
226 
227  if (plugin == NULL) {
228  cpl_msg_error(cpl_func, "Null plugin");
229  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
230  }
231 
232  /* Verify plugin type */
233  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
234  cpl_msg_error(cpl_func, "Plugin is not a recipe");
235  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
236  }
237 
238  /* Get the recipe */
239  recipe = (cpl_recipe *)plugin;
240 
241  /* Verify parameter and frame lists */
242  if (recipe->parameters == NULL) {
243  cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
244  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
245  }
246  if (recipe->frames == NULL) {
247  cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");
248  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
249  }
250 
251  /* Invoke the recipe */
252  recipe_status = gravity_p2vm(recipe->frames, recipe->parameters);
253 
254  /* Ensure DFS-compliance of the products */
255  if (cpl_dfs_update_product_header(recipe->frames)) {
256  if (!recipe_status) recipe_status = (int)cpl_error_get_code();
257  }
258 
259  if (!cpl_errorstate_is_equal(initial_errorstate)) {
260  /* Dump the error history since recipe execution start.
261  At this point the recipe cannot recover from the error */
262  cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);
263  }
264 
265  return recipe_status;
266 }
267 
268 /*----------------------------------------------------------------------------*/
274 /*----------------------------------------------------------------------------*/
275 static int gravity_p2vm_destroy(cpl_plugin * plugin)
276 {
277  cpl_recipe * recipe;
278 
279  if (plugin == NULL) {
280  cpl_msg_error(cpl_func, "Null plugin");
281  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
282  }
283 
284  /* Verify plugin type */
285  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
286  cpl_msg_error(cpl_func, "Plugin is not a recipe");
287  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
288  }
289 
290  /* Get the recipe */
291  recipe = (cpl_recipe *)plugin;
292 
293  cpl_parameterlist_delete(recipe->parameters);
294 
295  return 0;
296 }
297 
298 /*----------------------------------------------------------------------------*/
306 /*----------------------------------------------------------------------------*/
307 static int gravity_p2vm(cpl_frameset * frameset,
308  const cpl_parameterlist * parlist)
309 {
310  cpl_frameset * p2vm_frameset=NULL, * wavecalib_frameset=NULL, * darkcalib_frameset=NULL,
311  * flatcalib_frameset=NULL, * dark_frameset=NULL, * wave_frameset=NULL, * wavesc_frameset=NULL,
312  * badcalib_frameset=NULL, * flat_frameset=NULL, * used_frameset=NULL, * current_frameset=NULL;
313 
314  cpl_frame * frame=NULL, * frame_p2vm=NULL;
315 
316  gravi_data * p2vm_map=NULL, * data=NULL, * dark_map=NULL, * wave_map=NULL,
317  * profile_map=NULL, * badpix_map=NULL, * wave_data=NULL;
318  gravi_data * spectrum_data=NULL;
319  gravi_data * preproc_data=NULL;
320  gravi_data ** raw_data=NULL;
321  gravi_data * p2vmred_data = NULL;
322 
323  int nb_frame, i, nb_frame_gain = 0;
324 
325  cpl_propertylist * met_plist=NULL;
326  int ** valid_trans = cpl_malloc (2 * sizeof (int*));
327  int ** valid_CP = cpl_malloc (2 * sizeof (int*));
328  clock_t start;
329 
330  for (i = 0 ; i < 2; i++){
331  valid_trans[i] = cpl_calloc (4, sizeof (int));
332  valid_CP[i] = cpl_calloc (6, sizeof (int));
333  }
334 
335  /* Message */
336  gravity_print_banner ();
337  cpl_msg_set_time_on();
338  cpl_msg_set_component_on();
339  gravi_msg_function_start(1);
340 
341 
342  /* Get the input frameset */
343  cpl_ensure_code(gravi_dfs_set_groups(frameset) == CPL_ERROR_NONE, cpl_error_get_code()) ;
344 
345  /* Init the used frameset */
346  used_frameset = cpl_frameset_new ();
347 
348  /* Extract DARK frameset */
349  dark_frameset = gravi_frameset_extract_dark_data (frameset);
350  darkcalib_frameset = gravi_frameset_extract_dark_map (frameset);
351 
352  /* Extract FLAT frameset */
353  flat_frameset = gravi_frameset_extract_flat_data (frameset);
354  flatcalib_frameset = gravi_frameset_extract_flat_map (frameset);
355 
356  /* Extract BAD frameset */
357  badcalib_frameset = gravi_frameset_extract_bad_map (frameset);
358 
359  /* Extract WAVE frameset */
360  wave_frameset = gravi_frameset_extract_wave_data (frameset);
361  wavesc_frameset = gravi_frameset_extract_wavesc_data (frameset);
362  wavecalib_frameset = gravi_frameset_extract_wave_map (frameset);
363 
364  /* Extract P2VM frameset */
365  p2vm_frameset = gravi_frameset_extract_p2vm_data (frameset);
366 
367 
368 
369  /*
370  * (1) Identify and extract the dark file
371  */
372 
373  if (!cpl_frameset_is_empty (dark_frameset)) {
374  cpl_msg_info (cpl_func, " ***** Compute DARK map ***** ");
375 
376  /* Load this DARK_RAW */
377  frame = cpl_frameset_get_position (dark_frameset, 0);
378  data = gravi_data_load_rawframe (frame, used_frameset);
379  gravi_data_detector_cleanup (data, parlist);
380 
381  /* Compute the dark */
382  dark_map = gravi_compute_dark (data);
383  FREE (gravi_data_delete, data);
384 
385  CPLCHECK_CLEAN ("Cannot compute the DARK map");
386 
387  /* Save the dark map */
388  gravi_data_save_new (dark_map, frameset, NULL, parlist,
389  NULL, frame, "gravity_p2vm",
390  NULL, GRAVI_DARK_MAP);
391 
392  CPLCHECK_CLEAN ("Could not save the DARK map");
393  }
394  else if (!cpl_frameset_is_empty (darkcalib_frameset)) {
395  cpl_msg_info (cpl_func, " ***** Get DARK map ***** ");
396 
397  /* Load this DARK */
398  frame = cpl_frameset_get_position (darkcalib_frameset, 0);
399  dark_map = gravi_data_load_frame (frame, used_frameset);
400 
401  CPLCHECK_CLEAN ("Could not load the DARK map");
402 
403  /* This new DARK may be used latter for BADPIX */
404  cpl_frameset_insert (dark_frameset, cpl_frame_duplicate (frame));
405  }
406 
407 
408  /*
409  * (2) Identify and extract the BADPIX file
410  */
411 
412  if (!cpl_frameset_is_empty (badcalib_frameset)) {
413  cpl_msg_info (cpl_func, " ***** Get BAD pixel map ***** ");
414 
415  /* The BADPIX is already in the frameset */
416  frame = cpl_frameset_get_position (badcalib_frameset, 0);
417  badpix_map = gravi_data_load_frame (frame, used_frameset);
418  }
419  else if (!cpl_frameset_is_empty (dark_frameset) &&
420  !cpl_frameset_is_empty (flat_frameset)) {
421  cpl_msg_info (cpl_func, " ***** Compute BAD pixel map from DARK and FLAT_RAW ***** ");
422 
423  /* Identify the flat files */
424  nb_frame_gain = cpl_frameset_get_size (flat_frameset);
425  raw_data = cpl_calloc (nb_frame_gain, sizeof(gravi_data *));
426 
427  /* Build the list of FLAT files and output file name */
428  for (int i = 0; i < nb_frame_gain; i++) {
429  frame = cpl_frameset_get_position (flat_frameset, i);
430  raw_data[i] = gravi_data_load_rawframe (frame, NULL);
431  gravi_data_detector_cleanup (raw_data[i], parlist);
432  }
433 
434  /* Compute it from the DARK and the FLAT_RAW */
435  badpix_map = gravi_compute_badpix (dark_map, raw_data,
436  nb_frame_gain, parlist);
437 
438  CPLCHECK_CLEAN("Cannot compute the BAD pixel from DARK and FLAT");
439 
440  /* Save the BADPIX */
441  frame = cpl_frameset_get_position (dark_frameset, 0);
442  gravi_data_save_new (badpix_map, frameset, NULL, parlist,
443  NULL, frame, "gravity_p2vm",
444  NULL, GRAVI_BAD_MAP);
445 
446  CPLCHECK_CLEAN ("Could not save the BAD pixel map");
447 
448  FREELOOP (gravi_data_delete, raw_data, nb_frame_gain);
449  }
450 
451  /*
452  * (3) Check that the FLAT map in the input frameset
453  */
454 
455  if (!cpl_frameset_is_empty(flatcalib_frameset)) {
456  cpl_msg_info (cpl_func, " ***** Get FLAT map ***** ");
457 
458  /* The FLAT is already in the frameset */
459  frame = cpl_frameset_get_position (flatcalib_frameset, 0);
460  profile_map = gravi_data_load_frame (frame, used_frameset);
461  }
462  else if (!cpl_frameset_is_empty (flat_frameset)) {
463  cpl_msg_info (cpl_func, " ***** Compute FLAT map ***** ");
464 
465 
466  /* Check calibs */
467  if (!badpix_map || !dark_map) {
468  ERROR_CLEAN (CPL_ERROR_ILLEGAL_INPUT, "Missing DARK or BAD in frameset");
469  }
470 
471  /* Identify the flat files */
472  nb_frame_gain = cpl_frameset_get_size (flat_frameset);
473  raw_data = cpl_malloc (nb_frame_gain * sizeof(gravi_data *));
474 
475  /* Build the list of FLAT files and output file name */
476  for (i = 0; i < nb_frame_gain; i++) {
477  frame = cpl_frameset_get_position (flat_frameset, i);
478  raw_data[i] = gravi_data_load_rawframe (frame, used_frameset);
479  gravi_data_detector_cleanup (raw_data[i], parlist);
480  }
481 
482 
483  /* Compute the profile from the list of FLAT */
484  profile_map = gravi_compute_profile (raw_data, dark_map, badpix_map, nb_frame_gain, parlist);
485  CPLCHECK_CLEAN ("Cannot compute the FLAT profile");
486 
487  /* Compute the gain QC */
488  cpl_propertylist * gain_header;
489  gain_header = gravi_compute_gain (raw_data, nb_frame_gain, dark_map);
490  CPLCHECK_CLEAN ("Cannot compute the GAIN");
491 
492  /* Put the gain QC in profile_map */
493  cpl_propertylist * profile_header = gravi_data_get_header (profile_map);
494  cpl_propertylist_append (profile_header, gain_header);
495  FREE (cpl_propertylist_delete, gain_header);
496 
497  /* Save the FLAT map */
498  frame = cpl_frameset_get_position (flat_frameset, 0);
499 
500  gravi_data_save_new (profile_map, frameset, NULL, parlist,
501  used_frameset, frame, "gravity_p2vm",
502  NULL, GRAVI_FLAT_MAP);
503 
504  CPLCHECK_CLEAN ("Could not save the FLAT profile_map");
505 
506  /* Free the list of files */
507  FREELOOP (gravi_data_delete, raw_data, nb_frame_gain);
508  }
509 
510  /*
511  * (4) Check and get the WAVE frame
512  */
513 
514  if (!cpl_frameset_is_empty (wavecalib_frameset)) {
515  cpl_msg_info (cpl_func, " ***** Get wave map ***** ");
516 
517  /* The WAVE in the frame_set is a calibrated wave */
518  frame = cpl_frameset_get_position (wavecalib_frameset, 0);
519  wave_map = gravi_data_load_frame (frame, used_frameset);
520  }
521  else if (!cpl_frameset_is_empty (wave_frameset)) {
522  cpl_msg_info (cpl_func, " ***** Process the WAVE_RAW ***** ");
523 
524  /* Check calibs */
525  if ( !badpix_map || !profile_map || !dark_map) {
526  ERROR_CLEAN (CPL_ERROR_ILLEGAL_INPUT, "Missing DARK, FLAT, or BAD in frameset");
527  }
528 
529  /* Create the WAVE product */
530  wave_map = gravi_data_new (0);
531 
532  /* Load WAVE_RAW */
533  frame = cpl_frameset_get_position (wave_frameset, 0);
534  data = gravi_data_load_rawframe (frame, used_frameset);
535  gravi_data_detector_cleanup (data, parlist);
536 
537  /* Compute the P2VM of the MET from the WAVE_RAW */
538  cpl_msg_info (cpl_func, "Compute the P2VM_MET from WAVE_RAW");
539  cpl_table * met_table = gravi_data_get_table (data, GRAVI_METROLOGY_EXT);
540  cpl_table * p2vm_met = gravi_metrology_compute_p2vm (met_table);
541 
542  /* Set the P2VM_MET in WAVE */
543  gravi_data_add_table (wave_map, NULL, GRAVI_P2VM_MET_EXT, p2vm_met);
544 
545  CPLCHECK_CLEAN ("Cannot compute P2VM_MET");
546 
547  /* Reduce WAVE_RAW */
548  cpl_msg_info (cpl_func, "Extract SPECTRUM for WAVE_RAW");
549  spectrum_data = gravi_extract_spectrum (data, profile_map, dark_map,
550  badpix_map, NULL, parlist);
551 
552  cpl_msg_info (cpl_func, "Compute OPDs for WAVE_RAW");
553  gravi_wave_compute_opds (spectrum_data, gravi_data_get_table (data, GRAVI_METROLOGY_EXT));
554  FREE (gravi_data_delete, data);
555 
556  CPLCHECK_CLEAN ("Cannot process the WAVE_RAW");
557 
558  /* Save the file with OPD_SC, OPD_FT, OI_VIS_MET */
559  if (gravi_param_get_bool (parlist,"gravity.dfs.debug-file")) {
560  gravi_data_save_new (spectrum_data, frameset, NULL, parlist,
561  used_frameset, frame, "gravity_p2vm",
562  NULL, "DEBUG");
563  }
564 
565  /* Compute wave calibration for FT */
566  gravi_compute_wave (wave_map, spectrum_data, GRAVI_FT, parlist);
567 
568  CPLCHECK_CLEAN ("Cannot compute wave for FT");
569 
570  /* Load and process the WAVESC_RAW (if any) */
571  if (!cpl_frameset_is_empty (wavesc_frameset)) {
572  /* Erase spectrum data */
573  cpl_msg_info (cpl_func, "Delete WAVE_RAW data");
574  FREE (gravi_data_delete, spectrum_data);
575 
576  cpl_msg_info (cpl_func, " ***** Process the WAVESC_RAW ***** ");
577 
578  /* Load and process */
579  frame = cpl_frameset_get_position(wavesc_frameset, 0);
580  data = gravi_data_load_rawframe (frame, used_frameset);
581  gravi_data_detector_cleanup (data, parlist);
582 
583  cpl_msg_info (cpl_func, "Extract SPECTRUM for WAVESC_RAW");
584  spectrum_data = gravi_extract_spectrum (data, profile_map, dark_map,
585  badpix_map, NULL, parlist);
586 
587  cpl_msg_info (cpl_func, "Compute OPDs for WAVESC_RAW");
588  gravi_wave_compute_opds (spectrum_data, gravi_data_get_table (data, GRAVI_METROLOGY_EXT));
589  FREE (gravi_data_delete, data);
590 
591  CPLCHECK_CLEAN ("Cannot process the WAVESC_RAW");
592 
593  /* Save the file with OPD_SC, OPD_FT, OI_VIS_MET */
594  if (gravi_param_get_bool (parlist,"gravity.dfs.debug-file")) {
595  gravi_data_save_new (spectrum_data, frameset, NULL, parlist,
596  used_frameset, frame, "gravity_p2vm",
597  NULL, "DEBUG");
598  }
599  }
600  else {
601  cpl_msg_warning (cpl_func, "No WAVESC_RAW in the SOF:"
602  " SC wavelength will be inaccurate");
603  }
604 
605  /* Compute wave calibration for SC */
606  gravi_compute_wave (wave_map, spectrum_data, GRAVI_SC, parlist);
607 
608  CPLCHECK_CLEAN ("Cannot compute wave for SC");
609 
610  /* Free the spectrum */
611  FREE (gravi_data_delete, spectrum_data);
612 
613  /* Compute the QC */
614  gravi_wave_qc (wave_map, profile_map);
615 
616  /* Save the WAVE map */
617  gravi_data_save_new (wave_map, frameset, NULL, parlist,
618  used_frameset, frame, "gravity_p2vm",
619  NULL, GRAVI_WAVE_MAP);
620 
621  CPLCHECK_CLEAN ("Could not save the WAVE map");
622  }
623 
624  /*
625  * Build the frameset for the P2VM
626  */
627 
628  /* Check if P2VM are provided */
629  if ( cpl_frameset_is_empty (p2vm_frameset) ) {
630  cpl_msg_info (cpl_func,"All RAW data reduced... stop recipe");
631  goto cleanup;
632  }
633 
634  /* Check calibs */
635  if ( !badpix_map || !profile_map || !wave_map || !dark_map) {
636  ERROR_CLEAN (CPL_ERROR_ILLEGAL_INPUT, "Missing DARK, FLAT, BAD, or WAVE in frameset");
637  }
638 
639  /* Add the FLAT_RAW and WAVE_RAW to the p2vm frameset */
640  if ( !cpl_frameset_is_empty (flat_frameset) )
641  cpl_frameset_join (p2vm_frameset, flat_frameset);
642 
643  if ( !cpl_frameset_is_empty (wave_frameset) )
644  cpl_frameset_join (p2vm_frameset, wave_frameset);
645 
646  /* Get the number of the p2vm frame contained in the frameset */
647  nb_frame = cpl_frameset_get_size (p2vm_frameset);
648 
649  /* Check if the 11 files are here */
650  if (nb_frame != 11) {
651  ERROR_CLEAN (CPL_ERROR_ILLEGAL_INPUT, "Missing P2VM in frameset");
652  }
653 
654  /*
655  * (6) Loop on files of the p2vm frameset
656  */
657 
658  /* Construction of the p2vm data. */
659  cpl_msg_info (cpl_func, " ***** Create the P2VM ***** ");
660  p2vm_map = gravi_create_p2vm (wave_map);
661  CPLCHECK_CLEAN ("Cannot create the P2VM data");
662 
663  /* Loop on files */
664  for (i = 0; i < nb_frame; i++) {
665 
666  cpl_msg_info (cpl_func, " ***** file %d over %d ***** ", i+1, nb_frame );
667  current_frameset = cpl_frameset_duplicate (used_frameset);
668 
669  /* Load this frame */
670  frame = cpl_frameset_get_position (p2vm_frameset, i);
671  cpl_frameset_insert (used_frameset, cpl_frame_duplicate (frame));
672  data = gravi_data_load_rawframe (frame, current_frameset);
673  gravi_data_detector_cleanup (data, parlist);
674  CPLCHECK_CLEAN ("Cannot load data");
675 
676  /* Verbose the shutters */
677  cpl_msg_info (cpl_func, "Shutters: %d-%d-%d-%d",
678  gravi_data_get_shutter (data, 0), gravi_data_get_shutter (data, 1),
679  gravi_data_get_shutter (data, 2), gravi_data_get_shutter (data, 3));
680 
681  /* Create the product filename as the first P2VM file (1-1-0-0).
682  * This is to ensure the run_gravi_reduce.py script check
683  * for the correct product */
684  if ( frame_p2vm==NULL && gravi_data_check_shutter (data, 1,1,0,0) )
685  {
686  cpl_msg_info (cpl_func,"Use this frame for the P2VM product");
687  frame_p2vm = frame;
688  }
689 
690  /*
691  * If all shutter open we just continue
692  */
693  if ( gravi_data_check_shutter (data, 1,1,1,1) ) {
694 
695  /* Here we go to next file */
696  cpl_msg_info (cpl_func, "Nothing to be done with the file... yet.");
697  wave_data = data; data = NULL;
698 
699  FREE (cpl_frameset_delete, current_frameset);
700  continue;
701  }
702  /* End if all shutters open */
703 
704  /* Extract spectrum */
705  preproc_data = gravi_extract_spectrum (data, profile_map, dark_map,
706  badpix_map, NULL, parlist);
707  FREE (gravi_data_delete, data);
708  CPLCHECK_CLEAN ("Cannot extract spectrum");
709 
710  /* Rescale to common wavelength */
711  gravi_align_spectrum (preproc_data, wave_map, p2vm_map);
712  CPLCHECK_CLEAN ("Cannot re-interpolate spectrum");
713 
714  /* Compute the part of the p2vm associated to this file */
715  gravi_compute_p2vm (p2vm_map, preproc_data, valid_trans, valid_CP);
716  CPLCHECK_CLEAN("Cannot compute the P2VM");
717 
718  /* Option save the preproc file */
719  if (gravi_param_get_bool (parlist,"gravity.dfs.preproc-file")) {
720 
721  gravi_data_save_new (preproc_data, frameset, NULL, parlist,
722  current_frameset, frame, "gravity_p2vm",
723  NULL, GRAVI_PREPROC);
724  }
725 
726  /* Delete the preproc data */
727  start = clock();
728  FREE (gravi_data_delete,preproc_data);
729  cpl_msg_info(cpl_func, "Execution time to delete preproc_data : %f s",
730  (clock() - start) / (double)CLOCKS_PER_SEC);
731 
732  /* End loop on files to build the p2vm */
733  FREE (cpl_frameset_delete, current_frameset);
734  }
735 
736 
737  /*
738  * (7) P2VM normalization
739  */
740 
741  gravi_p2vm_normalisation (p2vm_map, valid_trans, valid_CP);
742  CPLCHECK_CLEAN("Cannot normalise the p2vm_map");
743 
744 
745  /*
746  * (8) Analyse the WAVE to get the phase correction
747  * and the internal spectrum to latter correct.
748  */
749 
750  cpl_msg_info (cpl_func, " ***** Analyse the WAVE file to calibrate the internal closure and transmission ***** ");
751 
752  /* Extract spectrum */
753  preproc_data = gravi_extract_spectrum (wave_data, profile_map, dark_map,
754  badpix_map, NULL, parlist);
755  CPLCHECK_CLEAN ("Cannot extract spectrum");
756 
757  /* Rescale to common wavelength */
758  gravi_align_spectrum (preproc_data, wave_map, p2vm_map);
759  CPLCHECK_CLEAN ("Cannot re-interpolate spectrum");
760 
761  /* Move extensions necessary to compute the p2vmred */
762  gravi_data_move_ext (preproc_data, wave_data, GRAVI_ARRAY_GEOMETRY_EXT);
763  gravi_data_move_ext (preproc_data, wave_data, GRAVI_OPTICAL_TRAIN_EXT);
764  FREE (gravi_data_delete, wave_data);
765  CPLCHECK_CLEAN ("Cannot move ext");
766 
767  /* Compute P2VMRED */
768  p2vmred_data = gravi_compute_p2vmred (preproc_data, p2vm_map, "gravi_single", parlist);
769  FREE (gravi_data_delete, preproc_data);
770  CPLCHECK_CLEAN ("Cannot apply p2vm");
771 
772  /* Perform the phase correction */
773  if (!strcmp (gravi_param_get_string (parlist, "gravity.calib.phase-calibration"), "CLOSURE")) {
774  gravi_p2vm_phase_correction (p2vm_map, p2vmred_data, 0);
775  }
776  else if (!strcmp (gravi_param_get_string (parlist, "gravity.calib.phase-calibration"), "DISP")) {
777  gravi_p2vm_phase_correction (p2vm_map, p2vmred_data, 1);
778  }
779  else if (!strcmp (gravi_param_get_string (parlist, "gravity.calib.phase-calibration"), "FULL")) {
780  gravi_p2vm_phase_correction (p2vm_map, p2vmred_data, 2);
781  }
782  else {
783  cpl_msg_info (cpl_func, "P2VM phases are kept to zero (option phase-calibration=NONE)");
784  }
785  CPLCHECK_CLEAN ("Cannot recalibrate the P2VM phases");
786 
787  /* Add the OI_FLUX to further normalize the flux if needed */
788  gravi_p2vm_transmission (p2vm_map, p2vmred_data);
789  FREE (gravi_data_delete, p2vmred_data);
790 
791  CPLCHECK_CLEAN ("Cannot compute the transmission");
792 
793  /*
794  * (9) Create product frame, add DataFlow keywords, save the file, log the
795  * saved file in the input frameset. Note that the output filename
796  * is already created (from first P2VM file)
797  */
798 
799  gravi_data_save_new (p2vm_map, frameset, NULL, parlist,
800  used_frameset, frame_p2vm, "gravity_p2vm",
801  NULL, GRAVI_P2VM_MAP);
802 
803  CPLCHECK_CLEAN("Could not save the P2VM on the output file");
804 
805  /* Deallocation of all variables */
806  cleanup:
807  cpl_msg_info (cpl_func,"Cleanup memory");
808 
809  FREE (cpl_frameset_delete, dark_frameset);
810  FREE (cpl_frameset_delete, darkcalib_frameset);
811  FREE (cpl_frameset_delete, badcalib_frameset);
812  FREE (gravi_data_delete, spectrum_data);
813  FREE (gravi_data_delete, p2vmred_data);
814  FREE (gravi_data_delete, wave_data);
815  FREE (gravi_data_delete, dark_map);
816  FREELOOP (gravi_data_delete, raw_data, nb_frame_gain);
817  FREE (gravi_data_delete, badpix_map);
818  FREE (cpl_propertylist_delete, met_plist);
819  FREE (cpl_frameset_delete, wavecalib_frameset);
820  FREE (cpl_frameset_delete, flatcalib_frameset);
821  FREE (cpl_frameset_delete, flat_frameset);
822  FREE (cpl_frameset_delete, wave_frameset);
823  FREE (cpl_frameset_delete, wavesc_frameset);
824  FREE (cpl_frameset_delete, used_frameset);
825  FREE (gravi_data_delete, data);
826  FREE (gravi_data_delete, preproc_data);
827  FREE (gravi_data_delete, dark_map);
828  FREE (gravi_data_delete, wave_map);
829  FREE (gravi_data_delete, profile_map);
830  FREELOOP (cpl_free, valid_CP, 2);
831  FREELOOP (cpl_free, valid_trans, 2);
832  FREE (gravi_data_delete, p2vm_map);
833  FREE (cpl_frameset_delete, p2vm_frameset);
834  FREE (cpl_frameset_delete, current_frameset);
835 
836  /* FIXME: check a *change* of cpl_state instead */
837  CPLCHECK_INT ("Could not cleanup memory");
838 
839  gravi_msg_function_exit(1);
840  return (int)cpl_error_get_code();
841 }
842 
843