GRAVI Pipeline Reference Manual  1.2.3
gravi_cpl.c
1 /* $Id: gravi_cpl.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 
31 /*-----------------------------------------------------------------------------
32  Includes
33  -----------------------------------------------------------------------------*/
34 
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38 
39 #include <cpl.h>
40 #include <string.h>
41 #include <stdio.h>
42 #include <math.h>
43 #include <time.h>
44 #include <complex.h>
45 
46 #include "gravi_data.h"
47 #include "gravi_dfs.h"
48 #include "gravi_pfits.h"
49 #include "gravi_cpl.h"
50 
51 #include "gravi_utils.h"
52 
53 #include "gravi_calib.h"
54 #include "gravi_vis.h"
55 #include "gravi_tf.h"
56 #include "gravi_eop.h"
57 
58 /*-----------------------------------------------------------------------------
59  Private prototypes
60  -----------------------------------------------------------------------------*/
61 
62 double pythag(double , double );
63 
64 cpl_matrix * svdcmp(cpl_matrix * , cpl_vector * , cpl_matrix * );
65 
66 /*-----------------------------------------------------------------------------
67  Functions code
68  -----------------------------------------------------------------------------*/
69 
70 
71 int gravi_array_threshold_min (cpl_array * array, double lo_cut,
72  double assign_lo_cut)
73 {
74  cpl_ensure (array, CPL_ERROR_NULL_INPUT, -1);
75 
76  cpl_size size = cpl_array_get_size (array);
77  cpl_size num = 0;
78 
79  for (cpl_size s = 0; s < size ; s++) {
80  if (cpl_array_get (array, s, NULL) < lo_cut) {
81  cpl_array_set (array, s, assign_lo_cut);
82  num ++;
83  }
84  }
85 
86  return num;
87 }
88 
89 
94 cpl_array ** gravi_array_new_list (int n, cpl_type type, int size)
95 {
96  cpl_ensure (n>0, CPL_ERROR_ILLEGAL_INPUT, NULL);
97  cpl_ensure (size>0, CPL_ERROR_ILLEGAL_INPUT, NULL);
98 
99  cpl_array ** output;
100  output = cpl_malloc (n * sizeof(cpl_array *));
101 
102  int out1;
103  if ( type == CPL_TYPE_DOUBLE )
104  for ( out1 = 0 ; out1 < n ; out1++ ) {
105  output[out1] = cpl_array_new (size, type);
106  cpl_array_fill_window_double (output[out1], 0, size, 0.0);
107  }
108  else if ( type == CPL_TYPE_DOUBLE_COMPLEX )
109  for ( out1 = 0 ; out1 < n ; out1++ ) {
110  output[out1] = cpl_array_new (size, type);
111  cpl_array_fill_window_double_complex (output[out1], 0, size, 0.0 * I*0.0);
112  }
113  else {
114  cpl_error_set_message (cpl_func,CPL_ERROR_ILLEGAL_INPUT,"This type is not supported.");
115  FREE (cpl_free, output);
116  return NULL;
117  }
118 
119  return output;
120 }
121 
122 cpl_error_code gravi_table_interpolate_column (cpl_table * to_table,
123  const char * to_x,
124  const char * to_y,
125  const cpl_table * from_table,
126  const char * from_x,
127  const char * from_y)
128 {
129  gravi_msg_function_start(1);
130  cpl_ensure_code (to_table, CPL_ERROR_NULL_INPUT);
131  cpl_ensure_code (to_x, CPL_ERROR_NULL_INPUT);
132  cpl_ensure_code (to_y, CPL_ERROR_NULL_INPUT);
133  cpl_ensure_code (from_table, CPL_ERROR_NULL_INPUT);
134  cpl_ensure_code (from_x, CPL_ERROR_NULL_INPUT);
135  cpl_ensure_code (from_y, CPL_ERROR_NULL_INPUT);
136 
137  /* Size */
138  cpl_size nxref = cpl_table_get_nrow (from_table);
139  cpl_size nxout = cpl_table_get_nrow (to_table);
140 
141  /* Xref vectors */
142  cpl_vector * xref = cpl_vector_new (nxref);
143  for (cpl_size row = 0; row < nxref; row++) {
144  cpl_vector_set (xref, row, cpl_table_get (from_table, from_x, row, NULL));
145  CPLCHECK_MSG ("Cannot get x data");
146  }
147 
148  /* Xout vectors */
149  cpl_vector * xout = cpl_vector_new (nxout);
150  for (cpl_size row = 0; row < nxout; row++) {
151  cpl_vector_set (xout, row, cpl_table_get (to_table, to_x, row, NULL));
152  CPLCHECK_MSG ("Cannot get x data");
153  }
154 
155  /* Allocate memory for the interpolation */
156  cpl_vector * yref = cpl_vector_new (nxref);
157  cpl_vector * yout = cpl_vector_new (nxout);
158  cpl_bivector * fref = cpl_bivector_wrap_vectors (xref, yref);
159  cpl_bivector * fout = cpl_bivector_wrap_vectors (xout, yout);
160 
161  /* Shall be a column of array */
162  cpl_size depth = cpl_table_get_column_depth (from_table, from_y);
163  if (depth == 0)
164  cpl_error_set_message (cpl_func,CPL_ERROR_INVALID_TYPE ,
165  "Report this error to gravity.drs");
166 
167  /* Output is of type DOUBLE */
168  const char * unit = cpl_table_get_column_unit (from_table, from_y);
169  gravi_table_init_column_array (to_table, to_y, unit, CPL_TYPE_DOUBLE, depth);
170 
171  /* Loop on column depth */
172  for (cpl_size size = 0; size < depth; size++) {
173 
174  /* Yref vector */
175  for (cpl_size row = 0; row < nxref; row++) {
176  double value = gravi_table_get_value (from_table, from_y, row, size);
177  cpl_vector_set (yref, row, value);
178  CPLCHECK_MSG ("Cannot get y data");
179  }
180 
181  /* Interpolate linear */
182  cpl_bivector_interpolate_linear (fout, fref);
183  CPLCHECK_MSG ("Cannot interpolate");
184 
185  /* fill Yout */
186  for (cpl_size row = 0; row < nxout; row++) {
187  double value = cpl_vector_get (yout, row);
188  gravi_table_set_value (to_table, to_y, row, size, value);
189  CPLCHECK_MSG ("Cannot set y data");
190  }
191 
192  } /* End loop on column depth */
193 
194  /* Free memory */
195  FREE (cpl_bivector_delete, fref);
196  FREE (cpl_bivector_delete, fout);
197 
198  gravi_msg_function_exit(1);
199  return CPL_ERROR_NONE;
200 }
201 
202 double gravi_table_get_column_mean (cpl_table * table, const char * name, int base, int nbase)
203 {
204  cpl_ensure (table, CPL_ERROR_NULL_INPUT, 0.0);
205  cpl_ensure (name, CPL_ERROR_NULL_INPUT, 0.0);
206 
207  double mean = 0.0;
208  cpl_size nrow = cpl_table_get_nrow (table) / nbase;
209  cpl_ensure (nrow, CPL_ERROR_ILLEGAL_INPUT, 0.0);
210 
211  cpl_type type = cpl_table_get_column_type (table, name);
212  cpl_size depth = cpl_table_get_column_depth (table, name);
213 
214  if (depth == 0 && type == CPL_TYPE_DOUBLE) {
215  double * data = cpl_table_get_data_double (table, name);
216  cpl_ensure (data, CPL_ERROR_ILLEGAL_INPUT, 0.0);
217  for (cpl_size r=0; r<nrow;r++) mean += data[r*nbase+base];
218  }
219  else if (depth == 0 && type == CPL_TYPE_FLOAT) {
220  float * data = cpl_table_get_data_float (table, name);
221  cpl_ensure (data, CPL_ERROR_ILLEGAL_INPUT, 0.0);
222  for (cpl_size r=0; r<nrow;r++) mean += data[r*nbase+base];
223  }
224  else if (depth == 0 && type == CPL_TYPE_INT) {
225  int * data = cpl_table_get_data_int (table, name);
226  cpl_ensure (data, CPL_ERROR_ILLEGAL_INPUT, 0.0);
227  for (cpl_size r=0; r<nrow;r++) mean += data[r*nbase+base];
228  }
229  else if (depth > 0) {
230  cpl_array ** arrays = cpl_table_get_data_array (table, name);
231  cpl_ensure (arrays, CPL_ERROR_ILLEGAL_INPUT, 0.0);
232  cpl_array * output = cpl_array_duplicate (arrays[base]);
233  cpl_ensure (output, CPL_ERROR_ILLEGAL_INPUT, 0.0);
234  for (cpl_size r=1; r<nrow;r++)
235  cpl_array_add (output, arrays[r*nbase+base]);
236  mean = cpl_array_get_mean (output) / nrow;
237  FREE (cpl_array_delete, output);
238  }
239  else {
240  cpl_error_set_message (cpl_func,CPL_ERROR_ILLEGAL_INPUT,"unknow type");
241  return 0.0;
242  }
243 
244  return mean / nrow;
245 }
246 
247 double gravi_table_get_column_std (cpl_table * table, const char * name, int base, int nbase)
248 {
249  cpl_ensure (table, CPL_ERROR_NULL_INPUT, 0.0);
250  cpl_ensure (name, CPL_ERROR_NULL_INPUT, 0.0);
251 
252  double mean = 0.0;
253  double mean2 = 0.0;
254  cpl_size nrow = cpl_table_get_nrow (table) / nbase;
255  cpl_ensure (nrow, CPL_ERROR_ILLEGAL_INPUT, 0.0);
256 
257  cpl_type type = cpl_table_get_column_type (table, name);
258  cpl_size depth = cpl_table_get_column_depth (table, name);
259 
260  if (depth == 0 && type == CPL_TYPE_DOUBLE) {
261  double * data = cpl_table_get_data_double (table, name);
262  cpl_ensure (data, CPL_ERROR_ILLEGAL_INPUT, 0.0);
263  for (cpl_size r=0; r<nrow;r++) mean += data[r*nbase+base];
264  for (cpl_size r=0; r<nrow;r++) mean2 += data[r*nbase+base] * data[r*nbase+base];
265  }
266  else if (depth == 0 && type == CPL_TYPE_FLOAT) {
267  float * data = cpl_table_get_data_float (table, name);
268  cpl_ensure (data, CPL_ERROR_ILLEGAL_INPUT, 0.0);
269  for (cpl_size r=0; r<nrow;r++) mean += data[r*nbase+base];
270  for (cpl_size r=0; r<nrow;r++) mean2 += data[r*nbase+base] * data[r*nbase+base];
271  }
272  else if (depth == 0 && type == CPL_TYPE_INT) {
273  int * data = cpl_table_get_data_int (table, name);
274  cpl_ensure (data, CPL_ERROR_ILLEGAL_INPUT, 0.0);
275  for (cpl_size r=0; r<nrow;r++) mean += data[r*nbase+base];
276  for (cpl_size r=0; r<nrow;r++) mean2 += data[r*nbase+base] * data[r*nbase+base];
277  }
278  else {
279  cpl_error_set_message (cpl_func,CPL_ERROR_ILLEGAL_INPUT,"unknow type");
280  return 0.0;
281  }
282 
283  return sqrt (mean2 / nrow - mean*mean / nrow / nrow);
284 }
285 
286 
287 cpl_array * gravi_table_get_column_mean_array (cpl_table * table, const char * name, int base, int nbase)
288 {
289  cpl_ensure (table, CPL_ERROR_NULL_INPUT, NULL);
290  cpl_ensure (name, CPL_ERROR_NULL_INPUT, NULL);
291 
292  cpl_size nrow = cpl_table_get_nrow (table) / nbase;
293  cpl_ensure (nrow, CPL_ERROR_ILLEGAL_INPUT, NULL);
294 
295  /* Get the pointer */
296  cpl_array ** arrays = cpl_table_get_data_array (table, name);
297  cpl_ensure (arrays, CPL_ERROR_ILLEGAL_INPUT, NULL);
298 
299  /* Build the mean */
300  cpl_array * output = cpl_array_duplicate (arrays[base]);
301  for (cpl_size r=1; r<nrow;r++)
302  cpl_array_add (output, arrays[r*nbase+base]);
303 
304  cpl_array_divide_scalar (output, nrow);
305  return output;
306 }
307 
308 
309 double ** gravi_table_get_data_array_double(cpl_table * table, const char * name)
310 {
311  cpl_ensure (table, CPL_ERROR_NULL_INPUT, NULL);
312  cpl_ensure (name, CPL_ERROR_NULL_INPUT, NULL);
313 
314  cpl_size nrow = cpl_table_get_nrow (table);
315  cpl_array ** pdata = cpl_table_get_data_array (table, name);
316 
317  cpl_ensure (nrow, CPL_ERROR_ILLEGAL_INPUT, NULL);
318  cpl_ensure (pdata, CPL_ERROR_ILLEGAL_INPUT, NULL);
319 
320  /* Allocate memory, this will have to be desalocated */
321  double ** data = cpl_malloc (sizeof(double*) * nrow);
322 
323  /* Get all the pointers */
324  for (cpl_size row=0; row<nrow; row++) {
325  data[row] = cpl_array_get_data_double (pdata[row]);
326  }
327 
328  CPLCHECK_NUL("Cannot load the requested arrays");
329 
330  return data;
331 }
332 
333 float ** gravi_table_get_data_array_float(cpl_table * table, const char * name)
334 {
335  cpl_ensure (table, CPL_ERROR_NULL_INPUT, NULL);
336  cpl_ensure (name, CPL_ERROR_NULL_INPUT, NULL);
337 
338  cpl_size nrow = cpl_table_get_nrow (table);
339  cpl_array ** pdata = cpl_table_get_data_array (table, name);
340 
341  cpl_ensure (nrow, CPL_ERROR_ILLEGAL_INPUT, NULL);
342  cpl_ensure (pdata, CPL_ERROR_ILLEGAL_INPUT, NULL);
343 
344  /* Allocate memory, this will have to be desalocated */
345  float ** data = cpl_malloc (sizeof(float*) * nrow);
346 
347  /* Get all the pointers */
348  for (cpl_size row=0; row<nrow; row++) {
349  data[row] = cpl_array_get_data_float (pdata[row]);
350  }
351 
352  CPLCHECK_NUL("Cannot load the requested arrays");
353 
354  return data;
355 }
356 
357 float complex ** gravi_table_get_data_array_float_complex (cpl_table * table, const char * name)
358 {
359  cpl_ensure (table, CPL_ERROR_NULL_INPUT, NULL);
360  cpl_ensure (name, CPL_ERROR_NULL_INPUT, NULL);
361 
362  cpl_size nrow = cpl_table_get_nrow (table);
363  cpl_array ** pdata = cpl_table_get_data_array (table, name);
364 
365  cpl_ensure (nrow, CPL_ERROR_ILLEGAL_INPUT, NULL);
366  cpl_ensure (pdata, CPL_ERROR_ILLEGAL_INPUT, NULL);
367 
368  /* Allocate memory, this will have to be desalocated */
369  float complex ** data = cpl_malloc (sizeof(float complex*) * nrow);
370 
371  /* Get all the pointers */
372  for (cpl_size row=0; row<nrow; row++) {
373  data[row] = cpl_array_get_data_float_complex (pdata[row]);
374  }
375 
376  CPLCHECK_NUL ("Cannot load the requested arrays");
377 
378  return data;
379 }
380 
381 
382 double complex ** gravi_table_get_data_array_double_complex (cpl_table * table, const char * name)
383 {
384  cpl_ensure (table, CPL_ERROR_NULL_INPUT, NULL);
385  cpl_ensure (name, CPL_ERROR_NULL_INPUT, NULL);
386 
387  cpl_size nrow = cpl_table_get_nrow (table);
388  cpl_array ** pdata = cpl_table_get_data_array (table, name);
389 
390  cpl_ensure (nrow, CPL_ERROR_ILLEGAL_INPUT, NULL);
391  cpl_ensure (pdata, CPL_ERROR_ILLEGAL_INPUT, NULL);
392 
393  /* Allocate memory, this will have to be desalocated */
394  double complex ** data = cpl_malloc (sizeof(double complex*) * nrow);
395 
396  /* Get all the pointers */
397  for (cpl_size row=0; row<nrow; row++) {
398  data[row] = cpl_array_get_data_double_complex (pdata[row]);
399  }
400 
401  CPLCHECK_NUL ("Cannot load the requested arrays");
402 
403  return data;
404 }
405 
406 int ** gravi_table_get_data_array_int(cpl_table * table, const char * name)
407 {
408  cpl_ensure (table, CPL_ERROR_NULL_INPUT, NULL);
409  cpl_ensure (name, CPL_ERROR_NULL_INPUT, NULL);
410 
411  cpl_size nrow = cpl_table_get_nrow (table);
412  cpl_array ** pdata = cpl_table_get_data_array (table, name);
413 
414  cpl_ensure (nrow, CPL_ERROR_ILLEGAL_INPUT, NULL);
415  cpl_ensure (pdata, CPL_ERROR_ILLEGAL_INPUT, NULL);
416 
417  /* Allocate memory, this will have to be desalocated */
418  int ** data = cpl_malloc (sizeof(int*) * nrow);
419 
420  /* Get all the pointers */
421  for (cpl_size row=0; row<nrow; row++) {
422  data[row] = cpl_array_get_data_int (pdata[row]);
423  }
424 
425  CPLCHECK_NUL("Cannot load the requested arrays");
426 
427  return data;
428 }
429 
430 /*
431  * Define and init an array of DOUBLE
432  */
433 cpl_array * gravi_array_init_double (long n , double value)
434 {
435  cpl_ensure (n>0, CPL_ERROR_ILLEGAL_INPUT, NULL);
436  cpl_array * output = cpl_array_new (n, CPL_TYPE_DOUBLE);
437  cpl_array_fill_window_double (output, 0, n, value);
438  return output;
439 }
440 
441 /*
442  * Define and init an array of INT
443  */
444 cpl_array * gravi_array_init_int (long n, int value)
445 {
446  cpl_ensure (n>0, CPL_ERROR_ILLEGAL_INPUT, NULL);
447  cpl_array * output = cpl_array_new (n, CPL_TYPE_INT);
448  cpl_array_fill_window_int (output, 0, n, value);
449  return output;
450 }
451 
452 /*
453  * Define and init an array of DOUBLE COMPLEX
454  */
455 cpl_array * gravi_array_init_double_complex (long n, double complex value)
456 {
457  cpl_ensure (n>0, CPL_ERROR_ILLEGAL_INPUT, NULL);
458  cpl_array * output = cpl_array_new (n, CPL_TYPE_DOUBLE_COMPLEX);
459  cpl_array_fill_window_double_complex (output, 0, n, value);
460  return output;
461 }
462 
463 /*
464  * Define and init an array of FLOAT COMPLEX
465  */
466 cpl_array * gravi_array_init_float_complex (long n, float complex value)
467 {
468  cpl_ensure (n>0, CPL_ERROR_ILLEGAL_INPUT, NULL);
469  cpl_array * output = cpl_array_new (n, CPL_TYPE_FLOAT_COMPLEX);
470  cpl_array_fill_window_float_complex (output, 0, n, value);
471  return output;
472 }
473 
474 /*
475  * Compute a new DOUBLE COMPLEX array filled with: input_re + i * input_im
476  */
477 cpl_array * gravi_array_wrap_complex (cpl_array * input_re, cpl_array * input_im)
478 {
479  cpl_ensure (input_re, CPL_ERROR_NULL_INPUT, NULL);
480  cpl_ensure (input_im, CPL_ERROR_NULL_INPUT, NULL);
481 
482  cpl_size size_re = cpl_array_get_size (input_re);
483  cpl_size size_im = cpl_array_get_size (input_im);
484 
485  cpl_ensure (size_re == size_im, CPL_ERROR_ILLEGAL_INPUT, NULL);
486 
487  cpl_array * output = cpl_array_new (size_re, CPL_TYPE_DOUBLE_COMPLEX);
488 
489  for (cpl_size n = 0; n < size_re; n ++) {
490  cpl_array_set_complex (output, n, 1.* I * cpl_array_get (input_im, n, NULL) +
491  cpl_array_get (input_re, n, NULL));
492  }
493 
494  return output;
495 }
496 
497 /*
498  * Compute a new FLOAT COMPLEX array filled with: input_re + i * input_im
499  */
500 cpl_array * gravi_array_wrap_float_complex (cpl_array * input_re, cpl_array * input_im)
501 {
502  cpl_ensure (input_re, CPL_ERROR_NULL_INPUT, NULL);
503  cpl_ensure (input_im, CPL_ERROR_NULL_INPUT, NULL);
504 
505  cpl_size size_re = cpl_array_get_size (input_re);
506  cpl_size size_im = cpl_array_get_size (input_im);
507 
508  cpl_ensure (size_re == size_im, CPL_ERROR_ILLEGAL_INPUT, NULL);
509 
510  cpl_array * output = cpl_array_new (size_re, CPL_TYPE_FLOAT_COMPLEX);
511 
512  int nv = 0.0;
513  for (cpl_size n = 0; n < size_re; n ++) {
514  cpl_array_set_float_complex (output, n, 1.* I * cpl_array_get (input_im, n, &nv) +
515  cpl_array_get (input_re, n, &nv));
516  }
517 
518  return output;
519 }
520 
521 /*
522  * Compute a new DOUBLE array filled with: input_re^2 + input_im^2
523  */
524 cpl_array * gravi_array_compute_norm2 (cpl_array * input_re, cpl_array * input_im)
525 {
526  cpl_ensure (input_re, CPL_ERROR_NULL_INPUT, NULL);
527  cpl_ensure (input_im, CPL_ERROR_NULL_INPUT, NULL);
528 
529  cpl_size size_re = cpl_array_get_size (input_re);
530  cpl_size size_im = cpl_array_get_size (input_im);
531 
532  cpl_ensure (size_re == size_im, CPL_ERROR_ILLEGAL_INPUT, NULL);
533 
534  cpl_array * output = cpl_array_new (size_re, CPL_TYPE_DOUBLE);
535  cpl_array_fill_window_double (output, 0, size_re, 0.0);
536 
537  int nv = 0.0;
538  for (cpl_size n = 0; n < size_re; n ++) {
539  cpl_array_set_double (output, n, pow(cpl_array_get (input_im, n, &nv),2) +
540  pow(cpl_array_get (input_re, n, &nv),2) );
541  }
542 
543  return output;
544 }
545 
546 /*
547  * Set an pair of arrays as the real and imaginary part of
548  * a FLOAT COMPLEX array into the table. Data are copied.
549  */
550 cpl_error_code gravi_table_set_array_double_complex (cpl_table * table,
551  const char * name,
552  cpl_size row,
553  cpl_array * visR,
554  cpl_array * visI)
555 {
556  cpl_ensure_code (table, CPL_ERROR_NULL_INPUT);
557  cpl_ensure_code (name, CPL_ERROR_NULL_INPUT);
558  cpl_ensure_code (visR, CPL_ERROR_NULL_INPUT);
559  cpl_ensure_code (visI, CPL_ERROR_NULL_INPUT);
560 
561  cpl_array * tmp_cast = gravi_array_wrap_complex (visR, visI);
562  cpl_table_set_array (table, name, row, tmp_cast);
563  cpl_array_delete (tmp_cast);
564 
565  CPLCHECK_MSG("Cannot set float_complex array");
566 
567  return CPL_ERROR_NONE;
568 }
569 
570 /*
571  * Set an array in radian into an table and convert it in DOUBLE
572  * with units [deg]
573  */
574 cpl_error_code gravi_table_set_array_phase (cpl_table * table, const char * name, cpl_size row, cpl_array * phase)
575 {
576  cpl_ensure_code (table, CPL_ERROR_NULL_INPUT);
577  cpl_ensure_code (name, CPL_ERROR_NULL_INPUT);
578  cpl_ensure_code (phase, CPL_ERROR_NULL_INPUT);
579 
580  cpl_array * tmp_cast;
581  if (cpl_array_get_type (phase) == CPL_TYPE_FLOAT_COMPLEX ||
582  cpl_array_get_type (phase) == CPL_TYPE_DOUBLE_COMPLEX ) {
583  tmp_cast = cpl_array_cast (phase, CPL_TYPE_DOUBLE_COMPLEX);
584  cpl_array_arg (tmp_cast);
585  } else
586  tmp_cast = cpl_array_cast (phase, CPL_TYPE_DOUBLE);
587 
588  cpl_array_multiply_scalar (tmp_cast, 180.0/ CPL_MATH_PI);
589  cpl_table_set_array (table, name, row, tmp_cast);
590  cpl_array_delete (tmp_cast);
591 
592  CPLCHECK_MSG("Cannot set phase array");
593 
594  return CPL_ERROR_NONE;
595 }
596 
597 /*----------------------------------------------------------------------------*/
604 /*----------------------------------------------------------------------------*/
605 cpl_error_code gravi_table_set_string_fixlen (cpl_table *table, const char *name, int row, const char *value, int len)
606 {
607  gravi_msg_function_start(0);
608  cpl_ensure_code (table, CPL_ERROR_NULL_INPUT);
609  cpl_ensure_code (name, CPL_ERROR_NULL_INPUT);
610  cpl_ensure_code (row>-1, CPL_ERROR_ILLEGAL_INPUT);
611  cpl_ensure_code (len>0, CPL_ERROR_ILLEGAL_INPUT);
612 
613  char * str = cpl_sprintf ("%-*.*s", len, len, value);
614  cpl_table_set_string (table, name, row, str);
615 
616  FREE (cpl_free, str);
617  CPLCHECK_MSG("Cannot set string");
618 
619  gravi_msg_function_exit(0);
620  return CPL_ERROR_NONE;
621 }
622 
623 /*
624  * Rebin a cpl_array from the SC wavelength table to the FT wavelength table
625  * For each FT bin, average all elements found in lbdEff+/-lbdBand/2
626  * The output array is created, the input array is not modified.
627  */
628 cpl_array * gravi_array_rebin (const cpl_array * input, const cpl_array * errs,
629  cpl_table * oi_wave_sc, cpl_table * oi_wave_ft)
630 {
631  gravi_msg_function_start(0);
632  cpl_ensure (input, CPL_ERROR_NULL_INPUT, NULL);
633  cpl_ensure (errs, CPL_ERROR_NULL_INPUT, NULL);
634  cpl_ensure (oi_wave_sc, CPL_ERROR_NULL_INPUT, NULL);
635  cpl_ensure (oi_wave_ft, CPL_ERROR_NULL_INPUT, NULL);
636 
637  /* Get the eff_wave and eff_band of the FT */
638  float *effWave_sc = cpl_table_get_data_float (oi_wave_sc, "EFF_WAVE");
639  float *effWave_ft = cpl_table_get_data_float (oi_wave_ft, "EFF_WAVE");
640  float *effBand_ft = cpl_table_get_data_float (oi_wave_ft, "EFF_BAND");
641  cpl_size nwave_ft = cpl_table_get_nrow (oi_wave_ft);
642  cpl_size nwave_sc = cpl_table_get_nrow (oi_wave_sc);
643 
644  CPLCHECK_NUL ("Cannot get data");
645 
646  cpl_array * output = cpl_array_new (nwave_ft, CPL_TYPE_DOUBLE);
647  cpl_array * weight = cpl_array_new (nwave_ft, CPL_TYPE_DOUBLE);
648 
649  /* Built the SC data at the spectral resolution of the FT (vis2_sc_lr) */
650  for (cpl_size wft = 0; wft < nwave_ft; wft++) {
651  for (cpl_size wsc = 0; wsc < nwave_sc; wsc++)
652  if ( fabs (effWave_sc[wsc] - effWave_ft[wft]) < 0.5 * effBand_ft[wft] ) {
653 
654  double v = cpl_array_get (input, wsc, NULL);
655  double w = cpl_array_get (errs, wsc, NULL);
656 
657  w = (w!=0?1./w:1.0);
658  cpl_array_set (output, wft, cpl_array_get (output, wft, NULL) + v * w);
659  cpl_array_set (weight, wft, cpl_array_get (weight, wft, NULL) + w);
660 
661  CPLCHECK_NUL("Cannot reduce the spectral resolution");
662  }
663  }
664 
665  cpl_array_divide (output, weight);
666  cpl_array_delete (weight);
667  gravi_msg_function_exit(0);
668  return output;
669 }
670 
671 
672 /*
673  * Add two columns from differents tables, without duplicating the data.
674  * Use cpl_table_add_columns for columns in the same table.
675  */
676 cpl_error_code gravi_table_add_columns (cpl_table * oi_vis1, const char *name1,
677  cpl_table * oi_vis2, const char *name2)
678 {
679  gravi_msg_function_start(0);
680  cpl_ensure_code (oi_vis1, CPL_ERROR_NULL_INPUT);
681  cpl_ensure_code (oi_vis2, CPL_ERROR_NULL_INPUT);
682  cpl_ensure_code (name1, CPL_ERROR_NULL_INPUT);
683  cpl_ensure_code (name2, CPL_ERROR_NULL_INPUT);
684 
685  int row;
686  cpl_msg_debug (cpl_func, "Colname (%s + %s) ",name1,name2);
687 
688  cpl_type type1 = cpl_table_get_column_type (oi_vis1, name1);
689  cpl_type type2 = cpl_table_get_column_type (oi_vis2, name2);
690  cpl_size nrow1 = cpl_table_get_nrow (oi_vis1);
691  cpl_size nrow2 = cpl_table_get_nrow (oi_vis2);
692  CPLCHECK_MSG("Cannot get type or nrow");
693 
694  if ( type1 != type2 || nrow1 != nrow2) {
695  return cpl_error_set_message (cpl_func,CPL_ERROR_ILLEGAL_INPUT,
696  "input columns not conformables");
697  }
698 
699  if ( type1 == CPL_TYPE_DOUBLE ) {
700  double * data1 = cpl_table_get_data_double (oi_vis1, name1);
701  double * data2 = cpl_table_get_data_double (oi_vis2, name2);
702  CPLCHECK_MSG("Cannot load data");
703 
704  for (row=0 ; row<nrow1 ; row++) data1[row] += data2[row];
705  }
706  else if ( type1 == CPL_TYPE_FLOAT_COMPLEX ) {
707  float complex * data1 = cpl_table_get_data_float_complex (oi_vis1, name1);
708  float complex * data2 = cpl_table_get_data_float_complex (oi_vis2, name2);
709  CPLCHECK_MSG("Cannot load data");
710 
711  for (row=0 ; row<nrow1; row++) data1[row] += data2[row];
712  }
713  else if ( type1 == CPL_TYPE_DOUBLE_COMPLEX ) {
714  double complex * data1 = cpl_table_get_data_double_complex (oi_vis1, name1);
715  double complex * data2 = cpl_table_get_data_double_complex (oi_vis2, name2);
716  CPLCHECK_MSG("Cannot load data");
717 
718  for (row=0 ; row<nrow1; row++) data1[row] += data2[row];
719  }
720  else if ( type1 & CPL_TYPE_POINTER ) {
721  cpl_array ** data1 = cpl_table_get_data_array (oi_vis1, name1);
722  cpl_array ** data2 = cpl_table_get_data_array (oi_vis2, name2);
723  CPLCHECK_MSG("Cannot load data");
724 
725  for (row=0 ; row<nrow1; row++) {
726  cpl_array_add (data1[row], data2[row]);
727  CPLCHECK_MSG("Cannot add data");
728  }
729  } else {
730  return cpl_error_set_message (cpl_func,CPL_ERROR_ILLEGAL_INPUT,
731  "unknow type -- report to DRS team");
732  }
733  /* End case */
734 
735  gravi_msg_function_exit(0);
736  return CPL_ERROR_NONE;
737 }
738 
739 
740 
741 /*
742  * Smooth column input_name with a box card of length 2*nsmooth+1
743  * Note that this is a running SUM, not a running MEAN.
744  * It integrated 2 x nsmooth + 1 running samples
745  * FIXME: check this running sum near the limits
746  */
747 cpl_error_code gravi_table_runint_column (cpl_table * oi_vis,
748  const char *input_name,
749  const char *output_name,
750  int nsmooth, int nbase)
751 {
752  gravi_msg_function_start(0);
753  cpl_ensure_code (oi_vis, CPL_ERROR_NULL_INPUT);
754  cpl_ensure_code (input_name, CPL_ERROR_NULL_INPUT);
755  cpl_ensure_code (output_name, CPL_ERROR_NULL_INPUT);
756  cpl_ensure_code (nsmooth>=0, CPL_ERROR_ILLEGAL_INPUT);
757  cpl_ensure_code (nbase>0, CPL_ERROR_ILLEGAL_INPUT);
758 
759  int row, base;
760  int row_add, row_sub;
761 
762  cpl_type type = cpl_table_get_column_type (oi_vis, input_name);
763  cpl_size nrow = cpl_table_get_nrow (oi_vis) / nbase;
764 
765  if ( type == CPL_TYPE_DOUBLE ) {
766  double * data = cpl_table_get_data_double (oi_vis, input_name);
767  double * output = cpl_malloc (sizeof(double) * nrow * nbase);
768  double buffer = 0.0;
769 
770  CPLCHECK_MSG("Cannot load data");
771 
772  /* Loop on base and rows */
773  for ( base=0 ; base<nbase ; base++) {
774  buffer = 0.0;
775 
776  for ( row=-nsmooth ; row<nrow ; row++) {
777  row_add = row+nsmooth;
778  row_sub = row-nsmooth-1;
779  if ( row_add < nrow ) buffer += data[row_add * nbase + base];
780  if ( row_sub >= 0 ) buffer -= data[row_sub * nbase + base];
781  if( row>=0 && row<nrow ) output[row * nbase + base] = (double)(buffer);
782  }
783  /* End loop on rows */
784  }
785  /* End loop on base */
786 
787  /* Wrap output column */
788  if ( !strcmp (input_name, output_name)) {
789  for (row = 0; row < nrow * nbase; row++) data[row] = output[row];
790  cpl_free (output);
791  } else {
792  if (cpl_table_has_column (oi_vis, output_name))
793  cpl_table_erase_column (oi_vis, output_name);
794  cpl_table_wrap_double (oi_vis, output, output_name);
795  }
796  CPLCHECK_MSG("Cannot Wrap");
797  }
798  else if ( type == CPL_TYPE_DOUBLE_COMPLEX ) {
799  double complex * data = cpl_table_get_data_double_complex (oi_vis, input_name);
800  double complex * output = cpl_malloc (sizeof(double complex) * nrow * nbase);
801  double complex buffer = 0.0;
802 
803  CPLCHECK_MSG("Cannot load data");
804 
805  /* Loop on rows */
806  for ( base=0 ; base<nbase ; base++) {
807  buffer = 0.0;
808 
809  for ( row=-nsmooth ; row<nrow ; row++) {
810  row_add = row+nsmooth;
811  row_sub = row-nsmooth-1;
812  if ( row_add < nrow ) buffer += data[row_add * nbase + base];
813  if ( row_sub >= 0 ) buffer -= data[row_sub * nbase + base];
814  if( row>=0 && row<nrow ) output[row * nbase + base] = (double complex)(buffer);
815  }
816  }
817  /* End loop on base */
818 
819  /* Wrap output column */
820  if ( !strcmp (input_name, output_name)) {
821  for (row = 0; row < nrow * nbase; row++) data[row] = output[row];
822  cpl_free (output);
823  } else {
824  if (cpl_table_has_column (oi_vis, output_name))
825  cpl_table_erase_column (oi_vis, output_name);
826  cpl_table_wrap_double_complex (oi_vis, output, output_name);
827  }
828  CPLCHECK_MSG ("Cannot Wrap");
829 
830  } else {
831  return cpl_error_set_message (cpl_func, CPL_ERROR_ILLEGAL_INPUT,
832  "This type is not supported..."
833  "report this error to DRS team !!");
834  }
835 
836  gravi_msg_function_exit(0);
837  return CPL_ERROR_NONE;
838 }
839 
840 cpl_error_code gravi_table_smooth_column (cpl_table * oi_vis,
841  const char *input_name,
842  const char *output_name,
843  int nsmooth, int nbase)
844 {
845  gravi_msg_function_start(0);
846  cpl_ensure_code (oi_vis, CPL_ERROR_NULL_INPUT);
847  cpl_ensure_code (input_name, CPL_ERROR_NULL_INPUT);
848  cpl_ensure_code (output_name, CPL_ERROR_NULL_INPUT);
849  cpl_ensure_code (nsmooth>0, CPL_ERROR_ILLEGAL_INPUT);
850  cpl_ensure_code (nbase>0, CPL_ERROR_ILLEGAL_INPUT);
851 
852  /* Performed the running integration and devide */
853  gravi_table_runint_column (oi_vis, input_name, output_name, nsmooth, nbase);
854  cpl_table_divide_scalar (oi_vis, output_name, 2.0*(double)nsmooth+1.0);
855 
856  gravi_msg_function_exit(0);
857  return CPL_ERROR_NONE;
858 }
859 
860 cpl_array * gravi_table_create_sigma_array (cpl_table * oi_wave)
861 {
862  int nv = 0;
863  cpl_size size = cpl_table_get_nrow (oi_wave);
864  cpl_array * sigma = cpl_array_new (size, CPL_TYPE_DOUBLE);
865 
866  for (cpl_size w = 0; w<size; w++ )
867  cpl_array_set (sigma, w, 1./cpl_table_get (oi_wave, "EFF_WAVE", w, &nv));
868 
869  CPLCHECK_NUL("Cannot compute the sigma array from EFF_WAVE");
870  return sigma;
871 }
872 
873 cpl_array * gravi_table_create_wave_array (cpl_table * oi_wave)
874 {
875  cpl_ensure (oi_wave, CPL_ERROR_NULL_INPUT, NULL);
876 
877  int nv = 0;
878  cpl_size size = cpl_table_get_nrow (oi_wave);
879  cpl_array * wave = cpl_array_new (size, CPL_TYPE_FLOAT);
880 
881  for (cpl_size w = 0; w<size; w++ )
882  cpl_array_set (wave, w, cpl_table_get (oi_wave, "EFF_WAVE", w, &nv));
883 
884  CPLCHECK_NUL("Cannot compute the wave array from EFF_WAVE");
885  return wave;
886 }
887 
888 
889 cpl_error_code gravi_array_normalize_complex (cpl_array * input)
890 {
891  cpl_ensure_code (input, CPL_ERROR_NULL_INPUT);
892 
893  int nv = 0;
894  cpl_size size = cpl_array_get_size (input);
895 
896  double complex cpx = 0.0 * I + 0.0;
897  for (cpl_size wave = 0; wave<size; wave++ ) {
898  cpx = cpl_array_get_complex (input,wave,&nv);
899  cpl_array_set_complex (input, wave, cpx / cabs (cpx));
900  if (nv) {cpl_array_set_invalid (input, wave); nv=0;}
901  }
902 
903  CPLCHECK_MSG("Cannot normalize complex");
904  return CPL_ERROR_NONE;
905 }
906 
907 cpl_array * gravi_array_create_inverse (cpl_array *input)
908 {
909  cpl_ensure (input, CPL_ERROR_NULL_INPUT, NULL);
910 
911  cpl_size size = cpl_array_get_size (input);
912 
913  cpl_array * inv = cpl_array_new (size, CPL_TYPE_DOUBLE);
914  cpl_array_fill_window (inv, 0, size, 1.0);
915  cpl_array_divide (inv, input);
916 
917  CPLCHECK_NUL("Cannot compute the sigma array from wave");
918  return inv;
919 }
920 
921 /*
922  * Unwrap an array of phase (in-place)
923  */
924 cpl_error_code gravi_array_phase_unwrap (cpl_array * input)
925 {
926  cpl_ensure_code (input, CPL_ERROR_NULL_INPUT);
927 
928  cpl_size size_x = cpl_array_get_size (input);
929  double phi_i, phi_ii, d_phi;
930  int k_wrap =0;
931 
932  for (cpl_size i_data = 1; i_data < size_x; i_data++){
933 
934  /* Evaluation of the phi(i_data) and
935  * phi(i_data-1) */
936 
937  phi_i = cpl_array_get(input, i_data, NULL);
938  phi_ii = cpl_array_get(input, i_data-1, NULL);
939 
940  d_phi = phi_i + k_wrap * 2 * M_PI - phi_ii;
941 
942  if (d_phi > M_PI) k_wrap ++;
943  if (d_phi < - M_PI) k_wrap --;
944 
945  cpl_array_set(input, i_data, cpl_array_get(input, i_data, NULL) + k_wrap * 2 * M_PI);
946  }
947 
948  CPLCHECK_INT("Cannot unwrap the phase array");
949  return CPL_ERROR_NONE;
950 }
951 
952 /*
953  * Fill in place the array with carg (cexp (1*I*array))
954  */
955 cpl_error_code gravi_array_phase_wrap (cpl_array * input)
956 {
957  cpl_ensure_code (input, CPL_ERROR_NULL_INPUT);
958 
959  cpl_size size = cpl_array_get_size (input);
960 
961  for (cpl_size wave = 0; wave<size; wave++ ) {
962  cpl_array_set (input, wave, carg (cexp ( 1.0 * I * cpl_array_get (input, wave, NULL))));
963  }
964 
965  CPLCHECK_MSG("Cannot wrap phase array");
966  return CPL_ERROR_NONE;
967 }
968 
973 cpl_array * gravi_array_cexp (double complex factor, const cpl_array * input)
974 {
975  cpl_ensure (input, CPL_ERROR_NULL_INPUT, NULL);
976 
977  cpl_size size = cpl_array_get_size (input);
978 
979  cpl_array * output = cpl_array_new (size, CPL_TYPE_DOUBLE_COMPLEX);
980  cpl_array_fill_window_complex (output, 0, size, (double complex)(0.0 + 0.0 * I));
981 
982  cpl_size n;
983  int nv = 0.0;
984  for (n = 0; n < size; n ++) {
985  cpl_array_set_complex (output, n, cexp (factor * cpl_array_get (input, n, &nv) ) );
986  }
987 
988  return output;
989 }
990 
995 cpl_error_code gravi_array_multiply_phasor (cpl_array * input, double complex factor, cpl_array * phase)
996 {
997  cpl_ensure_code (input, CPL_ERROR_NULL_INPUT);
998  cpl_ensure_code (phase, CPL_ERROR_NULL_INPUT);
999 
1000  cpl_size size_in = cpl_array_get_size (input);
1001  cpl_size size_ph = cpl_array_get_size (phase);
1002 
1003  cpl_ensure_code (size_in == size_ph, CPL_ERROR_ILLEGAL_INPUT);
1004 
1005  cpl_size n;
1006  int nv = 0.0;
1007  for (n = 0; n < size_in; n ++) {
1008  cpl_array_set_complex( input, n,
1009  cpl_array_get_complex( input, n, &nv) *
1010  cexp ( factor * cpl_array_get( phase, n, &nv) ) );
1011  }
1012 
1013  CPLCHECK_MSG ("Cannot multiply phasor");
1014  return CPL_ERROR_NONE;
1015 }
1016 
1021 cpl_error_code gravi_array_add_phasor (cpl_array * input, double complex factor, cpl_array * phase)
1022 {
1023  cpl_ensure_code (input, CPL_ERROR_NULL_INPUT);
1024  cpl_ensure_code (phase, CPL_ERROR_NULL_INPUT);
1025 
1026  cpl_size size_in = cpl_array_get_size (input);
1027  cpl_size size_ph = cpl_array_get_size (phase);
1028 
1029  cpl_ensure_code (size_in == size_ph, CPL_ERROR_ILLEGAL_INPUT);
1030 
1031  cpl_size n;
1032  int nv = 0.0;
1033  for (n = 0; n < size_in; n ++) {
1034  cpl_array_set_complex( input, n,
1035  cpl_array_get_complex( input, n, &nv) +
1036  cexp ( factor * cpl_array_get( phase, n, &nv) ) );
1037  CPLCHECK_MSG ("Cannot add phasor");
1038  }
1039 
1040  return CPL_ERROR_NONE;
1041 }
1042 
1047 cpl_error_code gravi_array_add_phasors (cpl_array * input, cpl_array * add, cpl_array * sub)
1048 {
1049  cpl_ensure_code (input, CPL_ERROR_NULL_INPUT);
1050  cpl_ensure_code (add, CPL_ERROR_NULL_INPUT);
1051  cpl_ensure_code (sub, CPL_ERROR_NULL_INPUT);
1052 
1053  cpl_size size_in = cpl_array_get_size (input);
1054  cpl_size size_add = cpl_array_get_size (add);
1055  cpl_size size_sub = cpl_array_get_size (sub);
1056 
1057  cpl_ensure_code (size_in == size_add, CPL_ERROR_ILLEGAL_INPUT);
1058  cpl_ensure_code (size_in == size_sub, CPL_ERROR_ILLEGAL_INPUT);
1059 
1060  cpl_size n;
1061  int nv = 0.0;
1062  for (n = 0; n < size_in; n ++) {
1063  cpl_array_set_complex (input, n,
1064  cpl_array_get_complex (input, n, &nv) +
1065  cpl_array_get_complex (add, n, &nv) *
1066  conj (cpl_array_get_complex (sub, n, &nv)));
1067  CPLCHECK_MSG ("Cannot add phasors");
1068  }
1069 
1070  return CPL_ERROR_NONE;
1071 }
1072 
1077 cpl_error_code gravi_array_add_phase (cpl_array * input, double factor, cpl_array * phase)
1078 {
1079  cpl_ensure_code (input, CPL_ERROR_NULL_INPUT);
1080  cpl_ensure_code (phase, CPL_ERROR_NULL_INPUT);
1081 
1082  cpl_size size_in = cpl_array_get_size (input);
1083  cpl_size size_ph = cpl_array_get_size (phase);
1084 
1085  cpl_ensure_code (size_in == size_ph, CPL_ERROR_ILLEGAL_INPUT);
1086 
1087  cpl_array * tmp = cpl_array_duplicate (phase);
1088 
1089  cpl_array_multiply_scalar (tmp, factor);
1090  cpl_array_add (input, tmp);
1091 
1092  cpl_array_delete (tmp);
1093 
1094  CPLCHECK_MSG("Cannot add phase");
1095  return CPL_ERROR_NONE;
1096 }
1097 
1098 cpl_error_code gravi_array_multiply_conj (cpl_array * input1, cpl_array * input2)
1099 {
1100  cpl_ensure_code (input1, CPL_ERROR_NULL_INPUT);
1101  cpl_ensure_code (input2, CPL_ERROR_NULL_INPUT);
1102 
1103  cpl_size size_in1 = cpl_array_get_size (input1);
1104  cpl_size size_in2 = cpl_array_get_size (input2);
1105 
1106  cpl_ensure_code (size_in1 == size_in2, CPL_ERROR_ILLEGAL_INPUT);
1107 
1108  for (cpl_size w = 0 ; w < size_in1 ; w++)
1109  cpl_array_set_complex (input1, w, cpl_array_get_complex (input1, w, NULL) *
1110  conj(cpl_array_get_complex (input2, w, NULL)));
1111 
1112  CPLCHECK_MSG ("Cannot multiply by conj");
1113  return CPL_ERROR_NONE;
1114 }
1115 
1116 
1117 /*
1118  * Returned a smoothed version of an array of DOUBLE
1119  * Invalid data are not checked (all considered as valid)
1120  */
1121 cpl_array * gravi_array_smooth (cpl_array * input, int nsmooth)
1122 {
1123  cpl_ensure (nsmooth>0, CPL_ERROR_ILLEGAL_INPUT, NULL);
1124  cpl_ensure (input, CPL_ERROR_NULL_INPUT, NULL);
1125 
1126  cpl_type type = cpl_array_get_type (input);
1127  cpl_size row, n_row = cpl_array_get_size ( input );
1128  int row_add, row_sub;
1129 
1130  /* Allocate memory of the output -- no check of valid/invalid data */
1131  cpl_array * output = cpl_array_duplicate (input);
1132 
1133  if ( type == CPL_TYPE_DOUBLE ) {
1134  double * data_input = cpl_array_get_data_double (input);
1135  double * data_output = cpl_array_get_data_double (output);
1136  double buffer = 0.0;
1137  int norm=0; // counter number of summed elements
1138 
1139  /* Running buffer -- FIXME: check arount limits */
1140  for ( row=-nsmooth ; row<n_row ; row++) {
1141  row_add = row+nsmooth;
1142  row_sub = row-nsmooth-1;
1143  if ( row_add < n_row ) {
1144  buffer += data_input[row_add];
1145  norm+=1;
1146  }
1147  if ( row_sub >= 0 ) {
1148  buffer -= data_input[row_sub];
1149  norm-=1;
1150  }
1151  if( row>=0 && row<n_row ) data_output[row] = (double)(buffer)/norm;
1152  }
1153  /* End loop on rows */
1154 
1155  } else {
1156  cpl_error_set_message (cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1157  "This type is not supported... report this error to DRS team !!");
1158  return NULL;
1159  }
1160 
1161  return output;
1162 }
1163 
1164 /*----------------------------------------------------------------------------*/
1185 /*----------------------------------------------------------------------------*/
1186 
1187 cpl_error_code gravi_array_get_group_delay_loop (cpl_array ** input, cpl_array * sigma,
1188  double * gd, cpl_size nrow,
1189  double max_width,
1190  int verbose)
1191 {
1192  gravi_msg_function_start(verbose);
1193  cpl_ensure_code (input, CPL_ERROR_NULL_INPUT);
1194  cpl_ensure_code (sigma, CPL_ERROR_NULL_INPUT);
1195  cpl_ensure_code (gd, CPL_ERROR_ILLEGAL_OUTPUT);
1196 
1197  int nv = 0;
1198  cpl_size nsigma = cpl_array_get_size (sigma);
1199  double width1, step1, width2, step2, width3, step3;
1200  cpl_size w, s, nstep1, nstep2, nstep3;
1201  double x, gd0, gd1, gd2, gd3, current_max = -1.0;
1202  double lbd = 1.0 / cpl_array_get (sigma,nsigma/2,&nv);
1203 
1204  /* Width of a single spectral channel in [m] */
1205  double coherence = 0.5 * nsigma / fabs (cpl_array_get (sigma,0,&nv) - cpl_array_get (sigma,nsigma-1,&nv));
1206 
1207  /* We never explore more than max_width */
1208  width1 = CPL_MIN (coherence, max_width);
1209  step1 = 2.0 * lbd;
1210  nstep1 = (cpl_size)(width1/step1);
1211 
1212  /* Second pass */
1213  width2 = 3.0 * step1;
1214  step2 = 0.1 * lbd;
1215  nstep2 = (cpl_size)(width2/step2);
1216 
1217  /* Third pass */
1218  width3 = 3.0 * step2;
1219  step3 = 0.01 * lbd;
1220  nstep3 = (cpl_size)(width3/step3);
1221 
1222  /* Allocate memory for the grid search */
1223  double P = 0.0;
1224  double * sigdata = cpl_malloc (sizeof(double complex) * nsigma);
1225  double complex * visdata = cpl_malloc (sizeof(double complex) * nsigma);
1226  double complex * waveform1 = cpl_malloc (sizeof(double complex) * (nstep1+2) * nsigma);
1227  double complex * waveform2 = cpl_malloc (sizeof(double complex) * (nstep2+2) * nsigma);
1228  double complex * waveform3 = cpl_malloc (sizeof(double complex) * (nstep3+2) * nsigma);
1229 
1230  /* Copy data as double to secure their type */
1231  for (w=0; w<nsigma; w++) sigdata[w] = cpl_array_get (sigma, w, &nv);
1232 
1233  /* Sum of wavenumber differences */
1234  double ds = 0.0;
1235  for (w=1; w<nsigma; w++) ds += sigdata[w] - sigdata[w-1];
1236  ds /= (nsigma-1);
1237 
1238  /* Build waveform */
1239  cpl_msg_debug (cpl_func, "Build waveform for 3 pass -- %lli %lli %lli steps", nstep1, nstep2, nstep3);
1240 
1241  for (s=0, x = -width1/2.0; x < +width1/2.0; x+=step1)
1242  for (w=0; w<nsigma; w++) { waveform1[s] = cexp (-2.*I*CPL_MATH_PI * x * sigdata[w]); s++;}
1243  for (s=0, x = -width2/2.0; x < +width2/2.0; x+=step2)
1244  for (w=0; w<nsigma; w++) { waveform2[s] = cexp (-2.*I*CPL_MATH_PI * x * sigdata[w]); s++;}
1245  for (s=0, x = -width3/2.0; x < +width3/2.0; x+=step3)
1246  for (w=0; w<nsigma; w++) { waveform3[s] = cexp (-2.*I*CPL_MATH_PI * x * sigdata[w]); s++;}
1247 
1248  cpl_msg_debug (cpl_func, "Loop on %lli rows to compute gdelay", nrow);
1249 
1250  /* Loop on rows */
1251  for (cpl_size row = 0; row<nrow; row++) {
1252 
1253  /* Copy data as double complex to secure their type and allow
1254  * in-place modification between the different grids */
1255  for (w=0; w<nsigma; w++) visdata[w] = cpl_array_get_complex (input[row], w, &nv);
1256 
1257  /* IOTA method in [m] -- as starting point, with
1258  * equal weight to all channels to avoid badpixels */
1259  double complex is = 0.0 + I * 0.0;
1260  for (w=1; w<nsigma; w++) {
1261  is += visdata[w] * conj(visdata[w-1]) / CPL_MAX(cabs(visdata[w]) * cabs(visdata[w-1]), 1e-15);
1262  }
1263  gd0 = carg (is) / ds / CPL_MATH_2PI;
1264 
1265  /* Remove GD */
1266  for (w=0; w<nsigma; w++) visdata[w] *= cexp (-2.*I*CPL_MATH_PI*gd0*sigdata[w]);
1267 
1268  /* Loop on x to find the maximum of P(x) = |FT(input(sigma))| */
1269  for (current_max = -1.0, s = 0, x = -width1/2; x < +width1/2; x+=step1) {
1270  double complex tmp = 0.0 * I + 0.0;
1271  for (w=0; w<nsigma; w++) {tmp += visdata[w] * waveform1[s]; s++;}
1272  P = cabs (tmp);
1273  if ( P > current_max) { current_max = P; gd1 = x; }
1274  }
1275 
1276  /* Remove GD */
1277  for (w=0; w<nsigma; w++) visdata[w] *= cexp (-2.*I*CPL_MATH_PI*gd1*sigdata[w]);
1278 
1279  /* Loop on x to find the maximum of P(x) = |FT(input(sigma))| */
1280  for (current_max = -1.0, s = 0, x = -width2/2; x < +width2/2; x+=step2) {
1281  double complex tmp = 0.0 * I + 0.0;
1282  for (w=0; w<nsigma; w++) {tmp += visdata[w] * waveform2[s]; s++;}
1283  P = cabs (tmp);
1284  if ( P > current_max) { current_max = P; gd2 = x; }
1285  }
1286 
1287  /* Remove GD */
1288  for (w=0; w<nsigma; w++) visdata[w] *= cexp (-2.*I*CPL_MATH_PI*gd2*sigdata[w]);
1289 
1290  /* Loop on x to find the maximum of P(x) = |FT(input(sigma))| */
1291  for (current_max = -1.0, s = 0, x = -width3/2; x < +width3/2; x+=step3) {
1292  double complex tmp = 0.0 * I + 0.0;
1293  for (w=0; w<nsigma; w++) {tmp += visdata[w] * waveform3[s]; s++;}
1294  P = cabs (tmp);
1295  if ( P > current_max) { current_max = P; gd3 = x; }
1296  }
1297 
1298  gd[row] = gd0 + gd1 + gd2 + gd3;
1299 
1300  CPLCHECK_MSG("Cannot compute GD");
1301  } /* End loop on rows */
1302 
1303  /* Clean memory */
1304  FREE (cpl_free, visdata);
1305  FREE (cpl_free, sigdata);
1306  FREE (cpl_free, waveform1);
1307  FREE (cpl_free, waveform2);
1308  FREE (cpl_free, waveform3);
1309 
1310  gravi_msg_function_exit(verbose);
1311  return CPL_ERROR_NONE;
1312 }
1313 
1314 cpl_error_code gravi_table_compute_group_delay (cpl_table * table, const char *input,
1315  const char *output, cpl_table * oi_wave)
1316 {
1317  gravi_msg_function_start(0);
1318  cpl_ensure_code (table, CPL_ERROR_NULL_INPUT);
1319  cpl_ensure_code (input, CPL_ERROR_NULL_INPUT);
1320  cpl_ensure_code (output, CPL_ERROR_NULL_INPUT);
1321  cpl_ensure_code (oi_wave, CPL_ERROR_NULL_INPUT);
1322 
1323  /* Create sigma */
1324  cpl_size nwave = cpl_table_get_nrow (oi_wave);
1325  cpl_array * sigma = cpl_array_new (nwave, CPL_TYPE_DOUBLE);
1326  for (cpl_size wave = 0; wave < nwave ; wave ++)
1327  cpl_array_set (sigma, wave, 1./cpl_table_get (oi_wave, "EFF_WAVE", wave, NULL));
1328 
1329  /* If output columns doesn't exist, create it */
1330  gravi_table_new_column (table, output, "m", CPL_TYPE_DOUBLE);
1331  double * gdelay = cpl_table_get_data_double (table, output);
1332 
1333  /* Get data */
1334  cpl_array ** input_arrays = cpl_table_get_data_array (table, input);
1335  cpl_size nrow = cpl_table_get_nrow (table);
1336 
1337  CPLCHECK_MSG ("Cannot get data");
1338 
1339  /* Run */
1340  gravi_array_get_group_delay_loop (input_arrays, sigma, gdelay,
1341  nrow, 1.e-3, CPL_TRUE);
1342  FREE (cpl_array_delete, sigma);
1343 
1344  gravi_msg_function_exit(0);
1345  return CPL_ERROR_NONE;
1346 }
1347 
1348 
1349 
1350 /*----------------------------------------------------------------------------*/
1357 /*----------------------------------------------------------------------------*/
1358 int gravi_table_are_equal (cpl_table * first, cpl_table * second)
1359 {
1360  gravi_msg_function_start(0);
1361  cpl_ensure_code (first, CPL_ERROR_NULL_INPUT);
1362  cpl_ensure_code (second, CPL_ERROR_NULL_INPUT);
1363 
1364  cpl_size nrow = cpl_table_get_nrow (first);
1365  cpl_size ncol = cpl_table_get_ncol (first);
1366  int nv = 0;
1367 
1368  if (nrow != cpl_table_get_nrow (second)) {cpl_msg_info(cpl_func, "Different rows"); return 0;}
1369  if (ncol != cpl_table_get_ncol (second)) {cpl_msg_info(cpl_func, "Different cols"); return 0;}
1370  if (cpl_table_compare_structure (first, second)) {cpl_msg_info(cpl_func, "Different structure"); return 0;}
1371 
1372  cpl_array *names = cpl_table_get_column_names (first);
1373 
1374  /* Loop on colums */
1375  for (cpl_size c = 0; c<ncol; c++) {
1376  const char * name = cpl_array_get_string (names, c);
1377  cpl_msg_debug (cpl_func,"Now test %s", name);
1378 
1379  /* Cast the type into an int, to avoid warnings */
1380  int type = cpl_table_get_column_type (first, name);
1381 
1382  switch (type) {
1383  case CPL_TYPE_STRING:
1384  for (cpl_size r = 0; r<nrow; r++)
1385  if (strcmp (cpl_table_get_string (first, name, r),
1386  cpl_table_get_string (second, name, r) ) )
1387  {cpl_msg_info (cpl_func,"Different values in column %s, row %lli", name,r); return 0;}
1388  break;
1389  case CPL_TYPE_DOUBLE:
1390  case CPL_TYPE_FLOAT:
1391  case CPL_TYPE_INT:
1392  for (cpl_size r = 0; r<nrow; r++)
1393  if (cpl_table_get (first, name, r, &nv) !=
1394  cpl_table_get (second, name, r, &nv) )
1395  {cpl_msg_info (cpl_func,"Different values in column %s, row %lli", name,r); return 0;}
1396  break;
1397  case CPL_TYPE_POINTER|CPL_TYPE_STRING:
1398  for (cpl_size r = 0; r<nrow; r++)
1399  for (cpl_size p = 0; p<cpl_table_get_column_depth (first,name); p++)
1400  if ( strcmp (cpl_array_get_string (cpl_table_get_array (first, name, r), p),
1401  cpl_array_get_string (cpl_table_get_array (second, name, r), p)) )
1402  {cpl_msg_info (cpl_func,"Different values in column %s, row %lli", name,r); return 0;}
1403  break;
1404  case CPL_TYPE_POINTER|CPL_TYPE_DOUBLE:
1405  case CPL_TYPE_POINTER|CPL_TYPE_FLOAT:
1406  case CPL_TYPE_POINTER|CPL_TYPE_INT:
1407  for (cpl_size r = 0; r<nrow; r++)
1408  for (cpl_size p = 0; p<cpl_table_get_column_depth (first,name); p++) {
1409  if (cpl_array_get (cpl_table_get_array (first, name, r), p, NULL) !=
1410  cpl_array_get (cpl_table_get_array (second, name, r), p, NULL) )
1411  {cpl_msg_info (cpl_func,"Different values in column %s, row %lli", name,r); return 0;}
1412  }
1413  break;
1414  default:
1415  cpl_error_set_message (cpl_func, CPL_ERROR_ILLEGAL_INPUT, "Cannot compare these tables (TBD, FIXME)");
1416  return 0;
1417  }
1418 
1419  }/* End loop on columns */
1420 
1421  gravi_msg_function_exit(0);
1422  return 1;
1423 }
1424 
1425 cpl_error_code gravi_table_new_column (cpl_table * table, const char * name, const char * unit, cpl_type type)
1426 {
1427  cpl_ensure_code (table, CPL_ERROR_NULL_INPUT);
1428  cpl_ensure_code (name, CPL_ERROR_NULL_INPUT);
1429 
1430  if ( cpl_table_has_column (table, name) &&
1431  cpl_table_get_column_type (table, name) == type) {
1432  cpl_msg_info (cpl_func, "Column %s already exists", name);
1433  } else {
1434  cpl_table_new_column (table, name, type);
1435  }
1436 
1437  if (type == CPL_TYPE_DOUBLE_COMPLEX || type == CPL_TYPE_FLOAT_COMPLEX)
1438  cpl_table_fill_column_window_complex (table, name, 0, cpl_table_get_nrow (table), 0.0 + I*0.0);
1439  else
1440  cpl_table_fill_column_window (table, name, 0, cpl_table_get_nrow (table), 0.0);
1441 
1442  if (unit) cpl_table_set_column_unit (table, name, unit);
1443 
1444  return CPL_ERROR_NONE;
1445 }
1446 
1447 cpl_error_code gravi_table_new_column_array (cpl_table * table, const char * name, const char * unit, cpl_type type, cpl_size size)
1448 {
1449  cpl_ensure_code (table, CPL_ERROR_NULL_INPUT);
1450  cpl_ensure_code (name, CPL_ERROR_NULL_INPUT);
1451 
1452  if ( cpl_table_has_column (table, name) )
1453  cpl_table_erase_column (table, name);
1454 
1455  cpl_table_new_column_array (table, name, type, size);
1456  if (unit) cpl_table_set_column_unit (table, name, unit);
1457 
1458  return CPL_ERROR_NONE;
1459 }
1460 
1461 cpl_error_code gravi_table_init_column_array (cpl_table * table, const char * name, const char * unit, cpl_type type, cpl_size size)
1462 {
1463  cpl_ensure_code (table, CPL_ERROR_NULL_INPUT);
1464  cpl_ensure_code (name, CPL_ERROR_NULL_INPUT);
1465 
1466  if ( cpl_table_has_column (table, name) )
1467  cpl_table_erase_column (table, name);
1468 
1469  cpl_table_new_column_array (table, name, type, size);
1470  if (unit) cpl_table_set_column_unit (table, name, unit);
1471 
1472  cpl_array * array = cpl_array_new (size, type);
1473  cpl_array_fill_window (array, 0, size, 0.0);
1474 
1475  cpl_size nrow = cpl_table_get_nrow (table);
1476  for (cpl_size row = 0; row < nrow; row++)
1477  cpl_table_set_array (table, name, row, array);
1478 
1479  FREE (cpl_array_delete, array);
1480 
1481  return CPL_ERROR_NONE;
1482 }
1483 
1484 /*---------------------------------------------------------------------------*/
1494 /*---------------------------------------------------------------------------*/
1495 
1496 cpl_error_code gravi_imagelist_unwrap_images (cpl_imagelist * imglist)
1497 {
1498  cpl_ensure_code (imglist, CPL_ERROR_NULL_INPUT);
1499 
1500  cpl_size nrow = cpl_imagelist_get_size (imglist);
1501 
1502  for (cpl_size i = nrow-1; i>=0 ; i--) {
1503  cpl_image_unwrap (cpl_imagelist_unset (imglist, i));
1504  CPLCHECK_MSG("Cannot unset image");
1505  }
1506 
1507  cpl_imagelist_delete (imglist);
1508  CPLCHECK_MSG("Cannot delete imagelist");
1509 
1510  return CPL_ERROR_NONE;
1511 }
1512 
1513 /*---------------------------------------------------------------------------*/
1524 /*---------------------------------------------------------------------------*/
1525 
1526 cpl_imagelist * gravi_imagelist_wrap_column (cpl_table * table_data, const char * data_x)
1527 {
1528  gravi_msg_function_start(0);
1529  cpl_ensure (table_data, CPL_ERROR_NULL_INPUT, NULL);
1530  cpl_ensure (data_x, CPL_ERROR_NULL_INPUT, NULL);
1531 
1532  /* Get the type of the column
1533  * Cast into an int to avoid warnings */
1534  int type_column = cpl_table_get_column_type (table_data, data_x);
1535 
1536  /* Get pointer to the data */
1537  cpl_size nrow = cpl_table_get_nrow (table_data);
1538  cpl_array ** array = cpl_table_get_data_array (table_data, data_x);
1539  cpl_ensure (array, CPL_ERROR_ILLEGAL_INPUT, NULL);
1540 
1541  /* If the column has no-dimension, we fake them */
1542  cpl_size nx, ny;
1543  if (cpl_table_get_column_dimensions (table_data, data_x)<2) {
1544  nx = cpl_table_get_column_depth (table_data, data_x);
1545  ny = 1;
1546  } else {
1547  nx = cpl_table_get_column_dimension (table_data, data_x, 0);
1548  ny = cpl_table_get_column_dimension (table_data, data_x, 1);
1549  }
1550  CPLCHECK_NUL ("Cannot get dimension");
1551 
1552  /* Create output */
1553  cpl_image * img;
1554  cpl_imagelist * imglist = cpl_imagelist_new();
1555 
1556  /* compute the image list depending of the DATA type */
1557  switch (type_column)
1558  {
1559  case CPL_TYPE_POINTER|CPL_TYPE_DOUBLE :
1560 
1561  for (cpl_size j = 0; j < nrow ; j++)
1562  {
1563  img = cpl_image_wrap_double (nx, ny, cpl_array_get_data_double(array[j]));
1564  cpl_imagelist_set (imglist, img, j);
1565  }
1566 
1567  break;
1568 
1569  case CPL_TYPE_POINTER|CPL_TYPE_INT :
1570 
1571  for (cpl_size j = 0; j < nrow ; j++)
1572  {
1573  img = cpl_image_wrap_int (nx, ny, cpl_array_get_data_int(array[j]));
1574  cpl_imagelist_set (imglist, img,j);
1575  }
1576 
1577  break;
1578 
1579  case CPL_TYPE_POINTER|CPL_TYPE_FLOAT :
1580  for (cpl_size j = 0; j < nrow ; j++)
1581  {
1582  img = cpl_image_wrap_float (nx, ny, cpl_array_get_data_float(array[j]));
1583  cpl_imagelist_set (imglist, img, j);
1584  }
1585 
1586  break;
1587 
1588  default:
1589 
1590  cpl_error_set_message(cpl_func, CPL_ERROR_INVALID_TYPE,
1591  "invalid type of image coming from %s", data_x);
1592  cpl_imagelist_delete (imglist);
1593  return NULL;
1594  break;
1595  }
1596 
1597  gravi_msg_function_exit(0);
1598  return imglist;
1599 }
1600 
1601 /*----------------------------------------------------------------------------*/
1606 /*----------------------------------------------------------------------------*/
1607 
1608 double gravi_image_get_noise_window (cpl_image *img,
1609  cpl_size llx, cpl_size lly,
1610  cpl_size urx, cpl_size ury)
1611 {
1612  gravi_msg_function_start(0);
1613  cpl_ensure (img, CPL_ERROR_NULL_INPUT, -1);
1614  int nv;
1615 
1616  /* Extract values in vector */
1617  cpl_vector * flux = cpl_vector_new ((urx-llx+1)*(ury-lly+1));
1618 
1619  for (cpl_size v = 0, x = llx; x <= urx; x++) {
1620  for (cpl_size y = lly; y <= ury; y++) {
1621  cpl_vector_set (flux, v, cpl_image_get (img, x, y, &nv));
1622  v++;
1623  CPLCHECK_MSG ("Cannot fill vector");
1624  }
1625  }
1626 
1627  /* FIXME: remove the median before square */
1628 
1629  /* Compute typical error as the
1630  * median of spatial variation */
1631  cpl_vector_multiply (flux, flux);
1632 
1633  double RMS = sqrt (cpl_vector_get_median (flux));
1634  FREE (cpl_vector_delete, flux);
1635 
1636  gravi_msg_function_exit(0);
1637  return RMS;
1638 }
1639 
1640 /*----------------------------------------------------------------------------*/
1641 
1642 cpl_error_code gravi_image_subtract_window (cpl_image * img1, const cpl_image * img2,
1643  cpl_size llx, cpl_size lly,
1644  cpl_size urx, cpl_size ury,
1645  cpl_size llx2, cpl_size lly2)
1646 {
1647  gravi_msg_function_start(0);
1648  cpl_ensure_code (img1, CPL_ERROR_NULL_INPUT);
1649  cpl_ensure_code (img2, CPL_ERROR_NULL_INPUT);
1650 
1651  /* Ensure size */
1652  cpl_size nx = cpl_image_get_size_x (img1);
1653  cpl_size ny = cpl_image_get_size_y (img1);
1654  urx = CPL_MIN (urx, nx);
1655  ury = CPL_MIN (ury, ny);
1656  llx2 -= llx;
1657  lly2 -= lly;
1658 
1659  int nv;
1660  for (cpl_size x=llx; x<=urx; x++) {
1661  for (cpl_size y=lly; y<=ury; y++) {
1662  cpl_image_set (img1, x, y,
1663  cpl_image_get (img1,x,y,&nv) -
1664  cpl_image_get (img2,x+llx2,y+lly2,&nv));
1665  }
1666  }
1667 
1668  gravi_msg_function_exit(0);
1669  return CPL_ERROR_NONE;
1670 }
1671 
1672 /*---------------------------------------------------------------------------*/
1685 /*---------------------------------------------------------------------------*/
1686 
1687 cpl_image * gravi_image_from_column (cpl_table * table_data, const char * data_x, cpl_size row)
1688 {
1689  gravi_msg_function_start(0);
1690  cpl_ensure (table_data, CPL_ERROR_NULL_INPUT, NULL);
1691  cpl_ensure (data_x, CPL_ERROR_NULL_INPUT, NULL);
1692  cpl_ensure (row < cpl_table_get_nrow (table_data), CPL_ERROR_ILLEGAL_INPUT, NULL);
1693 
1694  cpl_imagelist * wrap_imglist = gravi_imagelist_wrap_column (table_data, data_x);
1695  cpl_ensure (wrap_imglist, CPL_ERROR_ILLEGAL_INPUT, NULL);
1696 
1697  cpl_image * out_img = cpl_image_duplicate (cpl_imagelist_get (wrap_imglist, row));
1698  gravi_imagelist_unwrap_images (wrap_imglist);
1699 
1700  gravi_msg_function_exit(0);
1701  return out_img;
1702 }
1703 
1704 /*---------------------------------------------------------------------------*/
1717 /*---------------------------------------------------------------------------*/
1718 
1719 cpl_imagelist * gravi_imagelist_from_column (cpl_table * table_data, const char * data_x)
1720 {
1721  gravi_msg_function_start(0);
1722  cpl_ensure (table_data, CPL_ERROR_NULL_INPUT, NULL);
1723  cpl_ensure (data_x, CPL_ERROR_NULL_INPUT, NULL);
1724 
1725  cpl_imagelist * wrap_imglist = gravi_imagelist_wrap_column (table_data, data_x);
1726  cpl_ensure (wrap_imglist, CPL_ERROR_ILLEGAL_INPUT, NULL);
1727 
1728  cpl_imagelist * out_imglist = cpl_imagelist_duplicate (wrap_imglist);
1729  gravi_imagelist_unwrap_images (wrap_imglist);
1730 
1731  gravi_msg_function_exit(0);
1732  return out_imglist;
1733 }
1734 
1735 
1736 /*---------------------------------------------------------------------------*/
1747 /*---------------------------------------------------------------------------*/
1748 
1749 cpl_array * gravi_table_get_column_dimension (const cpl_table * table, const char * name)
1750 {
1751  cpl_ensure (table, CPL_ERROR_NULL_INPUT, NULL);
1752  cpl_ensure (name, CPL_ERROR_NULL_INPUT, NULL);
1753 
1754  cpl_size ndim = cpl_table_get_column_dimensions (table, name);
1755  cpl_array * dimension = cpl_array_new (ndim, CPL_TYPE_INT);
1756  for (cpl_size dim = 0; dim < ndim; dim++) {
1757  int value = cpl_table_get_column_dimension (table, name, dim);
1758  cpl_array_set (dimension, dim, value);
1759  }
1760 
1761  return dimension;
1762 }
1763 
1764 /*---------------------------------------------------------------------------*/
1774 /*---------------------------------------------------------------------------*/
1775 
1776 cpl_array * gravi_array_wrap_image (cpl_image * img)
1777 {
1778  cpl_ensure (img, CPL_ERROR_NULL_INPUT, NULL);
1779 
1780  cpl_type type_img = cpl_image_get_type (img);
1781  int x = cpl_image_get_size_x (img);
1782  int y = cpl_image_get_size_y (img);
1783 
1784  CPLCHECK_NUL ("Cannot get data");
1785 
1786  cpl_array * array = NULL;
1787  switch (type_img){
1788  case CPL_TYPE_FLOAT :
1789  array = cpl_array_wrap_float (cpl_image_get_data_float(img), x*y);
1790  break;
1791  case CPL_TYPE_DOUBLE :
1792  array = cpl_array_wrap_double (cpl_image_get_data_double(img), x*y);
1793  break;
1794  case CPL_TYPE_INT :
1795  array = cpl_array_wrap_int (cpl_image_get_data_int(img), x*y);
1796  break;
1797  default :
1798  cpl_error_set_message(cpl_func, CPL_ERROR_INVALID_TYPE,
1799  "invalid type of image");
1800  return NULL;
1801  }
1802 
1803  return array;
1804 }
1805 
1806 
1807 /*---------------------------------------------------------------------------*/
1818 /*---------------------------------------------------------------------------*/
1819 
1820 cpl_matrix * get_matrix_from_vector(cpl_vector * vector1,
1821  cpl_vector * vector2)
1822 {
1823  cpl_ensure (vector1, CPL_ERROR_NULL_INPUT, NULL);
1824 
1825  cpl_matrix * matrix, * matrix_wrap;
1826  int size = cpl_vector_get_size(vector1);
1827  double * data1, * data2;
1828 
1829  if( vector2 != NULL ){
1830  int size2 = cpl_vector_get_size(vector2);
1831  cpl_ensure (size == size2, CPL_ERROR_ILLEGAL_INPUT, NULL);
1832 
1833  data1 = cpl_malloc(2 * size * sizeof(double));
1834  memcpy(data1, cpl_vector_get_data(vector1), size * sizeof(double));
1835 
1836  data2 = cpl_vector_get_data(vector2);
1837  memcpy(data1 + size, data2, size * sizeof(double));
1838 
1839  matrix_wrap = cpl_matrix_wrap(2, size, data1);
1840  matrix = cpl_matrix_transpose_create(matrix_wrap);
1841 
1842  cpl_matrix_unwrap(matrix_wrap);
1843  }
1844  else{
1845  data1 = cpl_malloc(size * sizeof(double));
1846  memcpy(data1, cpl_vector_get_data(vector1), size * sizeof(double));
1847 
1848  matrix = cpl_matrix_wrap(size, 1, data1);
1849  }
1850  cpl_free(data1);
1851 
1852  return matrix;
1853 }
1854 
1855 /*---------------------------------------------------------------------------*/
1868 /*---------------------------------------------------------------------------*/
1869 
1870 cpl_vector * gravi_table_get_vector (cpl_table * spectrum_data,
1871  cpl_size index,
1872  const char * regname)
1873 {
1874  /* Check the inputs */
1875  cpl_ensure (spectrum_data, CPL_ERROR_NULL_INPUT, NULL);
1876  cpl_ensure (regname, CPL_ERROR_NULL_INPUT, NULL);
1877  cpl_ensure (index>=0, CPL_ERROR_ILLEGAL_INPUT, NULL);
1878 
1879  /* Get the array size */
1880  cpl_size size = cpl_table_get_column_depth (spectrum_data, regname);
1881  cpl_ensure (index<size, CPL_ERROR_ILLEGAL_INPUT, NULL);
1882 
1883  /* allocate the vector */
1884  cpl_size nrow = cpl_table_get_nrow (spectrum_data);
1885  cpl_vector * data_value = cpl_vector_new (nrow);
1886 
1887  if (size > 0) {
1888 
1889  /* Extract the data from the column region */
1890  cpl_array ** column_array = cpl_table_get_data_array (spectrum_data, regname);
1891  cpl_ensure (column_array, CPL_ERROR_ILLEGAL_INPUT, NULL);
1892 
1893  /* Loop on row */
1894  double value;
1895  for (cpl_size row = 0; row < nrow; row ++){
1896  value = cpl_array_get (column_array[row], index, NULL);
1897  cpl_vector_set (data_value, row, value);
1898  }
1899  } else if (cpl_table_get_column_type (spectrum_data, regname)
1900  == CPL_TYPE_DOUBLE) {
1901 
1902  double * data = cpl_table_get_data_double (spectrum_data, regname);
1903  for (cpl_size row = 0; row < nrow; row++) {
1904  cpl_vector_set (data_value, row, data[row]);
1905  }
1906 
1907  } else if (cpl_table_get_column_type (spectrum_data, regname)
1908  == CPL_TYPE_INT) {
1909 
1910  int * data = cpl_table_get_data_int (spectrum_data, regname);
1911  for (cpl_size row = 0; row < nrow; row++) {
1912  cpl_vector_set (data_value, row, data[row]);
1913  }
1914 
1915  } else {
1916  cpl_error_set_message (cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1917  "This type is not supported"
1918  "(report to DRS team).");
1919  FREE (cpl_vector_delete, data_value);
1920  return NULL;
1921  }
1922 
1923  return (data_value);
1924 }
1925 
1926 cpl_vector * gravi_table_get_vector_scalar (cpl_table * table,
1927  const char * name,
1928  cpl_size base,
1929  cpl_size nbase)
1930 {
1931  /* Check the inputs */
1932  cpl_ensure (table, CPL_ERROR_NULL_INPUT, NULL);
1933  cpl_ensure (name, CPL_ERROR_NULL_INPUT, NULL);
1934  cpl_ensure (base>=0, CPL_ERROR_ILLEGAL_INPUT, NULL);
1935  cpl_ensure (nbase>0, CPL_ERROR_ILLEGAL_INPUT, NULL);
1936 
1937  /* Ensure it is scalar */
1938  cpl_size size = cpl_table_get_column_depth (table, name);
1939  cpl_ensure (size==0, CPL_ERROR_ILLEGAL_INPUT, NULL);
1940 
1941  /* Allocate the vector */
1942  cpl_size nrow = cpl_table_get_nrow (table) / nbase;
1943  cpl_vector * vector = cpl_vector_new (nrow);
1944 
1945  /* Get the type */
1946  cpl_type type = cpl_table_get_column_type (table, name);
1947 
1948  if (type == CPL_TYPE_DOUBLE) {
1949  double * data = cpl_table_get_data_double (table, name);
1950  for (cpl_size row = 0; row < nrow; row++)
1951  cpl_vector_set (vector, row, data[row*nbase+base]);
1952  }
1953  else if (type == CPL_TYPE_FLOAT) {
1954  float * data = cpl_table_get_data_float (table, name);
1955  for (cpl_size row = 0; row < nrow; row++)
1956  cpl_vector_set (vector, row, data[row*nbase+base]);
1957  }
1958  else if (type == CPL_TYPE_INT) {
1959  int * data = cpl_table_get_data_int (table, name);
1960  for (cpl_size row = 0; row < nrow; row++)
1961  cpl_vector_set (vector, row, data[row*nbase+base]);
1962  }
1963  else {
1964  cpl_error_set_message (cpl_func, CPL_ERROR_ILLEGAL_INPUT,
1965  "This type is not supported"
1966  "(report to DRS team).");
1967  FREE (cpl_vector_delete, vector);
1968  return NULL;
1969  }
1970 
1971  return vector;
1972 }
1973 
1974 /*---------------------------------------------------------------------------*/
1989 /*---------------------------------------------------------------------------*/
1990 
1991 cpl_vector * gravi_table_get_vector_diff (cpl_table * spectrum_data, int index,
1992  const char * regname1,
1993  const char * regname2)
1994 {
1995  /* Check the inputs */
1996  cpl_ensure (spectrum_data, CPL_ERROR_NULL_INPUT, NULL);
1997  cpl_ensure (regname1, CPL_ERROR_NULL_INPUT, NULL);
1998  cpl_ensure (regname2, CPL_ERROR_NULL_INPUT, NULL);
1999  cpl_ensure (index>=0, CPL_ERROR_ILLEGAL_INPUT, NULL);
2000 
2001  /* Get the array size */
2002  cpl_size size1 = cpl_table_get_column_depth (spectrum_data, regname1);
2003  cpl_size size2 = cpl_table_get_column_depth (spectrum_data, regname2);
2004  cpl_ensure (index<size1, CPL_ERROR_ILLEGAL_INPUT, NULL);
2005  cpl_ensure (index<size2, CPL_ERROR_ILLEGAL_INPUT, NULL);
2006 
2007  /* Extract the data from the column region */
2008  cpl_array ** column_array1 = cpl_table_get_data_array (spectrum_data, regname1);
2009  cpl_array ** column_array2 = cpl_table_get_data_array (spectrum_data, regname2);
2010  cpl_ensure (column_array1, CPL_ERROR_ILLEGAL_INPUT, NULL);
2011  cpl_ensure (column_array2, CPL_ERROR_ILLEGAL_INPUT, NULL);
2012 
2013  /* allocate the vector */
2014  cpl_size nrow = cpl_table_get_nrow (spectrum_data);
2015  cpl_vector * data_value = cpl_vector_new (nrow);
2016 
2017  /* Loop on row */
2018  double value;
2019  for (cpl_size row = 0; row < nrow; row++){
2020  value = cpl_array_get (column_array1[row], index, NULL) - cpl_array_get (column_array2[row], index, NULL);
2021  cpl_vector_set (data_value, row, value);
2022  }
2023 
2024  return (data_value);
2025 }
2026 
2027 /*---------------------------------------------------------------------------*/
2031 /*---------------------------------------------------------------------------*/
2032 
2033 cpl_error_code gravi_image_fill (cpl_image * img, double value)
2034 {
2035  cpl_ensure_code (img, CPL_ERROR_NULL_INPUT);
2036 
2037  cpl_size nx = cpl_image_get_size_x (img);
2038  cpl_size ny = cpl_image_get_size_y (img);
2039  cpl_image_fill_window (img, 1,1,nx,ny, value);
2040 
2041  return CPL_ERROR_NONE;
2042 }
2043 
2044 /*---------------------------------------------------------------------------*/
2048 /*---------------------------------------------------------------------------*/
2049 
2050 cpl_image * gravi_image_wrap_matrix (cpl_matrix * matrix)
2051 {
2052  cpl_ensure (matrix, CPL_ERROR_NULL_INPUT, NULL);
2053  cpl_size nx = cpl_matrix_get_ncol (matrix);
2054  cpl_size ny = cpl_matrix_get_nrow (matrix);
2055  return cpl_image_wrap_double (nx, ny, cpl_matrix_get_data (matrix));
2056 }
2057 
2058 cpl_image * gravi_image_from_matrix (cpl_matrix * matrix)
2059 {
2060  cpl_ensure (matrix, CPL_ERROR_NULL_INPUT, NULL);
2061  cpl_size nx = cpl_matrix_get_ncol (matrix);
2062  cpl_size ny = cpl_matrix_get_nrow (matrix);
2063 
2064  cpl_image * image = cpl_image_new (nx,ny,CPL_TYPE_DOUBLE);
2065  for (cpl_size i = 0; i < nx; i++)
2066  for (cpl_size j = 0; j < ny; j++)
2067  cpl_image_set (image, i+1, j+1, cpl_matrix_get (matrix,j,i));
2068 
2069  return image;
2070 }
2071 
2072 /*---------------------------------------------------------------------------*/
2076 /*---------------------------------------------------------------------------*/
2077 
2078 cpl_image * gravi_image_wrap_vector (cpl_vector * vector)
2079 {
2080  cpl_ensure (vector, CPL_ERROR_NULL_INPUT, NULL);
2081  cpl_size nx = cpl_vector_get_size (vector);
2082  cpl_size ny = 1;
2083  return cpl_image_wrap_double (nx, ny, cpl_vector_get_data (vector));
2084 }
2085 
2086 cpl_image * gravi_image_from_vector (cpl_vector * vector)
2087 {
2088  cpl_ensure (vector, CPL_ERROR_NULL_INPUT, NULL);
2089  cpl_size nx = cpl_vector_get_size (vector);
2090  cpl_size ny = 1;
2091 
2092  cpl_image * image = cpl_image_new (nx,ny,CPL_TYPE_DOUBLE);
2093  for (cpl_size i = 0; i < nx; i++)
2094  cpl_image_set (image, i+1, 1, cpl_vector_get (vector,i));
2095 
2096  return image;
2097 }
2098 
2099 /*---------------------------------------------------------------------------*/
2110 /*---------------------------------------------------------------------------*/
2111 
2112 double gravi_image_get_quantile (const cpl_image * img, double thr)
2113 {
2114  cpl_ensure (img, CPL_ERROR_NULL_INPUT, -1);
2115  cpl_ensure (thr>0 && thr<1, CPL_ERROR_ILLEGAL_INPUT, -1);
2116 
2117  cpl_size nx = cpl_image_get_size_x (img);
2118  cpl_size ny = cpl_image_get_size_y (img);
2119  cpl_size nq = (cpl_size)(thr * nx * ny);
2120 
2121  cpl_ensure (nq>=0 && nq<=nx*ny, CPL_ERROR_ILLEGAL_INPUT, -1);
2122 
2123  /* Create vector and fill */
2124  int nv;
2125  cpl_vector * vect = cpl_vector_new (nx*ny);
2126  for (cpl_size ix = 0; ix < nx ; ix++)
2127  for (cpl_size iy = 0; iy < ny ; iy++)
2128  cpl_vector_set (vect, ix * ny + iy, cpl_image_get (img, ix+1, iy+1, &nv));
2129 
2130  /* Sort and get quartil */
2131  cpl_vector_sort (vect, CPL_SORT_ASCENDING);
2132  double value = cpl_vector_get (vect, nq);
2133  cpl_vector_delete (vect);
2134 
2135  return value;
2136 }
2137 
2138 /*---------------------------------------------------------------------------*/
2144 /*---------------------------------------------------------------------------*/
2145 
2146 double gravi_array_get_quantile (cpl_array * arr, double thr)
2147 {
2148  cpl_ensure (arr, CPL_ERROR_NULL_INPUT, -1);
2149  cpl_ensure (thr>0 && thr<1, CPL_ERROR_ILLEGAL_INPUT, -1);
2150 
2151  cpl_size nx = cpl_array_get_size (arr);
2152  cpl_size nq = (cpl_size)(thr * nx);
2153 
2154  cpl_ensure (nq>=0 && nq<=nx, CPL_ERROR_ILLEGAL_INPUT, -1);
2155 
2156  /* Create vector and fill */
2157  int nv;
2158  cpl_vector * vect = cpl_vector_new (nx);
2159  for (cpl_size ix = 0; ix < nx ; ix++)
2160  cpl_vector_set (vect, ix, cpl_array_get (arr, ix, &nv));
2161 
2162  /* Sort and get quartil */
2163  cpl_vector_sort (vect, CPL_SORT_ASCENDING);
2164  double value = cpl_vector_get (vect, nq);
2165  cpl_vector_delete (vect);
2166 
2167  return value;
2168 }
2169 
2170 /*---------------------------------------------------------------------------*/
2177 /*---------------------------------------------------------------------------*/
2178 
2179 cpl_size gravi_vector_get_maxpos (cpl_vector * vector)
2180 {
2181  cpl_ensure (vector, CPL_ERROR_NULL_INPUT, -1);
2182  cpl_size size = cpl_vector_get_size (vector);
2183 
2184  cpl_size pos = 0;
2185  double value = cpl_vector_get (vector, 0);
2186  for (int s = 1; s < size; s++) {
2187  if (cpl_vector_get (vector, s) > value) {
2188  pos = s;
2189  value = cpl_vector_get (vector, s);
2190  }
2191  }
2192 
2193  return pos;
2194 }
2195 
2196 /*---------------------------------------------------------------------------*/
2206 /*---------------------------------------------------------------------------*/
2207 double gravi_vector_get_mean_clip (cpl_vector * vector_in,
2208  double percent,
2209  double nsigma)
2210 {
2211  cpl_ensure (vector_in, CPL_ERROR_NULL_INPUT, 0.0);
2212  cpl_ensure (percent > 0, CPL_ERROR_ILLEGAL_INPUT, 0.0);
2213  cpl_ensure (percent < 0.5, CPL_ERROR_ILLEGAL_INPUT, 0.0);
2214  cpl_ensure (nsigma > 0, CPL_ERROR_ILLEGAL_INPUT, 0.0);
2215 
2216  /* Sort */
2217  cpl_vector * sort_vector = cpl_vector_duplicate (vector_in);
2218  cpl_vector_sort (sort_vector, CPL_SORT_ASCENDING);
2219 
2220  /* Clip extrems values */
2221  cpl_size size = cpl_vector_get_size (vector_in);
2222  cpl_size sizeout = size*(1-percent*2);
2223  cpl_size start = (size-sizeout)/2;
2224 
2225  cpl_vector * vector = cpl_vector_new (sizeout);
2226  for (cpl_size i = 0 ; i < sizeout ; i++)
2227  cpl_vector_set (vector, i, cpl_vector_get (sort_vector, i+start));
2228 
2229  /* Clip above several sigmas */
2230  cpl_vector * vector_med = cpl_vector_new (sizeout);
2231  double med = cpl_vector_get_median (vector);
2232  double rms = nsigma * cpl_vector_get_stdev (vector);
2233 
2234  cpl_size size_med = 0;
2235  for (cpl_size i = 0 ; i < cpl_vector_get_size (vector) ; i++)
2236  if ( (cpl_vector_get (vector, i) > med-rms) &&
2237  (cpl_vector_get (vector, i) < med+rms) ) {
2238  cpl_vector_set (vector_med, size_med, cpl_vector_get (vector, i));
2239  size_med++;
2240  }
2241  cpl_vector_set_size (vector_med, size_med);
2242 
2243  /* Compute mean of accepted values */
2244  double output = cpl_vector_get_mean (vector_med);
2245 
2246  FREE (cpl_vector_delete, vector_med);
2247  FREE (cpl_vector_delete, sort_vector);
2248  return output;
2249 }
2250 
2251 /*---------------------------------------------------------------------------*/
2259 /*---------------------------------------------------------------------------*/
2260 
2261 cpl_vector * gravi_vector_extract (const cpl_vector * vector, int start, int step)
2262 {
2263  cpl_size size = cpl_vector_get_size (vector);
2264  cpl_size newsize = size / step;
2265  cpl_vector * out = cpl_vector_new (newsize);
2266 
2267  for (int s = 0; s < newsize; s++)
2268  cpl_vector_set (out, s, cpl_vector_get (vector, s*step+start));
2269 
2270  return out;
2271 }
2272 
2273 /*---------------------------------------------------------------------------*/
2282 /*---------------------------------------------------------------------------*/
2283 
2284 cpl_error_code gravi_vector_unwrap_with_guess (cpl_vector * vector, cpl_vector * ref, double ref_to_phase)
2285 {
2286  cpl_ensure_code (vector, CPL_ERROR_NULL_INPUT);
2287  cpl_ensure_code (ref, CPL_ERROR_NULL_INPUT);
2288 
2289  cpl_size nrow = cpl_vector_get_size (vector);
2290 
2291  double referenced, referenced_prev = 0.0;
2292  cpl_size wrap = 0;
2293 
2294  for (cpl_size row = 0 ; row < nrow; row ++) {
2295  double phase_ref = ref_to_phase * cpl_vector_get (ref, row);
2296 
2297  /* Referenced phase in radian in [0,2pi] */
2298  referenced = (cpl_vector_get (vector, row) - phase_ref);
2299  referenced = fmod (referenced, CPL_MATH_2PI);
2300  if (referenced < 0) referenced += CPL_MATH_2PI;
2301 
2302  /* Check if referenced_phase is wrapp */
2303  if ( referenced - referenced_prev > CPL_MATH_PI ) wrap --;
2304  if ( referenced - referenced_prev < -CPL_MATH_PI ) wrap ++;
2305  referenced_prev = referenced;
2306 
2307  /* Set back in-place */
2308  cpl_vector_set (vector, row, phase_ref + referenced + wrap * CPL_MATH_2PI);
2309  }
2310 
2311  CPLCHECK_MSG ("Cannot unwrap with guess");
2312 
2313  return CPL_ERROR_NONE;
2314 }
2315 
2316 /*---------------------------------------------------------------------------*/
2329 /*---------------------------------------------------------------------------*/
2330 
2331 cpl_error_code gravi_table_multiply_scalar (cpl_table * table, const char * name,
2332  int base, int nbase, double value)
2333 {
2334  cpl_ensure_code (table, CPL_ERROR_NULL_INPUT);
2335  cpl_ensure_code (name, CPL_ERROR_NULL_INPUT);
2336  cpl_ensure_code (nbase==1 || nbase==4 || nbase==6, CPL_ERROR_ILLEGAL_INPUT);
2337  cpl_ensure_code (base>=0 && base <nbase, CPL_ERROR_ILLEGAL_INPUT);
2338 
2339  cpl_size nrow = cpl_table_get_nrow (table) / nbase;
2340 
2341  if (cpl_table_get_column_depth (table, name) > 0) {
2342  cpl_array ** array = cpl_table_get_data_array (table, name);
2343  for (cpl_size row = 0 ; row < nrow ; row ++) {
2344  cpl_array_multiply_scalar (array[row*nbase+base], value);
2345  CPLCHECK_MSG ("Cannot multiply (array may not be numerical)");
2346  }
2347  } else if(cpl_table_get_column_type (table, name) == CPL_TYPE_DOUBLE) {
2348  double * array = cpl_table_get_data_double (table, name);
2349  for (cpl_size row = 0 ; row < nrow ; row ++) {
2350  array[row*nbase+base] *= value;
2351  }
2352  } else if(cpl_table_get_column_type (table, name) == CPL_TYPE_INT) {
2353  int * array = cpl_table_get_data_int (table, name);
2354  for (cpl_size row = 0 ; row < nrow ; row ++) {
2355  array[row*nbase+base] *= value;
2356  }
2357  } else {
2358  return cpl_error_set_message (cpl_func, CPL_ERROR_INVALID_TYPE,
2359  "Column type is not supported");
2360  }
2361 
2362  CPLCHECK_MSG ("Cannot multiply");
2363  return CPL_ERROR_NONE;
2364 }
2365 
2366 /*---------------------------------------------------------------------------*/
2379 /*---------------------------------------------------------------------------*/
2380 
2381 cpl_error_code gravi_table_add_scalar (cpl_table * table, const char * name,
2382  int base, int nbase, double value)
2383 {
2384  cpl_ensure_code (table, CPL_ERROR_NULL_INPUT);
2385  cpl_ensure_code (name, CPL_ERROR_NULL_INPUT);
2386  cpl_ensure_code (nbase==1 || nbase==4 || nbase==6, CPL_ERROR_ILLEGAL_INPUT);
2387  cpl_ensure_code (base>=0 && base <nbase, CPL_ERROR_ILLEGAL_INPUT);
2388 
2389  cpl_size nrow = cpl_table_get_nrow (table) / nbase;
2390 
2391  if (cpl_table_get_column_depth (table, name) > 0) {
2392  cpl_array ** array = cpl_table_get_data_array (table, name);
2393  for (cpl_size row = 0 ; row < nrow ; row ++) {
2394  cpl_array_add_scalar (array[row*nbase+base], value);
2395  CPLCHECK_MSG ("Cannot multiply (array may not be numerical)");
2396  }
2397  } else if(cpl_table_get_column_type (table, name) == CPL_TYPE_DOUBLE) {
2398  double * array = cpl_table_get_data_double (table, name);
2399  for (cpl_size row = 0 ; row < nrow ; row ++) {
2400  array[row*nbase+base] += value;
2401  }
2402  } else if(cpl_table_get_column_type (table, name) == CPL_TYPE_INT) {
2403  int * array = cpl_table_get_data_int (table, name);
2404  for (cpl_size row = 0 ; row < nrow ; row ++) {
2405  array[row*nbase+base] += value;
2406  }
2407  } else {
2408  return cpl_error_set_message (cpl_func, CPL_ERROR_INVALID_TYPE,
2409  "Column type is not supported");
2410  }
2411 
2412  CPLCHECK_MSG ("Cannot multiply");
2413  return CPL_ERROR_NONE;
2414 }
2415 
2416 
2417 /*---------------------------------------------------------------------------*/
2430 /*---------------------------------------------------------------------------*/
2431 
2432 cpl_matrix * gravi_matrix_interpolate_col (cpl_matrix * matrix,
2433  cpl_vector * xref,
2434  cpl_vector * xout)
2435 {
2436  gravi_msg_function_start(0);
2437 
2438  cpl_ensure (matrix, CPL_ERROR_NULL_INPUT, NULL);
2439  cpl_ensure (xref, CPL_ERROR_NULL_INPUT, NULL);
2440  cpl_ensure (xout, CPL_ERROR_NULL_INPUT, NULL);
2441 
2442  cpl_size nrow = cpl_matrix_get_nrow (matrix);
2443  cpl_size ncol = cpl_matrix_get_ncol (matrix);
2444  cpl_size nxref = cpl_vector_get_size (xref);
2445  cpl_size nxout = cpl_vector_get_size (xout);
2446 
2447  cpl_ensure (ncol == nxref, CPL_ERROR_ILLEGAL_INPUT, NULL);
2448  cpl_ensure (nxout > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
2449 
2450  /* Allocate memory */
2451  cpl_matrix * outmatrix = cpl_matrix_new (nrow, nxout);
2452  cpl_vector * yref = cpl_vector_new (nxref);
2453  cpl_vector * yout = cpl_vector_new (nxout);
2454  cpl_bivector * fref = cpl_bivector_wrap_vectors (xref, yref);
2455  cpl_bivector * fout = cpl_bivector_wrap_vectors (xout, yout);
2456 
2457  /* Loop on rows */
2458  for (cpl_size row = 0; row < nrow; row++) {
2459  for (cpl_size x = 0; x < nxref; x++)
2460  cpl_vector_set (yref, x, cpl_matrix_get (matrix, row, x));
2461  cpl_bivector_interpolate_linear (fout, fref);
2462  for (cpl_size x = 0; x < nxout; x++)
2463  cpl_matrix_set (outmatrix, row, x, cpl_vector_get (yout, x));
2464  CPLCHECK_NUL ("Cannot interpolate matrix");
2465  }
2466 
2467  FREE (cpl_bivector_unwrap_vectors, fref);
2468  FREE (cpl_bivector_unwrap_vectors, fout);
2469  FREE (cpl_vector_delete, yref);
2470  FREE (cpl_vector_delete, yout);
2471 
2472  gravi_msg_function_exit(0);
2473  return outmatrix;
2474 }
2475 
2476 /*---------------------------------------------------------------------------*/
2484 /*---------------------------------------------------------------------------*/
2485 
2486 cpl_matrix * gravi_matrix_invertSV_create (cpl_matrix *a_in)
2487 {
2488  gravi_msg_function_start(0);
2489 
2490  cpl_ensure (a_in, CPL_ERROR_NULL_INPUT, NULL);
2491 
2492  cpl_size m = cpl_matrix_get_nrow (a_in);
2493  cpl_size n = cpl_matrix_get_ncol (a_in);
2494 
2495  cpl_vector * w = cpl_vector_new (n);
2496  cpl_matrix * v = cpl_matrix_new (n, n);
2497 
2498  /*
2499  * fill nr matrix with data
2500  * w are the singular values of the matrix
2501  */
2502  cpl_matrix * a_out = svdcmp (a_in, w, v);
2503  CPLCHECK_NUL ("Error in inverse SV");
2504 
2505  /* Check the singular values */
2506  for (cpl_size ii = 0; ii < n; ii++) {
2507  if (cpl_vector_get (w, ii) < 0.1)
2508  cpl_msg_warning (cpl_func, "Singular Value %lld = %e",
2509  ii, cpl_vector_get (w, ii));
2510  }
2511 
2512  /*
2513  * Compute inverse (vt*1/w*at)
2514  */
2515  cpl_matrix * a_inv = cpl_matrix_new (n,m);
2516  double * a_inv_data = cpl_matrix_get_data (a_inv);
2517 
2518  for (cpl_size j = 0; j < m; j++) {
2519  for (cpl_size i = 0; i < n; i++){
2520  double wv_at = 0;
2521 
2522  for (cpl_size ii = 0; ii < n; ii++)
2523  if (cpl_vector_get (w, ii) > 1e-15)
2524  wv_at += cpl_matrix_get (v, i, ii) /
2525  cpl_vector_get (w, ii) *
2526  cpl_matrix_get (a_out, j, ii);
2527 
2528  a_inv_data[j + i * m] = wv_at;
2529  }
2530  }
2531 
2532  /* Delete intermediate matrix */
2533  cpl_vector_delete (w);
2534  cpl_matrix_delete (v);
2535  cpl_matrix_delete (a_out);
2536 
2537  gravi_msg_function_exit(0);
2538  return a_inv;
2539 }
2540 
2541 /*
2542  * pythag fonction from numerical recipe in C,
2543  * necessary for gravi_matrix_invertSV_create
2544  */
2545 double pythag(double a, double b)
2546 {
2547  double absa=fabs(a);
2548  double absb=fabs(b);
2549  if (absa > absb)
2550  return absa*sqrt(1.0+pow(absb/absa, 2));
2551  else
2552  return (absb == 0.0 ? 0.0 : absb*sqrt(1.0+pow(absa/absb, 2)));
2553 }
2554 
2555 /*
2556  * svdcmp fonction from numerical recipe in C
2557  * w and v are pre-allocated results,
2558  * necessary for gravi_matrix_invertSV_create
2559  */
2560 cpl_matrix * svdcmp (cpl_matrix * a_in, cpl_vector * w, cpl_matrix * v)
2561 {
2562  gravi_msg_function_start(0);
2563  cpl_ensure (a_in, CPL_ERROR_NULL_INPUT, NULL);
2564 
2565  int flag, i, its, j, jj, k, l, nm, n, m;
2566  double anorm, c, f, g, h, s, scale, x, y, z;
2567  cpl_vector * rv1;
2568  cpl_matrix * a;
2569 
2570  a = cpl_matrix_duplicate(a_in);
2571  m = cpl_matrix_get_nrow (a_in);
2572  n = cpl_matrix_get_ncol (a_in);
2573  rv1 = cpl_vector_new(n);
2574 
2575  g = scale = anorm = 0.0;
2576  for (i = 0; i < n; i++) {
2577  l = i + 1;
2578  cpl_vector_set(rv1, i, scale*g);
2579  g = s = scale = 0.0;
2580  if (i < m) {
2581  for (k = i; k < m; k++)
2582  scale += fabs(cpl_matrix_get(a, k, i));
2583  if (scale) {
2584 
2585  for (k = i; k < m; k++) {
2586 
2587  cpl_matrix_set (a, k, i, cpl_matrix_get(a, k, i)/scale);
2588  s += cpl_matrix_get(a, k, i) * cpl_matrix_get(a, k, i);
2589  }
2590  f = cpl_matrix_get(a, i, i);
2591  g = -SIGN(sqrt(s),f);
2592  h = f * g - s;
2593  cpl_matrix_set (a, i, i, f - g);
2594  for (j = l; j < n; j++) {
2595  for (s = 0.0, k = i; k < m; k++)
2596  s += cpl_matrix_get(a, k, i) * cpl_matrix_get(a, k, j);
2597 
2598  f = s / h;
2599  for (k = i; k < m; k++)
2600  cpl_matrix_set (a, k, j, cpl_matrix_get(a, k, j) +
2601  f * cpl_matrix_get(a, k, i));
2602 
2603  }
2604  for (k = i; k < m; k++)
2605  cpl_matrix_set (a, k, i, cpl_matrix_get(a, k, i) * scale);
2606 
2607  }
2608  }
2609 
2610  cpl_vector_set(w, i, scale *g);
2611 
2612  g = s = scale = 0.0;
2613  if (i < m && i != (n - 1)) {
2614  for (k = l; k < n; k++)
2615  scale += fabs(cpl_matrix_get(a, i, k));;
2616  if (scale) {
2617  for (k = l; k < n; k++) {
2618  cpl_matrix_set (a, i, k, cpl_matrix_get(a, i, k) / scale);
2619  s += cpl_matrix_get(a, i, k) * cpl_matrix_get(a, i, k);
2620  }
2621  f = cpl_matrix_get(a, i, l);
2622  g = -SIGN(sqrt(s),f);
2623  h = f * g - s;
2624  cpl_matrix_set (a, i, l, f - g);
2625  for (k = l; k < n; k++)
2626  cpl_vector_set(rv1, k, cpl_matrix_get(a, i, k)/h);
2627  for (j = l; j < m; j++) {
2628  for (s = 0.0, k = l; k < n; k++)
2629  s += cpl_matrix_get(a, j, k) * cpl_matrix_get(a, i, k);
2630  for (k = l; k < n; k++)
2631  cpl_matrix_set (a, j, k, cpl_matrix_get(a, j, k) + s * cpl_vector_get(rv1, k));
2632  }
2633  for (k = l; k < n; k++)
2634  cpl_matrix_set (a, i, k, cpl_matrix_get(a, i, k) * scale);
2635  }
2636  }
2637 
2638  anorm = fmax(anorm,(fabs(cpl_vector_get(w, i)) +
2639  fabs(cpl_vector_get(rv1, i))));
2640 
2641  }
2642 
2643  for (i = (n - 1); i >= 0; i--) {
2644  if (i < n) {
2645  if (g) {
2646  for (j = l; j < n; j++)
2647  cpl_matrix_set(v, j, i, (cpl_matrix_get(a, i, j) /
2648  cpl_matrix_get(a, i, l)) / g);
2649 
2650  for (j = l;j < n; j++) {
2651  for (s = 0.0, k = l; k < n; k++)
2652  s += cpl_matrix_get(a, i, k) * cpl_matrix_get(v, k, j);
2653 
2654  for (k = l; k < n; k++)
2655  cpl_matrix_set(v, k, j, cpl_matrix_get(v, k, j) + s *
2656  cpl_matrix_get(v, k, i));
2657 
2658  }
2659  }
2660  for (j = l; j < n; j++) {
2661  cpl_matrix_set(v, i, j, 0.0);
2662  cpl_matrix_set(v, j, i, 0.0);
2663  }
2664  }
2665  cpl_matrix_set(v, i, i, 1.0);
2666 
2667  g = cpl_vector_get(rv1, i);
2668  l = i;
2669  }
2670 
2671  for (i = (IMIN(m,n) - 1); i >= 0; i--) {
2672  l = i + 1;
2673  g = cpl_vector_get(w, i);
2674  for (j = l; j < n; j++)
2675  cpl_matrix_set(a, i, j, 0.0);
2676 
2677  if (g) {
2678  g = 1.0/g;
2679  for (j = l; j < n; j++) {
2680  for (s = 0.0, k = l; k < m; k++)
2681  s += cpl_matrix_get(a, k, i) * cpl_matrix_get(a, k, j);
2682 
2683  f = (s / cpl_matrix_get(a, i, i)) * g;
2684 
2685  for (k = i; k < m; k++)
2686  cpl_matrix_set(a, k, j, cpl_matrix_get(a, k, j) + f *
2687  cpl_matrix_get(a, k, i));
2688 
2689  }
2690  for (j = i; j < m; j++)
2691  cpl_matrix_set(a, j, i, cpl_matrix_get(a, j, i) * g);
2692 
2693  }
2694  else
2695  for (j = i; j < m; j++)
2696  cpl_matrix_set(a, j, i, 0.0);
2697 
2698  cpl_matrix_set(a, i, i, cpl_matrix_get(a, i, i) + 1);
2699 
2700  }
2701 
2702  for (k = (n - 1); k >= 0; k--) {
2703  for (its = 1; its <= 60; its ++) {
2704  flag = 1;
2705 
2706  for (l = k; l >= 0; l--) {
2707  nm = l;
2708  if ((fabs(cpl_vector_get(rv1, l)) + anorm) == anorm) {
2709  flag = 0;
2710  break;
2711  }
2712  if ((fabs(cpl_vector_get(w, nm)) + anorm) == anorm)
2713  break;
2714  }
2715 
2716  if (flag) {
2717  c = 0.0;
2718  s = 1.0;
2719  for (i = l; i <= k; i++) {
2720  f = s * cpl_vector_get(rv1, i);
2721  cpl_vector_set(rv1, i, c * cpl_vector_get(rv1, i));
2722  if ((fabs(f) + anorm) == anorm)
2723  break;
2724  g = cpl_vector_get(w, i);
2725  h = pythag(f,g);
2726  cpl_vector_set(w, i, h);
2727  h = 1.0 / h;
2728  c = g * h;
2729  s = -f * h;
2730  for (j = 0; j < m; j++) {
2731  y = cpl_matrix_get(a, j, nm);
2732  z = cpl_matrix_get(a, j, i);
2733  cpl_matrix_set(a, j, nm, y*c+z*s);
2734  cpl_matrix_set(a, j, i, z*c-y*s);
2735  }
2736  }
2737  }
2738  z = cpl_vector_get(w, k);
2739  if (l == k) {
2740  if (z < 0.0) {
2741  cpl_vector_set(w, k, -z);
2742  for (j = 0; j < n; j++)
2743  cpl_matrix_set(v, j, k, -cpl_matrix_get(v, j, k));
2744 
2745  }
2746  break;
2747  }
2748 
2749  if (its == 120) {
2750  cpl_error_set_message(cpl_func,
2751  CPL_ERROR_ILLEGAL_INPUT,
2752  "no convergence in 120 svdcmp iterations");
2753  cpl_vector_delete(rv1);
2754  cpl_matrix_delete(a);
2755  return NULL;
2756  }
2757  x = cpl_vector_get(w, l);
2758  nm = k ;//- 1;
2759  y = cpl_vector_get(w, nm); ;
2760  g = cpl_vector_get(rv1, nm);
2761  h = cpl_vector_get(rv1, k);
2762  f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y);
2763  g = pythag(f,1.0);
2764  f = ((x - z) * (x + z) + h * ((y / (f + SIGN(g, f))) - h)) / x;
2765  c = s = 1.0;
2766  for (j = l; j < nm; j++) {
2767  i = j+1;
2768  g = cpl_vector_get(rv1, i);
2769  y = cpl_vector_get(w, i);
2770  h = s * g;
2771  g = c * g;
2772  z = pythag(f, h);
2773  cpl_vector_set(rv1, j, z);
2774  c = f / z;
2775  s = h / z;
2776  f = x * c + g * s;
2777  g = g * c - x * s;
2778  h = y * s;
2779  y *= c;
2780  for (jj = 0; jj < n; jj++) {
2781  x = cpl_matrix_get(v, jj, j);
2782  z=cpl_matrix_get(v, jj, i);
2783  cpl_matrix_set(v, jj, j, x*c+z*s);
2784  cpl_matrix_set(v, jj, i, z*c-x*s);
2785  }
2786  z = pythag(f, h);
2787  cpl_vector_set(w, j, z);
2788 
2789  if (z) {
2790  z = 1.0 / z;
2791  c = f * z;
2792  s = h * z;
2793  }
2794  f = c * g + s * y;
2795  x = c * y - s * g;
2796  for (jj = 0; jj < m; jj++) {
2797  y = cpl_matrix_get(a, jj, j);
2798  z = cpl_matrix_get(a, jj, i);
2799  cpl_matrix_set(a, jj, j, y*c+z*s);
2800  cpl_matrix_set(a, jj, i, z*c-y*s);
2801  }
2802  }
2803  cpl_vector_set(rv1, l, 0.0);
2804  cpl_vector_set(rv1, k, f);
2805  cpl_vector_set(w, k, x);
2806  }
2807 
2808  }
2809  cpl_vector_delete(rv1);
2810 
2811  gravi_msg_function_exit(0);
2812  return a;
2813 }
2814 
2815 
2816 /*----------------------------------------------------------------------------*/
2825 /*----------------------------------------------------------------------------*/
2826 cpl_table * gravi_table_extract_time_interval (cpl_table *table, double start, double end)
2827 {
2828  gravi_msg_function_start(1);
2829  cpl_ensure (table, CPL_ERROR_NULL_INPUT, NULL);
2830 
2831  /* Select only interested */
2832  cpl_table_select_all (table);
2833  cpl_table_and_selected_double (table, "TIME", CPL_NOT_LESS_THAN, start);
2834  cpl_table_and_selected_double (table, "TIME", CPL_LESS_THAN, end);
2835  cpl_table * out = cpl_table_extract_selected (table);
2836 
2837  gravi_msg_function_exit(1);
2838  return out;
2839 }
2840 
double gravi_image_get_quantile(const cpl_image *img, double thr)
Compute the quantile of an image.
Definition: gravi_cpl.c:2112
cpl_array * gravi_table_get_column_dimension(const cpl_table *table, const char *name)
Return an array ready for cpl_table_set_column_dimension.
Definition: gravi_cpl.c:1749
cpl_vector * gravi_table_get_vector(cpl_table *spectrum_data, cpl_size index, const char *regname)
Create a vector from the row index of the column regname.
Definition: gravi_cpl.c:1870
cpl_imagelist * gravi_imagelist_from_column(cpl_table *table_data, const char *data_x)
Create an imagelist from a column array in table.
Definition: gravi_cpl.c:1719
cpl_vector * gravi_vector_extract(const cpl_vector *vector, int start, int step)
Extract part of a vector.
Definition: gravi_cpl.c:2261
cpl_error_code gravi_array_add_phasor(cpl_array *input, double complex factor, cpl_array *phase)
Add a REAL phase to a COMPLEX array, in-place: input = input + cexp (factor * phase) ...
Definition: gravi_cpl.c:1021
cpl_array * gravi_array_cexp(double complex factor, const cpl_array *input)
Compute the complex exponention of an array: cexp (factor * input)
Definition: gravi_cpl.c:973
cpl_error_code gravi_table_multiply_scalar(cpl_table *table, const char *name, int base, int nbase, double value)
Multiply scalar or array column by scalar.
Definition: gravi_cpl.c:2331
cpl_matrix * gravi_matrix_interpolate_col(cpl_matrix *matrix, cpl_vector *xref, cpl_vector *xout)
Linear interpolation of matrix column.
Definition: gravi_cpl.c:2432
int gravi_table_are_equal(cpl_table *first, cpl_table *second)
Check if two tables have the same content.
Definition: gravi_cpl.c:1358
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:2826
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:94
cpl_error_code gravi_array_multiply_phasor(cpl_array *input, double complex factor, cpl_array *phase)
Multiply a REAL phase to a COMPLEX array, in-place: input = input * cexp (factor * phase) ...
Definition: gravi_cpl.c:995
cpl_error_code gravi_array_get_group_delay_loop(cpl_array **input, cpl_array *sigma, double *gd, cpl_size nrow, double max_width, int verbose)
Optimized computation of GDELAY for a list of arrays.
Definition: gravi_cpl.c:1187
cpl_error_code gravi_array_add_phase(cpl_array *input, double factor, cpl_array *phase)
Add a REAL phase to a REAL phase array, in-place: input = input + factor * phase. ...
Definition: gravi_cpl.c:1077
cpl_error_code gravi_image_fill(cpl_image *img, double value)
Fill entire image with value.
Definition: gravi_cpl.c:2033
cpl_matrix * gravi_matrix_invertSV_create(cpl_matrix *a_in)
Invers a matrix with singular value decomposition.
Definition: gravi_cpl.c:2486
cpl_array * gravi_array_wrap_image(cpl_image *img)
Wrap the data of na image into an array.
Definition: gravi_cpl.c:1776
cpl_error_code gravi_table_set_string_fixlen(cpl_table *table, const char *name, int row, const char *value, int len)
Set string in table, ensuring fixed length (right space padding). see cpl_table_set_string.
Definition: gravi_cpl.c:605
cpl_error_code gravi_imagelist_unwrap_images(cpl_imagelist *imglist)
Unwrap an imagelist an all its images.
Definition: gravi_cpl.c:1496
double gravi_image_get_noise_window(cpl_image *img, cpl_size llx, cpl_size lly, cpl_size urx, cpl_size ury)
Estimate the median noise in a window. This noise is estimated as the median{img**2}**0.5, so that it is a robust estimate.
Definition: gravi_cpl.c:1608
cpl_image * gravi_image_from_column(cpl_table *table_data, const char *data_x, cpl_size row)
Create an image from a column array in table.
Definition: gravi_cpl.c:1687
double gravi_vector_get_mean_clip(cpl_vector *vector_in, double percent, double nsigma)
Return the mean of a vector after extrema and RMS clipping.
Definition: gravi_cpl.c:2207
cpl_vector * gravi_table_get_vector_diff(cpl_table *spectrum_data, int index, const char *regname1, const char *regname2)
Create a vector from the row index of the column regname.
Definition: gravi_cpl.c:1991
double gravi_array_get_quantile(cpl_array *arr, double thr)
Compute the value of the vector corresponding to the quantile &#39;thr&#39; (0 < thr < 1) ...
Definition: gravi_cpl.c:2146
cpl_error_code gravi_vector_unwrap_with_guess(cpl_vector *vector, cpl_vector *ref, double ref_to_phase)
Unwrap a phase vector following a guess vector. The difference is actually unwrap and shall thus be s...
Definition: gravi_cpl.c:2284
cpl_error_code gravi_table_add_scalar(cpl_table *table, const char *name, int base, int nbase, double value)
Multply scalar or array column by scalar.
Definition: gravi_cpl.c:2381
cpl_size gravi_vector_get_maxpos(cpl_vector *vector)
Return the index of maximum in a vector. If several indexes exists with the maximum value...
Definition: gravi_cpl.c:2179
cpl_error_code gravi_array_add_phasors(cpl_array *input, cpl_array *add, cpl_array *sub)
Add a pair of COMPLEX arrays to a COMPLEX array, in-place: input = input + add*conj(sub) ...
Definition: gravi_cpl.c:1047
cpl_image * gravi_image_wrap_matrix(cpl_matrix *matrix)
Wrap matrix into an image (data not duplicated)
Definition: gravi_cpl.c:2050
cpl_image * gravi_image_wrap_vector(cpl_vector *vector)
Wrap vector into an image (data not duplicated)
Definition: gravi_cpl.c:2078
cpl_imagelist * gravi_imagelist_wrap_column(cpl_table *table_data, const char *data_x)
Wrap a column array of a table into an imagelist.
Definition: gravi_cpl.c:1526
cpl_matrix * get_matrix_from_vector(cpl_vector *vector1, cpl_vector *vector2)
Copy the content of two vector into a newly allocated 2D matrix.
Definition: gravi_cpl.c:1820