GRAVI Pipeline Reference Manual 1.10.1
Loading...
Searching...
No Matches
gravi_vis.c
Go to the documentation of this file.
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
35/*
36 * History
37 * 21.11.2018 memory leak in gravi_average_self_visphi
38 * changes marked as 'EKW'
39 * 11/01/2019 Fix Warning parameter 'ret'
40 */
41/*-----------------------------------------------------------------------------
42 Includes
43 -----------------------------------------------------------------------------*/
44
45#ifdef HAVE_CONFIG_H
46#include <config.h>
47#endif
48
49#include <cpl.h>
50#include <string.h>
51#include <stdio.h>
52#include <math.h>
53#include <time.h>
54#include <complex.h>
55#include <string.h>
56#include <float.h>
57
58#include "gravi_data.h"
59#include "gravi_dfs.h"
60#include "gravi_pfits.h"
61#include "gravi_cpl.h"
62
63#include "gravi_utils.h"
64
65#include "gravi_vis.h"
66#include "gravi_eop.h"
67#include "gravi_tf.h"
68#include "gravi_idp.h"
69
70/*-----------------------------------------------------------------------------
71 Private prototypes
72 -----------------------------------------------------------------------------*/
73
74double gravi_randn (void);
75
76cpl_error_code gravi_array_online_variance(cpl_array * data, cpl_array * mean, cpl_array * variance, int n);
77cpl_error_code gravi_array_online_variance_res(cpl_array ** data,
78 int n, int rephase);
79cpl_error_code gravi_flux_average_bootstrap(cpl_table * oi_flux_avg,
80 cpl_table * oi_flux,
81 int nboot,
82 double outlier_threshold);
83cpl_error_code gravi_t3_average_bootstrap(cpl_table * oi_t3_avg,
84 cpl_table * oi_vis,
85 cpl_table * oi_flux,
86 int nboot,
87 int use_vFactor,
88 int use_pFactor,
89 double outlier_threshold);
90cpl_error_code gravi_vis_average_bootstrap (cpl_table * oi_vis_avg,
91 cpl_table * oi_vis2_avg,
92 cpl_table * oi_vis,
93 int nboot,
94 const char * phase_ref,
95 int use_vFactor,
96 int use_pFactor,
97 int use_debiasing,
98 double outlier_threshold);
99
100cpl_error_code gravi_vis_flag_nan (cpl_table * oi_table);
101
102cpl_error_code gravi_vis_average_amp (cpl_table *oi_table, const char *name, const char *err, int nbase);
103cpl_error_code gravi_vis_average_phi (cpl_table *oi_table, const char *name, const char *err, int nbase);
104cpl_error_code gravi_vis_average_value (cpl_table *oi_table, const char *name, const char *err, int nbase);
105cpl_error_code gravi_vis_resamp_amp (cpl_table * oi_table, const char * name, const char * err,
106 cpl_size nsamp, cpl_size nwave_new);
107cpl_error_code gravi_vis_resamp_phi (cpl_table * oi_table, const char * name, const char * err,
108 cpl_size nsamp, cpl_size nwave_new);
109cpl_error_code gravi_vis_smooth_amp (cpl_table * oi_table, const char * name, const char * err,
110 cpl_size nsamp);
111cpl_error_code gravi_vis_smooth_phi (cpl_table * oi_table, const char * name, const char * err,
112 cpl_size nsamp);
113
114cpl_error_code gravi_vis_fit_amp (cpl_table * oi_table, const char * name,
115 const char * err, cpl_size maxdeg);
116
117cpl_error_code gravi_vis_compute_column_mean (cpl_table * out_table,
118 cpl_table * in_table,
119 const char * name, int ntel);
120
121cpl_error_code gravi_vis_flag_median (cpl_table * oi_table, const char * data, const char *flag, double value);
122
123cpl_error_code gravi_average_self_visphi(cpl_table * oi_vis_avg,
124 cpl_table * oi_vis,
125 cpl_array * wavenumber,
126 const char * phase_ref, int* cmin, int* cmax, int nrange);
127
128double gdAbacusErrPhi(double x);
129
130/*-----------------------------------------------------------------------------
131 Function code
132 -----------------------------------------------------------------------------*/
133
134/*----------------------------------------------------------------------------*/
138/*----------------------------------------------------------------------------*/
139
140double gravi_randn (void)
141{
142 int nsamp = 50;
143 double samp[] = {0.97446388, 0.78404357, 2.24226141, 1.85507201, 1.10792943,
144 1.34028771, -0.15399594, 0.07316682, 1.60898976, 0.33111245,
145 0.76767625, -2.1252529 , 0.3898138 , 2.1218198 , 0.51703696,
146 0.38451722, 1.07581416, -0.61435275, 1.91926679, 1.10020069,
147 1.82407999, 1.07367663, 0.46105875, 0.45497282, 1.65549611,
148 1.21647974, -0.32725523, -0.36477508, 0.43947414, 1.0242778 ,
149 2.05617949, 1.06163165, 1.24564147, 2.36249995, 0.20676319,
150 1.30886256, 0.7122533 , 2.28503709, 0.7134141 , -0.19104819,
151 2.9925884 , 0.95761567, 2.11770457, 0.34763896, 0.30040327,
152 2.3535165 , 1.65839907, 1.89819461, 1.67480833, 1.11174145};
153
154 /* FIXME: build a better normal random generator !! */
155 return samp[rand()%nsamp];
156}
157
158
159/*-----------------------------------------------------------------------------*/
160
161cpl_error_code gravi_array_online_variance(cpl_array * data, cpl_array * mean, cpl_array * variance, int n)
162{
163 cpl_ensure_code (data, CPL_ERROR_NULL_INPUT);
164 cpl_ensure_code (mean, CPL_ERROR_NULL_INPUT);
165 cpl_ensure_code (variance, CPL_ERROR_NULL_INPUT);
166 cpl_ensure_code (n>=0, CPL_ERROR_ILLEGAL_INPUT);
167
168 double delta = 0.0;
169 double rdata = 0.0;
170 double rmean = 0.0;
171 double n1 = 1. / ( (double)n + 1.0 );
172 double n2 = (double)n / ( (double)n + 1.0 );
173
174 cpl_size size = cpl_array_get_size (data);
175
176 /* delta = (x - mean)/(n+1)
177 mean = mean + delta
178 M2 = M2*n/(n+1) + delta*(x - mean) */
179
180 cpl_size w;
181 int nv = 0.0;
182 for (w = 0; w < size; w ++) {
183 /* delta = (x - mean)/(n+1) */
184 rdata = cpl_array_get (data, w, &nv);
185 rmean = cpl_array_get (mean, w, &nv);
186 delta = ( rdata - rmean ) * n1;
187 /* mean = mean + delta */
188 rmean = rmean + delta;
189 cpl_array_set (mean, w, rmean);
190 /* M2 = M2*n/(n+1) + delta*(x - mean) */
191 cpl_array_set (variance, w,
192 cpl_array_get (variance, w, &nv) * n2 + delta * ( rdata - rmean ));
193 }
194
195 int code;
196 if ( (code=cpl_error_get_code()) ) {
197 return cpl_error_set_message(cpl_func, code, "Cannot do online variance");
198 }
199
200 return CPL_ERROR_NONE;
201}
202
203/*-----------------------------------------------------------------------------*/
219/*-----------------------------------------------------------------------------*/
220
221cpl_error_code gravi_array_online_variance_res(cpl_array ** data,
222 int n, int rephase)
223{
225 cpl_ensure_code (data, CPL_ERROR_NULL_INPUT);
226 cpl_ensure_code (n>=0, CPL_ERROR_ILLEGAL_INPUT);
227
228 cpl_size size = cpl_array_get_size (data[0]);
229 cpl_msg_debug(cpl_func,"Start function");
230
231 /* If first boot, we init the runnning mean and running variance
232 * and we store in the first array */
233 if ( n == 0 ) {
234 cpl_array_add (data[2], data[0]);
235 }
236
237 /* Recenter phase around the mean phase before computing its VARIANCE */
238 if (rephase) {
239 for (int w=0; w<size; w++ ) {
240 cpl_array_set (data[0], w,
241 carg( cexp (1*I* (cpl_array_get(data[0], w, NULL) -
242 cpl_array_get(data[2], w, NULL))) ) );
243 }
244 }
245
246 /* Run the gravi_online */
247 gravi_array_online_variance(data[0], data[1], data[3], n);
248
249 /* Free the current boot to prepare for next integration */
250 cpl_array_fill_window (data[0], 0, size, 0.0);
251
252 CPLCHECK_MSG ("Error in online variance");
253
255 return CPL_ERROR_NONE;
256}
257
258/*-----------------------------------------------------------------------------*/
272/*-----------------------------------------------------------------------------*/
273
274cpl_error_code gravi_flux_average_bootstrap(cpl_table * oi_flux_avg,
275 cpl_table * oi_flux,
276 int nboot,
277 double outlier_threshold)
278{
280 cpl_ensure_code (oi_flux_avg, CPL_ERROR_ILLEGAL_OUTPUT);
281 cpl_ensure_code (oi_flux, CPL_ERROR_NULL_INPUT);
282 cpl_ensure_code (nboot>0, CPL_ERROR_ILLEGAL_INPUT);
283
284 /* parameters */
285 int nv = 0, ntel = 4;
286 cpl_size nrow = cpl_table_get_nrow (oi_flux) / ntel;
287 cpl_size nwave = cpl_table_get_column_depth (oi_flux, "FLUX");
288
289 /* Pointer to columns, to speed-up */
290 cpl_array ** pFLUX = cpl_table_get_data_array (oi_flux, "FLUX");
291 cpl_array ** pFLUXERR = cpl_table_get_data_array (oi_flux, "FLUXERR");
292 cpl_array ** pFLAG = cpl_table_get_data_array (oi_flux, "FLAG");
293 double * pINTTIME = cpl_table_get_data_double (oi_flux, "INT_TIME");
294 double * pMJD = cpl_table_get_data_double (oi_flux, "MJD");
295 CPLCHECK_MSG ("Cannot get the data");
296
297 /* Loop on tel */
298 for (cpl_size tel = 0; tel < ntel; tel++) {
299
300 /* Tel for base and base for closure */
301 cpl_size nvalid = 0;
302
303 /* Arrays to store the final, integrated quantities
304 * 0: current boot, 1: running_mean, 2: first boot, 3: variance */
305 cpl_array **flux_res = gravi_array_new_list (4, CPL_TYPE_DOUBLE, nwave);
306 double total_exptime = 0.0, mjd_avg = 0.0;
307
308 /*
309 * (0) Optimize the number of segment
310 */
311
312 /* Get the number of non-rejected frames */
313 int * flag = cpl_malloc( sizeof(int) * nrow );
314 for ( int row=0 ; row<nrow; row++ ) {
315 flag[row] = 0; nvalid++;
316 }
317
318 /* Build an optimal number of segment and nrow_per_segment */
319 cpl_size nrow_per_seg = CPL_MAX(nvalid / CPL_MIN (nrow, 100), 1);
320 cpl_size nseg = nvalid / nrow_per_seg;
321
322 /* Ensure there are at least 5 samples to bootstrap on,
323 * if no add montecarlo samples */
324 cpl_size nsamp = 5, nmontecarlo = CPL_MAX (nsamp - nseg, 0);
325
326 cpl_msg_info ("Stat", "%6lld valid frames over %6lld (%5.1f%%), make %4lld seg. of %5lld (miss %lld), add %lld MonteCarlo",
327 nvalid, nrow, (double)nvalid/(double)nrow*100.0,
328 nseg, nrow_per_seg, nvalid - nseg*nrow_per_seg, nmontecarlo);
329
330 /* Case we have at least one valid frame */
331 if ( nvalid > 0 ) {
332
333 /*
334 * (1) Pre-integration over segment, to bootstrap on less statistic
335 */
336
337 cpl_array **flux = gravi_array_new_list (nseg + nmontecarlo, CPL_TYPE_DOUBLE, nwave);
338
339 /* Loop on segment */
340 cpl_size row = -1;
341 for ( int seg = 0 ; seg < nseg + nmontecarlo; seg ++ ) {
342 cpl_msg_debug(cpl_func,"pre integration of seg %d start with row %lld", seg, row);
343
344 /* Find nrow_per_seg valid frame to integrate in this segment */
345 cpl_size r = 0;
346 while ( r < nrow_per_seg ) {
347 row = (row + 1) % nrow;
348 if ( flag[row] ) {continue;} else {r++;}
349
350 /* Get indices */
351 cpl_size rtel = row * ntel + tel;
352
353 /* Compute the total integration time.
354 * Do not integrate for the MonteCarlo samples */
355 if (seg < nseg) {
356 total_exptime += pINTTIME[rtel];
357 mjd_avg += pMJD[rtel] * pINTTIME[rtel];
358 }
359
360 /* fast-no-CPL integration: get pointers on data */
361 double * tflux = cpl_array_get_data_double (flux[seg]);
362
363 /* Loop on wave */
364 for ( int w=0; w<nwave; w++ ) {
365 double FLUX = cpl_array_get (pFLUX[rtel], w, NULL);
366 double FLUXERR = cpl_array_get (pFLUXERR[rtel], w, NULL);
367 int outlier_flag = cpl_array_get (pFLAG[rtel], w, NULL);
368 CPLCHECK_MSG ("Cannot get data");
369
370 /* Reject outlier */
371 if (outlier_flag) {
372 FLUX = 0.0;
373 }
374 /* Add noise if this is a Monte Carlo sample. */
375 if ( seg > nseg-1 ) {
376 FLUX += 2 * FLUXERR * gravi_randn();
377 }
378
379 /* flux = < FLUX > over the frames in [e] */
380 tflux[w] += FLUX;
381
382 } /* End loop on wave */
383 } /* End loop on rows in this segment */
384 }/* End loop on segments */
385
386 /*
387 * (2) Compute the variance by bootstraping on the segments
388 */
389
390 /* Loop on bootstramp to compute the avg and the
391 * variance by the bootstraping methode */
392 srand(1);
393
394 for ( int boot = 0 ; boot < nboot ; boot ++ ) {
395 cpl_msg_debug(cpl_func,"Bootstrap %d over %d", boot+1, nboot);
396
397 /* Integrate nseg segment randomly selected.
398 * This loop is vectorialized in spectral direction */
399 for (int rowb = 0; rowb < nseg; rowb ++){
400
401 /* For the first bootstrap, we use all observed samples
402 * For the others, we also includes the possible montecarlo
403 * FIXME: verify the uniformity of rand for small nrows */
404 int rows;
405 if (boot == 0 ) rows = rowb;
406 else rows = rand()%(nseg+nmontecarlo);
407
408 /* Integrate the flux of selected segments */
409 cpl_array_add (flux_res[0], flux[rows]);
410 }
411 /* End loop on selected segments */
412
413 /* Compute the VARIANCE over the bootstraped samples with the 'online_variance' algorithm.
414 * See https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance */
415 gravi_array_online_variance_res (flux_res, boot, 0);
416
417 CPLCHECK_MSG("while computing the variances over the bootstrap");
418 }
419 /* End Loop on bootstrap */
420
421 /* Free list of segments and running mean */
422 FREELOOP (cpl_array_delete, flux, nseg + nmontecarlo);
423
424 /* Convert variance from bootstrap to RMS */
425 cpl_msg_debug(cpl_func,"Put the RMS over bootstrap");
426 cpl_array_power (flux_res[3], 0.5);
427 CPLCHECK_MSG("while converting variance -> rms");
428
429 /* Normalise integration */
430 mjd_avg /= total_exptime;
431
432 }
433
434 /*
435 * Step (1,2) in case there are no valid frames at all
436 */
437 if (nvalid == 0) {
438 cpl_msg_debug (cpl_func,"Not valid frames, force zero and infinit RMS");
439 cpl_array_fill_window (flux_res[3], 0, nwave, 1e10);
440 mjd_avg = cpl_table_get_column_mean (oi_flux, "MJD");
441 }
442
443 /* Renormalise by the number of outliers.
444 Also flag channels with too much outliers. */
445 cpl_array ** pflag = cpl_table_get_data_array (oi_flux_avg, "FLAG");
446 cpl_array * array = gravi_table_get_column_sum_array (oi_flux, "FLAG", tel, ntel);
447 CPLCHECK_MSG("cannot get data");
448
449 for (int wave = 0; wave < nwave; wave++) {
450 double value = cpl_array_get (array, wave, NULL) / nrow;
451 if (value < 1.0) {
452 cpl_array_set (flux_res[2], wave, cpl_array_get (flux_res[2], wave, NULL) / (1.0 - value));
453 }
454 if (value > outlier_threshold) {
455 cpl_array_set (pflag[tel], wave, 1);
456 }
457 }
458 FREE (cpl_array_delete, array);
459
460 /*
461 * (3) Save the results on the oi_flux_avg tables
462 */
463
464 cpl_table_set_array (oi_flux_avg, "FLUX", tel, flux_res[2]);
465 cpl_table_set_array (oi_flux_avg, "FLUXERR", tel, flux_res[3]);
466 CPLCHECK_MSG("filling FLUX and FLUXERR");
467
468 /* Flag the data with >100% error */
469 gravi_vis_flag_relative_threshold (oi_flux_avg, "FLUXERR", "FLUX", "FLAG", 1.0);
470 gravi_vis_flag_lower (oi_flux_avg, "FLUXERR", "FLAG", 0.0);
471 CPLCHECK_MSG("cannot flag baddata data");
472
473 /* Compute the total integration time */
474 cpl_msg_debug(cpl_func,"Total integration time = %.3f s", total_exptime);
475 cpl_table_set_double (oi_flux_avg, "INT_TIME", tel, total_exptime);
476 cpl_table_set_double (oi_flux_avg, "MJD", tel, mjd_avg);
477 cpl_table_set (oi_flux_avg, "NVALID", tel, nvalid);
478 cpl_table_set (oi_flux_avg, "NDIT", tel, nrow);
479
480 /* Set the TARGET_ID and STA_INDEX */
481 cpl_table_set_int (oi_flux_avg, "TARGET_ID", tel, cpl_table_get_int (oi_flux, "TARGET_ID", tel, &nv));
482 cpl_table_set_int (oi_flux_avg, "STA_INDEX", tel, cpl_table_get_int (oi_flux, "STA_INDEX", tel, &nv));
483
484 FREELOOP (cpl_array_delete, flux_res, 4);
485 cpl_free(flag);
486
487 } /* End loop on tel */
488
490 return CPL_ERROR_NONE;
491}
492
493/*-----------------------------------------------------------------------------*/
508/*-----------------------------------------------------------------------------*/
509
510cpl_error_code gravi_t3_average_bootstrap(cpl_table * oi_t3_avg,
511 cpl_table * oi_vis,
512 cpl_table * oi_flux,
513 int nboot,
514 int use_vFactor,
515 int use_pFactor,
516 double outlier_threshold)
517{
519 cpl_ensure_code (oi_t3_avg, CPL_ERROR_ILLEGAL_OUTPUT);
520 cpl_ensure_code (oi_vis, CPL_ERROR_NULL_INPUT);
521 cpl_ensure_code (oi_flux, CPL_ERROR_NULL_INPUT);
522 cpl_ensure_code (nboot>0, CPL_ERROR_ILLEGAL_INPUT);
523
524 /* Tel for base and base for closure
525 * Assume all the observations are made with the same array geometry.
526 * sta_index_t3[0] <-> tel1[clo[j][0]] = tel1[clo[j][2]]
527 * sta_index_t3[1] <-> tel1[clo[j][1]] = tel2[clo[j][0]]
528 * sta_index_t3[2] <-> tel2[clo[j][2]] = tel2[clo[j][1]]
529 */
530 int nv = 0, ntel = 4, nclo = 4;
531
532 cpl_size nrow = cpl_table_get_nrow (oi_vis) / GRAVI_NBASE;
533 cpl_size nwave = cpl_table_get_column_depth (oi_vis, "VISDATA");
534
535 /* Pointer to column, to speed-up */
536 cpl_array ** pVISDATA = cpl_table_get_data_array (oi_vis, "VISDATA");
537 cpl_array ** pVISERR = cpl_table_get_data_array (oi_vis, "VISERR");
538 cpl_array ** pFLUX = cpl_table_get_data_array (oi_flux, "FLUX");
539 cpl_array ** pFLAG = cpl_table_get_data_array (oi_vis, "FLAG");
540 double * pINTTIME = cpl_table_get_data_double (oi_vis, "INT_TIME");
541 double * pMJD = cpl_table_get_data_double (oi_vis, "MJD");
542 double * pUCOORD = cpl_table_get_data_double (oi_vis, "UCOORD");
543 double * pVCOORD = cpl_table_get_data_double (oi_vis, "VCOORD");
544 cpl_array ** pVFACTOR = use_vFactor?cpl_table_get_data_array (oi_vis, "V_FACTOR"):NULL;
545 /* awkwardness for scalar PFACTOR if SC, array over wave if FT */
546 double *pPFACTOR = NULL;
547 cpl_array **ppPFACTOR = NULL;
548 if (use_pFactor) {
549 if (cpl_table_get_column_depth(oi_vis, "P_FACTOR") > 0) {
550 ppPFACTOR = cpl_table_get_data_array(oi_vis, "P_FACTOR");
551 } else {
552 pPFACTOR = cpl_table_get_data_double(oi_vis, "P_FACTOR");
553 }
554 }
555
556 CPLCHECK_MSG ("Cannot get the data");
557
558 /* Loop on closure */
559 for (cpl_size closure = 0; closure < nclo; closure++) {
560
561 cpl_size nvalid = 0;
562 int base0 = GRAVI_CLO_BASE[closure][0];
563 int base1 = GRAVI_CLO_BASE[closure][1];
564 int base2 = GRAVI_CLO_BASE[closure][2];
565 int ctel0 = GRAVI_CLO_TEL[closure][0];
566 int ctel1 = GRAVI_CLO_TEL[closure][1];
567 int ctel2 = GRAVI_CLO_TEL[closure][2];
568
569 /* Arrays to store the final, integrated quantities
570 * 0: current boot, 1: running_mean, 2: first boot, 3: variance */
571 cpl_array **t3Amp_res = gravi_array_new_list (4, CPL_TYPE_DOUBLE, nwave);
572 cpl_array **t3Phi_res = gravi_array_new_list (4, CPL_TYPE_DOUBLE, nwave);
573 double total_exptime = 0.0, mjd_avg = 0.0;
574 double u1Coord = 0.0, v1Coord = 0.0, u2Coord = 0.0, v2Coord = 0.0;
575
576 /*
577 * (0) Optimize the number of segment
578 */
579
580 /* Get the number of non-rejected frames */
581 int * flag = cpl_table_get_data_int (oi_vis, "REJECTION_FLAG");
582 cpl_ensure_code (flag, CPL_ERROR_ILLEGAL_INPUT);
583 int * flagclo = cpl_malloc( sizeof(int) * nrow );
584 for ( int row=0 ; row<nrow; row++ ) {
585 flagclo[row] = flag[row * GRAVI_NBASE + base0] + flag[row * GRAVI_NBASE + base1] + flag[row * GRAVI_NBASE + base2];
586 if ( flagclo[row] == 0 ) nvalid++;
587 }
588
589 /* Build an optimal number of segment and nrow_per_segment */
590 cpl_size nrow_per_seg = CPL_MAX (nvalid / CPL_MIN (nrow, 100), 1);
591 cpl_size nseg = nvalid / nrow_per_seg;
592
593 /* Ensure there are at least 5 samples to bootstrap on,
594 * if no add montecarlo samples */
595 cpl_size nsamp = 5, nmontecarlo = CPL_MAX (nsamp - nseg, 0);
596
597 cpl_msg_info ("Stat", "%6lld valid frames over %6lld (%5.1f%%), make %4lld seg. of %5lld (miss %lld), add %lld MonteCarlo",
598 nvalid, nrow, (double)nvalid/(double)nrow*100.0,
599 nseg, nrow_per_seg, nvalid - nseg*nrow_per_seg, nmontecarlo);
600
601 /* Case we have at least one valid frame */
602 if ( nvalid > 0 ) {
603
604 /*
605 * (1) Pre-integration over segment, to bootstrap on less statistic
606 */
607
608 cpl_array **bisp = gravi_array_new_list (nseg + nmontecarlo, CPL_TYPE_DOUBLE_COMPLEX, nwave);
609 cpl_array **F012 = gravi_array_new_list (nseg + nmontecarlo, CPL_TYPE_DOUBLE, nwave);
610
611 /* Loop on segment */
612 cpl_size row = -1;
613 for ( int seg = 0 ; seg < nseg + nmontecarlo ; seg ++ ) {
614 cpl_msg_debug(cpl_func,"pre integration of seg %d start with row %lld", seg, row);
615
616 /* Find nrow_per_seg valid frame to integrate in this segment */
617 cpl_size r = 0;
618 while ( r < nrow_per_seg ) {
619 row = (row + 1) % nrow;
620 if ( flagclo[row] ) {continue;} else {r++;}
621
622 /* Get indices */
623 cpl_size rbase0 = row * GRAVI_NBASE + base0;
624 cpl_size rbase1 = row * GRAVI_NBASE + base1;
625 cpl_size rbase2 = row * GRAVI_NBASE + base2;
626
627 /* Compute the total integration time.
628 * Do not integrate for the MonteCarlo samples */
629 if (seg < nseg) {
630 total_exptime += pINTTIME[rbase0];
631 mjd_avg += pMJD[rbase0] * pINTTIME[rbase0];
632 u1Coord += pUCOORD[rbase0] * pINTTIME[rbase0];
633 v1Coord += pVCOORD[rbase0] * pINTTIME[rbase0];
634 u2Coord += pUCOORD[rbase1] * pINTTIME[rbase0];
635 v2Coord += pVCOORD[rbase1] * pINTTIME[rbase0];
636 }
637
638 /* fast-no-CPL integration: get pointers on data */
639 double complex * tbisp = cpl_array_get_data_double_complex (bisp[seg]);
640 double *tF012 = cpl_array_get_data_double (F012[seg]);
641 CPLCHECK_MSG ("Cannot get data");
642
643 double PFACTOR0 = 1.0, PFACTOR1 = 1.0, PFACTOR2 = 1.0;
644 if (use_pFactor && ppPFACTOR == NULL) { /* SC */
645 PFACTOR0 = pPFACTOR[rbase0];
646 PFACTOR1 = pPFACTOR[rbase1];
647 PFACTOR2 = pPFACTOR[rbase2];
648 if (use_pFactor == 2) {
649 PFACTOR0 *= PFACTOR0;
650 PFACTOR1 *= PFACTOR1;
651 PFACTOR2 *= PFACTOR2;
652 }
653 CPLCHECK_MSG ("Cannot get PFACTOR data");
654 }
655
656 /* Loop on wave */
657 for ( int w=0; w<nwave; w++ ) {
658 if (use_pFactor && ppPFACTOR) { /* FT */
659 pPFACTOR = cpl_array_get_data_double(ppPFACTOR[rbase0]);
660 PFACTOR0 = pPFACTOR[w];
661 pPFACTOR = cpl_array_get_data_double(ppPFACTOR[rbase1]);
662 PFACTOR1 = pPFACTOR[w];
663 pPFACTOR = cpl_array_get_data_double(ppPFACTOR[rbase2]);
664 PFACTOR2 = pPFACTOR[w];
665 if (use_pFactor == 2) {
666 PFACTOR0 *= PFACTOR0;
667 PFACTOR1 *= PFACTOR1;
668 PFACTOR2 *= PFACTOR2;
669 }
670 CPLCHECK_MSG ("Cannot get PFACTOR data");
671 }
672
673 double complex Vis0 = cpl_array_get_complex (pVISDATA[rbase0], w, NULL);
674 double complex Vis1 = cpl_array_get_complex (pVISDATA[rbase1], w, NULL);
675 double complex Vis2 = cpl_array_get_complex (pVISDATA[rbase2], w, NULL);
676 double complex VisErr0 = cpl_array_get_complex (pVISERR[rbase0], w, NULL);
677 double complex VisErr1 = cpl_array_get_complex (pVISERR[rbase1], w, NULL);
678 double complex VisErr2 = cpl_array_get_complex (pVISERR[rbase2], w, NULL);
679 double F0 = cpl_array_get (pFLUX[row * ntel + ctel0], w, NULL);
680 double F1 = cpl_array_get (pFLUX[row * ntel + ctel1], w, NULL);
681 double F2 = cpl_array_get (pFLUX[row * ntel + ctel2], w, NULL);
682 double VFACTOR0 = (use_vFactor?cpl_array_get (pVFACTOR[rbase0], w, NULL):1.0);
683 double VFACTOR1 = (use_vFactor?cpl_array_get (pVFACTOR[rbase1], w, NULL):1.0);
684 double VFACTOR2 = (use_vFactor?cpl_array_get (pVFACTOR[rbase2], w, NULL):1.0);
685 int outlier_flag0 = cpl_array_get (pFLAG[rbase0], w, NULL);
686 int outlier_flag1 = cpl_array_get (pFLAG[rbase1], w, NULL);
687 int outlier_flag2 = cpl_array_get (pFLAG[rbase2], w, NULL);
688
689 /* Reject outlier */
690 if (outlier_flag0 || outlier_flag1 || outlier_flag2) {
691 Vis0 = 0.0+0.0*I;
692 Vis1 = 0.0+0.0*I;
693 Vis2 = 0.0+0.0*I;
694 VisErr0 = 0.0+0.0*I;
695 VisErr1 = 0.0+0.0*I;
696 VisErr2 = 0.0+0.0*I;
697 F0 = 0.0;
698 F1 = 0.0;
699 F2 = 0.0;
700 }
701
702 /* Add noise if this is a Monte Carlo sample.
703 * APPROX: Noise is only added to the coherent fluxes */
704 if ( seg > nseg-1 ) {
705 Vis0 += 1.*I * cimag(VisErr0) * gravi_randn();
706 Vis0 += 1. * creal(VisErr0) * gravi_randn();
707 Vis1 += 1.*I * cimag(VisErr1) * gravi_randn();
708 Vis1 += 1. * creal(VisErr1) * gravi_randn();
709 Vis2 += 1.*I * cimag(VisErr2) * gravi_randn();
710 Vis2 += 1. * creal(VisErr2) * gravi_randn();
711 }
712
713 /* bisp = < v1*v2*conj(v3) > over the frames in [e^3] */
714 tbisp[w] += Vis0 * Vis1 * conj (Vis2);
715
716 /* F012 = < F0*F1*F2 > over the frames in [e^3]
717 * corrected from expected visibility losses */
718 tF012[w] += F0 * F1 * F2 *
719 sqrt (CPL_MAX (VFACTOR0 * VFACTOR1 * VFACTOR2 *
720 PFACTOR0 * PFACTOR1 * PFACTOR2, 0.0));
721
722 } /* End loop on wave */
723 } /* End loop on rows in this segment */
724 }/* End loop on segments */
725
726 /*
727 * (2) Compute the variance by bootstraping on the segments
728 */
729
730 /* Loop on bootstramp to compute the avg and the
731 * variance by the bootstraping methode */
732 srand(1);
733
734 for ( int boot = 0 ; boot < nboot ; boot ++ ) {
735 cpl_msg_debug(cpl_func,"Bootstrap %d over %d", boot+1, nboot);
736
737 /* Init the integration of nseg segment randomly selected */
738 cpl_array * bisp_boot = gravi_array_init_double_complex (nwave, 0.0 + I*0.0);
739 cpl_array * f012_boot = gravi_array_init_double (nwave, 0.0);
740
741 /* Integrate nseg segment randomly selected.
742 * This loop is vectorialized in spectral direction */
743 for (int rowb = 0; rowb < nseg; rowb ++){
744
745 /* For the first bootstrap, we use all observed samples
746 * For the others, we also includes the possible montecarlo
747 * FIXME: verify the uniformity of rand for small nrows */
748 int rows;
749 if (boot == 0 ) rows = rowb;
750 else rows = rand()%(nseg+nmontecarlo);
751
752 /* Integrate the bispectre and flux of selected segments */
753 cpl_array_add (bisp_boot, bisp[rows]);
754 cpl_array_add (f012_boot, F012[rows]);
755 }
756 /* End loop on selected segments */
757
758 /* Make sure the geometric flux is not null */
759 gravi_array_threshold_min (f012_boot, 1e-15);
760
761 /* Compute the argument and the module of the bispectrum */
762 FREE (cpl_array_delete, t3Amp_res[0]);
763 t3Amp_res[0] = cpl_array_duplicate(bisp_boot);
764 cpl_array_abs (t3Amp_res[0]);
765 cpl_array_divide (t3Amp_res[0], f012_boot);
766
767 FREE (cpl_array_delete, t3Phi_res[0]);
768 t3Phi_res[0] = cpl_array_duplicate(bisp_boot);
769 cpl_array_arg (t3Phi_res[0]);
770
771 /* Compute the VARIANCE over the bootstraped samples with the 'online_variance' algorithm.
772 * See https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance */
773 gravi_array_online_variance_res (t3Amp_res, boot, 0);
774 gravi_array_online_variance_res (t3Phi_res, boot, 1);
775
776 FREE (cpl_array_delete, bisp_boot);
777 FREE (cpl_array_delete, f012_boot);
778 CPLCHECK_MSG("while computing the variances over the bootstrap");
779 }
780 /* End Loop on bootstrap */
781
782 /* Free list of segments and running mean */
783 FREELOOP (cpl_array_delete, bisp, nseg + nmontecarlo);
784 FREELOOP (cpl_array_delete, F012, nseg + nmontecarlo);
785
786 /* Convert variance from bootstrap to RMS */
787 cpl_msg_debug(cpl_func,"Put the RMS over bootstrap");
788 cpl_array_power (t3Phi_res[3], 0.5);
789 cpl_array_power (t3Amp_res[3], 0.5);
790 CPLCHECK_MSG("while converting variance -> rms");
791
792 /* Normalizase integration */
793 mjd_avg /= total_exptime;
794 u1Coord /= total_exptime;
795 v1Coord /= total_exptime;
796 u2Coord /= total_exptime;
797 v2Coord /= total_exptime;
798
799 }
800
801 /*
802 * Step (1,2) in case there are no valid frames at all
803 */
804 if (nvalid == 0) {
805 cpl_msg_debug (cpl_func,"Not valid frames, force zero and infinit RMS");
806 cpl_array_fill_window (t3Amp_res[3], 0, nwave, 1e10);
807 cpl_array_fill_window (t3Phi_res[3], 0, nwave, 1e10);
808 mjd_avg = cpl_table_get_column_mean (oi_vis, "MJD");
809 }
810
811 /* Flag channels with too much outliers. */
812 cpl_array ** pflag = cpl_table_get_data_array (oi_t3_avg, "FLAG");
813 CPLCHECK_MSG("cannot get data");
814
815 cpl_array * array = cpl_array_new (nwave, CPL_TYPE_INT);
816 cpl_array_fill_window (array, 0, nwave, 0.0);
817 int * sum_flag = cpl_array_get_data_int (array);
818
819 for (int row=0; row < nrow; row++) {
820 cpl_array * arr0 = pFLAG[row * GRAVI_NBASE + base0];
821 cpl_array * arr1 = pFLAG[row * GRAVI_NBASE + base1];
822 cpl_array * arr2 = pFLAG[row * GRAVI_NBASE + base2];
823 for (int wave = 0; wave < nwave; wave++) {
824 if (cpl_array_get (arr0, wave, NULL) ||
825 cpl_array_get (arr1, wave, NULL) ||
826 cpl_array_get (arr2, wave, NULL) )
827 sum_flag[wave] ++;
828 }
829 }
830
831 for (int wave = 0; wave < nwave; wave++) {
832 double value = cpl_array_get (array, wave, NULL) / nrow;
833 if (value > outlier_threshold) {
834 cpl_array_set (pflag[closure], wave, 1);
835 }
836 }
837 FREE (cpl_array_delete, array);
838
839 /*
840 * (3) Save the results on the oi_t3_avg tables
841 */
842
843 /* Save the cloture amplitude on the oi_T3 tables */
844 cpl_table_set_array (oi_t3_avg, "T3AMP", closure, t3Amp_res[2]);
845 cpl_table_set_array (oi_t3_avg, "T3AMPERR", closure, t3Amp_res[3]);
846 CPLCHECK_MSG("filling T3AMP");
847
848 /* Save the cloture phase on the oi_T3 tables */
849 gravi_table_set_array_phase (oi_t3_avg, "T3PHI", closure, t3Phi_res[2]);
850 gravi_table_set_array_phase (oi_t3_avg, "T3PHIERR", closure, t3Phi_res[3]);
851 CPLCHECK_MSG("filling T3PHI");
852
853 /* Flag the data with >100% error or >60deg error or negative errors */
854 gravi_vis_flag_threshold (oi_t3_avg, "T3PHIERR", "FLAG", 60.0);
855 gravi_vis_flag_threshold (oi_t3_avg, "T3AMPERR", "FLAG", 1.0);
856 gravi_vis_flag_lower (oi_t3_avg, "T3AMPERR", "FLAG", 0.0);
857 gravi_vis_flag_median (oi_t3_avg, "T3PHIERR", "FLAG", 5.0);
858 CPLCHECK_MSG("cannot flag baddata data");
859
860 /* Compute the total integration time and MJD */
861 cpl_msg_debug(cpl_func,"Total integration time = %.3f s", total_exptime);
862 cpl_table_set_double (oi_t3_avg, "INT_TIME", closure, total_exptime);
863 cpl_table_set_double (oi_t3_avg, "MJD", closure, mjd_avg);
864 cpl_table_set_double (oi_t3_avg, "U1COORD", closure, u1Coord);
865 cpl_table_set_double (oi_t3_avg, "V1COORD", closure, v1Coord);
866 cpl_table_set_double (oi_t3_avg, "U2COORD", closure, u2Coord);
867 cpl_table_set_double (oi_t3_avg, "V2COORD", closure, v2Coord);
868 cpl_table_set (oi_t3_avg, "NVALID", closure, nvalid);
869 cpl_table_set (oi_t3_avg, "NDIT", closure, nrow);
870
871 /* Set the TARGET_ID */
872 cpl_table_set_int (oi_t3_avg, "TARGET_ID", closure, cpl_table_get_int (oi_vis, "TARGET_ID", base0, &nv));
873
874 /* Set STA_INDEX */
875 cpl_array * sta_index = cpl_array_new (3, CPL_TYPE_INT);
876 cpl_array_set_int (sta_index, 0, cpl_table_get_int (oi_flux,"STA_INDEX", ctel0, &nv));
877 cpl_array_set_int (sta_index, 1, cpl_table_get_int (oi_flux,"STA_INDEX", ctel1, &nv));
878 cpl_array_set_int (sta_index, 2, cpl_table_get_int (oi_flux,"STA_INDEX", ctel2, &nv));
879 cpl_table_set_array (oi_t3_avg, "STA_INDEX", closure, sta_index);
880 FREE (cpl_array_delete, sta_index);
881
882 /* Free the aggregate flags for closures */
883 FREELOOP (cpl_array_delete, t3Phi_res, 4);
884 FREELOOP (cpl_array_delete, t3Amp_res, 4);
885 FREE (cpl_free, flagclo);
886
887 } /* End loop on closure */
888
890 return CPL_ERROR_NONE;
891}
892
893/*-----------------------------------------------------------------------------*/
913/*-----------------------------------------------------------------------------*/
914
915cpl_error_code gravi_vis_average_bootstrap (cpl_table * oi_vis_avg,
916 cpl_table * oi_vis2_avg,
917 cpl_table * oi_vis,
918 int nboot,
919 const char * phase_ref,
920 int use_vFactor,
921 int use_pFactor,
922 int use_debiasing,
923 double outlier_threshold)
924{
926 cpl_ensure_code (oi_vis_avg, CPL_ERROR_ILLEGAL_OUTPUT);
927 cpl_ensure_code (oi_vis2_avg, CPL_ERROR_ILLEGAL_OUTPUT);
928 cpl_ensure_code (oi_vis, CPL_ERROR_NULL_INPUT);
929 cpl_ensure_code (nboot>0, CPL_ERROR_ILLEGAL_INPUT);
930
931 /* Parameters */
932 int nv = 0;
933 cpl_size nrow = cpl_table_get_nrow (oi_vis) / GRAVI_NBASE;
934 cpl_size nwave = cpl_table_get_column_depth (oi_vis, "VISDATA");
935
936 /* Pointer to columns, to speed-up */
937 cpl_array ** pVISDATA = cpl_table_get_data_array (oi_vis, "VISDATA");
938 cpl_array ** pVISERR = cpl_table_get_data_array (oi_vis, "VISERR");
939 cpl_array ** pFNORM = cpl_table_get_data_array (oi_vis, "F1F2");
940 cpl_array ** pFLAG = cpl_table_get_data_array (oi_vis, "FLAG");
941 double * pINTTIME = cpl_table_get_data_double (oi_vis, "INT_TIME");
942 double * pMJD = cpl_table_get_data_double (oi_vis, "MJD");
943 double * pUCOORD = cpl_table_get_data_double (oi_vis, "UCOORD");
944 double * pVCOORD = cpl_table_get_data_double (oi_vis, "VCOORD");
945 cpl_array ** pVFACTOR = use_vFactor?cpl_table_get_data_array (oi_vis, "V_FACTOR"):NULL;
946 /* awkwardness for scalar PFACTOR if SC, array over wave if FT */
947 double *pPFACTOR = NULL;
948 cpl_array **ppPFACTOR = NULL;
949 if (use_pFactor) {
950 if (cpl_table_get_column_depth(oi_vis, "P_FACTOR") > 0) {
951 ppPFACTOR = cpl_table_get_data_array(oi_vis, "P_FACTOR");
952 } else {
953 pPFACTOR = cpl_table_get_data_double(oi_vis, "P_FACTOR");
954 }
955 }
956 CPLCHECK_MSG ("Cannot get the data");
957
958 /* Get the reference phase */
959 cpl_array ** pPHASEREF = NULL;
960 if (phase_ref && strcmp (phase_ref, "NONE"))
961 pPHASEREF = cpl_table_get_data_array (oi_vis, phase_ref);
962 CPLCHECK_MSG ("Cannot get the reference phase data (column missing?)");
963
964 /* Loop on base */
965 for (cpl_size base = 0; base < GRAVI_NBASE; base ++) {
966
967 /* Tel for base */
968 cpl_size nvalid = 0;
969
970 /* Arrays to store the final, integrated quantities
971 * 0: current boot, 1: running_mean, 2: first boot, 3: variance */
972 cpl_array **visR_res = gravi_array_new_list (4, CPL_TYPE_DOUBLE, nwave);
973 cpl_array **visI_res = gravi_array_new_list (4, CPL_TYPE_DOUBLE, nwave);
974 cpl_array **vis2_res = gravi_array_new_list (4, CPL_TYPE_DOUBLE, nwave);
975 cpl_array **visAmp_res = gravi_array_new_list (4, CPL_TYPE_DOUBLE, nwave);
976 cpl_array **visPhi_res = gravi_array_new_list (4, CPL_TYPE_DOUBLE, nwave);
977 double total_exptime = 0.0, mjd_avg = 0.0;
978 double uCoord = 0.0, vCoord = 0.0;
979
980 /*
981 * (0) Optimize the number of segment
982 */
983
984 /* Get the number of non-rejected frames */
985 int * flag = cpl_table_get_data_int (oi_vis, "REJECTION_FLAG");
986 cpl_ensure_code (flag, CPL_ERROR_ILLEGAL_INPUT);
987 for ( int row=0 ; row<nrow; row++ ) if ( flag[row * GRAVI_NBASE + base] == 0 ) nvalid++;
988
989 /* Build an optimal number of segment and nrow_per_segment */
990 cpl_size nrow_per_seg = CPL_MAX (nvalid / CPL_MIN (nrow, 100), 1);
991 cpl_size nseg = nvalid / nrow_per_seg;
992
993 /* Ensure there are at least 5 samples to bootstrap on,
994 * if no add montecarlo samples */
995 cpl_size nsamp = 5, nmontecarlo = CPL_MAX (nsamp - nseg, 0);
996
997 cpl_msg_info ("Stat", "%6lld valid frames over %6lld (%5.1f%%), make %4lld seg. of %5lld (miss %lld), add %lld MonteCarlo",
998 nvalid, nrow, (double)nvalid/(double)nrow*100.0,
999 nseg, nrow_per_seg, nvalid - nseg*nrow_per_seg, nmontecarlo);
1000
1001 /* Case we have at least one valid frame */
1002 if ( nvalid > 0 ) {
1003
1004 /*
1005 * (1) Pre-integration over segment, to bootstrap on less statistic
1006 */
1007 cpl_array **visR = gravi_array_new_list (nseg + nmontecarlo, CPL_TYPE_DOUBLE, nwave);
1008 cpl_array **visI = gravi_array_new_list (nseg + nmontecarlo, CPL_TYPE_DOUBLE, nwave);
1009 cpl_array **POWER = gravi_array_new_list (nseg + nmontecarlo, CPL_TYPE_DOUBLE, nwave);
1010 cpl_array **F12 = gravi_array_new_list (nseg + nmontecarlo, CPL_TYPE_DOUBLE, nwave);
1011 cpl_array **F1F2 = gravi_array_new_list (nseg + nmontecarlo, CPL_TYPE_DOUBLE, nwave);
1012
1013 /* Loop on segment */
1014 cpl_size row = -1;
1015 for ( int seg = 0 ; seg < nseg + nmontecarlo ; seg ++ ) {
1016 cpl_msg_debug(cpl_func,"pre integration of seg %d start with row %lld", seg, row);
1017
1018 /* Find nrow_per_seg valid frame to integrate in this segment */
1019 cpl_size r = 0;
1020 while ( r < nrow_per_seg ) {
1021 row = (row + 1) % nrow;
1022 if ( flag[row * GRAVI_NBASE + base] ) {continue;} else {r++;}
1023
1024 /* Get indices */
1025 cpl_size rbase = row * GRAVI_NBASE + base;
1026
1027 /* Compute the total integration time.
1028 * Do not integrate for the MonteCarlo samples */
1029 if (seg < nseg) {
1030 total_exptime += pINTTIME[rbase];
1031 mjd_avg += pMJD[rbase] * pINTTIME[rbase];
1032 uCoord += pUCOORD[rbase] * pINTTIME[rbase];
1033 vCoord += pVCOORD[rbase] * pINTTIME[rbase];
1034 }
1035
1036 /* fast-no-CPL integration: get pointers on data */
1037 double *tR = cpl_array_get_data_double (visR[seg]);
1038 double *tI = cpl_array_get_data_double (visI[seg]);
1039 double *tP = cpl_array_get_data_double (POWER[seg]);
1040 double *tF1F2 = cpl_array_get_data_double (F1F2[seg]);
1041 double *tF12 = cpl_array_get_data_double (F12[seg]);
1042 CPLCHECK_MSG ("Cannot get data");
1043
1044 double PFACTOR = 1.0;
1045 if (use_pFactor && ppPFACTOR == NULL) { /* SC */
1046 PFACTOR = pPFACTOR[rbase];
1047 if (use_pFactor == 2) PFACTOR *= PFACTOR;
1048 CPLCHECK_MSG ("Cannot get PFACTOR data");
1049 }
1050
1051 /* Loop on wave */
1052 for (int w = 0; w < nwave; w++) {
1053 if (use_pFactor && ppPFACTOR) { /* FT */
1054 pPFACTOR = cpl_array_get_data_double(ppPFACTOR[rbase]);
1055 PFACTOR = pPFACTOR[w];
1056 if (use_pFactor == 2) PFACTOR *= PFACTOR;
1057 CPLCHECK_MSG ("Cannot get PFACTOR data");
1058 }
1059 double VFACTOR = use_vFactor?cpl_array_get (pVFACTOR[rbase], w, NULL):1.0;
1060 double PHASEREF = pPHASEREF?cpl_array_get (pPHASEREF[rbase], w, NULL):0.0;
1061 double FNORM = cpl_array_get (pFNORM[rbase], w, NULL);
1062 double complex Vis = cpl_array_get_complex (pVISDATA[rbase], w, NULL);
1063 double complex VErr = cpl_array_get_complex (pVISERR[rbase], w, NULL);
1064 double mR = creal (Vis);
1065 double mI = cimag (Vis);
1066 double eR = creal (VErr);
1067 double eI = cimag (VErr);
1068 int outlier_flag = cpl_array_get (pFLAG[rbase], w, NULL);
1069 CPLCHECK_MSG ("Cannot get data");
1070
1071 /* Reject outlier */
1072 if (outlier_flag) {
1073 mR = 0.0; mI = 0.0;
1074 eR = 0.0; eI = 0.0;
1075 FNORM = 0.0;
1076 }
1077
1078 /* Add noise if this is a Monte Carlo sample.
1079 * APPROX: Noise is only added to the coherent flux */
1080 if ( seg > nseg-1 ) {
1081 mR += 2 * eR * gravi_randn();
1082 mI += 2 * eI * gravi_randn();
1083 }
1084 if (PHASEREF) {
1085 /* Integrate <R> and <I> rephased */
1086 tR[w] += cos(PHASEREF) * mR - sin(PHASEREF) * mI;
1087 tI[w] += cos(PHASEREF) * mI + sin(PHASEREF) * mR;
1088 } else {
1089 /* Integrate directly without rephasing */
1090 tR[w] += mR;
1091 tI[w] += mI;
1092 }
1093
1094 /* Compute the flux <F1F2> and <sqrt(|F1F2|)> x sign(F1F2)
1095 * corrected by the vFactor if needed */
1096 tF1F2[w] += FNORM * VFACTOR * PFACTOR;
1097 tF12[w] += sqrt( CPL_MAX (FNORM * VFACTOR * PFACTOR, 0.0) );
1098
1099 /* Integrate < R2 + I2 - sR2 - sI2 > */
1100 if (use_debiasing) {
1101 tP[w] += mR*mR + mI*mI - eR*eR - eI*eI;
1102 } else {
1103 tP[w] += mR*mR + mI*mI;
1104 }
1105 } /* End loop on wave */
1106 } /* End loop on rows in this segment */
1107 } /* End loop on segments */
1108
1109
1110 /*
1111 * (2) Compute the variance by bootstraping on the segments
1112 */
1113
1114 /* Loop on bootstramp to compute the avg and the
1115 * variance by the bootstraping methode */
1116 srand(1);
1117
1118 for ( int boot = 0 ; boot < nboot ; boot ++ ) {
1119 cpl_msg_debug (cpl_func,"Bootstrap %d over %d", boot+1, nboot);
1120
1121 /* Init the itegration of nseg segments */
1122 cpl_array * F12_boot = gravi_array_init_double (nwave, 0.0);
1123 cpl_array * F1F2_boot = gravi_array_init_double (nwave, 0.0);
1124
1125 /* Integrate nseg segments randomly selected.
1126 * This loop is vectorialized in spectral direction */
1127 for (int rowb = 0; rowb < nseg; rowb ++) {
1128
1129 /* For the first bootstrap, we use all observed samples
1130 * For the others, we also includes the possible montecarlo
1131 * FIXME: verify the uniformity of rand for small nrows */
1132 int rows;
1133 if (boot == 0 ) rows = rowb;
1134 else rows = rand()%(nseg+nmontecarlo);
1135
1136 /* Integrate the selected segments */
1137 cpl_array_add (visR_res[0], visR[rows]);
1138 cpl_array_add (visI_res[0], visI[rows]);
1139 cpl_array_add (vis2_res[0], POWER[rows]);
1140 cpl_array_add (F12_boot, F12[rows]);
1141 cpl_array_add (F1F2_boot, F1F2[rows]);
1142 }
1143 /* End loop to integrate nseg segments randomly selected
1144 * We now have a random realisation of a high SNR dataset
1145 * to which we can apply the estimators */
1146
1147 /* Make sure the geometric flux is not null */
1148 gravi_array_threshold_min (F1F2_boot, 1e-15);
1149
1150 /* Energy estimator
1151 vis2 = POWER / F1F2 */
1152 cpl_array_divide (vis2_res[0], F1F2_boot);
1153 CPLCHECK_MSG("while computing the energie integration");
1154
1155 /* Norm of coherent integration
1156 visAmp = sqrt(visR^2 + visR^2) / F12 */
1157 FREE (cpl_array_delete, visAmp_res[0]);
1158 visAmp_res[0] = gravi_array_compute_norm2 (visR_res[0], visI_res[0]);
1159 cpl_array_power (visAmp_res[0], 0.5);
1160 cpl_array_divide (visAmp_res[0], F12_boot);
1161 CPLCHECK_MSG("while computing the norm of the coherent integration");
1162
1163 /* Phase of coherent integration
1164 visPhi = arctan( visI, visR ) */
1165 FREE (cpl_array_delete, visPhi_res[0]);
1166 visPhi_res[0] = gravi_array_wrap_complex (visR_res[0], visI_res[0]);
1167 cpl_array_arg (visPhi_res[0]);
1168
1169 /* Compute the VARIANCE over the bootstraped samples with the 'online_variance' algorithm.
1170 * See https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance */
1171 gravi_array_online_variance_res (vis2_res, boot, 0);
1172 gravi_array_online_variance_res (visAmp_res, boot, 0);
1173 gravi_array_online_variance_res (visR_res, boot, 0);
1174 gravi_array_online_variance_res (visI_res, boot, 0);
1175 gravi_array_online_variance_res (visPhi_res, boot, 1);
1176 CPLCHECK_MSG("while computing the variances over the bootstrap");
1177
1178 /* Delete these temporary integrations */
1179 FREE (cpl_array_delete, F12_boot);
1180 FREE (cpl_array_delete, F1F2_boot);
1181 CPLCHECK_MSG("while freeing during bootstrap");
1182 }
1183 /* End bootstrap */
1184
1185 /* Free list of segments */
1186 FREELOOP (cpl_array_delete, visR, nseg + nmontecarlo);
1187 FREELOOP (cpl_array_delete, visI, nseg + nmontecarlo);
1188 FREELOOP (cpl_array_delete, POWER, nseg + nmontecarlo);
1189 FREELOOP (cpl_array_delete, F12, nseg + nmontecarlo);
1190 FREELOOP (cpl_array_delete, F1F2, nseg + nmontecarlo);
1191
1192 /* Convert variance from bootstrap to RMS */
1193 cpl_msg_debug (cpl_func,"Put the RMS over bootstrap");
1194 cpl_array_power (vis2_res[3], 0.5);
1195 cpl_array_power (visAmp_res[3], 0.5);
1196 cpl_array_power (visPhi_res[3], 0.5);
1197 cpl_array_power (visR_res[3], 0.5);
1198 cpl_array_power (visI_res[3], 0.5);
1199 CPLCHECK_MSG ("while converting variance -> rms");
1200
1201 /* Normalize integration */
1202 mjd_avg /= total_exptime;
1203 uCoord /= total_exptime;
1204 vCoord /= total_exptime;
1205 }
1206
1207 /*
1208 * Step (1,2) in case there are no valid frames at all
1209 */
1210 if (nvalid == 0) {
1211 cpl_msg_debug (cpl_func,"Not valid frames, force zero and infinit RMS");
1212 cpl_array_fill_window (vis2_res[3], 0, nwave, 1e10);
1213 cpl_array_fill_window (visR_res[3], 0, nwave, 1e10);
1214 cpl_array_fill_window (visI_res[3], 0, nwave, 1e10);
1215 cpl_array_fill_window (visAmp_res[3], 0, nwave, 1e10);
1216 cpl_array_fill_window (visPhi_res[3], 0, nwave, 1e10);
1217 mjd_avg = cpl_table_get_column_mean (oi_vis, "MJD");
1218 }
1219
1220 /* Renormalise by the number of outliers.
1221 Also flag channels with too much outliers. */
1222 cpl_array ** pflag_vis = cpl_table_get_data_array (oi_vis_avg, "FLAG");
1223 cpl_array ** pflag_vis2 = cpl_table_get_data_array (oi_vis2_avg, "FLAG");
1224 cpl_array * array = gravi_table_get_column_sum_array (oi_vis, "FLAG", base, GRAVI_NBASE);
1225 CPLCHECK_MSG("cannot get data");
1226
1227 for (int wave = 0; wave < nwave; wave++) {
1228 double value = cpl_array_get (array, wave, NULL) / nrow;
1229 if (value < 1.0) {
1230 cpl_array_set (visR_res[2], wave, cpl_array_get (visR_res[2], wave, NULL) / (1.0 - value));
1231 cpl_array_set (visI_res[2], wave, cpl_array_get (visI_res[2], wave, NULL) / (1.0 - value));
1232 }
1233 if (value > outlier_threshold) {
1234 cpl_array_set (pflag_vis[base], wave, 1);
1235 cpl_array_set (pflag_vis2[base], wave, 1);
1236 }
1237 }
1238 FREE (cpl_array_delete, array);
1239
1240 /*
1241 * (3) Save the results on the oi_vis_avg tables
1242 */
1243
1244 cpl_table_set_array (oi_vis2_avg, "VIS2DATA", base, vis2_res[2]);
1245 cpl_table_set_array (oi_vis2_avg, "VIS2ERR", base, vis2_res[3]);
1246 CPLCHECK_MSG("filling VIS2");
1247
1248 gravi_table_set_array_double_complex (oi_vis_avg, "VISDATA", base, visR_res[2], visI_res[2]);
1249 gravi_table_set_array_double_complex (oi_vis_avg, "VISERR", base, visR_res[3], visI_res[3]);
1250 CPLCHECK_MSG("filling VISDATA");
1251
1252 cpl_table_set_array (oi_vis_avg, "RVIS", base, visR_res[2]);
1253 cpl_table_set_array (oi_vis_avg, "RVISERR", base, visR_res[3]);
1254 CPLCHECK_MSG("filling RVIS");
1255
1256 cpl_table_set_array (oi_vis_avg, "IVIS", base, visI_res[2]);
1257 cpl_table_set_array (oi_vis_avg, "IVISERR", base, visI_res[3]);
1258 CPLCHECK_MSG("filling IVIS");
1259
1260 cpl_table_set_array (oi_vis_avg, "VISAMP", base, visAmp_res[2]);
1261 cpl_table_set_array (oi_vis_avg, "VISAMPERR", base, visAmp_res[3]);
1262 CPLCHECK_MSG("filling VISAMP");
1263
1264 gravi_table_set_array_phase (oi_vis_avg, "VISPHI", base, visPhi_res[2]);
1265 gravi_table_set_array_phase (oi_vis_avg, "VISPHIERR", base, visPhi_res[3]);
1266 CPLCHECK_MSG("filling VISPHI");
1267
1268 /* Flag the data with >100% error or >60deg error */
1269 gravi_vis_flag_threshold (oi_vis2_avg, "VIS2ERR", "FLAG", 1.0);
1270 gravi_vis_flag_lower (oi_vis2_avg, "VIS2ERR", "FLAG", 0.0);
1271 gravi_vis_flag_median (oi_vis2_avg, "VIS2ERR", "FLAG", 5.0);
1272 gravi_vis_flag_threshold (oi_vis_avg, "VISAMPERR", "FLAG", 1.0);
1273 gravi_vis_flag_lower (oi_vis_avg, "VISAMPERR", "FLAG", 0.0);
1274 gravi_vis_flag_median (oi_vis_avg, "VISPHIERR", "FLAG", 5.0);
1275 CPLCHECK_MSG("cannot flag baddata data");
1276
1277 /* Compute the total integration time */
1278 cpl_table_set (oi_vis_avg, "INT_TIME", base, total_exptime);
1279 cpl_table_set (oi_vis2_avg, "INT_TIME", base, total_exptime);
1280 cpl_table_set (oi_vis_avg, "MJD", base, mjd_avg);
1281 cpl_table_set (oi_vis2_avg, "MJD", base, mjd_avg);
1282 cpl_table_set (oi_vis_avg, "UCOORD", base, uCoord);
1283 cpl_table_set (oi_vis_avg, "VCOORD", base, vCoord);
1284 cpl_table_set (oi_vis2_avg, "UCOORD", base, uCoord);
1285 cpl_table_set (oi_vis2_avg, "VCOORD", base, vCoord);
1286 CPLCHECK_MSG("cannot fill time");
1287
1288 /* Set some statistics */
1289 cpl_table_set (oi_vis2_avg, "NVALID", base, nvalid);
1290 cpl_table_set (oi_vis2_avg, "NDIT", base, nrow);
1291 cpl_table_set (oi_vis_avg, "NVALID", base, nvalid);
1292 cpl_table_set (oi_vis_avg, "NDIT", base, nrow);
1293 CPLCHECK_MSG("cannot fill nvalid");
1294
1295 /* Set the TARGET_ID and STA_INDEX */
1296 cpl_table_set_int (oi_vis_avg, "TARGET_ID", base, cpl_table_get_int (oi_vis, "TARGET_ID", base, &nv));
1297 cpl_table_set_int (oi_vis2_avg, "TARGET_ID", base, cpl_table_get_int (oi_vis, "TARGET_ID", base, &nv));
1298 cpl_table_set_array (oi_vis_avg, "STA_INDEX", base, cpl_table_get_array (oi_vis, "STA_INDEX", base));
1299 cpl_table_set_array (oi_vis2_avg, "STA_INDEX", base, cpl_table_get_array (oi_vis, "STA_INDEX", base));
1300
1301 /* Free variance */
1302 FREELOOP (cpl_array_delete, vis2_res, 4);
1303 FREELOOP (cpl_array_delete, visAmp_res, 4);
1304 FREELOOP (cpl_array_delete, visPhi_res, 4);
1305 FREELOOP (cpl_array_delete, visR_res, 4);
1306 FREELOOP (cpl_array_delete, visI_res, 4);
1307
1308 }
1309 /* End loop on bases */
1310
1312 return CPL_ERROR_NONE;
1313}
1314
1315double gdAbacusErrPhi(double x)
1340{
1341 const double Asymptot = CPL_MATH_PI / sqrt(3.0);
1342 double c[8] = {2.7191808010909,
1343 -17.1901043936273,
1344 45.0654103760899,
1345 -63.4441678243197,
1346 52.3098941426378,
1347 -25.8090699917488,
1348 7.84352873962491,
1349 -1.57308595820081};
1350
1351 double x2, x3, x4, x5, x6, x7, z;
1352 if (x > Asymptot) {
1353 return (1E10);
1354 }
1355 if (x > 1.74413) {
1356 return (0.691 / (Asymptot - x));
1357 }
1358 if (x < 0.1) {
1359 return (x);
1360 }
1361 x2 = x*x;
1362 x3 = x2*x;
1363 x4 = x2*x2;
1364 x5 = x3*x2;
1365 x6 = x3*x3;
1366 x7 = x6*x;
1367 z = c[0] * x7 + c[1] * x6 + c[2] * x5 + c[3] * x4 + c[4] * x3 + c[5] * x2 + c[6] * x + c[7];
1368 return pow(10, z);
1369}
1370
1371/*-----------------------------------------------------------------------------*/
1382/*-----------------------------------------------------------------------------*/
1383
1384cpl_error_code gravi_average_self_visphi(cpl_table * oi_vis_avg,
1385 cpl_table * oi_vis,
1386 cpl_array * wavenumber,
1387 const char * phase_ref, int* cmin, int* cmax, int nrange)
1388{
1390 cpl_ensure_code(oi_vis_avg, CPL_ERROR_ILLEGAL_OUTPUT);
1391 cpl_ensure_code(oi_vis, CPL_ERROR_NULL_INPUT);
1392
1393 /* Parameters */
1394 cpl_size nrow = cpl_table_get_nrow(oi_vis) / GRAVI_NBASE;
1395 cpl_size nwave = cpl_table_get_column_depth(oi_vis, "VISDATA");
1396
1397 int use_crange = (nrange > 0);
1398 if (use_crange) {
1399 for (int i = 0; i < nrange; ++i) {
1400 if (cmax[i] - cmin[i] < 1) {
1401 use_crange = 0;
1402 break;
1403 }
1404 if (cmax[i] > nwave - 1) {
1405 use_crange = 0;
1406 break;
1407 }
1408 if (cmin[i] < 0) {
1409 use_crange = 0;
1410 break;
1411 }
1412 }
1413 if (use_crange) {
1414 for (int i = 0; i < nrange; ++i) cpl_msg_info("Reference Channel", "Part %02d [%3d:%3d]", i + 1, cmin[i], cmax[i]);
1415 } else {
1416 cpl_msg_info("Warning (SELF_VISPHI)", "Invalid Ranges Found, continuing with default Method.");
1417 }
1418 }
1419
1420 /* Pointer to columns, to speed-up */
1421 cpl_array ** pVISDATA = cpl_table_get_data_array(oi_vis, "VISDATA");
1422 cpl_array ** pVISERR = cpl_table_get_data_array(oi_vis, "VISERR");
1423 CPLCHECK_MSG("Cannot get the data");
1424
1425 /* Get the reference phase unless it has already been removed*/
1426 cpl_array ** pPHASEREF = NULL;
1427 if (phase_ref && strcmp(phase_ref, "NONE"))
1428 pPHASEREF = cpl_table_get_data_array(oi_vis, phase_ref);
1429 CPLCHECK_MSG("Cannot get the reference phase data (column missing?)");
1430
1431 /* Loop on base */
1432 for (cpl_size base = 0; base < GRAVI_NBASE; base++) {
1433
1434 /* number of valid rows for base */
1435 cpl_size nvalid = 0;
1436
1437 /* Arrays to store the final, integrated quantities
1438 * 0: running_mean, 2: variance */
1439 cpl_array **visPhi_res = gravi_array_new_list(2, CPL_TYPE_DOUBLE, nwave);
1440
1441 /* Get the number of non-rejected frames */
1442 int * flag = cpl_table_get_data_int(oi_vis, "REJECTION_FLAG");
1443 cpl_ensure_code(flag, CPL_ERROR_ILLEGAL_INPUT);
1444 for (int row = 0; row < nrow; row++) if (flag[row * GRAVI_NBASE + base] == 0) nvalid++;
1445
1446 cpl_msg_info("Stat (SELF_VISPHI)", "%6lld valid frames over %6lld (%5.1f%%)",
1447 nvalid, nrow, (double) nvalid / (double) nrow * 100.0);
1448
1449 /*
1450 * return in case there are no valid frames at all
1451 */
1452 if (nvalid == 0) {
1453 cpl_msg_debug(cpl_func, "No valid frames, force zero and infinite RMS");
1454 cpl_array_fill_window(visPhi_res[1], 0, nwave, 1e10);
1455 gravi_table_set_array_phase(oi_vis_avg, "VISPHI", base, visPhi_res[0]);
1456 gravi_table_set_array_phase(oi_vis_avg, "VISPHIERR", base, visPhi_res[1]);
1457 CPLCHECK_MSG("filling VISPHI");
1458 /* Free variance */
1459 FREELOOP(cpl_array_delete, visPhi_res, 2);
1460 break;
1461 }
1462
1463 cpl_array **Vis = gravi_array_new_list(nvalid, CPL_TYPE_DOUBLE_COMPLEX, nwave);
1464 cpl_array **EVis = gravi_array_new_list(nvalid, CPL_TYPE_DOUBLE_COMPLEX, nwave);
1465
1466 cpl_array **W1 = gravi_array_new_list(nvalid, CPL_TYPE_DOUBLE_COMPLEX, nwave);
1467 cpl_array **EW1 = gravi_array_new_list(nvalid, CPL_TYPE_DOUBLE_COMPLEX, nwave);
1468 /* Loop on row */
1469
1470 for (cpl_size currentRow = 0, validRowIndex = -1; currentRow < nrow; currentRow++) {
1471 if (flag[currentRow * GRAVI_NBASE + base]) {
1472 continue;
1473 } else {
1474 /* Get indices */
1475 cpl_size rbase = currentRow * GRAVI_NBASE + base;
1476 validRowIndex++;
1477
1478 /* fast-no-CPL integration: get pointers on data */
1479 double complex *ptrC = cpl_array_get_data_double_complex(Vis[validRowIndex]);
1480 double complex *ptrEC = cpl_array_get_data_double_complex(EVis[validRowIndex]);
1481 CPLCHECK_MSG("Cannot get data");
1482
1483 /* Loop on wave */
1484 for (int w = 0; w < nwave; w++) {
1485 double PHASEREF = pPHASEREF ? cpl_array_get(pPHASEREF[rbase], w, NULL) : 0.0;
1486 double complex vis = cpl_array_get_double_complex(pVISDATA[rbase], w, NULL);
1487 double complex viserr = cpl_array_get_double_complex(pVISERR[rbase], w, NULL);
1488 CPLCHECK_MSG("Cannot get data");
1489 if (PHASEREF) {
1490 /* rephase <R> and <I> */
1491 ptrC[w] = (cos(PHASEREF) * creal(vis) - sin(PHASEREF) * cimag(vis)) +
1492 I * (cos(PHASEREF) * cimag(vis) + sin(PHASEREF) * creal(vis));
1493 } else {
1494 /* no rephasing */
1495 ptrC[w] = vis;
1496 }
1497 ptrEC[w] = viserr;
1498 } /* End loop on wave */
1499 } /* End frame not flagged */
1500 } /* End loop on rows */
1501
1502 for (int irow = 0; irow < nvalid; irow++) {
1503
1504 /* Normalize the phasor to avoid bad pixels */
1505 /*
1506 cpl_array * norm = cpl_array_duplicate(Vis[irow]);
1507 cpl_array_abs(norm);
1508 cpl_array_divide(Vis[irow], norm);
1509 */
1510
1511 /* Compute and remove the mean group delay in [m] */
1512 double mean_delay = 0.0;
1513 gravi_array_get_group_delay_loop(&Vis[irow], NULL, wavenumber, &mean_delay, 1, 2e-3, CPL_FALSE);
1514 gravi_array_multiply_phasor(Vis[irow], -2 * I * CPL_MATH_PI * mean_delay, wavenumber);
1515
1516 /* Compute and remove the mean phase in [rad] */
1517 double mean_phase = carg(cpl_array_get_mean_complex(Vis[irow]));
1518 cpl_array_multiply_scalar_complex(Vis[irow], cexp(-I * mean_phase));
1519 }
1520
1521 cpl_array *CRef = cpl_array_new(nwave, CPL_TYPE_DOUBLE_COMPLEX);
1522 cpl_array *ECRef = cpl_array_new(nwave, CPL_TYPE_DOUBLE_COMPLEX);
1523 double complex *pCRef = cpl_array_get_data_double_complex(CRef);
1524 double complex *pECRef = cpl_array_get_data_double_complex(ECRef);
1525
1526 /* Production of the reference channel: mean of all R and I parts
1527 * of all channels except the one considered ( eq 2.3) */
1528 for (int irow = 0; irow < nvalid; irow++) {
1529 /*reset sum to 0 */
1530 double complex totalVis = 0.0 + I * 0.0;
1531 double complex totalEVis = 0.0 + I * 0.0;
1532 /* fast-no-CPL integration: get pointers on data */
1533 double complex *pVis = cpl_array_get_data_double_complex(Vis[irow]);
1534 double complex *pEVis = cpl_array_get_data_double_complex(EVis[irow]);
1535
1536 double complex *pW1 = cpl_array_get_data_double_complex(W1[irow]);
1537 double complex *pEW1 = cpl_array_get_data_double_complex(EW1[irow]);
1538
1539 CPLCHECK_MSG("Cannot get data");
1540 if (use_crange) {
1541 /* sum all Vis for this row */
1542 int nchans = 0;
1543 for (int i = 0; i < nrange; ++i) {
1544 for (int w = cmin[i]; w < cmax[i]; ++w) {
1545 totalVis += pVis[w];
1546 totalEVis += pEVis[w];
1547 nchans++;
1548 }
1549 }
1550 for (int w = 0; w < nwave; w++) {
1551 cpl_array_set_double_complex(CRef, w, totalVis / nchans);
1552 cpl_array_set_double_complex(ECRef, w, totalEVis / nchans);
1553 }
1554 } else {
1555 /* sum all Vis for this row */
1556 for (int w = 0; w < nwave; w++) {
1557 totalVis += pVis[w];
1558 totalEVis += pEVis[w];
1559 }
1560 /* then construct Cref by substracting current R and I
1561 * at that Wlen and make the arithmetic mean. The code permits
1562 * to avoid not only the channel itself removed but the 2*radius
1563 * around (not activated). */
1564 int iw = 0;
1565 int radius = 0;
1566 int divider = nwave - (2 * radius) - 1;
1567 for (; iw < radius; iw++) {
1568 cpl_array_set_double_complex(CRef, iw, totalVis / nwave);
1569 cpl_array_set_double_complex(ECRef, iw, totalEVis / nwave);
1570 }
1571 for (; iw < nwave - radius; iw++) {
1572 double complex tmp = 0.0 + I * 0.0;
1573 double complex Etmp = 0.0 + I * 0.0;
1574 for (int j = iw; j < iw + 2 * radius + 1; ++j) tmp += pVis[iw];
1575 cpl_array_set_double_complex(CRef, iw, (totalVis - tmp) / divider);
1576 for (int j = iw; j < iw + 2 * radius + 1; ++j) Etmp += pEVis[iw];
1577 cpl_array_set_double_complex(ECRef, iw, (totalEVis - Etmp) / divider);
1578 }
1579 for (; iw < radius; iw++) {
1580 cpl_array_set_double_complex(CRef, iw, totalVis / nwave);
1581 cpl_array_set_double_complex(ECRef, iw, totalEVis / nwave);
1582 }
1583 }
1584 /* Now the interspectrum is C*~C_Ref. Store in w1. */
1585 for (int w = 0; w < nwave; w++) {
1586 pW1[w] = pVis[w] * conj(pCRef[w]);
1587
1588 /* Please have a look to the F. Millour thesis
1589 (http://tel.archives-ouvertes.fr/tel-00134268),
1590 pp.91-92 (eq. 4.55 to 4.58) */
1591 pEW1[w] = (creal(pEVis[w]) * gravi_pow2(creal(pCRef[w])) +
1592 creal(pECRef[w]) * gravi_pow2(creal(pVis[w])) +
1593 cimag(pVis[w]) * gravi_pow2(cimag(pCRef[w])) +
1594 cimag(pECRef[w]) + gravi_pow2(cimag(pVis[w]))) +
1595
1596 I * (
1597 cimag(pVis[w]) * gravi_pow2(creal(pCRef[w])) +
1598 cimag(pECRef[w]) * gravi_pow2(creal(pVis[w])) +
1599 creal(pVis[w]) * gravi_pow2(cimag(pCRef[w])) +
1600 creal(pECRef[w]) + gravi_pow2(cimag(pVis[w]))
1601 );
1602 }
1603 }
1604
1605 FREE(cpl_array_delete, CRef);
1606 FREE(cpl_array_delete, ECRef);
1607 FREELOOP(cpl_array_delete, Vis, nvalid);
1608 FREELOOP(cpl_array_delete, EVis, nvalid);
1609
1610 double *pPhi = cpl_array_get_data_double(visPhi_res[0]);
1611 double *pPhiErr = cpl_array_get_data_double(visPhi_res[1]);
1612
1613 /* Compute mean VisPhi as average of selected frames. */
1614 for (int w = 0; w < nwave; w++) {
1615 cpl_array *cpxVisVect = cpl_array_new(nvalid, CPL_TYPE_DOUBLE_COMPLEX);
1616
1617 /* The W1 vector */
1618 for (int irow = 0; irow < nvalid; irow++) {
1619 const double complex *pW1 = cpl_array_get_data_double_complex_const(W1[irow]);
1620 cpl_array_set_double_complex(cpxVisVect, irow, pW1[w]);
1621 }
1622 /* The Phase Herself */
1623 /* average re and im */
1624 double complex w1Avg;
1625 w1Avg = cpl_array_get_mean_complex(cpxVisVect);
1626
1627 /* store */
1628 pPhi[w] = atan2(cimag(w1Avg), creal(w1Avg));
1629 /* WE USE THE STATISTICAL ERROR FOR BINNING */
1630 w1Avg = conj(w1Avg);
1631 cpl_array *Vect = cpl_array_new(nvalid, CPL_TYPE_DOUBLE);
1632 for (int irow = 0; irow < nvalid; irow++) {
1633 const double complex *tW1 = cpl_array_get_data_double_complex_const(W1[irow]);
1634 /* add w1*conj(w1Avg) to vector*/
1635 cpl_array_set_double(Vect, irow, atan2(cimag(tW1[w] * w1Avg), creal(tW1[w] * w1Avg)));
1636 }
1637 double x = cpl_array_get_stdev(Vect);
1638 /* Err on Phi must be corrected with an abacus*/
1639 pPhiErr[w] = gdAbacusErrPhi(x / sqrt(nvalid));
1640 /* START EKW 21/11/2018 */
1641 FREE(cpl_array_delete, cpxVisVect);
1642 FREE(cpl_array_delete, Vect);
1643 /* END EKW 21/11/2018 */
1644 }
1645
1646 gravi_table_set_array_phase(oi_vis_avg, "VISPHI", base, visPhi_res[0]);
1647 gravi_table_set_array_phase(oi_vis_avg, "VISPHIERR", base, visPhi_res[1]);
1648 CPLCHECK_MSG("filling VISPHI");
1649 /* Free variance */
1650 FREELOOP(cpl_array_delete, visPhi_res, 2);
1651 /* START EKW 21/11/2018 */
1652 FREELOOP(cpl_array_delete, EW1 , nvalid);
1653 FREELOOP(cpl_array_delete, W1 , nvalid);
1654 /* END EKW 21/11/2018 */
1655
1656 }
1657
1658 /* End loop on bases */
1659
1661 return CPL_ERROR_NONE;
1662}
1663
1664/*----------------------------------------------------------------------------*/
1673/*----------------------------------------------------------------------------*/
1674
1676 const cpl_parameterlist * parlist,
1677 cpl_size * current_frame)
1678{
1680 cpl_ensure (p2vmred_data, CPL_ERROR_NULL_INPUT, NULL);
1681 cpl_ensure (parlist, CPL_ERROR_NULL_INPUT, NULL);
1682
1683 int nv, ntel = 4;
1684
1685 /*
1686 * Compute the limit of integration
1687 */
1688
1689 /* Get the current position and the maximum nb to integrate */
1690 cpl_size max_frame = gravi_param_get_int (parlist, "gravity.vis.max-frame");
1691 cpl_msg_info (cpl_func,"Average %lli frames starting from %lli",
1692 max_frame, *current_frame);
1693
1694
1695
1696 /* Get the SC DIT */
1697 cpl_propertylist * p2vmred_header = gravi_data_get_header (p2vmred_data);
1698 double dit_sc = gravi_pfits_get_dit_sc (p2vmred_header) * 1e6;
1699
1700 /* Get the vis_SC table for first polarisation */
1701 int npol_sc = gravi_pfits_get_pola_num (p2vmred_header, GRAVI_SC);
1702 cpl_table * vis_SC = gravi_data_get_oi_vis (p2vmred_data, GRAVI_SC, 0, npol_sc);
1703 cpl_size nrow = cpl_table_get_nrow (vis_SC) / GRAVI_NBASE;
1704
1705 /* Get first and last frame for this integration */
1706 cpl_size sframe = *current_frame;
1707 cpl_size eframe = CPL_MIN (*current_frame + max_frame - 1, nrow-1);
1708
1709 /* Check if we reached the end of the file, or increment */
1710 if (eframe >= nrow-1) *current_frame = -1;
1711 else *current_frame += max_frame;
1712
1713 /* Compute start and end-time */
1714 double start_time, end_time;
1715 start_time = cpl_table_get (vis_SC, "TIME", sframe*GRAVI_NBASE, &nv) - dit_sc/2;
1716 end_time = cpl_table_get (vis_SC, "TIME", eframe*GRAVI_NBASE, &nv) + dit_sc/2;
1717
1718 /* Compute verbose */
1719 cpl_msg_info (cpl_func,"Integrate frames: first = %lli last = %lli", sframe, eframe);
1720 cpl_msg_info (cpl_func,"start = %f end = %f [s]", start_time*1e-6, end_time*1e-6);
1721
1722
1723 /*
1724 * Prepare the output
1725 */
1726
1727 cpl_msg_info(cpl_func, "Construction of the averaged output data");
1728
1729 gravi_data * vis_data = gravi_data_new (0);
1730 cpl_propertylist * vis_header = gravi_data_get_header (vis_data);
1731 cpl_propertylist_append (vis_header, p2vmred_header);
1732
1733 /* Copy the oi tables needed in output data.
1734 * This will duplicate all OI_WAVELENGTH tables */
1735 gravi_data_copy_ext (vis_data, p2vmred_data, GRAVI_OI_ARRAY_EXT);
1736 gravi_data_copy_ext (vis_data, p2vmred_data, GRAVI_OI_TARGET_EXT);
1737 gravi_data_copy_ext (vis_data, p2vmred_data, GRAVI_OI_WAVELENGTH_EXT);
1738
1739 CPLCHECK_NUL ("Cannot get tables for output data");
1740
1741 /*
1742 * Start with FT
1743 */
1744
1745 if (gravi_data_has_type (p2vmred_data, "_FT") <= 0 ) {
1746 cpl_msg_info (cpl_func, "P2VMRED data has no FT extensions");
1747 }
1748 else {
1749 /* Reduction parameters */
1750 int v_factor_flag_ft = 0;
1751 int p_factor_flag_ft = 0;
1752 const char *p_factor_str_ft = gravi_param_get_string (parlist, "gravity.vis.vis-correction-ft");
1753 if (!strcmp("PFACTOR", p_factor_str_ft))
1754 p_factor_flag_ft = 1;
1755 else if (!strcmp("PFACTOR_SQUARED", p_factor_str_ft))
1756 p_factor_flag_ft = 2;
1757 int debiasing_flag_ft = gravi_param_get_bool (parlist, "gravity.vis.debias-ft");
1758 int nboot_ft = gravi_param_get_int (parlist, "gravity.vis.nboot");
1759 const char * phase_ref_ft = "SELF_REF";
1760 double outlier_threshold_ft = 0.0;
1761 cpl_msg_info (cpl_func, "vFactor correction for FT is %s",v_factor_flag_ft?"ENABLE":"DISABLE");
1762 cpl_msg_info (cpl_func, "pFactor correction for FT is %s",(p_factor_flag_ft>0)?p_factor_str_ft:"DISABLE");
1763
1764 CPLCHECK_NUL("Cannot get parameters");
1765
1766 cpl_msg_info (cpl_func, "Bias subtraction of V2 for FT is %s",debiasing_flag_ft?"ENABLE":"DISABLE");
1767 cpl_msg_info (cpl_func, "Reference phase for FT is %s",phase_ref_ft);
1768
1769
1770 /*
1771 * Loop on polarisations
1772 */
1773 int npol_ft = gravi_pfits_get_pola_num (p2vmred_header, GRAVI_FT);
1774 for (int pol = 0; pol < npol_ft; pol++) {
1775 cpl_msg_info (cpl_func, "Start FT polarisation %d over %d",pol+1, npol_ft);
1776
1777 /* Get the input table of FT */
1778 cpl_table * vis_FT = gravi_data_get_oi_vis (p2vmred_data, GRAVI_FT, pol, npol_ft);
1779 cpl_table * flux_FT = gravi_data_get_oi_flux (p2vmred_data, GRAVI_FT, pol, npol_ft);
1780 int nwave_ft = cpl_table_get_column_depth (vis_FT, "VISDATA");
1781 CPLCHECK_NUL ("Cannot get data");
1782
1783 /* Create averated product */
1784 cpl_table * oi_vis2_FT = gravi_table_oi_create (nwave_ft, 1, GRAVI_OI_VIS2_EXT);
1785 gravi_table_new_column (oi_vis2_FT, "NDIT", NULL, CPL_TYPE_INT);
1786 gravi_table_new_column (oi_vis2_FT, "NVALID", NULL, CPL_TYPE_INT);
1787
1788 cpl_table * oi_vis_FT = gravi_table_oi_create (nwave_ft, 1, GRAVI_OI_VIS_EXT);
1789 gravi_table_new_column (oi_vis_FT, "NDIT", NULL, CPL_TYPE_INT);
1790 gravi_table_new_column (oi_vis_FT, "NVALID", NULL, CPL_TYPE_INT);
1791
1792 cpl_table * oi_T3_FT = gravi_table_oi_create (nwave_ft, 1, GRAVI_OI_T3_EXT);
1793 gravi_table_new_column (oi_T3_FT, "NDIT", NULL, CPL_TYPE_INT);
1794 gravi_table_new_column (oi_T3_FT, "NVALID", NULL, CPL_TYPE_INT);
1795
1796 cpl_table * oi_flux_FT = gravi_table_oi_create (nwave_ft, 1, GRAVI_OI_FLUX_EXT);
1797 gravi_table_new_column (oi_flux_FT, "NDIT", NULL, CPL_TYPE_INT);
1798 gravi_table_new_column (oi_flux_FT, "NVALID", NULL, CPL_TYPE_INT);
1799 CPLCHECK_NUL ("Cannot create product");
1800
1801 /* Keep only selected rows */
1802 vis_FT = gravi_table_extract_time_interval (vis_FT, start_time, end_time);
1803 flux_FT = gravi_table_extract_time_interval (flux_FT, start_time, end_time);
1804
1805 /*
1806 * Compute OIVIS2 and OIVIS for FT
1807 */
1808 cpl_msg_info (cpl_func, "Compute OIVIS2 and OIVIS for FT");
1809
1810 gravi_vis_average_bootstrap (oi_vis_FT, oi_vis2_FT, vis_FT,
1811 nboot_ft,
1812 phase_ref_ft,
1813 v_factor_flag_ft,
1814 p_factor_flag_ft,
1815 debiasing_flag_ft,
1816 outlier_threshold_ft);
1817 CPLCHECK_NUL("Cannot average the FT frames");
1818
1819 /*
1820 * Compute OIT3 for FT
1821 */
1822 cpl_msg_info (cpl_func, "Compute OIT3 for FT");
1823
1824 gravi_t3_average_bootstrap (oi_T3_FT, vis_FT, flux_FT,
1825 nboot_ft,
1826 v_factor_flag_ft,
1827 p_factor_flag_ft,
1828 outlier_threshold_ft);
1829 CPLCHECK_NUL("Cannot average t3 of FT");
1830
1831 /*
1832 * Compute OI_FLUX for FT
1833 */
1834 cpl_msg_info (cpl_func, "Compute OI_FLUX for FT");
1835
1836 gravi_flux_average_bootstrap (oi_flux_FT, flux_FT,
1837 nboot_ft,
1838 outlier_threshold_ft);
1839 CPLCHECK_NUL("Cannot average flux of FT");
1840
1841 /*
1842 * Add tables in the vis_data
1843 */
1844 cpl_propertylist * vis_plist = gravi_data_get_oi_vis_plist (p2vmred_data, GRAVI_FT, pol, npol_ft);
1845 cpl_propertylist * oivis_plist = cpl_propertylist_new();
1846 cpl_propertylist_copy_property (oivis_plist, vis_plist, "DATE-OBS");
1847 cpl_propertylist_copy_property (oivis_plist, vis_plist, "EXTVER");
1848 cpl_propertylist_copy_property (oivis_plist, vis_plist, "ARRNAME");
1849 cpl_propertylist_copy_property (oivis_plist, vis_plist, "INSNAME");
1850 cpl_propertylist_update_string (oivis_plist, "AMPTYP","absolute");
1851 cpl_propertylist_update_string (oivis_plist, "PHITYP","differential");
1852 cpl_propertylist_update_int (oivis_plist, "PHIORDER",1);
1853 gravi_data_add_table (vis_data, oivis_plist, GRAVI_OI_VIS_EXT, oi_vis_FT);
1854
1855 cpl_propertylist * oivis2_plist = cpl_propertylist_new();
1856 cpl_propertylist_copy_property (oivis2_plist, vis_plist, "DATE-OBS");
1857 cpl_propertylist_copy_property (oivis2_plist, vis_plist, "EXTVER");
1858 cpl_propertylist_copy_property (oivis2_plist, vis_plist, "ARRNAME");
1859 cpl_propertylist_copy_property (oivis2_plist, vis_plist, "INSNAME");
1860 gravi_data_add_table (vis_data, oivis2_plist, GRAVI_OI_VIS2_EXT, oi_vis2_FT);
1861
1862 cpl_propertylist * oit3_plist = cpl_propertylist_new();
1863 cpl_propertylist_copy_property (oit3_plist, vis_plist, "DATE-OBS");
1864 cpl_propertylist_copy_property (oit3_plist, vis_plist, "EXTVER");
1865 cpl_propertylist_copy_property (oit3_plist, vis_plist, "ARRNAME");
1866 cpl_propertylist_copy_property (oit3_plist, vis_plist, "INSNAME");
1867 gravi_data_add_table (vis_data, oit3_plist, GRAVI_OI_T3_EXT, oi_T3_FT);
1868
1869 cpl_propertylist * oiflux_plist = cpl_propertylist_new();
1870 cpl_propertylist_copy_property (oiflux_plist, vis_plist, "DATE-OBS");
1871 cpl_propertylist_copy_property (oiflux_plist, vis_plist, "EXTVER");
1872 cpl_propertylist_copy_property (oiflux_plist, vis_plist, "ARRNAME");
1873 cpl_propertylist_copy_property (oiflux_plist, vis_plist, "INSNAME");
1874 cpl_propertylist_update_string (oiflux_plist, "CALSTAT", "U");
1875 cpl_propertylist_set_comment (oiflux_plist, "CALSTAT", "Uncalibrated flux per telescope");
1876 gravi_data_add_table (vis_data, oiflux_plist, GRAVI_OI_FLUX_EXT, oi_flux_FT);
1877
1878 CPLCHECK_NUL ("Cannot add tables");
1879
1880 FREE (cpl_table_delete, vis_FT);
1881 FREE (cpl_table_delete, flux_FT);
1882
1883 } /* end loop on pol */
1884 } /* End FT */
1885
1886 /*
1887 * Then with SC
1888 */
1889
1890 if (gravi_data_has_type (p2vmred_data, "_SC") <= 0 ) {
1891 cpl_msg_info (cpl_func, "P2VMRED data has no SC extensions");
1892 }
1893 else {
1894
1895 /* Read the object separation. Actually should
1896 * be the mode maybe more than the separation */
1897 double SOBJ_X = gravi_pfits_get_sobj_x (p2vmred_header);
1898 double SOBJ_Y = gravi_pfits_get_sobj_y (p2vmred_header);
1899 double SOBJ_R = sqrt(SOBJ_X*SOBJ_X + SOBJ_Y*SOBJ_Y);
1900
1901 /* Reference phase requested by user, deal with AUTO */
1902 const char * phase_ref_sc = gravi_param_get_string (parlist, "gravity.vis.phase-ref-sc");
1903
1904 if ( !strcmp (phase_ref_sc,"AUTO") && SOBJ_R > 0.001)
1905 {
1906 phase_ref_sc = "IMAGING_REF";
1907 if (cpl_table_has_column (vis_SC, phase_ref_sc) == 0) {
1908 phase_ref_sc = "PHASE_REF";
1909 cpl_msg_warning (cpl_func, "No table 'IMAGING_REF', changing mode to phase_ref_sc='PHASE_REF'");
1910 CPLCHECK_NUL("tototo....");
1911 }
1912 }
1913 else if ( !strcmp (phase_ref_sc,"AUTO") && SOBJ_R < 0.001)
1914 phase_ref_sc = "PHASE_REF";
1915
1916 cpl_msg_info (cpl_func, "Reference phase for SC is %s",phase_ref_sc);
1917
1918 /* Output phase requested by user, deal with AUTO */
1919 const char * output_phase_sc = gravi_param_get_string (parlist, "gravity.vis.output-phase-sc");
1920
1921 if ( !strcmp (output_phase_sc,"AUTO") && SOBJ_R > 0.001)
1922 output_phase_sc = "ABSOLUTE";
1923 else if ( !strcmp (output_phase_sc,"AUTO") && SOBJ_R < 0.001)
1924 output_phase_sc = "DIFFERENTIAL";
1925
1926 /*
1927 force SELF_REF if SELF_VISPHI unless NONE has been selected (for what purpose?)
1928 */
1929 if (!strcmp(output_phase_sc, "SELF_VISPHI")) {
1930 if (strcmp(phase_ref_sc, "NONE")) {
1931 phase_ref_sc = "SELF_REF"; /*we are robust to phase_ref_sc=NONE but SELF_REF is better */
1932 cpl_msg_info(cpl_func, "Reference phase for SC forced to %s due to option SELF_VISPHI", phase_ref_sc);
1933 } else cpl_msg_info(cpl_func, "Reference phase for SC is %s", phase_ref_sc);
1934 } else cpl_msg_info(cpl_func, "Reference phase for SC is %s", phase_ref_sc);
1935
1936 cpl_msg_info (cpl_func, "Output phase for SC is %s",output_phase_sc);
1937
1938 /* Other reduction parameters */
1939 int v_factor_flag_sc = strstr (gravi_param_get_string (parlist, "gravity.vis.vis-correction-sc"),"VFACTOR") ? 1 : 0;
1940 int p_factor_flag_sc = strstr (gravi_param_get_string (parlist, "gravity.vis.vis-correction-sc"),"PFACTOR") ? 1 : 0;
1941 int debiasing_flag_sc = gravi_param_get_bool (parlist, "gravity.vis.debias-sc");
1942 int nboot_sc = gravi_param_get_int (parlist, "gravity.vis.nboot");
1943 const char* rangeString = gravi_param_get_string (parlist, "gravity.vis.output-phase-channels");
1944 double outlier_threshold_sc = gravi_param_get_double (parlist, "gravity.vis.outlier-fraction-threshold");
1945 cpl_msg_info (cpl_func, "Bias subtraction of V2 for SC is %s",debiasing_flag_sc?"ENABLE":"DISABLE");
1946 cpl_msg_info (cpl_func, "Threshold for fraction of outlier is %.3f",outlier_threshold_sc);
1947 /*
1948 force VFACTOR and PFACTOR to 0 for SELF_VISPHI by precaution.
1949 */
1950 if (!strcmp(output_phase_sc, "SELF_VISPHI")) {
1951 v_factor_flag_sc= 0;
1952 p_factor_flag_sc= 0;
1953 cpl_msg_info(cpl_func, "vFactor correction for SC is %s due to option SELF_VISPHI", v_factor_flag_sc ? "ENABLE" : "DISABLE");
1954 cpl_msg_info(cpl_func, "pFactor correction for SC is %s due to option SELF_VISPHI", p_factor_flag_sc ? "ENABLE" : "DISABLE");
1955 } else {
1956 cpl_msg_info (cpl_func, "vFactor correction for SC is %s",v_factor_flag_sc?"ENABLE":"DISABLE");
1957 cpl_msg_info (cpl_func, "pFactor correction for SC is %s",p_factor_flag_sc?"ENABLE":"DISABLE");
1958 }
1959
1960 CPLCHECK_NUL("Cannot get parameters");
1961
1962 /*
1963 * Loop on polarisations
1964 */
1965 for (int pol = 0; pol < npol_sc; pol++) {
1966 cpl_msg_info (cpl_func, "Start SC polarisation %d over %d",pol+1, npol_sc);
1967
1968 /* Get the input table of SC */
1969 cpl_table * vis_SC = gravi_data_get_oi_vis (p2vmred_data, GRAVI_SC, pol, npol_sc);
1970 cpl_table * flux_SC = gravi_data_get_oi_flux (p2vmred_data, GRAVI_SC, pol, npol_sc);
1971 cpl_table * oi_wavelengthsc = gravi_data_get_oi_wave (p2vmred_data, GRAVI_SC, pol, npol_sc);
1972 CPLCHECK_NUL ("Cannot get data");
1973
1974 /* Compute the wavenumber for SC in [m^-1] */
1975 cpl_array * wavenumber_sc;
1976 int nwave_sc = cpl_table_get_column_depth (vis_SC, "VISDATA");
1977 wavenumber_sc = cpl_array_new (nwave_sc, CPL_TYPE_DOUBLE);
1978 for (cpl_size wave = 0; wave < nwave_sc; wave ++){
1979 cpl_array_set (wavenumber_sc, wave, 1./cpl_table_get (oi_wavelengthsc, "EFF_WAVE", wave, &nv));
1980 }
1981
1982 CPLCHECK_NUL ("Cannot build the wave and wavenumber");
1983
1984 /* Create averaged tables */
1985 cpl_table * oi_vis2_SC = gravi_table_oi_create (nwave_sc, 1, GRAVI_OI_VIS2_EXT);
1986 gravi_table_new_column (oi_vis2_SC, "NDIT", NULL, CPL_TYPE_INT);
1987 gravi_table_new_column (oi_vis2_SC, "NVALID", NULL, CPL_TYPE_INT);
1988
1989 cpl_table * oi_vis_SC = gravi_table_oi_create (nwave_sc, 1, GRAVI_OI_VIS_EXT);
1990 gravi_table_new_column (oi_vis_SC, "NDIT", NULL, CPL_TYPE_INT);
1991 gravi_table_new_column (oi_vis_SC, "NVALID", NULL, CPL_TYPE_INT);
1992 gravi_table_new_column (oi_vis_SC, "GDELAY", "m", CPL_TYPE_DOUBLE);
1993 gravi_table_new_column (oi_vis_SC, "PHASE", "rad", CPL_TYPE_DOUBLE);
1994
1995 cpl_table * oi_T3_SC = gravi_table_oi_create (nwave_sc, 1, GRAVI_OI_T3_EXT);
1996 gravi_table_new_column (oi_T3_SC, "NDIT", NULL, CPL_TYPE_INT);
1997 gravi_table_new_column (oi_T3_SC, "NVALID", NULL, CPL_TYPE_INT);
1998
1999 cpl_table * oi_flux_SC = gravi_table_oi_create (nwave_sc, 1, GRAVI_OI_FLUX_EXT);
2000 gravi_table_new_column (oi_flux_SC, "NDIT", NULL, CPL_TYPE_INT);
2001 gravi_table_new_column (oi_flux_SC, "NVALID", NULL, CPL_TYPE_INT);
2002 gravi_table_new_column (oi_flux_SC, "LKDT_MET_FC", "mjd", CPL_TYPE_DOUBLE);
2003
2004 CPLCHECK_NUL("Cannot create columns in averaged OIFITS...");
2005
2006 /* Keep only selected rows */
2007 vis_SC = gravi_table_extract_time_interval (vis_SC, start_time, end_time);
2008 flux_SC = gravi_table_extract_time_interval (flux_SC, start_time, end_time);
2009
2010 /*
2011 * Compute OIVIS2 and OIVIS for SC
2012 */
2013 cpl_msg_info (cpl_func, "Compute OIVIS2 and OIVIS for SC");
2014
2015 gravi_vis_average_bootstrap (oi_vis_SC, oi_vis2_SC, vis_SC,
2016 nboot_sc,
2017 phase_ref_sc,
2018 v_factor_flag_sc,
2019 p_factor_flag_sc,
2020 debiasing_flag_sc,
2021 outlier_threshold_sc);
2022 CPLCHECK_NUL("Cannot average the SC frames");
2023
2024 /* Compute other columns */
2025 gravi_vis_compute_column_mean (oi_vis_SC, vis_SC, "OPD_MET_FC", 6);
2026 gravi_vis_compute_column_mean (oi_vis_SC, vis_SC, "PHASE_REF_COEFF", 6);
2027 gravi_vis_compute_column_mean (oi_vis_SC, vis_SC, "E_U", 6);
2028 gravi_vis_compute_column_mean (oi_vis_SC, vis_SC, "E_V", 6);
2029 gravi_vis_compute_column_mean (oi_vis_SC, vis_SC, "E_W", 6);
2030 gravi_vis_compute_column_mean (oi_vis_SC, vis_SC, "E_AZ", 6);
2031 gravi_vis_compute_column_mean (oi_vis_SC, vis_SC, "E_ZD", 6);
2032 CPLCHECK_NUL("Cannot compute means.");
2033
2034 /* Re compute the astrometric phase from VISDATA to deal with absolute phase
2035 * VISDATA as well as (R,I) remains unchanged. The goal is to split
2036 * the differential phase, calibratable so far, from the absolute phase */
2037 if ( !strcmp (output_phase_sc,"DIFFERENTIAL") || !strcmp (output_phase_sc,"ABSOLUTE") ) {
2038 for (int base = 0; base < GRAVI_NBASE; base++) {
2039
2040 /* We duplicate VISDATA, to keep the value untouched in the table */
2041 cpl_array * visData_sc, * visErr_sc;
2042 visData_sc = cpl_array_cast (cpl_table_get_array (oi_vis_SC, "VISDATA", base),
2043 CPL_TYPE_DOUBLE_COMPLEX);
2044
2045 /* Normalize the phasor by error, to discard crazy points */
2046 visErr_sc = cpl_array_duplicate (visData_sc);
2047 cpl_array_abs (visErr_sc);
2048 cpl_array_divide (visData_sc, visErr_sc);
2049
2050 /* Get the flag */
2051 cpl_array * flag_sc;
2052 flag_sc = (cpl_array *)cpl_table_get_array (oi_vis_SC, "FLAG", base);
2053
2054 /* Compute and remove the mean group delay in [m] */
2055 double mean_delay = 0.0;
2056 gravi_array_get_group_delay_loop (&visData_sc, &flag_sc, wavenumber_sc, &mean_delay, 1, 2e-3, CPL_FALSE);
2057 gravi_array_multiply_phasor (visData_sc, - 2*I*CPL_MATH_PI * mean_delay, wavenumber_sc);
2058
2059 /* Save this delay [m] */
2060 cpl_table_set (oi_vis_SC, "GDELAY", base, mean_delay);
2061
2062 /* Compute and remove the mean phase in [rad] */
2063 double mean_phase = carg (cpl_array_get_mean_complex (visData_sc));
2064 cpl_array_multiply_scalar_complex (visData_sc, cexp(- I * mean_phase));
2065
2066 /* Save this phase [rad] */
2067 cpl_table_set (oi_vis_SC, "PHASE", base, mean_phase);
2068
2069 /* Set back the phase in [deg] (skip for ABSOLUTE mode) */
2070 if ( !strcmp (output_phase_sc,"DIFFERENTIAL") ) {
2071 cpl_array_arg (visData_sc);
2072 gravi_table_set_array_phase (oi_vis_SC, "VISPHI", base, visData_sc);
2073 }
2074 cpl_array_delete (visData_sc);
2075 cpl_array_delete (visErr_sc);
2076
2077 CPLCHECK_NUL("when computing the astrometric phase");
2078
2079 } /* End loop on base */
2080 }
2081 if (!strcmp(output_phase_sc, "SELF_VISPHI")) {
2082 int* cmin=NULL;
2083 int* cmax=NULL;
2084 int nrange=0;
2085 /* rather complex C way to analyse strings defining clusters of wavelengths like " [ 12345 : 12346 , 678 : 680 , 822:864]" */
2086 if (strcmp(rangeString, "UNKNOWN")) {
2087 /*find number of ranges (they are separated by ',')*/
2088 char *str, *str1 ;
2089 int l=strlen(rangeString)+1;
2090 int j=0;
2091 int i=0;
2092 str=(char*)malloc(l);
2093 strncpy(str,rangeString,l); /*for future use*/
2094 for (i = 0; i<l; ++i) if (str[i]!=' ' && str[i]!='\t') str[j++]=str[i]; //remove ALL blanks.
2095 str[j]='\0';
2096 l=strlen(str)+1;
2097 str1=(char*)malloc(l);
2098 strncpy(str1,str,l); /*for future use, as strtok destroys its arguments*/
2099
2100 char *token;
2101 token = strtok(str, "[,]");
2102 while (token) {
2103 nrange++;
2104 token = strtok(NULL, "[,]");
2105 }
2106 if (nrange > 1) {
2107 cmin=(int*) calloc(nrange,sizeof(int));
2108 cmax=(int*) calloc(nrange,sizeof(int));
2109
2110 char *str2, *subtoken;
2111 char *saveptr1, *saveptr2;
2112 for (j = 0; ; j++, str1 = NULL) {
2113 token = strtok_r(str1, "[,]" , &saveptr1);
2114 if (token == NULL)
2115 break;
2116 for (str2 = token, i=0; i<2 ; str2 = NULL, ++i) {
2117 subtoken = strtok_r(str2, ":", &saveptr2);
2118 if (subtoken == NULL)
2119 break;
2120 /* int ret=sscanf(subtoken,"%d", (i==0)?&(cmin[j]):&(cmax[j])); */
2121 }
2122 }
2123 }
2124 }
2125
2126 gravi_average_self_visphi(oi_vis_SC, vis_SC, wavenumber_sc, phase_ref_sc, cmin, cmax, nrange);
2127 }
2128 /*
2129 * Compute OIT3 for SC
2130 */
2131 cpl_msg_info (cpl_func, "Compute OIT3 for SC");
2132
2133 gravi_t3_average_bootstrap (oi_T3_SC, vis_SC, flux_SC,
2134 nboot_sc,
2135 v_factor_flag_sc,
2136 p_factor_flag_sc,
2137 outlier_threshold_sc);
2138 CPLCHECK_NUL("Cannot average t3 of SC");
2139
2140 /*
2141 * Compute OI_FLUX for SC
2142 */
2143 cpl_msg_info (cpl_func, "Compute OI_FLUX for SC");
2144
2145 gravi_flux_average_bootstrap (oi_flux_SC, flux_SC,
2146 nboot_sc, outlier_threshold_sc);
2147 CPLCHECK_NUL("Cannot average flux of SC");
2148
2149 /* Compute other columns */
2150 gravi_vis_compute_column_mean (oi_flux_SC, flux_SC, "OPD_MET_FC", 4);
2151 gravi_vis_compute_column_mean (oi_flux_SC, flux_SC, "FT_POS", 4);
2152 gravi_vis_compute_column_mean (oi_flux_SC, flux_SC, "SC_POS", 4);
2153 gravi_vis_compute_column_mean (oi_flux_SC, flux_SC, "OPL_AIR", 4);
2154 CPLCHECK_NUL ("Cannot compute mean columns");
2155
2156 /* Save the FC metrology lock date */
2157 for (int tel = 0; tel < ntel; tel++){
2158 double lockdate = gravi_pfits_get_metfc_lockmjd (p2vmred_header, tel);
2159 cpl_table_set (oi_flux_SC, "LKDT_MET_FC", tel, lockdate);
2160 }
2161
2162 /*
2163 * Add tables in the vis_data
2164 */
2165 cpl_propertylist * vis_plist = gravi_data_get_oi_vis_plist (p2vmred_data, GRAVI_SC, pol, npol_sc);
2166 cpl_propertylist * oivis_plist = cpl_propertylist_new();
2167 cpl_propertylist_copy_property (oivis_plist, vis_plist, "DATE-OBS");
2168 cpl_propertylist_copy_property (oivis_plist, vis_plist, "EXTVER");
2169 cpl_propertylist_copy_property (oivis_plist, vis_plist, "ARRNAME");
2170 cpl_propertylist_copy_property (oivis_plist, vis_plist, "INSNAME");
2171 cpl_propertylist_update_string (oivis_plist, "AMPTYP","absolute");
2172 if ( !strcmp (output_phase_sc,"DIFFERENTIAL") )
2173 cpl_propertylist_update_string (oivis_plist, "PHITYP","differential");
2174 if ( !strcmp (output_phase_sc,"ABSOLUTE") )
2175 cpl_propertylist_update_string (oivis_plist, "PHITYP","absolute");
2176 cpl_propertylist_update_int (oivis_plist, "PHIORDER",1);
2177 gravi_data_add_table (vis_data, oivis_plist, GRAVI_OI_VIS_EXT, oi_vis_SC);
2178
2179 cpl_propertylist * oivis2_plist = cpl_propertylist_new();
2180 cpl_propertylist_copy_property (oivis2_plist, vis_plist, "DATE-OBS");
2181 cpl_propertylist_copy_property (oivis2_plist, vis_plist, "EXTVER");
2182 cpl_propertylist_copy_property (oivis2_plist, vis_plist, "ARRNAME");
2183 cpl_propertylist_copy_property (oivis2_plist, vis_plist, "INSNAME");
2184 gravi_data_add_table (vis_data, oivis2_plist, GRAVI_OI_VIS2_EXT, oi_vis2_SC);
2185
2186 cpl_propertylist * oit3_plist = cpl_propertylist_new();
2187 cpl_propertylist_copy_property (oit3_plist, vis_plist, "DATE-OBS");
2188 cpl_propertylist_copy_property (oit3_plist, vis_plist, "EXTVER");
2189 cpl_propertylist_copy_property (oit3_plist, vis_plist, "ARRNAME");
2190 cpl_propertylist_copy_property (oit3_plist, vis_plist, "INSNAME");
2191 gravi_data_add_table (vis_data, oit3_plist, GRAVI_OI_T3_EXT, oi_T3_SC);
2192
2193 cpl_propertylist * oiflux_plist = cpl_propertylist_new();
2194 cpl_propertylist_copy_property (oiflux_plist, vis_plist, "DATE-OBS");
2195 cpl_propertylist_copy_property (oiflux_plist, vis_plist, "EXTVER");
2196 cpl_propertylist_copy_property (oiflux_plist, vis_plist, "ARRNAME");
2197 cpl_propertylist_copy_property (oiflux_plist, vis_plist, "INSNAME");
2198 cpl_propertylist_update_string (oiflux_plist, "CALSTAT", "U");
2199 cpl_propertylist_set_comment (oiflux_plist, "CALSTAT", "Uncalibrated flux per telescope");
2200 gravi_data_add_table (vis_data, oiflux_plist, GRAVI_OI_FLUX_EXT, oi_flux_SC);
2201
2202 CPLCHECK_NUL ("Cannot add tables");
2203
2204 /* Delete waves */
2205 FREE (cpl_array_delete, wavenumber_sc);
2206 CPLCHECK_NUL ("Cannot delete wavenumber");
2207
2208 FREE (cpl_table_delete, vis_SC);
2209 FREE (cpl_table_delete, flux_SC);
2210
2211 } /* end loop on pol */
2212 } /* End SC */
2213
2214
2215 /* Add the night-obs in the main HEADER. This is the MJD of the begining
2216 of the night, similar for all files from noon to noon (~local time) */
2217 double mjd_obs = cpl_table_get_column_mean (gravi_data_get_table (vis_data, GRAVI_OI_VIS_EXT), "MJD");
2218 cpl_propertylist_update_int (vis_header, GRAVI_NIGHT_OBS, (int)floor(mjd_obs-0.625));
2219
2221 return vis_data;
2222}
2223
2224
2225/*----------------------------------------------------------------------------*/
2235/*----------------------------------------------------------------------------*/
2236
2237cpl_error_code gravi_compute_vis_qc (gravi_data * vis_data, cpl_frameset* frameset,
2238 cpl_propertylist **frame_qcs, cpl_size nb_frame,
2239 char * input_data_type)
2240{
2242 cpl_ensure_code (vis_data, CPL_ERROR_NULL_INPUT);
2243 cpl_ensure_code (frame_qcs, CPL_ERROR_NULL_INPUT);
2244
2245 int nv, ntel=4, nclo=4;
2246 char qc_name[100];
2247
2248 /*
2249 * Prepare the output
2250 */
2251
2252 cpl_propertylist * vis_header = gravi_data_get_header (vis_data);
2253 cpl_propertylist * plist = gravi_data_get_extra_primary_header (vis_data);
2254
2255
2256 /*
2257 * Start with FT
2258 */
2259 if (gravi_data_has_type (vis_data, "_FT") <= 0 ) {
2260 cpl_msg_info (cpl_func, "VIS data has no FT extensions");
2261 }
2262 else {
2263
2264 /* Loop on polarisations */
2265 int npol_ft = gravi_pfits_get_pola_num (vis_header, GRAVI_FT);
2266 for (int pol = 0; pol < npol_ft; pol++) {
2267 cpl_msg_info (cpl_func, "Start FT polarisation %d over %d",pol+1, npol_ft);
2268
2269 /* Loop on bases to compute OIVIS2 and OIVIS for FT
2270 */
2271 cpl_msg_info (cpl_func, "Compute QC OIVIS2 and OIVIS for FT");
2272
2273 cpl_table * oi_vis2_FT = gravi_data_get_oi_vis2 (vis_data, GRAVI_FT, pol, npol_ft);
2274 cpl_table * oi_vis_FT = gravi_data_get_oi_vis (vis_data, GRAVI_FT, pol, npol_ft);
2275
2276 for (int base = 0; base < GRAVI_NBASE; base++) {
2277
2278 /* Add the QC parameters for FT */
2279
2280 sprintf (qc_name, "ESO QC VIS2_FT%s_P%d AVG", GRAVI_BASE_NAME[base], pol+1);
2281 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_vis2_FT, "VIS2DATA", base, GRAVI_NBASE));
2282 cpl_propertylist_set_comment (plist, qc_name, "mean over lbd");
2283
2284 sprintf (qc_name, "ESO QC VIS2ERR_FT%s_P%d AVG", GRAVI_BASE_NAME[base], pol+1);
2285 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_vis2_FT, "VIS2ERR", base, GRAVI_NBASE));
2286 cpl_propertylist_set_comment (plist, qc_name, "mean over lbd");
2287
2288 sprintf (qc_name, "ESO QC VISPHI_FT%s_P%d AVG", GRAVI_BASE_NAME[base], pol+1);
2289 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_vis_FT, "VISPHI", base, GRAVI_NBASE));
2290 cpl_propertylist_set_comment (plist, qc_name, "[deg] mean over lbd");
2291
2292 sprintf (qc_name, "ESO QC VISPHIERR_FT%s_P%d AVG", GRAVI_BASE_NAME[base], pol+1);
2293 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_vis_FT, "VISPHIERR", base, GRAVI_NBASE));
2294 cpl_propertylist_set_comment (plist, qc_name, "[deg] mean over lbd");
2295
2296 sprintf (qc_name, "ESO QC VISAMP_FT%s_P%d AVG", GRAVI_BASE_NAME[base], pol+1);
2297 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_vis_FT, "VISAMP", base, GRAVI_NBASE));
2298 cpl_propertylist_set_comment (plist, qc_name, "mean over lbd");
2299
2300 sprintf (qc_name, "ESO QC VISAMPERR_FT%s_P%d AVG", GRAVI_BASE_NAME[base], pol+1);
2301 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_vis_FT, "VISAMPERR", base, GRAVI_NBASE));
2302 cpl_propertylist_set_comment (plist, qc_name, "mean over lbd");
2303
2304 CPLCHECK_MSG("Cannot compute QC parameter for OI_VIS for FT");
2305 } /* End loop on base */
2306
2307 /*
2308 * Loop on triplet to compute OIT3 for FT
2309 */
2310 cpl_msg_info (cpl_func, "Compute QC OIT3 for FT");
2311
2312 cpl_table * oi_T3_FT = gravi_data_get_oi_t3 (vis_data, GRAVI_FT, pol, npol_ft);
2313
2314 for (int clo = 0; clo < nclo; clo++){
2315
2316 sprintf (qc_name, "ESO QC T3PHI_FT%s_P%d AVG", GRAVI_CLO_NAME[clo], pol+1);
2317 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_T3_FT, "T3PHI", clo, nclo));
2318 cpl_propertylist_set_comment (plist, qc_name, "[deg] mean over lbd");
2319
2320 sprintf (qc_name, "ESO QC T3PHIERR_FT%s_P%d AVG", GRAVI_CLO_NAME[clo], pol+1);
2321 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_T3_FT, "T3PHIERR", clo, nclo));
2322 cpl_propertylist_set_comment (plist, qc_name, "[deg] mean over lbd");
2323
2324 CPLCHECK_MSG("Cannot compute QC parameter for OI_T3 for FT");
2325 } /* End loop on triplets */
2326
2327 /*
2328 * Loop on beams to compute OI_FLUX for FT
2329 */
2330 cpl_msg_info (cpl_func, "Compute QC OI_FLUX for FT");
2331
2332 cpl_table * oi_flux_FT = gravi_data_get_oi_flux (vis_data, GRAVI_FT, pol, npol_ft);
2333
2334 for (int tel = 0; tel < ntel; tel++){
2335
2336 sprintf (qc_name, "ESO QC FLUX_FT%d_P%d AVG", tel+1, pol+1);
2337 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_flux_FT, "FLUX", tel, ntel));
2338 cpl_propertylist_set_comment (plist, qc_name, "[e/total_int_time] mean over lbd");
2339
2340 sprintf (qc_name, "ESO QC FLUXERR_FT%d_P%d AVG", tel+1, pol+1);
2341 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_flux_FT, "FLUXERR", tel, ntel));
2342 cpl_propertylist_set_comment (plist, qc_name, "[e/total_int_time] mean over lbd");
2343
2344 sprintf (qc_name, "ESO QC FLUXRATE_FT%d_P%d SUM", tel+1, pol+1);
2345 double flux_rate = cpl_array_get_mean (cpl_table_get_array (oi_flux_FT, "FLUX", tel)) *
2346 cpl_array_get_size (cpl_table_get_array (oi_flux_FT, "FLUX", tel)) / cpl_table_get_double (oi_flux_FT, "INT_TIME", tel, &nv);
2347 cpl_propertylist_update_double (plist, qc_name, flux_rate);
2348 cpl_propertylist_set_comment (plist, qc_name, "[e/s] sum over lbd");
2349
2350 CPLCHECK_MSG("Cannot compute QC parameter for OI_FLUX for FT");
2351 } /* End loop on beams */
2352
2353 } /* end loop on pol */
2354 } /* End FT */
2355
2356
2357
2358 /*
2359 * Then with SC
2360 */
2361 if (gravi_data_has_type (vis_data, "_SC") <= 0 ) {
2362 cpl_msg_info (cpl_func, "VIS data has no SC extensions");
2363 }
2364 else {
2365
2366 /* Loop on polarisations */
2367 int npol_sc = gravi_pfits_get_pola_num (vis_header, GRAVI_SC);
2368
2369 for (int pol = 0; pol < npol_sc; pol++) {
2370
2371 /*
2372 * Loop on bases to compute OIVIS2 and OIVIS for SC
2373 */
2374 cpl_msg_info (cpl_func, "Compute QC OIVIS2 and OIVIS for SC");
2375
2376 cpl_table * oi_vis2_SC = gravi_data_get_oi_vis2 (vis_data, GRAVI_SC, pol, npol_sc);
2377 cpl_table * oi_vis_SC = gravi_data_get_oi_vis (vis_data, GRAVI_SC, pol, npol_sc);
2378
2379 for (int base = 0; base < GRAVI_NBASE; base++) {
2380 double pfactor = 0, vfactor = 0, std_pfactor = 0, std_vfactor = 0;
2381 cpl_size total_weight = 0;
2382 for (int frame = 0; frame < nb_frame; frame++) {
2383 cpl_size weight = cpl_propertylist_get_long_long(frame_qcs[frame], "NROW");
2384 total_weight += weight;
2385 sprintf (qc_name, "ESO QC VFACTOR%s_P%d AVG", GRAVI_BASE_NAME[base], pol+1);
2386 vfactor += weight * cpl_propertylist_get_double(frame_qcs[frame], qc_name);
2387 sprintf (qc_name, "ESO QC VFACTOR%s_P%d STD", GRAVI_BASE_NAME[base], pol+1);
2388 if (cpl_propertylist_has(frame_qcs[frame], qc_name))
2389 std_vfactor += weight * cpl_propertylist_get_double(frame_qcs[frame], qc_name);
2390 sprintf (qc_name, "ESO QC PFACTOR%s_P%d AVG", GRAVI_BASE_NAME[base], pol+1);
2391 pfactor += weight * cpl_propertylist_get_double(frame_qcs[frame], qc_name);
2392 sprintf (qc_name, "ESO QC PFACTOR%s_P%d STD", GRAVI_BASE_NAME[base], pol+1);
2393 if (cpl_propertylist_has(frame_qcs[frame], qc_name))
2394 std_pfactor += weight * cpl_propertylist_get_double(frame_qcs[frame], qc_name);
2395 }
2396 vfactor /= total_weight;
2397 std_vfactor /= total_weight;
2398 pfactor /= total_weight;
2399 std_pfactor /= total_weight;
2400
2401 sprintf (qc_name, "ESO QC VFACTOR%s_P%d AVG", GRAVI_BASE_NAME[base], pol+1);
2402 cpl_propertylist_update_double(plist, qc_name, vfactor);
2403 cpl_propertylist_set_comment (plist, qc_name, "mean v-factor");
2404
2405 if (std_vfactor > 0.0) {
2406 sprintf (qc_name, "ESO QC VFACTOR%s_P%d STD", GRAVI_BASE_NAME[base], pol+1);
2407 cpl_propertylist_update_double(plist, qc_name, std_vfactor);
2408 cpl_propertylist_set_comment (plist, qc_name, "standard deviation of v-factor");
2409 }
2410
2411 sprintf (qc_name, "ESO QC PFACTOR%s_P%d AVG", GRAVI_BASE_NAME[base], pol+1);
2412 cpl_propertylist_update_double(plist, qc_name, pfactor);
2413 cpl_propertylist_set_comment (plist, qc_name, "mean p-factor");
2414
2415 if (std_pfactor > 0.0) {
2416 sprintf (qc_name, "ESO QC PFACTOR%s_P%d STD", GRAVI_BASE_NAME[base], pol+1);
2417 cpl_propertylist_update_double(plist, qc_name, std_pfactor);
2418 cpl_propertylist_set_comment (plist, qc_name, "standard deviation of p-factor");
2419 }
2420
2421 sprintf (qc_name, "ESO QC GD_SC%s_P%d AVG", GRAVI_BASE_NAME[base], pol+1);
2422 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_vis_SC, "GDELAY", base, GRAVI_NBASE));
2423 cpl_propertylist_set_comment (plist, qc_name, "[m] mean Group-Delay");
2424
2425 sprintf (qc_name, "ESO QC VIS2_SC%s_P%d AVG", GRAVI_BASE_NAME[base], pol+1);
2426 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_vis2_SC, "VIS2DATA", base, GRAVI_NBASE));
2427 cpl_propertylist_set_comment (plist, qc_name, "mean over lbd");
2428
2429 sprintf (qc_name, "ESO QC VIS2ERR_SC%s_P%d AVG", GRAVI_BASE_NAME[base], pol+1);
2430 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_vis2_SC, "VIS2ERR", base, GRAVI_NBASE));
2431 cpl_propertylist_set_comment (plist, qc_name, "mean over lbd");
2432
2433 sprintf (qc_name, "ESO QC VISPHI_SC%s_P%d AVG", GRAVI_BASE_NAME[base], pol+1);
2434 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_vis_SC, "VISPHI", base, GRAVI_NBASE));
2435 cpl_propertylist_set_comment (plist, qc_name, "[deg] mean over lbd");
2436
2437 sprintf (qc_name, "ESO QC VISPHIERR_SC%s_P%d AVG", GRAVI_BASE_NAME[base], pol+1);
2438 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_vis_SC, "VISPHIERR", base, GRAVI_NBASE));
2439 cpl_propertylist_set_comment (plist, qc_name, "[deg] mean over lbd");
2440
2441 sprintf (qc_name, "ESO QC VISAMP_SC%s_P%d AVG", GRAVI_BASE_NAME[base], pol+1);
2442 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_vis_SC, "VISAMP", base, GRAVI_NBASE));
2443 cpl_propertylist_set_comment (plist, qc_name, "mean over lbd");
2444
2445 sprintf (qc_name, "ESO QC VISAMPERR_SC%s_P%d AVG", GRAVI_BASE_NAME[base], pol+1);
2446 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_vis_SC, "VISAMPERR", base, GRAVI_NBASE));
2447 cpl_propertylist_set_comment (plist, qc_name, "mean over lbd");
2448
2449 double coeff2 = gravi_table_get_value (oi_vis_SC, "PHASE_REF_COEFF", base, 2);
2450 sprintf (qc_name, "ESO QC PHASE_REF_COEFF2 SC%s_P%d", GRAVI_BASE_NAME[base], pol+1);
2451 cpl_propertylist_update_double (plist, qc_name, coeff2);
2452 cpl_propertylist_set_comment (plist, qc_name, "[rad] 2sd order of FT phase");
2453
2454 CPLCHECK_MSG("Cannot set QC parameter for OI_VIS for SC");
2455 } /* End loop on base */
2456
2457 /*
2458 * Loop on triplet to compute OIT3 for SC
2459 */
2460 cpl_msg_info (cpl_func, "Compute QC OIT3 for SC");
2461
2462 cpl_table * oi_T3_SC = gravi_data_get_oi_t3 (vis_data, GRAVI_SC, pol, npol_sc);
2463
2464 for (int clo = 0; clo < nclo; clo++) {
2465 sprintf (qc_name, "ESO QC P3FACTOR%s_P%d AVG", GRAVI_CLO_NAME[clo], pol+1);
2466 cpl_size total_weight = 0;
2467 double p3factor = 0;
2468 for (int frame = 0; frame < nb_frame; frame++) {
2469 cpl_size weight = cpl_propertylist_get_long_long(frame_qcs[frame], "NROW");
2470 total_weight += weight;
2471 p3factor += weight * cpl_propertylist_get_double(frame_qcs[frame], qc_name);
2472 }
2473 p3factor /= total_weight;
2474
2475 cpl_propertylist_update_double(plist, qc_name, p3factor);
2476 cpl_propertylist_set_comment (plist, qc_name, "mean p3-factor");
2477
2478 sprintf (qc_name, "ESO QC T3PHI_SC%s_P%d AVG", GRAVI_CLO_NAME[clo], pol+1);
2479 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_T3_SC, "T3PHI", clo, nclo));
2480 cpl_propertylist_set_comment (plist, qc_name, "[deg] mean over lbd");
2481
2482 sprintf (qc_name, "ESO QC T3PHIERR_SC%s_P%d AVG", GRAVI_CLO_NAME[clo], pol+1);
2483 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_T3_SC, "T3PHIERR", clo, nclo));
2484 cpl_propertylist_set_comment (plist, qc_name, "[deg] mean over lbd");
2485
2486 CPLCHECK_MSG("Cannot set QC parameter for OI_T3 for SC");
2487 }/* End loop on triplets */
2488
2489 /*
2490 * Loop on beams to compute OI_FLUX for SC
2491 */
2492 cpl_msg_info (cpl_func, "Compute QC OI_FLUX for SC");
2493
2494 cpl_table * oi_flux_SC = gravi_data_get_oi_flux (vis_data, GRAVI_SC, pol, npol_sc);
2495
2496 for (int tel = 0; tel < ntel; tel++){
2497
2498 sprintf (qc_name, "ESO QC FLUX_SC%d_P%d AVG", tel+1, pol+1);
2499 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_flux_SC, "FLUX", tel, ntel));
2500 cpl_propertylist_set_comment (plist, qc_name, "[e/total_int_time] mean over lbd");
2501
2502 sprintf (qc_name, "ESO QC FLUXERR_SC%d_P%d AVG", tel+1, pol+1);
2503 cpl_propertylist_update_double (plist, qc_name, gravi_table_get_column_mean (oi_flux_SC, "FLUXERR", tel, ntel));
2504 cpl_propertylist_set_comment (plist, qc_name, "[e/total_int_time] mean over lbd");
2505
2506 sprintf (qc_name, "ESO QC FLUXRATE_SC%d_P%d SUM", tel+1, pol+1);
2507 double flux_rate = cpl_array_get_mean (cpl_table_get_array (oi_flux_SC, "FLUX", tel)) *
2508 cpl_array_get_size(cpl_table_get_array (oi_flux_SC, "FLUX", tel)) / cpl_table_get_double (oi_flux_SC, "INT_TIME", tel, &nv);
2509 cpl_propertylist_update_double (plist, qc_name, flux_rate);
2510 cpl_propertylist_set_comment (plist, qc_name, "[e/s] sum over lbd");
2511
2512 double ftpos_mean = cpl_table_get (oi_flux_SC, "FT_POS", tel, NULL);
2513 sprintf (qc_name, "ESO QC FT_POS SC%d_P%d", tel+1, pol+1);
2514 cpl_propertylist_update_double (plist, qc_name, ftpos_mean);
2515 cpl_propertylist_set_comment (plist, qc_name, "[V]");
2516
2517 double oplair_mean = cpl_table_get (oi_flux_SC, "OPL_AIR", tel, NULL);
2518 sprintf (qc_name, "ESO QC OPL_AIR SC%d_P%d", tel+1, pol+1);
2519 cpl_propertylist_update_double (plist, qc_name, oplair_mean);
2520 cpl_propertylist_set_comment (plist, qc_name, "[m]");
2521
2522 CPLCHECK_MSG("Cannot set QC parameter for OI_FLUX for SC");
2523 } /* End loop on beams */
2524
2525 } /* end loop on pol */
2526
2527 cpl_msg_info (cpl_func, "Compute IDP parameters");
2528
2529 /* Compute additional idp parameters */
2530 cpl_propertylist * idp_hdr = gravi_idp_compute(vis_data, vis_header, frameset, input_data_type);
2531 cpl_propertylist_append(plist, idp_hdr);
2532 cpl_propertylist_delete(idp_hdr);
2533
2534 CPLCHECK_MSG("Cannot compute IDP parameters");
2535 } /* End SC */
2536
2537
2538 cpl_propertylist_update_string (plist, "ESO QC FIELD MODE",
2539 gravi_pfits_get_mode_name(vis_header));
2540 cpl_propertylist_set_comment (plist, "ESO QC FIELD MODE", "Field mode");
2541
2542 CPLCHECK_MSG("Cannot create QC parameters");
2543
2545 return CPL_ERROR_NONE;
2546}
2547
2548/*----------------------------------------------------------------------------*/
2561cpl_error_code gravi_data_get_minmax_uvcoord(const cpl_table *oi_vis2,
2562 double * min_uvcoord,
2563 double * max_uvcoord)
2564{
2565 cpl_ensure (oi_vis2, CPL_ERROR_NULL_INPUT, 0.0);
2566
2567 *min_uvcoord = DBL_MAX;
2568 *max_uvcoord = DBL_MIN;
2569
2570 int valid;
2571 cpl_size nrow = cpl_table_get_nrow (oi_vis2);
2572
2573 const double * ucoord = cpl_table_get_data_double_const(oi_vis2, "UCOORD");
2574 const double * vcoord = cpl_table_get_data_double_const(oi_vis2, "VCOORD");
2575
2576 const cpl_array ** flags = cpl_table_get_data_array_const (oi_vis2, "FLAG");
2577
2578 double uvcoord = 0;
2579 cpl_size flag_array_size = cpl_array_get_size(flags[0]);
2580 for (cpl_size r=0; r<nrow;r++)
2581 {
2582 int flagged = 0;
2583 for(cpl_size el=0; el<flag_array_size; el++)
2584 {
2585 if (cpl_array_get_int(flags[r], el, &valid))
2586 {
2587 flagged = 1;
2588 break;
2589 }
2590 }
2591 if(!flagged)
2592 {
2593 uvcoord = sqrt(ucoord[r]*ucoord[r]+vcoord[r]*vcoord[r]);
2594 if(uvcoord > *max_uvcoord)
2595 *max_uvcoord = uvcoord;
2596 if(uvcoord < *min_uvcoord)
2597 *min_uvcoord = uvcoord;
2598 }
2599 }
2600 return CPL_ERROR_NONE;
2601}
2602
2603
2604
2605/*----------------------------------------------------------------------------*/
2614/*----------------------------------------------------------------------------*/
2615
2616cpl_error_code gravi_normalize_sc_to_ft (gravi_data * vis_data)
2617{
2619 cpl_ensure_code (vis_data, CPL_ERROR_NULL_INPUT);
2620
2621 cpl_propertylist * hdr_data = gravi_data_get_header (vis_data);
2622 int pol, npol = gravi_pfits_get_pola_num (hdr_data, GRAVI_SC);
2623 double qFactor;
2624
2625 if ( npol != gravi_pfits_get_pola_num (hdr_data, GRAVI_FT)) {
2626 return cpl_error_set_message(cpl_func,CPL_ERROR_ILLEGAL_INPUT,"polarisation of SC and FT shall be compatible");
2627 }
2628
2629 /* Loop on polarisation. Assume the same polarisation
2630 * splitting for both SC and FT */
2631 for ( pol= 0 ; pol < npol ; pol++ ) {
2632
2633 cpl_table * oi_wave_sc = gravi_data_get_oi_wave (vis_data, GRAVI_SC, pol, npol);
2634 cpl_table * oi_wave_ft = gravi_data_get_oi_wave (vis_data, GRAVI_FT, pol, npol);
2635
2636 /*
2637 * Get data for VIS2 and VISAMP
2638 */
2639 cpl_table * oi_vis2_sc = gravi_data_get_oi_vis2 (vis_data, GRAVI_SC, pol, npol);
2640 cpl_table * oi_vis2_ft = gravi_data_get_oi_vis2 (vis_data, GRAVI_FT, pol, npol);
2641 cpl_table * oi_vis_sc = gravi_data_get_oi_vis (vis_data, GRAVI_SC, pol, npol);
2642 cpl_table * oi_vis_ft = gravi_data_get_oi_vis (vis_data, GRAVI_FT, pol, npol);
2643
2644 CPLCHECK_MSG("Cannot get data");
2645
2646 /* Loop on baselines */
2647 for (cpl_size base = 0; base < cpl_table_get_nrow (oi_vis2_ft); base ++) {
2648
2649 /* Get the VIS2 of FT */
2650 const cpl_array * vis2_ft = cpl_table_get_array (oi_vis2_ft, "VIS2DATA", base);
2651
2652 /* Create the rebin VIS2 of SC */
2653 cpl_array * vis2_lr = gravi_array_rebin (cpl_table_get_array (oi_vis2_sc, "VIS2DATA", base),
2654 cpl_table_get_array (oi_vis2_sc, "VIS2ERR", base),
2655 oi_wave_sc, oi_wave_ft);
2656
2657 /* Compute the mean visibility loss over the band.
2658 * FIXME: shall use vis2_ft = (a.lbd+b) * vis2_lr, which could be done with cpl_matrix */
2659 qFactor = cpl_array_get_mean (vis2_lr) / cpl_array_get_mean (vis2_ft);
2660 cpl_msg_info (cpl_func, "vis2 %lli: qFactor = %f", base, qFactor);
2661
2662 /* Divide the SC data */
2663 cpl_array_divide_scalar (cpl_table_get_data_array (oi_vis2_sc, "VIS2DATA")[base], qFactor);
2664 cpl_array_divide_scalar (cpl_table_get_data_array (oi_vis2_sc, "VIS2ERR")[base], qFactor);
2665
2666 /* Get the VISAMP of FT */
2667 const cpl_array * vis_ft = cpl_table_get_array (oi_vis_ft, "VISAMP", base);
2668
2669 /* Create the rebin VISAMP of SC */
2670 cpl_array * vis_lr = gravi_array_rebin (cpl_table_get_array (oi_vis_sc, "VISAMP", base),
2671 cpl_table_get_array (oi_vis_sc, "VISAMPERR", base),
2672 oi_wave_sc, oi_wave_ft);
2673
2674 /* Compute the mean visibility loss over the band. */
2675 qFactor = cpl_array_get_mean (vis_lr) / cpl_array_get_mean (vis_ft);
2676 cpl_msg_info (cpl_func, "visAmp %lli: qFactor = %f", base, qFactor);
2677
2678 /* Divide the SC data */
2679 cpl_array_divide_scalar (cpl_table_get_data_array (oi_vis_sc, "VISAMP")[base], qFactor);
2680 cpl_array_divide_scalar (cpl_table_get_data_array (oi_vis_sc, "VISAMPERR")[base], qFactor);
2681
2682 FREE (cpl_array_delete, vis2_lr);
2683 FREE (cpl_array_delete, vis_lr);
2684 } /* End loop on baselines */
2685
2686 } /* End loop on pol */
2687
2689 return CPL_ERROR_NONE;
2690}
2691
2692/*----------------------------------------------------------------------------*/
2700/*----------------------------------------------------------------------------*/
2701
2702cpl_error_code gravi_vis_mjd_to_time (gravi_data * vis_data)
2703{
2705 cpl_ensure_code (vis_data, CPL_ERROR_NULL_INPUT);
2706 char date[90];
2707
2708 /* Loop on extension */
2709 int next = gravi_data_get_size (vis_data);
2710 for (int ext = 0; ext < next; ext ++) {
2711
2712 const char * extname = gravi_data_get_extname (vis_data,ext);
2713 if (!strcmp (extname, "OI_VIS") ||
2714 !strcmp (extname, "OI_VIS2") ||
2715 !strcmp (extname, "OI_T3") ||
2716 !strcmp (extname, "OI_FLUX")) {
2717
2718 /* Get the DATE-OBS in format YYYY-MM-DDT00:00:00.000 */
2719 cpl_propertylist * plist = gravi_data_get_plist_x (vis_data, ext);
2720 sprintf (date, "%.10sT00:00:00.000", cpl_propertylist_get_string (plist, "DATE-OBS"));
2721
2722 /* Get the MJD of this DATE-OBS */
2723 double mjd0 = gravi_convert_to_mjd (date);
2724 cpl_msg_debug (cpl_func, "DATE-OBS = %s -> mjd = %.3f", date, mjd0);
2725
2726 /* Compute TIME in [s] following the OIFITS standard */
2727 cpl_table * oi_table = gravi_data_get_table_x (vis_data, ext);
2728 cpl_size nrow = cpl_table_get_nrow (oi_table);
2729 for (cpl_size row = 0; row < nrow; row++) {
2730 double mjd = cpl_table_get (oi_table, "MJD", row, NULL);
2731 cpl_table_set (oi_table, "TIME", row, (mjd-mjd0) * 24 * 3600);
2732 }
2733
2734 /* Set units */
2735 cpl_table_set_column_unit (oi_table, "TIME", "s");
2736 }
2737 } /* End loop on extensions */
2738
2740 return CPL_ERROR_NONE;
2741}
2742
2743
2744/*----------------------------------------------------------------------------*/
2754/*----------------------------------------------------------------------------*/
2755
2756cpl_error_code gravi_flat_flux (gravi_data * vis_data, gravi_data * p2vm_map)
2757{
2759 cpl_ensure_code (vis_data, CPL_ERROR_NULL_INPUT);
2760 cpl_ensure_code (p2vm_map, CPL_ERROR_NULL_INPUT);
2761
2762 int num_used_tf = 1;
2763 gravi_data **used_tf_data = &p2vm_map;
2764
2765 /* Get the header */
2766 cpl_propertylist * hdr_data = gravi_data_get_header (vis_data);
2767
2768 /* For each type of data SC / FT */
2769 int ntype_data = 2;
2770 for (int type_data = 0; type_data < ntype_data ; type_data ++) {
2771
2772 /* Loop on polarisation */
2773 int npol = gravi_pfits_get_pola_num (hdr_data, type_data);
2774 for (int pol= 0 ; pol < npol ; pol++ ) {
2775
2776 /* Calibrate the FLUX as a real quantity */
2777 double delta_t = 10000.0;
2778 gravi_apply_tf_amp (vis_data, NULL, used_tf_data, num_used_tf,
2780 GRAVI_INSNAME(type_data, pol, npol),
2781 "FLUX", "FLUXERR", 4, delta_t);
2782
2783 CPLCHECK_MSG("Cannot apply normalize flux");
2784
2785 }
2786 /* End loop on polarisation */
2787 }
2788 /* End loop on data_type */
2789
2791 return CPL_ERROR_NONE;
2792}
2793
2794/*----------------------------------------------------------------------------*/
2804/*----------------------------------------------------------------------------*/
2805
2806cpl_error_code gravi_vis_average_amp (cpl_table *oi_table, const char *name, const char *err, int nbase)
2807{
2808 cpl_ensure_code (oi_table, CPL_ERROR_NULL_INPUT);
2809 cpl_ensure_code (name, CPL_ERROR_NULL_INPUT);
2810 cpl_ensure_code (err, CPL_ERROR_NULL_INPUT);
2811
2812 cpl_size nwave = cpl_table_get_column_depth (oi_table, name);
2813 cpl_array * weight = gravi_array_init_double (nwave, 0.0);
2814 cpl_array * value = gravi_array_init_double (nwave, 0.0);
2815
2816 /* Loop on base */
2817 int nrow = cpl_table_get_nrow (oi_table) / nbase;
2818 for (cpl_size base = 0; base < nbase ; base++) {
2819 cpl_array_fill_window (weight, 0, nwave, 0.0);
2820 cpl_array_fill_window (value, 0, nwave, 0.0);
2821
2822 /* Loop on row and wave */
2823 for (cpl_size row = 0; row < nrow ; row++) {
2824 const cpl_array * rval = cpl_table_get_array (oi_table, name, base + row*nbase);
2825 const cpl_array * rerr = cpl_table_get_array (oi_table, err, base + row*nbase);
2826 const cpl_array * flag = cpl_table_get_array (oi_table, "FLAG", base + row*nbase);
2827 for (cpl_size wave = 0; wave < nwave; wave++) {
2828 double w = pow (cpl_array_get (rerr, wave, NULL), -2);
2829 if (cpl_array_get (flag, wave, NULL)) w = 10e-20;
2830 double v = cpl_array_get (rval, wave, NULL);
2831 cpl_array_set (weight, wave, cpl_array_get (weight, wave, NULL) + w);
2832 cpl_array_set (value, wave, cpl_array_get (value, wave, NULL) + v * w);
2833 }
2834 }
2835 CPLCHECK_MSG("Cannot average amp");
2836
2837 /* Set the mean */
2838 cpl_array_divide (value, weight);
2839 cpl_table_set_array (oi_table, name, base, value);
2840
2841 /* Set the variance of the mean */
2842 cpl_array_power (weight, -0.5);
2843 cpl_table_set_array (oi_table, err, base, weight);
2844
2845
2846
2847 } /* End loop on base */
2848
2849 FREE (cpl_array_delete, weight);
2850 FREE (cpl_array_delete, value);
2851 return CPL_ERROR_NONE;
2852}
2853
2854/*----------------------------------------------------------------------------*/
2865/*----------------------------------------------------------------------------*/
2866
2867cpl_error_code gravi_vis_average_phi (cpl_table *oi_table, const char *name, const char *err, int nbase)
2868{
2869 cpl_ensure_code (oi_table, CPL_ERROR_NULL_INPUT);
2870 cpl_ensure_code (name, CPL_ERROR_NULL_INPUT);
2871 cpl_ensure_code (err, CPL_ERROR_NULL_INPUT);
2872
2873 cpl_size nwave = cpl_table_get_column_depth (oi_table, name);
2874 cpl_array * weight = gravi_array_init_double (nwave, 0.0);
2875 cpl_array * value = gravi_array_init_double_complex (nwave, 0.0 + I*0.0);
2876
2877 /* Loop on base */
2878 int nrow = cpl_table_get_nrow (oi_table) / nbase;
2879 for (cpl_size base = 0; base < nbase ; base++) {
2880 cpl_array_fill_window (weight, 0, nwave, 0.0);
2881 cpl_array_fill_window_complex (value, 0, nwave, 0.0);
2882
2883 /* Loop on row and wave */
2884 for (cpl_size row = 0; row < nrow ; row++) {
2885 const cpl_array * rval = cpl_table_get_array (oi_table, name, base + row*nbase);
2886 const cpl_array * rerr = cpl_table_get_array (oi_table, err, base + row*nbase);
2887 const cpl_array * flag = cpl_table_get_array (oi_table, "FLAG", base + row*nbase);
2888 for (cpl_size wave = 0; wave < nwave; wave++) {
2889 double w = pow (cpl_array_get (rerr, wave, NULL), -2);
2890 if (cpl_array_get (flag, wave, NULL)) w = 10e-20;
2891 double complex v = cexp (1.*I * cpl_array_get (rval, wave, NULL) * CPL_MATH_RAD_DEG);
2892 cpl_array_set (weight, wave, cpl_array_get (weight, wave, NULL) + w);
2893 cpl_array_set_complex (value, wave, cpl_array_get_complex (value, wave, NULL) + v * w);
2894 }
2895 }
2896 CPLCHECK_MSG("Cannot average phi");
2897
2898 /* Set the mean */
2899 gravi_table_set_array_phase (oi_table, name, base, value);
2900 /* Set the variance of the mean */
2901 cpl_array_power (weight, -0.5);
2902 cpl_table_set_array (oi_table, err, base, weight);
2903
2904 } /* End loop on base */
2905
2906 FREE (cpl_array_delete, weight);
2907 FREE (cpl_array_delete, value);
2908 return CPL_ERROR_NONE;
2909}
2910
2911/*----------------------------------------------------------------------------*/
2921/*----------------------------------------------------------------------------*/
2922
2923cpl_error_code gravi_vis_average_value (cpl_table *oi_table, const char *name, const char *err, int nbase)
2924{
2925 cpl_ensure_code (oi_table, CPL_ERROR_NULL_INPUT);
2926 cpl_ensure_code (name, CPL_ERROR_NULL_INPUT);
2927 int nv = 0;
2928
2929 /* Loop on base */
2930 int nrow = cpl_table_get_nrow (oi_table) / nbase;
2931 for (cpl_size base = 0; base < nbase ; base++) {
2932 double weight = 0.0;
2933 double value = 0.0;
2934
2935 /* Loop on row */
2936 for (cpl_size row = 0; row < nrow ; row++) {
2937 double w = (err!=NULL ? pow (cpl_table_get (oi_table, err, base + row*nbase, &nv), -2.0) : 1.0);
2938 value += cpl_table_get (oi_table, name, base + row*nbase, &nv) * w;
2939 weight += w;
2940 }
2941 CPLCHECK_MSG("Cannot average value");
2942
2943 /* Set the mean */
2944 cpl_table_set (oi_table, name, base, value / weight);
2945 } /* End loop on base */
2946
2947 return CPL_ERROR_NONE;
2948}
2949
2950/*----------------------------------------------------------------------------*/
2959/*----------------------------------------------------------------------------*/
2960cpl_error_code gravi_force_uncertainties (gravi_data * oi_data,
2961 const cpl_parameterlist * parlist)
2962{
2964 cpl_ensure_code (oi_data, CPL_ERROR_NULL_INPUT);
2965 cpl_ensure_code (parlist, CPL_ERROR_NULL_INPUT);
2966
2967 double err;
2968
2969 /* Get header */
2970 cpl_propertylist * header = gravi_data_get_header (oi_data);
2971
2972 /* VISAMPERR SC */
2973 err = gravi_param_get_double_default (parlist, "gravity.postprocess.visamperr-sc", -1.0);
2974 if ( err > 0) {
2975 cpl_msg_info (cpl_func,"Force VISAMPERR to %.e for all observations", err);
2976
2978 for (int pol = 0; pol < npol; pol++) {
2979 cpl_table * oi_table = gravi_data_get_oi_vis (oi_data, GRAVI_SC, pol, npol);
2980 cpl_array ** array = cpl_table_get_data_array (oi_table, "VISAMPERR");
2981 for (cpl_size row = 0; row<cpl_table_get_nrow (oi_table); row++) {
2982 cpl_array_fill_window (array[row], 0, CPL_SIZE_MAX, err);
2983 }
2984 }
2985 }
2986
2987 /* VISPHIERR SC */
2988 err = gravi_param_get_double_default (parlist, "gravity.postprocess.visphierr-sc", -1.0);
2989 if ( err > 0) {
2990 cpl_msg_info (cpl_func,"Force VISPHIERR to %.e for all observations", err);
2991
2993 for (int pol = 0; pol < npol; pol++) {
2994 cpl_table * oi_table = gravi_data_get_oi_vis (oi_data, GRAVI_SC, pol, npol);
2995 cpl_array ** array = cpl_table_get_data_array (oi_table, "VISPHIERR");
2996 for (cpl_size row = 0; row<cpl_table_get_nrow (oi_table); row++) {
2997 cpl_array_fill_window (array[row], 0, CPL_SIZE_MAX, err);
2998 }
2999 }
3000 }
3001
3002 /* FLUXERR SC */
3003 err = gravi_param_get_double_default (parlist, "gravity.postprocess.fluxerr-sc", -1.0);
3004 if ( err > 0) {
3005 cpl_msg_info (cpl_func,"Force FLUXERR to %.e for all observations", err);
3006
3008 for (int pol = 0; pol < npol; pol++) {
3009 cpl_table * oi_table = gravi_data_get_oi_flux (oi_data, GRAVI_SC, pol, npol);
3010 cpl_array ** array = cpl_table_get_data_array (oi_table, "FLUXERR");
3011 for (cpl_size row = 0; row<cpl_table_get_nrow (oi_table); row++) {
3012 cpl_array_fill_window (array[row], 0, CPL_SIZE_MAX, err);
3013 }
3014 }
3015 }
3016
3017 /* VIS2ERR SC */
3018 err = gravi_param_get_double_default (parlist, "gravity.postprocess.vis2err-sc", -1.0);
3019 if ( err > 0) {
3020 cpl_msg_info (cpl_func,"Force VIS2ERR to %.e for all observations", err);
3021
3023 for (int pol = 0; pol < npol; pol++) {
3024 cpl_table * oi_table = gravi_data_get_oi_vis2 (oi_data, GRAVI_SC, pol, npol);
3025 cpl_array ** array = cpl_table_get_data_array (oi_table, "VIS2ERR");
3026 for (cpl_size row = 0; row<cpl_table_get_nrow (oi_table); row++) {
3027 cpl_array_fill_window (array[row], 0, CPL_SIZE_MAX, err);
3028 }
3029 }
3030 }
3031
3033 return CPL_ERROR_NONE;
3034}
3035
3036
3037/*----------------------------------------------------------------------------*/
3048/*----------------------------------------------------------------------------*/
3049
3050cpl_error_code gravi_average_vis (gravi_data * oi_data)
3051{
3053 cpl_ensure_code (oi_data, CPL_ERROR_NULL_INPUT);
3054
3055 gravi_msg_warning ("FIXME", "Average the different observation is EXPERIMENTAL");
3056
3057 cpl_msg_warning (cpl_func, "FIXME: Weightening of UVCOORD and MJD is not done properly yet !");
3058 cpl_msg_warning (cpl_func, "FIXME: Integration of INT_TIME is not done properly yet !");
3059
3060 cpl_table * oi_table;
3061
3062 /* Create output data */
3063 cpl_propertylist * header = gravi_data_get_header (oi_data);
3064
3065 /* Loop on oidata, type_data and polarisation */
3066 for (int type_data = 0; type_data < 2 ; type_data ++) {
3067
3068 if (!gravi_data_has_type (oi_data, type_data == GRAVI_SC ? "_SC" : "_FT")) {
3069 cpl_msg_info (cpl_func, "OI_VIS has no %s, skip", GRAVI_TYPE(type_data));
3070 continue;
3071 }
3072
3073 int npol = gravi_pfits_get_pola_num (header, type_data);
3074 for (int pol = 0 ; pol < npol ; pol++ ) {
3075
3076 cpl_size nrow = cpl_table_get_nrow (gravi_data_get_oi_vis (oi_data, type_data, pol, npol))/GRAVI_NBASE;
3077 if (nrow == 1) {
3078 cpl_msg_info (cpl_func, "OI_VIS %s has only one observation, skip", GRAVI_TYPE(type_data));
3079 continue;
3080 }
3081
3082 /* OI_VIS */
3083 oi_table = gravi_data_get_oi_vis (oi_data, type_data, pol, npol);
3084 gravi_vis_average_value (oi_table, "TIME", NULL, 6);
3085 gravi_vis_average_value (oi_table, "MJD", NULL, 6);
3086 gravi_vis_average_value (oi_table, "INT_TIME", NULL, 6);
3087 gravi_vis_average_value (oi_table, "UCOORD", NULL, 6);
3088 gravi_vis_average_value (oi_table, "VCOORD", NULL, 6);
3089 gravi_vis_average_amp (oi_table, "VISAMP", "VISAMPERR", 6);
3090 gravi_vis_average_phi (oi_table, "VISPHI", "VISPHIERR", 6);
3091 gravi_vis_average_amp (oi_table, "RVIS", "RVISERR", 6);
3092 gravi_vis_average_amp (oi_table, "IVIS", "IVISERR", 6);
3093 // gravi_vis_average_amp (oi_table, "VISDATA", "VISERR"); // FIXME: to be done !!
3094 gravi_msg_warning ("FIXME", "VISDATA are not averaged !!!!");
3095 cpl_table_erase_window (oi_table, 6, CPL_SIZE_MAX);
3096
3097 CPLCHECK_MSG ("Cannot co-add OI_VIS");
3098
3099 /* OI_VIS2 */
3100 oi_table = gravi_data_get_oi_vis2 (oi_data, type_data, pol, npol);
3101 gravi_vis_average_value (oi_table, "TIME", NULL, 6);
3102 gravi_vis_average_value (oi_table, "MJD", NULL, 6);
3103 gravi_vis_average_value (oi_table, "INT_TIME", NULL, 6);
3104 gravi_vis_average_value (oi_table, "UCOORD", NULL, 6);
3105 gravi_vis_average_value (oi_table, "VCOORD", NULL, 6);
3106 gravi_vis_average_amp (oi_table, "VIS2DATA", "VIS2ERR", 6);
3107 cpl_table_erase_window (oi_table, 6, CPL_SIZE_MAX);
3108
3109 CPLCHECK_MSG ("Cannot co-add OI_VIS2");
3110
3111 /* OI_FLUX */
3112 oi_table = gravi_data_get_oi_flux (oi_data, type_data, pol, npol);
3113 gravi_vis_average_value (oi_table, "TIME", NULL, 4);
3114 gravi_vis_average_value (oi_table, "MJD", NULL, 4);
3115 gravi_vis_average_value (oi_table, "INT_TIME", NULL, 4);
3116 gravi_vis_average_amp (oi_table, "FLUX", "FLUXERR", 4);
3117 cpl_table_erase_window (oi_table, 4, CPL_SIZE_MAX);
3118
3119 CPLCHECK_MSG ("Cannot co-add OI_FLUX");
3120
3121 /* OI_T3 */
3122 oi_table = gravi_data_get_oi_t3 (oi_data, type_data, pol, npol);
3123 gravi_vis_average_value (oi_table, "TIME", NULL, 4);
3124 gravi_vis_average_value (oi_table, "MJD", NULL, 4);
3125 gravi_vis_average_value (oi_table, "INT_TIME", NULL, 4);
3126 gravi_vis_average_value (oi_table, "U1COORD", NULL, 4);
3127 gravi_vis_average_value (oi_table, "V1COORD", NULL, 4);
3128 gravi_vis_average_value (oi_table, "U2COORD", NULL, 4);
3129 gravi_vis_average_value (oi_table, "V2COORD", NULL, 4);
3130 gravi_vis_average_amp (oi_table, "T3AMP", "T3AMPERR", 4);
3131 gravi_vis_average_phi (oi_table, "T3PHI", "T3PHIERR", 4);
3132 cpl_table_erase_window (oi_table, 4, CPL_SIZE_MAX);
3133
3134 CPLCHECK_MSG ("Cannot co-add OI_T3");
3135
3136 } /* End loop on polarisation */
3137 } /* End loop on type_data */
3138
3140 return CPL_ERROR_NONE;
3141}
3142
3143/*----------------------------------------------------------------------------*/
3152/*----------------------------------------------------------------------------*/
3153
3154cpl_error_code gravi_vis_smooth_amp (cpl_table * oi_table, const char * name, const char * err,
3155 cpl_size nsamp)
3156{
3158 cpl_ensure_code (oi_table, CPL_ERROR_NULL_INPUT);
3159 if (nsamp < 1) return CPL_ERROR_NONE;
3160 int nv;
3161
3162 /* Get values */
3163 cpl_size nwave = cpl_table_get_column_depth (oi_table, name);
3164 cpl_size nrow = cpl_table_get_nrow (oi_table);
3165 cpl_ensure_code (nrow > 0, CPL_ERROR_ILLEGAL_INPUT);
3166
3167 /* Get arrays */
3168 cpl_array ** v_array = cpl_table_get_data_array (oi_table, name);
3169 cpl_array ** e_array = cpl_table_get_data_array (oi_table, err);
3170 cpl_array ** f_array = cpl_table_get_data_array (oi_table, "FLAG");
3171 CPLCHECK_MSG ("Cannot get data");
3172
3173 /* Allocate output */
3174 cpl_array * smo_array = cpl_array_duplicate (v_array[0]);
3175 cpl_array * err_array = cpl_array_duplicate (e_array[0]);
3176
3177 /* Loop on rows */
3178 for (cpl_size row = 0 ; row < nrow ; row ++) {
3179
3180 /* Median filter the uncertainties, to avoid
3181 * putting all on some sample */
3182 cpl_vector * i_vector = cpl_vector_new (nwave);
3183 for (cpl_size wave = 0; wave < nwave; wave++)
3184 cpl_vector_set (i_vector, wave, cpl_array_get (e_array[row],wave,&nv));
3185 cpl_vector * o_vector;
3186 o_vector = cpl_vector_filter_median_create (i_vector, nsamp);
3187
3188 /* Loop on waves */
3189 for (cpl_size wave = 0 ; wave < nwave ; wave ++) {
3190 double sum = 0.0, weight = 0.0;
3191
3192 /* Loop on samples to average */
3193 for (cpl_size samp = CPL_MAX(0,wave-nsamp) ; samp < CPL_MIN(nwave,wave+nsamp) ; samp ++) {
3194 if (cpl_array_get (f_array[row],samp,&nv)) {
3195 weight += 10e-20;
3196 sum += 0.0;
3197 } else {
3198 double w = pow (cpl_vector_get (o_vector,samp), -2);
3199 sum += cpl_array_get (v_array[row],samp,&nv) * w;
3200 weight += w;
3201 }
3202 }
3203
3204 cpl_array_set_double (smo_array, wave, sum / weight);
3205 cpl_array_set_double (err_array, wave, pow (weight, -0.5));
3206 }
3207
3208 /* Set back */
3209 cpl_table_set_array (oi_table, name, row, smo_array);
3210 cpl_table_set_array (oi_table, err, row, err_array);
3211 CPLCHECK_MSG ("Cannot smooth amp");
3212
3213 FREE (cpl_vector_delete, i_vector);
3214 FREE (cpl_vector_delete, o_vector);
3215 } /* End loop on rows */
3216
3217 FREE (cpl_array_delete, smo_array);
3218 FREE (cpl_array_delete, err_array);
3219
3221 return CPL_ERROR_NONE;
3222}
3223
3224/*----------------------------------------------------------------------------*/
3233/*----------------------------------------------------------------------------*/
3234
3235cpl_error_code gravi_vis_smooth_phi (cpl_table * oi_table, const char * name, const char * err,
3236 cpl_size nsamp)
3237{
3239 cpl_ensure_code (oi_table, CPL_ERROR_NULL_INPUT);
3240 if (nsamp < 1) return CPL_ERROR_NONE;
3241
3242 /* Get values */
3243 cpl_size nwave = cpl_table_get_column_depth (oi_table, name);
3244 cpl_size nrow = cpl_table_get_nrow (oi_table);
3245 cpl_ensure_code (nrow > 0, CPL_ERROR_ILLEGAL_INPUT);
3246 int nv;
3247
3248 /* Get arrays */
3249 cpl_array ** v_array = cpl_table_get_data_array (oi_table, name);
3250 cpl_array ** e_array = cpl_table_get_data_array (oi_table, err);
3251 cpl_array ** f_array = cpl_table_get_data_array (oi_table, "FLAG");
3252 CPLCHECK_MSG ("Cannot get data");
3253
3254 /* Allocate output */
3255 cpl_array * smo_array = cpl_array_duplicate (v_array[0]);
3256 cpl_array * err_array = cpl_array_duplicate (e_array[0]);
3257
3258 /* Loop on rows */
3259 for (cpl_size row = 0 ; row < nrow ; row ++) {
3260
3261 /* Median filter the uncertainties, to avoid
3262 * putting all on some sample */
3263 cpl_vector * i_vector = cpl_vector_new (nwave);
3264 for (cpl_size wave = 0; wave < nwave; wave++)
3265 cpl_vector_set (i_vector, wave, cpl_array_get (e_array[row],wave,&nv));
3266 cpl_vector * o_vector;
3267 o_vector = cpl_vector_filter_median_create (i_vector, nsamp);
3268
3269 /* Loop on waves */
3270 for (cpl_size wave = 0 ; wave < nwave ; wave ++) {
3271 double complex sum = 0.0 + I*0.0;
3272 double weight = 0.0;
3273
3274 /* Loop on samples to average */
3275 for (cpl_size samp = CPL_MAX(0,wave-nsamp) ; samp < CPL_MIN(nwave,wave+nsamp) ; samp ++) {
3276 if (cpl_array_get (f_array[row],samp,&nv)) {
3277 weight += 10e-20;
3278 sum += 0.0;
3279 } else {
3280 double w = pow (cpl_vector_get (o_vector,samp), -2);
3281 sum += cexp (1.*I* cpl_array_get (v_array[row],samp,&nv) * CPL_MATH_RAD_DEG) * w;
3282 weight += w;
3283 }
3284 }
3285
3286 cpl_array_set_double (smo_array, wave, carg (sum) * CPL_MATH_DEG_RAD);
3287 cpl_array_set_double (err_array, wave, pow (weight, -0.5));
3288 }
3289
3290 /* Set back */
3291 cpl_table_set_array (oi_table, name, row, smo_array);
3292 cpl_table_set_array (oi_table, err, row, err_array);
3293 CPLCHECK_MSG ("Cannot smooth phi");
3294
3295 FREE (cpl_vector_delete, i_vector);
3296 FREE (cpl_vector_delete, o_vector);
3297 } /* End loop on rows */
3298
3299 FREE (cpl_array_delete, smo_array);
3300 FREE (cpl_array_delete, err_array);
3301
3303 return CPL_ERROR_NONE;
3304}
3305
3306/*----------------------------------------------------------------------------*/
3315/*----------------------------------------------------------------------------*/
3316
3317cpl_error_code gravi_vis_fit_amp (cpl_table * oi_table, const char * name,
3318 const char * err, cpl_size maxdeg)
3319{
3321 cpl_ensure_code (oi_table, CPL_ERROR_NULL_INPUT);
3322 if (maxdeg < 0) return CPL_ERROR_NONE;
3323
3324 /* Get values */
3325 cpl_size nwave = cpl_table_get_column_depth (oi_table, name);
3326 cpl_size nrow = cpl_table_get_nrow (oi_table);
3327 cpl_ensure_code (nrow > 0, CPL_ERROR_ILLEGAL_INPUT);
3328 int nv;
3329
3330 /* Get arrays */
3331 cpl_array ** v_array = cpl_table_get_data_array (oi_table, name);
3332 cpl_array ** e_array = cpl_table_get_data_array (oi_table, err);
3333 cpl_array ** f_array = cpl_table_get_data_array (oi_table, "FLAG");
3334 CPLCHECK_MSG ("Cannot get data");
3335
3336 /* Loop on rows */
3337 for (cpl_size row = 0 ; row < nrow ; row ++) {
3338
3339 /* Create the vectors and matrix */
3340 cpl_matrix * coeff = cpl_matrix_new (nwave,maxdeg+1);
3341 cpl_matrix * rhs = cpl_matrix_new (nwave,1);
3342
3343 /* Fill */
3344 for (cpl_size wave = 0 ; wave < nwave ; wave ++) {
3345 double weight = cpl_array_get (f_array[row],wave,&nv) ? 10e-20 :
3346 pow (cpl_array_get (e_array[row],wave,&nv), -2);
3347 double value = cpl_array_get (f_array[row],wave,&nv) ? 0.0 :
3348 cpl_array_get (v_array[row],wave,&nv);
3349
3350 if (weight > 1e10)
3351 {
3352 cpl_msg_warning (cpl_func, "name = %s row = %lli wave = %lli "
3353 "has faulty uncertainty", name, row, wave);
3354 weight = 0.0;
3355 cpl_array_set (f_array[row],wave,1);
3356 }
3357
3358 cpl_matrix_set (rhs, wave, 0, value * weight);
3359 for (cpl_size deg = 0; deg <= maxdeg; deg++)
3360 cpl_matrix_set (coeff, wave, deg, pow ((double)wave,(double)deg) * weight);
3361 CPLCHECK_MSG ("Cannot fill");
3362 }
3363
3364 //printf ("name = %s row = %i maxdeg = %i\n", name, row, maxdeg);
3365 //cpl_matrix_dump (rhs, NULL);
3366 //cpl_matrix_dump (coeff, NULL);
3367
3368 /* Solve */
3369 cpl_errorstate prev_state = cpl_errorstate_get();
3370 cpl_matrix * solve = cpl_matrix_solve_normal (coeff, rhs);
3371
3372 /* Dump errors */
3373 if ( !cpl_errorstate_is_equal (prev_state))
3374 {
3375 cpl_errorstate_dump (prev_state, 0, NULL);
3376 cpl_msg_error (cpl_func,"%s row=%lld",name,row);
3377 }
3378 CPLCHECK_MSG ("Cannot solve matrix");
3379
3380 /* Evaluate */
3381 for (cpl_size wave = 0 ; wave < nwave ; wave ++) {
3382 double value = 0;
3383 for (cpl_size deg = 0; deg <= maxdeg; deg++)
3384 value += cpl_matrix_get (solve, deg, 0) * pow (wave, deg);
3385 cpl_array_set (v_array[row],wave,value);
3386 CPLCHECK_MSG ("Cannot evaluate");
3387 }
3388
3389 FREE (cpl_matrix_delete, coeff);
3390 FREE (cpl_matrix_delete, rhs);
3391 FREE (cpl_matrix_delete, solve);
3392 }
3393
3395 return CPL_ERROR_NONE;
3396}
3397
3398/*----------------------------------------------------------------------------*/
3412/*----------------------------------------------------------------------------*/
3413
3414cpl_error_code gravi_vis_smooth (gravi_data * oi_data,
3415 cpl_size nsamp_vis,
3416 cpl_size nsamp_flx,
3417 cpl_size maxdeg)
3418{
3420 cpl_ensure_code (oi_data, CPL_ERROR_NULL_INPUT);
3421
3422 cpl_table * oi_table;
3423
3424 /* Create output data */
3425 cpl_propertylist * header = gravi_data_get_header (oi_data);
3426
3427 int type_data = GRAVI_SC;
3428 int npol = gravi_pfits_get_pola_num (header, type_data);
3429
3430 for (int pol = 0 ; pol < npol ; pol++ ) {
3431
3432 /* OI_FLUX */
3433 oi_table = gravi_data_get_oi_flux (oi_data, type_data, pol, npol);
3434 gravi_vis_flag_nan (oi_table);
3435 gravi_vis_flag_lower (oi_table, "FLUXERR", "FLAG", 0.0);
3436 if (cpl_table_has_column(oi_table, "FLUXDATA"))
3437 {
3438 cpl_msg_info(cpl_func, "Smoothing OIFITS2 FLUXDATA column");
3439 gravi_vis_smooth_amp (oi_table, "FLUXDATA", "FLUXERR", nsamp_flx);
3440 gravi_vis_flag_relative_threshold (oi_table, "FLUXERR", "FLUXDATA", "FLAG", 1.0);
3441 }
3442 else
3443 {
3444 gravi_vis_smooth_amp (oi_table, "FLUX", "FLUXERR", nsamp_flx);
3445 gravi_vis_flag_relative_threshold (oi_table, "FLUXERR", "FLUX", "FLAG", 1.0);
3446 }
3447 CPLCHECK_MSG ("Cannot resamp OI_FLUX");
3448
3449 /* OI_VIS2 */
3450 oi_table = gravi_data_get_oi_vis2 (oi_data, type_data, pol, npol);
3451 gravi_vis_flag_nan (oi_table);
3452 gravi_vis_flag_lower (oi_table, "VIS2ERR", "FLAG", 0.);
3453 gravi_vis_flag_median (oi_table, "VIS2ERR", "FLAG", 5.0);
3454 gravi_vis_smooth_amp (oi_table, "VIS2DATA", "VIS2ERR", nsamp_vis);
3455 gravi_vis_fit_amp (oi_table, "VIS2DATA", "VIS2ERR", maxdeg);
3456 gravi_vis_flag_threshold (oi_table, "VIS2ERR", "FLAG", 1.);
3457 CPLCHECK_MSG ("Cannot resamp OI_VIS2");
3458
3459 /* OI_VIS */
3460 oi_table = gravi_data_get_oi_vis (oi_data, type_data, pol, npol);
3461 gravi_vis_flag_nan (oi_table);
3462 gravi_vis_flag_lower (oi_table, "VISAMPERR", "FLAG", 0.);
3463 gravi_vis_flag_median (oi_table, "VISPHIERR", "FLAG", 5.0);
3464 gravi_vis_smooth_amp (oi_table, "VISAMP", "VISAMPERR", nsamp_vis);
3465 gravi_vis_smooth_phi (oi_table, "VISPHI", "VISPHIERR", nsamp_vis);
3466 gravi_vis_fit_amp (oi_table, "VISAMP", "VISAMPERR", maxdeg);
3467 gravi_vis_fit_amp (oi_table, "VISPHI", "VISPHIERR", maxdeg);
3468 gravi_vis_smooth_amp (oi_table, "RVIS", "RVISERR", nsamp_flx);
3469 gravi_vis_smooth_amp (oi_table, "IVIS", "IVISERR", nsamp_flx);
3470 gravi_vis_flag_threshold (oi_table, "VISAMPERR", "FLAG", 1.);
3471
3472 gravi_msg_warning ("FIXME", "VISDATA is not properly smooth !!");
3473 CPLCHECK_MSG ("Cannot resamp OI_VIS");
3474
3475 /* OI_T3 */
3476 oi_table = gravi_data_get_oi_t3 (oi_data, type_data, pol, npol);
3477 gravi_vis_flag_nan (oi_table);
3478 gravi_vis_flag_lower (oi_table, "T3AMPERR", "FLAG", 0.0);
3479 gravi_vis_flag_median (oi_table, "T3PHIERR", "FLAG", 5.0);
3480 gravi_vis_smooth_amp (oi_table, "T3AMP", "T3AMPERR", nsamp_vis);
3481 gravi_vis_smooth_phi (oi_table, "T3PHI", "T3PHIERR", nsamp_vis);
3482 gravi_vis_fit_amp (oi_table, "T3AMP", "T3AMPERR", maxdeg);
3483 gravi_vis_fit_amp (oi_table, "T3PHI", "T3PHIERR", maxdeg);
3484 gravi_vis_flag_threshold (oi_table, "T3AMPERR", "FLAG", 1.0);
3485 CPLCHECK_MSG ("Cannot resamp OI_T3");
3486
3487 } /* End loop on polarisation */
3488
3490 return CPL_ERROR_NONE;
3491}
3492
3493/*----------------------------------------------------------------------------*/
3503/*----------------------------------------------------------------------------*/
3504
3505cpl_error_code gravi_vis_resamp_amp (cpl_table * oi_table, const char * name, const char * err,
3506 cpl_size nsamp, cpl_size nwave_new)
3507{
3509 cpl_ensure_code (oi_table, CPL_ERROR_NULL_INPUT);
3510
3511 /* Loop on rows */
3512 cpl_size nrow = cpl_table_get_nrow (oi_table);
3513 cpl_ensure_code (nrow > 0, CPL_ERROR_ILLEGAL_INPUT);
3514 for (cpl_size row = 0 ; row < nrow ; row ++) {
3515
3516 /* Loop on new waves */
3517 for (cpl_size wave = 0 ; wave < nwave_new ; wave ++) {
3518 double sum = 0.0;
3519 double weight = 0.0;
3520 for (cpl_size samp = 0 ; samp < nsamp ; samp ++) {
3521 double w = pow (gravi_table_get_value (oi_table,err,row,wave*nsamp+samp), -2.0);
3522 if (gravi_table_get_value (oi_table,"FLAG",row,wave*nsamp+samp)) w = 10e-20;
3523 sum += gravi_table_get_value (oi_table,name,row,wave*nsamp+samp) * w;
3524 weight += w;
3525 }
3526 gravi_table_set_value (oi_table,name,row,wave, sum / weight);
3527 gravi_table_set_value (oi_table,err,row,wave, pow (weight, -0.5));
3528 }
3529
3530 } /* End loop on rows */
3531
3532 cpl_table_set_column_depth (oi_table, name, nwave_new);
3533 cpl_table_set_column_depth (oi_table, err, nwave_new);
3534
3536 return CPL_ERROR_NONE;
3537}
3538
3539/*----------------------------------------------------------------------------*/
3549/*----------------------------------------------------------------------------*/
3550
3551cpl_error_code gravi_vis_resamp_phi (cpl_table * oi_table, const char * name, const char * err,
3552 cpl_size nsamp, cpl_size nwave_new)
3553{
3555 cpl_ensure_code (oi_table, CPL_ERROR_NULL_INPUT);
3556
3557 /* Loop on rows */
3558 cpl_size nrow = cpl_table_get_nrow (oi_table);
3559 cpl_ensure_code (nrow > 0, CPL_ERROR_ILLEGAL_INPUT);
3560 for (cpl_size row = 0 ; row < nrow ; row ++) {
3561
3562 /* Loop on new waves */
3563 for (cpl_size wave = 0 ; wave < nwave_new ; wave ++) {
3564 double complex sum = 0.0;
3565 double weight = 0.0;
3566 for (cpl_size samp = 0 ; samp < nsamp ; samp ++) {
3567 double w = pow (gravi_table_get_value (oi_table,err,row,wave*nsamp+samp), -2.0);
3568 if (gravi_table_get_value (oi_table,"FLAG",row,wave*nsamp+samp)) w = 10e-20;
3569 sum += cexp (1.*I* gravi_table_get_value (oi_table,name,row,wave*nsamp+samp) * CPL_MATH_RAD_DEG) * w;
3570 weight += w;
3571 }
3572 gravi_table_set_value (oi_table,name,row,wave, carg (sum) * CPL_MATH_DEG_RAD);
3573 gravi_table_set_value (oi_table,err,row,wave, pow (weight, -0.5));
3574 }
3575
3576 } /* End loop on rows */
3577
3578 cpl_table_set_column_depth (oi_table, name, nwave_new);
3579 cpl_table_set_column_depth (oi_table, err, nwave_new);
3580
3582 return CPL_ERROR_NONE;
3583}
3584
3585/*----------------------------------------------------------------------------*/
3596/*----------------------------------------------------------------------------*/
3597
3598cpl_error_code gravi_vis_resamp (gravi_data * oi_data, cpl_size nsamp)
3599{
3601 cpl_ensure_code (oi_data, CPL_ERROR_NULL_INPUT);
3602 cpl_ensure_code (nsamp>1, CPL_ERROR_ILLEGAL_INPUT);
3603
3604 cpl_table * oi_table;
3605 cpl_size nwave, nwave_new;
3606 int nv = 0;
3607
3608 /* Create output data */
3609 cpl_propertylist * header = gravi_data_get_header (oi_data);
3610
3611 int type_data = GRAVI_SC;
3612 int npol = gravi_pfits_get_pola_num (header, type_data);
3613 for (int pol = 0 ; pol < npol ; pol++ ) {
3614
3615 /* OI_WAVELENGTH table */
3616 oi_table = gravi_data_get_oi_wave (oi_data, type_data, pol, npol);
3617 nwave = cpl_table_get_nrow (oi_table);
3618
3619 /* New number of wave sample */
3620 nwave_new = nwave / nsamp;
3621 cpl_msg_info (cpl_func, "Resamp the SC data by %lld bins: %lld -> %lld",
3622 nsamp, nwave, nwave_new);
3623 cpl_ensure_code (nwave_new > 1, CPL_ERROR_ILLEGAL_INPUT);
3624
3625 /* Get the wavelength */
3626 for (cpl_size wave = 0 ; wave < nwave_new ; wave ++) {
3627 /* Compute effective band first */
3628 cpl_table_set (oi_table, "EFF_BAND", wave,
3629 cpl_table_get (oi_table, "EFF_WAVE", wave*nsamp+nsamp-1, &nv) -
3630 cpl_table_get (oi_table, "EFF_WAVE", wave*nsamp, &nv));
3631
3632 /* Average them */
3633 double mean = 0.0;
3634 for (cpl_size samp = 0 ; samp < nsamp ; samp++)
3635 mean += cpl_table_get (oi_table, "EFF_WAVE", wave*nsamp+samp, &nv);
3636 cpl_table_set (oi_table, "EFF_WAVE", wave, mean / nsamp);
3637 }
3638
3639 /* Erase last entries */
3640 cpl_table_erase_window (oi_table, nwave_new, CPL_SIZE_MAX);
3641 CPLCHECK_MSG ("Cannot resamp OI_WAVELENGTH");
3642
3643 /* OI_FLUX */
3644 oi_table = gravi_data_get_oi_flux (oi_data, type_data, pol, npol);
3645 gravi_vis_resamp_amp (oi_table, "FLUX", "FLUXERR", nsamp, nwave_new);
3646 cpl_table_set_column_depth (oi_table, "FLAG", nwave_new);
3647 gravi_vis_flag_relative_threshold (oi_table, "FLUXERR", "FLUX", "FLAG", 1.0);
3648 CPLCHECK_MSG ("Cannot resamp OI_FLUX");
3649
3650 /* OI_VIS2 */
3651 oi_table = gravi_data_get_oi_vis2 (oi_data, type_data, pol, npol);
3652 gravi_vis_resamp_amp (oi_table, "VIS2DATA", "VIS2ERR", nsamp, nwave_new);
3653 cpl_table_set_column_depth (oi_table, "FLAG", nwave_new);
3654 gravi_vis_flag_threshold (oi_table, "VIS2ERR", "FLAG", 1.);
3655 CPLCHECK_MSG ("Cannot resamp OI_VIS2");
3656
3657 /* OI_VIS */
3658 oi_table = gravi_data_get_oi_vis (oi_data, type_data, pol, npol);
3659 gravi_vis_resamp_amp (oi_table, "VISAMP", "VISAMPERR", nsamp, nwave_new);
3660 gravi_vis_resamp_amp (oi_table, "VISPHI", "VISPHIERR", nsamp, nwave_new);
3661 gravi_vis_resamp_amp (oi_table, "RVIS", "RVISERR", nsamp, nwave_new);
3662 gravi_vis_resamp_amp (oi_table, "IVIS", "IVISERR", nsamp, nwave_new);
3663 cpl_table_set_column_depth (oi_table, "FLAG", nwave_new);
3664 gravi_vis_flag_threshold (oi_table, "VISAMPERR", "FLAG", 1.);
3665
3666 gravi_msg_warning ("FIXME", "VISDATA is not properly resampled !!");
3667 cpl_table_set_column_depth (oi_table, "VISDATA", nwave_new);
3668 cpl_table_set_column_depth (oi_table, "VISERR", nwave_new);
3669 CPLCHECK_MSG ("Cannot resamp OI_VIS");
3670
3671 /* OI_T3 */
3672 oi_table = gravi_data_get_oi_t3 (oi_data, type_data, pol, npol);
3673 gravi_vis_resamp_amp (oi_table, "T3AMP", "T3AMPERR", nsamp, nwave_new);
3674 gravi_vis_resamp_amp (oi_table, "T3PHI", "T3PHIERR", nsamp, nwave_new);
3675 cpl_table_set_column_depth (oi_table, "FLAG", nwave_new);
3676 gravi_vis_flag_threshold (oi_table, "T3AMPERR", "FLAG", 1.0);
3677 CPLCHECK_MSG ("Cannot resamp OI_T3");
3678
3679 } /* End loop on polarisation */
3680
3682 return CPL_ERROR_NONE;
3683}
3684
3685/*----------------------------------------------------------------------------*/
3693/*----------------------------------------------------------------------------*/
3694
3695cpl_error_code gravi_vis_copy_fluxdata (gravi_data * oi_data, int delete_flux)
3696{
3698 cpl_ensure_code (oi_data, CPL_ERROR_NULL_INPUT);
3699
3700 /* header */
3701 cpl_propertylist * header = gravi_data_get_header (oi_data);
3702
3703 /* Loop on oidata, type_data and polarisation */
3704 for (int type_data = 0; type_data < 2 ; type_data ++) {
3705
3706 if (!gravi_data_has_type (oi_data, type_data == GRAVI_SC ? "_SC" : "_FT")) {
3707 cpl_msg_info (cpl_func, "OI_FLUX has no %s, skip", GRAVI_TYPE(type_data));
3708 continue;
3709 }
3710
3711 int npol = gravi_pfits_get_pola_num (header, type_data);
3712 for (int pol = 0 ; pol < npol ; pol++ ) {
3713
3714 /* OI_FLUX table */
3715 cpl_table * oi_flux;
3716 oi_flux = gravi_data_get_oi_flux (oi_data, type_data, pol, npol);
3717
3718 /* Delete column if existing */
3719 if (cpl_table_has_column (oi_flux, "FLUXDATA") )
3720 cpl_table_erase_column (oi_flux, "FLUXDATA");
3721
3722 /* Duplicate FLUX into FLUXDATA */
3723 cpl_table_duplicate_column (oi_flux, "FLUXDATA", oi_flux, "FLUX");
3724
3725 /* Delete original FLUX column if so requested */
3726 if(delete_flux)
3727 cpl_table_erase_column(oi_flux, "FLUX");
3728 } /* End loop on polarisation */
3729
3730 } /* End loop on SC/FT */
3731
3733 return CPL_ERROR_NONE;
3734}
3735
3736/*----------------------------------------------------------------------------*/
3742/*----------------------------------------------------------------------------*/
3743
3744cpl_error_code gravi_vis_flag_nan (cpl_table * oi_table)
3745{
3747 cpl_ensure_code (oi_table, CPL_ERROR_NULL_INPUT);
3748
3749 cpl_size nrow = cpl_table_get_nrow (oi_table);
3750 cpl_ensure_code (nrow > 0, CPL_ERROR_ILLEGAL_INPUT);
3751
3752 int ncols = 10;
3753 const char * names[] = {"VIS2DATA","VIS2ERR","VISAMP","VISAMPERR",
3754 "VISPHI","VISPHIERR","T3PHI","T3PHIERR",
3755 "T3AMP","T3AMPERR"};
3756
3757 /* Loop on columns */
3758 for (int c = 0; c < ncols; c++) {
3759
3760 if (!cpl_table_has_column (oi_table,names[c])) continue;
3761 cpl_msg_info (cpl_func,"Check column %s",names[c]);
3762
3763 /* Get data of this columns */
3764 cpl_size nwave = cpl_table_get_column_depth (oi_table, names[c]);
3765 cpl_array ** v_array = cpl_table_get_data_array (oi_table, names[c]);
3766 cpl_array ** f_array = cpl_table_get_data_array (oi_table, "FLAG");
3767 CPLCHECK_MSG ("Cannot get data");
3768
3769 /* Loop on rows and waves */
3770 cpl_size ninvalid = 0;
3771 for (cpl_size row = 0; row < nrow ; row ++) {
3772 for (cpl_size wave = 0 ; wave < nwave ; wave ++) {
3773
3774 /* Get value */
3775 int nv = 0;
3776 double value = cpl_array_get (v_array[row], wave, &nv);
3777
3778 /* Check value */
3779 if (nv || isnan (value)) {
3780 cpl_array_set (f_array[row], wave, 1.0);
3781 cpl_array_set (v_array[row], wave, 0.0);
3782 ninvalid ++;
3783 }
3784 CPLCHECK_MSG ("Cannot check data");
3785 }
3786 } /* End loop on rows and waves */
3787
3788 /* Verbose */
3789 if (ninvalid > 0) {
3790 cpl_msg_warning (cpl_func, "Flag %lld invalid data (NAN or NULL) in %s", ninvalid, names[c]);
3791 }
3792
3793 } /* End loop on columns */
3794
3796 return CPL_ERROR_NONE;
3797}
3798
3799/*----------------------------------------------------------------------------*/
3811/*----------------------------------------------------------------------------*/
3812
3813cpl_error_code gravi_vis_flag_threshold (cpl_table * oi_table, const char * data, const char *flag, double value)
3814{
3816 cpl_ensure_code (oi_table, CPL_ERROR_NULL_INPUT);
3817 cpl_ensure_code (data, CPL_ERROR_NULL_INPUT);
3818 cpl_ensure_code (flag, CPL_ERROR_ILLEGAL_OUTPUT);
3819
3820 /* Get pointer to speed up */
3821 int nv = 0;
3822 cpl_size nrow = cpl_table_get_nrow (oi_table);
3823 cpl_array ** pdata = cpl_table_get_data_array (oi_table, data);
3824 cpl_array ** pflag = cpl_table_get_data_array (oi_table, flag);
3825
3826 CPLCHECK_MSG ("Cannot get data");
3827
3828 cpl_size size = cpl_array_get_size (pdata[0]);
3829
3830 /* Loop on row and index. Add to FLAG if data is above threshold */
3831 for ( cpl_size row = 0 ; row < nrow ; row ++ ) {
3832 if (pdata[row]==NULL) continue;
3833
3834 for ( cpl_size indx = 0 ; indx < size ; indx ++ ) {
3835 if ( cpl_array_get (pdata[row], indx, &nv) > value ) {
3836 cpl_array_set (pflag[row], indx, cpl_array_get (pflag[row], indx, &nv) + 1 );
3837 }
3838 }
3839 }
3840
3842 return CPL_ERROR_NONE;
3843}
3844
3845/*----------------------------------------------------------------------------*/
3857/*----------------------------------------------------------------------------*/
3858
3859cpl_error_code gravi_vis_flag_lower (cpl_table * oi_table, const char * data, const char *flag, double value)
3860{
3862 cpl_ensure_code (oi_table, CPL_ERROR_NULL_INPUT);
3863 cpl_ensure_code (data, CPL_ERROR_NULL_INPUT);
3864 cpl_ensure_code (flag, CPL_ERROR_ILLEGAL_OUTPUT);
3865
3866 /* Get pointer to speed up */
3867 int nv = 0;
3868 cpl_size nrow = cpl_table_get_nrow (oi_table);
3869 cpl_array ** pdata = cpl_table_get_data_array (oi_table, data);
3870 cpl_array ** pflag = cpl_table_get_data_array (oi_table, flag);
3871
3872 CPLCHECK_MSG ("Cannot get data");
3873
3874 cpl_size size = cpl_array_get_size (pdata[0]);
3875
3876 /* Loop on row and index. Add to FLAG if data is above threshold */
3877 for ( cpl_size row = 0 ; row < nrow ; row ++ ) {
3878 if (pdata[row]==NULL) continue;
3879
3880 for ( cpl_size indx = 0 ; indx < size ; indx ++ ) {
3881 if ( cpl_array_get (pdata[row], indx, &nv) <= value ) {
3882 cpl_array_set (pflag[row], indx, cpl_array_get (pflag[row], indx, &nv) + 1 );
3883 }
3884 }
3885 }
3886
3888 return CPL_ERROR_NONE;
3889}
3890
3891/*----------------------------------------------------------------------------*/
3903/*----------------------------------------------------------------------------*/
3904
3905cpl_error_code gravi_vis_flag_median (cpl_table * oi_table, const char * data, const char *flag, double value)
3906{
3908 cpl_ensure_code (oi_table, CPL_ERROR_NULL_INPUT);
3909 cpl_ensure_code (data, CPL_ERROR_NULL_INPUT);
3910 cpl_ensure_code (flag, CPL_ERROR_ILLEGAL_OUTPUT);
3911
3912 /* Get pointer to speed up */
3913 int nv = 0;
3914 cpl_size nrow = cpl_table_get_nrow (oi_table);
3915 cpl_array ** pdata = cpl_table_get_data_array (oi_table, data);
3916 cpl_array ** pflag = cpl_table_get_data_array (oi_table, flag);
3917
3918 CPLCHECK_MSG ("Cannot get data");
3919
3920 cpl_size size = cpl_array_get_size (pdata[0]);
3921 cpl_vector * i_vector = cpl_vector_new (size);
3922
3923 /* Loop on row and index. Add to FLAG if data is above threshold */
3924 for ( cpl_size row = 0 ; row < nrow ; row ++ ) {
3925 if (pdata[row]==NULL || size<100) continue;
3926
3927 /* Set */
3928 for (cpl_size indx = 0; indx < size; indx++)
3929 cpl_vector_set (i_vector, indx, cpl_array_get (pdata[0],indx,&nv));
3930
3931 /* Median filter over 8 pixels wide */
3932 cpl_vector * o_vector = cpl_vector_filter_median_create (i_vector, 4);
3933
3934 /* Check whose pixel have a large values compare to this median */
3935 for ( cpl_size indx = 0 ; indx < size ; indx ++ ) {
3936 if ( cpl_array_get (pdata[row], indx, &nv) > value * cpl_vector_get (o_vector, indx)) {
3937 cpl_array_set (pflag[row], indx, cpl_array_get (pflag[row], indx, &nv) + 1 );
3938 }
3939 }
3940
3941 FREE (cpl_vector_delete, o_vector);
3942 }
3943
3944 FREE (cpl_vector_delete, i_vector);
3946 return CPL_ERROR_NONE;
3947}
3948
3949
3950/*----------------------------------------------------------------------------*/
3963/*----------------------------------------------------------------------------*/
3964
3965cpl_error_code gravi_vis_flag_relative_threshold(cpl_table * oi_table, const char * err,
3966 const char * data, const char *flag, double value)
3967{
3969 cpl_ensure_code (oi_table, CPL_ERROR_NULL_INPUT);
3970 cpl_ensure_code (data, CPL_ERROR_NULL_INPUT);
3971 cpl_ensure_code (err, CPL_ERROR_NULL_INPUT);
3972 cpl_ensure_code (flag, CPL_ERROR_ILLEGAL_OUTPUT);
3973
3974 /* Get pointer to speed up */
3975 int nv = 0;
3976 cpl_size row, nrow = cpl_table_get_nrow (oi_table);
3977 cpl_array ** perr = cpl_table_get_data_array (oi_table, err);
3978 cpl_array ** pdata = cpl_table_get_data_array (oi_table, data);
3979 cpl_array ** pflag = cpl_table_get_data_array (oi_table, flag);
3980
3981 CPLCHECK_MSG ("Cannot get data");
3982
3983 cpl_size indx, size = cpl_array_get_size (pdata[0]);
3984
3985 /* Loop on row and index. Add to FLAG if data is above threshold */
3986 for ( row = 0 ; row < nrow ; row ++ ) {
3987 if (perr[row]==NULL) continue;
3988 cpl_array * tmp = cpl_array_duplicate (perr[row]);
3989 cpl_array_divide (tmp, pdata[row]);
3990 for ( indx = 0 ; indx < size ; indx ++ ) {
3991 if ( cpl_array_get (tmp, indx, &nv) > value) {
3992 cpl_array_set (pflag[row], indx, cpl_array_get (pflag[row], indx, &nv) + 1 );
3993 }
3994 }
3995 cpl_array_delete (tmp);
3996 }
3997
3999 return CPL_ERROR_NONE;
4000}
4001
4002/*----------------------------------------------------------------------------*/
4013/*----------------------------------------------------------------------------*/
4014
4015cpl_error_code gravi_vis_erase_obs (cpl_table * oi_table, cpl_array *flag_array, cpl_size ntel)
4016{
4018 cpl_ensure_code (oi_table, CPL_ERROR_NULL_INPUT);
4019 cpl_ensure_code (flag_array, CPL_ERROR_NULL_INPUT);
4020
4021 /* Get nrow */
4022 cpl_size nrow = cpl_table_get_nrow (oi_table) / ntel;
4023 cpl_ensure_code (nrow == cpl_array_get_size (flag_array),
4024 CPL_ERROR_ILLEGAL_INPUT);
4025
4026 /* Loop and select */
4027 cpl_table_unselect_all (oi_table);
4028 for (cpl_size row = 0; row < nrow; row++) {
4029 if (cpl_array_get (flag_array, row, NULL) == 0) continue;
4030 cpl_table_or_selected_window (oi_table, row * ntel, ntel);
4031 }
4032
4033 /* Delete selected */
4034 cpl_table_erase_selected (oi_table);
4035 CPLCHECK_MSG ("Cannot erase");
4036
4038 return CPL_ERROR_NONE;
4039}
4040
4041/*----------------------------------------------------------------------------*/
4061/*----------------------------------------------------------------------------*/
4062
4063cpl_error_code gravi_vis_compute_column_mean (cpl_table * out_table,
4064 cpl_table * in_table,
4065 const char * name, int ntel)
4066{
4068 cpl_ensure_code (out_table, CPL_ERROR_NULL_INPUT);
4069 cpl_ensure_code (in_table, CPL_ERROR_NULL_INPUT);
4070 cpl_ensure_code (name, CPL_ERROR_NULL_INPUT);
4071 cpl_ensure_code (ntel == cpl_table_get_nrow (out_table),
4072 CPL_ERROR_ILLEGAL_OUTPUT);
4073
4074 /* Check if column exist */
4075 if ( !cpl_table_has_column (in_table, name)) {
4076 cpl_msg_info (cpl_func, "Cannot average column %s (not existing)", name);
4077 return CPL_ERROR_NONE;
4078 }
4079
4080 /* Cast the type into an int, to avoid warnings */
4081 int type = cpl_table_get_column_type (in_table, name);
4082 cpl_size depth = cpl_table_get_column_depth (in_table, name);
4083
4084 /* Get the number of rows */
4085 cpl_size nrow = cpl_table_get_nrow (in_table) / ntel;
4086 cpl_ensure_code (nrow, CPL_ERROR_ILLEGAL_INPUT);
4087
4088 /* Get the column REJECTION_FLAG */
4089 int * flag = NULL;
4090 if (cpl_table_has_column (in_table, "REJECTION_FLAG"))
4091 flag = cpl_table_get_data_int (in_table, "REJECTION_FLAG");
4092
4093 cpl_msg_info (cpl_func, "Average column: %s (%s REJECTION_FLAG)",
4094 name, flag ? "with" : "without");
4095
4096 switch (type) {
4097 case CPL_TYPE_DOUBLE:
4098 case CPL_TYPE_FLOAT:
4099 case CPL_TYPE_INT:
4100 /* Case scalar column */
4101 if (!cpl_table_has_column (out_table, name))
4102 cpl_table_new_column (out_table, name, CPL_TYPE_DOUBLE);
4103 for (int tel = 0; tel < ntel; tel++) {
4104 cpl_size nvalid = 0;
4105 double mean = 0.0;
4106 for (cpl_size row = 0; row < nrow; row++) {
4107 if (flag && flag[row*ntel+tel] != 0) continue;
4108 nvalid ++;
4109 mean += cpl_table_get (in_table, name, row*ntel+tel, NULL);
4110 }
4111 if (nvalid > 0) mean /= nvalid;
4112 cpl_table_set (out_table, name, tel, mean);
4113 }
4114 break;
4115
4116 case CPL_TYPE_POINTER|CPL_TYPE_DOUBLE:
4117 case CPL_TYPE_POINTER|CPL_TYPE_FLOAT:
4118 case CPL_TYPE_POINTER|CPL_TYPE_INT:
4119 /* Case real array column */
4120 if (!cpl_table_has_column (out_table, name))
4121 cpl_table_new_column_array (out_table, name, CPL_TYPE_DOUBLE, depth);
4122 for (int tel = 0; tel < ntel; tel++) {
4123 cpl_size nvalid = 0;
4124 cpl_array * mean = gravi_array_init_double (depth, 0.0);
4125 for (cpl_size row = 0; row < nrow; row++) {
4126 if (flag && flag[row*ntel+tel] != 0) continue;
4127 nvalid ++;
4128 cpl_array_add (mean, cpl_table_get_array (in_table, name, row*ntel+tel));
4129 CPLCHECK_MSG ("Cannot add arrays...");
4130 }
4131 if (nvalid > 0) cpl_array_divide_scalar (mean, nvalid);
4132 cpl_table_set_array (out_table, name, tel, mean);
4133 FREE (cpl_array_delete, mean);
4134 }
4135 break;
4136
4137 case CPL_TYPE_POINTER|CPL_TYPE_DOUBLE_COMPLEX:
4138 case CPL_TYPE_POINTER|CPL_TYPE_FLOAT_COMPLEX:
4139 /* Case complex array column */
4140 if (!cpl_table_has_column (out_table, name))
4141 cpl_table_new_column_array (out_table, name, CPL_TYPE_DOUBLE_COMPLEX, depth);
4142 for (int tel = 0; tel < ntel; tel++) {
4143 cpl_size nvalid = 0;
4144 cpl_array * mean = gravi_array_init_double_complex (depth, 0.0*I+0.0);
4145 for (cpl_size row = 0; row < nrow; row++) {
4146 if (flag && flag[row*ntel+tel] != 0) continue;
4147 nvalid ++;
4148 cpl_array_add (mean, cpl_table_get_array (in_table, name, row*ntel+tel));
4149 }
4150 if (nvalid > 0) cpl_array_divide_scalar (mean, nvalid);
4151 cpl_table_set_array (out_table, name, tel, mean);
4152
4153 FREE (cpl_array_delete, mean);
4154 }
4155 break;
4156
4157 cpl_msg_error (cpl_func, "Type column not yet supported...");
4158 cpl_error_set_message (cpl_func, CPL_ERROR_ILLEGAL_INPUT,"This type is not supported.");
4159 return CPL_ERROR_ILLEGAL_INPUT;
4160 }
4161
4162 /* Copy units */
4163 cpl_table_set_column_unit (out_table, name, cpl_table_get_column_unit (in_table, name));
4164
4166 return CPL_ERROR_NONE;
4167}
4168
4169/*----------------------------------------------------------------------------*/
4181/*----------------------------------------------------------------------------*/
4182
4183cpl_error_code gravi_vis_force_time (gravi_data * oi_data)
4184{
4186 cpl_ensure_code (oi_data, CPL_ERROR_NULL_INPUT);
4187
4188 /* Number of extensions */
4189 cpl_size nb_ext = gravi_data_get_size (oi_data);
4190 cpl_ensure_code (nb_ext>0, CPL_ERROR_ILLEGAL_INPUT);
4191
4192 /* Init averaging */
4193 double mean_mjd = 0.0;
4194 double mean_time = 0.0;
4195 cpl_size count = 0;
4196
4197 /* Loop on extensions */
4198 for (int ext = 0; ext < nb_ext; ext++) {
4199
4200 /* Check if data table */
4201 const char * extname = gravi_data_get_extname (oi_data, ext);
4202 if (!strcmp (extname, "OI_VIS") || !strcmp (extname, "OI_VIS2") ||
4203 !strcmp (extname, "OI_T3") || !strcmp (extname, "OI_FLUX")) {
4204
4205 /* Average MJD and TIME */
4206 cpl_table * oi_table = gravi_data_get_table_x (oi_data, ext);
4207 mean_mjd += cpl_table_get_column_mean (oi_table, "MJD");
4208 mean_time += cpl_table_get_column_mean (oi_table, "TIME");
4209 count ++;
4210
4211 CPLCHECK_MSG ("Cannot get TIME or MJD...");
4212 }
4213 }
4214
4215 /* Compute mean */
4216 cpl_ensure_code (count>0, CPL_ERROR_ILLEGAL_INPUT);
4217 mean_mjd /= count;
4218 mean_time /= count;
4219
4220 /* Verbose */
4221 cpl_msg_info (cpl_func, "Mean MDJ = %g [mdj]", mean_mjd);
4222 cpl_msg_info (cpl_func, "Mean TIME = %g [s]", mean_time);
4223
4224 /* Loop on extensions */
4225 for (int ext = 0; ext < nb_ext; ext++) {
4226
4227 /* Check if data table */
4228 const char * extname = gravi_data_get_extname (oi_data, ext);
4229 if (!strcmp (extname, "OI_VIS") || !strcmp (extname, "OI_VIS2") ||
4230 !strcmp (extname, "OI_T3") || !strcmp (extname, "OI_FLUX")) {
4231
4232 /* Set MJD and TIME */
4233 cpl_table * oi_table = gravi_data_get_table_x (oi_data, ext);
4234 cpl_table_fill_column_window (oi_table, "MJD", 0, CPL_SIZE_MAX, mean_mjd);
4235 cpl_table_fill_column_window (oi_table, "TIME", 0, CPL_SIZE_MAX, mean_time);
4236
4237 CPLCHECK_MSG ("Cannot set average TIME or MJD...");
4238 }
4239 }
4240
4242 return CPL_ERROR_NONE;
4243}
4244
4245
#define gravi_table_set_value(table, name, row, value, val)
Definition: gravi_cpl.h:50
#define gravi_table_get_value(table, name, row, value)
Definition: gravi_cpl.h:49
typedefCPL_BEGIN_DECLS struct _gravi_data_ gravi_data
Definition: gravi_data.h:39
#define gravi_data_get_oi_t3(data, type, pol, npol)
Definition: gravi_data.h:48
#define gravi_data_get_oi_flux(data, type, pol, npol)
Definition: gravi_data.h:49
#define gravi_data_get_header(data)
Definition: gravi_data.h:75
#define gravi_data_get_oi_vis2(data, type, pol, npol)
Definition: gravi_data.h:47
#define gravi_data_get_oi_wave(data, type, pol, npol)
Definition: gravi_data.h:45
#define gravi_data_get_oi_vis_plist(data, type, pol, npol)
Definition: gravi_data.h:70
#define gravi_data_get_oi_vis(data, type, pol, npol)
Definition: gravi_data.h:46
#define gravi_data_get_extname(data, ext)
Definition: gravi_data.h:76
const cpl_size ntel
cpl_propertylist * gravi_idp_compute(gravi_data *vis_data, cpl_propertylist *header, cpl_frameset *frameset, char *input_data_type)
Create IDP keywords to satisfy standard.
Definition: gravi_idp.c:47
cpl_msg_debug(cpl_func, "Spectra has <50 pixels -> don't flat")
cpl_propertylist * header
Definition: gravi_old.c:2004
cpl_propertylist * plist
Definition: gravi_old.c:2000
cpl_msg_info(cpl_func, "Compute WAVE_SCAN for %s", GRAVI_TYPE(type_data))
cpl_propertylist_update_double(header, "ESO QC MINWAVE SC", cpl_propertylist_get_double(plist, "ESO QC MINWAVE SC"))
#define GRAVI_OI_VIS2_EXT
Definition: gravi_pfits.h:95
#define GRAVI_INSNAME(type, pol, npol)
Definition: gravi_pfits.h:198
#define GRAVI_OI_TARGET_EXT
Definition: gravi_pfits.h:86
#define GRAVI_OI_ARRAY_EXT
Definition: gravi_pfits.h:83
#define GRAVI_SC
Definition: gravi_pfits.h:165
#define GRAVI_OI_VIS_EXT
Definition: gravi_pfits.h:92
#define GRAVI_OI_FLUX_EXT
Definition: gravi_pfits.h:93
#define GRAVI_NIGHT_OBS
Definition: gravi_pfits.h:36
#define GRAVI_OI_T3_EXT
Definition: gravi_pfits.h:94
#define GRAVI_TYPE(type)
Definition: gravi_pfits.h:167
#define GRAVI_FT
Definition: gravi_pfits.h:166
#define GRAVI_OI_WAVELENGTH_EXT
Definition: gravi_pfits.h:91
#define gravi_msg_function_exit(flag)
Definition: gravi_utils.h:85
#define FREE(function, variable)
Definition: gravi_utils.h:69
#define CPLCHECK_NUL(msg)
Definition: gravi_utils.h:48
#define gravi_msg_function_start(flag)
Definition: gravi_utils.h:84
#define CPLCHECK_MSG(msg)
Definition: gravi_utils.h:45
#define gravi_pow2(data)
Definition: gravi_utils.h:81
#define FREELOOP(function, variable, n)
Definition: gravi_utils.h:72
#define GRAVI_NBASE
Definition: gravi_utils.h:105
cpl_error_code gravi_table_set_array_double_complex(cpl_table *table, const char *name, cpl_size row, cpl_array *visR, cpl_array *visI)
Definition: gravi_cpl.c:713
cpl_table * gravi_table_extract_time_interval(cpl_table *table, double start, double end)
Extract rows from table based on the TIME column.
Definition: gravi_cpl.c:3260
double gravi_table_get_column_mean(cpl_table *table, const char *name, int base, int nbase)
Definition: gravi_cpl.c:342
cpl_error_code gravi_table_new_column(cpl_table *table, const char *name, const char *unit, cpl_type type)
Definition: gravi_cpl.c:1655
cpl_error_code gravi_table_set_array_phase(cpl_table *table, const char *name, cpl_size row, cpl_array *phase)
Definition: gravi_cpl.c:737
cpl_array * gravi_array_init_double(long n, double value)
Definition: gravi_cpl.c:596
cpl_error_code gravi_array_get_group_delay_loop(cpl_array **input, cpl_array **flag, cpl_array *sigma, double *gd, cpl_size nrow, double max_width, int verbose)
Optimized computation of GDELAY for a list of arrays.
Definition: gravi_cpl.c:1402
cpl_array * gravi_table_get_column_sum_array(cpl_table *table, const char *name, int base, int nbase)
Definition: gravi_cpl.c:426
cpl_array * gravi_array_compute_norm2(cpl_array *input_re, cpl_array *input_im)
Definition: gravi_cpl.c:687
int gravi_array_threshold_min(cpl_array *array, double lo_cut)
Definition: gravi_cpl.c:71
cpl_array * gravi_array_rebin(const cpl_array *input, const cpl_array *errs, cpl_table *oi_wave_sc, cpl_table *oi_wave_ft)
Definition: gravi_cpl.c:791
cpl_array * gravi_array_init_double_complex(long n, double complex value)
Definition: gravi_cpl.c:618
cpl_array ** gravi_array_new_list(int n, cpl_type type, int size)
Allocate a list of arrays, pre-filled with 0.0.
Definition: gravi_cpl.c:93
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:1158
cpl_array * gravi_array_wrap_complex(cpl_array *input_re, cpl_array *input_im)
Definition: gravi_cpl.c:640
cpl_propertylist * gravi_data_get_extra_primary_header(gravi_data *self)
Get the propertylist for additional keywords to the primary header.
Definition: gravi_data.c:2074
gravi_data * gravi_data_new(int nb_ext)
Create an empty gravi_data.
Definition: gravi_data.c:110
cpl_error_code gravi_data_add_table(gravi_data *self, cpl_propertylist *plist, const char *extname, cpl_table *table)
Add a BINTABLE extension in gravi_data.
Definition: gravi_data.c:2289
int gravi_data_has_type(gravi_data *self, const char *type)
Return the number of ext whose EXTNAME and INSNAME match 'type'.
Definition: gravi_data.c:1833
cpl_table * gravi_data_get_table(gravi_data *self, const char *extname)
Return a pointer on a table extension by its EXTNAME.
Definition: gravi_data.c:2096
cpl_propertylist * gravi_data_get_plist_x(gravi_data *self, int i)
Get the propertylist of an extension by position.
Definition: gravi_data.c:1876
int gravi_data_get_size(const gravi_data *self)
Get the number of extension in a gravi_data.
Definition: gravi_data.c:828
cpl_error_code gravi_data_copy_ext(gravi_data *output, gravi_data *input, const char *name)
Copy extensions from one data to another.
Definition: gravi_data.c:1690
cpl_table * gravi_data_get_table_x(gravi_data *self, int i)
Get the table of an extension by position.
Definition: gravi_data.c:1901
int gravi_param_get_bool(const cpl_parameterlist *parlist, const char *name)
Definition: gravi_dfs.c:1534
const char * gravi_param_get_string(const cpl_parameterlist *parlist, const char *name)
Definition: gravi_dfs.c:1547
int gravi_param_get_int(const cpl_parameterlist *parlist, const char *name)
Definition: gravi_dfs.c:1521
double gravi_param_get_double(const cpl_parameterlist *parlist, const char *name)
Definition: gravi_dfs.c:1508
double gravi_param_get_double_default(const cpl_parameterlist *parlist, const char *name, double def)
Get the parameter from the parameter list.
Definition: gravi_dfs.c:1460
int gravi_pfits_get_pola_num(const cpl_propertylist *plist, int type_data)
Definition: gravi_pfits.c:263
const char * gravi_pfits_get_mode_name(const cpl_propertylist *plist)
Definition: gravi_pfits.c:242
double gravi_pfits_get_sobj_y(const cpl_propertylist *plist)
Definition: gravi_pfits.c:461
double gravi_pfits_get_metfc_lockmjd(const cpl_propertylist *plist, int tel)
Definition: gravi_pfits.c:295
double gravi_convert_to_mjd(const char *start)
Definition: gravi_pfits.c:1188
double gravi_pfits_get_dit_sc(const cpl_propertylist *plist)
Definition: gravi_pfits.c:664
double gravi_pfits_get_sobj_x(const cpl_propertylist *plist)
Definition: gravi_pfits.c:455
cpl_error_code gravi_apply_tf_amp(gravi_data *science, gravi_data *science_tf, gravi_data **used_tf_data, int num_tf_data, const char *extName, const char *insName, const char *ampName, const char *ampErrName, int nbase, double delta_t)
Interpolate the TF at the time of the science observation for an amplitude quantity.
Definition: gravi_tf.c:248
cpl_error_code gravi_msg_warning(const char *component, const char *msg)
Definition: gravi_utils.c:127
char GRAVI_BASE_NAME[6][3]
Definition: gravi_utils.c:57
int GRAVI_CLO_TEL[4][3]
Definition: gravi_utils.c:64
char GRAVI_CLO_NAME[4][4]
Definition: gravi_utils.c:65
cpl_table * gravi_table_oi_create(int nwave, int nrow, const char *oi_name)
Create the oi table (oi_vis, oi_vis2, oi_t3)
Definition: gravi_utils.c:153
int GRAVI_CLO_BASE[4][3]
Definition: gravi_utils.c:68
cpl_error_code gravi_vis_average_bootstrap(cpl_table *oi_vis_avg, cpl_table *oi_vis2_avg, cpl_table *oi_vis, int nboot, const char *phase_ref, int use_vFactor, int use_pFactor, int use_debiasing, double outlier_threshold)
Average the visibility of all DITs into a final, averaged value.
Definition: gravi_vis.c:915
cpl_error_code gravi_vis_resamp_amp(cpl_table *oi_table, const char *name, const char *err, cpl_size nsamp, cpl_size nwave_new)
Rebin amplitude column of OIFITS table.
Definition: gravi_vis.c:3505
cpl_error_code gravi_normalize_sc_to_ft(gravi_data *vis_data)
Align the SC visibilities on the FT visibilities.
Definition: gravi_vis.c:2616
cpl_error_code gravi_force_uncertainties(gravi_data *oi_data, const cpl_parameterlist *parlist)
Force uncertainties.
Definition: gravi_vis.c:2960
double gravi_randn(void)
Normal distribution pseudo-random generator.
Definition: gravi_vis.c:140
gravi_data * gravi_compute_vis(gravi_data *p2vmred_data, const cpl_parameterlist *parlist, cpl_size *current_frame)
The function average the individual frames of a P2VMREDUCED file into a final, single observation per...
Definition: gravi_vis.c:1675
cpl_error_code gravi_vis_fit_amp(cpl_table *oi_table, const char *name, const char *err, cpl_size maxdeg)
Smooth amp column of OIFITS table.
Definition: gravi_vis.c:3317
cpl_error_code gravi_flux_average_bootstrap(cpl_table *oi_flux_avg, cpl_table *oi_flux, int nboot, double outlier_threshold)
Average the flux of all DITs into a final, averaged value.
Definition: gravi_vis.c:274
cpl_error_code gravi_average_self_visphi(cpl_table *oi_vis_avg, cpl_table *oi_vis, cpl_array *wavenumber, const char *phase_ref, int *cmin, int *cmax, int nrange)
Compute Averaged VISPHI in the manner described, e.g., in F. Millour's thesis.
Definition: gravi_vis.c:1384
cpl_error_code gravi_vis_flag_nan(cpl_table *oi_table)
Flag samples of OIFITS table which are NAN or NULL.
Definition: gravi_vis.c:3744
cpl_error_code gravi_t3_average_bootstrap(cpl_table *oi_t3_avg, cpl_table *oi_vis, cpl_table *oi_flux, int nboot, int use_vFactor, int use_pFactor, double outlier_threshold)
Average the closure-phase of all DITs into a final, averaged value.
Definition: gravi_vis.c:510
cpl_error_code gravi_vis_smooth(gravi_data *oi_data, cpl_size nsamp_vis, cpl_size nsamp_flx, cpl_size maxdeg)
Smooth the SC table by nsamp consecutive spectral bins.
Definition: gravi_vis.c:3414
cpl_error_code gravi_vis_force_time(gravi_data *oi_data)
Force all data in OI_TABLE to have the same TIME and MJD.
Definition: gravi_vis.c:4183
cpl_error_code gravi_vis_mjd_to_time(gravi_data *vis_data)
Recompute the TIME column of all OIFITS extension from the MJD column, following the OIFITS standard ...
Definition: gravi_vis.c:2702
cpl_error_code gravi_vis_compute_column_mean(cpl_table *out_table, cpl_table *in_table, const char *name, int ntel)
Compute the mean of a column in OIFITS table, and save the result in the specified output table.
Definition: gravi_vis.c:4063
cpl_error_code gravi_vis_average_phi(cpl_table *oi_table, const char *name, const char *err, int nbase)
Average phases column of a multi-observation OIFITS table Phases are averaged with arg{<exp(i....
Definition: gravi_vis.c:2867
double gdAbacusErrPhi(double x)
Definition: gravi_vis.c:1315
cpl_error_code gravi_vis_smooth_phi(cpl_table *oi_table, const char *name, const char *err, cpl_size nsamp)
Smooth phase column of OIFITS table.
Definition: gravi_vis.c:3235
cpl_error_code gravi_vis_average_amp(cpl_table *oi_table, const char *name, const char *err, int nbase)
Average amplitudes column of a multi-observation OIFITS table The averaged quantities are stored in t...
Definition: gravi_vis.c:2806
cpl_error_code gravi_vis_copy_fluxdata(gravi_data *oi_data, int delete_flux)
Duplicate the column FLUX into FLUXDATA, for OIFITS2 compliance.
Definition: gravi_vis.c:3695
cpl_error_code gravi_vis_resamp(gravi_data *oi_data, cpl_size nsamp)
Re-bin the SC table by nsamp consecutive spectral bins.
Definition: gravi_vis.c:3598
cpl_error_code gravi_vis_resamp_phi(cpl_table *oi_table, const char *name, const char *err, cpl_size nsamp, cpl_size nwave_new)
Rebin phase column of OIFITS table (arg{<exp(i.phi)>})
Definition: gravi_vis.c:3551
cpl_error_code gravi_compute_vis_qc(gravi_data *vis_data, cpl_frameset *frameset, cpl_propertylist **frame_qcs, cpl_size nb_frame, char *input_data_type)
Compute the QC parameters for a VIS (averaged) data.
Definition: gravi_vis.c:2237
cpl_error_code gravi_data_get_minmax_uvcoord(const cpl_table *oi_vis2, double *min_uvcoord, double *max_uvcoord)
Compute the minimum and maximum values of sqrt(ucoord**2 + vcoord**2)
Definition: gravi_vis.c:2561
cpl_error_code gravi_array_online_variance(cpl_array *data, cpl_array *mean, cpl_array *variance, int n)
Definition: gravi_vis.c:161
cpl_error_code gravi_flat_flux(gravi_data *vis_data, gravi_data *p2vm_map)
Divide the OI_FLUX by OI_FLUX from the P2VM (no checks, no time distance...)
Definition: gravi_vis.c:2756
cpl_error_code gravi_array_online_variance_res(cpl_array **data, int n, int rephase)
On-line variance of arrays.
Definition: gravi_vis.c:221
cpl_error_code gravi_vis_flag_threshold(cpl_table *oi_table, const char *data, const char *flag, double value)
Flag samples of OIFITS table based on absolute threshold.
Definition: gravi_vis.c:3813
cpl_error_code gravi_vis_flag_relative_threshold(cpl_table *oi_table, const char *err, const char *data, const char *flag, double value)
Flag samples of OIFITS table based on relative threshold.
Definition: gravi_vis.c:3965
cpl_error_code gravi_vis_flag_lower(cpl_table *oi_table, const char *data, const char *flag, double value)
Flag samples of OIFITS table based on absolute threshold.
Definition: gravi_vis.c:3859
cpl_error_code gravi_average_vis(gravi_data *oi_data)
Coadd the observations together.
Definition: gravi_vis.c:3050
cpl_error_code gravi_vis_flag_median(cpl_table *oi_table, const char *data, const char *flag, double value)
Flag samples of OIFITS table based on runnning median.
Definition: gravi_vis.c:3905
cpl_error_code gravi_vis_smooth_amp(cpl_table *oi_table, const char *name, const char *err, cpl_size nsamp)
Smooth amplitude column of OIFITS table.
Definition: gravi_vis.c:3154
cpl_error_code gravi_vis_average_value(cpl_table *oi_table, const char *name, const char *err, int nbase)
Average scalar column of a multi-observation OIFITS table. The averaged quantities are stored in the ...
Definition: gravi_vis.c:2923
cpl_error_code gravi_vis_erase_obs(cpl_table *oi_table, cpl_array *flag_array, cpl_size ntel)
Erase observation from an OIFITS table.
Definition: gravi_vis.c:4015