GRAVI Pipeline Reference Manual 1.9.0
Loading...
Searching...
No Matches
gravi_p2vm.c
Go to the documentation of this file.
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 * 14/03/2019 fix the selection for the medium wavelength range; remove unused DEFINE
42 */
43/*-----------------------------------------------------------------------------
44 Includes
45 -----------------------------------------------------------------------------*/
46
47#ifdef HAVE_CONFIG_H
48#include <config.h>
49#endif
50
51#include <cpl.h>
52#include <stdio.h>
53#include <string.h>
54#include <math.h>
55#include <time.h>
56#include <complex.h>
57
58#include "gravi_data.h"
59#include "gravi_dfs.h"
60#include "gravi_pfits.h"
61#include "gravi_cpl.h"
62
63#include "gravi_utils.h"
64#include "gravi_ellipse.h"
65#include "gravi_p2vm.h"
66
67
68/*-----------------------------------------------------------------------------
69 Private prototypes
70 -----------------------------------------------------------------------------*/
71
72cpl_table* gravi_create_p2vm_table (cpl_table * detector_table,
73 int nwave);
74
75cpl_table * gravi_create_oiwave_table_sc (cpl_table * wave_table,
76 cpl_propertylist * header,
77 gravi_data *wave_param);
78
79cpl_table * gravi_create_oiwave_table_ft (cpl_table * wave_table,
80 cpl_table * detector_table,
81 int pol);
82
83/*-----------------------------------------------------------------------------
84 Function code
85 -----------------------------------------------------------------------------*/
86
87/*---------------------------------------------------------------------------*/
101/*---------------------------------------------------------------------------*/
102
103cpl_table* gravi_create_p2vm_table (cpl_table * detector_table,
104 int nwave)
105{
107 cpl_ensure (detector_table, CPL_ERROR_NULL_INPUT, NULL);
108 cpl_ensure (nwave>0, CPL_ERROR_ILLEGAL_INPUT, NULL);
109
110 /* Get the number of region */
111 int ntel = 4;
112 int n_region = cpl_table_get_nrow (detector_table);
113
114 /* Creating the table with nRegion rows */
115 cpl_table * p2vm_table = cpl_table_new (n_region);
116
118 cpl_table_duplicate_column (p2vm_table, "REGNAME",
119 detector_table, "REGNAME");
121 cpl_table_new_column_array (p2vm_table,"TRANSMISSION", CPL_TYPE_FLOAT,
122 nwave * ntel);
124 cpl_table_new_column_array (p2vm_table,"COHERENCE", CPL_TYPE_FLOAT,
125 nwave * (ntel * (ntel - 1) / 2));
127 cpl_table_new_column_array (p2vm_table,"PHASE", CPL_TYPE_FLOAT,
128 nwave * (ntel * (ntel - 1) / 2));
130 cpl_table_new_column_array (p2vm_table,"C_MATRIX", CPL_TYPE_FLOAT,
131 nwave * (ntel * (ntel - 1) / 2));
132
133 /* Initialization of all these columns */
134 cpl_array * zero_array_transmission, * zero_array;
135 zero_array_transmission = cpl_array_new (nwave*ntel, CPL_TYPE_FLOAT);
136 cpl_array_fill_window_float (zero_array_transmission, 0, nwave*ntel, 0);
137
138 zero_array = cpl_array_new (nwave*(ntel*(ntel-1)/2),
139 CPL_TYPE_FLOAT );
140 cpl_array_fill_window_float (zero_array, 0,
141 nwave * (ntel * (ntel - 1) / 2), 0);
142
143 /* Fill in the arrays on the columns */
144 for (int i = 0; i < n_region; i++){
145 cpl_table_set_array (p2vm_table, "TRANSMISSION", i, zero_array_transmission);
146 cpl_table_set_array (p2vm_table, "COHERENCE", i, zero_array);
147 cpl_table_set_array (p2vm_table, "PHASE", i, zero_array);
148 cpl_table_set_array (p2vm_table, "C_MATRIX", i, zero_array);
149 }
150
151 cpl_array * dimensions;
152 dimensions = cpl_array_new (2, CPL_TYPE_INT);
153
154 /* Define the dimension of the transmission column */
155 cpl_array_set_int (dimensions, 0, nwave);
156 cpl_array_set_int (dimensions, 1, ntel);
157 cpl_table_set_column_dimensions (p2vm_table, "TRANSMISSION", dimensions);
158
159 /* Define the dimension of the coherence column */
160 cpl_array_set_int (dimensions, 1, (ntel*(ntel-1)/2));
161 cpl_table_set_column_dimensions (p2vm_table, "COHERENCE", dimensions);
162
163 /* Define the dimension of the phase column */
164 cpl_array_set_int (dimensions, 1, (ntel*(ntel-1)/2));
165 cpl_table_set_column_dimensions (p2vm_table, "PHASE", dimensions);
166
167 cpl_table_set_column_dimensions (p2vm_table, "C_MATRIX", dimensions);
168
169 FREE (cpl_array_delete, zero_array_transmission);
170 FREE (cpl_array_delete, zero_array);
171 FREE (cpl_array_delete, dimensions);
172
174 return p2vm_table;
175}
176
177/*---------------------------------------------------------------------------*/
189/*---------------------------------------------------------------------------*/
190
191cpl_table * gravi_create_oiwave_table_sc (cpl_table * wave_table,
192 cpl_propertylist * header,
193 gravi_data *wave_param)
194{
196 cpl_ensure (wave_table, CPL_ERROR_NULL_INPUT, NULL);
197 cpl_ensure (header, CPL_ERROR_NULL_INPUT, NULL);
198
199
200 /* EKW START 04/12/2018 */
201 /* set the calibrated eff_wave for LOW res*/
202 /* OP 2018-02-12: new bandwidths measured for 3pix interpolation
203 average of the six P1 baselines
204 also valid for P2
205 */
206/*
207 double calib_eff_wave[14] = {7.046E-08,
208 1.243E-07,
209 1.342E-07,
210 1.278E-07,
211 1.255E-07,
212 1.345E-07,
213 1.423E-07,
214 1.332E-07,
215 1.235E-07,
216 1.165E-07,
217 1.158E-07,
218 1.157E-07,
219 1.120E-07,
220 9.597E-08};
221
222*/
223 /* double *roof_pos; */
224 double * calib_eff_wave;
225 cpl_table * calib_eff_table = gravi_data_get_table (wave_param, "WAVE_TAB");
226 // CPLCHECK_MSG ("STATIC_PARAM not available in the SOF. It is mandatory for acqcam reduction.");
227
228 if ( cpl_table_has_column(calib_eff_table , "FBAND_WAVE") == 1 ) {
229 calib_eff_wave = cpl_table_get_data_double (calib_eff_table, "FBAND_WAVE");
230 cpl_msg_info(cpl_func,"calib_eff_wave [0] : %e", calib_eff_wave[0] );
231 cpl_msg_info(cpl_func,"calib_eff_wave [1] : %e", calib_eff_wave[1] );
232 cpl_msg_info(cpl_func,"calib_eff_wave [2] : %e", calib_eff_wave[2] );
233 cpl_msg_info(cpl_func,"calib_eff_wave [3] : %e", calib_eff_wave[3] );
234 }
235 else {
236 cpl_msg_error(cpl_func,"Cannot get the default values for calib_eff_wave");
237 cpl_msg_error(cpl_func,"WAVE_TAB table in WAVE_PARAM input does not have FBAND_WAVE column");
238 return NULL;
239 }
240
241 /* Read the minimum and maximum wavelength values from the wave_param fits file
242 * */
243 double gravi_high_lbd_min = cpl_propertylist_get_double (gravi_data_get_plist(wave_param,GRAVI_PRIMARY_HDR_EXT), "ESO OIWAVE HIGH LBD MIN");
244 cpl_msg_info (cpl_func,"gravi_high_lbd_min : %e", gravi_high_lbd_min);
245
246 double gravi_high_lbd_max = cpl_propertylist_get_double (gravi_data_get_plist(wave_param,GRAVI_PRIMARY_HDR_EXT), "ESO OIWAVE HIGH LBD MAX");
247 cpl_msg_info (cpl_func,"gravi_high_lbd_max : %e", gravi_high_lbd_max);
248
249 double gravi_med_lbd_min = cpl_propertylist_get_double (gravi_data_get_plist(wave_param,GRAVI_PRIMARY_HDR_EXT), "ESO OIWAVE MED LBD MIN");
250 cpl_msg_info (cpl_func,"gravi_med_lbd_min : %e", gravi_med_lbd_min);
251
252 double gravi_med_lbd_max = cpl_propertylist_get_double (gravi_data_get_plist(wave_param,GRAVI_PRIMARY_HDR_EXT), "ESO OIWAVE MED LBD MAX");
253 cpl_msg_info (cpl_func,"gravi_med_lbd_max : %e", gravi_med_lbd_max);
254
255 double gravi_low_lbd_min = cpl_propertylist_get_double (gravi_data_get_plist(wave_param,GRAVI_PRIMARY_HDR_EXT), "ESO OIWAVE LOW LBD MIN");
256 cpl_msg_info (cpl_func,"gravi_low_lbd_min : %e", gravi_low_lbd_min);
257
258 double gravi_low_lbd_max = cpl_propertylist_get_double (gravi_data_get_plist(wave_param,GRAVI_PRIMARY_HDR_EXT), "ESO OIWAVE LOW LBD MAX");
259 cpl_msg_info (cpl_func,"gravi_low_lbd_max : %e", gravi_low_lbd_max);
260
261 /* EKW END 04/12/2018 */
262
263 /* Get the QC */
264 /*double qc_min, qc_max;
265 qc_min = cpl_propertylist_get_double (header, QC_MINWAVE(GRAVI_SC));
266 qc_max = cpl_propertylist_get_double (header, QC_MAXWAVE(GRAVI_SC));
267 */
268 CPLCHECK_NUL ("Cannot read the QC MINWAVE MAXWAVE");
269
270 /* Get the max_wave and min_wave*/
271 int n_element = cpl_table_get_column_depth (wave_table, "DATA1");
272 CPLCHECK_NUL ("Cannot get the number of elements");
273 double max_wave ,min_wave ;
274 if (n_element<20)
275 {
276 /* EKW max_wave = ESO OIWAVE LOW LBD MAX
277 min_wave = ESO OIWAVE LOW LBD MIN; */
278 max_wave = gravi_low_lbd_max;
279 min_wave = gravi_low_lbd_min;
280 cpl_msg_info (cpl_func,"Using Low resolution wavelength table");
281
282 } else if (n_element<500)
283 {
284 /* EKW max_wave = ESO OIWAVE MED LBD MAX;
285 min_wave = ESO OIWAVE MED LBD MAX; */
286 max_wave = gravi_med_lbd_max;
287 min_wave = gravi_med_lbd_min;
288 cpl_msg_info (cpl_func,"Using Med resolution wavelength table");
289
290 } else
291 {
292 /*max_wave = ESO OIWAVE HIGH LBD MAX;
293 min_wave = ESO OIWAVE HIGH LBD MAX; */
294 max_wave = gravi_high_lbd_max;
295 min_wave = gravi_high_lbd_min;
296 cpl_msg_info (cpl_func,"Using High resolution wavelength table");
297 }
298 CPLCHECK_NUL ("Cannot get the max_wave and min_wave");
299
300 /* Get the nwave */
301 cpl_size nwave = gravi_wave_get_nlambda (wave_table, min_wave, max_wave);
302 CPLCHECK_NUL ("Cannot define the limits");
303
304 /* Create the OI_WAVELENGTH table */
305 cpl_table * oiwave_table = cpl_table_new (nwave);
306
307 cpl_table_new_column (oiwave_table, "EFF_WAVE", CPL_TYPE_FLOAT);
308 cpl_table_set_column_unit (oiwave_table, "EFF_WAVE", "m");
309
310 cpl_table_new_column (oiwave_table, "EFF_BAND", CPL_TYPE_FLOAT);
311 cpl_table_set_column_unit (oiwave_table, "EFF_BAND", "m");
312
313 /* Construction of the new wavelength table
314 * To be improved if needed (non linear computation) */
315 for (cpl_size wave = 0; wave < nwave; wave++){
316 double lambda = min_wave + wave * (max_wave-min_wave)/(nwave-1);
317 cpl_table_set (oiwave_table, "EFF_WAVE", wave, lambda);
318 // introduce *2 to be closer to the real Band pass
319 cpl_table_set (oiwave_table, "EFF_BAND", wave, (max_wave-min_wave)/(nwave-1)*2);
320 //for LOW mode (nwave=11) set to measured bandpass
321 if (nwave == 14) cpl_table_set (oiwave_table, "EFF_BAND", wave, calib_eff_wave[wave]);
322 }
323
324 //FREE(cpl_table_delete, calib_eff_table); /* EKW 04/12/2018 */
325
326 //free(calib_eff_wave2); /* EKW 04/12/2018 */
328 return oiwave_table;
329}
330
331/*---------------------------------------------------------------------------*/
343/*---------------------------------------------------------------------------*/
344
345cpl_table * gravi_create_oiwave_table_ft (cpl_table * wave_table,
346 cpl_table * detector_table,
347 int pol)
348{
350 cpl_ensure (wave_table, CPL_ERROR_NULL_INPUT, NULL);
351 cpl_ensure (detector_table, CPL_ERROR_NULL_INPUT, NULL);
352 cpl_ensure (pol == 0 || pol == 1, CPL_ERROR_ILLEGAL_INPUT, NULL);
353
354 /* Get the nwave */
355 cpl_size nwave = gravi_spectrum_get_nwave (wave_table);
356 cpl_size nreg = cpl_table_get_nrow (detector_table);
357
358 /* Create the OI_WAVELENGTH table */
359 cpl_table * oiwave_table = cpl_table_new (nwave);
360
361 cpl_table_new_column (oiwave_table, "EFF_WAVE", CPL_TYPE_FLOAT);
362 cpl_table_set_column_unit (oiwave_table, "EFF_WAVE", "m");
363
364 cpl_table_new_column (oiwave_table, "EFF_BAND", CPL_TYPE_FLOAT);
365 cpl_table_set_column_unit (oiwave_table, "EFF_BAND", "m");
366
367 /* Fill each channel */
368 for (cpl_size wave = 0; wave < nwave; wave++) {
369 double lambda = (wave == nwave-1) ? 1.0 : 0.0;
370
371 /* Loop on regions */
372 for (int reg = 0; reg < nreg; reg++) {
373 if (gravi_region_get_pol (detector_table, reg) != pol) continue;
374 double value = gravi_table_get_value (wave_table, GRAVI_DATA[reg], 0, wave);
375
376 if (wave == 0) lambda = CPL_MAX (lambda, value + 0.00001e-6);
377 else if (wave == nwave-1) lambda = CPL_MIN (lambda, value - 0.00001e-6);
378 else lambda += value / 24.0;
379 }
380 cpl_msg_info (cpl_func, "lbd[%lld] = %g [um]", wave, lambda*1e6);
381
382 cpl_table_set (oiwave_table, "EFF_WAVE", wave, lambda);
383 cpl_table_set (oiwave_table, "EFF_BAND", wave, 8.5e-8);
384 }
385
386 //cpl_msg_info (cpl_func, "Force linear wave");
387 //double min_wave = cpl_table_get (oiwave_table, "EFF_WAVE", 0, NULL);
388 //double max_wave = cpl_table_get (oiwave_table, "EFF_WAVE", nwave-1, NULL);
389 //for (cpl_size wave = 0; wave < nwave; wave++){
390 // double lambda = min_wave + wave * (max_wave-min_wave)/(nwave-1);
391 // cpl_table_set (oiwave_table, "EFF_WAVE", wave, lambda);
392 //}
393
395 return oiwave_table;
396}
397
398/*----------------------------------------------------------------------------*/
411/*----------------------------------------------------------------------------*/
412
414{
415 cpl_table * oiwave_table;
416
417 /* Verbose */
419 cpl_ensure (wave_map, CPL_ERROR_NULL_INPUT, NULL);
420
421 cpl_propertylist * wave_header = gravi_data_get_header (wave_map);
422 CPLCHECK_NUL ("Cannot load data");
423
424 /* Create output map */
425 gravi_data * p2vm_map = gravi_data_new(0);
426
427 /* Duplicate the P2VM_MET in product */
428 gravi_data_copy_ext (p2vm_map, wave_map, GRAVI_P2VM_MET_EXT);
429 CPLCHECK_NUL ("Cannot copy tables");
430
431 /* Loop on SC/FT */
432 for (int type_data = 0; type_data < 2 ; type_data++) {
433
434 /* Check if this data is present */
435 if (!gravi_data_has_wave (wave_map, type_data)) {
436 cpl_msg_info (cpl_func,"No data for %s, skip it", GRAVI_TYPE(type_data));
437 continue;
438 }
439
440 /* Copy the IMAGING_DETECTOR table into product */
441 gravi_data_copy_ext (p2vm_map, wave_map, GRAVI_IMAGING_DETECTOR_EXT(type_data));
442 CPLCHECK_NUL ("Cannot copy tables");
443
444 /* Get the WAVE_DATA and IMAGIGN_DETECTOR */
445 cpl_table * wave_table = gravi_data_get_wave_data (wave_map, type_data);
446 cpl_table * detector_table = gravi_data_get_imaging_detector (wave_map, type_data);
447 CPLCHECK_NUL ("Cannot get data");
448
449 /*
450 * Build the OI_WAVELENGTHs
451 */
452
453 /* Loop on polarisation */
454 int n_pol = gravi_spectrum_get_npol (wave_table);
455 for (int pol = 0 ; pol<n_pol ; pol++) {
456
457 if (type_data == GRAVI_SC)
458 /* Create the SC OI_WAVELENGTH, will be the same for
459 * both polarisations, and static from user requirement */
460 oiwave_table = gravi_create_oiwave_table_sc (wave_table,
461 wave_header,
462 wave_param);
463 else
464 /* Create the FT OI_WAVELENGTH, as a meach of each channel */
465 oiwave_table = gravi_create_oiwave_table_ft (wave_table,
466 detector_table,
467 pol);
468
469 /* Create plist */
470 cpl_propertylist * oiwave_plist = cpl_propertylist_new ();
471 cpl_propertylist_append_int (oiwave_plist, "NWAVE", cpl_table_get_nrow (oiwave_table));
472 cpl_propertylist_update_int (oiwave_plist, "OI_REVN", 1);
473 cpl_propertylist_append_string (oiwave_plist, "INSNAME", GRAVI_INSNAME(type_data,pol,n_pol));
474 cpl_propertylist_append_int (oiwave_plist, "EXTVER", GRAVI_EXTVER(type_data,pol,n_pol));
475
476 /* Add this OI_WAVELENGTH to the spectrum_data */
477 gravi_data_add_table (p2vm_map, oiwave_plist,
478 GRAVI_OI_WAVELENGTH_EXT, oiwave_table);
479 CPLCHECK_NUL ("Cannot add the table");
480 }
481
482 /*
483 * Build the P2VM
484 */
485 cpl_size n_wave = cpl_table_get_nrow (oiwave_table);
486
487 /* Init the table */
488 cpl_table * p2vm_table;
489 p2vm_table = gravi_create_p2vm_table (detector_table, n_wave);
490
491 /* Init the header of this table */
492 cpl_propertylist * p2vm_plist = cpl_propertylist_new();
493 CPLCHECK_NUL ("Cannot create propertylist");
494
495 /* Add the p2vm_table */
496 const char * extname = (type_data == GRAVI_SC ? GRAVI_P2VM_DATA_SC_EXT : GRAVI_P2VM_DATA_FT_EXT);
497 gravi_data_add_table (p2vm_map, p2vm_plist, extname, p2vm_table);
498
499 CPLCHECK_NUL ("Cannot create P2VM");
500 } /* End loop SC/FT */
501
503 return p2vm_map;
504}
505
506/*----------------------------------------------------------------------------*/
544/*----------------------------------------------------------------------------*/
545
546cpl_error_code gravi_compute_p2vm (gravi_data * p2vm_map, gravi_data * preproc_data,
547 int ** valid_trans, int ** valid_pair,
548 enum gravi_detector_type det_type)
549{
551 cpl_ensure_code (p2vm_map, CPL_ERROR_NULL_INPUT);
552 cpl_ensure_code (preproc_data, CPL_ERROR_NULL_INPUT);
553
554 int nv = 0;
555
556 /*
557 * Loop on type data (SC/FT)
558 */
559 int init_type_data = 1;
560 int end_type_data = 1;
561 if(det_type == GRAVI_DET_SC || det_type == GRAVI_DET_ALL)
562 init_type_data = 0;
563 if(det_type == GRAVI_DET_FT || det_type == GRAVI_DET_ALL)
564 end_type_data = 1;
565 for (int type_data = init_type_data; type_data <= end_type_data; type_data++ ) {
566
567 /* Check if SPECTRUM data exists */
568 if (!gravi_data_has_spectrum (preproc_data, type_data)) {
569 cpl_msg_info (cpl_func,"No data for %s, skip it", GRAVI_TYPE(type_data));
570 continue;
571 }
572
573 /* Primary header of input data */
574 cpl_propertylist * preproc_header = gravi_data_get_header (preproc_data);
575
576 /* Get the tables extension */
577 cpl_table * detector_table, * spectrum_table, * p2vm_table;
578 detector_table = gravi_data_get_imaging_detector (preproc_data, type_data);
579 spectrum_table = gravi_data_get_spectrum_data (preproc_data, type_data);
580 p2vm_table = gravi_data_get_p2vm_data (p2vm_map, type_data);
581
582 cpl_ensure_code (detector_table, CPL_ERROR_ILLEGAL_INPUT);
583 cpl_ensure_code (spectrum_table, CPL_ERROR_ILLEGAL_INPUT);
584 cpl_ensure_code (p2vm_table, CPL_ERROR_ILLEGAL_INPUT);
585
586 /* Get the number of regions */
587 int n_region = cpl_table_get_nrow (detector_table);
588 int npol = n_region > 24 ? npol = 2 : 1;
589
590 /* Get the oiwave_tables */
591 cpl_table ** oiwave_tables = gravi_data_get_oiwave_tables (p2vm_map, type_data, npol);
592
593 /* Get the number of waves */
594 int nwave = cpl_table_get_nrow (oiwave_tables[0]);
595
596 /* Get the P2VM column (where to store the data) */
597 cpl_array ** transmission, ** coherence, ** phase, ** norma_m;
598 coherence = cpl_table_get_data_array (p2vm_table, "COHERENCE");
599 phase = cpl_table_get_data_array (p2vm_table, "PHASE");
600 norma_m = cpl_table_get_data_array (p2vm_table, "C_MATRIX");
601 transmission = cpl_table_get_data_array (p2vm_table, "TRANSMISSION");
602
603 /* Get if a single telescope or baseline is open */
604 int tel = -1, base = -1;
605 if (gravi_check_shutter (preproc_header,1,0,0,0)) tel = 0;
606 if (gravi_check_shutter (preproc_header,0,1,0,0)) tel = 1;
607 if (gravi_check_shutter (preproc_header,0,0,1,0)) tel = 2;
608 if (gravi_check_shutter (preproc_header,0,0,0,1)) tel = 3;
609 if (gravi_check_shutter (preproc_header,1,1,0,0)) base = 0;
610 if (gravi_check_shutter (preproc_header,1,0,1,0)) base = 1;
611 if (gravi_check_shutter (preproc_header,1,0,0,1)) base = 2;
612 if (gravi_check_shutter (preproc_header,0,1,1,0)) base = 3;
613 if (gravi_check_shutter (preproc_header,0,1,0,1)) base = 4;
614 if (gravi_check_shutter (preproc_header,0,0,1,1)) base = 5;
615 cpl_ensure_code (tel>=0 || base>=0, CPL_ERROR_ILLEGAL_INPUT);
616
617 /*
618 * A single telescope is open
619 */
620 if (tel >= 0) {
621 valid_trans[type_data][tel] = 1;
622
623 cpl_msg_info (cpl_func, "Compute the transmission of "
624 "tel %d for %s", tel+1, GRAVI_TYPE(type_data));
625
626 /* Init for integration */
627 cpl_image * imgflux = NULL;
628 cpl_image ** spectrum_img;
629 spectrum_img = cpl_calloc (n_region,sizeof(cpl_image*));
630
631 for (cpl_size region = 0; region < n_region; region++){
632
633 /* Get the data of this region */
634 cpl_imagelist * spectrum_imglist;
635 spectrum_imglist = gravi_imagelist_wrap_column (spectrum_table, GRAVI_DATA[region]);
636
637 /* Compute the median over the rows = un-normalized transmission */
638 spectrum_img[region] = cpl_imagelist_collapse_median_create (spectrum_imglist);
639 gravi_imagelist_unwrap_images (spectrum_imglist);
640
641 /* Compute the total flux for this telescope (sum over all regions)
642 * for further normalization */
643 if (imgflux == NULL)
644 imgflux = cpl_image_duplicate (spectrum_img[region]);
645 else
646 cpl_image_add (imgflux, spectrum_img[region]);
647 } /* loop on regions */
648
649 /* Compute the total flux over the spectrum */
650 double max_flux = cpl_image_get_flux (imgflux);
651
652 /* Set the normalized transmission */
653 for (cpl_size region = 0; region < n_region; region++){
654
655 /* Normalisation of the transmission*/
656 cpl_image_divide_scalar (spectrum_img[region], max_flux);
657
658 /* Set the transmission in the 2D map of transmission */
659 for (cpl_size wave = 0; wave < nwave; wave++) {
660 double value = cpl_image_get (spectrum_img[region], wave+1, 1, &nv);
661 cpl_array_set (transmission[region],
662 wave + nwave * tel, value);
663 }
664
665 CPLCHECK_MSG ("Cannot compute transmission");
666 }/* End loop on region */
667
668 FREELOOP (cpl_image_delete, spectrum_img, n_region);
669 FREE (cpl_image_delete, imgflux);
670 } /* valid test for transmission (single tel) */
671
672
673 /*
674 * One pair is open
675 */
676 if (base >= 0) {
677 int tel1 = GRAVI_BASE_TEL[base][0];
678 int tel2 = GRAVI_BASE_TEL[base][1];
679
680 valid_pair[type_data][base] = 1;
681
682 cpl_msg_info(cpl_func, "Compute the coherence and "
683 "phase of pair (%d,%d) for %s", tel1+1,
684 tel2+1, GRAVI_TYPE(type_data));
685
686 /* Get the size of the vectors */
687 int nrow = cpl_table_get_nrow (spectrum_table);
688
689 /*
690 * Recover the mean OPD modulation (averaved over pol
691 * and channels) using the ellipses. In [m]
692 */
693
694 cpl_vector * mean_opd;
695 mean_opd = gravi_ellipse_meanopd_create (spectrum_table, detector_table,
696 oiwave_tables, NULL, base);
697 CPLCHECK_MSG ("Cannot compute opd");
698
699 /*
700 * Compute the P2VM complex coherence for each channel and region
701 */
702 double residuals_avg = 0;
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 cpl_matrix ** model_matrices = cpl_calloc (npol, sizeof(cpl_matrix *));
716
717 for (int pol = 0; pol < npol; pol ++) {
718 model_matrices[pol] = cpl_matrix_new (nrow, 3);
719
720 for (cpl_size row = 0; row < nrow; row++) {
721 cpl_matrix_set (model_matrices[pol], row, 0, 1.0);
722 double lambda = cpl_table_get (oiwave_tables[pol], "EFF_WAVE", wave, NULL);
723 double phi = cpl_vector_get (mean_opd, row) / lambda * CPL_MATH_2PI;
724 double enveloppe = cpl_vector_get (envelope_vector, row);
725 cpl_matrix_set (model_matrices[pol], row, 1, sin(phi)*enveloppe);
726 cpl_matrix_set (model_matrices[pol], row, 2, cos(phi)*enveloppe);
727 }
728
729 /* Invers the matrix of the carrying-wave */
730 inv_matrixes[pol] = gravi_matrix_invertSV_create (model_matrices[pol]);
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 cpl_vector * yerr_window = gravi_table_get_vector (spectrum_table, wave,
742 GRAVI_DATAERR[region]);
743
744 /* Vector init_val contains the best fit coeficient of the fit,
745 * that is the mean flux c and the complex coherence flux,
746 * computed as: init_val = inv_matrix * data
747 * FIXME: can be done in CPL ? */
748 cpl_vector * init_val = cpl_vector_new(3);
749
750 for (cpl_size j = 0; j < 3; j++){
751 double comp = 0;
752 for (cpl_size i = 0; i < nrow; i++){
753 comp += cpl_matrix_get (inv_matrixes[pol], j, i) * cpl_vector_get (y_window, i);
754 }
755 cpl_vector_set (init_val, j, comp);
756 }
757
758 /* compute the residuals */
759 double residuals_sum=0;
760 cpl_size count = 0;
761
762// cpl_vector * fit = cpl_vector_new(nrow);
763 for (cpl_size i = 0; i < nrow; i++){
764 double comp = 0;
765 for (cpl_size j = 0; j < 3; j++){
766 comp += cpl_matrix_get (model_matrices[pol], i, j) * cpl_vector_get (init_val, j);
767 }
768 if (cpl_vector_get (yerr_window, i) > 0.001 ) {
769 residuals_sum += pow((cpl_vector_get (y_window, i)-comp)/cpl_vector_get (yerr_window, i) , 2);
770 count +=1;
771 }
772// cpl_vector_set (fit, i, comp);
773 }
774
775// if (region == 1)
776// if (wave == 7){
777// const cpl_vector ** vectors = malloc(4 * sizeof(cpl_vector*));
778// cpl_vector * error = cpl_vector_duplicate(y_window);
779// cpl_vector_subtract(error, fit);
780// vectors[0]=NULL;
781// vectors[1]=fit;
782// vectors[2] = error;
783// vectors[3] = y_window;
784// cpl_plot_vectors(NULL, NULL, NULL, vectors, 4);
785// cpl_plot_vector(NULL, NULL, NULL, error);
786// printf("Chi2 : %g \n", residuals_sum/count);
787// }
788 if (count > 0) residuals_avg += residuals_sum/count;
789
790 /* Compute the P2VM coherence [e]. */
791 double coherence_fit =
792 sqrt( pow (cpl_vector_get(init_val, 2), 2) +
793 pow (cpl_vector_get(init_val, 1), 2));
794
795 cpl_array_set (coherence[region], wave + nwave *
796 base, coherence_fit);
797
798 /* Compute the P2VM phase [rad] */
799 double phase_fit;
800 phase_fit = atan2( cpl_vector_get(init_val, 2),
801 cpl_vector_get(init_val, 1));
802
803 cpl_array_set (phase[region], wave + nwave * base,
804 phase_fit);
805
806 /* Save the c parameter for normalisation purpose */
807 cpl_array_set (norma_m[region], wave + nwave * base,
808 cpl_vector_get (init_val,0));
809
810 FREE (cpl_vector_delete, init_val);
811 FREE (cpl_vector_delete, y_window);
812 FREE (cpl_vector_delete, yerr_window);
813 } /* loop on region */
814
815 FREELOOP (cpl_matrix_delete, inv_matrixes, npol);
816 FREELOOP (cpl_matrix_delete, model_matrices, npol);
817 FREE (cpl_vector_delete, envelope_vector);
818 } /* loop on wave */
819
820 /* Write QC in header */
821 cpl_propertylist * p2vm_header = gravi_data_get_header (p2vm_map);
822 char qc_name[90];
823 cpl_msg_info (cpl_func, "Averaged of CHI2 of p2vm fit for %s base %i = %f", GRAVI_TYPE(type_data), base+1, residuals_avg / (nwave*n_region));
824 sprintf (qc_name, "ESO QC P2VM%s%i CHI2", GRAVI_TYPE(type_data), base+1);
825 cpl_propertylist_append_double (p2vm_header, qc_name, residuals_avg / (nwave*n_region));
826 cpl_propertylist_set_comment (p2vm_header, qc_name, "Chi2 avg. of p2vm fit");
827
828 FREE (cpl_vector_delete, mean_opd);
829 } /* End case valid_pair (baseline) */
830
831 FREE (cpl_free, oiwave_tables);
832
833 /* If an error is catched */
834 CPLCHECK_MSG ("Cannot compute the P2VM");
835
836 } /* Loop on type_data SC/FT */
837
839 return CPL_ERROR_NONE;
840}
841
842
843/*----------------------------------------------------------------------------*/
878/*----------------------------------------------------------------------------*/
879
880cpl_error_code gravi_p2vm_normalisation (gravi_data * p2vm_map,
881 int ** valid_trans,
882 int ** valid_pair )
883{
884 int ntel = 4, n_base = 6;
885 int nv = 0;
886
887 /* Message and timer */
889 cpl_ensure_code (p2vm_map, CPL_ERROR_NULL_INPUT);
890 cpl_ensure_code (valid_trans, CPL_ERROR_NULL_INPUT);
891 cpl_ensure_code (valid_pair, CPL_ERROR_NULL_INPUT);
892
893 cpl_propertylist * p2vm_header = gravi_data_get_header (p2vm_map);
894
895 /*
896 * Loop on FT and SC
897 */
898 for (int type_data = 0; type_data < 2; type_data ++){
899
900 /* Check if this data is present */
901 if (!gravi_data_has_p2vm (p2vm_map, type_data)) {
902 cpl_msg_info (cpl_func,"No data for %s, skip it", GRAVI_TYPE(type_data));
903 continue;
904 }
905
906 cpl_msg_info (cpl_func, "Normalisation of P2VM for %s",
907 GRAVI_TYPE(type_data));
908
909 /* Load P2VM and detector tables */
910 cpl_table * p2vm_table, * detector_table;
911 detector_table = gravi_data_get_imaging_detector (p2vm_map, type_data);
912 p2vm_table = gravi_data_get_p2vm_data (p2vm_map, type_data);
913
914 /* Get info */
915 cpl_size n_region = cpl_table_get_nrow (detector_table);
916 int n_pol = n_region > 24 ? 2 : 1;
917
918 /* Get the number of wave */
919 cpl_table * oiwave_table;
920 oiwave_table = gravi_data_get_oi_wave (p2vm_map, type_data, 0, n_pol);
921 cpl_size nwave = cpl_table_get_nrow (oiwave_table);
922 cpl_ensure_code (nwave, CPL_ERROR_ILLEGAL_INPUT);
923
924 /* Get the P2VM column (where to store the data) */
925 cpl_array ** transmission, ** coherence, ** phase;
926 coherence = cpl_table_get_data_array (p2vm_table, "COHERENCE");
927 phase = cpl_table_get_data_array (p2vm_table, "PHASE");
928 transmission = cpl_table_get_data_array (p2vm_table, "TRANSMISSION");
929
930 /*
931 * Set P2VM A-phase to zero
932 */
933
934 /* Loop on polarisation and baseline */
935 for (int pol = 0; pol < n_pol; pol++) {
936 for (int base = 0; base < 6; base++){
937
938 /* Check if this baseline is computed */
939 if ( !valid_pair[type_data][base]) continue;
940
941 /* Get the index of the k band ABCD */
942 int iA = gravi_get_region (detector_table, base, 'A', pol);
943 int iB = gravi_get_region (detector_table, base, 'B', pol);
944 int iC = gravi_get_region (detector_table, base, 'C', pol);
945 int iD = gravi_get_region (detector_table, base, 'D', pol);
946
947 for (cpl_size i = 0; i < cpl_array_get_size(phase[0]); i++){
948
949 double valA = cpl_array_get (phase[iA], i, NULL);
950 cpl_array_set (phase[iA], i, 0.0);
951
952 double valB = cpl_array_get (phase[iB], i, NULL) - valA;
953 if (valB < 0) valB += CPL_MATH_2PI;
954 cpl_array_set (phase[iB], i, valB);
955
956 double valC = cpl_array_get (phase[iC], i, NULL) - valA;
957 if (valC < 0) valC += CPL_MATH_2PI;
958 cpl_array_set (phase[iC], i, valC);
959
960 double valD = cpl_array_get (phase[iD], i, NULL) - valA;
961 if (valD < 0) valD += CPL_MATH_2PI;
962 cpl_array_set (phase[iD], i, valD);
963
964 CPLCHECK_MSG ("Cannot unwrap AC and BD of P2VM");
965 } /* End loop on wave */
966 } /* end loop on baseline */
967 } /* end loop on polarisation */
968
969 CPLCHECK_MSG ("Cannot compute P2VM");
970
971 /*
972 * Normalisation of the P2VM transmission
973 */
974
975 /* Compute the mean transmission */
976 int ntrans = cpl_array_get_size (transmission[0]);
977 cpl_array * mean_transmission = cpl_array_new (ntrans, CPL_TYPE_FLOAT);
978 cpl_array_fill_window (mean_transmission, 0, ntrans, 0.);
979
980 for (cpl_size region = 0; region < n_region; region++) {
981 cpl_array_add (mean_transmission,transmission[region]);
982 }
983 cpl_array_divide_scalar (mean_transmission, n_region);
984
985 /* Normalized the transmissions */
986 for (cpl_size region = 0; region < n_region; region++){
987 cpl_array_divide (transmission[region], mean_transmission);
988 }
989 FREE (cpl_array_delete, mean_transmission);
990
991 /*
992 * Normalisation of the P2VM coherence
993 */
994
995 /* Init quantities to compute mean flux per tel */
996 double mean_flux[4] = {0.0,0.0,0.0,0.0};
997 int n_flux[4] = {0,0,0,0};
998
999 /* Loop on baseline */
1000 for (int base = 0; base < 6; base++) {
1001 int tel0 = GRAVI_BASE_TEL[base][0];
1002 int tel1 = GRAVI_BASE_TEL[base][1];
1003
1004 /* Compute the input flux solving c=TI for each wave */
1005 for (cpl_size wave = 0; wave < nwave; wave++){
1006
1007 /* Construction of the transmission matrix */
1008 cpl_matrix * matrix_T = cpl_matrix_new (n_region, 4);
1009
1010 /* Get index of each tranmission on the matrix */
1011 cpl_vector * vector_c = gravi_table_get_vector (p2vm_table, wave+nwave*base, "C_MATRIX");
1012 cpl_matrix * matrix_c = cpl_matrix_new (n_region, 1);
1013 for(cpl_size region = 0; region < n_region; region++) {
1014 cpl_matrix_set (matrix_c, region, 0, cpl_vector_get (vector_c, region));
1015 for (int tel = 0; tel < ntel; tel++){
1016 cpl_matrix_set (matrix_T, region, tel,
1017 cpl_array_get (transmission[region],
1018 tel*nwave+wave ,&nv));
1019 }
1020 } /* End loop on region */
1021 FREE (cpl_vector_delete, vector_c);
1022
1023 /* Compute the matrix_I */
1024 cpl_errorstate prestate = cpl_errorstate_get();
1025
1026 cpl_matrix * matrix_I = cpl_matrix_solve_normal (matrix_T, matrix_c);
1027
1028 /* Check if singular value */
1029 if (! strcmp("Singular matrix", cpl_error_get_message())){
1030 cpl_msg_warning(cpl_func, "matrix_c or matrix_T "
1031 "are singular for tel1 = %d tel2 = %d and wave = %lld",
1032 tel0, tel1, wave);
1033 cpl_errorstate_set (prestate);
1034 cpl_matrix_delete (matrix_T);
1035 cpl_matrix_delete (matrix_I);
1036 cpl_matrix_delete (matrix_c);
1037 } else {
1038
1039 /* Store the total flux for each tel (will be used to compute
1040 * the mean over wave, output and files) in [e/dit/output] */
1041 mean_flux[tel0] += cpl_matrix_get (matrix_I, tel0, 0);
1042 mean_flux[tel1] += cpl_matrix_get (matrix_I, tel1, 0);
1043 n_flux[tel0] ++;
1044 n_flux[tel1] ++;
1045
1046 /* Get the coefficient of normalisation */
1047 double F0 = cpl_matrix_get (matrix_I, tel0, 0);
1048 double F1 = cpl_matrix_get (matrix_I, tel1, 0);
1049 double coeff = sqrt (fabs(F0*F1));
1050
1051 /* Normalisation */
1052 if (coeff !=0 ) {
1053 for (cpl_size region = 0; region < n_region; region++){
1054 double value = cpl_array_get (coherence[region],
1055 wave+nwave*base, &nv);
1056 cpl_array_set (coherence[region],
1057 wave+nwave*base,
1058 value / coeff);
1059 }
1060 }
1061
1062 FREE (cpl_matrix_delete, matrix_c);
1063 FREE (cpl_matrix_delete, matrix_I);
1064 FREE (cpl_matrix_delete, matrix_T);
1065 }
1066 } /* end loop on WAVE */
1067 } /* end loop on baseline */
1068
1069
1070
1071 /*
1072 * Compute the QC parameters for the mean flux
1073 */
1074 char qc_name[90];
1075 for (int tel = 0; tel<4; tel++ ) {
1076 cpl_msg_info (cpl_func, "Mean flux tel%i = %f (n=%i)", tel, mean_flux[tel] / n_flux[tel], n_flux[tel]);
1077 sprintf (qc_name, "ESO QC FLUX_%s%i AVG", GRAVI_TYPE(type_data), tel);
1078 cpl_propertylist_append_double (p2vm_header, qc_name, mean_flux[tel] / n_flux[tel]);
1079 cpl_propertylist_set_comment (p2vm_header, qc_name, "[e/DIT/chanel/output/file] mean flux");
1080 }
1081
1082
1083 /* Compute the QC parameters:
1084 * - Mean Coherence
1085 * - Mean of rms of Coherence
1086 * - Mean of rms of Phase */
1087
1088 /* Allocate stat tables */
1089 cpl_array * sig_phi_arr = cpl_array_new(n_region, CPL_TYPE_DOUBLE);
1090 cpl_array * sig_coh_arr = cpl_array_new(n_region, CPL_TYPE_DOUBLE);
1091 cpl_array * mean_coh_arr = cpl_array_new(n_region, CPL_TYPE_DOUBLE);
1092 cpl_array * mean_coh_base_arr = cpl_array_new(n_base, CPL_TYPE_DOUBLE);
1093 cpl_array * min_coh_base_arr = cpl_array_new(n_base, CPL_TYPE_DOUBLE);
1094 cpl_array * max_coh_base_arr = cpl_array_new(n_base, CPL_TYPE_DOUBLE);
1095 cpl_array * mean_trans_arr = cpl_array_new(n_region, CPL_TYPE_DOUBLE);
1096 cpl_array * sig_transdiff_arr = cpl_array_new(n_region, CPL_TYPE_DOUBLE);
1097
1098 cpl_array_fill_window (mean_coh_base_arr, 0, n_base, 0);
1099 cpl_array_fill_window (min_coh_base_arr, 0, n_base, 10);
1100 cpl_array_fill_window (max_coh_base_arr, 0, n_base, 0);
1101
1102 /* Compute the values per region */
1103 for (cpl_size region = 0; region < n_region; region ++ ) {
1104
1105 /* Get the base of region */
1106 int base = gravi_region_get_base (detector_table, region);
1107 int tel0 = GRAVI_BASE_TEL[base][0];
1108 int tel1 = GRAVI_BASE_TEL[base][1];
1109
1110 /* Get quantities for this region and base */
1111 cpl_array * coh_region = cpl_array_extract (coherence[region],
1112 nwave*base, nwave);
1113 cpl_array * trans_tel1 = cpl_array_extract (transmission[region],
1114 nwave*tel0, nwave);
1115 cpl_array * trans_tel2 = cpl_array_extract (transmission[region],
1116 nwave*tel1, nwave);
1117 cpl_array * ph_region = cpl_array_extract (phase[region],
1118 nwave*base, nwave);
1119
1120 /* Compute spectral averaged quantities */
1121 cpl_array_set (mean_coh_arr, region,
1122 cpl_array_get_mean (coh_region));
1123
1124 cpl_array_set (sig_coh_arr, region,
1125 cpl_array_get_stdev (coh_region));
1126
1127 cpl_array_set (mean_trans_arr, region,
1128 (cpl_array_get_mean (trans_tel1) +
1129 cpl_array_get_mean (trans_tel2)) /2);
1130
1131 cpl_array_set (sig_phi_arr, region,
1132 cpl_array_get_stdev (ph_region));
1133
1134 cpl_array * diff_trans;
1135 diff_trans = cpl_array_duplicate (trans_tel1);
1136 cpl_array_subtract (diff_trans, trans_tel2);
1137 cpl_array_set (sig_transdiff_arr, region,
1138 cpl_array_get_stdev (diff_trans));
1139 cpl_array_delete (diff_trans);
1140
1141 /* Normalize coherence with trans */
1142 cpl_array_power (trans_tel1, 0.5);
1143 cpl_array_power (trans_tel2, 0.5);
1144 cpl_array_divide (coh_region, trans_tel1);
1145 cpl_array_divide (coh_region, trans_tel2);
1146 cpl_array_divide_scalar (coh_region, 2.);
1147
1148 /* Compute averaged quantities per baseline */
1149 cpl_array_set (mean_coh_base_arr, base,
1150 cpl_array_get (mean_coh_base_arr, base, NULL) +
1151 cpl_array_get_mean (coh_region)/(n_region/6));
1152
1153 /* Compute percentil */
1154 double min_percentile = gravi_array_get_quantile (coh_region, 0.05);
1155 double max_percentile = gravi_array_get_quantile (coh_region, 0.95);
1156
1157 if (cpl_array_get(min_coh_base_arr, base, NULL) > min_percentile)
1158 cpl_array_set(min_coh_base_arr, base, min_percentile);
1159
1160 if (cpl_array_get(max_coh_base_arr, base, NULL) < max_percentile)
1161 cpl_array_set(max_coh_base_arr, base, max_percentile);
1162
1163 /* Delete variables */
1164 cpl_array_delete (coh_region);
1165 cpl_array_delete (trans_tel2);
1166 cpl_array_delete (trans_tel1);
1167 cpl_array_delete (ph_region);
1168
1169 } /* End loop on regions */
1170
1171 CPLCHECK_MSG ("Cannot compute_the averages values per region");
1172
1173 /* Compute the full-averaged QC */
1174 double mean_coh, sig_coh, sig_phi, min_trans, mean_trans, max_trans;
1175 mean_coh = cpl_array_get_mean (mean_coh_arr) /
1176 (2*cpl_array_get_mean (mean_trans_arr));
1177 sig_coh = cpl_array_get_mean (sig_coh_arr) /
1178 (2*cpl_array_get_mean (mean_trans_arr));
1179 sig_phi = cpl_array_get_mean (sig_phi_arr);
1180 min_trans = cpl_array_get_min (mean_trans_arr)/2.;
1181 max_trans = cpl_array_get_max (mean_trans_arr)/2.;
1182 mean_trans = cpl_array_get_mean (mean_trans_arr)/2.;
1183
1184 CPLCHECK_MSG ("Cannot compute averaged values");
1185
1186 /* Set these full-averaged QC parameters */
1188 mean_coh);
1190 sig_coh);
1192 sig_phi);
1194 mean_trans);
1196 min_trans);
1198 max_trans);
1199 cpl_msg_info (cpl_func, "QC %s COH_AVG = %e COH_RMS %e PHASE_RMS = %e TRANS_AVG %e TRANS_MIN = %e TRANS_MAX = %e",
1200 GRAVI_TYPE(type_data), mean_coh, (sig_coh), sig_phi, min_trans, mean_trans, max_trans);
1201
1202
1203
1204 /* QC per baseline */
1205 for (int base=0; base< n_base; base++){
1206 /* ESO QC P2VM_COHERENCE */
1207 sprintf (qc_name, "ESO QC P2VM_COHERENCE_%s%s", GRAVI_TYPE(type_data), GRAVI_BASE_NAME[base]);
1208 cpl_propertylist_update_double (p2vm_header, qc_name,
1209 cpl_array_get (mean_coh_base_arr, base, NULL));
1210 cpl_propertylist_set_comment (p2vm_header, qc_name,
1211 "Avg coh. over lbd per baseline");
1212
1213 /* ESO QC P2VM_MINCOHERENCE_ */
1214 sprintf (qc_name, "ESO QC P2VM_MINCOHERENCE_%s%s", GRAVI_TYPE(type_data), GRAVI_BASE_NAME[base]);
1215 cpl_propertylist_update_double (p2vm_header, qc_name,
1216 cpl_array_get (min_coh_base_arr, base, NULL));
1217 cpl_propertylist_set_comment (p2vm_header, qc_name,
1218 "Min coh. (5 perc) over lbd per baseline");
1219
1220 /* ESO QC P2VM_MAXCOHERENCE_ */
1221 sprintf (qc_name, "ESO QC P2VM_MAXCOHERENCE_%s%s", GRAVI_TYPE(type_data), GRAVI_BASE_NAME[base]);
1222 cpl_propertylist_update_double (p2vm_header, qc_name,
1223 cpl_array_get (max_coh_base_arr, base, NULL));
1224 cpl_propertylist_set_comment (p2vm_header, qc_name,
1225 "Max coh. (95 perc) over lbd per baseline");
1226 }
1227 CPLCHECK_MSG ("Cannot append QC params");
1228
1229 FREE (cpl_array_delete, sig_phi_arr);
1230 FREE (cpl_array_delete, sig_coh_arr);
1231 FREE (cpl_array_delete, mean_coh_arr);
1232 FREE (cpl_array_delete, mean_trans_arr);
1233 FREE (cpl_array_delete, sig_transdiff_arr);
1234 FREE (cpl_array_delete, mean_coh_base_arr);
1235 FREE (cpl_array_delete, min_coh_base_arr);
1236 FREE (cpl_array_delete, max_coh_base_arr);
1237
1238 } /* end loop on FT and SC */
1239
1241 return CPL_ERROR_NONE;
1242}
1243
1244/*----------------------------------------------------------------------------*/
1265/*----------------------------------------------------------------------------*/
1266
1267cpl_error_code gravi_p2vm_phase_correction (gravi_data * p2vm_map,
1268 gravi_data * p2vmred_data,
1269 int full_phase)
1270{
1272 cpl_ensure_code (p2vm_map, CPL_ERROR_NULL_INPUT);
1273 cpl_ensure_code (p2vmred_data, CPL_ERROR_NULL_INPUT);
1274
1275 int nv;
1276
1277 /* Get the header */
1278 cpl_propertylist * p2vmred_header = gravi_data_get_header (p2vmred_data);
1279
1280 /*
1281 * Loop on FT and SC
1282 */
1283 for (int type_data = 0; type_data < 2; type_data ++) {
1284
1285 /* Check if P2VM has this type */
1286 if (!gravi_data_has_p2vm (p2vm_map, type_data)) {
1287 cpl_msg_info (cpl_func,"No data for %s in P2VM, skip it", GRAVI_TYPE(type_data));
1288 continue;
1289 }
1290
1291 cpl_msg_info (cpl_func, "Calibrate the internal phase of %s (%s)",
1292 GRAVI_TYPE(type_data),full_phase?"full phases":"closure phases");
1293
1294 /* Where the instrumental phase will be stored */
1295 cpl_array ** visphase = cpl_calloc (12, sizeof(cpl_array*));
1296
1297 /* Loop on polarisation */
1298 int npol = gravi_pfits_get_pola_num (p2vmred_header, type_data);
1299 for ( int pol= 0 ; pol < npol ; pol++ ) {
1300
1301 cpl_msg_info (cpl_func, "Compute correction for pol %i over %i", pol+1, npol);
1302
1303 /* Get the OI_WAVE and the OI_VIS tables */
1304 cpl_table * oi_wave = gravi_data_get_oi_wave (p2vmred_data, type_data, pol, npol);
1305 cpl_table * oi_vis = gravi_data_get_oi_vis (p2vmred_data, type_data, pol, npol);
1306 cpl_array * sigma = gravi_table_create_sigma_array (oi_wave);
1307 cpl_size nrow = cpl_table_get_nrow (oi_vis) / 6;
1308
1309 /* Get a pointer of the VISDATA column */
1310 cpl_array ** visdata = cpl_table_get_data_array (oi_vis, "VISDATA");
1311 float * wavedata = cpl_table_get_data_float (oi_wave, "EFF_WAVE");
1312 cpl_size nwave = cpl_array_get_size (visdata[0]);
1313 cpl_size wave0 = nwave/2;
1314
1315 /*
1316 * Compute OPLs of the 4 beam as the phase of the mean channel
1317 * for the baselines 01, 02, 03, in [rad]
1318 */
1319 cpl_msg_debug (cpl_func,"Compute OPLs of beam");
1320
1321 double ** opl = cpl_malloc (sizeof(double*) * nrow);
1322 for (cpl_size row=0 ; row<nrow ; row++) {
1323 opl[row] = cpl_malloc (sizeof(double) * 4);
1324 opl[row][0] = 0.0;
1325 for ( int base= 1 ; base < 4 ; base++ ) {
1326 opl[row][base] = carg (cpl_array_get_complex (visdata[row * 6 + base-1], wave0, &nv));
1327 }
1328 } /* End compute OPLs */
1329
1330 /* Unwrap OPLs */
1331 for ( int base= 1 ; base < 4 ; base++ ) {
1332 double wrap = 0.0, ref = opl[0][base];
1333 for (cpl_size row=1 ; row<nrow ; row++) {
1334 if ( (opl[row][base] - ref) < -CPL_MATH_PI ) wrap += 2.*CPL_MATH_PI;
1335 if ( (opl[row][base] - ref) > CPL_MATH_PI ) wrap -= 2.*CPL_MATH_PI;
1336 ref = opl[row][base];
1337 opl[row][base] += wrap;
1338 }
1339 } /* End unwrap OPLs */
1340
1341 /* Remove mean OPLs */
1342 for ( int base= 1 ; base < 4 ; base++ ) {
1343 double mean = 0.0;
1344 for (cpl_size row=0 ; row<nrow ; row++) mean += opl[row][base];
1345 for (cpl_size row=0 ; row<nrow ; row++) opl[row][base] -= mean / nrow;
1346 }
1347
1348 CPLCHECK_MSG("Cannot compute OPL");
1349
1350 /*
1351 * Coherent integration of visdata of each baseline with the current P2VM
1352 */
1353 cpl_msg_debug (cpl_func,"Compute coherent integration of VISDATA");
1354
1355 for ( int base = 0 ; base < 6 ; base++ ) {
1356 /* Allocate memory for visphase */
1357 visphase[base + pol*6] = cpl_array_new (nwave, CPL_TYPE_FLOAT_COMPLEX);
1358 cpl_array_fill_window_complex (visphase[base + pol*6], 0, nwave, 0.0 * I + 0.0);
1359
1360 /* Coherent integration of the visdata */
1361 for (cpl_size row=0 ; row<nrow ; row++) {
1362 double x = opl[row][GRAVI_BASE_TEL[base][1]] - opl[row][GRAVI_BASE_TEL[base][0]];
1363 for (cpl_size wave=0; wave<nwave; wave++)
1364 cpl_array_set_complex (visphase[base + pol*6], wave,
1365 cpl_array_get_complex (visphase[base + pol*6], wave, &nv) +
1366 cpl_array_get_complex (visdata[row * 6 + base], wave, &nv) *
1367 cexp (-1.*I * x * wavedata[wave0] / wavedata[wave]) );
1368 } /* End loop on rows and waves */
1369
1370 /* Normalize to pure phasor, to give equal weight to all channels */
1371 // gravi_array_normalize_complex (visphase[base + pol*6]);
1372
1373 } /* End loop on base */
1374
1375
1376 /*
1377 * Force the phase correction of the 3 first baselines to be zero (01,02,03).
1378 * Update other baselines to keep the measured closure phases. Thus
1379 * we only correct chromatic closure phases, not chromatic phase.
1380 * Here we *assume* the 3 first baseline are {01, 02, 03}
1381 */
1382
1383 cpl_array ** ref = cpl_malloc (4 * sizeof(cpl_array*));
1384 ref[0] = cpl_array_new (nwave, CPL_TYPE_DOUBLE_COMPLEX);
1385 cpl_array_fill_window_complex (ref[0], 0, nwave, 0.0 * I + 1.0);
1386
1387 if (full_phase == 0) {
1388
1389 cpl_msg_info (cpl_func,"Force phiA(lbd) to be zero for baselines (01,02,03) = keep only closures");
1390
1391 for (int base = 0; base<3 ; base++)
1392 ref[base+1] = cpl_array_duplicate (visphase[base + pol*6]);
1393
1394 } else if (full_phase == 1) {
1395
1396 cpl_msg_info (cpl_func,"Force phiA(lbd) to have zero mean and minimum GD for baselines (01,02,03)");
1397
1398 for (int base = 0; base<3 ; base++) {
1399 double gd = 0.0;
1400 gravi_array_get_group_delay_loop (&visphase[base + pol*6], NULL, sigma,
1401 &gd, 1, 2e-3, CPL_FALSE);
1402 cpl_array * tmp = cpl_array_duplicate (visphase[base + pol*6]);
1403 gravi_array_multiply_phasor (tmp, -CPL_MATH_2PI*I*gd, sigma);
1404 gd += carg (cpl_array_get_mean_complex (tmp)) / CPL_MATH_2PI / cpl_array_get_mean (sigma);
1405 cpl_array_delete (tmp);
1406 ref[base+1] = gravi_array_cexp (CPL_MATH_2PI * I * gd, sigma);
1407 }
1408
1409 } else if (full_phase == 2) {
1410
1411 cpl_msg_info (cpl_func,"Force phiA(lbd) to have zero-GD for baselines (01,02,03)");
1412
1413 for (int base = 0; base<3 ; base++) {
1414 double gd = 0.0;
1415 gravi_array_get_group_delay_loop (&visphase[base + pol*6], NULL, sigma,
1416 &gd, 1, 2e-3, CPL_FALSE);
1417 ref[base+1] = gravi_array_cexp (CPL_MATH_2PI * I * gd, sigma);
1418 }
1419 } else {
1420 return cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT, "Option for phase calibration out of range");
1421 }
1422
1423 /* Remove the corresponding REF in each base
1424 * visphase_ij *= ref_i * conj(ref_j) */
1425 for ( int base = 0 ; base < 6 ; base++ ) {
1426 cpl_array_multiply (visphase[base + pol*6], ref[GRAVI_BASE_TEL[base][0]]);
1427 gravi_array_multiply_conj (visphase[base + pol*6], ref[GRAVI_BASE_TEL[base][1]]);
1428 }
1429
1430
1431 /* SL: 7 Sept 2019
1432 * Filter visphase to remove "wiggles", ie, high frequency oscilations
1433 */
1434 if (nwave>100) /* Only for MED and HIGH with SCIENCE SPECTROMETER */
1435 for ( int base = 0 ; base < 6 ; base++ ) {
1436
1437 cpl_msg_info (cpl_func,"Performing wiggle removal on baseline %i (pol %i over %i)",
1438 base+1, pol+1, npol);
1439
1440 /* initialise polynomial of order 6 */
1441 cpl_size mindeg = 0, maxdeg = 6;
1442 cpl_polynomial * fit = cpl_polynomial_new (1);
1443
1444 /* visphase will be added to the phase of the P2VM
1445 * Need to be unwrapped before interpolation, and removal of the wiggles */
1446 cpl_array * phase_unwraped = cpl_array_cast (visphase[base + pol*6], CPL_TYPE_DOUBLE_COMPLEX);
1447
1448 /* Compute group-delay */
1449 double gd = 0.0;
1450 gravi_array_get_group_delay_loop (&phase_unwraped, NULL, sigma,
1451 &gd, 1, 2e-3, CPL_FALSE);
1452
1453 /* Remove mean group-delay and phase-delay to unwrap */
1454 gravi_array_multiply_phasor (phase_unwraped, - 2*I*CPL_MATH_PI * gd, sigma);
1455 double mean_phase = carg (cpl_array_get_mean_complex (phase_unwraped));
1456 cpl_array_multiply_scalar_complex (phase_unwraped, cexp(- I * mean_phase));
1457
1458 /* Compute argument and add back the delay and the phase [rad] */
1459 cpl_array_arg (phase_unwraped);
1460 gravi_array_add_phase (phase_unwraped, 2.*CPL_MATH_PI * gd, sigma);
1461 cpl_array_add_scalar (phase_unwraped, mean_phase);
1462
1463 /* Create the wavenumber matrix */
1464
1465 double sigma0 = cpl_array_get_mean (sigma);
1466 double delta0 = cpl_array_get_max (sigma)-cpl_array_get_min (sigma);
1467
1468 cpl_matrix * sigma_matrix = cpl_matrix_new (1,nwave);
1469 for (cpl_size wave = 0; wave < nwave; wave ++) {
1470 cpl_matrix_set (sigma_matrix, 0, wave, (cpl_array_get (sigma,wave,&nv) - sigma0)/delta0 );
1471 }
1472
1473 /* Polynomial fit */
1474 cpl_vector * input = cpl_vector_wrap (nwave, cpl_array_get_data_double (phase_unwraped));
1475 cpl_polynomial_fit (fit, sigma_matrix, NULL, input, NULL, CPL_FALSE, &mindeg, &maxdeg);
1476 cpl_vector_unwrap (input);
1477 cpl_array_delete (phase_unwraped);
1478
1479 /* Evaluate phase of visPhase */
1480 for (cpl_size wave=0; wave<nwave;wave++) {
1481 cpl_array_set_complex (visphase[base + pol*6], wave, cexp( I * cpl_polynomial_eval_1d (fit, cpl_matrix_get (sigma_matrix,0,wave), NULL)));
1482 }
1483
1484 FREE (cpl_polynomial_delete, fit);
1485 FREE (cpl_matrix_delete, sigma_matrix);
1486 }
1487
1488 FREELOOP (cpl_array_delete, ref, 4);
1489 FREELOOP (cpl_free, opl, nrow);
1490 FREE (cpl_array_delete, sigma);
1491 } /* End loop on pol */
1492
1493 CPLCHECK_MSG("Cannot perform coherent integration");
1494
1495
1496
1497
1498
1499 /*
1500 * Apply these phase corrections to the P2VM phases
1501 */
1502 cpl_msg_info (cpl_func,"Apply correction to P2VM phases");
1503
1504 cpl_table * p2vm = gravi_data_get_p2vm_data (p2vm_map, type_data);
1505 cpl_array ** phase = cpl_table_get_data_array (p2vm, "PHASE");
1506 cpl_size nreg = cpl_table_get_nrow (p2vm);
1507 cpl_size nwave = cpl_array_get_size (visphase[0]);
1508
1509 /* Loop on region */
1510 for (cpl_size reg=0; reg<nreg; reg++) {
1511
1512 /* Get the polarisation and base of this region */
1513 int base = gravi_region_get_base (p2vm, reg);
1514 int pol = gravi_region_get_pol (p2vm, reg);
1515
1516 /* Subtract the corresponding phase */
1517 for (cpl_size wave=0; wave<nwave;wave++) {
1518 double phi = carg ( cexp (1.*I*cpl_array_get (phase[reg], wave + nwave * base, &nv)) *
1519 conj(cpl_array_get_complex (visphase[base + pol*6], wave, &nv) ));
1520 cpl_array_set (phase[reg], wave + nwave * base, (phi>=0.0?phi:phi+CPL_MATH_2PI));
1521 }
1522
1523 } /* End loop on region */
1524
1525 CPLCHECK_MSG("Cannot correct P2VM phases");
1526 FREELOOP (cpl_array_delete, visphase, 12);
1527
1528 } /* End loop on FT and SC */
1529
1531 return CPL_ERROR_NONE;
1532}
1533
1534/*----------------------------------------------------------------------------*/
1548/*----------------------------------------------------------------------------*/
1549
1550cpl_error_code gravi_p2vm_transmission (gravi_data * p2vm_map, gravi_data * p2vmred_data)
1551{
1553 cpl_ensure_code (p2vm_map, CPL_ERROR_NULL_INPUT);
1554 cpl_ensure_code (p2vmred_data, CPL_ERROR_NULL_INPUT);
1555
1556 cpl_propertylist * p2vmred_header = gravi_data_get_header (p2vmred_data);
1557
1558 /* Loop on SC / FT */
1559 for (int type_data = 0; type_data < 2; type_data ++) {
1560
1561 /* Loop on polarisation */
1562 int npol = gravi_pfits_get_pola_num (p2vmred_header, type_data);
1563 for (int pol = 0; pol < npol; pol++) {
1564
1565 cpl_msg_info (cpl_func, "Compute the internal transmission of %s (pol %i over %i)",
1566 GRAVI_TYPE(type_data), pol+1, npol);
1567
1568 /* Get FLUX data */
1569 cpl_table * flux_tbl = gravi_data_get_oi_flux (p2vmred_data, type_data, pol, npol);
1570 cpl_array ** flux = cpl_table_get_data_array (flux_tbl, "FLUX");
1571 cpl_size nwave = cpl_array_get_size (flux[0]);
1572 cpl_size nrow = cpl_table_get_nrow (flux_tbl) / 4;
1573
1574 /* Create OI_FLUX table */
1575 cpl_table * oi_flux = gravi_table_oi_create (nwave, 1, GRAVI_OI_FLUX_EXT);
1576 cpl_array * flux_mean = cpl_array_new (nwave, CPL_TYPE_DOUBLE);
1577
1578 CPLCHECK_MSG("Cannot get data");
1579
1580 for (int tel = 0; tel < 4; tel++) {
1581
1582 /* Compute total flux for this tel */
1583 cpl_array_fill_window (flux_mean, 0, nwave, 0.0);
1584 for (cpl_size row = 0; row < nrow; row++) {
1585 cpl_array_add (flux_mean, flux[tel + row*4]);
1586 }
1587
1588 /* Normalize to 1 */
1589 cpl_array_divide_scalar (flux_mean, cpl_array_get_mean (flux_mean));
1590
1591 /* Set the transmission */
1592 cpl_table_set_array (oi_flux, "FLUX", tel, flux_mean);
1593
1594 /* Set its uncertainty */
1595 cpl_array_fill_window (flux_mean, 0, nwave, 0.0);
1596 cpl_table_set_array (oi_flux, "FLUXERR", tel, flux_mean);
1597
1598 } /* End loop on tel*/
1599
1600 FREE (cpl_array_delete, flux_mean);
1601
1602 /* Set this transmission to the output data
1603 * (need to duplicate header but strickly equal) */
1604 cpl_propertylist * plist = gravi_data_get_oi_flux_plist (p2vmred_data, type_data, pol, npol);
1605 plist = cpl_propertylist_duplicate (plist);
1606 gravi_data_add_table (p2vm_map, plist, NULL, oi_flux);
1607
1608 CPLCHECK_MSG("Cannot set data");
1609 } /* End loop on pols */
1610 } /* End loop on SC/FT */
1611
1613 return CPL_ERROR_NONE;
1614}
1615
#define GRAVI_PRIMARY_HDR_EXT
Definition: gravi-test.h:212
#define gravi_table_get_value(table, name, row, value)
Definition: gravi_cpl.h:49
typedefCPL_BEGIN_DECLS struct _gravi_data_ gravi_data
Definition: gravi_data.h:39
#define gravi_data_has_wave(data, type)
Definition: gravi_data.h:55
#define gravi_data_has_p2vm(data, type)
Definition: gravi_data.h:58
#define gravi_data_get_spectrum_data(data, type)
Definition: gravi_data.h:63
#define gravi_data_get_wave_data(data, type)
Definition: gravi_data.h:53
#define gravi_data_get_oi_flux(data, type, pol, npol)
Definition: gravi_data.h:49
#define gravi_data_get_header(data)
Definition: gravi_data.h:75
#define gravi_data_get_oi_wave(data, type, pol, npol)
Definition: gravi_data.h:45
#define gravi_data_get_oi_flux_plist(data, type, pol, npol)
Definition: gravi_data.h:73
#define gravi_data_get_p2vm_data(data, type)
Definition: gravi_data.h:57
#define gravi_data_has_spectrum(data, type)
Definition: gravi_data.h:65
#define gravi_data_get_imaging_detector(data, type)
Definition: gravi_data.h:60
#define gravi_data_get_oi_vis(data, type, pol, npol)
Definition: gravi_data.h:46
const cpl_size ntel
cpl_msg_debug(cpl_func, "Spectra has <50 pixels -> don't flat")
cpl_propertylist * header
Definition: gravi_old.c:2004
cpl_propertylist * plist
Definition: gravi_old.c:2000
cpl_msg_info(cpl_func, "Compute WAVE_SCAN for %s", GRAVI_TYPE(type_data))
cpl_propertylist_update_double(header, "ESO QC MINWAVE SC", cpl_propertylist_get_double(plist, "ESO QC MINWAVE SC"))
cpl_image_delete(flat_profiled)
#define GRAVI_INSNAME(type, pol, npol)
Definition: gravi_pfits.h:198
#define QC_MINTRANS_SC
Definition: gravi_pfits.h:161
#define QC_MAXTRANS_SC
Definition: gravi_pfits.h:162
#define GRAVI_SC
Definition: gravi_pfits.h:165
#define GRAVI_P2VM_DATA_FT_EXT
Definition: gravi_pfits.h:73
#define GRAVI_OI_FLUX_EXT
Definition: gravi_pfits.h:93
#define QC_MEANTRANS_SC
Definition: gravi_pfits.h:160
#define GRAVI_P2VM_DATA_SC_EXT
Definition: gravi_pfits.h:72
#define GRAVI_EXTVER(type, pol, npol)
Definition: gravi_pfits.h:204
gravi_detector_type
Definition: gravi_pfits.h:170
@ GRAVI_DET_FT
Definition: gravi_pfits.h:171
@ GRAVI_DET_ALL
Definition: gravi_pfits.h:173
@ GRAVI_DET_SC
Definition: gravi_pfits.h:172
#define QC_MEANCOH_SC
Definition: gravi_pfits.h:151
#define GRAVI_P2VM_MET_EXT
Definition: gravi_pfits.h:71
#define QC_MEANCOH_FT
Definition: gravi_pfits.h:154
#define QC_RMSCOH_SC
Definition: gravi_pfits.h:152
#define GRAVI_TYPE(type)
Definition: gravi_pfits.h:167
#define QC_RMSPHASE_FT
Definition: gravi_pfits.h:156
#define QC_MINTRANS_FT
Definition: gravi_pfits.h:158
#define QC_RMSCOH_FT
Definition: gravi_pfits.h:155
#define GRAVI_IMAGING_DETECTOR_EXT(type)
Definition: gravi_pfits.h:51
#define QC_MEANTRANS_FT
Definition: gravi_pfits.h:157
#define QC_MAXTRANS_FT
Definition: gravi_pfits.h:159
#define QC_RMSPHASE_SC
Definition: gravi_pfits.h:153
#define GRAVI_OI_WAVELENGTH_EXT
Definition: gravi_pfits.h:91
#define gravi_spectrum_get_npol(table)
Definition: gravi_utils.h:92
#define gravi_msg_function_exit(flag)
Definition: gravi_utils.h:85
#define FREE(function, variable)
Definition: gravi_utils.h:69
#define CPLCHECK_NUL(msg)
Definition: gravi_utils.h:48
#define gravi_msg_function_start(flag)
Definition: gravi_utils.h:84
#define CPLCHECK_MSG(msg)
Definition: gravi_utils.h:45
#define FREELOOP(function, variable, n)
Definition: gravi_utils.h:72
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:1137
cpl_matrix * gravi_matrix_invertSV_create(cpl_matrix *a_in)
Invers a matrix with singular value decomposition.
Definition: gravi_cpl.c:2921
cpl_error_code gravi_array_add_phase(cpl_array *input, double factor, cpl_array *phase)
Add a REAL phase to a REAL phase array, in-place: input = input + factor * phase.
Definition: gravi_cpl.c:1241
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:1757
double gravi_array_get_quantile(cpl_array *arr, double thr)
Compute the value of the vector corresponding to the quantile 'thr' (0 < thr < 1)
Definition: gravi_cpl.c:2511
cpl_error_code gravi_imagelist_unwrap_images(cpl_imagelist *imglist)
Unwrap an imagelist an all its images.
Definition: gravi_cpl.c:1727
cpl_error_code gravi_array_get_group_delay_loop(cpl_array **input, cpl_array **flag, 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:1403
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:2235
cpl_array * gravi_table_create_sigma_array(cpl_table *oi_wave)
Definition: gravi_cpl.c:1024
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:1159
cpl_error_code gravi_array_multiply_conj(cpl_array *input1, cpl_array *input2)
Definition: gravi_cpl.c:1262
cpl_propertylist * gravi_data_get_plist(gravi_data *self, const char *extname)
Get the propertylist from EXTNAME.
Definition: gravi_data.c:2049
gravi_data * gravi_data_new(int nb_ext)
Create an empty gravi_data.
Definition: gravi_data.c:110
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:2289
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:2664
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:2096
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:1690
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_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:1267
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,...
Definition: gravi_p2vm.c:880
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:191
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,...
Definition: gravi_p2vm.c:546
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:345
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:1550
gravi_data * gravi_create_p2vm(gravi_data *wave_map, gravi_data *wave_param)
Create a new P2VM map.
Definition: gravi_p2vm.c:413
cpl_table * gravi_create_p2vm_table(cpl_table *detector_table, int nwave)
Create a new p2vm table.
Definition: gravi_p2vm.c:103
int gravi_pfits_get_pola_num(const cpl_propertylist *plist, int type_data)
Definition: gravi_pfits.c:263
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
char GRAVI_BASE_NAME[6][3]
Definition: gravi_utils.c:57
cpl_size gravi_spectrum_get_nwave(const cpl_table *table)
Definition: gravi_utils.c:1013
int gravi_check_shutter(cpl_propertylist *header, int t0, int t1, int t2, int t3)
Definition: gravi_utils.c:943
char GRAVI_DATAERR[50][10]
Definition: gravi_utils.c:79
char GRAVI_DATA[50][7]
Definition: gravi_utils.c:71
cpl_vector * gravi_compute_envelope(const cpl_vector *opd, int wave, int nwave)
Compute the envelope value.
Definition: gravi_utils.c:1081
int GRAVI_BASE_TEL[GRAVI_NBASE][2]
Definition: gravi_utils.c:56
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_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
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