GRAVI Pipeline Reference Manual  1.2.3
gravi_signal.c
1 /* $Id: gravi_vis.c,v 1.10 2014/11/12 15: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  Includes
39  -----------------------------------------------------------------------------*/
40 
41 #ifdef HAVE_CONFIG_H
42 #include <config.h>
43 #endif
44 
45 #include <cpl.h>
46 #include <string.h>
47 #include <stdio.h>
48 #include <math.h>
49 #include <time.h>
50 #include <complex.h>
51 
52 #include "gravi_data.h"
53 #include "gravi_dfs.h"
54 #include "gravi_pfits.h"
55 #include "gravi_cpl.h"
56 
57 #include "gravi_utils.h"
58 #include "gravi_signal.h"
59 
60 /*-----------------------------------------------------------------------------
61  Private prototypes
62  -----------------------------------------------------------------------------*/
63 
64 cpl_error_code gravi_vis_bootstrap_snr_and_delay(cpl_table * oi_vis,
65  const char * name_snr,
66  const char * name_gdl);
67 cpl_error_code gravi_vis_correct_phasediff(cpl_table * oi_vis1, const char *name1,
68  cpl_table * oi_vis2, const char *name2,
69  double * phasediff);
70 cpl_error_code gravi_vis_compute_mean_phasor(cpl_table * oi_vis,
71  const char * name_vis,
72  const char * name_err,
73  const char * name_pha,
74  const char * name_var);
75 cpl_error_code gravi_vis_compute_interspectre (cpl_table * oi_vis,
76  const char * name_vis,
77  const char * name_is);
78 cpl_error_code gravi_vis_compute_snr(cpl_table * oi_vis,
79  const char * name_pha,
80  const char * name_var,
81  const char * name_snr);
82 cpl_error_code gravi_vis_compute_isdelay(cpl_table * oi_vis,
83  const char * name_isp,
84  const char * name_gdl,
85  cpl_table * oi_wavelength);
86 cpl_error_code gravi_vis_create_pfactor_sc (cpl_table * vis_SC, cpl_table * flux_FT);
87 cpl_error_code gravi_vis_create_f1f2_sc (cpl_table * vis_SC, cpl_table * flux_SC);
88 cpl_error_code gravi_vis_create_f1f2_ft (cpl_table * vis_FT, cpl_table * flux_FT);
89 cpl_error_code gravi_vis_create_phaseref_ft (cpl_table * vis_FT);
90 cpl_error_code gravi_vis_create_met_sc (cpl_table * vis_SC, cpl_table * vis_MET);
91 cpl_error_code gravi_flux_create_fddlpos_sc (cpl_table * flux_SC, cpl_table * fddl_table);
92 cpl_error_code gravi_flux_create_totalflux_sc (cpl_table * flux_SC, cpl_table * flux_FT);
93 cpl_error_code gravi_flux_create_met_sc (cpl_table * flux_SC, cpl_table * vis_MET);
94 cpl_error_code gravi_flux_create_acq_sc (cpl_table * vis_SC,
95  cpl_table * vis_ACQ);
96 
97 cpl_error_code gravi_vis_create_acq_sc (cpl_table * vis_SC,
98  cpl_table * vis_ACQ);
99 
100 cpl_error_code gravi_vis_create_vfactor_sc (cpl_table * vis_SC,
101  cpl_table * wave_table_sc,
102  cpl_table * vis_FT,
103  cpl_table * wave_table_ft);
104 cpl_error_code gravi_vis_create_lockratio_sc (cpl_table * vis_SC,
105  cpl_table * vis_FT);
106 
107 cpl_error_code gravi_vis_create_phaseref_sc (cpl_table * vis_SC,
108  cpl_table * wave_table_sc,
109  cpl_table * wave_table_ft);
110 
111 
112 cpl_error_code gravi_vis_create_opddisp_sc (cpl_table * vis_SC,
113  cpl_table * flux_SC,
114  cpl_table * wave_table,
115  cpl_table * disp_table,
116  cpl_propertylist * header,
117  const cpl_parameterlist * parlist);
118 
119 cpl_error_code gravi_vis_create_imagingref_sc (cpl_table * vis_SC,
120  cpl_table * wave_table,
121  cpl_propertylist * header,
122  const cpl_parameterlist * parlist);
123 
124 /*-----------------------------------------------------------------------------
125  Function code
126  -----------------------------------------------------------------------------*/
127 
128 /* -------------------------------------------------------------------------- */
141 /* -------------------------------------------------------------------------- */
142 
143 cpl_error_code gravi_vis_bootstrap_snr_and_delay(cpl_table * oi_vis,
144  const char * name_snr,
145  const char * name_gdl)
146 {
147  gravi_msg_function_start(0);
148  cpl_ensure_code (oi_vis, CPL_ERROR_NULL_INPUT);
149  cpl_ensure_code (name_snr, CPL_ERROR_NULL_INPUT);
150  cpl_ensure_code (name_gdl, CPL_ERROR_NULL_INPUT);
151 
152  /* Get poointer to data */
153  double * snr = cpl_table_get_data_double (oi_vis, name_snr);
154  double * gdl = cpl_table_get_data_double (oi_vis, name_gdl);
155 
156  CPLCHECK_MSG("Cannot load data to compute SNR column");
157 
158  /* Loop on base */
159  cpl_size nrow = cpl_table_get_nrow (oi_vis) / 6;
160  for (int base=0; base<6; base++ ) {
161 
162  /* Loop on the two closing triangles of this baseline */
163  for (int tri=0; tri<2; tri++ ) {
164 
165  /* Search a closing triangle */
166  int b1 = GRAVI_TRI_BASE[base][tri][0];
167  int b2 = GRAVI_TRI_BASE[base][tri][1];
168  int sign1 = GRAVI_TRI_SIGN[base][tri][0];
169  int sign2 = GRAVI_TRI_SIGN[base][tri][1];
170 
171  cpl_msg_debug(cpl_func, "Found triangle tels %i%i -> bases (%i,%i, %i,%i)",
172  GRAVI_BASE_TEL[base][0],GRAVI_BASE_TEL[base][1],b1,b2,sign1,sign2);
173 
174  /* Loop on rows */
175  for (cpl_size row = 0; row < nrow; row++) {
176  /* Get the bootstraped SNR as the min over the closing baseline */
177  double snrN = CPL_MIN( snr[row*6+b1], snr[row*6+b2] );
178  if ( snrN > snr[row*6+base] ) {
179  snr[row*6+base] = snrN;
180  gdl[row*6+base] = sign1 * gdl[row*6+b1] + sign2 * gdl[row*6+b2];
181  }
182  }
183  /* End loop on rows */
184  }
185  /* End loop on closing triangle */
186 
187  cpl_msg_debug(cpl_func,"TODO: loop on 3-baseline bootstrap");
188  }
189  /* End loop on base */
190 
191  gravi_msg_function_exit(0);
192  return CPL_ERROR_NONE;
193 }
194 
195 /* -------------------------------------------------------------------------- */
209 /* -------------------------------------------------------------------------- */
210 
211 cpl_error_code gravi_vis_correct_phasediff(cpl_table * oi_vis1, const char *name1,
212  cpl_table * oi_vis2, const char *name2,
213  double * phasediff)
214 {
215  gravi_msg_function_start(0);
216  cpl_ensure_code (oi_vis1, CPL_ERROR_NULL_INPUT);
217  cpl_ensure_code (oi_vis2, CPL_ERROR_NULL_INPUT);
218  cpl_ensure_code (name1, CPL_ERROR_NULL_INPUT);
219  cpl_ensure_code (name2, CPL_ERROR_NULL_INPUT);
220  cpl_ensure_code (phasediff, CPL_ERROR_ILLEGAL_OUTPUT);
221 
222  int nbase = 6;
223 
224  cpl_type type1 = cpl_table_get_column_type (oi_vis1, name1 );
225  cpl_type type2 = cpl_table_get_column_type (oi_vis2, name2 );
226  cpl_size nrow1 = cpl_table_get_nrow (oi_vis1) / nbase;
227  cpl_size nrow2 = cpl_table_get_nrow (oi_vis2) / nbase;
228 
229  if ( type1 != CPL_TYPE_DOUBLE_COMPLEX ||
230  type2 != CPL_TYPE_DOUBLE_COMPLEX ||
231  nrow1 != nrow2)
232  return cpl_error_set_message (cpl_func,CPL_ERROR_ILLEGAL_INPUT,"input columns not conformables or not DOUBLE COMPLEX");
233 
234  double complex * data1 = cpl_table_get_data_double_complex (oi_vis1, name1);
235  double complex * data2 = cpl_table_get_data_double_complex (oi_vis2, name2);
236  CPLCHECK_MSG("Cannot load data");
237 
238  /* Loop on base */
239  for (int base = 0; base < nbase; base++) {
240  double complex phasor = 0.0;
241 
242  /* Multiply and sum */
243  for (cpl_size row = 0; row < nrow1; row++) {
244  phasor += data1[row*nbase+base] * conj( data2[row*6+base] );
245  }
246 
247  phasediff[base] = carg( phasor );
248 
249  /* Correct phase from oi_vis1 to be the one of oi_vis2 */
250  for (cpl_size row = 0; row < nrow1; row++) {
251  data1[row*6+base] *= cexp( -I*phasediff[base] );
252  }
253  }
254 
255  gravi_msg_function_exit(0);
256  return CPL_ERROR_NONE;
257 }
258 
259 /* -------------------------------------------------------------------------- */
270 /* -------------------------------------------------------------------------- */
271 
272 cpl_error_code gravi_vis_compute_mean_phasor(cpl_table * oi_vis,
273  const char * name_vis,
274  const char * name_err,
275  const char * name_pha,
276  const char * name_var)
277 {
278  gravi_msg_function_start(0);
279  cpl_ensure_code (oi_vis, CPL_ERROR_NULL_INPUT);
280  cpl_ensure_code (name_vis, CPL_ERROR_NULL_INPUT);
281  cpl_ensure_code (name_err, CPL_ERROR_NULL_INPUT);
282  cpl_ensure_code (name_pha, CPL_ERROR_ILLEGAL_OUTPUT);
283  cpl_ensure_code (name_var, CPL_ERROR_ILLEGAL_OUTPUT);
284 
285  cpl_size nrow = cpl_table_get_nrow (oi_vis);
286 
287  /* Init memory for the output array. */
288  gravi_table_new_column (oi_vis, name_pha, "e", CPL_TYPE_DOUBLE_COMPLEX);
289  double complex * phasorRaw = cpl_table_get_data_double_complex (oi_vis, name_pha);
290 
291  gravi_table_new_column (oi_vis, name_var, "e^2", CPL_TYPE_DOUBLE);
292  double * varRaw = cpl_table_get_data_double (oi_vis, name_var);
293 
294  /* Get input pointer to speed up */
295  cpl_array** tVis = cpl_table_get_data_array (oi_vis, name_vis);
296  cpl_array** tErr = cpl_table_get_data_array (oi_vis, name_err);
297 
298  /* Get nwave */
299  int nwave = cpl_array_get_size (tVis[0]);
300 
301  CPLCHECK_MSG ("Cannot get data");
302 
303  /* Loop on rows and bases */
304  for (cpl_size row = 0; row < nrow; row++ ) {
305 
306  double complex * cpx = cpl_array_get_data_double_complex (tVis[row]);
307  double complex * err = cpl_array_get_data_double_complex (tErr[row]);
308  cpl_ensure_code (cpx, CPL_ERROR_ILLEGAL_INPUT);
309  cpl_ensure_code (err, CPL_ERROR_ILLEGAL_INPUT);
310  phasorRaw[row] = 0.0;
311  varRaw[row] = 0.0;
312 
313  /* Compute integrated phasor and variance over the spectral channels */
314  for (cpl_size wave = 0; wave < nwave; wave++) {
315  phasorRaw[row] += cpx[wave];
316  varRaw[row] += cabs(err[wave]) * cabs(err[wave]);
317  }
318 
319  }
320  /* End loop on rows */
321 
322  CPLCHECK_MSG("Cannot fill IS and PHASOR column");
323 
324  gravi_msg_function_exit(0);
325  return CPL_ERROR_NONE;
326 }
327 
328 /* -------------------------------------------------------------------------- */
339 /* -------------------------------------------------------------------------- */
340 
341 cpl_error_code gravi_vis_compute_interspectre (cpl_table * oi_vis,
342  const char * name_vis,
343  const char * name_is)
344 {
345  gravi_msg_function_start(0);
346  cpl_ensure_code (oi_vis, CPL_ERROR_NULL_INPUT);
347  cpl_ensure_code (name_vis, CPL_ERROR_NULL_INPUT);
348  cpl_ensure_code (name_is, CPL_ERROR_NULL_INPUT);
349 
350  cpl_size nrow = cpl_table_get_nrow (oi_vis);
351 
352  /* Get input pointer to speed up */
353  cpl_array** tVis = cpl_table_get_data_array (oi_vis, name_vis);
354  cpl_ensure_code (tVis, CPL_ERROR_ILLEGAL_INPUT);
355 
356  /* Get nwave */
357  int nwave = cpl_array_get_size (tVis[0]);
358 
359  CPLCHECK_MSG ("Cannot get data");
360 
361  /* Init memory for the output array. */
362  gravi_table_new_column (oi_vis, name_is, "e^2", CPL_TYPE_DOUBLE_COMPLEX);
363  double complex * interSpectreRaw = cpl_table_get_data_double_complex (oi_vis, name_is);
364 
365  CPLCHECK_MSG ("Cannot create columns");
366 
367  /* Loop on rows and bases */
368  for (cpl_size row = 0; row < nrow; row++) {
369 
370  double complex * cpx = cpl_array_get_data_double_complex (tVis[row]);
371  cpl_ensure_code (cpx, CPL_ERROR_ILLEGAL_INPUT);
372 
373  interSpectreRaw[row] = 0.0;
374 
375  /* Compute integrated interspectre over the spectral channels */
376  for (cpl_size wave = 0; wave < nwave-1; wave++)
377  interSpectreRaw[row] += cpx[wave] * conj( cpx[wave+1] );
378  }
379  /* End loop on rows */
380 
381  CPLCHECK_MSG ("Cannot fill IS column");
382 
383  gravi_msg_function_exit(0);
384  return CPL_ERROR_NONE;
385 }
386 
387 
388 /* -------------------------------------------------------------------------- */
399 /* -------------------------------------------------------------------------- */
400 
401 cpl_error_code gravi_vis_compute_snr (cpl_table * oi_vis,
402  const char * name_pha,
403  const char * name_var,
404  const char * name_snr)
405 {
406  gravi_msg_function_start(0);
407  cpl_ensure_code (oi_vis, CPL_ERROR_NULL_INPUT);
408  cpl_ensure_code (name_pha, CPL_ERROR_NULL_INPUT);
409  cpl_ensure_code (name_var, CPL_ERROR_NULL_INPUT);
410  cpl_ensure_code (name_snr, CPL_ERROR_ILLEGAL_OUTPUT);
411 
412  cpl_size nrow = cpl_table_get_nrow (oi_vis);
413 
414  /* Get input pointer to data */
415  double complex * cpx = cpl_table_get_data_double_complex (oi_vis, name_pha);
416  double * dbl = cpl_table_get_data_double (oi_vis, name_var);
417 
418  CPLCHECK_MSG ("Cannot load data to compute SNR column");
419 
420  /* Init memory for the output array. */
421  gravi_table_new_column (oi_vis, name_snr, NULL, CPL_TYPE_DOUBLE);
422  double * snr = cpl_table_get_data_double (oi_vis, name_snr);
423 
424  CPLCHECK_MSG ("Cannot createl SNR column");
425 
426  /* Loop on rows and bases */
427  for (cpl_size row = 0; row < nrow; row++) {
428  snr[row] = cabs( cpx[row] ) / sqrt (fabs(dbl[row]));
429  }
430 
431  CPLCHECK_MSG ("Cannot fill SNR column");
432 
433  gravi_msg_function_exit(0);
434  return CPL_ERROR_NONE;
435 }
436 
437 /* -------------------------------------------------------------------------- */
449 /* -------------------------------------------------------------------------- */
450 
451 cpl_error_code gravi_vis_compute_isdelay (cpl_table * oi_vis,
452  const char * name_isp,
453  const char * name_gdl,
454  cpl_table * oi_wavelength)
455 {
456  gravi_msg_function_start(0);
457  cpl_ensure_code (oi_vis, CPL_ERROR_NULL_INPUT);
458  cpl_ensure_code (name_isp, CPL_ERROR_NULL_INPUT);
459  cpl_ensure_code (name_gdl, CPL_ERROR_NULL_INPUT);
460  cpl_ensure_code (oi_wavelength, CPL_ERROR_NULL_INPUT);
461 
462  cpl_size nrow = cpl_table_get_nrow (oi_vis);
463 
464  /* Get pointer to data */
465  double complex * cpx1 = cpl_table_get_data_double_complex (oi_vis, name_isp);
466 
467  CPLCHECK_MSG("Cannot load data to compute GDELAY column");
468 
469  /* Init memory for the output array. */
470  gravi_table_new_column (oi_vis, name_gdl, "m", CPL_TYPE_DOUBLE);
471  double * gdl = cpl_table_get_data_double (oi_vis, name_gdl);
472  CPLCHECK_MSG("Cannot set GDELAY column");
473 
474  /* Compute the coherence */
475  cpl_size wave = cpl_table_get_ncol (oi_wavelength)/2;
476  double factor = 1./fabs(1./cpl_table_get (oi_wavelength, "EFF_WAVE", wave, NULL) -
477  1./cpl_table_get (oi_wavelength, "EFF_WAVE", wave+1, NULL));
478 
479  cpl_msg_debug (cpl_func, "Compute the coherence length (%e m)", factor);
480 
481  CPLCHECK_MSG("Cannot compute coherence length");
482 
483  /* Loop on rows and bases */
484  for (cpl_size row = 0; row < nrow; row++ ) {
485  /* Compute the GD */
486  gdl[row] = (double)carg( cpx1[row] ) / (2.0*M_PI) * factor;
487  }
488 
489  CPLCHECK_MSG("Cannot fill GDELAY column");
490 
491  gravi_msg_function_exit(0);
492  return CPL_ERROR_NONE;
493 }
494 
495 
496 /*----------------------------------------------------------------------------*/
509 /*----------------------------------------------------------------------------*/
510 
511 cpl_error_code gravi_compute_snr (gravi_data * p2vmred_data,
512  const cpl_parameterlist * parlist)
513 {
514  /* Message and timer */
515  gravi_msg_function_start(1);
516  cpl_ensure_code (p2vmred_data, CPL_ERROR_NULL_INPUT);
517 
518  char qc_name[90];
519  int nbase = 6;
520 
521  cpl_propertylist * p2vmred_header = gravi_data_get_header (p2vmred_data);
522  double periode_sc = gravi_pfits_get_period_sc (p2vmred_header); // [s]
523  CPLCHECK_MSG ("Cannot get header");
524 
525  /*
526  * Compute the real-time group-delay and SNR
527  * as well as a running average.
528  */
529 
530  /* Loop on polarisations and type_data */
531  for (int type_data = 0; type_data < 2; type_data ++) {
532 
533  if (gravi_data_has_type (p2vmred_data, GRAVI_TYPE(type_data)) < 2 ) {
534  cpl_msg_info (cpl_func, "Cannot compute real-time snr for %s "
535  "(no data)", GRAVI_TYPE(type_data));
536  continue;
537  }
538 
539  int nsmooth;
540  if (type_data == GRAVI_FT) {
541  /* For FT, the DIT is selected to match somehow the atmospheric
542  * coherence time, hence we shall smooth over 'a few' samples */
543  nsmooth = gravi_param_get_int (parlist, "gravity.signal.nsmooth-snr-ft");
544  }
545  else {
546  /* For SC, we select a smoothing of 1s. Note that the SNR of SC is
547  * not used for selecting frame, thus this choice is not critical */
548  nsmooth = 1./ periode_sc;
549  nsmooth = CPL_MIN (CPL_MAX (nsmooth, 0), 20);
550  }
551 
552 
553  /* Loop on polarisation */
554  int npol = gravi_pfits_get_pola_num (p2vmred_header, type_data);
555  for (int pol = 0; pol < npol; pol++) {
556 
557  cpl_msg_info(cpl_func, "Compute SNR for pol %i of %s (smoothed over %i frames)",
558  pol+1,GRAVI_TYPE(type_data),2*nsmooth+1);
559 
560  cpl_table * oi_vis = gravi_data_get_oi_vis (p2vmred_data, type_data, pol, npol);
561  CPLCHECK_MSG ("Cannot get data");
562 
563  /* Compute interspectre and phasor */
564  gravi_vis_compute_interspectre (oi_vis, "VISDATA", "IPHASOR");
565  gravi_vis_compute_mean_phasor (oi_vis, "VISDATA", "VISERR", "PHASOR", "PHASOR_VAR");
566 
567  /* Compute real-time SNR */
568  gravi_vis_compute_snr (oi_vis, "PHASOR", "PHASOR_VAR", "SNR");
569  CPLCHECK_MSG ("Cannot compute PHASOR and IPHASOR");
570 
571  /* Compute a smoothed version of quantities. Note that this is a running SUM,
572  * not a running MEAN. Hence the SNR is enlarged by the smoothing */
573  gravi_table_runint_column (oi_vis, "IPHASOR", "IPHASOR_SMT", nsmooth, nbase);
574  gravi_table_runint_column (oi_vis, "PHASOR", "PHASOR_SMT", nsmooth, nbase);
575  gravi_table_runint_column (oi_vis, "PHASOR_VAR", "PHASOR_VAR_SMT", nsmooth, nbase);
576  CPLCHECK_MSG ("Cannot running integration");
577 
578  } /* End loop on pol */
579  } /* End loop on type_data */
580 
581  /*
582  * Compute bootstraped GD and SNR for the FT.
583  * Bootstraped meant with all possible information merging
584  * (polar, baseline, time)
585  */
586 
587  /* Loop on type_data */
588  for (int type_data = 0; type_data < 2; type_data ++) {
589 
590  if (gravi_data_has_type (p2vmred_data, GRAVI_TYPE(type_data)) < 2 ) {
591  cpl_msg_info (cpl_func, "Cannot compute bootstraped snr %s "
592  "(no data)", GRAVI_TYPE(type_data));
593  continue;
594  }
595 
596  int npol = gravi_pfits_get_pola_num (p2vmred_header, type_data);
597 
598  cpl_msg_info(cpl_func, "Compute bootstraped GDELAY_BOOT and SNR for %s...",(type_data==GRAVI_FT?"FT":"SC"));
599 
600  /* Get the FT data */
601  cpl_table * oi_wave = gravi_data_get_oi_wave (p2vmred_data, type_data, 0, npol);
602  cpl_table * oi_vis_p2, * oi_vis_p1;
603  oi_vis_p1 = gravi_data_get_oi_vis (p2vmred_data, type_data, 0, npol);
604 
605  CPLCHECK_MSG("Cannot get OI_VIS_P1 table");
606 
607  /* Duplicate interspectre to get the bootstraped column */
608  cpl_table_duplicate_column (oi_vis_p1, "IPHASOR_BOOT", oi_vis_p1, "IPHASOR_SMT");
609  CPLCHECK_MSG("Cannot duplicate columns");
610 
611  /* Duplicate phasor and variance to get the bootstraped column. */
612  cpl_table_duplicate_column (oi_vis_p1, "PHASOR_BOOT", oi_vis_p1, "PHASOR_SMT");
613  CPLCHECK_MSG("Cannot duplicate columns");
614 
615  cpl_table_duplicate_column (oi_vis_p1, "PHASOR_VAR_BOOT", oi_vis_p1, "PHASOR_VAR_SMT");
616  CPLCHECK_MSG("Cannot duplicate columns");
617 
618  /* If two polarisations */
619  if ( npol > 1) {
620 
621  cpl_msg_info(cpl_func, "Add the signal of both polarisation to enhance SNR and GDELAY accuracy");
622  oi_vis_p2 = gravi_data_get_oi_vis (p2vmred_data, type_data, 1, npol);
623 
624  CPLCHECK_MSG("Cannot get OI_VIS_P2 table");
625 
626  /* Sum the interspectre of the second polarisation. No need to deal
627  * with polarisation shifts as they probably have the same GD */
628  gravi_table_add_columns (oi_vis_p1, "IPHASOR_BOOT", oi_vis_p2, "IPHASOR_SMT");
629  CPLCHECK_MSG("Cannot add columns");
630 
631  /* Removing the mean phase difference from PHASOR of first polarisation
632  * to be able to sum with maximum SNR */
633  double phasediff[6];
634  gravi_vis_correct_phasediff (oi_vis_p1, "PHASOR_BOOT", oi_vis_p2, "PHASOR_SMT", phasediff);
635 
636  /* Sum the phasor and the variance of the second polarisation. */
637  gravi_table_add_columns (oi_vis_p1, "PHASOR_BOOT", oi_vis_p2, "PHASOR_SMT");
638  gravi_table_add_columns (oi_vis_p1, "PHASOR_VAR_BOOT", oi_vis_p2, "PHASOR_VAR_SMT");
639 
640  /* Dump these phase difference as QC parameters */
641  cpl_msg_info(cpl_func,"Add the phase difference as QC parameters");
642  for (int base = 0; base < nbase; base++) {
643  sprintf (qc_name, "ESO QC PHASE_POLDIFF_%s%d%d",(type_data==GRAVI_FT?"FT":"SC"),
644  GRAVI_BASE_TEL[base][0]+1, GRAVI_BASE_TEL[base][1]+1);
645  cpl_propertylist_update_double (p2vmred_header, qc_name, phasediff[base] * CPL_MATH_DEG_RAD);
646  cpl_propertylist_set_comment (p2vmred_header, qc_name, "[deg] differential phase" );
647  cpl_msg_info (cpl_func,"%s=%f [deg]",qc_name,phasediff[base] * CPL_MATH_DEG_RAD);
648  CPLCHECK_MSG("QC PHASE_POLDIFF");
649  }
650 
651  CPLCHECK_MSG("Cannot add columns of second polarisation");
652  }
653  /* End case two polarisations */
654 
655  /* Compute the highest possible GDDELAY and SNR per baseline. */
656  gravi_vis_compute_isdelay (oi_vis_p1, "IPHASOR_BOOT", "GDELAY_BOOT",oi_wave);
657  gravi_vis_compute_snr (oi_vis_p1, "PHASOR_BOOT", "PHASOR_VAR_BOOT", "SNR_BOOT_TMP");
658 
659  /* Bootstrap over the baselines. Note the aggressive smooth of SNR to avoid
660  * bootstrapoing on noisy SNR (stabilization). */
661  int nstabilize = (type_data == GRAVI_FT ? 50 : 1);
662  gravi_table_smooth_column (oi_vis_p1, "SNR_BOOT_TMP", "SNR_BOOT", nstabilize, nbase);
663  gravi_vis_bootstrap_snr_and_delay (oi_vis_p1, "SNR_BOOT", "GDELAY_BOOT");
664 
665  CPLCHECK_MSG("Cannot compute and fill SNR_BOOT or GDELAY_BOOT column");
666 
667  /* If two polarisations. Copy this SNR and GDELAY to the second polarisation */
668  if (npol > 1) {
669  cpl_msg_info (cpl_func, "Duplicate columns in polarisation 2");
670  if (cpl_table_has_column (oi_vis_p2, "SNR_BOOT"))
671  cpl_table_erase_column(oi_vis_p2, "SNR_BOOT");
672  cpl_table_duplicate_column (oi_vis_p2, "SNR_BOOT", oi_vis_p1, "SNR_BOOT");
673 
674  if (cpl_table_has_column (oi_vis_p2, "GDELAY_BOOT"))
675  cpl_table_erase_column(oi_vis_p2, "GDELAY_BOOT");
676  cpl_table_duplicate_column (oi_vis_p2, "GDELAY_BOOT", oi_vis_p1, "GDELAY_BOOT");
677  CPLCHECK_MSG("Cannot duplicate column for polarisation 2");
678  }
679 
680  /* Remove useless column (IPHASOR, PHASOR, PHASOR_VAR) when the
681  * smoothing and bootstraping are done */
682  cpl_msg_info (cpl_func, "Erase useless columns in P2VMREDUCED");
683 
684  cpl_table_erase_column (oi_vis_p1, "IPHASOR");
685  cpl_table_erase_column (oi_vis_p1, "IPHASOR_SMT");
686  cpl_table_erase_column (oi_vis_p1, "IPHASOR_BOOT");
687  cpl_table_erase_column (oi_vis_p1, "PHASOR");
688  cpl_table_erase_column (oi_vis_p1, "PHASOR_SMT");
689  cpl_table_erase_column (oi_vis_p1, "PHASOR_BOOT");
690  cpl_table_erase_column (oi_vis_p1, "PHASOR_VAR");
691  cpl_table_erase_column (oi_vis_p1, "PHASOR_VAR_SMT");
692  cpl_table_erase_column (oi_vis_p1, "PHASOR_VAR_BOOT");
693  cpl_table_erase_column (oi_vis_p1, "SNR_BOOT_TMP");
694  CPLCHECK_MSG("Cannot erase column for polarisation 1");
695 
696  if ( npol > 1) {
697  cpl_table_erase_column (oi_vis_p2, "IPHASOR");
698  cpl_table_erase_column (oi_vis_p2, "IPHASOR_SMT");
699  cpl_table_erase_column (oi_vis_p2, "PHASOR");
700  cpl_table_erase_column (oi_vis_p2, "PHASOR_SMT");
701  cpl_table_erase_column (oi_vis_p2, "PHASOR_VAR");
702  cpl_table_erase_column (oi_vis_p2, "PHASOR_VAR_SMT");
703  CPLCHECK_MSG("Cannot erase column for polarisation 2");
704  }
705 
706  /* Add the QC */
707  char qc_name[100];
708  double qc_value;
709 
710  for (cpl_size base = 0; base < nbase; base++) {
711  snprintf (qc_name, 100, "ESO QC SNRB_%s%s AVG", GRAVI_TYPE(type_data), GRAVI_BASE_NAME[base]);
712  qc_value = gravi_table_get_column_mean (oi_vis_p1, "SNR_BOOT", base, nbase);
713  cpl_propertylist_update_double (p2vmred_header, qc_name, qc_value);
714  cpl_propertylist_set_comment (p2vmred_header, qc_name, "mean bootstrapped SNR");
715  }
716 
717  } /* End loop on type_data */
718 
719  gravi_msg_function_exit(1);
720  return CPL_ERROR_NONE;
721 }
722 
723 
724 /*----------------------------------------------------------------------------*/
741 /*----------------------------------------------------------------------------*/
742 
743 cpl_error_code gravi_signal_create_sync (cpl_table * vis_SC, int nbase_sc, double dit_sc,
744  cpl_table * vis_FT, int nbase_ft,
745  const char * name)
746 {
747  gravi_msg_function_start(1);
748  cpl_ensure_code (vis_SC, CPL_ERROR_NULL_INPUT);
749  cpl_ensure_code (vis_FT, CPL_ERROR_NULL_INPUT);
750 
751  /* Get the number of rows */
752  cpl_size nrow_sc = cpl_table_get_nrow (vis_SC) / nbase_sc;
753  cpl_size nrow_ft = cpl_table_get_nrow (vis_FT) / nbase_ft;
754 
755  CPLCHECK_MSG ("Cannot get data");
756 
757  /* Create columns in vis_SC */
758  char full_name[90];
759  sprintf (full_name, "FIRST_%s", name);
760  gravi_table_new_column (vis_SC, full_name, NULL, CPL_TYPE_INT);
761  int * first_ft = cpl_table_get_data_int (vis_SC, full_name);
762 
763  sprintf (full_name, "LAST_%s", name);
764  gravi_table_new_column (vis_SC, full_name, NULL, CPL_TYPE_INT);
765  int * last_ft = cpl_table_get_data_int (vis_SC, full_name);
766 
767  sprintf (full_name, "NFRAME_%s", name);
768  gravi_table_new_column (vis_SC, full_name, NULL, CPL_TYPE_INT);
769  int * nframe_ft = cpl_table_get_data_int (vis_SC, full_name);
770 
771  CPLCHECK_MSG ("Cannot create columns");
772 
773  /* Loop on base (here assume base may have different timing) */
774  for (cpl_size base_sc = 0; base_sc < nbase_sc; base_sc++) {
775 
776  /* Start info on the second table
777  * base_ft is always 0 if nbase_ft is 1 */
778  cpl_size row_ft = 0;
779  cpl_size base_ft = base_sc % nbase_ft;
780 
781  /* Loop on SC rows */
782  for (cpl_size row_sc = 0; row_sc < nrow_sc; row_sc ++) {
783 
784  /* Get the first FT sample */
785  while ( cpl_table_get (vis_FT, "TIME", row_ft * nbase_ft + base_ft, NULL) <
786  cpl_table_get (vis_SC, "TIME", row_sc * nbase_sc + base_sc, NULL) - dit_sc/2.) {
787  if (row_ft >= nrow_ft-1) break; // avoid reading outside of the table
788  row_ft ++;
789  }
790  first_ft[row_sc * nbase_sc + base_sc] = row_ft;
791 
792  /* Get the last sample */
793  while ( cpl_table_get (vis_FT, "TIME", row_ft * nbase_ft + base_ft, NULL) <
794  cpl_table_get (vis_SC, "TIME", row_sc * nbase_sc + base_sc, NULL) + dit_sc/2.) {
795  if (row_ft >= nrow_ft-1) break; // avoid reading outside of the table
796  row_ft ++;
797  }
798  last_ft[row_sc * nbase_sc + base_sc] = row_ft;
799 
800  /* Check if enough data */
801  if ( first_ft[row_sc * nbase_sc + base_sc] < 2 ||
802  last_ft[row_sc * nbase_sc + base_sc] > nrow_ft - 2 ) {
803  cpl_msg_warning (cpl_func,"Not enough %s data to synchronise with DIT %lli over %lli", name, row_sc+1, nrow_sc);
804  first_ft[row_sc * nbase_sc + base_sc] = 0;
805  last_ft[row_sc * nbase_sc + base_sc] = 0;
806  }
807 
808  /* Number of frames */
809  nframe_ft[row_sc * nbase_sc + base_sc] = last_ft[row_sc * nbase_sc + base_sc] - first_ft[row_sc * nbase_sc + base_sc];
810  }
811  }
812  /* End loop on SC row and base */
813 
814  gravi_msg_function_exit(1);
815  return CPL_ERROR_NONE;
816 }
817 
818 /* -------------------------------------------------------------------------- */
828 /* -------------------------------------------------------------------------- */
829 
830 cpl_error_code gravi_vis_create_pfactor_sc (cpl_table * vis_SC, cpl_table * flux_FT)
831 {
832  gravi_msg_function_start(1);
833  cpl_ensure_code (vis_SC, CPL_ERROR_NULL_INPUT);
834  cpl_ensure_code (flux_FT, CPL_ERROR_NULL_INPUT);
835 
836  /* Get the number of rows */
837  cpl_size nbase = 6, ntel = 4;
838  cpl_size nrow_sc = cpl_table_get_nrow (vis_SC) / nbase;
839 
840  /* Create the column */
841  gravi_table_new_column (vis_SC, "P_FACTOR", NULL, CPL_TYPE_DOUBLE);
842  double * pFactor = cpl_table_get_data_double (vis_SC, "P_FACTOR");
843 
844  /* Get SC data */
845  int * first_ft = cpl_table_get_data_int (vis_SC, "FIRST_FT");
846  int * last_ft = cpl_table_get_data_int (vis_SC, "LAST_FT");
847 
848  /* Get FT data (used already computed and smoothed total-flux) */
849  double * flux = cpl_table_get_data_double (flux_FT, "TOTALFLUX");
850 
851  CPLCHECK_MSG ("Cannot get pointer to data");
852 
853  /* Loop on base and SC rows */
854  for (cpl_size base = 0; base < nbase; base++) {
855  for (cpl_size row_sc = 0; row_sc < nrow_sc; row_sc ++) {
856  cpl_size nsc = row_sc*nbase+base;
857 
858  /* Loop on the sync FT frames */
859  double sf0f1 = 0.0, f0 = 0.0, f1 = 0.0;
860  for (cpl_size row_ft = first_ft[nsc] ; row_ft < last_ft[nsc]; row_ft++) {
861  int t0 = GRAVI_BASE_TEL[base][0] + row_ft * ntel;
862  int t1 = GRAVI_BASE_TEL[base][1] + row_ft * ntel;
863  sf0f1 += sqrt (CPL_MAX(flux[t0] * flux[t1], 0));
864  f0 += flux[t0];
865  f1 += flux[t1];
866  }
867 
868  /* Discard unused */
869  if (f0==0 || f1==0) continue;
870 
871  /* Compute the pFactor */
872  pFactor[nsc] = sf0f1 * sf0f1 / (f0 * f1);
873  }
874  }
875 
876  gravi_msg_function_exit(1);
877  return CPL_ERROR_NONE;
878 }
879 
880 /* -------------------------------------------------------------------------- */
891 /* -------------------------------------------------------------------------- */
892 
893 cpl_error_code gravi_vis_create_f1f2_sc (cpl_table * vis_SC, cpl_table * flux_SC)
894 {
895  gravi_msg_function_start(1);
896  cpl_ensure_code (vis_SC, CPL_ERROR_NULL_INPUT);
897  cpl_ensure_code (flux_SC, CPL_ERROR_NULL_INPUT);
898 
899  cpl_size nbase = 6, ntel = 4;
900  cpl_size nrow_sc = cpl_table_get_nrow (flux_SC) / ntel;
901  cpl_size nwave_sc = cpl_table_get_column_depth (flux_SC, "FLUX");
902 
903  /* Get pointer to data */
904  cpl_array ** flux_sc = cpl_table_get_data_array (flux_SC, "FLUX");
905 
906  CPLCHECK_MSG ("Cannot get data");
907 
908  /* New column */
909  gravi_table_new_column_array (vis_SC, "F1F2", "e^2", CPL_TYPE_DOUBLE, nwave_sc);
910  cpl_array ** f1f2_sc = cpl_table_get_data_array (vis_SC, "F1F2");
911 
912  for (cpl_size base = 0; base < nbase; base++) {
913  for (cpl_size row = 0; row < nrow_sc; row ++) {
914 
915  /* Compute the photometric normalisation of SC
916  * This is simply FLUX1 * FLUX2 */
917  f1f2_sc[row*nbase+base] = cpl_array_cast (flux_sc[row*ntel+GRAVI_BASE_TEL[base][0]], CPL_TYPE_DOUBLE);
918  cpl_array_multiply (f1f2_sc[row*nbase+base], flux_sc[row*ntel+GRAVI_BASE_TEL[base][1]]);
919  }
920  }
921 
922  gravi_msg_function_exit(1);
923  return CPL_ERROR_NONE;
924 }
925 
926 /* -------------------------------------------------------------------------- */
939 /* -------------------------------------------------------------------------- */
940 
941 cpl_error_code gravi_vis_create_f1f2_ft (cpl_table * vis_FT, cpl_table * flux_FT)
942 {
943  gravi_msg_function_start(1);
944  cpl_ensure_code (vis_FT, CPL_ERROR_NULL_INPUT);
945  cpl_ensure_code (flux_FT, CPL_ERROR_NULL_INPUT);
946 
947  cpl_size ntel = 4, nbase = 6;
948  cpl_size nrow_ft = cpl_table_get_nrow (flux_FT) / ntel;
949  cpl_size nwave_ft = cpl_table_get_column_depth (flux_FT, "FLUX");
950 
951  /* Get pointer to data */
952  double * total_flux_ft = cpl_table_get_data_double (flux_FT, "TOTALFLUX");
953  cpl_array ** flux_ft = cpl_table_get_data_array (flux_FT, "FLUX");
954 
955  CPLCHECK_MSG ("Cannot get data");
956 
957  /* Compute the four mean_spectra */
958  cpl_array ** mean_spectra = cpl_malloc (4 * sizeof (cpl_array*));
959 
960  for (cpl_size tel = 0; tel < ntel; tel ++) {
961  mean_spectra[tel] = cpl_array_duplicate (flux_ft[tel]);
962  for (cpl_size n = 1; n < nrow_ft; n ++) cpl_array_add (mean_spectra[tel], flux_ft[n*ntel+tel]);
963  cpl_array_divide_scalar (mean_spectra[tel], cpl_array_get_mean (mean_spectra[tel]) * nwave_ft);
964  CPLCHECK_MSG ("Cannot compute mean spectra");
965  }
966 
967  /* Compute the photometric normalisation for the FT:
968  * F1F2 = Fsmooth1(t) * Fsmooth2(t) * mean_spectra1(lbd) * mean_spectra2(lbd) */
969  gravi_table_new_column_array (vis_FT, "F1F2", "e^2", CPL_TYPE_DOUBLE, nwave_ft);
970  cpl_array ** f1f2_ft = cpl_table_get_data_array (vis_FT, "F1F2");
971 
972  CPLCHECK_MSG ("Cannot create columns");
973 
974  /* Loop on base */
975  for (cpl_size base = 0; base < nbase; base++) {
976  int t0 = GRAVI_BASE_TEL[base][0];
977  int t1 = GRAVI_BASE_TEL[base][1];
978  for (cpl_size n = 0; n < nrow_ft; n ++) {
979  f1f2_ft[n*nbase+base] = cpl_array_duplicate (mean_spectra[t0]);
980  cpl_array_multiply (f1f2_ft[n*nbase+base], mean_spectra[t1]);
981  cpl_array_multiply_scalar (f1f2_ft[n*nbase+base], total_flux_ft[n*ntel+t0] * total_flux_ft[n*ntel+t1]);
982  // f1f2_ft[n*nbase+base] = cpl_array_duplicate (flux_ft[n*ntel+t0]);
983  // cpl_array_multiply (f1f2_ft[n*nbase+base], flux_ft[n*ntel+t1]);
984  }
985  }
986 
987  FREELOOP (cpl_array_delete, mean_spectra, 4);
988 
989  gravi_msg_function_exit(1);
990  return CPL_ERROR_NONE;
991 }
992 
993 /* -------------------------------------------------------------------------- */
1003 /* -------------------------------------------------------------------------- */
1004 
1005 cpl_error_code gravi_vis_create_phaseref_ft (cpl_table * vis_FT)
1006 {
1007  gravi_msg_function_start(1);
1008  cpl_ensure_code (vis_FT, CPL_ERROR_NULL_INPUT);
1009 
1010  /* Get the FT data */
1011  cpl_size nbase = 6;
1012  cpl_size nrow_ft = cpl_table_get_nrow (vis_FT) / nbase;
1013  cpl_size nwave_ft = cpl_table_get_column_depth (vis_FT, "VISDATA");
1014  cpl_array ** visData_ft = cpl_table_get_data_array (vis_FT, "VISDATA");
1015 
1016  CPLCHECK_MSG ("Cannot get data");
1017 
1018  /* Create the column */
1019  gravi_table_new_column_array (vis_FT, "SELF_REF", "rad", CPL_TYPE_DOUBLE, nwave_ft);
1020  cpl_array ** phaseref_ft = cpl_table_get_data_array (vis_FT, "SELF_REF");
1021 
1022  CPLCHECK_MSG ("Cannot create columns");
1023 
1024  /* Compute the PHASE_REF for the FT as a weighted
1025  * mean of -3..+3 frames */
1026  for (cpl_size base = 0; base < nbase; base ++) {
1027 
1028  /* Loop on running frames */
1029  for (cpl_size n = 3; n < nrow_ft - 3; n ++) {
1030  phaseref_ft[n*nbase+base] = cpl_array_cast (visData_ft[(n-1)*nbase+base], CPL_TYPE_DOUBLE_COMPLEX);
1031  cpl_array_add (phaseref_ft[n*nbase+base], visData_ft[(n+1)*nbase+base]);
1032  cpl_array_multiply_scalar (phaseref_ft[n*nbase+base], 2.0);
1033  cpl_array_add (phaseref_ft[n*nbase+base], visData_ft[(n-2)*nbase+base]);
1034  cpl_array_add (phaseref_ft[n*nbase+base], visData_ft[(n+2)*nbase+base]);
1035  cpl_array_multiply_scalar (phaseref_ft[n*nbase+base], 2.0);
1036  cpl_array_add (phaseref_ft[n*nbase+base], visData_ft[(n-3)*nbase+base]);
1037  cpl_array_add (phaseref_ft[n*nbase+base], visData_ft[(n+3)*nbase+base]);
1038  // cpl_array_fill_window_complex (phaseref_ft[n*nbase+base], 0, nwave_ft, cpl_array_get_mean_complex (phaseref_ft[n*nbase+base]));
1039  cpl_array_arg (phaseref_ft[n*nbase+base]);
1040  cpl_array_multiply_scalar (phaseref_ft[n*nbase+base], -1.0);
1041 
1042  CPLCHECK_MSG("Cannot compute the PHASE_REF for the FT");
1043  }
1044  phaseref_ft[0*nbase+base] = cpl_array_duplicate (phaseref_ft[3*nbase+base]);
1045  phaseref_ft[1*nbase+base] = cpl_array_duplicate (phaseref_ft[3*nbase+base]);
1046  phaseref_ft[2*nbase+base] = cpl_array_duplicate (phaseref_ft[3*nbase+base]);
1047  phaseref_ft[(nrow_ft-3)*nbase+base] = cpl_array_duplicate (phaseref_ft[(nrow_ft-4)*nbase+base]);
1048  phaseref_ft[(nrow_ft-2)*nbase+base] = cpl_array_duplicate (phaseref_ft[(nrow_ft-4)*nbase+base]);
1049  phaseref_ft[(nrow_ft-1)*nbase+base] = cpl_array_duplicate (phaseref_ft[(nrow_ft-4)*nbase+base]);
1050  }
1051  /* End loop on FT rows and base */
1052 
1053  cpl_msg_warning (cpl_func,"Change of PHASE_REF_FT common channel new... to be decided !!");
1054 
1055  gravi_msg_function_exit(1);
1056  return CPL_ERROR_NONE;
1057 }
1058 
1059 /* -------------------------------------------------------------------------- */
1070 /* -------------------------------------------------------------------------- */
1071 
1072 cpl_error_code gravi_vis_create_acq_sc (cpl_table * vis_SC,
1073  cpl_table * vis_ACQ)
1074 {
1075  gravi_msg_function_start(1);
1076  cpl_ensure_code (vis_SC, CPL_ERROR_NULL_INPUT);
1077  cpl_ensure_code (vis_ACQ, CPL_ERROR_NULL_INPUT);
1078 
1079  cpl_size nbase = 6, ntel = 4;
1080  cpl_size nrow_sc = cpl_table_get_nrow (vis_SC) / nbase;
1081 
1082  /* Get SC data */
1083  int * first = cpl_table_get_data_int (vis_SC, "FIRST_ACQ");
1084  int * last = cpl_table_get_data_int (vis_SC, "LAST_ACQ");
1085  CPLCHECK_MSG("Cannot get data");
1086 
1087  /* Get ACQ data */
1088  int * pup_n = cpl_table_get_data_int (vis_ACQ, "PUPIL_NSPOT");
1089  double * pup_x = cpl_table_get_data_double (vis_ACQ, "PUPIL_X");
1090  double * pup_y = cpl_table_get_data_double (vis_ACQ, "PUPIL_Y");
1091  double * pup_z = cpl_table_get_data_double (vis_ACQ, "PUPIL_Z");
1092  CPLCHECK_MSG("Cannot get direct pointer to data");
1093 
1094  /* New columns */
1095  gravi_table_new_column (vis_SC, "PUPIL_X", NULL, CPL_TYPE_DOUBLE);
1096  double * pup_x_sc = cpl_table_get_data_double (vis_SC, "PUPIL_X");
1097  gravi_table_new_column (vis_SC, "PUPIL_Y", NULL, CPL_TYPE_DOUBLE);
1098  double * pup_y_sc = cpl_table_get_data_double (vis_SC, "PUPIL_Y");
1099  gravi_table_new_column (vis_SC, "PUPIL_Z", NULL, CPL_TYPE_DOUBLE);
1100  double * pup_z_sc = cpl_table_get_data_double (vis_SC, "PUPIL_Z");
1101 
1102  /* Loop on base and rows */
1103  for (cpl_size base = 0; base < nbase; base++) {
1104  for (cpl_size row_sc = 0; row_sc < nrow_sc; row_sc ++) {
1105  cpl_size nsc = row_sc * nbase + base;
1106 
1107  /* Sum over synch ACQ frames, only valid frames */
1108  cpl_size nframe = 0;
1109  for (cpl_size row = first[nsc] ; row < last[nsc]; row++) {
1110  cpl_size row0 = row * ntel + GRAVI_BASE_TEL[base][0];
1111  cpl_size row1 = row * ntel + GRAVI_BASE_TEL[base][1];
1112 
1113  if (pup_n[row0] != 0 && pup_n[row1] !=0 ) {
1114  pup_x_sc[nsc] += pup_x[row0] - pup_x[row1];
1115  pup_y_sc[nsc] += pup_y[row0] - pup_y[row1];
1116  pup_z_sc[nsc] += pup_z[row0] - pup_z[row1];
1117  nframe ++;
1118  }
1119 
1120  CPLCHECK_MSG ("Fail to integrate the ACQ frames");
1121  }
1122 
1123  /* Normalize the means (if nframe == 0, values are zero) */
1124  if (nframe != 0 ){
1125  pup_x_sc[nsc] /= (double)nframe;
1126  pup_y_sc[nsc] /= (double)nframe;
1127  pup_z_sc[nsc] /= (double)nframe;
1128  }
1129 
1130  } /* End loop on SC frames */
1131  }/* End loop on bases */
1132 
1133  gravi_msg_function_exit(1);
1134  return CPL_ERROR_NONE;
1135 }
1136 
1137 /* -------------------------------------------------------------------------- */
1148 /* -------------------------------------------------------------------------- */
1149 
1150 cpl_error_code gravi_flux_create_acq_sc (cpl_table * flux_SC,
1151  cpl_table * vis_ACQ)
1152 {
1153  gravi_msg_function_start(1);
1154  cpl_ensure_code (flux_SC, CPL_ERROR_NULL_INPUT);
1155  cpl_ensure_code (vis_ACQ, CPL_ERROR_NULL_INPUT);
1156 
1157  cpl_size ntel = 4;
1158  cpl_size nrow_sc = cpl_table_get_nrow (flux_SC) / ntel;
1159 
1160  /* Get SC data */
1161  int * first = cpl_table_get_data_int (flux_SC, "FIRST_ACQ");
1162  int * last = cpl_table_get_data_int (flux_SC, "LAST_ACQ");
1163  CPLCHECK_MSG ("Cannot get data");
1164 
1165  /* Get ACQ data */
1166  int * pup_n = cpl_table_get_data_int (vis_ACQ, "PUPIL_NSPOT");
1167  double * pup_x = cpl_table_get_data_double (vis_ACQ, "PUPIL_X");
1168  double * pup_y = cpl_table_get_data_double (vis_ACQ, "PUPIL_Y");
1169  double * pup_z = cpl_table_get_data_double (vis_ACQ, "PUPIL_Z");
1170  CPLCHECK_MSG ("Cannot get direct pointer to data");
1171 
1172  /* New columns -- filled with zero */
1173  gravi_table_new_column (flux_SC, "PUPIL_X", NULL, CPL_TYPE_DOUBLE);
1174  double * pup_x_sc = cpl_table_get_data_double (flux_SC, "PUPIL_X");
1175  gravi_table_new_column (flux_SC, "PUPIL_Y", NULL, CPL_TYPE_DOUBLE);
1176  double * pup_y_sc = cpl_table_get_data_double (flux_SC, "PUPIL_Y");
1177  gravi_table_new_column (flux_SC, "PUPIL_Z", NULL, CPL_TYPE_DOUBLE);
1178  double * pup_z_sc = cpl_table_get_data_double (flux_SC, "PUPIL_Z");
1179 
1180  /* Loop on base and rows */
1181  for (cpl_size tel = 0; tel < ntel; tel++) {
1182  for (cpl_size row_sc = 0; row_sc < nrow_sc; row_sc ++) {
1183  cpl_size nsc = row_sc * ntel + tel;
1184 
1185  /* Sum over synch ACQ frames, only valid frames */
1186  cpl_size nframe = 0;
1187  for (cpl_size row = first[nsc] ; row < last[nsc]; row++) {
1188  cpl_size row0 = row * ntel + tel;
1189 
1190  if (pup_n[row0] != 0) {
1191  pup_x_sc[nsc] += pup_x[row0];
1192  pup_y_sc[nsc] += pup_y[row0];
1193  pup_z_sc[nsc] += pup_z[row0];
1194  nframe ++;
1195  }
1196 
1197  CPLCHECK_MSG ("Fail to integrate the ACQ frames");
1198  }
1199 
1200  /* Normalize the means (if nframe == 0, values are zero) */
1201  if (nframe != 0 ){
1202  pup_x_sc[nsc] /= (double)nframe;
1203  pup_y_sc[nsc] /= (double)nframe;
1204  pup_z_sc[nsc] /= (double)nframe;
1205  }
1206 
1207  } /* End loop on SC frames */
1208  }/* End loop on bases */
1209 
1210  gravi_msg_function_exit(1);
1211  return CPL_ERROR_NONE;
1212 }
1213 
1214 /* -------------------------------------------------------------------------- */
1225 /* -------------------------------------------------------------------------- */
1226 
1227 cpl_error_code gravi_vis_create_met_sc (cpl_table * vis_SC, cpl_table * vis_MET)
1228 {
1229  gravi_msg_function_start(1);
1230  cpl_ensure_code (vis_SC, CPL_ERROR_NULL_INPUT);
1231  cpl_ensure_code (vis_MET, CPL_ERROR_NULL_INPUT);
1232 
1233  cpl_size nbase = 6, ndiode = 4, ntel = 4;
1234  cpl_size nrow_sc = cpl_table_get_nrow (vis_SC) / nbase;
1235 
1236  /* Get SC data */
1237  int * first_met = cpl_table_get_data_int (vis_SC, "FIRST_MET");
1238  int * last_met = cpl_table_get_data_int (vis_SC, "LAST_MET");
1239 
1240  CPLCHECK_MSG("Cannot get data");
1241 
1242  /* Get MET data */
1243  double * phase_met_fc = cpl_table_get_data_double (vis_MET, "PHASE_FC");
1244  double * opd_met_fc = cpl_table_get_data_double (vis_MET, "OPD_FC");
1245  cpl_array ** phase_met_tel = cpl_table_get_data_array (vis_MET, "PHASE_TEL");
1246  cpl_array ** opd_met_tel = cpl_table_get_data_array (vis_MET, "OPD_TEL");
1247  cpl_array ** phasor_met_telfc = cpl_table_get_data_array (vis_MET, "PHASOR_TELFC");
1248 
1249  double * opd_met_fc_corr = cpl_table_get_data_double (vis_MET, "OPD_FC_CORR");
1250  double * opd_met_telfc_mcorr = cpl_table_get_data_double (vis_MET, "OPD_TELFC_MCORR");
1251  cpl_array ** opd_met_telfc_corr = cpl_table_get_data_array (vis_MET, "OPD_TELFC_CORR");
1252 
1253  CPLCHECK_MSG("Cannot get direct pointer to data");
1254 
1255  /* New columns */
1256  gravi_table_new_column (vis_SC, "PHASE_MET_FC", "rad", CPL_TYPE_DOUBLE);
1257  double * phase_metdit_fc = cpl_table_get_data_double (vis_SC, "PHASE_MET_FC");
1258 
1259  gravi_table_new_column (vis_SC, "PHASE_MET_TEL", "rad", CPL_TYPE_DOUBLE);
1260  double * phase_metdit_tel = cpl_table_get_data_double (vis_SC, "PHASE_MET_TEL");
1261 
1262  gravi_table_new_column (vis_SC, "OPD_MET_FC", "m", CPL_TYPE_DOUBLE);
1263  double * opd_metdit_fc = cpl_table_get_data_double (vis_SC, "OPD_MET_FC");
1264 
1265  gravi_table_new_column_array (vis_SC, "OPD_MET_TEL", "m", CPL_TYPE_DOUBLE, ndiode);
1266  cpl_array ** opd_metdit_tel = cpl_table_get_data_array (vis_SC, "OPD_MET_TEL");
1267 
1268  gravi_table_new_column_array (vis_SC, "PHASOR_MET_TELFC", "V^4", CPL_TYPE_DOUBLE_COMPLEX, ndiode);
1269  cpl_array ** phasor_metdit_telfc = cpl_table_get_data_array (vis_SC, "PHASOR_MET_TELFC");
1270 
1271  gravi_table_new_column (vis_SC, "OPD_MET_FC_CORR", "m", CPL_TYPE_DOUBLE);
1272  double * opd_metdit_fc_corr = cpl_table_get_data_double (vis_SC, "OPD_MET_FC_CORR");
1273 
1274  gravi_table_new_column (vis_SC, "OPD_MET_TELFC_MCORR", "m", CPL_TYPE_DOUBLE);
1275  double * opd_metdit_telfc_mcorr = cpl_table_get_data_double (vis_SC, "OPD_MET_TELFC_MCORR");
1276 
1277  gravi_table_new_column_array (vis_SC, "OPD_MET_TELFC_CORR", "m", CPL_TYPE_DOUBLE, ndiode);
1278  cpl_array ** opd_metdit_telfc_corr = cpl_table_get_data_array (vis_SC, "OPD_MET_TELFC_CORR");
1279 
1280  CPLCHECK_MSG("Cannot create columns");
1281 
1282  /* Loop on base and rows */
1283  for (cpl_size base = 0; base < nbase; base++) {
1284  for (cpl_size row_sc = 0; row_sc < nrow_sc; row_sc ++) {
1285  cpl_size nsc = row_sc * nbase + base;
1286 
1287  opd_metdit_tel[nsc] = gravi_array_init_double (ndiode, 0.0);
1288  phasor_metdit_telfc[nsc] = gravi_array_init_double_complex (ndiode, 0.0+I*0.0);
1289  opd_metdit_telfc_corr[nsc] = gravi_array_init_double (ndiode, 0.0);
1290 
1291  /* Sum over synch MET frames */
1292  for (cpl_size row_met = first_met[nsc] ; row_met < last_met[nsc]; row_met++) {
1293  cpl_size nmet0 = row_met * ntel + GRAVI_BASE_TEL[base][0];
1294  cpl_size nmet1 = row_met * ntel + GRAVI_BASE_TEL[base][1];
1295 
1296  /* Mean OPD_FC_CORR and OPD_TELFC_MCORR for each BASELINE */
1297  opd_metdit_fc_corr[nsc] += opd_met_fc_corr[nmet0] - opd_met_fc_corr[nmet1];
1298  opd_metdit_telfc_mcorr[nsc] += opd_met_telfc_mcorr[nmet0] - opd_met_telfc_mcorr[nmet1];
1299 
1300  /* Mean OPD_TELFC_CORR for each BASELINE and diode */
1301  cpl_array_add (opd_metdit_telfc_corr[nsc], opd_met_telfc_corr[nmet0]);
1302  cpl_array_subtract (opd_metdit_telfc_corr[nsc], opd_met_telfc_corr[nmet1]);
1303 
1304  /* Mean OPD_MET at Telescope (each diode) */
1305  cpl_array_add (opd_metdit_tel[nsc], opd_met_tel[nmet0]);
1306  cpl_array_subtract (opd_metdit_tel[nsc], opd_met_tel[nmet1]);
1307 
1308  /* Mean PHASE_MET at Telescope (mean of 4 diodes) */
1309  phase_metdit_tel[nsc] += cpl_array_get_mean (phase_met_tel[nmet0]) -
1310  cpl_array_get_mean (phase_met_tel[nmet1]);
1311 
1312  /* Mean PHASE_MET_FC at Beam Combiner */
1313  phase_metdit_fc[nsc] += phase_met_fc[nmet0] - phase_met_fc[nmet1];
1314 
1315  /* Mean OPD_MET_FC at Beam Combiner */
1316  opd_metdit_fc[nsc] += opd_met_fc[nmet0] - opd_met_fc[nmet1];
1317 
1318  /* Mean PHASOR_MET_TELFC */
1319  gravi_array_add_phasors (phasor_metdit_telfc[nsc],
1320  phasor_met_telfc[nmet0],
1321  phasor_met_telfc[nmet1]);
1322 
1323  CPLCHECK_MSG ("Fail to integrate the metrology");
1324  }
1325 
1326  /* Normalize the means (if nframe == 0, values are zero) */
1327  cpl_size nframe = last_met[nsc] - first_met[nsc];
1328  if (nframe != 0 ){
1329  opd_metdit_fc_corr[nsc] /= nframe;
1330  opd_metdit_telfc_mcorr[nsc] /= nframe;
1331  cpl_array_divide_scalar (opd_metdit_telfc_corr[nsc], (double)nframe);
1332 
1333  cpl_array_divide_scalar (opd_metdit_tel[nsc], (double)nframe);
1334  phase_metdit_tel[nsc] /= nframe;
1335  phase_metdit_fc[nsc] /= nframe;
1336  opd_metdit_fc[nsc] /= nframe;
1337  cpl_array_divide_scalar (phasor_metdit_telfc[nsc], (double)nframe);
1338  }
1339  CPLCHECK_MSG ("Fail to compute metrology per base from metrology per tel");
1340 
1341  } /* End loop on SC frames */
1342  }/* End loop on bases */
1343 
1344 
1345  /* Compute the information comming from VIS_ACQ
1346  * camera... through the VIS_MET */
1347  if (cpl_table_has_column (vis_MET,"FIELD_FIBER_DX")) {
1348 
1349  double * fdx_met = cpl_table_get_data_double (vis_MET, "FIELD_FIBER_DX");
1350  double * fdy_met = cpl_table_get_data_double (vis_MET, "FIELD_FIBER_DY");
1351 
1352  gravi_table_new_column (vis_SC, "FIELD_FIBER_DX", "pix", CPL_TYPE_DOUBLE);
1353  double * fdx_metdit = cpl_table_get_data_double (vis_SC, "FIELD_FIBER_DX");
1354 
1355  gravi_table_new_column (vis_SC, "FIELD_FIBER_DY", "pix", CPL_TYPE_DOUBLE);
1356  double * fdy_metdit = cpl_table_get_data_double (vis_SC, "FIELD_FIBER_DY");
1357 
1358  /* Loop on base and rows */
1359  for (cpl_size base = 0; base < nbase; base++) {
1360  for (cpl_size row_sc = 0; row_sc < nrow_sc; row_sc ++) {
1361  cpl_size nsc = row_sc * nbase + base;
1362 
1363  /* Sum over synch MET frames */
1364  for (cpl_size row_met = first_met[nsc] ; row_met < last_met[nsc]; row_met++) {
1365  cpl_size nmet0 = row_met * ntel + GRAVI_BASE_TEL[base][0];
1366  cpl_size nmet1 = row_met * ntel + GRAVI_BASE_TEL[base][1];
1367 
1368  /* Mean FIELD_FIBER */
1369  fdx_metdit[nsc] += fdx_met[nmet0] - fdx_met[nmet1];
1370  fdy_metdit[nsc] += fdy_met[nmet0] - fdy_met[nmet1];
1371  }
1372  CPLCHECK_MSG ("Fail to compute metrology per base from metrology per tel");
1373 
1374  /* Normalize the means (if nframe == 0, values are zero) */
1375  cpl_size nframe = last_met[nsc] - first_met[nsc];
1376  if (nframe != 0 ){
1377  fdx_metdit[nsc] /= nframe;
1378  fdy_metdit[nsc] /= nframe;
1379  }
1380 
1381  } /* End loop on SC frames */
1382  }/* End loop on bases */
1383  }
1384 
1385 
1386  gravi_msg_function_exit(1);
1387  return CPL_ERROR_NONE;
1388 }
1389 
1390 
1391 /* -------------------------------------------------------------------------- */
1410 /* -------------------------------------------------------------------------- */
1411 
1412 cpl_error_code gravi_vis_create_met_ft (cpl_table * vis_FT, cpl_table * vis_MET)
1413 {
1414  gravi_msg_function_start(1);
1415  cpl_ensure_code (vis_FT, CPL_ERROR_NULL_INPUT);
1416  cpl_ensure_code (vis_MET, CPL_ERROR_NULL_INPUT);
1417 
1418  cpl_size nbase = 6, ntel = 4;
1419  cpl_size nrow_ft = cpl_table_get_nrow (vis_FT) / nbase;
1420  cpl_size nrow_met = cpl_table_get_nrow (vis_MET) / ntel;
1421 
1422  CPLCHECK_MSG("Cannot get data");
1423 
1424  /* Get the FT period in table [us] */
1425  double periode_ft = cpl_table_get (vis_FT, "TIME", nbase, NULL) -
1426  cpl_table_get (vis_FT, "TIME", 0, NULL);
1427  cpl_msg_info (cpl_func, "PERIOD FT = %g [us]", periode_ft);
1428 
1429  /* Get MET data */
1430  double * phase_met_fc = cpl_table_get_data_double (vis_MET, "PHASE_FC");
1431 
1432  CPLCHECK_MSG("Cannot get direct pointer to data");
1433 
1434  /* New columns */
1435  gravi_table_new_column (vis_FT, "PHASE_MET_FC", "rad", CPL_TYPE_DOUBLE);
1436  double * phase_metdit_fc = cpl_table_get_data_double (vis_FT, "PHASE_MET_FC");
1437 
1438  CPLCHECK_MSG("Cannot create columns");
1439 
1440  /* Loop on base and rows */
1441  for (cpl_size base = 0; base < nbase; base++) {
1442  int tel0 = GRAVI_BASE_TEL[base][0];
1443  int tel1 = GRAVI_BASE_TEL[base][1];
1444 
1445  for (cpl_size last_met = 0, first_met = 0, row_ft = 0; row_ft < nrow_ft; row_ft ++) {
1446  cpl_size nft = row_ft * nbase + base;
1447  double time_ft = cpl_table_get (vis_FT, "TIME", row_ft*nbase+base, NULL);
1448 
1449  /*
1450  * FIXME: to respect previous implementation in gravi_wave
1451  * while ((time_met < (time_ft + exptime_ft))){
1452  * we use this shiffted window time_ft -> time_ft + periode_ft
1453  */
1454 
1455  /* First sample of MET (assume same DIT for all beam in vis_MET) */
1456  first_met = CPL_MAX (CPL_MIN (last_met - 5, nrow_met - 1), 0);
1457  while ((cpl_table_get (vis_MET, "TIME", first_met*ntel, NULL) <= (time_ft + 0.0))) {
1458  first_met++;
1459  if (first_met == nrow_met) break;
1460  }
1461  CPLCHECK_MSG ("Cannot get first");
1462 
1463  /* Last sample of MET (assume same DIT for all beam in vis_MET) */
1464  last_met = CPL_MAX (CPL_MIN (first_met - 1, nrow_met - 1), 0);
1465  while ((cpl_table_get (vis_MET, "TIME", last_met*ntel, NULL) < (time_ft + periode_ft))) {
1466  last_met++;
1467  if (last_met == nrow_met) break;
1468  }
1469  CPLCHECK_MSG ("Cannot get last");
1470 
1471  /* For first few FT samples, we use the first MET if none found */
1472  if (row_ft < 5 && last_met == 0) last_met = 1;
1473 
1474  /* For last few FT samples, we use the last MET if none found
1475  * also avoid going outside the table */
1476  if (row_ft > nrow_ft-5 && first_met == nrow_met) first_met = nrow_met - 1;
1477  if (row_ft > nrow_ft-5 && last_met == nrow_met) last_met = nrow_met;
1478 
1479  /* Check if enough data */
1480  if ( last_met == 0 || last_met > nrow_met ) {
1481  return cpl_error_set_message (cpl_func,CPL_ERROR_ILLEGAL_INPUT,
1482  "Not enough MET data to synchronise "
1483  "with FT DIT %lli over %lli", row_ft+1, nrow_ft);
1484  }
1485 
1486  if ( last_met - first_met > 0 ) {
1487  /* If at least one MET samples inside, we average
1488  * FIXME: maybe we better always interpolate ?? */
1489 
1490  for (cpl_size rin_met = first_met; rin_met < last_met; rin_met ++)
1491  phase_metdit_fc[nft] += phase_met_fc[rin_met*ntel+tel0] - phase_met_fc[rin_met*ntel+tel1];
1492 
1493  phase_metdit_fc[nft] /= (last_met - first_met);
1494 
1495  } else {
1496  /* If no MET inside sample, we interpolate linear */
1497  cpl_size rowa_met = first_met-1;
1498  cpl_size rowb_met = last_met;
1499 
1500  double phia_met = phase_met_fc[rowa_met*ntel+tel0] - phase_met_fc[rowa_met*ntel+tel1];
1501  double phib_met = phase_met_fc[rowb_met*ntel+tel0] - phase_met_fc[rowb_met*ntel+tel1];
1502  double timea_met = cpl_table_get (vis_MET, "TIME",rowa_met*ntel, NULL);
1503  double timeb_met = cpl_table_get (vis_MET, "TIME",rowb_met*ntel, NULL);
1504 
1505  phase_metdit_fc[nft] = phia_met +
1506  (phib_met - phia_met) * (time_ft - timea_met) / (timeb_met - timea_met);
1507  CPLCHECK_MSG ("Cannot interpolate");
1508  }
1509 
1510  CPLCHECK_MSG ("Fail to compute metrology per FT base from metrology per tel");
1511  } /* End loop on FT frames */
1512 
1513  }/* End loop on bases */
1514 
1515  gravi_msg_function_exit(1);
1516  return CPL_ERROR_NONE;
1517 }
1518 
1519 
1520 /* -------------------------------------------------------------------------- */
1536 /* -------------------------------------------------------------------------- */
1537 
1538 cpl_error_code gravi_vis_create_opdsc_ft (cpl_table * vis_FT,
1539  cpl_table * vis_SC,
1540  double dit_sc)
1541 {
1542  gravi_msg_function_start(1);
1543  cpl_ensure_code (vis_FT, CPL_ERROR_NULL_INPUT);
1544  cpl_ensure_code (vis_SC, CPL_ERROR_NULL_INPUT);
1545 
1546  cpl_size nbase = 6;
1547  cpl_size nrow_ft = cpl_table_get_nrow (vis_FT) / nbase;
1548  cpl_size nrow_sc = cpl_table_get_nrow (vis_SC) / nbase;
1549 
1550  CPLCHECK_MSG("Cannot get data");
1551 
1552  /* Get OPD data */
1553  double * phase_sc = cpl_table_get_data_double (vis_SC, "OPD");
1554 
1555  CPLCHECK_MSG("Cannot get direct pointer to data");
1556 
1557  /* New columns */
1558  gravi_table_new_column (vis_FT, "OPD_SC", "rad", CPL_TYPE_DOUBLE);
1559  double * phase_scdit = cpl_table_get_data_double (vis_FT, "OPD_SC");
1560 
1561  CPLCHECK_MSG("Cannot create columns");
1562 
1563  /* Loop on base and rows */
1564  for (cpl_size base = 0; base < nbase; base++) {
1565  cpl_size row_ft = 0;
1566 
1567  for (cpl_size row_sc = 0; row_sc < nrow_sc; row_sc ++) {
1568  cpl_size nsc = row_sc * nbase + base;
1569  double time_sc = cpl_table_get (vis_SC, "TIME", nsc, NULL);
1570 
1571  /* First sample of FT in the SC DIT */
1572  while ((cpl_table_get (vis_FT, "TIME", row_ft*nbase+base, NULL) < (time_sc - dit_sc/2))) {
1573  row_ft++;
1574  if (row_ft >= nrow_ft) break;
1575  }
1576 
1577  /* While inside the SC DIT -- we fill the OPD_FT column */
1578  while ((cpl_table_get (vis_FT, "TIME", row_ft*nbase+base, NULL) < (time_sc + dit_sc/2))) {
1579 
1580  phase_scdit[row_ft*nbase+base] = phase_sc[nsc];
1581 
1582  row_ft++;
1583  if (row_ft >= nrow_ft) break;
1584  }
1585 
1586  if (row_ft >= nrow_ft) {
1587  return cpl_error_set_message (cpl_func,CPL_ERROR_ILLEGAL_INPUT,
1588  "Not enough FT data to synchronise "
1589  "with SC DIT %lli over %lli", row_sc+1, nrow_sc);
1590  }
1591 
1592  } /* End loop on SC frames */
1593 
1594  }/* End loop on bases */
1595 
1596  gravi_msg_function_exit(1);
1597  return CPL_ERROR_NONE;
1598 }
1599 
1600 
1601 /* -------------------------------------------------------------------------- */
1612 /* -------------------------------------------------------------------------- */
1613 
1614 cpl_error_code gravi_flux_create_met_sc (cpl_table * flux_SC, cpl_table * vis_MET)
1615 {
1616  gravi_msg_function_start(1);
1617  cpl_ensure_code (flux_SC, CPL_ERROR_NULL_INPUT);
1618  cpl_ensure_code (vis_MET, CPL_ERROR_NULL_INPUT);
1619 
1620  cpl_size ntel = 4, ndiode = 4;
1621  cpl_size nrow_sc = cpl_table_get_nrow (flux_SC) / ntel;
1622 
1623  /* Get SC data */
1624  int * first_met = cpl_table_get_data_int (flux_SC, "FIRST_MET");
1625  int * last_met = cpl_table_get_data_int (flux_SC, "LAST_MET");
1626 
1627  CPLCHECK_MSG("Cannot get data");
1628 
1629  /* Get MET data */
1630  double * opd_met_fc = cpl_table_get_data_double (vis_MET, "OPD_FC");
1631  cpl_array ** opd_met_tel = cpl_table_get_data_array (vis_MET, "OPD_TEL");
1632  cpl_array ** phasor_met_telfc = cpl_table_get_data_array (vis_MET, "PHASOR_TELFC");
1633 
1634  double * opd_met_fc_corr = cpl_table_get_data_double (vis_MET, "OPD_FC_CORR");
1635  double * opd_met_telfc_mcorr = cpl_table_get_data_double (vis_MET, "OPD_TELFC_MCORR");
1636  cpl_array ** opd_met_telfc_corr = cpl_table_get_data_array (vis_MET, "OPD_TELFC_CORR");
1637 
1638  CPLCHECK_MSG("Cannot get direct pointer to data");
1639 
1640  /* New columns */
1641  gravi_table_new_column (flux_SC, "OPD_MET_FC", "m", CPL_TYPE_DOUBLE);
1642  double * opd_metdit_fc = cpl_table_get_data_double (flux_SC, "OPD_MET_FC");
1643 
1644  gravi_table_new_column_array (flux_SC, "OPD_MET_TEL", "m", CPL_TYPE_DOUBLE, ndiode);
1645  cpl_array ** opd_metdit_tel = cpl_table_get_data_array (flux_SC, "OPD_MET_TEL");
1646 
1647  gravi_table_new_column_array (flux_SC, "PHASOR_MET_TELFC", "V^4", CPL_TYPE_DOUBLE_COMPLEX, ndiode);
1648  cpl_array ** phasor_metdit_telfc = cpl_table_get_data_array (flux_SC, "PHASOR_MET_TELFC");
1649 
1650  gravi_table_new_column (flux_SC, "OPD_MET_FC_CORR", "m", CPL_TYPE_DOUBLE);
1651  double * opd_metdit_fc_corr = cpl_table_get_data_double (flux_SC, "OPD_MET_FC_CORR");
1652 
1653  gravi_table_new_column (flux_SC, "OPD_MET_TELFC_MCORR", "m", CPL_TYPE_DOUBLE);
1654  double * opd_metdit_telfc_mcorr = cpl_table_get_data_double (flux_SC, "OPD_MET_TELFC_MCORR");
1655 
1656  gravi_table_new_column_array (flux_SC, "OPD_MET_TELFC_CORR", "m", CPL_TYPE_DOUBLE, ndiode);
1657  cpl_array ** opd_metdit_telfc_corr = cpl_table_get_data_array (flux_SC, "OPD_MET_TELFC_CORR");
1658 
1659  CPLCHECK_MSG("Cannot create columns");
1660 
1661  /* Loop on base and rows */
1662  for (cpl_size tel = 0; tel < ntel; tel++) {
1663  for (cpl_size row_sc = 0; row_sc < nrow_sc; row_sc ++) {
1664  cpl_size nsc = row_sc * ntel + tel;
1665 
1666  opd_metdit_tel[nsc] = gravi_array_init_double (ndiode, 0.0);
1667  phasor_metdit_telfc[nsc] = gravi_array_init_double_complex (ndiode, 0.0+I*0.0);
1668  opd_metdit_telfc_corr[nsc] = gravi_array_init_double (ndiode, 0.0);
1669 
1670  /* Sum over synch MET frames */
1671  for (cpl_size row_met = first_met[nsc] ; row_met < last_met[nsc]; row_met++) {
1672  cpl_size nmet = row_met * ntel + tel;
1673 
1674  /* Mean OPD_MET_TEL at Telescope (each diode) */
1675  cpl_array_add (opd_metdit_tel[nsc], opd_met_tel[nmet]);
1676 
1677  /* Mean OPD_MET_FC at Beam Combiner */
1678  opd_metdit_fc[nsc] += opd_met_fc[nmet];
1679 
1680  /* Mean PHASOR_MET_TELFC */
1681  cpl_array_add (phasor_metdit_telfc[nsc], phasor_met_telfc[nmet]);
1682 
1683  /* Mean OPD_FC_CORR and OPD_TELFC_MCORR for each BASELINE */
1684  opd_metdit_fc_corr[nsc] += opd_met_fc_corr[nmet];
1685  opd_metdit_telfc_mcorr[nsc] += opd_met_telfc_mcorr[nmet];
1686 
1687  /* Mean OPD_TELFC_CORR for each BASELINE and diode */
1688  cpl_array_add (opd_metdit_telfc_corr[nsc], opd_met_telfc_corr[nmet]);
1689 
1690  CPLCHECK_MSG ("Fail to integrate the metrology");
1691  }
1692 
1693  /* Normalize the means (if nframe == 0, values are zero) */
1694  cpl_size nframe = last_met[nsc] - first_met[nsc];
1695  if (nframe != 0 ){
1696  opd_metdit_fc_corr[nsc] /= nframe;
1697  opd_metdit_telfc_mcorr[nsc] /= nframe;
1698  cpl_array_divide_scalar (opd_metdit_telfc_corr[nsc], (double)nframe);
1699 
1700  cpl_array_divide_scalar (opd_metdit_tel[nsc], (double)nframe);
1701  opd_metdit_fc[nsc] /= nframe;
1702  cpl_array_divide_scalar (phasor_metdit_telfc[nsc], (double)nframe);
1703  }
1704  CPLCHECK_MSG ("Fail to integrate the metrology");
1705 
1706  } /* End loop on SC frames */
1707  }/* End loop on bases */
1708 
1709 
1710  /* Compute the information comming from VIS_ACQ
1711  * camera... through the VIS_MET */
1712  if (cpl_table_has_column (vis_MET,"FIELD_FIBER_DX")) {
1713 
1714  double * fdx_met = cpl_table_get_data_double (vis_MET, "FIELD_FIBER_DX");
1715  double * fdy_met = cpl_table_get_data_double (vis_MET, "FIELD_FIBER_DY");
1716 
1717  gravi_table_new_column (flux_SC, "FIELD_FIBER_DX", "pix", CPL_TYPE_DOUBLE);
1718  double * fdx_metdit = cpl_table_get_data_double (flux_SC, "FIELD_FIBER_DX");
1719 
1720  gravi_table_new_column (flux_SC, "FIELD_FIBER_DY", "pix", CPL_TYPE_DOUBLE);
1721  double * fdy_metdit = cpl_table_get_data_double (flux_SC, "FIELD_FIBER_DY");
1722 
1723  /* Loop on tel and rows */
1724  for (cpl_size tel = 0; tel < ntel; tel++) {
1725  for (cpl_size row_sc = 0; row_sc < nrow_sc; row_sc ++) {
1726  cpl_size nsc = row_sc * ntel + tel;
1727 
1728  /* Sum over synch MET frames */
1729  for (cpl_size row_met = first_met[nsc] ; row_met < last_met[nsc]; row_met++) {
1730  cpl_size nmet0 = row_met * ntel + tel;
1731 
1732  /* Mean FIELD_FIBER */
1733  fdx_metdit[nsc] += fdx_met[nmet0];
1734  fdy_metdit[nsc] += fdy_met[nmet0];
1735  }
1736  CPLCHECK_MSG ("Fail to compute metrology per base from metrology per tel");
1737 
1738  /* Normalize the means (if nframe == 0, values are zero) */
1739  cpl_size nframe = last_met[nsc] - first_met[nsc];
1740  if (nframe != 0 ){
1741  fdx_metdit[nsc] /= nframe;
1742  fdy_metdit[nsc] /= nframe;
1743  }
1744 
1745  } /* End loop on SC frames */
1746  }/* End loop on tels */
1747  }
1748 
1749  gravi_msg_function_exit(1);
1750  return CPL_ERROR_NONE;
1751 }
1752 
1753 /* -------------------------------------------------------------------------- */
1765 /* -------------------------------------------------------------------------- */
1766 
1767 cpl_error_code gravi_flux_create_fddlpos_sc (cpl_table * flux_SC, cpl_table * fddl_table)
1768 {
1769  gravi_msg_function_start(1);
1770  cpl_ensure_code (flux_SC, CPL_ERROR_NULL_INPUT);
1771  cpl_ensure_code (fddl_table, CPL_ERROR_NULL_INPUT);
1772 
1773  cpl_size ntel = 4;
1774  cpl_size nrow_sc = cpl_table_get_nrow (flux_SC) / ntel;
1775 
1776  /* Get SC data */
1777  int * first_fddl = cpl_table_get_data_int (flux_SC, "FIRST_FDDL");
1778  int * last_fddl = cpl_table_get_data_int (flux_SC, "LAST_FDDL");
1779 
1780  cpl_array ** ftpos = cpl_table_get_data_array (fddl_table, "FT_POS");
1781  cpl_array ** scpos = cpl_table_get_data_array (fddl_table, "SC_POS");
1782  cpl_array ** oplair = cpl_table_get_data_array (fddl_table, "OPL_AIR");
1783 
1784  CPLCHECK_MSG("Cannot get data");
1785 
1786  /* New columns */
1787  gravi_table_new_column (flux_SC, "FT_POS", "V", CPL_TYPE_DOUBLE);
1788  double * ftpos_flux = cpl_table_get_data_double (flux_SC, "FT_POS");
1789 
1790  gravi_table_new_column (flux_SC, "SC_POS", "V", CPL_TYPE_DOUBLE);
1791  double * scpos_flux = cpl_table_get_data_double (flux_SC, "SC_POS");
1792 
1793  gravi_table_new_column (flux_SC, "OPL_AIR", "m", CPL_TYPE_DOUBLE);
1794  double * oplair_flux = cpl_table_get_data_double (flux_SC, "OPL_AIR");
1795 
1796  CPLCHECK_MSG("Cannot create columns");
1797 
1798  /* Loop on tel and frames */
1799  for (cpl_size tel = 0; tel < ntel; tel++) {
1800  for (cpl_size row_sc = 0; row_sc < nrow_sc; row_sc ++) {
1801  cpl_size nsc = row_sc * ntel + tel;
1802 
1803  /* Mean FDDL and OPL_AIR during this frame for this tel */
1804  for (cpl_size row_fddl = first_fddl[nsc] ; row_fddl < last_fddl[nsc]; row_fddl++) {
1805  ftpos_flux[nsc] += cpl_array_get (ftpos[row_fddl], tel, NULL);
1806  scpos_flux[nsc] += cpl_array_get (scpos[row_fddl], tel, NULL);
1807  oplair_flux[nsc] += cpl_array_get (oplair[row_fddl], tel, NULL);
1808  }
1809 
1810  /* Normalise the means (if nframe == 0, values are zero) */
1811  cpl_size nframe = last_fddl[nsc] - first_fddl[nsc];
1812  if (nframe != 0 ) {
1813  ftpos_flux[nsc] /= nframe;
1814  scpos_flux[nsc] /= nframe;
1815  oplair_flux[nsc] /= nframe;
1816  }
1817 
1818  } /* End loop on SC frames */
1819  }/* End loop on tels */
1820 
1821  gravi_msg_function_exit(1);
1822  return CPL_ERROR_NONE;
1823 }
1824 
1825 /* -------------------------------------------------------------------------- */
1836 /* -------------------------------------------------------------------------- */
1837 
1838 cpl_error_code gravi_flux_create_totalflux_sc (cpl_table * flux_SC, cpl_table * flux_FT)
1839 {
1840  gravi_msg_function_start(1);
1841  cpl_ensure_code (flux_SC, CPL_ERROR_NULL_INPUT);
1842  cpl_ensure_code (flux_FT, CPL_ERROR_NULL_INPUT);
1843 
1844  cpl_size ntel = 4;
1845  cpl_size nrow_sc = cpl_table_get_nrow (flux_SC) / ntel;
1846  cpl_size nwave_sc = cpl_table_get_column_depth (flux_SC, "FLUX");
1847  cpl_size nwave_ft = cpl_table_get_column_depth (flux_FT, "FLUX");
1848 
1849  /* Get SC and FT data */
1850  int * first_ft = cpl_table_get_data_int (flux_SC, "FIRST_FT");
1851  int * last_ft = cpl_table_get_data_int (flux_SC, "LAST_FT");
1852 
1853  cpl_array ** flux_sc = cpl_table_get_data_array (flux_SC, "FLUX");
1854  cpl_array ** flux_ft = cpl_table_get_data_array (flux_FT, "FLUX");
1855 
1856  CPLCHECK_MSG("Cannot get data");
1857 
1858  /* New columns */
1859  gravi_table_new_column (flux_SC, "TOTALFLUX_SC", "e", CPL_TYPE_DOUBLE);
1860  double * total_flux_scdit = cpl_table_get_data_double (flux_SC, "TOTALFLUX_SC");
1861 
1862  gravi_table_new_column (flux_SC, "TOTALFLUX_FT", "e", CPL_TYPE_DOUBLE);
1863  double * total_flux_ftdit = cpl_table_get_data_double (flux_SC, "TOTALFLUX_FT");
1864 
1865  CPLCHECK_MSG("Cannot create columns");
1866 
1867  for (cpl_size tel = 0; tel < ntel; tel++) {
1868  for (cpl_size row_sc = 0; row_sc < nrow_sc; row_sc ++) {
1869  cpl_size nsc = row_sc * ntel + tel;
1870 
1871  /* Store the total flux of SC over the SC frame [e] */
1872  total_flux_scdit[nsc] = cpl_array_get_mean (flux_sc[nsc]) * nwave_sc;
1873 
1874  /* Store the total flux of FT over the SC frame [e] */
1875  for (cpl_size row_ft = first_ft[nsc] ; row_ft < last_ft[nsc]; row_ft++) {
1876  total_flux_ftdit[nsc] += cpl_array_get_mean (flux_ft[row_ft * ntel + tel]) * nwave_ft;
1877  }
1878 
1879  CPLCHECK_MSG("Issue in the loop to average FT and SC flux per frame");
1880 
1881  } /* End loop on SC frames */
1882  }/* End loop on tels */
1883 
1884  gravi_msg_function_exit(1);
1885  return CPL_ERROR_NONE;
1886 }
1887 
1888 /* -------------------------------------------------------------------------- */
1904 /* -------------------------------------------------------------------------- */
1905 
1906 cpl_error_code gravi_vis_create_vfactor_sc (cpl_table * vis_SC,
1907  cpl_table * wave_table_sc,
1908  cpl_table * vis_FT,
1909  cpl_table * wave_table_ft)
1910 {
1911  gravi_msg_function_start(1);
1912  cpl_ensure_code (vis_SC, CPL_ERROR_NULL_INPUT);
1913  cpl_ensure_code (vis_FT, CPL_ERROR_NULL_INPUT);
1914  cpl_ensure_code (wave_table_sc, CPL_ERROR_NULL_INPUT);
1915  cpl_ensure_code (wave_table_ft, CPL_ERROR_NULL_INPUT);
1916 
1917  /* Get variables */
1918  cpl_size nbase = 6;
1919  cpl_size nrow_sc = cpl_table_get_nrow (vis_SC) / nbase;
1920  cpl_size nwave_sc = cpl_table_get_column_depth (vis_SC, "VISDATA");
1921  cpl_size nwave_ft = cpl_table_get_column_depth (vis_FT, "VISDATA");
1922 
1923  /* Get SC and FT data */
1924  int * first_ft = cpl_table_get_data_int (vis_SC, "FIRST_FT");
1925  int * last_ft = cpl_table_get_data_int (vis_SC, "LAST_FT");
1926 
1927  cpl_array ** visErr_ft = cpl_table_get_data_array (vis_FT, "VISERR");
1928  cpl_array ** visData_ft = cpl_table_get_data_array (vis_FT, "VISDATA");
1929 
1930  CPLCHECK_MSG ("Cannot get data");
1931 
1932  /* Create wavenumber to be faster */
1933  double meanwave_ft = cpl_table_get_column_mean (wave_table_ft, "EFF_WAVE");
1934  double * wavenumber_sc = cpl_malloc (nwave_sc * sizeof(double));
1935  for (cpl_size wave = 0; wave < nwave_sc ; wave ++) {
1936  wavenumber_sc[wave] = 1. / cpl_table_get (wave_table_sc, "EFF_WAVE", wave, NULL);
1937  }
1938 
1939  CPLCHECK_MSG ("Cannot get data");
1940 
1941  /* New columns */
1942  gravi_table_new_column_array (vis_SC, "VISDATA_FT", "e", CPL_TYPE_DOUBLE_COMPLEX, nwave_ft);
1943  cpl_array ** visData_ftdit = cpl_table_get_data_array (vis_SC, "VISDATA_FT");
1944 
1945  gravi_table_new_column_array (vis_SC, "VISVAR_FT", "e^2", CPL_TYPE_DOUBLE, nwave_ft);
1946  cpl_array ** visVar_ftdit = cpl_table_get_data_array (vis_SC, "VISVAR_FT");
1947 
1948  gravi_table_new_column_array (vis_SC, "VISPOWER_FT", "e^2", CPL_TYPE_DOUBLE, nwave_ft);
1949  cpl_array ** visPower_ftdit = cpl_table_get_data_array (vis_SC, "VISPOWER_FT");
1950 
1951  gravi_table_new_column_array (vis_SC, "V_FACTOR", NULL, CPL_TYPE_DOUBLE, nwave_sc);
1952  cpl_array ** vFactor = cpl_table_get_data_array (vis_SC, "V_FACTOR");
1953 
1954  gravi_table_new_column_array (vis_SC, "V_FACTOR_FT", NULL, CPL_TYPE_DOUBLE, nwave_ft);
1955  cpl_array ** vFactor_ftdit = cpl_table_get_data_array (vis_SC, "V_FACTOR_FT");
1956 
1957  gravi_table_new_column (vis_SC, "V_FACTOR_WL", NULL, CPL_TYPE_DOUBLE);
1958  double * vFactor_wl = cpl_table_get_data_double (vis_SC, "V_FACTOR_WL");
1959 
1960  CPLCHECK_MSG ("Cannot create columns");
1961 
1962  /* Loop on base and row SC */
1963  for (cpl_size base = 0; base < nbase; base++) {
1964  for (cpl_size row_sc = 0; row_sc < nrow_sc; row_sc++) {
1965  int nsc = row_sc * nbase + base;
1966 
1967  /* Init integration of FT quantities during the SC frame */
1968  visData_ftdit[nsc] = gravi_array_init_double_complex (nwave_ft, 0.0 + I*0.0);
1969  visVar_ftdit[nsc] = gravi_array_init_double (nwave_ft, 0.0);
1970  visPower_ftdit[nsc] = gravi_array_init_double (nwave_ft, 0.0);
1971 
1972  double vFactor_incoh = 0.0;
1973  double complex vFactor_coh = 0.0 + I * 0.0;
1974  double vFactor_var = 0.0;
1975 
1976  /* Integrate quantities during the SC frame */
1977  cpl_size nframe = last_ft[nsc] - first_ft[nsc];
1978  for (cpl_size row_ft = first_ft[nsc] ; row_ft < last_ft[nsc]; row_ft++) {
1979  cpl_array * tmp_data;
1980 
1981  /* Integrate visVar_ftdit = < |visDataErr|^2 > over the current SC frame [e^2] */
1982  tmp_data = visErr_ft[row_ft * nbase + base];
1983  for (cpl_size wave = 0; wave < nwave_ft; wave ++){
1984  cpl_array_set (visVar_ftdit[nsc], wave,
1985  cpl_array_get (visVar_ftdit[nsc], wave, NULL) +
1986  pow (cabs( cpl_array_get_complex (tmp_data, wave, NULL) ), 2));
1987  }
1988 
1989  /* Integrate visData_ftdit[nsc] = < visData > over the current SC frame [e] */
1990  tmp_data = visData_ft[row_ft * nbase + base];
1991  for (cpl_size wave = 0; wave < nwave_ft; wave ++){
1992  cpl_array_set_complex (visData_ftdit[nsc], wave,
1993  cpl_array_get_complex (visData_ftdit[nsc], wave, NULL) +
1994  cpl_array_get_complex (tmp_data, wave, NULL));
1995  }
1996 
1997  /* Integrate visPower_ftdit = < |visData|^2 > over the current SC frame [e^2] */
1998  for (cpl_size wave = 0; wave < nwave_ft; wave ++){
1999  cpl_array_set (visPower_ftdit[nsc], wave,
2000  cpl_array_get (visPower_ftdit[nsc], wave, NULL) +
2001  pow (cabs( cpl_array_get_complex (tmp_data, wave, NULL)), 2));
2002  }
2003 
2004  /* Integrate the same quantities for the white light vFactor
2005  * This is first doing a coherent integration over the wavelengths */
2006  vFactor_incoh += pow (cabs (cpl_array_get_mean_complex (visData_ft[row_ft * nbase + base])) * nwave_ft, 2);
2007  vFactor_coh += cpl_array_get_mean_complex (visData_ft[row_ft * 6 + base]) * nwave_ft;
2008  for (cpl_size wave = 0; wave < nwave_ft; wave ++) {
2009  vFactor_var += pow (cabs (cpl_array_get_complex (visErr_ft[row_ft * nbase + base], wave, NULL)), 2);
2010  }
2011 
2012  CPLCHECK_MSG("Issue in the loop to build average FT quantities");
2013  } /* End loop on FT frame within this SC frame */
2014 
2015  /* Compute the vFactor as the contrast attenuation within the SC DIT
2016  * (|<visData>|^2 - <|visErr|^2>) / (<|visData|^2> - <|visErr|^2>) / nframe */
2017  vFactor_ftdit[nsc] = cpl_array_new (nwave_ft, CPL_TYPE_DOUBLE);
2018  if (nframe != 0) {
2019  for (cpl_size wave = 0; wave < nwave_ft; wave ++) {
2020  cpl_array_set (vFactor_ftdit[nsc], wave,
2021  (pow (cabs (cpl_array_get_complex (visData_ftdit[nsc], wave, NULL)),2) -
2022  cpl_array_get (visVar_ftdit[nsc], wave, NULL)) /
2023  (cpl_array_get (visPower_ftdit[nsc], wave, NULL) -
2024  cpl_array_get (visVar_ftdit[nsc], wave, NULL)) / (double)nframe);
2025  }
2026 
2027  /* Compute the white light vFactor, that is fist performing a coherent
2028  * integration of the spectral channels. To lower the bias */
2029  vFactor_wl[nsc] = (cabs(vFactor_coh)*cabs(vFactor_coh) - vFactor_var) /
2030  (vFactor_incoh - vFactor_var) / (double)nframe;
2031  }
2032  /* if nframe == 0 set the vFactor to 0 */
2033  else {
2034  for (cpl_size wave = 0; wave < nwave_ft; wave ++) {
2035  cpl_array_set (vFactor_ftdit[nsc], wave,0);
2036  }
2037  vFactor_wl[nsc] = 0;
2038  }
2039 
2040  /* Compute the mean vFactor of the FT, and fit with a function exp(-a2/lbd2) to
2041  * project on the SC wavelength. This has only one free parameter */
2042  vFactor[nsc] = cpl_array_new (nwave_sc, CPL_TYPE_DOUBLE);
2043  double a2 = log (CPL_MAX(CPL_MIN (vFactor_wl[nsc], 1.0),1e-10)) * meanwave_ft*meanwave_ft;
2044  for (cpl_size wave = 0; wave < nwave_sc; wave ++) {
2045  cpl_array_set (vFactor[nsc], wave, exp ( a2 * pow (wavenumber_sc[wave], 2)));
2046  }
2047 
2048  }
2049  }
2050  /* End loop on SC frames and base */
2051 
2052  FREE (cpl_free, wavenumber_sc);
2053 
2054  gravi_msg_function_exit(1);
2055  return CPL_ERROR_NONE;
2056 }
2057 
2058 /* -------------------------------------------------------------------------- */
2072 /* -------------------------------------------------------------------------- */
2073 
2074 cpl_error_code gravi_vis_create_lockratio_sc (cpl_table * vis_SC,
2075  cpl_table * vis_FT)
2076 {
2077  gravi_msg_function_start(1);
2078  cpl_ensure_code (vis_SC, CPL_ERROR_NULL_INPUT);
2079  cpl_ensure_code (vis_FT, CPL_ERROR_NULL_INPUT);
2080 
2081  /* Get variables */
2082  cpl_size nbase = 6;
2083  cpl_size nrow_sc = cpl_table_get_nrow (vis_SC) / nbase;
2084 
2085  /* Get SC and FT data */
2086  int * reject_flag_ft = cpl_table_get_data_int (vis_FT, "REJECTION_FLAG");
2087  int * first_ft = cpl_table_get_data_int (vis_SC, "FIRST_FT");
2088  int * last_ft = cpl_table_get_data_int (vis_SC, "LAST_FT");
2089 
2090  CPLCHECK_MSG ("Cannot get data");
2091 
2092  /* Create columns */
2093  gravi_table_new_column (vis_SC, "FRINGEDET_RATIO", NULL, CPL_TYPE_DOUBLE);
2094  double * fringedet_ftdit = cpl_table_get_data_double (vis_SC, "FRINGEDET_RATIO");
2095 
2096  CPLCHECK_MSG ("Cannot create columns");
2097 
2098  /* Loop on base and row SC */
2099  for (cpl_size base = 0; base < nbase; base++) {
2100  for (cpl_size row_sc = 0; row_sc < nrow_sc; row_sc++) {
2101  int nsc = row_sc * nbase + base;
2102 
2103  /* Integrate fraction of the SC frame with detected FT fringes */
2104  for (cpl_size row_ft = first_ft[nsc] ; row_ft < last_ft[nsc]; row_ft++) {
2105  fringedet_ftdit[nsc] += (reject_flag_ft[row_ft * nbase + base] == 0 ? 1 : 0);
2106  }
2107 
2108  /* Normalize the mean (if nframe == 0, value is zero) */
2109  cpl_size nframe = last_ft[nsc] - first_ft[nsc];
2110  if (nframe != 0) fringedet_ftdit[nsc] /= (double)nframe;
2111  }
2112  } /* End loop on base and SC frames */
2113 
2114  gravi_msg_function_exit(1);
2115  return CPL_ERROR_NONE;
2116 }
2117 
2118 /* -------------------------------------------------------------------------- */
2135 /* -------------------------------------------------------------------------- */
2136 
2137 cpl_error_code gravi_vis_create_phaseref_sc (cpl_table * vis_SC,
2138  cpl_table * wavesc_table,
2139  cpl_table * waveft_table)
2140 {
2141  gravi_msg_function_start(1);
2142  cpl_ensure_code (vis_SC, CPL_ERROR_NULL_INPUT);
2143  cpl_ensure_code (wavesc_table, CPL_ERROR_NULL_INPUT);
2144 
2145  cpl_array ** visData_ftdit;
2146  double * gdelay_ftdit;
2147  const char * output_name = NULL, * coeff_name = NULL;
2148  if (waveft_table != NULL) {
2149  cpl_msg_info (cpl_func, "Compute reference phase of SC from the FT data");
2150  visData_ftdit = cpl_table_get_data_array (vis_SC, "VISDATA_FT");
2151  gdelay_ftdit = cpl_table_get_data_double (vis_SC, "GDELAY_FT");
2152  output_name = "PHASE_REF";
2153  coeff_name = "PHASE_REF_COEFF";
2154  } else {
2155  cpl_msg_info (cpl_func, "Compute reference phase of SC from the SC");
2156  visData_ftdit = cpl_table_get_data_array (vis_SC, "VISDATA");
2157  gdelay_ftdit = cpl_table_get_data_double (vis_SC, "GDELAY");
2158  waveft_table = wavesc_table;
2159  output_name = "SELF_REF";
2160  coeff_name = "SELF_REF_COEFF";
2161  }
2162 
2163  /* Get general data */
2164  cpl_size nbase = 6;
2165  cpl_size nrow_sc = cpl_table_get_nrow (vis_SC) / nbase;
2166  cpl_size nwave_sc = cpl_table_get_nrow (wavesc_table);
2167  cpl_size nwave_ft = cpl_table_get_nrow (waveft_table);
2168 
2169  CPLCHECK_MSG ("Cannot get data");
2170 
2171  /* Variable for fit */
2172  cpl_size mindeg = 0, maxdeg = 2;
2173  cpl_polynomial * fit = cpl_polynomial_new (1);
2174 
2175  /* Create the vectors and matrix only once to be faster */
2176  cpl_matrix * wave_ft = cpl_matrix_new (1,nwave_ft);
2177  cpl_vector * wave_sc = cpl_vector_new (nwave_sc);
2178  cpl_array * wavenumber_ft = cpl_array_new (nwave_ft, CPL_TYPE_DOUBLE);
2179 
2180  double lbd0 = cpl_table_get_column_mean (waveft_table, "EFF_WAVE");
2181  double delta0 = cpl_table_get_column_max (waveft_table, "EFF_WAVE") -
2182  cpl_table_get_column_min (waveft_table, "EFF_WAVE");
2183  for (cpl_size wave = 0; wave < nwave_ft; wave ++) {
2184  double lbd = cpl_table_get (waveft_table, "EFF_WAVE", wave, NULL);
2185  cpl_matrix_set (wave_ft, 0, wave, (lbd - lbd0) / delta0);
2186  cpl_array_set (wavenumber_ft, wave, 1./lbd);
2187  }
2188  for (cpl_size wave = 0; wave < nwave_sc; wave ++) {
2189  cpl_vector_set (wave_sc, wave, cpl_table_get (wavesc_table, "EFF_WAVE", wave, NULL));
2190  }
2191 
2192  CPLCHECK_MSG ("Cannot create wave arrays");
2193 
2194  /* Create columns */
2195  gravi_table_new_column_array (vis_SC, output_name, "rad", CPL_TYPE_DOUBLE, nwave_sc);
2196  cpl_array ** phaseref = cpl_table_get_data_array (vis_SC, output_name);
2197 
2198  /* Create columns */
2199  gravi_table_new_column_array (vis_SC, coeff_name, NULL, CPL_TYPE_DOUBLE, maxdeg+1);
2200  cpl_array ** phase_coeff = cpl_table_get_data_array (vis_SC, coeff_name);
2201 
2202  CPLCHECK_MSG ("Cannot create column");
2203 
2204  /* Loop on base and SC frames */
2205  for (cpl_size base = 0; base < nbase; base++) {
2206  for (cpl_size row_sc = 0; row_sc < nrow_sc; row_sc ++) {
2207  int nsc = row_sc * nbase + base;
2208 
2209  /* phaseref_ftdit is the FT phase arg{visData_ftdit}
2210  * Need to be unwrapped before interpolation. */
2211  cpl_array * phaseref_ftdit = cpl_array_cast (visData_ftdit[nsc], CPL_TYPE_DOUBLE_COMPLEX);
2212 
2213  /* Remove mean group-delay and phase-delay to unwrap */
2214  gravi_array_multiply_phasor (phaseref_ftdit, - 2*I*CPL_MATH_PI * gdelay_ftdit[nsc], wavenumber_ft);
2215  double mean_phase = carg (cpl_array_get_mean_complex (phaseref_ftdit));
2216  cpl_array_multiply_scalar_complex (phaseref_ftdit, cexp(- I * mean_phase));
2217 
2218  /* Compute argument and add back the delay and the phase [rad] */
2219  cpl_array_arg (phaseref_ftdit);
2220  gravi_array_add_phase (phaseref_ftdit, 2.*CPL_MATH_PI*gdelay_ftdit[nsc], wavenumber_ft);
2221  cpl_array_add_scalar (phaseref_ftdit, mean_phase);
2222 
2223  /* Interpolate the FT phase at the SC wavelengths with a polynomial of order 2
2224  * rewrap the phase, and make it phase_ref = - phase_ft */
2225 
2226  /* Polynomial fit */
2227  cpl_vector * input = cpl_vector_wrap (nwave_ft, cpl_array_get_data_double (phaseref_ftdit));
2228  cpl_polynomial_fit (fit, wave_ft, NULL, input, NULL, CPL_FALSE, &mindeg, &maxdeg);
2229  cpl_vector_unwrap (input);
2230  cpl_array_delete (phaseref_ftdit);
2231 
2232  /* Save fit coefficients */
2233  phase_coeff[nsc] = cpl_array_new (maxdeg+1, CPL_TYPE_DOUBLE);
2234  for (cpl_size d = 0; d < maxdeg+1; d++)
2235  cpl_array_set (phase_coeff[nsc], d, cpl_polynomial_get_coeff (fit, &d));
2236 
2237  /* Evaluate polynomial at the output sampling */
2238  phaseref[nsc] = cpl_array_new (nwave_sc, CPL_TYPE_DOUBLE);
2239  for (cpl_size w = 0; w < nwave_sc; w++) {
2240  double delta = (cpl_vector_get(wave_sc, w) - lbd0) / delta0;
2241  cpl_array_set (phaseref[nsc], w, cpl_polynomial_eval_1d (fit, delta, NULL));
2242  }
2243 
2244  gravi_array_phase_wrap (phaseref[nsc]);
2245  cpl_array_multiply_scalar (phaseref[nsc], -1.0);
2246 
2247  CPLCHECK_MSG ("Cannot compute the PHASE_REF for SC");
2248  } /* End loop on SC frames */
2249  } /* End loop on base */
2250 
2251  FREE (cpl_vector_delete, wave_sc);
2252  FREE (cpl_matrix_delete, wave_ft);
2253  FREE (cpl_array_delete, wavenumber_ft);
2254  FREE (cpl_polynomial_delete, fit);
2255 
2256  gravi_msg_function_exit(1);
2257  return CPL_ERROR_NONE;
2258 }
2259 
2260 /* -------------------------------------------------------------------------- */
2269 /* -------------------------------------------------------------------------- */
2270 
2271 cpl_error_code gravi_flux_create_fddllin_sc (cpl_table * flux_SC,
2272  cpl_table * disp_table)
2273 {
2274  gravi_msg_function_start(1);
2275  cpl_ensure_code (flux_SC, CPL_ERROR_NULL_INPUT);
2276 
2277  cpl_size ntel = 4;
2278  cpl_size nrow = cpl_table_get_nrow (flux_SC) / ntel;
2279 
2280  /* Create the column */
2281  gravi_table_new_column (flux_SC, "FDDL", "m", CPL_TYPE_DOUBLE);
2282  CPLCHECK_MSG ("Cannot create columns");
2283 
2284  /* If not DISP_DATA, we just create the columns */
2285  if (disp_table == NULL) {
2286  gravi_msg_function_exit(1);
2287  return CPL_ERROR_NONE;
2288  }
2289 
2290  /* Get the list of coeficients for FDDL linearity */
2291  cpl_msg_info (cpl_func, "Load the linearity model coeficients");
2292 
2293  double ** lin_fddl_sc = gravi_table_get_data_array_double (disp_table, "LIN_FDDL_SC");
2294  double ** lin_fddl_ft = gravi_table_get_data_array_double (disp_table, "LIN_FDDL_FT");
2295  cpl_size disp_order = cpl_table_get_column_depth (disp_table, "LIN_FDDL_SC");
2296  CPLCHECK_MSG ("Cannot get linearity model data");
2297 
2298  /* Get data */
2299  double * ftpos = cpl_table_get_data_double (flux_SC, "FT_POS");
2300  double * scpos = cpl_table_get_data_double (flux_SC, "SC_POS");
2301  double * fddl = cpl_table_get_data_double (flux_SC, "FDDL");
2302  CPLCHECK_MSG ("Cannot get POS data");
2303 
2304  /* Loop on tel and frames */
2305  for (cpl_size tel = 0; tel < ntel; tel++) {
2306  for (cpl_size row = 0; row < nrow; row ++) {
2307  cpl_size nsc = row * ntel + tel;
2308 
2309  /* Apply the non-linearity to the FDDL while
2310  * computing the mean of SC and FT: [V] -> [m] */
2311  fddl[nsc] = 0;
2312  for (int o = 0; o < disp_order; o++) {
2313  fddl[nsc] += lin_fddl_sc[tel][o] * pow (scpos[nsc], (double)o) * 0.5e-6;
2314  fddl[nsc] += lin_fddl_ft[tel][o] * pow (ftpos[nsc], (double)o) * 0.5e-6;
2315  }
2316  } /* End loop on rows */
2317  } /* End loop on base */
2318 
2319  /* Free the temporary allocations */
2320  FREE (cpl_free, lin_fddl_sc);
2321  FREE (cpl_free, lin_fddl_ft);
2322 
2323  gravi_msg_function_exit(1);
2324  return CPL_ERROR_NONE;
2325 }
2326 
2327 /* -------------------------------------------------------------------------- */
2341 /* -------------------------------------------------------------------------- */
2342 
2343 cpl_error_code gravi_vis_create_opddisp_sc (cpl_table * vis_SC,
2344  cpl_table * flux_SC,
2345  cpl_table * wave_table,
2346  cpl_table * disp_table,
2347  cpl_propertylist * header,
2348  const cpl_parameterlist * parlist)
2349 {
2350  gravi_msg_function_start(1);
2351  cpl_ensure_code (vis_SC, CPL_ERROR_NULL_INPUT);
2352  cpl_ensure_code (wave_table, CPL_ERROR_NULL_INPUT);
2353  cpl_ensure_code (header, CPL_ERROR_NULL_INPUT);
2354 
2355  cpl_size nwave_sc = cpl_table_get_column_depth (vis_SC, "VISDATA");
2356 
2357  /* If not DISP_DATA, we cannot create these columns */
2358  if (disp_table == NULL) {
2359  cpl_msg_info (cpl_func,"Cannot create OPD_DISP, not DISP_MODEL table");
2360  gravi_msg_function_exit(1);
2361  return CPL_ERROR_NONE;
2362  }
2363 
2364 
2365  /* Compute the N_MEAN(lbd) and N_DIFF(lbd) for each beam from their
2366  * polynomial model: n = Sum[ coef_i x ((lbd-lbd_met)/lbd_met)^i ] */
2367  cpl_msg_info (cpl_func, "Load the dispersion model coeficients");
2368 
2369  /* Allocate memory */
2370  double ** n_mean = cpl_malloc (4 * sizeof(double*));
2371  double ** n_diff = cpl_malloc (4 * sizeof(double*));
2372  for (int t = 0; t < 4; t++) {
2373  n_mean[t] = cpl_calloc (nwave_sc, sizeof(double));
2374  n_diff[t] = cpl_calloc (nwave_sc, sizeof(double));
2375  }
2376 
2377  if ( cpl_table_has_column (disp_table,"N_MEAN") &&
2378  cpl_table_has_column (disp_table,"WAVE0")) {
2379  /* The N_MEAN and N_DIFF are described as n(lbd) / n(lbdmet)
2380  * with a polynomial versus (wave0/wave-1) */
2381  cpl_msg_info (cpl_func, "Dispersion model as N/Nmet [wave0/wave-1]");
2382  cpl_size disp_order = cpl_table_get_column_depth (disp_table, "N_MEAN");
2383  for (int t = 0; t < 4; t++) {
2384  double lbd0 = cpl_table_get (disp_table, "WAVE0", t, NULL);
2385  for (int w = 0; w < nwave_sc; w++ ) {
2386  double lbd = cpl_table_get (wave_table, "EFF_WAVE", w, NULL);
2387  double xfit = lbd0/lbd - 1.0;
2388  for (int o = 0; o < disp_order; o++) {
2389  n_mean[t][w] += gravi_table_get_value (disp_table, "N_MEAN", t, o) * pow (xfit, o);
2390  n_diff[t][w] += gravi_table_get_value (disp_table, "N_DIFF", t, o) * pow (xfit, o);
2391  }
2392  }
2393  }
2394  } else {
2395  FREELOOP (cpl_free, n_mean, 4);
2396  FREELOOP (cpl_free, n_diff, 4);
2397  cpl_msg_error (cpl_func,"The DISP_MODEL is not recognized... contact the DRS team");
2398  return cpl_error_set_message (cpl_func,CPL_ERROR_ILLEGAL_INPUT,
2399  "The DISP_MODEL is not recognized... contact the DRS team");
2400  }
2401 
2402  CPLCHECK_MSG ("Cannot compute N_MEAN or N_DIFF");
2403 
2404  cpl_size nbase = 6, ntel = 4;
2405  cpl_size nrow_sc = cpl_table_get_nrow (vis_SC) / nbase;
2406 
2407  /* Create the columns */
2408  gravi_table_new_column_array (vis_SC, "OPD_DISP", "m", CPL_TYPE_DOUBLE, nwave_sc);
2409  cpl_array ** opd_disp = cpl_table_get_data_array (vis_SC, "OPD_DISP");
2410 
2411  gravi_table_new_column (vis_SC, "GDELAY_DISP", "m", CPL_TYPE_DOUBLE);
2412  double * gd_disp = cpl_table_get_data_double (vis_SC, "GDELAY_DISP");
2413 
2414  gravi_table_new_column_array (vis_SC, "PHASE_DISP", "rad", CPL_TYPE_DOUBLE, nwave_sc);
2415  cpl_array ** phase_disp = cpl_table_get_data_array (vis_SC, "PHASE_DISP");
2416 
2417  CPLCHECK_MSG ("Cannot create columns");
2418 
2419  /* Get data */
2420  double * opd_met = cpl_table_get_data_double (flux_SC, "OPD_MET_FC");
2421  double * fddl = cpl_table_get_data_double (flux_SC, "FDDL");
2422 
2423  CPLCHECK_MSG ("Cannot get data");
2424 
2425  /* Create wavenumber to be faster */
2426  double * wavenumber_sc = cpl_malloc (nwave_sc * sizeof(double));
2427  for (cpl_size wave = 0; wave < nwave_sc ; wave ++) {
2428  wavenumber_sc[wave] = 1. / cpl_table_get (wave_table, "EFF_WAVE", wave, NULL);
2429  }
2430 
2431  /* Determine OPD_MET_ZERO_FC, based on the content of the header */
2432  int t;
2433  char name[100];
2434  double * opl_zero_fc = cpl_malloc (4 * sizeof(double));
2435  // double gd_zero_fc;
2436 
2437  /* Initialise opl_zero_fc to zero */
2438  for (t = 0; t < ntel; t++) {
2439  opl_zero_fc[t] = 0.0;
2440  }
2441  if ( gravi_param_get_bool (parlist, "gravity.signal.use-met-zero") ) {
2442  cpl_msg_info (cpl_func, "Metrology zero calculation is enabled!");
2443 
2444  /* Replace by OCS MET OPL_ZERO_FC, if available */
2445  for (t = 0; t < ntel; t++) {
2446  sprintf (name, "ESO OCS MET OPL_ZERO_FC%i", t+1);
2447  if (cpl_propertylist_has (header, name)) {
2448  opl_zero_fc[t] = cpl_propertylist_get_double (header, name)*1e-3;
2449  sprintf (name, "ESO FDDL MET OFFSET%i", t+1);
2450  opl_zero_fc[t] += cpl_propertylist_get_double (header, name)*1e-3;
2451  cpl_msg_info (cpl_func, "Updating metrology zero with OCS MET OPL_ZERO_FC%i and FDDL MET OFFSET%i: %f [mm]", t+1, t+1, opl_zero_fc[t]);
2452  }
2453  }
2454 
2455  /* Replace by PRO MET GD_ZERO_FC, if available */
2456  for (t = 0; t < ntel; t++) {
2457  if ( gravi_pfits_has_gdzero (header, t+1) ) {
2458  opl_zero_fc[t] =
2459  gravi_pfits_get_gdzero (header, t+1)*1e-3
2460  * (wavenumber_sc[nwave_sc/2-1] - wavenumber_sc[nwave_sc/2+1])
2461  / (n_mean[t][nwave_sc/2-1] * wavenumber_sc[nwave_sc/2-1] - n_mean[t][nwave_sc/2+1] * wavenumber_sc[nwave_sc/2+1]);
2462  cpl_msg_info (cpl_func, "Updating metrology zero with QC/PRO MET GD_ZERO_FC%i: %f [mm]", t+1, opl_zero_fc[t]);
2463  }
2464  }
2465  // Replace by PRO MET OPL_ZERO_FC, if available
2466  for (t = 0; t < ntel; t++) {
2467  if ( gravi_pfits_get_oplzero (header, t+1) ){
2468  opl_zero_fc[t] = gravi_pfits_get_oplzero (header, t+1)*1e-3;
2469  cpl_msg_info (cpl_func, "Updating metrology zero with QC/PRO MET OPL_ZERO_FC%i: %f [mm]", t+1, opl_zero_fc[t]);
2470  }
2471  }
2472  } else {
2473  cpl_msg_info (cpl_func, "Metrology zero calculation is disabled!");
2474  }
2475 
2476  /* Loop on tel and frames */
2477  for (cpl_size base = 0; base < nbase; base++) {
2478  for (cpl_size row_sc = 0; row_sc < nrow_sc; row_sc ++) {
2479 
2480  cpl_size nsc = row_sc * nbase + base;
2481  cpl_size t0 = GRAVI_BASE_TEL[base][0], t0f = row_sc * ntel + t0;
2482  cpl_size t1 = GRAVI_BASE_TEL[base][1], t1f = row_sc * ntel + t1;
2483 
2484  /* Compute the group-delay introduced by FDDL in the middle of the band
2485  * This is obviously to a constant */
2486  cpl_size wave = nwave_sc / 2;
2487  double s1 = wavenumber_sc[wave-1];
2488  double s2 = wavenumber_sc[wave+1];
2489  double o1 =
2490  (n_mean[t0][wave-1] * (opd_met[t0f]-opl_zero_fc[t0]) + n_diff[t0][wave-1] * fddl[t0f]) -
2491  (n_mean[t1][wave-1] * (opd_met[t1f]-opl_zero_fc[t1]) + n_diff[t1][wave-1] * fddl[t1f]);
2492  double o2 =
2493  (n_mean[t0][wave+1] * (opd_met[t0f]-opl_zero_fc[t0]) + n_diff[t0][wave+1] * fddl[t0f]) -
2494  (n_mean[t1][wave+1] * (opd_met[t1f]-opl_zero_fc[t1]) + n_diff[t1][wave+1] * fddl[t1f]);
2495 
2496  gd_disp[nsc] = (o1*s1 - o2*s2) / (s1-s2);
2497 
2498  /* Compute the phase introduced by FDDL. This is also to a dispersive constant
2499  * since the amount of fiber and vaccum is not known */
2500  phase_disp[nsc] = cpl_array_new (nwave_sc, CPL_TYPE_DOUBLE);
2501 
2502  for (int w = 0; w < nwave_sc ; w++) {
2503  cpl_array_set (phase_disp[nsc], w,
2504  ((n_mean[t0][w] * (opd_met[t0f]-opl_zero_fc[t0]) + n_diff[t0][w] * fddl[t0f]) -
2505  (n_mean[t1][w] * (opd_met[t1f]-opl_zero_fc[t1]) + n_diff[t1][w] * fddl[t1f]) -
2506  gd_disp[nsc]) * wavenumber_sc[w] * CPL_MATH_2PI);
2507  }
2508 
2509  gravi_array_phase_wrap (phase_disp[nsc]);
2510 
2511  /* Compute the OPD_DISP for each wavelength :
2512  * T0 = N_DIFF0 * (FDDL_SC0+FDDL_FT0)/2 + N_MEAN0 * (MET_SC0-MET_FT0)
2513  * T1 = N_DIFF1 * (FDDL_SC1+FDDL_FT1)/2 + N_MEAN1 * (MET_SC1-MET_FT1) */
2514  opd_disp[nsc] = cpl_array_new (nwave_sc, CPL_TYPE_DOUBLE);
2515 
2516  for (int w = 0; w < nwave_sc ; w++) {
2517  cpl_array_set (opd_disp[nsc], w,
2518  (n_mean[t0][w] * (opd_met[t0f]-opl_zero_fc[t0]) + n_diff[t0][w] * fddl[t0f]) -
2519  (n_mean[t1][w] * (opd_met[t1f]-opl_zero_fc[t1]) + n_diff[t1][w] * fddl[t1f]) );
2520  }
2521 
2522  } /* End loop on rows */
2523  } /* End loop on base */
2524 
2525  /* Free the temporary allocations */
2526  FREELOOP (cpl_free, n_mean, 4);
2527  FREELOOP (cpl_free, n_diff, 4);
2528  FREE (cpl_free, wavenumber_sc);
2529  FREE (cpl_free, opl_zero_fc);
2530 
2531  gravi_msg_function_exit(1);
2532  return CPL_ERROR_NONE;
2533 }
2534 
2535 /*----------------------------------------------------------------------------*/
2547 /*----------------------------------------------------------------------------*/
2548 
2549 cpl_error_code gravi_vis_create_imagingref_sc (cpl_table * vis_SC,
2550  cpl_table * wave_table,
2551  cpl_propertylist * header,
2552  const cpl_parameterlist * parlist)
2553 {
2554  gravi_msg_function_start(1);
2555  cpl_ensure_code (vis_SC, CPL_ERROR_NULL_INPUT);
2556  cpl_ensure_code (wave_table, CPL_ERROR_NULL_INPUT);
2557  cpl_ensure_code (header, CPL_ERROR_NULL_INPUT);
2558 
2559  /* Get from OI_VIS the number of wavelength channels and rows */
2560  cpl_size nwave = cpl_table_get_column_depth (vis_SC, "VISDATA");
2561  cpl_size nrow = cpl_table_get_nrow (vis_SC);
2562 
2563  /* Get from OI_VIS the data needed for the calculation */
2564  double * ucoord = cpl_table_get_data_double (vis_SC, "UCOORD");
2565  double * vcoord = cpl_table_get_data_double (vis_SC, "VCOORD");
2566  cpl_array ** phase_ref = cpl_table_get_data_array (vis_SC, "PHASE_REF");
2567  double * opd_met_telfc_mcorr = NULL;
2568  double * opd_met_fc_corr = NULL;
2569  CPLCHECK_MSG ("Cannot get input data");
2570 
2571  /* If OPD_DISP is not computed, we cannot compute IMAGING_REF neither */
2572  if ( !cpl_table_has_column (vis_SC, "OPD_DISP") ) {
2573  cpl_msg_info (cpl_func,"Cannot compute IMAGING_REF, not column OPD_DISP");
2574  gravi_msg_function_exit(1);
2575  return CPL_ERROR_NONE;
2576  }
2577 
2578  cpl_array ** opd_disp = cpl_table_get_data_array (vis_SC, "OPD_DISP");
2579  CPLCHECK_MSG ("Cannot get OPD_DISP data");
2580 
2581  /* Get from header the separation, converted from mas to radian */
2582  double sep_U = gravi_pfits_get_sobj_x (header)*1e-3/3600.0/CPL_MATH_DEG_RAD;
2583  double sep_V = gravi_pfits_get_sobj_y (header)*1e-3/3600.0/CPL_MATH_DEG_RAD;
2584 
2585  /* Create new PHASE_REF_IMG column array */
2586  gravi_table_new_column_array (vis_SC, "IMAGING_REF", "rad", CPL_TYPE_DOUBLE, nwave);
2587  cpl_array ** imaging_ref = cpl_table_get_data_array (vis_SC, "IMAGING_REF");
2588  CPLCHECK_MSG ("Cannot create column");
2589 
2590  /* Which megtrology should be used for IMAGING_REF calculation? */
2591  const char * imaging_ref_met = gravi_param_get_string (parlist, "gravity.signal.imaging-ref-met");
2592  cpl_msg_info (cpl_func, "imaging-ref-met = %s", imaging_ref_met);
2593  if (!strcmp (imaging_ref_met,"TEL")) {
2594  cpl_msg_info (cpl_func,"Use telescope metrology for IMAGING_REF computation");
2595  opd_met_telfc_mcorr = cpl_table_get_data_double (vis_SC, "OPD_MET_TELFC_MCORR");
2596  opd_met_fc_corr = cpl_table_get_data_double (vis_SC, "OPD_MET_FC_CORR");
2597  } else if (!strcmp (imaging_ref_met,"FC_CORR")) {
2598  cpl_msg_info (cpl_func,"Use corrected fiber coupler metrology for IMAGING_REF computation");
2599  opd_met_fc_corr = cpl_table_get_data_double (vis_SC, "OPD_MET_FC_CORR");
2600  } else if (!strcmp (imaging_ref_met,"FC")) {
2601  cpl_msg_info (cpl_func,"Use fiber coupler metrology for IMAGING_REF computation");
2602  } else {
2603  cpl_msg_error (cpl_func,"Unknown metrology source for IMAGING_REF calculation!");
2604  cpl_ensure_code (imaging_ref_met, CPL_ERROR_ILLEGAL_INPUT);
2605  }
2606 
2607  /* Compute the reference phase for each row */
2608  for (cpl_size row = 0; row < nrow; row ++) {
2609 
2610  /* New array */
2611  imaging_ref[row] = cpl_array_new (nwave, CPL_TYPE_DOUBLE);
2612 
2613  /* If requested, use fiber coupler correction or telescope metrology */
2614  double opd_met_corr = (opd_met_telfc_mcorr ? opd_met_telfc_mcorr[row] : 0.0)
2615  + (opd_met_fc_corr ? opd_met_fc_corr[row] : 0.0);
2616 
2617  /* Compute VISPHI for each wavelength */
2618  for (int w = 0; w < nwave; w++) {
2619 
2620  double wavelength = cpl_table_get (wave_table, "EFF_WAVE", w, NULL);
2621 
2622  /* IMAGING_REF = PHASE_REF - OPD_DISP * (2PI/EFF_WAVE) +
2623  (UCOORD*SOBJ_X + VCOORD*SOBJ_Y) * (2PI/EFF_WAVE) */
2624  cpl_array_set (imaging_ref[row], w,
2625  cpl_array_get (phase_ref[row], w, NULL)
2626  - cpl_array_get (opd_disp[row], w, NULL) * CPL_MATH_2PI / wavelength
2627  + (ucoord[row] * sep_U + vcoord[row] * sep_V) * CPL_MATH_2PI / wavelength
2628  - opd_met_corr * CPL_MATH_2PI / wavelength);
2629  CPLCHECK_MSG ("Cannot compute the imaging phase");
2630  }
2631 
2632  /* Wrap this phase in [rad] */
2633  gravi_array_phase_wrap (imaging_ref[row]);
2634  }
2635 
2636  gravi_msg_function_exit(1);
2637  return CPL_ERROR_NONE;
2638 }
2639 
2640 /*----------------------------------------------------------------------------*/
2654 /*----------------------------------------------------------------------------*/
2655 
2656 cpl_error_code gravi_compute_signals (gravi_data * p2vmred_data,
2657  gravi_data * disp_data,
2658  const cpl_parameterlist * parlist)
2659 {
2660  gravi_msg_function_start(1);
2661  cpl_ensure_code (p2vmred_data, CPL_ERROR_NULL_INPUT);
2662 
2663  int nbase = 6, ntel = 4;
2664 
2665  /* Get header data */
2666  cpl_propertylist * p2vmred_header = gravi_data_get_header (p2vmred_data);
2667  int npol_ft = gravi_pfits_get_pola_num (p2vmred_header, GRAVI_FT);
2668  int npol_sc = gravi_pfits_get_pola_num (p2vmred_header, GRAVI_SC);
2669 
2670  CPLCHECK_MSG ("Cannot get header");
2671 
2672  /* FIXME: probably doesn't work with npol_sc != npol_ft */
2673  if ( npol_sc != npol_ft ) {
2674  gravi_msg_warning ("FIXME", "Not sure this function works with npol_sc != npol_ft");
2675  }
2676 
2677 
2678  /* Get the SC DIT */
2679  double dit_sc = gravi_pfits_get_dit_sc (p2vmred_header) * 1e6;
2680  cpl_msg_info (cpl_func,"dit_sc = %g [us]", dit_sc);
2681 
2682 
2683  /*
2684  * Loop on polarisations
2685  */
2686  for (int pol = 0; pol < CPL_MAX(npol_sc,npol_ft); pol++) {
2687 
2688  /* verbose */
2689  cpl_msg_info (cpl_func, "Start polarisation %d over %d",pol+1, CPL_MAX(npol_sc,npol_ft));
2690  cpl_msg_info(cpl_func, "Insname FT : %s, pol %d npol %d",
2691  GRAVI_INSNAME(GRAVI_FT,pol,npol_ft), pol, npol_ft);
2692  cpl_msg_info(cpl_func, "Insname SC : %s, pol %d npol %d",
2693  GRAVI_INSNAME(GRAVI_SC,pol,npol_sc), pol, npol_sc);
2694 
2695  /* Get the table of reduced data from FT */
2696  cpl_table * vis_FT = gravi_data_get_oi_vis (p2vmred_data, GRAVI_FT, pol, npol_ft);
2697  cpl_table * flux_FT = gravi_data_get_oi_flux (p2vmred_data, GRAVI_FT, pol, npol_ft);
2698  CPLCHECK_MSG ("Cannot get the FT tables");
2699 
2700  /* Get the table of reduced data from SC */
2701  cpl_table * vis_SC = gravi_data_get_oi_vis (p2vmred_data, GRAVI_SC, pol, npol_sc);
2702  cpl_table * flux_SC = gravi_data_get_oi_flux (p2vmred_data, GRAVI_SC, pol, npol_sc);
2703  CPLCHECK_MSG ("Cannot get the SC tables");
2704 
2705  /* Get the metrology and FDDL */
2706  cpl_table * vis_met = gravi_data_get_table (p2vmred_data, GRAVI_OI_VIS_MET_EXT);
2707  cpl_table * fddl_table = gravi_data_get_table (p2vmred_data, GRAVI_FDDL_EXT);
2708  CPLCHECK_MSG ("Cannot get the VIS_MET and FDDL tables");
2709 
2710  /* Get the OIFITS tables that are alredy in the data */
2711  cpl_table * oi_wavelengthft = gravi_data_get_oi_wave (p2vmred_data, GRAVI_FT, pol, npol_ft);
2712  cpl_table * oi_wavelengthsc = gravi_data_get_oi_wave (p2vmred_data, GRAVI_SC, pol, npol_sc);
2713  CPLCHECK_MSG ("Cannot get the OI_WAVELENGTH tables");
2714 
2715 
2716  /*
2717  * (1) Create synchronisation information
2718  */
2719 
2720  /* Create the FIRST_FT and LAST_FT for each SC frame */
2721  gravi_signal_create_sync (vis_SC, 6, dit_sc, vis_FT, 6, "FT");
2722  gravi_signal_create_sync (vis_SC, 6, dit_sc, vis_met, 4, "MET");
2723 
2724  CPLCHECK_MSG ("Cannot sync vis_SC");
2725 
2726  /* Create the FIRST_MET and LAST_MET for each SC frame */
2727  gravi_signal_create_sync (flux_SC, 4, dit_sc, flux_FT, 4, "FT");
2728  gravi_signal_create_sync (flux_SC, 4, dit_sc, vis_met, 4, "MET");
2729  gravi_signal_create_sync (flux_SC, 4, dit_sc, fddl_table, 1, "FDDL");
2730 
2731  CPLCHECK_MSG ("Cannot sync flux_SC");
2732 
2733  /*
2734  * (2) Create the signals for FLUX_FT
2735  */
2736 
2737  cpl_array ** flux_ft = cpl_table_get_data_array (flux_FT, "FLUX");
2738  cpl_size nwave_ft = cpl_table_get_column_depth (vis_FT, "VISDATA");
2739  cpl_size nrow_ft = cpl_table_get_nrow (vis_FT) / nbase;
2740 
2741  gravi_table_new_column (flux_FT, "TOTALFLUX", "e", CPL_TYPE_DOUBLE);
2742  double * total_flux_ft = cpl_table_get_data_double (flux_FT, "TOTALFLUX");
2743 
2744  CPLCHECK_MSG ("Cannot create columns");
2745 
2746  /* Total flux in [e] */
2747  for (cpl_size row = 0; row < nrow_ft * ntel; row ++) {
2748  total_flux_ft[row] = cpl_array_get_mean (flux_ft[row]) * nwave_ft;
2749  }
2750 
2751  /* Smooth TOTALFLUX of the FT over few samples. Maybe make sure
2752  * this is a constant frequency, not a constant nb of samples */
2753  gravi_table_smooth_column (flux_FT, "TOTALFLUX", "TOTALFLUX", 10, ntel);
2754 
2755  CPLCHECK_MSG("Cannot compute TOTALFLUX for FT");
2756 
2757  /*
2758  * (3) Create the signals for VIS_FT
2759  */
2760 
2761  /* Create F1F2 and PHASE_REF column */
2762  gravi_vis_create_f1f2_ft (vis_FT, flux_FT);
2764 
2765  CPLCHECK_MSG ("Cannot create signals for VIS_FT");
2766 
2767  /*
2768  * (4) Create the signal for FLUX_SC
2769  */
2770  gravi_flux_create_met_sc (flux_SC, vis_met);
2771  gravi_flux_create_fddlpos_sc (flux_SC, fddl_table);
2772  gravi_flux_create_totalflux_sc (flux_SC, flux_FT);
2773 
2774  CPLCHECK_MSG ("Cannot create the signal for FLUX_SC");
2775 
2776  /*
2777  * (5) Create the signals for VIS_SC
2778  */
2779  gravi_vis_create_pfactor_sc (vis_SC, flux_FT);
2780  gravi_vis_create_f1f2_sc (vis_SC, flux_SC);
2781  gravi_vis_create_met_sc (vis_SC, vis_met);
2782 
2783  gravi_vis_create_vfactor_sc (vis_SC, oi_wavelengthsc,
2784  vis_FT, oi_wavelengthft);
2785 
2786  CPLCHECK_MSG ("Cannot create signals for VIS_SC");
2787 
2788  /*
2789  * Create QC for PFACTOR and VFACTOR
2790  */
2791 
2792  for (int base = 0; base < nbase; base++) {
2793  char qc_name[100];
2794 
2795  sprintf (qc_name, "ESO QC VFACTOR%s_P%d AVG", GRAVI_BASE_NAME[base], pol+1);
2796  double vmean = gravi_table_get_column_mean (vis_SC, "V_FACTOR_WL", base, nbase);
2797  cpl_propertylist_update_double (p2vmred_header, qc_name, vmean);
2798  cpl_propertylist_set_comment (p2vmred_header, qc_name, "mean v-factor");
2799 
2800  sprintf (qc_name, "ESO QC PFACTOR%s_P%d AVG", GRAVI_BASE_NAME[base], pol+1);
2801  double pmean = gravi_table_get_column_mean (vis_SC, "P_FACTOR", base, nbase);
2802  cpl_propertylist_update_double (p2vmred_header, qc_name, pmean);
2803  cpl_propertylist_set_comment (p2vmred_header, qc_name, "mean p-factor");
2804  }
2805 
2806  /*
2807  * If available, create the signal from ACQ camera
2808  */
2809  if (gravi_data_has_extension (p2vmred_data, GRAVI_OI_VIS_ACQ_EXT)) {
2810 
2811  cpl_table * vis_ACQ = gravi_data_get_table (p2vmred_data, GRAVI_OI_VIS_ACQ_EXT);
2812  gravi_signal_create_sync (vis_SC, 6, dit_sc, vis_ACQ, 4, "ACQ");
2813  gravi_signal_create_sync (flux_SC, 4, dit_sc, vis_ACQ, 4, "ACQ");
2814 
2815  gravi_vis_create_acq_sc (vis_SC, vis_ACQ);
2816  gravi_flux_create_acq_sc (flux_SC, vis_ACQ);
2817  }
2818 
2819  /*
2820  * Compute FDDL = (FDDL_SC + FDDL_FT)/2 in [m]
2821  * from the POS_SC, POS_FT and the linearity coeficients
2822  *
2823  * Compute the OPD_DISP = n(lbd) * ODD_MET
2824  * from the OPD_MET and the dispersion coeficients
2825  */
2826  cpl_table * disp_table = disp_data ? gravi_data_get_table (disp_data, "DISP_MODEL") : NULL;
2827 
2828  gravi_flux_create_fddllin_sc (flux_SC, disp_table);
2829  gravi_vis_create_opddisp_sc (vis_SC, flux_SC, oi_wavelengthsc, disp_table, p2vmred_header, parlist);
2830 
2831  CPLCHECK_MSG ("Cannot compute the OPD_DISP");
2832 
2833 
2834  /*
2835  * Compute the GDELAY of the FT and SC with the proper algorithm.
2836  * Critical since these quantities are used for debuging astrometry
2837  */
2838 
2839  /* Recompute the GDELAY of the FT (probably useless since one use GDELAY_FT) */
2840  gravi_table_compute_group_delay (vis_FT, "VISDATA", "GDELAY", oi_wavelengthft);
2841 
2842  /* Recompute the GDELAY of the SC (probably usefull) */
2843  gravi_table_compute_group_delay (vis_SC, "VISDATA", "GDELAY", oi_wavelengthsc);
2844 
2845  /* Compute the GDELAY_FT of VISDATA_FT in SC table (critical) */
2846  gravi_table_compute_group_delay (vis_SC, "VISDATA_FT", "GDELAY_FT", oi_wavelengthft);
2847 
2848  CPLCHECK_MSG ("Cannot compute the GDELAYs");
2849 
2850  /* Compute the SELF_REF phase reference for SC (first) */
2851  gravi_vis_create_phaseref_sc (vis_SC, oi_wavelengthsc, NULL);
2852 
2853  /* Compute the PHASE_REF reference for SC */
2854  gravi_vis_create_phaseref_sc (vis_SC, oi_wavelengthsc, oi_wavelengthft);
2855 
2856  /* Create the IMAGING_REF phase ref, need PHASE_REF */
2857  gravi_vis_create_imagingref_sc (vis_SC, oi_wavelengthsc, p2vmred_header, parlist);
2858 
2859  CPLCHECK_MSG ("Cannot compute the PHASE_REF");
2860  } /* End loop on pol */
2861 
2862 
2863  gravi_msg_function_exit(1);
2864  return CPL_ERROR_NONE;
2865 }
2866 
2867 /*----------------------------------------------------------------------------*/
2887 /*----------------------------------------------------------------------------*/
2888 
2889 cpl_error_code gravi_compute_rejection (gravi_data * p2vmred_data,
2890  const cpl_parameterlist * parlist)
2891 {
2892  gravi_msg_function_start(1);
2893  cpl_ensure_code (p2vmred_data, CPL_ERROR_NULL_INPUT);
2894 
2895  int nbase = 6;
2896 
2897  /* Get header data */
2898  cpl_propertylist * p2vmred_header = gravi_data_get_header (p2vmred_data);
2899  CPLCHECK_MSG ("Cannot get header");
2900 
2901  /*
2902  * (1) Do the FT rejection flags
2903  */
2904  if (gravi_data_has_type (p2vmred_data, "_FT") < 2 ) {
2905  cpl_msg_info (cpl_func, "Cannot compute rejection flags for FT (no FT data)");
2906  }
2907  else {
2908  cpl_msg_info (cpl_func, "Compute rejection flags for FT");
2909 
2910  /* Get the SNR thresholds from parameter */
2911  double threshold_SNR_ft = gravi_param_get_double (parlist, "gravity.signal.snr-min-ft");
2912  double threshold_STATE_ft = gravi_param_get_double (parlist, "gravity.signal.state-min-ft");
2913  double min_GSTATE_ft = gravi_param_get_double (parlist, "gravity.signal.global-state-min-ft");
2914  double max_GSTATE_ft = gravi_param_get_double (parlist, "gravity.signal.global-state-max-ft");
2915 
2916  cpl_msg_info (cpl_func,"SNR threshold to define fringe-detection in FT: %g", threshold_SNR_ft);
2917  cpl_msg_info (cpl_func,"STATE threshold for FT: %g", threshold_STATE_ft);
2918  cpl_msg_info (cpl_func,"GLOBAL_STATE threshold for FT: %g - %g", min_GSTATE_ft, max_GSTATE_ft);
2919 
2920  /* Loop on polarisations */
2921  int npol_ft = gravi_pfits_get_pola_num (p2vmred_header, GRAVI_FT);
2922  for (int pol = 0; pol < npol_ft; pol++) {
2923 
2924  /* Get the pointer to data */
2925  cpl_table * vis_FT = gravi_data_get_oi_vis (p2vmred_data, GRAVI_FT, pol, npol_ft);
2926  double * snr = cpl_table_get_data_double (vis_FT, "SNR_BOOT");
2927  int * state = cpl_table_get_data_int (vis_FT, "STATE");
2928  int * gstate = cpl_table_get_data_int (vis_FT, "OPDC_STATE");
2929 
2930  gravi_table_new_column (vis_FT, "REJECTION_FLAG", NULL, CPL_TYPE_INT);
2931  int * reject_flag_ft = cpl_table_get_data_int (vis_FT, "REJECTION_FLAG");
2932 
2933  CPLCHECK_MSG ("Cannot create columns");
2934 
2935  /* Loop on base and rows */
2936  cpl_size nrow_ft = cpl_table_get_nrow (vis_FT) / nbase;
2937  for (cpl_size row = 0; row < nrow_ft * nbase; row ++) {
2938 
2939  /* Rejection based on SNR (first bit) */
2940  int snr_bit = 0;
2941  if ( snr[row] < threshold_SNR_ft )
2942  gravi_bit_set (reject_flag_ft[row], snr_bit);
2943  else
2944  gravi_bit_clear (reject_flag_ft[row], snr_bit);
2945 
2946  /* Rejection based on STATE (2sd bit) */
2947  int state_bit = 1;
2948  if ( state[row] < threshold_STATE_ft ||
2949  gstate[row] < min_GSTATE_ft ||
2950  gstate[row] > max_GSTATE_ft )
2951  gravi_bit_set (reject_flag_ft[row], state_bit);
2952  else
2953  gravi_bit_clear (reject_flag_ft[row], state_bit);
2954  }
2955 
2956  } /* End loop on polarisation */
2957  } /* End FT */
2958 
2959 
2960  /*
2961  * (2) Ratio of FT valid inside each SC DIT
2962  */
2963  if (gravi_data_has_type (p2vmred_data, "_FT") < 1 ||
2964  gravi_data_has_type (p2vmred_data, "_SC") < 1) {
2965  cpl_msg_info (cpl_func, "Cannot compute tracking ratio for SC (no FT or SC data)");
2966  }
2967  else {
2968  cpl_msg_info (cpl_func, "Compute tracking ratio for each SC DIT");
2969 
2970  /* Loop on polarisations */
2971  int npol_sc = gravi_pfits_get_pola_num (p2vmred_header, GRAVI_SC);
2972  int npol_ft = gravi_pfits_get_pola_num (p2vmred_header, GRAVI_FT);
2973  for (int pol = 0; pol < npol_sc; pol++) {
2974 
2975  cpl_table * vis_SC = gravi_data_get_oi_vis (p2vmred_data, GRAVI_SC, pol, npol_sc);
2976  cpl_table * vis_FT = gravi_data_get_oi_vis (p2vmred_data, GRAVI_FT, CPL_MIN(pol,npol_ft), npol_ft);
2977  gravi_vis_create_lockratio_sc (vis_SC, vis_FT);
2978  CPLCHECK_MSG ("Cannot compute lockratio_sc");
2979  }
2980  }
2981 
2982  /*
2983  * (3) Do the SC rejection flags
2984  */
2985  if (gravi_data_has_type (p2vmred_data, "_SC") < 2 ) {
2986  cpl_msg_info (cpl_func, "Cannot compute rejection flags for SC (no SC data)");
2987  }
2988  else {
2989  cpl_msg_info (cpl_func, "Compute rejection flags for SC");
2990 
2991  /* Get the SC rejection parameters */
2992  double minlockratio_sc = gravi_param_get_double (parlist, "gravity.signal.tracking-min-sc");
2993  double minvfactor_sc = gravi_param_get_double (parlist, "gravity.signal.vfactor-min-sc");
2994 
2995  cpl_msg_info (cpl_func,"Fringe-detection ratio to discard frame on SC: %g", minlockratio_sc);
2996  cpl_msg_info (cpl_func,"vFactor threshold to discard frame on SC: %g", minvfactor_sc);
2997 
2998  /* Loop on polarisations */
2999  int npol_sc = gravi_pfits_get_pola_num (p2vmred_header, GRAVI_SC);
3000  for (int pol = 0; pol < npol_sc; pol++) {
3001 
3002  /* Get the table of reduced data */
3003  cpl_table * vis_SC = gravi_data_get_oi_vis (p2vmred_data, GRAVI_SC, pol, npol_sc);
3004  double * vFactor_wl = cpl_table_get_data_double (vis_SC, "V_FACTOR_WL");
3005  double * fringedet_ftdit = cpl_table_get_data_double (vis_SC, "FRINGEDET_RATIO");
3006 
3007  gravi_table_new_column (vis_SC, "REJECTION_FLAG", NULL, CPL_TYPE_INT);
3008  int * reject_flag_sc = cpl_table_get_data_int (vis_SC, "REJECTION_FLAG");
3009 
3010  CPLCHECK_MSG ("Cannot create columns");
3011 
3012  /* Loop on base and row SC */
3013  cpl_size nrow_sc = cpl_table_get_nrow (vis_SC) / nbase;
3014  for (cpl_size row_sc = 0; row_sc < nrow_sc * nbase; row_sc++) {
3015 
3016  /* Rejection based in lockratio (first bit) */
3017  int lock_bit = 0;
3018  if ( fringedet_ftdit[row_sc] < minlockratio_sc )
3019  gravi_bit_set (reject_flag_sc[row_sc], lock_bit);
3020  else
3021  gravi_bit_clear (reject_flag_sc[row_sc], lock_bit);
3022 
3023  /* Rejection based in the white-light vFactor (second bit) */
3024  int vfactor_bit = 1;
3025  if ( vFactor_wl[row_sc] < minvfactor_sc )
3026  gravi_bit_set (reject_flag_sc[row_sc], vfactor_bit);
3027  else
3028  gravi_bit_clear (reject_flag_sc[row_sc], vfactor_bit);
3029  }
3030 
3031  } /* End loop on pol */
3032  } /* End SC */
3033 
3034  gravi_msg_function_exit(1);
3035  return CPL_ERROR_NONE;
3036 }
3037 
cpl_error_code gravi_vis_create_acq_sc(cpl_table *vis_SC, cpl_table *vis_ACQ)
Compute the averaged ACQ signal for each SC DIT per base.
cpl_error_code gravi_vis_create_f1f2_ft(cpl_table *vis_FT, cpl_table *flux_FT)
Compute the photometric normalisation for the FT.
Definition: gravi_signal.c:941
cpl_error_code gravi_vis_create_opdsc_ft(cpl_table *vis_FT, cpl_table *vis_SC, double dit_sc)
Compute the resampled SC signal for each FT DIT per base.
int gravi_data_has_extension(gravi_data *raw_calib, const char *ext_name)
Check if data has extension with given EXTNAME.
Definition: gravi_data.c:1443
cpl_error_code gravi_vis_correct_phasediff(cpl_table *oi_vis1, const char *name1, cpl_table *oi_vis2, const char *name2, double *phasediff)
Correct for mean phase-difference between coherent fluxes.
Definition: gravi_signal.c:211
cpl_error_code gravi_vis_compute_mean_phasor(cpl_table *oi_vis, const char *name_vis, const char *name_err, const char *name_pha, const char *name_var)
Compute real-time mean phasor of a VISDATA by averaging all spectral elements.
Definition: gravi_signal.c:272
cpl_error_code gravi_flux_create_met_sc(cpl_table *flux_SC, cpl_table *vis_MET)
Compute the averaged MET signal for each SC DIT per beam.
cpl_error_code gravi_compute_snr(gravi_data *p2vmred_data, const cpl_parameterlist *parlist)
Compute real-time SNR and Group-Delay of the observation.
Definition: gravi_signal.c:511
cpl_error_code gravi_vis_create_phaseref_sc(cpl_table *vis_SC, cpl_table *wave_table_sc, cpl_table *wave_table_ft)
Compute the reference phase for each SC DIT.
cpl_error_code gravi_vis_compute_interspectre(cpl_table *oi_vis, const char *name_vis, const char *name_is)
Compute the real-time interspectra.
Definition: gravi_signal.c:341
cpl_error_code gravi_vis_create_opddisp_sc(cpl_table *vis_SC, cpl_table *flux_SC, cpl_table *wave_table, cpl_table *disp_table, cpl_propertylist *header, const cpl_parameterlist *parlist)
Compute the MET opd including the dispersion from the FDDL.
cpl_error_code gravi_vis_create_phaseref_ft(cpl_table *vis_FT)
Compute the self-reference phase for each FT DIT.
cpl_error_code gravi_vis_compute_isdelay(cpl_table *oi_vis, const char *name_isp, const char *name_gdl, cpl_table *oi_wavelength)
Compute the group-delay from interspectra.
Definition: gravi_signal.c:451
cpl_error_code gravi_vis_bootstrap_snr_and_delay(cpl_table *oi_vis, const char *name_snr, const char *name_gdl)
Boostrap real-time SNR and GDELAY.
Definition: gravi_signal.c:143
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_error_code gravi_vis_create_pfactor_sc(cpl_table *vis_SC, cpl_table *flux_FT)
Compute the PFACTOR for the SC.
Definition: gravi_signal.c:830
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_vis_create_met_sc(cpl_table *vis_SC, cpl_table *vis_MET)
Compute the averaged MET signal for each SC DIT per base.
cpl_error_code gravi_vis_create_lockratio_sc(cpl_table *vis_SC, cpl_table *vis_FT)
Create the clockratio for each SC DIT and baseline.
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:1077
cpl_error_code gravi_vis_compute_snr(cpl_table *oi_vis, const char *name_pha, const char *name_var, const char *name_snr)
Compute the real-time SNR.
Definition: gravi_signal.c:401
cpl_error_code gravi_vis_create_vfactor_sc(cpl_table *vis_SC, cpl_table *wave_table_sc, cpl_table *vis_FT, cpl_table *wave_table_ft)
Compute the VFACTOR for each SC DIT based on real-time FT.
cpl_error_code gravi_flux_create_acq_sc(cpl_table *vis_SC, cpl_table *vis_ACQ)
Compute the averaged ACQ signal for each SC DIT per beam.
cpl_error_code gravi_compute_signals(gravi_data *p2vmred_data, gravi_data *disp_data, const cpl_parameterlist *parlist)
Create intermediate signal in the P2VMREDUCED file.
cpl_error_code gravi_compute_rejection(gravi_data *p2vmred_data, const cpl_parameterlist *parlist)
Create rejection flags P2VMREDUCED file.
cpl_error_code gravi_flux_create_fddllin_sc(cpl_table *flux_SC, cpl_table *disp_table)
Compute the (FDDL_SC + FDDL_FT)/2 position in [m].
cpl_error_code gravi_flux_create_fddlpos_sc(cpl_table *flux_SC, cpl_table *fddl_table)
Compute the averaged FDDL signal for each SC DIT per beam.
int gravi_data_has_type(gravi_data *self, const char *type)
Return the number of ext whose EXTNAME and INSNAME match &#39;type&#39;.
Definition: gravi_data.c:1468
cpl_error_code gravi_array_add_phasors(cpl_array *input, cpl_array *add, cpl_array *sub)
Add a pair of COMPLEX arrays to a COMPLEX array, in-place: input = input + add*conj(sub) ...
Definition: gravi_cpl.c:1047
cpl_error_code gravi_vis_create_imagingref_sc(cpl_table *vis_SC, cpl_table *wave_table, cpl_propertylist *header, const cpl_parameterlist *parlist)
Create phase-referenced imaging data in the P2VMREDUCED file.
cpl_error_code gravi_vis_create_met_ft(cpl_table *vis_FT, cpl_table *vis_MET)
Compute the resampled MET signal for each FT DIT per base.
cpl_error_code gravi_flux_create_totalflux_sc(cpl_table *flux_SC, cpl_table *flux_FT)
Compute total flux of each DIT for the SC and of the FT.
cpl_error_code gravi_signal_create_sync(cpl_table *vis_SC, int nbase_sc, double dit_sc, cpl_table *vis_FT, int nbase_ft, const char *name)
Compute synchronisation indices between OIFITS tables.
Definition: gravi_signal.c:743
cpl_error_code gravi_vis_create_f1f2_sc(cpl_table *vis_SC, cpl_table *flux_SC)
Compute the photometric normalisation for the SC.
Definition: gravi_signal.c:893