GRAVI Pipeline Reference Manual  0.9.6
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 */
185  gravi_parameter_add_badpix (recipe->parameters);
186 
187  /* --How to deal with bad-pixels */
188  p = cpl_parameter_new_value ("gravity.calib.force-badpix-to-zero", CPL_TYPE_BOOL,
189  "Force the badpixel to zero in profile",
190  "gravity.calib", TRUE);
191  cpl_parameter_set_alias (p, CPL_PARAMETER_MODE_CLI, "force-badpix-to-zero");
192  cpl_parameter_disable (p, CPL_PARAMETER_MODE_ENV);
193  cpl_parameterlist_append (recipe->parameters, p);
194 
195  /* --the width of the profile element */
196  p = cpl_parameter_new_value ("gravity.calib.profile-width", CPL_TYPE_INT,
197  "Width of profile in pixel",
198  "gravity.calib", 6);
199  cpl_parameter_set_alias (p, CPL_PARAMETER_MODE_CLI, "profile-width");
200  cpl_parameter_disable (p, CPL_PARAMETER_MODE_ENV);
201  cpl_parameterlist_append (recipe->parameters, p);
202 
203  /* Phase definition in P2VM */
204  p = cpl_parameter_new_enum ("gravity.calib.phase-calibration", CPL_TYPE_STRING,
205  "The relative phase of the P2VM are defined by \n "
206  "NONE defines phiA(lbd) at zero for all baselines;\n "
207  "CLOSURE defines phiA(lbd) at zero for baselines (01,02,03);\n "
208  "DISP defines phiA(lbd) to have zero mean and minimum GD for baselines (01,02,03);\n "
209  "FULL defines phiA(lbd) to have zero-GD for baselines (01,02,03)",
210  "gravi.p2vm", "CLOSURE", 4, "NONE", "CLOSURE", "DISP", "FULL");
211  cpl_parameter_set_alias (p, CPL_PARAMETER_MODE_CLI, "phase-calibration");
212  cpl_parameter_disable (p, CPL_PARAMETER_MODE_ENV);
213  cpl_parameterlist_append (recipe->parameters, p);
214 
215  return 0;
216 }
217 
218 /*----------------------------------------------------------------------------*/
224 /*----------------------------------------------------------------------------*/
225 static int gravity_p2vm_exec(cpl_plugin * plugin)
226 {
227 
228  cpl_recipe * recipe;
229  int recipe_status;
230  cpl_errorstate initial_errorstate = cpl_errorstate_get();
231 
232  /* Return immediately if an error code is already set */
233  if (cpl_error_get_code() != CPL_ERROR_NONE) {
234  cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
235  cpl_func, __LINE__, cpl_error_get_where());
236  return (int)cpl_error_get_code();
237  }
238 
239  if (plugin == NULL) {
240  cpl_msg_error(cpl_func, "Null plugin");
241  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
242  }
243 
244  /* Verify plugin type */
245  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
246  cpl_msg_error(cpl_func, "Plugin is not a recipe");
247  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
248  }
249 
250  /* Get the recipe */
251  recipe = (cpl_recipe *)plugin;
252 
253  /* Verify parameter and frame lists */
254  if (recipe->parameters == NULL) {
255  cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
256  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
257  }
258  if (recipe->frames == NULL) {
259  cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");
260  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
261  }
262 
263  /* Invoke the recipe */
264  recipe_status = gravity_p2vm(recipe->frames, recipe->parameters);
265 
266  /* Ensure DFS-compliance of the products */
267  if (cpl_dfs_update_product_header(recipe->frames)) {
268  if (!recipe_status) recipe_status = (int)cpl_error_get_code();
269  }
270 
271  if (!cpl_errorstate_is_equal(initial_errorstate)) {
272  /* Dump the error history since recipe execution start.
273  At this point the recipe cannot recover from the error */
274  cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);
275  }
276 
277  return recipe_status;
278 }
279 
280 /*----------------------------------------------------------------------------*/
286 /*----------------------------------------------------------------------------*/
287 static int gravity_p2vm_destroy(cpl_plugin * plugin)
288 {
289  cpl_recipe * recipe;
290 
291  if (plugin == NULL) {
292  cpl_msg_error(cpl_func, "Null plugin");
293  cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
294  }
295 
296  /* Verify plugin type */
297  if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
298  cpl_msg_error(cpl_func, "Plugin is not a recipe");
299  cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
300  }
301 
302  /* Get the recipe */
303  recipe = (cpl_recipe *)plugin;
304 
305  cpl_parameterlist_delete(recipe->parameters);
306 
307  return 0;
308 }
309 
310 /*----------------------------------------------------------------------------*/
318 /*----------------------------------------------------------------------------*/
319 static int gravity_p2vm(cpl_frameset * frameset,
320  const cpl_parameterlist * parlist)
321 {
322  cpl_frameset * p2vm_frameset=NULL, * wavecalib_frameset=NULL, * darkcalib_frameset=NULL,
323  * flatcalib_frameset=NULL, * dark_frameset=NULL, * wave_frameset=NULL, * wavesc_frameset=NULL,
324  * badcalib_frameset=NULL, * flat_frameset=NULL, * used_frameset=NULL, * current_frameset=NULL;
325 
326  cpl_frame * frame=NULL, * frame_p2vm=NULL;
327 
328  gravi_data * p2vm_map=NULL, * data=NULL, * dark_map=NULL, * wave_map=NULL,
329  * profile_map=NULL, * badpix_map=NULL, * wave_data=NULL;
330  gravi_data * spectrum_data=NULL;
331  gravi_data * preproc_data=NULL;
332  gravi_data ** raw_data=NULL;
333  gravi_data * p2vmred_data = NULL;
334 
335  int nb_frame, i, nb_frame_gain = 0;
336 
337  cpl_propertylist * met_plist=NULL;
338  int ** valid_trans = cpl_malloc (2 * sizeof (int*));
339  int ** valid_CP = cpl_malloc (2 * sizeof (int*));
340  clock_t start;
341 
342  for (i = 0 ; i < 2; i++){
343  valid_trans[i] = cpl_calloc (4, sizeof (int));
344  valid_CP[i] = cpl_calloc (6, sizeof (int));
345  }
346 
347  /* Message */
348  gravity_print_banner ();
349  cpl_msg_set_time_on();
350  cpl_msg_set_component_on();
351  gravi_msg_function_start(1);
352 
353 
354  /* Get the input frameset */
355  cpl_ensure_code(gravi_dfs_set_groups(frameset) == CPL_ERROR_NONE, cpl_error_get_code()) ;
356 
357  /* Init the used frameset */
358  used_frameset = cpl_frameset_new ();
359 
360  /* Extract DARK frameset */
361  dark_frameset = gravi_frameset_extract_dark_data (frameset);
362  darkcalib_frameset = gravi_frameset_extract_dark_map (frameset);
363 
364  /* Extract FLAT frameset */
365  flat_frameset = gravi_frameset_extract_flat_data (frameset);
366  flatcalib_frameset = gravi_frameset_extract_flat_map (frameset);
367 
368  /* Extract BAD frameset */
369  badcalib_frameset = gravi_frameset_extract_bad_map (frameset);
370 
371  /* Extract WAVE frameset */
372  wave_frameset = gravi_frameset_extract_wave_data (frameset);
373  wavesc_frameset = gravi_frameset_extract_wavesc_data (frameset);
374  wavecalib_frameset = gravi_frameset_extract_wave_map (frameset);
375 
376  /* Extract P2VM frameset */
377  p2vm_frameset = gravi_frameset_extract_p2vm_data (frameset);
378 
379 
380 
381  /*
382  * (1) Identify and extract the dark file
383  */
384 
385  if (!cpl_frameset_is_empty (dark_frameset)) {
386  cpl_msg_info (cpl_func, " ***** Compute DARK map ***** ");
387 
388  /* Load this DARK_RAW */
389  frame = cpl_frameset_get_position (dark_frameset, 0);
390  data = gravi_data_load_rawframe (frame, used_frameset);
391  gravi_data_detector_cleanup (data, parlist);
392 
393  /* Compute the dark */
394  dark_map = gravi_compute_dark (data);
395  FREE (gravi_data_delete, data);
396 
397  CPLCHECK_CLEAN ("Cannot compute the DARK map");
398 
399  /* Save the dark map */
400  gravi_data_save_new (dark_map, frameset, NULL, parlist,
401  NULL, frame, "gravity_p2vm",
402  NULL, GRAVI_DARK_MAP);
403 
404  CPLCHECK_CLEAN ("Could not save the DARK map");
405  }
406  else if (!cpl_frameset_is_empty (darkcalib_frameset)) {
407  cpl_msg_info (cpl_func, " ***** Get DARK map ***** ");
408 
409  /* Load this DARK */
410  frame = cpl_frameset_get_position (darkcalib_frameset, 0);
411  dark_map = gravi_data_load_frame (frame, used_frameset);
412 
413  CPLCHECK_CLEAN ("Could not load the DARK map");
414 
415  /* This new DARK may be used latter for BADPIX */
416  cpl_frameset_insert (dark_frameset, cpl_frame_duplicate (frame));
417  }
418 
419 
420  /*
421  * (2) Identify and extract the BADPIX file
422  */
423 
424  if (!cpl_frameset_is_empty (badcalib_frameset)) {
425  cpl_msg_info (cpl_func, " ***** Get BAD pixel map ***** ");
426 
427  /* The BADPIX is already in the frameset */
428  frame = cpl_frameset_get_position (badcalib_frameset, 0);
429  badpix_map = gravi_data_load_frame (frame, used_frameset);
430  }
431  else if (!cpl_frameset_is_empty (dark_frameset) &&
432  !cpl_frameset_is_empty (flat_frameset)) {
433  cpl_msg_info (cpl_func, " ***** Compute BAD pixel map from DARK and FLAT_RAW ***** ");
434 
435  /* Identify the flat files */
436  nb_frame_gain = cpl_frameset_get_size (flat_frameset);
437  raw_data = cpl_calloc (nb_frame_gain, sizeof(gravi_data *));
438 
439  /* Build the list of FLAT files and output file name */
440  for (int i = 0; i < nb_frame_gain; i++) {
441  frame = cpl_frameset_get_position (flat_frameset, i);
442  raw_data[i] = gravi_data_load_rawframe (frame, NULL);
443  gravi_data_detector_cleanup (raw_data[i], parlist);
444  }
445 
446  /* Compute it from the DARK and the FLAT_RAW */
447  badpix_map = gravi_compute_badpix (dark_map, raw_data,
448  nb_frame_gain, parlist);
449 
450  CPLCHECK_CLEAN("Cannot compute the BAD pixel from DARK and FLAT");
451 
452  /* Save the BADPIX */
453  frame = cpl_frameset_get_position (dark_frameset, 0);
454  gravi_data_save_new (badpix_map, frameset, NULL, parlist,
455  NULL, frame, "gravity_p2vm",
456  NULL, GRAVI_BAD_MAP);
457 
458  CPLCHECK_CLEAN ("Could not save the BAD pixel map");
459 
460  FREELOOP (gravi_data_delete, raw_data, nb_frame_gain);
461  }
462 
463  /*
464  * (3) Check that the FLAT map in the input frameset
465  */
466 
467  if (!cpl_frameset_is_empty(flatcalib_frameset)) {
468  cpl_msg_info (cpl_func, " ***** Get FLAT map ***** ");
469 
470  /* The FLAT is already in the frameset */
471  frame = cpl_frameset_get_position (flatcalib_frameset, 0);
472  profile_map = gravi_data_load_frame (frame, used_frameset);
473  }
474  else if (!cpl_frameset_is_empty (flat_frameset)) {
475  cpl_msg_info (cpl_func, " ***** Compute FLAT map ***** ");
476 
477 
478  /* Check calibs */
479  if (!badpix_map || !dark_map) {
480  ERROR_CLEAN (CPL_ERROR_ILLEGAL_INPUT, "Missing DARK or BAD in frameset");
481  }
482 
483  /* Identify the flat files */
484  nb_frame_gain = cpl_frameset_get_size (flat_frameset);
485  raw_data = cpl_malloc (nb_frame_gain * sizeof(gravi_data *));
486 
487  /* Build the list of FLAT files and output file name */
488  for (i = 0; i < nb_frame_gain; i++) {
489  frame = cpl_frameset_get_position (flat_frameset, i);
490  raw_data[i] = gravi_data_load_rawframe (frame, used_frameset);
491  gravi_data_detector_cleanup (raw_data[i], parlist);
492  }
493 
494 
495  /* Compute the profile from the list of FLAT */
496  profile_map = gravi_compute_profile (raw_data, dark_map, badpix_map, nb_frame_gain, parlist);
497  CPLCHECK_CLEAN ("Cannot compute the FLAT profile");
498 
499  /* Compute the gain QC */
500  cpl_propertylist * gain_header;
501  gain_header = gravi_compute_gain (raw_data, nb_frame_gain, dark_map);
502  CPLCHECK_CLEAN ("Cannot compute the GAIN");
503 
504  /* Put the gain QC in profile_map */
505  cpl_propertylist * profile_header = gravi_data_get_header (profile_map);
506  cpl_propertylist_append (profile_header, gain_header);
507  FREE (cpl_propertylist_delete, gain_header);
508 
509  /* Save the FLAT map */
510  frame = cpl_frameset_get_position (flat_frameset, 0);
511 
512  gravi_data_save_new (profile_map, frameset, NULL, parlist,
513  used_frameset, frame, "gravity_p2vm",
514  NULL, GRAVI_FLAT_MAP);
515 
516  CPLCHECK_CLEAN ("Could not save the FLAT profile_map");
517 
518  /* Free the list of files */
519  FREELOOP (gravi_data_delete, raw_data, nb_frame_gain);
520  }
521 
522  /*
523  * (4) Check and get the WAVE frame
524  */
525 
526  if (!cpl_frameset_is_empty (wavecalib_frameset)) {
527  cpl_msg_info (cpl_func, " ***** Get wave map ***** ");
528 
529  /* The WAVE in the frame_set is a calibrated wave */
530  frame = cpl_frameset_get_position (wavecalib_frameset, 0);
531  wave_map = gravi_data_load_frame (frame, used_frameset);
532  }
533  else if (!cpl_frameset_is_empty (wave_frameset)) {
534  cpl_msg_info (cpl_func, " ***** Process the WAVE_RAW ***** ");
535 
536  /* Check calibs */
537  if ( !badpix_map || !profile_map || !dark_map) {
538  ERROR_CLEAN (CPL_ERROR_ILLEGAL_INPUT, "Missing DARK, FLAT, or BAD in frameset");
539  }
540 
541  /* Create the WAVE product */
542  wave_map = gravi_data_new (0);
543 
544  /* Load WAVE_RAW */
545  frame = cpl_frameset_get_position (wave_frameset, 0);
546  data = gravi_data_load_rawframe (frame, used_frameset);
547  gravi_data_detector_cleanup (data, parlist);
548 
549  /* Compute the P2VM of the MET from the WAVE_RAW */
550  cpl_msg_info (cpl_func, "Compute the P2VM_MET from WAVE_RAW");
551  cpl_table * met_table = gravi_data_get_table (data, GRAVI_METROLOGY_EXT);
552  cpl_table * p2vm_met = gravi_metrology_compute_p2vm (met_table);
553 
554  /* Set the P2VM_MET in WAVE */
555  gravi_data_add_table (wave_map, NULL, GRAVI_P2VM_MET_EXT, p2vm_met);
556 
557  CPLCHECK_CLEAN ("Cannot compute P2VM_MET");
558 
559  /* Reduce WAVE_RAW */
560  cpl_msg_info (cpl_func, "Extract SPECTRUM for WAVE_RAW");
561  spectrum_data = gravi_extract_spectrum (data, profile_map, dark_map, badpix_map, NULL);
562 
563  cpl_msg_info (cpl_func, "Compute OPDs for WAVE_RAW");
564  gravi_wave_compute_opds (spectrum_data, gravi_data_get_table (data, GRAVI_METROLOGY_EXT),
565  gravi_param_get_bool (parlist,"gravity.dfs.debug-file"));
566  FREE (gravi_data_delete, data);
567 
568  CPLCHECK_CLEAN ("Cannot process the WAVE_RAW");
569 
570  /* Compute wave calibration for FT */
571  gravi_compute_wave (wave_map, spectrum_data, GRAVI_FT);
572 
573  CPLCHECK_CLEAN ("Cannot compute wave for FT");
574 
575  /* Load and process the WAVESC_RAW (if any) */
576  if (!cpl_frameset_is_empty (wavesc_frameset)) {
577  /* Erase spectrum data */
578  cpl_msg_info (cpl_func, "Delete WAVE_RAW data");
579  FREE (gravi_data_delete, spectrum_data);
580 
581  cpl_msg_info (cpl_func, " ***** Process the WAVESC_RAW ***** ");
582 
583  /* Load and process */
584  frame = cpl_frameset_get_position(wavesc_frameset, 0);
585  data = gravi_data_load_rawframe (frame, used_frameset);
586  gravi_data_detector_cleanup (data, parlist);
587 
588  cpl_msg_info (cpl_func, "Extract SPECTRUM for WAVESC_RAW");
589  spectrum_data = gravi_extract_spectrum (data, profile_map, dark_map, badpix_map, NULL);
590 
591  cpl_msg_info (cpl_func, "Compute OPDs for WAVESC_RAW");
592  gravi_wave_compute_opds (spectrum_data, gravi_data_get_table (data, GRAVI_METROLOGY_EXT),
593  gravi_param_get_bool (parlist,"gravity.dfs.debug-file"));
594  FREE (gravi_data_delete, data);
595 
596  CPLCHECK_CLEAN ("Cannot process the WAVESC_RAW");
597  }
598  else {
599  cpl_msg_warning (cpl_func, "No WAVESC_RAW in the SOF:"
600  " SC wavelength will be inaccurate");
601  }
602 
603  /* Compute wave calibration for SC */
604  gravi_compute_wave (wave_map, spectrum_data, GRAVI_SC);
605 
606  CPLCHECK_CLEAN ("Cannot compute wave for SC");
607 
608  /* Free the spectrum */
609  FREE (gravi_data_delete, spectrum_data);
610 
611  /* Compute the QC */
612  gravi_wave_qc (wave_map, profile_map);
613 
614  /* Save the WAVE map */
615  gravi_data_save_new (wave_map, frameset, NULL, parlist,
616  used_frameset, frame, "gravity_p2vm",
617  NULL, GRAVI_WAVE_MAP);
618 
619  CPLCHECK_CLEAN ("Could not save the WAVE map");
620  }
621 
622  /*
623  * Build the frameset for the P2VM
624  */
625 
626  /* Check if P2VM are provided */
627  if ( cpl_frameset_is_empty (p2vm_frameset) ) {
628  cpl_msg_info (cpl_func,"All RAW data reduced... stop recipe");
629  goto cleanup;
630  }
631 
632  /* Check calibs */
633  if ( !badpix_map || !profile_map || !wave_map || !dark_map) {
634  ERROR_CLEAN (CPL_ERROR_ILLEGAL_INPUT, "Missing DARK, FLAT, BAD, or WAVE in frameset");
635  }
636 
637  /* Add the FLAT_RAW and WAVE_RAW to the p2vm frameset */
638  if ( !cpl_frameset_is_empty (flat_frameset) )
639  cpl_frameset_join (p2vm_frameset, flat_frameset);
640 
641  if ( !cpl_frameset_is_empty (wave_frameset) )
642  cpl_frameset_join (p2vm_frameset, wave_frameset);
643 
644  /* Get the number of the p2vm frame contained in the frameset */
645  nb_frame = cpl_frameset_get_size (p2vm_frameset);
646 
647  /* Check if the 11 files are here */
648  if (nb_frame != 11) {
649  ERROR_CLEAN (CPL_ERROR_ILLEGAL_INPUT, "Missing P2VM in frameset");
650  }
651 
652  /*
653  * (6) Loop on files of the p2vm frameset
654  */
655 
656  /* Construction of the p2vm data. */
657  cpl_msg_info (cpl_func, " ***** Create the P2VM ***** ");
658  p2vm_map = gravi_create_p2vm (wave_map);
659  CPLCHECK_CLEAN ("Cannot create the P2VM data");
660 
661  /* Loop on files */
662  for (i = 0; i < nb_frame; i++) {
663 
664  cpl_msg_info (cpl_func, " ***** file %d over %d ***** ", i+1, nb_frame );
665  current_frameset = cpl_frameset_duplicate (used_frameset);
666 
667  /* Load this frame */
668  frame = cpl_frameset_get_position (p2vm_frameset, i);
669  cpl_frameset_insert (used_frameset, cpl_frame_duplicate (frame));
670  data = gravi_data_load_rawframe (frame, current_frameset);
671  gravi_data_detector_cleanup (data, parlist);
672  CPLCHECK_CLEAN ("Cannot load data");
673 
674  /* Verbose the shutters */
675  cpl_msg_info (cpl_func, "Shutters: %d-%d-%d-%d",
676  gravi_data_get_shutter (data, 0), gravi_data_get_shutter (data, 1),
677  gravi_data_get_shutter (data, 2), gravi_data_get_shutter (data, 3));
678 
679  /* Create the product filename as the first P2VM file (1-1-0-0).
680  * This is to ensure the run_gravi_reduce.py script check
681  * for the correct product */
682  if ( frame_p2vm==NULL && gravi_data_check_shutter (data, 1,1,0,0) )
683  {
684  cpl_msg_info (cpl_func,"Use this frame for the P2VM product");
685  frame_p2vm = frame;
686  }
687 
688  /*
689  * If all shutter open we just continue
690  */
691  if ( gravi_data_check_shutter (data, 1,1,1,1) ) {
692 
693  /* Here we go to next file */
694  cpl_msg_info (cpl_func, "Nothing to be done with the file... yet.");
695  wave_data = data; data = NULL;
696 
697  FREE (cpl_frameset_delete, current_frameset);
698  continue;
699  }
700  /* End if all shutters open */
701 
702  /* Extract spectrum */
703  preproc_data = gravi_extract_spectrum (data, profile_map, dark_map, badpix_map, NULL);
704  FREE (gravi_data_delete, data);
705  CPLCHECK_CLEAN ("Cannot extract spectrum");
706 
707  /* Rescale to common wavelength */
708  gravi_align_spectrum (preproc_data, wave_map, p2vm_map);
709  CPLCHECK_CLEAN ("Cannot re-interpolate spectrum");
710 
711  /* Compute the part of the p2vm associated to this file */
712  gravi_compute_p2vm (p2vm_map, preproc_data, valid_trans, valid_CP);
713  CPLCHECK_CLEAN("Cannot compute the P2VM");
714 
715  /* Option save the preproc file */
716  if (gravi_param_get_bool (parlist,"gravity.dfs.preproc-file")) {
717 
718  gravi_data_save_new (preproc_data, frameset, NULL, parlist,
719  current_frameset, frame, "gravity_p2vm",
720  NULL, GRAVI_PREPROC);
721  }
722 
723  /* Delete the preproc data */
724  start = clock();
725  FREE (gravi_data_delete,preproc_data);
726  cpl_msg_info(cpl_func, "Execution time to delete preproc_data : %f s",
727  (clock() - start) / (double)CLOCKS_PER_SEC);
728 
729  /* End loop on files to build the p2vm */
730  FREE (cpl_frameset_delete, current_frameset);
731  }
732 
733 
734  /*
735  * (7) P2VM normalization
736  */
737 
738  gravi_p2vm_normalisation (p2vm_map, valid_trans, valid_CP);
739  CPLCHECK_CLEAN("Cannot normalise the p2vm_map");
740 
741 
742  /*
743  * (8) Analyse the WAVE to get the phase correction
744  * and the internal spectrum to latter correct.
745  */
746 
747  cpl_msg_info (cpl_func, " ***** Analyse the WAVE file to calibrate the internal closure and transmission ***** ");
748 
749  /* Extract spectrum */
750  preproc_data = gravi_extract_spectrum (wave_data, profile_map, dark_map, badpix_map, NULL);
751  CPLCHECK_CLEAN ("Cannot extract spectrum");
752 
753  /* Rescale to common wavelength */
754  gravi_align_spectrum (preproc_data, wave_map, p2vm_map);
755  CPLCHECK_CLEAN ("Cannot re-interpolate spectrum");
756 
757  /* Move extensions necessary to compute the p2vmred */
758  gravi_data_move_ext (preproc_data, wave_data, GRAVI_ARRAY_GEOMETRY_EXT);
759  gravi_data_move_ext (preproc_data, wave_data, GRAVI_OPTICAL_TRAIN_EXT);
760  FREE (gravi_data_delete, wave_data);
761  CPLCHECK_CLEAN ("Cannot move ext");
762 
763  /* Compute P2VMRED */
764  p2vmred_data = gravi_compute_p2vmred (preproc_data, p2vm_map, "gravi_single", parlist);
765  FREE (gravi_data_delete, preproc_data);
766  CPLCHECK_CLEAN ("Cannot apply p2vm");
767 
768  /* Perform the phase correction */
769  if (!strcmp (gravi_param_get_string (parlist, "gravity.calib.phase-calibration"), "CLOSURE")) {
770  gravi_p2vm_phase_correction (p2vm_map, p2vmred_data, 0);
771  }
772  else if (!strcmp (gravi_param_get_string (parlist, "gravity.calib.phase-calibration"), "DISP")) {
773  gravi_p2vm_phase_correction (p2vm_map, p2vmred_data, 1);
774  }
775  else if (!strcmp (gravi_param_get_string (parlist, "gravity.calib.phase-calibration"), "FULL")) {
776  gravi_p2vm_phase_correction (p2vm_map, p2vmred_data, 2);
777  }
778  else {
779  cpl_msg_info (cpl_func, "P2VM phases are kept to zero (option phase-calibration=NONE)");
780  }
781  CPLCHECK_CLEAN ("Cannot recalibrate the P2VM phases");
782 
783  /* Add the OI_FLUX to further normalize the flux if needed */
784  gravi_p2vm_transmission (p2vm_map, p2vmred_data);
785  FREE (gravi_data_delete, p2vmred_data);
786 
787  CPLCHECK_CLEAN ("Cannot compute the transmission");
788 
789  /*
790  * (9) Create product frame, add DataFlow keywords, save the file, log the
791  * saved file in the input frameset. Note that the output filename
792  * is already created (from first P2VM file)
793  */
794 
795  gravi_data_save_new (p2vm_map, frameset, NULL, parlist,
796  used_frameset, frame_p2vm, "gravity_p2vm",
797  NULL, GRAVI_P2VM_MAP);
798 
799  CPLCHECK_CLEAN("Could not save the P2VM on the output file");
800 
801  /* Deallocation of all variables */
802  cleanup:
803  cpl_msg_info (cpl_func,"Cleanup memory");
804 
805  FREE (cpl_frameset_delete, dark_frameset);
806  FREE (cpl_frameset_delete, darkcalib_frameset);
807  FREE (cpl_frameset_delete, badcalib_frameset);
808  FREE (gravi_data_delete, spectrum_data);
809  FREE (gravi_data_delete, p2vmred_data);
810  FREE (gravi_data_delete, wave_data);
811  FREE (gravi_data_delete, dark_map);
812  FREELOOP (gravi_data_delete, raw_data, nb_frame_gain);
813  FREE (gravi_data_delete, badpix_map);
814  FREE (cpl_propertylist_delete, met_plist);
815  FREE (cpl_frameset_delete, wavecalib_frameset);
816  FREE (cpl_frameset_delete, flatcalib_frameset);
817  FREE (cpl_frameset_delete, flat_frameset);
818  FREE (cpl_frameset_delete, wave_frameset);
819  FREE (cpl_frameset_delete, wavesc_frameset);
820  FREE (cpl_frameset_delete, used_frameset);
821  FREE (gravi_data_delete, data);
822  FREE (gravi_data_delete, preproc_data);
823  FREE (gravi_data_delete, dark_map);
824  FREE (gravi_data_delete, wave_map);
825  FREE (gravi_data_delete, profile_map);
826  FREELOOP (cpl_free, valid_CP, 2);
827  FREELOOP (cpl_free, valid_trans, 2);
828  FREE (gravi_data_delete, p2vm_map);
829  FREE (cpl_frameset_delete, p2vm_frameset);
830  FREE (cpl_frameset_delete, current_frameset);
831 
832  /* FIXME: check a *change* of cpl_state instead */
833  CPLCHECK_INT ("Could not cleanup memory");
834 
835  gravi_msg_function_exit(1);
836  return (int)cpl_error_get_code();
837 }
838 
839