GRAVI Pipeline Reference Manual  1.2.3
gravi_p2vm.c
1 /* $Id: gravi_preproc.c,v 1.12 2011/04/31 06:10:40 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 
37 /*
38  * History
39  * 04/12/2018 use GRAVITY_WAVE.fits calibration file instead of hardcoded values
40  * 10/01/2019 fix a few warnings : roof_pos, qc_min, qc_max parameter usage
41  */
42 /*-----------------------------------------------------------------------------
43  Includes
44  -----------------------------------------------------------------------------*/
45 
46 #ifdef HAVE_CONFIG_H
47 #include <config.h>
48 #endif
49 
50 #include <cpl.h>
51 #include <stdio.h>
52 #include <string.h>
53 #include <math.h>
54 #include <time.h>
55 #include <complex.h>
56 
57 #include "gravi_data.h"
58 #include "gravi_dfs.h"
59 #include "gravi_pfits.h"
60 #include "gravi_cpl.h"
61 
62 #include "gravi_utils.h"
63 #include "gravi_ellipse.h"
64 #include "gravi_p2vm.h"
65 
66 /*-----------------------------------------------------------------------------
67  Defines
68  -----------------------------------------------------------------------------*/
69 
70 #define GRAVI_DEFAULT_LBD_MIN 1.99e-6
71 #define GRAVI_DEFAULT_LBD_MAX 2.45e-6
72 #define GRAVI_LOW_LBD_MIN 2.0000e-6
73 #define GRAVI_LOW_LBD_MAX 2.481e-6
74 
75 /*-----------------------------------------------------------------------------
76  Private prototypes
77  -----------------------------------------------------------------------------*/
78 
79 cpl_table* gravi_create_p2vm_table (cpl_table * detector_table,
80  int nwave);
81 
82 cpl_table * gravi_create_oiwave_table_sc (cpl_table * wave_table,
83  cpl_propertylist * header,
84  gravi_data *wave_param);
85 
86 cpl_table * gravi_create_oiwave_table_ft (cpl_table * wave_table,
87  cpl_table * detector_table,
88  int pol);
89 
90 /*-----------------------------------------------------------------------------
91  Function code
92  -----------------------------------------------------------------------------*/
93 
94 /*---------------------------------------------------------------------------*/
108 /*---------------------------------------------------------------------------*/
109 
110 cpl_table* gravi_create_p2vm_table (cpl_table * detector_table,
111  int nwave)
112 {
113  gravi_msg_function_start(0);
114  cpl_ensure (detector_table, CPL_ERROR_NULL_INPUT, NULL);
115  cpl_ensure (nwave>0, CPL_ERROR_ILLEGAL_INPUT, NULL);
116 
117  /* Get the number of region */
118  int ntel = 4;
119  int n_region = cpl_table_get_nrow (detector_table);
120 
121  /* Creating the table with nRegion rows */
122  cpl_table * p2vm_table = cpl_table_new (n_region);
123 
125  cpl_table_duplicate_column (p2vm_table, "REGNAME",
126  detector_table, "REGNAME");
128  cpl_table_new_column_array (p2vm_table,"TRANSMISSION", CPL_TYPE_FLOAT,
129  nwave * ntel);
131  cpl_table_new_column_array (p2vm_table,"COHERENCE", CPL_TYPE_FLOAT,
132  nwave * (ntel * (ntel - 1) / 2));
134  cpl_table_new_column_array (p2vm_table,"PHASE", CPL_TYPE_FLOAT,
135  nwave * (ntel * (ntel - 1) / 2));
137  cpl_table_new_column_array (p2vm_table,"C MATRIX", CPL_TYPE_FLOAT,
138  nwave * (ntel * (ntel - 1) / 2));
139 
140  /* Initialization of all these columns */
141  cpl_array * zero_array_transmission, * zero_array;
142  zero_array_transmission = cpl_array_new (nwave*ntel, CPL_TYPE_FLOAT);
143  cpl_array_fill_window_float (zero_array_transmission, 0, nwave*ntel, 0);
144 
145  zero_array = cpl_array_new (nwave*(ntel*(ntel-1)/2),
146  CPL_TYPE_FLOAT );
147  cpl_array_fill_window_float (zero_array, 0,
148  nwave * (ntel * (ntel - 1) / 2), 0);
149 
150  /* Fill in the arrays on the columns */
151  for (int i = 0; i < n_region; i++){
152  cpl_table_set_array (p2vm_table, "TRANSMISSION", i, zero_array_transmission);
153  cpl_table_set_array (p2vm_table, "COHERENCE", i, zero_array);
154  cpl_table_set_array (p2vm_table, "PHASE", i, zero_array);
155  cpl_table_set_array (p2vm_table, "C MATRIX", i, zero_array);
156  }
157 
158  cpl_array * dimensions;
159  dimensions = cpl_array_new (2, CPL_TYPE_INT);
160 
161  /* Define the dimension of the transmission column */
162  cpl_array_set_int (dimensions, 0, nwave);
163  cpl_array_set_int (dimensions, 1, ntel);
164  cpl_table_set_column_dimensions (p2vm_table, "TRANSMISSION", dimensions);
165 
166  /* Define the dimension of the coherence column */
167  cpl_array_set_int (dimensions, 1, (ntel*(ntel-1)/2));
168  cpl_table_set_column_dimensions (p2vm_table, "COHERENCE", dimensions);
169 
170  /* Define the dimension of the phase column */
171  cpl_array_set_int (dimensions, 1, (ntel*(ntel-1)/2));
172  cpl_table_set_column_dimensions (p2vm_table, "PHASE", dimensions);
173 
174  cpl_table_set_column_dimensions (p2vm_table, "C MATRIX", dimensions);
175 
176  FREE (cpl_array_delete, zero_array_transmission);
177  FREE (cpl_array_delete, zero_array);
178  FREE (cpl_array_delete, dimensions);
179 
180  gravi_msg_function_exit(0);
181  return p2vm_table;
182 }
183 
184 /*---------------------------------------------------------------------------*/
196 /*---------------------------------------------------------------------------*/
197 
198 cpl_table * gravi_create_oiwave_table_sc (cpl_table * wave_table,
199  cpl_propertylist * header,
200  gravi_data *wave_param)
201 {
202  gravi_msg_function_start(1);
203  cpl_ensure (wave_table, CPL_ERROR_NULL_INPUT, NULL);
204  cpl_ensure (header, CPL_ERROR_NULL_INPUT, NULL);
205 
206 
207  /* EKW START 04/12/2018 */
208  /* set the calibrated eff_wave for LOW res*/
209  /* OP 2018-02-12: new bandwidths measured for 3pix interpolation
210  average of the six P1 baselines
211  also valid for P2
212  */
213 /*
214  double calib_eff_wave[14] = {7.046E-08,
215  1.243E-07,
216  1.342E-07,
217  1.278E-07,
218  1.255E-07,
219  1.345E-07,
220  1.423E-07,
221  1.332E-07,
222  1.235E-07,
223  1.165E-07,
224  1.158E-07,
225  1.157E-07,
226  1.120E-07,
227  9.597E-08};
228 
229 */
230  /* double *roof_pos; */
231  double * calib_eff_wave;
232  cpl_table * calib_eff_table = gravi_data_get_table (wave_param, "WAVE_TAB");
233  // CPLCHECK_MSG ("STATIC_CALIB not available in the SOF. It is mandatory for acqcam reduction.");
234 
235  if ( cpl_table_has_column(calib_eff_table , "FBAND_WAVE") ) {
236  calib_eff_wave = cpl_table_get_data_double (calib_eff_table, "FBAND_WAVE");
237  cpl_msg_info(cpl_func,"calib_eff_wave [0] : %e", calib_eff_wave[0] );
238  cpl_msg_info(cpl_func,"calib_eff_wave [1] : %e", calib_eff_wave[1] );
239  cpl_msg_info(cpl_func,"calib_eff_wave [2] : %e", calib_eff_wave[2] );
240  cpl_msg_info(cpl_func,"calib_eff_wave [3] : %e", calib_eff_wave[3] );
241  }
242  else {
243  cpl_msg_error(cpl_func,"Cannot get the default values for calib_eff_wave");
244  }
245 
246  /* from the Define at the begin
247  * #define GRAVI_DEFAULT_LBD_MIN 1.99e-6
248  * #define GRAVI_DEFAULT_LBD_MAX 2.45e-6
249  * #define GRAVI_LOW_LBD_MIN 2.0000e-6
250  * #define GRAVI_LOW_LBD_MAX 2.481e-6
251  * Additionally a MEDIAN entry was also requested by Sylvestre
252  * */
253  double gravi_high_lbd_min = cpl_propertylist_get_double (gravi_data_get_plist(wave_param,GRAVI_PRIMARY_HDR_EXT), "ESO OIWAVE HIGH LBD MIN");
254  cpl_msg_info (cpl_func,"gravi_high_lbd_min : %e", gravi_high_lbd_min);
255 
256  double gravi_high_lbd_max = cpl_propertylist_get_double (gravi_data_get_plist(wave_param,GRAVI_PRIMARY_HDR_EXT), "ESO OIWAVE HIGH LBD MAX");
257  cpl_msg_info (cpl_func,"gravi_high_lbd_max : %e", gravi_high_lbd_max);
258 
259  double gravi_med_lbd_min = cpl_propertylist_get_double (gravi_data_get_plist(wave_param,GRAVI_PRIMARY_HDR_EXT), "ESO OIWAVE MED LBD MIN");
260  cpl_msg_info (cpl_func,"gravi_med_lbd_min : %e", gravi_med_lbd_min);
261 
262  double gravi_med_lbd_max = cpl_propertylist_get_double (gravi_data_get_plist(wave_param,GRAVI_PRIMARY_HDR_EXT), "ESO OIWAVE MED LBD MAX");
263  cpl_msg_info (cpl_func,"gravi_med_lbd_max : %e", gravi_med_lbd_max);
264 
265  double gravi_low_lbd_min = cpl_propertylist_get_double (gravi_data_get_plist(wave_param,GRAVI_PRIMARY_HDR_EXT), "ESO OIWAVE LOW LBD MIN");
266  cpl_msg_info (cpl_func,"gravi_low_lbd_min : %e", gravi_low_lbd_min);
267 
268  double gravi_low_lbd_max = cpl_propertylist_get_double (gravi_data_get_plist(wave_param,GRAVI_PRIMARY_HDR_EXT), "ESO OIWAVE LOW LBD MAX");
269  cpl_msg_info (cpl_func,"gravi_low_lbd_max : %e", gravi_low_lbd_max);
270 
271  /* EKW END 04/12/2018 */
272 
273  /* Get the QC */
274  /*double qc_min, qc_max;
275  qc_min = cpl_propertylist_get_double (header, QC_MINWAVE(GRAVI_SC));
276  qc_max = cpl_propertylist_get_double (header, QC_MAXWAVE(GRAVI_SC));
277  */
278  CPLCHECK_NUL ("Cannot read the QC MINWAVE MAXWAVE");
279 
280  /* Get the max_wave and min_wave*/
281  int n_element = cpl_table_get_column_depth (wave_table, "DATA1");
282  CPLCHECK_NUL ("Cannot get the number of elements");
283  double max_wave ,min_wave ;
284  if (n_element<20)
285  {
286  /* EKW max_wave = GRAVI_LOW_LBD_MAX;
287  min_wave = GRAVI_LOW_LBD_MIN; */
288  max_wave = gravi_low_lbd_max;
289  min_wave = gravi_low_lbd_min;
290  cpl_msg_info (cpl_func,"Using Low resolution wavelength table");
291 
292  }else{
293  /*max_wave = GRAVI_DEFAULT_LBD_MAX;
294  min_wave = GRAVI_DEFAULT_LBD_MIN; */
295  max_wave = gravi_high_lbd_max;
296  min_wave = gravi_high_lbd_min;
297  cpl_msg_info (cpl_func,"Using High/Med resolution wavelength table");
298  }
299  CPLCHECK_NUL ("Cannot get the max_wave and min_wave");
300 
301  /* Get the nwave */
302  cpl_size nwave = gravi_wave_get_nlambda (wave_table, min_wave, max_wave);
303  CPLCHECK_NUL ("Cannot define the limits");
304 
305  /* Create the OI_WAVELENGTH table */
306  cpl_table * oiwave_table = cpl_table_new (nwave);
307 
308  cpl_table_new_column (oiwave_table, "EFF_WAVE", CPL_TYPE_FLOAT);
309  cpl_table_set_column_unit (oiwave_table, "EFF_WAVE", "m");
310 
311  cpl_table_new_column (oiwave_table, "EFF_BAND", CPL_TYPE_FLOAT);
312  cpl_table_set_column_unit (oiwave_table, "EFF_BAND", "m");
313 
314  /* Construction of the new wavelength table
315  * To be improved if needed (non linear computation) */
316  for (cpl_size wave = 0; wave < nwave; wave++){
317  double lambda = min_wave + wave * (max_wave-min_wave)/(nwave-1);
318  cpl_table_set (oiwave_table, "EFF_WAVE", wave, lambda);
319  // introduce *2 to be closer to the real Band pass
320  cpl_table_set (oiwave_table, "EFF_BAND", wave, (max_wave-min_wave)/(nwave-1)*2);
321  //for LOW mode (nwave=11) set to measured bandpass
322  if (nwave == 14) cpl_table_set (oiwave_table, "EFF_BAND", wave, calib_eff_wave[wave]);
323  }
324 
325  //FREE(cpl_table_delete, calib_eff_table); /* EKW 04/12/2018 */
326 
327  //free(calib_eff_wave2); /* EKW 04/12/2018 */
328  gravi_msg_function_exit(1);
329  return oiwave_table;
330 }
331 
332 /*---------------------------------------------------------------------------*/
344 /*---------------------------------------------------------------------------*/
345 
346 cpl_table * gravi_create_oiwave_table_ft (cpl_table * wave_table,
347  cpl_table * detector_table,
348  int pol)
349 {
350  gravi_msg_function_start(1);
351  cpl_ensure (wave_table, CPL_ERROR_NULL_INPUT, NULL);
352  cpl_ensure (detector_table, CPL_ERROR_NULL_INPUT, NULL);
353  cpl_ensure (pol == 0 || pol == 1, CPL_ERROR_ILLEGAL_INPUT, NULL);
354 
355  /* Get the nwave */
356  cpl_size nwave = gravi_spectrum_get_nwave (wave_table);
357  cpl_size nreg = cpl_table_get_nrow (detector_table);
358 
359  /* Create the OI_WAVELENGTH table */
360  cpl_table * oiwave_table = cpl_table_new (nwave);
361 
362  cpl_table_new_column (oiwave_table, "EFF_WAVE", CPL_TYPE_FLOAT);
363  cpl_table_set_column_unit (oiwave_table, "EFF_WAVE", "m");
364 
365  cpl_table_new_column (oiwave_table, "EFF_BAND", CPL_TYPE_FLOAT);
366  cpl_table_set_column_unit (oiwave_table, "EFF_BAND", "m");
367 
368  /* Fill each channel */
369  for (cpl_size wave = 0; wave < nwave; wave++) {
370  double lambda = (wave == nwave-1) ? 1.0 : 0.0;
371 
372  /* Loop on regions */
373  for (int reg = 0; reg < nreg; reg++) {
374  if (gravi_region_get_pol (detector_table, reg) != pol) continue;
375  double value = gravi_table_get_value (wave_table, GRAVI_DATA[reg], 0, wave);
376 
377  if (wave == 0) lambda = CPL_MAX (lambda, value + 0.00001e-6);
378  else if (wave == nwave-1) lambda = CPL_MIN (lambda, value - 0.00001e-6);
379  else lambda += value / 24.0;
380  }
381  cpl_msg_info (cpl_func, "lbd[%lld] = %g [um]", wave, lambda*1e6);
382 
383  cpl_table_set (oiwave_table, "EFF_WAVE", wave, lambda);
384  cpl_table_set (oiwave_table, "EFF_BAND", wave, 8.5e-8);
385  }
386 
387  //cpl_msg_info (cpl_func, "Force linear wave");
388  //double min_wave = cpl_table_get (oiwave_table, "EFF_WAVE", 0, NULL);
389  //double max_wave = cpl_table_get (oiwave_table, "EFF_WAVE", nwave-1, NULL);
390  //for (cpl_size wave = 0; wave < nwave; wave++){
391  // double lambda = min_wave + wave * (max_wave-min_wave)/(nwave-1);
392  // cpl_table_set (oiwave_table, "EFF_WAVE", wave, lambda);
393  //}
394 
395  gravi_msg_function_exit(1);
396  return oiwave_table;
397 }
398 
399 /*----------------------------------------------------------------------------*/
412 /*----------------------------------------------------------------------------*/
413 
414 gravi_data * gravi_create_p2vm (gravi_data * wave_map, gravi_data *wave_param)
415 {
416  cpl_table * oiwave_table;
417 
418  /* Verbose */
419  gravi_msg_function_start(1);
420  cpl_ensure (wave_map, CPL_ERROR_NULL_INPUT, NULL);
421 
422  cpl_propertylist * wave_header = gravi_data_get_header (wave_map);
423  CPLCHECK_NUL ("Cannot load data");
424 
425  /* Create output map */
426  gravi_data * p2vm_map = gravi_data_new(0);
427 
428  /* Duplicate the P2VM_MET in product */
429  gravi_data_copy_ext (p2vm_map, wave_map, GRAVI_P2VM_MET_EXT);
430  CPLCHECK_NUL ("Cannot copy tables");
431 
432  /* Loop on SC/FT */
433  for (int type_data = 0; type_data < 2 ; type_data++) {
434 
435  /* Check if this data is present */
436  if (!gravi_data_has_wave (wave_map, type_data)) {
437  cpl_msg_info (cpl_func,"No data for %s, skip it", GRAVI_TYPE(type_data));
438  continue;
439  }
440 
441  /* Copy the IMAGING_DETECTOR table into product */
442  gravi_data_copy_ext (p2vm_map, wave_map, GRAVI_IMAGING_DETECTOR_EXT(type_data));
443  CPLCHECK_NUL ("Cannot copy tables");
444 
445  /* Get the WAVE_DATA and IMAGIGN_DETECTOR */
446  cpl_table * wave_table = gravi_data_get_wave_data (wave_map, type_data);
447  cpl_table * detector_table = gravi_data_get_imaging_detector (wave_map, type_data);
448  CPLCHECK_NUL ("Cannot get data");
449 
450  /*
451  * Build the OI_WAVELENGTHs
452  */
453 
454  /* Loop on polarisation */
455  int n_pol = gravi_spectrum_get_npol (wave_table);
456  for (int pol = 0 ; pol<n_pol ; pol++) {
457 
458  if (type_data == GRAVI_SC)
459  /* Create the SC OI_WAVELENGTH, will be the same for
460  * both polarisations, and static from user requirement */
461  oiwave_table = gravi_create_oiwave_table_sc (wave_table,
462  wave_header,
463  wave_param);
464  else
465  /* Create the FT OI_WAVELENGTH, as a meach of each channel */
466  oiwave_table = gravi_create_oiwave_table_ft (wave_table,
467  detector_table,
468  pol);
469 
470  /* Create plist */
471  cpl_propertylist * oiwave_plist = cpl_propertylist_new ();
472  cpl_propertylist_append_int (oiwave_plist, "NWAVE", cpl_table_get_nrow (oiwave_table));
473  cpl_propertylist_update_int (oiwave_plist, "OI_REVN", 1);
474  cpl_propertylist_append_string (oiwave_plist, "INSNAME", GRAVI_INSNAME(type_data,pol,n_pol));
475  cpl_propertylist_append_int (oiwave_plist, "EXTVER", GRAVI_EXTVER(type_data,pol,n_pol));
476 
477  /* Add this OI_WAVELENGTH to the spectrum_data */
478  gravi_data_add_table (p2vm_map, oiwave_plist,
479  GRAVI_OI_WAVELENGTH_EXT, oiwave_table);
480  CPLCHECK_NUL ("Cannot add the table");
481  }
482 
483  /*
484  * Build the P2VM
485  */
486  cpl_size n_wave = cpl_table_get_nrow (oiwave_table);
487 
488  /* Init the table */
489  cpl_table * p2vm_table;
490  p2vm_table = gravi_create_p2vm_table (detector_table, n_wave);
491 
492  /* Init the header of this table */
493  cpl_propertylist * p2vm_plist = cpl_propertylist_new();
494  CPLCHECK_NUL ("Cannot create propertylist");
495 
496  /* Add the p2vm_table */
497  const char * extname = (type_data == GRAVI_SC ? GRAVI_P2VM_DATA_SC_EXT : GRAVI_P2VM_DATA_FT_EXT);
498  gravi_data_add_table (p2vm_map, p2vm_plist, extname, p2vm_table);
499 
500  CPLCHECK_NUL ("Cannot create P2VM");
501  } /* End loop SC/FT */
502 
503  gravi_msg_function_exit(1);
504  return p2vm_map;
505 }
506 
507 /*----------------------------------------------------------------------------*/
545 /*----------------------------------------------------------------------------*/
546 
547 cpl_error_code gravi_compute_p2vm (gravi_data * p2vm_map, gravi_data * preproc_data,
548  int ** valid_trans, int ** valid_pair,
549  enum gravi_detector_type det_type)
550 {
551  gravi_msg_function_start(1);
552  cpl_ensure_code (p2vm_map, CPL_ERROR_NULL_INPUT);
553  cpl_ensure_code (preproc_data, CPL_ERROR_NULL_INPUT);
554 
555  int nv = 0;
556 
557  /*
558  * Loop on type data (SC/FT)
559  */
560  int init_type_data = 1;
561  int end_type_data = 1;
562  if(det_type == GRAVI_DET_SC || det_type == GRAVI_DET_ALL)
563  init_type_data = 0;
564  if(det_type == GRAVI_DET_FT || det_type == GRAVI_DET_ALL)
565  end_type_data = 1;
566  for (int type_data = init_type_data; type_data <= end_type_data; type_data++ ) {
567 
568  /* Check if SPECTRUM data exists */
569  if (!gravi_data_has_spectrum (preproc_data, type_data)) {
570  cpl_msg_info (cpl_func,"No data for %s, skip it", GRAVI_TYPE(type_data));
571  continue;
572  }
573 
574  /* Primary header of input data */
575  cpl_propertylist * preproc_header = gravi_data_get_header (preproc_data);
576 
577  /* Get the tables extension */
578  cpl_table * detector_table, * spectrum_table, * p2vm_table;
579  detector_table = gravi_data_get_imaging_detector (preproc_data, type_data);
580  spectrum_table = gravi_data_get_spectrum_data (preproc_data, type_data);
581  p2vm_table = gravi_data_get_p2vm_data (p2vm_map, type_data);
582 
583  cpl_ensure_code (detector_table, CPL_ERROR_ILLEGAL_INPUT);
584  cpl_ensure_code (spectrum_table, CPL_ERROR_ILLEGAL_INPUT);
585  cpl_ensure_code (p2vm_table, CPL_ERROR_ILLEGAL_INPUT);
586 
587  /* Get the number of regions */
588  int n_region = cpl_table_get_nrow (detector_table);
589  int npol = n_region > 24 ? npol = 2 : 1;
590 
591  /* Get the oiwave_tables */
592  cpl_table ** oiwave_tables = gravi_data_get_oiwave_tables (p2vm_map, type_data, npol);
593 
594  /* Get the number of waves */
595  int nwave = cpl_table_get_nrow (oiwave_tables[0]);
596 
597  /* Get the P2VM column (where to store the data) */
598  cpl_array ** transmission, ** coherence, ** phase, ** norma_m;
599  coherence = cpl_table_get_data_array (p2vm_table, "COHERENCE");
600  phase = cpl_table_get_data_array (p2vm_table, "PHASE");
601  norma_m = cpl_table_get_data_array (p2vm_table, "C MATRIX");
602  transmission = cpl_table_get_data_array (p2vm_table, "TRANSMISSION");
603 
604  /* Get if a single telescope or baseline is open */
605  int tel = -1, base = -1;
606  if (gravi_check_shutter (preproc_header,1,0,0,0)) tel = 0;
607  if (gravi_check_shutter (preproc_header,0,1,0,0)) tel = 1;
608  if (gravi_check_shutter (preproc_header,0,0,1,0)) tel = 2;
609  if (gravi_check_shutter (preproc_header,0,0,0,1)) tel = 3;
610  if (gravi_check_shutter (preproc_header,1,1,0,0)) base = 0;
611  if (gravi_check_shutter (preproc_header,1,0,1,0)) base = 1;
612  if (gravi_check_shutter (preproc_header,1,0,0,1)) base = 2;
613  if (gravi_check_shutter (preproc_header,0,1,1,0)) base = 3;
614  if (gravi_check_shutter (preproc_header,0,1,0,1)) base = 4;
615  if (gravi_check_shutter (preproc_header,0,0,1,1)) base = 5;
616  cpl_ensure_code (tel>=0 || base>=0, CPL_ERROR_ILLEGAL_INPUT);
617 
618  /*
619  * A single telescope is open
620  */
621  if (tel >= 0) {
622  valid_trans[type_data][tel] = 1;
623 
624  cpl_msg_info (cpl_func, "Compute the transmission of "
625  "tel %d for %s", tel+1, GRAVI_TYPE(type_data));
626 
627  /* Init for integration */
628  cpl_image * imgflux = NULL;
629  cpl_image ** spectrum_img;
630  spectrum_img = cpl_calloc (n_region,sizeof(cpl_image*));
631 
632  for (cpl_size region = 0; region < n_region; region++){
633 
634  /* Get the data of this region */
635  cpl_imagelist * spectrum_imglist;
636  spectrum_imglist = gravi_imagelist_wrap_column (spectrum_table, GRAVI_DATA[region]);
637 
638  /* Compute the median over the rows = un-normalized transmission */
639  spectrum_img[region] = cpl_imagelist_collapse_median_create (spectrum_imglist);
640  gravi_imagelist_unwrap_images (spectrum_imglist);
641 
642  /* Compute the total flux for this telescope (sum over all regions)
643  * for further normalization */
644  if (imgflux == NULL)
645  imgflux = cpl_image_duplicate (spectrum_img[region]);
646  else
647  cpl_image_add (imgflux, spectrum_img[region]);
648  } /* loop on regions */
649 
650  /* Compute the total flux over the spectrum */
651  double max_flux = cpl_image_get_flux (imgflux);
652 
653  /* Set the normalized transmission */
654  for (cpl_size region = 0; region < n_region; region++){
655 
656  /* Normalisation of the transmission*/
657  cpl_image_divide_scalar (spectrum_img[region], max_flux);
658 
659  /* Set the transmission in the 2D map of transmission */
660  for (cpl_size wave = 0; wave < nwave; wave++) {
661  double value = cpl_image_get (spectrum_img[region], wave+1, 1, &nv);
662  cpl_array_set (transmission[region],
663  wave + nwave * tel, value);
664  }
665 
666  CPLCHECK_MSG ("Cannot compute transmission");
667  }/* End loop on region */
668 
669  FREELOOP (cpl_image_delete, spectrum_img, n_region);
670  FREE (cpl_image_delete, imgflux);
671  } /* valid test for transmission (single tel) */
672 
673 
674  /*
675  * One pair is open
676  */
677  if (base >= 0) {
678  int tel1 = GRAVI_BASE_TEL[base][0];
679  int tel2 = GRAVI_BASE_TEL[base][1];
680 
681  valid_pair[type_data][base] = 1;
682 
683  cpl_msg_info(cpl_func, "Compute the coherence and "
684  "phase of pair (%d,%d) for %s", tel1+1,
685  tel2+1, GRAVI_TYPE(type_data));
686 
687  /* Get the size of the vectors */
688  int nrow = cpl_table_get_nrow (spectrum_table);
689 
690  /*
691  * Recover the mean OPD modulation (averaved over pol
692  * and channels) using the ellipses. In [m]
693  */
694 
695  cpl_vector * mean_opd;
696  mean_opd = gravi_ellipse_meanopd_create (spectrum_table, detector_table,
697  oiwave_tables, NULL, base);
698  CPLCHECK_MSG ("Cannot compute opd");
699 
700  /*
701  * Compute the P2VM complex coherence for each channel and region
702  */
703 
704  for (cpl_size wave = 0; wave < nwave; wave++){
705 
706  /* Compute envelope from OPD for this channel
707  * Wavelength is hard-coded in the enveloppe, thus
708  * doesn' depend on polarisation */
709  cpl_vector * envelope_vector = gravi_compute_envelope (mean_opd, wave, nwave);
710 
711  /* Fill a matrix with nrows and 3 columns:
712  * [ 1.0, sin(2.pi.opd/lbd)*env(opd), cos(2.pi.opd/lbd)*env(opd) ]
713  * different for each polarisation */
714  cpl_matrix ** inv_matrixes = cpl_calloc (npol, sizeof(cpl_matrix *));
715 
716  for (int pol = 0; pol < npol; pol ++) {
717  cpl_matrix * model_matrix = cpl_matrix_new (nrow, 3);
718 
719  for (cpl_size row = 0; row < nrow; row++) {
720  cpl_matrix_set (model_matrix, row, 0, 1.0);
721  double lambda = cpl_table_get (oiwave_tables[pol], "EFF_WAVE", wave, NULL);
722  double phi = cpl_vector_get (mean_opd, row) / lambda * CPL_MATH_2PI;
723  double enveloppe = cpl_vector_get (envelope_vector, row);
724  cpl_matrix_set (model_matrix, row, 1, sin(phi)*enveloppe);
725  cpl_matrix_set (model_matrix, row, 2, cos(phi)*enveloppe);
726  }
727 
728  /* Invers the matrix of the carrying-wave */
729  inv_matrixes[pol] = gravi_matrix_invertSV_create (model_matrix);
730  FREE (cpl_matrix_delete, model_matrix);
731  }
732 
733  /* Loop on region to apply this fit */
734  for (cpl_size region = 0; region < n_region; region ++){
735 
736  int pol = gravi_region_get_pol (detector_table, region);
737 
738  cpl_vector * y_window;
739  y_window = gravi_table_get_vector (spectrum_table, wave,
740  GRAVI_DATA[region]);
741 
742  /* Vector init_val contains the best fit coeficient of the fit,
743  * that is the mean flux c and the complex coherence flux,
744  * computed as: init_val = inv_matrix * data
745  * FIXME: can be done in CPL ? */
746  cpl_vector * init_val = cpl_vector_new(3);
747 
748  for (cpl_size j = 0; j < 3; j++){
749  double comp = 0;
750  for (cpl_size i = 0; i < nrow; i++){
751  comp += cpl_matrix_get (inv_matrixes[pol], j, i) * cpl_vector_get (y_window, i);
752  }
753  cpl_vector_set (init_val, j, comp);
754  }
755 
756  /* Compute the P2VM coherence [e]. */
757  double coherence_fit =
758  sqrt( pow (cpl_vector_get(init_val, 2), 2) +
759  pow (cpl_vector_get(init_val, 1), 2));
760 
761  cpl_array_set (coherence[region], wave + nwave *
762  base, coherence_fit);
763 
764  /* Compute the P2VM phase [rad] */
765  double phase_fit;
766  phase_fit = atan2( cpl_vector_get(init_val, 2),
767  cpl_vector_get(init_val, 1));
768 
769  cpl_array_set (phase[region], wave + nwave * base,
770  phase_fit);
771 
772  /* Save the c parameter for normalisation purpose */
773  cpl_array_set (norma_m[region], wave + nwave * base,
774  cpl_vector_get (init_val,0));
775 
776  FREE (cpl_vector_delete, init_val);
777  FREE (cpl_vector_delete, y_window);
778  } /* loop on region */
779 
780  FREELOOP (cpl_matrix_delete, inv_matrixes, npol);
781  FREE (cpl_vector_delete, envelope_vector);
782  } /* loop on wave */
783 
784  FREE (cpl_vector_delete, mean_opd);
785  } /* End case valid_pair (baseline) */
786 
787  FREE (cpl_free, oiwave_tables);
788 
789  /* If an error is catched */
790  CPLCHECK_MSG ("Cannot compute the P2VM");
791 
792  } /* Loop on type_data SC/FT */
793 
794  gravi_msg_function_exit(1);
795  return CPL_ERROR_NONE;
796 }
797 
798 
799 /*----------------------------------------------------------------------------*/
834 /*----------------------------------------------------------------------------*/
835 
836 cpl_error_code gravi_p2vm_normalisation (gravi_data * p2vm_map,
837  int ** valid_trans,
838  int ** valid_pair )
839 {
840  int ntel = 4, n_base = 6;
841  int nv = 0;
842 
843  /* Message and timer */
844  gravi_msg_function_start(1);
845  cpl_ensure_code (p2vm_map, CPL_ERROR_NULL_INPUT);
846  cpl_ensure_code (valid_trans, CPL_ERROR_NULL_INPUT);
847  cpl_ensure_code (valid_pair, CPL_ERROR_NULL_INPUT);
848 
849  cpl_propertylist * p2vm_header = gravi_data_get_header (p2vm_map);
850 
851  /*
852  * Loop on FT and SC
853  */
854  for (int type_data = 0; type_data < 2; type_data ++){
855 
856  /* Check if this data is present */
857  if (!gravi_data_has_p2vm (p2vm_map, type_data)) {
858  cpl_msg_info (cpl_func,"No data for %s, skip it", GRAVI_TYPE(type_data));
859  continue;
860  }
861 
862  cpl_msg_info (cpl_func, "Normalisation of P2VM for %s",
863  GRAVI_TYPE(type_data));
864 
865  /* Load P2VM and detector tables */
866  cpl_table * p2vm_table, * detector_table;
867  detector_table = gravi_data_get_imaging_detector (p2vm_map, type_data);
868  p2vm_table = gravi_data_get_p2vm_data (p2vm_map, type_data);
869 
870  /* Get info */
871  cpl_size n_region = cpl_table_get_nrow (detector_table);
872  int n_pol = n_region > 24 ? 2 : 1;
873 
874  /* Get the number of wave */
875  cpl_table * oiwave_table;
876  oiwave_table = gravi_data_get_oi_wave (p2vm_map, type_data, 0, n_pol);
877  cpl_size nwave = cpl_table_get_nrow (oiwave_table);
878  cpl_ensure_code (nwave, CPL_ERROR_ILLEGAL_INPUT);
879 
880  /* Get the P2VM column (where to store the data) */
881  cpl_array ** transmission, ** coherence, ** phase;
882  coherence = cpl_table_get_data_array (p2vm_table, "COHERENCE");
883  phase = cpl_table_get_data_array (p2vm_table, "PHASE");
884  transmission = cpl_table_get_data_array (p2vm_table, "TRANSMISSION");
885 
886  /*
887  * Set P2VM A-phase to zero
888  */
889 
890  /* Loop on polarisation and baseline */
891  for (int pol = 0; pol < n_pol; pol++) {
892  for (int base = 0; base < 6; base++){
893 
894  /* Check if this baseline is computed */
895  if ( !valid_pair[type_data][base]) continue;
896 
897  /* Get the index of the k band ABCD */
898  int iA = gravi_get_region (detector_table, base, 'A', pol);
899  int iB = gravi_get_region (detector_table, base, 'B', pol);
900  int iC = gravi_get_region (detector_table, base, 'C', pol);
901  int iD = gravi_get_region (detector_table, base, 'D', pol);
902 
903  for (cpl_size i = 0; i < cpl_array_get_size(phase[0]); i++){
904 
905  double valA = cpl_array_get (phase[iA], i, NULL);
906  cpl_array_set (phase[iA], i, 0.0);
907 
908  double valB = cpl_array_get (phase[iB], i, NULL) - valA;
909  if (valB < 0) valB += CPL_MATH_2PI;
910  cpl_array_set (phase[iB], i, valB);
911 
912  double valC = cpl_array_get (phase[iC], i, NULL) - valA;
913  if (valC < 0) valC += CPL_MATH_2PI;
914  cpl_array_set (phase[iC], i, valC);
915 
916  double valD = cpl_array_get (phase[iD], i, NULL) - valA;
917  if (valD < 0) valD += CPL_MATH_2PI;
918  cpl_array_set (phase[iD], i, valD);
919 
920  CPLCHECK_MSG ("Cannot unwrap AC and BD of P2VM");
921  } /* End loop on wave */
922  } /* end loop on baseline */
923  } /* end loop on polarisation */
924 
925  CPLCHECK_MSG ("Cannot compute P2VM");
926 
927  /*
928  * Normalisation of the P2VM transmission
929  */
930 
931  /* Compute the mean transmission */
932  int ntrans = cpl_array_get_size (transmission[0]);
933  cpl_array * mean_transmission = cpl_array_new (ntrans, CPL_TYPE_FLOAT);
934  cpl_array_fill_window (mean_transmission, 0, ntrans, 0.);
935 
936  for (cpl_size region = 0; region < n_region; region++) {
937  cpl_array_add (mean_transmission,transmission[region]);
938  }
939  cpl_array_divide_scalar (mean_transmission, n_region);
940 
941  /* Normalized the transmissions */
942  for (cpl_size region = 0; region < n_region; region++){
943  cpl_array_divide (transmission[region], mean_transmission);
944  }
945  FREE (cpl_array_delete, mean_transmission);
946 
947  /*
948  * Normalisation of the P2VM coherence
949  */
950 
951  /* Init quantities to compute mean flux per tel */
952  double mean_flux[4] = {0.0,0.0,0.0,0.0};
953  int n_flux[4] = {0,0,0,0};
954 
955  /* Loop on baseline */
956  for (int base = 0; base < 6; base++) {
957  int tel0 = GRAVI_BASE_TEL[base][0];
958  int tel1 = GRAVI_BASE_TEL[base][1];
959 
960  /* Compute the input flux solving c=TI for each wave */
961  for (cpl_size wave = 0; wave < nwave; wave++){
962 
963  /* Construction of the transmission matrix */
964  cpl_matrix * matrix_T = cpl_matrix_new (n_region, 4);
965 
966  /* Get index of each tranmission on the matrix */
967  cpl_vector * vector_c = gravi_table_get_vector (p2vm_table, wave+nwave*base, "C MATRIX");
968  cpl_matrix * matrix_c = cpl_matrix_new (n_region, 1);
969  for(cpl_size region = 0; region < n_region; region++) {
970  cpl_matrix_set (matrix_c, region, 0, cpl_vector_get (vector_c, region));
971  for (int tel = 0; tel < ntel; tel++){
972  cpl_matrix_set (matrix_T, region, tel,
973  cpl_array_get (transmission[region],
974  tel*nwave+wave ,&nv));
975  }
976  } /* End loop on region */
977  FREE (cpl_vector_delete, vector_c);
978 
979  /* Compute the matrix_I */
980  cpl_errorstate prestate = cpl_errorstate_get();
981 
982  cpl_matrix * matrix_I = cpl_matrix_solve_normal (matrix_T, matrix_c);
983 
984  /* Check if singular value */
985  if (! strcmp("Singular matrix", cpl_error_get_message())){
986  cpl_msg_warning(cpl_func, "matrix_c or matrix_T "
987  "are singular for tel1 = %d tel2 = %d and wave = %lld",
988  tel0, tel1, wave);
989  cpl_errorstate_set (prestate);
990  cpl_matrix_delete (matrix_T);
991  cpl_matrix_delete (matrix_I);
992  cpl_matrix_delete (matrix_c);
993  } else {
994 
995  /* Store the total flux for each tel (will be used to compute
996  * the mean over wave, output and files) in [e/dit/output] */
997  mean_flux[tel0] += cpl_matrix_get (matrix_I, tel0, 0);
998  mean_flux[tel1] += cpl_matrix_get (matrix_I, tel1, 0);
999  n_flux[tel0] ++;
1000  n_flux[tel1] ++;
1001 
1002  /* Get the coefficient of normalisation */
1003  double F0 = cpl_matrix_get (matrix_I, tel0, 0);
1004  double F1 = cpl_matrix_get (matrix_I, tel1, 0);
1005  double coeff = sqrt (fabs(F0*F1));
1006 
1007  /* Normalisation */
1008  if (coeff !=0 ) {
1009  for (cpl_size region = 0; region < n_region; region++){
1010  double value = cpl_array_get (coherence[region],
1011  wave+nwave*base, &nv);
1012  cpl_array_set (coherence[region],
1013  wave+nwave*base,
1014  value / coeff);
1015  }
1016  }
1017 
1018  FREE (cpl_matrix_delete, matrix_c);
1019  FREE (cpl_matrix_delete, matrix_I);
1020  FREE (cpl_matrix_delete, matrix_T);
1021  }
1022  } /* end loop on WAVE */
1023  } /* end loop on baseline */
1024 
1025 
1026 
1027  /*
1028  * Compute the QC parameters for the mean flux
1029  */
1030  char qc_name[90];
1031  for (int tel = 0; tel<4; tel++ ) {
1032  cpl_msg_info (cpl_func, "Mean flux tel%i = %f (n=%i)", tel, mean_flux[tel] / n_flux[tel], n_flux[tel]);
1033  sprintf (qc_name, "ESO QC FLUX_%s%i AVG", GRAVI_TYPE(type_data), tel);
1034  cpl_propertylist_append_double (p2vm_header, qc_name, mean_flux[tel] / n_flux[tel]);
1035  cpl_propertylist_set_comment (p2vm_header, qc_name, "[e/DIT/chanel/output/file] mean flux");
1036  }
1037 
1038 
1039  /* Compute the QC parameters:
1040  * - Mean Coherence
1041  * - Mean of rms of Coherence
1042  * - Mean of rms of Phase */
1043 
1044  /* Allocate stat tables */
1045  cpl_array * sig_phi_arr = cpl_array_new(n_region, CPL_TYPE_DOUBLE);
1046  cpl_array * sig_coh_arr = cpl_array_new(n_region, CPL_TYPE_DOUBLE);
1047  cpl_array * mean_coh_arr = cpl_array_new(n_region, CPL_TYPE_DOUBLE);
1048  cpl_array * mean_coh_base_arr = cpl_array_new(n_base, CPL_TYPE_DOUBLE);
1049  cpl_array * min_coh_base_arr = cpl_array_new(n_base, CPL_TYPE_DOUBLE);
1050  cpl_array * mean_trans_arr = cpl_array_new(n_region, CPL_TYPE_DOUBLE);
1051  cpl_array * sig_transdiff_arr = cpl_array_new(n_region, CPL_TYPE_DOUBLE);
1052 
1053  cpl_array_fill_window (mean_coh_base_arr, 0, n_base, 0);
1054  cpl_array_fill_window (min_coh_base_arr, 0, n_base, 10);
1055 
1056  /* Compute the values per region */
1057  for (cpl_size region = 0; region < n_region; region ++ ) {
1058 
1059  /* Get the base of region */
1060  int base = gravi_region_get_base (detector_table, region);
1061  int tel0 = GRAVI_BASE_TEL[base][0];
1062  int tel1 = GRAVI_BASE_TEL[base][1];
1063 
1064  /* Get quantities for this region and base */
1065  cpl_array * coh_region = cpl_array_extract (coherence[region],
1066  nwave*base, nwave);
1067  cpl_array * trans_tel1 = cpl_array_extract (transmission[region],
1068  nwave*tel0, nwave);
1069  cpl_array * trans_tel2 = cpl_array_extract (transmission[region],
1070  nwave*tel1, nwave);
1071  cpl_array * ph_region = cpl_array_extract (phase[region],
1072  nwave*base, nwave);
1073 
1074  /* Compute spectral averaged quantities */
1075  cpl_array_set (mean_coh_arr, region,
1076  cpl_array_get_mean (coh_region));
1077 
1078  cpl_array_set (sig_coh_arr, region,
1079  cpl_array_get_stdev (coh_region));
1080 
1081  cpl_array_set (mean_trans_arr, region,
1082  (cpl_array_get_mean (trans_tel1) +
1083  cpl_array_get_mean (trans_tel2)) /2);
1084 
1085  cpl_array_set (sig_phi_arr, region,
1086  cpl_array_get_stdev (ph_region));
1087 
1088  cpl_array * diff_trans;
1089  diff_trans = cpl_array_duplicate (trans_tel1);
1090  cpl_array_subtract (diff_trans, trans_tel2);
1091  cpl_array_set (sig_transdiff_arr, region,
1092  cpl_array_get_stdev (diff_trans));
1093  cpl_array_delete (diff_trans);
1094 
1095  /* Normalize coherence with trans */
1096  cpl_array_power (trans_tel1, 0.5);
1097  cpl_array_power (trans_tel2, 0.5);
1098  cpl_array_divide (coh_region, trans_tel1);
1099  cpl_array_divide (coh_region, trans_tel2);
1100  cpl_array_divide_scalar (coh_region, 2.);
1101 
1102  /* Compute averaged quantities per baseline */
1103  cpl_array_set (mean_coh_base_arr, base,
1104  cpl_array_get (mean_coh_base_arr, base, NULL) +
1105  cpl_array_get_mean (coh_region)/(n_region/6));
1106 
1107  /* Compute percentil */
1108  double min_percentile = gravi_array_get_quantile (coh_region, 0.05);
1109 
1110  if (cpl_array_get(min_coh_base_arr, base, NULL) > min_percentile)
1111  cpl_array_set(min_coh_base_arr, base, min_percentile);
1112 
1113  /* Delete variables */
1114  cpl_array_delete (coh_region);
1115  cpl_array_delete (trans_tel2);
1116  cpl_array_delete (trans_tel1);
1117  cpl_array_delete (ph_region);
1118 
1119  } /* End loop on regions */
1120 
1121  CPLCHECK_MSG ("Cannot compute_the averages values per region");
1122 
1123  /* Compute the full-averaged QC */
1124  double mean_coh, sig_coh, sig_phi;
1125  mean_coh = cpl_array_get_mean (mean_coh_arr) /
1126  (2*cpl_array_get_mean (mean_trans_arr));
1127  sig_coh = cpl_array_get_mean (sig_coh_arr) /
1128  (2*cpl_array_get_mean (mean_trans_arr));
1129  sig_phi = cpl_array_get_mean (sig_phi_arr);
1130  CPLCHECK_MSG ("Cannot compute averaged values");
1131 
1132  /* Set these full-averaged QC parameters */
1133  cpl_propertylist_update_double (p2vm_header, (type_data)?QC_MEANCOH_FT:QC_MEANCOH_SC,
1134  mean_coh);
1135  cpl_propertylist_update_double (p2vm_header, (type_data)?QC_RMSCOH_FT:QC_RMSCOH_SC,
1136  sig_coh);
1137  cpl_propertylist_update_double (p2vm_header, (type_data)?QC_RMSPHASE_FT:QC_RMSPHASE_SC,
1138  sig_phi);
1139  cpl_msg_info (cpl_func, "QC %s COH_AVG = %e COH_RMS %e PHASE_RMS = %e",
1140  GRAVI_TYPE(type_data), mean_coh, (sig_coh), sig_phi);
1141 
1142  /* QC per baseline */
1143  for (int base=0; base< n_base; base++){
1144  sprintf (qc_name, "ESO QC P2VM_COHERENCE_%s%s", GRAVI_TYPE(type_data), GRAVI_BASE_NAME[base]);
1145  cpl_propertylist_update_double (p2vm_header, qc_name,
1146  cpl_array_get (mean_coh_base_arr, base, NULL));
1147  cpl_propertylist_set_comment (p2vm_header, qc_name,
1148  "Avg coh. over lbd per baseline");
1149 
1150  sprintf (qc_name, "ESO QC P2VM_MINCOHERENCE_%s%s", GRAVI_TYPE(type_data), GRAVI_BASE_NAME[base]);
1151  cpl_propertylist_update_double (p2vm_header, qc_name,
1152  cpl_array_get (min_coh_base_arr, base, NULL));
1153  cpl_propertylist_set_comment (p2vm_header, qc_name,
1154  "Min coh. (5 perc) over lbd per baseline");
1155  }
1156  CPLCHECK_MSG ("Cannot append QC params");
1157 
1158  FREE (cpl_array_delete, sig_phi_arr);
1159  FREE (cpl_array_delete, sig_coh_arr);
1160  FREE (cpl_array_delete, mean_coh_arr);
1161  FREE (cpl_array_delete, mean_trans_arr);
1162  FREE (cpl_array_delete, sig_transdiff_arr);
1163  FREE (cpl_array_delete, mean_coh_base_arr);
1164  FREE (cpl_array_delete, min_coh_base_arr);
1165 
1166  } /* end loop on FT and SC */
1167 
1168  gravi_msg_function_exit(1);
1169  return CPL_ERROR_NONE;
1170 }
1171 
1172 /*----------------------------------------------------------------------------*/
1193 /*----------------------------------------------------------------------------*/
1194 
1195 cpl_error_code gravi_p2vm_phase_correction (gravi_data * p2vm_map,
1196  gravi_data * p2vmred_data,
1197  int full_phase)
1198 {
1199  gravi_msg_function_start(1);
1200  cpl_ensure_code (p2vm_map, CPL_ERROR_NULL_INPUT);
1201  cpl_ensure_code (p2vmred_data, CPL_ERROR_NULL_INPUT);
1202 
1203  int nv;
1204 
1205  /* Get the header */
1206  cpl_propertylist * p2vmred_header = gravi_data_get_header (p2vmred_data);
1207 
1208  /*
1209  * Loop on FT and SC
1210  */
1211  for (int type_data = 0; type_data < 2; type_data ++) {
1212 
1213  /* Check if P2VM has this type */
1214  if (!gravi_data_has_p2vm (p2vm_map, type_data)) {
1215  cpl_msg_info (cpl_func,"No data for %s in P2VM, skip it", GRAVI_TYPE(type_data));
1216  continue;
1217  }
1218 
1219  cpl_msg_info (cpl_func, "Calibrate the internal phase of %s (%s)",
1220  GRAVI_TYPE(type_data),full_phase?"full phases":"closure phases");
1221 
1222  /* Where the instrumental phase will be stored */
1223  cpl_array ** visphase = cpl_calloc (12, sizeof(cpl_array*));
1224 
1225  /* Loop on polarisation */
1226  int npol = gravi_pfits_get_pola_num (p2vmred_header, type_data);
1227  for ( int pol= 0 ; pol < npol ; pol++ ) {
1228 
1229  cpl_msg_info (cpl_func, "Compute correction for pol %i over %i", pol+1, npol);
1230 
1231  /* Get the OI_WAVE and the OI_VIS tables */
1232  cpl_table * oi_wave = gravi_data_get_oi_wave (p2vmred_data, type_data, pol, npol);
1233  cpl_table * oi_vis = gravi_data_get_oi_vis (p2vmred_data, type_data, pol, npol);
1234  cpl_array * sigma = gravi_table_create_sigma_array (oi_wave);
1235  cpl_size nrow = cpl_table_get_nrow (oi_vis) / 6;
1236 
1237  /* Get a pointer of the VISDATA column */
1238  cpl_array ** visdata = cpl_table_get_data_array (oi_vis, "VISDATA");
1239  float * wavedata = cpl_table_get_data_float (oi_wave, "EFF_WAVE");
1240  cpl_size nwave = cpl_array_get_size (visdata[0]);
1241  cpl_size wave0 = nwave/2;
1242 
1243  /*
1244  * Compute OPLs of the 4 beam as the phase of the mean channel
1245  * for the baselines 01, 02, 03, in [rad]
1246  */
1247  cpl_msg_debug (cpl_func,"Compute OPLs of beam");
1248 
1249  double ** opl = cpl_malloc (sizeof(double*) * nrow);
1250  for (cpl_size row=0 ; row<nrow ; row++) {
1251  opl[row] = cpl_malloc (sizeof(double) * 4);
1252  opl[row][0] = 0.0;
1253  for ( int base= 1 ; base < 4 ; base++ ) {
1254  opl[row][base] = carg (cpl_array_get_complex (visdata[row * 6 + base-1], wave0, &nv));
1255  }
1256  } /* End compute OPLs */
1257 
1258  /* Unwrap OPLs */
1259  for ( int base= 1 ; base < 4 ; base++ ) {
1260  double wrap = 0.0, ref = opl[0][base];
1261  for (cpl_size row=1 ; row<nrow ; row++) {
1262  if ( (opl[row][base] - ref) < -CPL_MATH_PI ) wrap += 2.*CPL_MATH_PI;
1263  if ( (opl[row][base] - ref) > CPL_MATH_PI ) wrap -= 2.*CPL_MATH_PI;
1264  ref = opl[row][base];
1265  opl[row][base] += wrap;
1266  }
1267  } /* End unwrap OPLs */
1268 
1269  /* Remove mean OPLs */
1270  for ( int base= 1 ; base < 4 ; base++ ) {
1271  double mean = 0.0;
1272  for (cpl_size row=0 ; row<nrow ; row++) mean += opl[row][base];
1273  for (cpl_size row=0 ; row<nrow ; row++) opl[row][base] -= mean / nrow;
1274  }
1275 
1276  CPLCHECK_MSG("Cannot compute OPL");
1277 
1278  /*
1279  * Coherent integration of visdata of each baseline with the current P2VM
1280  */
1281  cpl_msg_debug (cpl_func,"Compute coherent integration of VISDATA");
1282 
1283  for ( int base = 0 ; base < 6 ; base++ ) {
1284  /* Allocate memory for visphase */
1285  visphase[base + pol*6] = cpl_array_new (nwave, CPL_TYPE_FLOAT_COMPLEX);
1286  cpl_array_fill_window_complex (visphase[base + pol*6], 0, nwave, 0.0 * I + 0.0);
1287 
1288  /* Coherent integration of the visdata */
1289  for (cpl_size row=0 ; row<nrow ; row++) {
1290  double x = opl[row][GRAVI_BASE_TEL[base][1]] - opl[row][GRAVI_BASE_TEL[base][0]];
1291  for (cpl_size wave=0; wave<nwave; wave++)
1292  cpl_array_set_complex (visphase[base + pol*6], wave,
1293  cpl_array_get_complex (visphase[base + pol*6], wave, &nv) +
1294  cpl_array_get_complex (visdata[row * 6 + base], wave, &nv) *
1295  cexp (-1.*I * x * wavedata[wave0] / wavedata[wave]) );
1296  } /* End loop on rows and waves */
1297 
1298  /* Normalize to pure phasor, to give equal weight to all channels */
1299  // gravi_array_normalize_complex (visphase[base + pol*6]);
1300 
1301  } /* End loop on base */
1302 
1303 
1304  /*
1305  * Force the phase correction of the 3 first baselines to be zero (01,02,03).
1306  * Update other baselines to keep the measured closure phases. Thus
1307  * we only correct chromatic closure phases, not chromatic phase.
1308  * Here we *assume* the 3 first baseline are {01, 02, 03}
1309  */
1310 
1311  cpl_array ** ref = cpl_malloc (4 * sizeof(cpl_array*));
1312  ref[0] = cpl_array_new (nwave, CPL_TYPE_DOUBLE_COMPLEX);
1313  cpl_array_fill_window_complex (ref[0], 0, nwave, 0.0 * I + 1.0);
1314 
1315  if (full_phase == 0) {
1316 
1317  cpl_msg_info (cpl_func,"Force phiA(lbd) to be zero for baselines (01,02,03) = keep only closures");
1318 
1319  for (int base = 0; base<3 ; base++)
1320  ref[base+1] = cpl_array_duplicate (visphase[base + pol*6]);
1321 
1322  } else if (full_phase == 1) {
1323 
1324  cpl_msg_info (cpl_func,"Force phiA(lbd) to have zero mean and minimum GD for baselines (01,02,03)");
1325 
1326  for (int base = 0; base<3 ; base++) {
1327  double gd = 0.0;
1328  gravi_array_get_group_delay_loop (&visphase[base + pol*6], sigma,
1329  &gd, 1, 2e-3, CPL_FALSE);
1330  cpl_array * tmp = cpl_array_duplicate (visphase[base + pol*6]);
1331  gravi_array_multiply_phasor (tmp, -CPL_MATH_2PI*I*gd, sigma);
1332  gd += carg (cpl_array_get_mean_complex (tmp)) / CPL_MATH_2PI / cpl_array_get_mean (sigma);
1333  cpl_array_delete (tmp);
1334  ref[base+1] = gravi_array_cexp (CPL_MATH_2PI * I * gd, sigma);
1335  }
1336 
1337  } else if (full_phase == 2) {
1338 
1339  cpl_msg_info (cpl_func,"Force phiA(lbd) to have zero-GD for baselines (01,02,03)");
1340 
1341  for (int base = 0; base<3 ; base++) {
1342  double gd = 0.0;
1343  gravi_array_get_group_delay_loop (&visphase[base + pol*6], sigma,
1344  &gd, 1, 2e-3, CPL_FALSE);
1345  ref[base+1] = gravi_array_cexp (CPL_MATH_2PI * I * gd, sigma);
1346  }
1347  } else {
1348  return cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT, "Option for phase calibration out of range");
1349  }
1350 
1351  /* Remove the corresponding REF in each base
1352  * visphase_ij *= ref_i * conj(ref_j) */
1353  for ( int base = 0 ; base < 6 ; base++ ) {
1354  cpl_array_multiply (visphase[base + pol*6], ref[GRAVI_BASE_TEL[base][0]]);
1355  gravi_array_multiply_conj (visphase[base + pol*6], ref[GRAVI_BASE_TEL[base][1]]);
1356  }
1357 
1358  FREELOOP (cpl_array_delete, ref, 4);
1359  FREELOOP (cpl_free, opl, nrow);
1360  FREE (cpl_array_delete, sigma);
1361  } /* End loop on pol */
1362 
1363  CPLCHECK_MSG("Cannot perform coherent integration");
1364 
1365  /*
1366  * Apply these phase corrections to the P2VM phases
1367  */
1368  cpl_msg_info (cpl_func,"Apply correction to P2VM phases");
1369 
1370  cpl_table * p2vm = gravi_data_get_p2vm_data (p2vm_map, type_data);
1371  cpl_array ** phase = cpl_table_get_data_array (p2vm, "PHASE");
1372  cpl_size nreg = cpl_table_get_nrow (p2vm);
1373  cpl_size nwave = cpl_array_get_size (visphase[0]);
1374 
1375  /* Loop on region */
1376  for (cpl_size reg=0; reg<nreg; reg++) {
1377 
1378  /* Get the polarisation and base of this region */
1379  int base = gravi_region_get_base (p2vm, reg);
1380  int pol = gravi_region_get_pol (p2vm, reg);
1381 
1382  /* Subtract the corresponding phase */
1383  for (cpl_size wave=0; wave<nwave;wave++) {
1384  double phi = carg ( cexp (1.*I*cpl_array_get (phase[reg], wave + nwave * base, &nv)) *
1385  conj(cpl_array_get_complex (visphase[base + pol*6], wave, &nv) ));
1386  cpl_array_set (phase[reg], wave + nwave * base, (phi>=0.0?phi:phi+CPL_MATH_2PI));
1387  }
1388 
1389  } /* End loop on region */
1390 
1391  CPLCHECK_MSG("Cannot correct P2VM phases");
1392  FREELOOP (cpl_array_delete, visphase, 12);
1393 
1394  } /* End loop on FT and SC */
1395 
1396  gravi_msg_function_exit(1);
1397  return CPL_ERROR_NONE;
1398 }
1399 
1400 /*----------------------------------------------------------------------------*/
1414 /*----------------------------------------------------------------------------*/
1415 
1416 cpl_error_code gravi_p2vm_transmission (gravi_data * p2vm_map, gravi_data * p2vmred_data)
1417 {
1418  gravi_msg_function_start(1);
1419  cpl_ensure_code (p2vm_map, CPL_ERROR_NULL_INPUT);
1420  cpl_ensure_code (p2vmred_data, CPL_ERROR_NULL_INPUT);
1421 
1422  cpl_propertylist * p2vmred_header = gravi_data_get_header (p2vmred_data);
1423 
1424  /* Loop on SC / FT */
1425  for (int type_data = 0; type_data < 2; type_data ++) {
1426 
1427  /* Loop on polarisation */
1428  int npol = gravi_pfits_get_pola_num (p2vmred_header, type_data);
1429  for (int pol = 0; pol < npol; pol++) {
1430 
1431  cpl_msg_info (cpl_func, "Compute the internal transmission of %s (pol %i over %i)",
1432  GRAVI_TYPE(type_data), pol+1, npol);
1433 
1434  /* Get FLUX data */
1435  cpl_table * flux_tbl = gravi_data_get_oi_flux (p2vmred_data, type_data, pol, npol);
1436  cpl_array ** flux = cpl_table_get_data_array (flux_tbl, "FLUX");
1437  cpl_size nwave = cpl_array_get_size (flux[0]);
1438  cpl_size nrow = cpl_table_get_nrow (flux_tbl) / 4;
1439 
1440  /* Create OI_FLUX table */
1441  cpl_table * oi_flux = gravi_table_oi_create (nwave, 1, GRAVI_OI_FLUX_EXT);
1442  cpl_array * flux_mean = cpl_array_new (nwave, CPL_TYPE_DOUBLE);
1443 
1444  CPLCHECK_MSG("Cannot get data");
1445 
1446  for (int tel = 0; tel < 4; tel++) {
1447 
1448  /* Compute total flux for this tel */
1449  cpl_array_fill_window (flux_mean, 0, nwave, 0.0);
1450  for (cpl_size row = 0; row < nrow; row++) {
1451  cpl_array_add (flux_mean, flux[tel + row*4]);
1452  }
1453 
1454  /* Normalize to 1 */
1455  cpl_array_divide_scalar (flux_mean, cpl_array_get_mean (flux_mean));
1456 
1457  /* Set the transmission */
1458  cpl_table_set_array (oi_flux, "FLUX", tel, flux_mean);
1459 
1460  /* Set its uncertainty */
1461  cpl_array_fill_window (flux_mean, 0, nwave, 0.0);
1462  cpl_table_set_array (oi_flux, "FLUXERR", tel, flux_mean);
1463 
1464  } /* End loop on tel*/
1465 
1466  FREE (cpl_array_delete, flux_mean);
1467 
1468  /* Set this transmission to the output data
1469  * (need to duplicate header but strickly equal) */
1470  cpl_propertylist * plist = gravi_data_get_oi_flux_plist (p2vmred_data, type_data, pol, npol);
1471  plist = cpl_propertylist_duplicate (plist);
1472  gravi_data_add_table (p2vm_map, plist, NULL, oi_flux);
1473 
1474  CPLCHECK_MSG("Cannot set data");
1475  } /* End loop on pols */
1476  } /* End loop on SC/FT */
1477 
1478  gravi_msg_function_exit(1);
1479  return CPL_ERROR_NONE;
1480 }
1481 
gravi_data * gravi_data_new(int nb_ext)
Create an empty gravi_data.
Definition: gravi_data.c:102
int gravi_region_get_pol(cpl_table *imaging_detector, int region)
Return the polarisation id of a region.
Definition: gravi_utils.c:445
int gravi_region_get_base(cpl_table *imaging_detector, int region)
Return the base of a region.
Definition: gravi_utils.c:361
cpl_error_code gravi_data_copy_ext(gravi_data *output, gravi_data *input, const char *name)
Copy extensions from one data to another.
Definition: gravi_data.c:1325
cpl_vector * gravi_table_get_vector(cpl_table *spectrum_data, cpl_size index, const char *regname)
Create a vector from the row index of the column regname.
Definition: gravi_cpl.c:1870
cpl_error_code gravi_p2vm_transmission(gravi_data *p2vm_map, gravi_data *p2vmred_data)
Compute the flux normalisation in the P2VM.
Definition: gravi_p2vm.c:1416
cpl_array * gravi_array_cexp(double complex factor, const cpl_array *input)
Compute the complex exponention of an array: cexp (factor * input)
Definition: gravi_cpl.c:973
cpl_table ** gravi_data_get_oiwave_tables(gravi_data *data, int type_data, int npol)
Get pointer to the OI_WAVELENGTH tables of both polarisations.
Definition: gravi_data.c:2253
cpl_error_code gravi_compute_p2vm(gravi_data *p2vm_map, gravi_data *preproc_data, int **valid_trans, int **valid_pair, enum gravi_detector_type det_type)
The given output FITS file contain a p2vm table with the values of the transmission, phase and coherence extract using the p2vm matrix.
Definition: gravi_p2vm.c:547
cpl_error_code gravi_p2vm_phase_correction(gravi_data *p2vm_map, gravi_data *p2vmred_data, int full_phase)
Correct the phase of the P2VM from internal closure-phases.
Definition: gravi_p2vm.c:1195
cpl_error_code gravi_array_multiply_phasor(cpl_array *input, double complex factor, cpl_array *phase)
Multiply a REAL phase to a COMPLEX array, in-place: input = input * cexp (factor * phase) ...
Definition: gravi_cpl.c:995
cpl_table * gravi_data_get_table(gravi_data *self, const char *extname)
Return a pointer on a table extension by its EXTNAME.
Definition: gravi_data.c:1716
cpl_error_code gravi_array_get_group_delay_loop(cpl_array **input, cpl_array *sigma, double *gd, cpl_size nrow, double max_width, int verbose)
Optimized computation of GDELAY for a list of arrays.
Definition: gravi_cpl.c:1187
cpl_vector * gravi_compute_envelope(const cpl_vector *opd, int wave, int nwave)
Compute the envelope value.
Definition: gravi_utils.c:1081
int gravi_get_region(cpl_table *img_det, int base, char phase, int pol)
Find the region matching base, phase and pol.
Definition: gravi_utils.c:584
cpl_matrix * gravi_matrix_invertSV_create(cpl_matrix *a_in)
Invers a matrix with singular value decomposition.
Definition: gravi_cpl.c:2486
cpl_table * gravi_create_oiwave_table_ft(cpl_table *wave_table, cpl_table *detector_table, int pol)
Create a new oiwave table for FT.
Definition: gravi_p2vm.c:346
cpl_error_code gravi_imagelist_unwrap_images(cpl_imagelist *imglist)
Unwrap an imagelist an all its images.
Definition: gravi_cpl.c:1496
double gravi_array_get_quantile(cpl_array *arr, double thr)
Compute the value of the vector corresponding to the quantile &#39;thr&#39; (0 < thr < 1) ...
Definition: gravi_cpl.c:2146
cpl_propertylist * gravi_data_get_plist(gravi_data *self, const char *extname)
Get the propertylist from EXTNAME.
Definition: gravi_data.c:1684
cpl_vector * gravi_ellipse_meanopd_create(cpl_table *spectrum_table, cpl_table *detector_table, cpl_table **oiwave_tables, cpl_vector *guess_vector, int base)
Compute the OPD modulation of a baseline from spectrum.
cpl_table * gravi_create_p2vm_table(cpl_table *detector_table, int nwave)
Create a new p2vm table.
Definition: gravi_p2vm.c:110
cpl_table * gravi_create_oiwave_table_sc(cpl_table *wave_table, cpl_propertylist *header, gravi_data *wave_param)
Create a new oiwave table for SC.
Definition: gravi_p2vm.c:198
int gravi_wave_get_nlambda(cpl_table *wave_data, double lambda_min, double lambda_max)
Get the number of spectral element between lambdamin et lambdamax.
Definition: gravi_utils.c:611
cpl_error_code gravi_p2vm_normalisation(gravi_data *p2vm_map, int **valid_trans, int **valid_pair)
The given output FITS file contain a p2vm table with the values of the transmission, phase and coherence extract using the p2vm matrix so this function will normalise the p2vm map.
Definition: gravi_p2vm.c:836
cpl_error_code gravi_data_add_table(gravi_data *self, cpl_propertylist *plist, const char *extname, cpl_table *table)
Add a BINTABLE extension in gravi_data.
Definition: gravi_data.c:1909
gravi_data * gravi_create_p2vm(gravi_data *wave_map, gravi_data *wave_param)
Create a new P2VM map.
Definition: gravi_p2vm.c:414
cpl_table * gravi_table_oi_create(int nwave, int nrow, const char *oi_name)
Create the oi table (oi_vis, oi_vis2, oi_t3)
Definition: gravi_utils.c:153
cpl_imagelist * gravi_imagelist_wrap_column(cpl_table *table_data, const char *data_x)
Wrap a column array of a table into an imagelist.
Definition: gravi_cpl.c:1526