57 #include "gravi_data.h" 58 #include "gravi_dfs.h" 59 #include "gravi_pfits.h" 60 #include "gravi_cpl.h" 62 #include "gravi_utils.h" 63 #include "gravi_ellipse.h" 64 #include "gravi_p2vm.h" 70 #define GRAVI_DEFAULT_LBD_MIN 1.99e-6 71 #define GRAVI_DEFAULT_LBD_MAX 2.45e-6 72 #define GRAVI_LOW_LBD_MIN 2.0000e-6 73 #define GRAVI_LOW_LBD_MAX 2.481e-6 83 cpl_propertylist * header,
84 gravi_data *wave_param);
87 cpl_table * detector_table,
113 gravi_msg_function_start(0);
114 cpl_ensure (detector_table, CPL_ERROR_NULL_INPUT, NULL);
115 cpl_ensure (nwave>0, CPL_ERROR_ILLEGAL_INPUT, NULL);
119 int n_region = cpl_table_get_nrow (detector_table);
122 cpl_table * p2vm_table = cpl_table_new (n_region);
125 cpl_table_duplicate_column (p2vm_table,
"REGNAME",
126 detector_table,
"REGNAME");
128 cpl_table_new_column_array (p2vm_table,
"TRANSMISSION", CPL_TYPE_FLOAT,
131 cpl_table_new_column_array (p2vm_table,
"COHERENCE", CPL_TYPE_FLOAT,
132 nwave * (ntel * (ntel - 1) / 2));
134 cpl_table_new_column_array (p2vm_table,
"PHASE", CPL_TYPE_FLOAT,
135 nwave * (ntel * (ntel - 1) / 2));
137 cpl_table_new_column_array (p2vm_table,
"C MATRIX", CPL_TYPE_FLOAT,
138 nwave * (ntel * (ntel - 1) / 2));
141 cpl_array * zero_array_transmission, * zero_array;
142 zero_array_transmission = cpl_array_new (nwave*ntel, CPL_TYPE_FLOAT);
143 cpl_array_fill_window_float (zero_array_transmission, 0, nwave*ntel, 0);
145 zero_array = cpl_array_new (nwave*(ntel*(ntel-1)/2),
147 cpl_array_fill_window_float (zero_array, 0,
148 nwave * (ntel * (ntel - 1) / 2), 0);
151 for (
int i = 0; i < n_region; i++){
152 cpl_table_set_array (p2vm_table,
"TRANSMISSION", i, zero_array_transmission);
153 cpl_table_set_array (p2vm_table,
"COHERENCE", i, zero_array);
154 cpl_table_set_array (p2vm_table,
"PHASE", i, zero_array);
155 cpl_table_set_array (p2vm_table,
"C MATRIX", i, zero_array);
158 cpl_array * dimensions;
159 dimensions = cpl_array_new (2, CPL_TYPE_INT);
162 cpl_array_set_int (dimensions, 0, nwave);
163 cpl_array_set_int (dimensions, 1, ntel);
164 cpl_table_set_column_dimensions (p2vm_table,
"TRANSMISSION", dimensions);
167 cpl_array_set_int (dimensions, 1, (ntel*(ntel-1)/2));
168 cpl_table_set_column_dimensions (p2vm_table,
"COHERENCE", dimensions);
171 cpl_array_set_int (dimensions, 1, (ntel*(ntel-1)/2));
172 cpl_table_set_column_dimensions (p2vm_table,
"PHASE", dimensions);
174 cpl_table_set_column_dimensions (p2vm_table,
"C MATRIX", dimensions);
176 FREE (cpl_array_delete, zero_array_transmission);
177 FREE (cpl_array_delete, zero_array);
178 FREE (cpl_array_delete, dimensions);
180 gravi_msg_function_exit(0);
199 cpl_propertylist * header,
200 gravi_data *wave_param)
202 gravi_msg_function_start(1);
203 cpl_ensure (wave_table, CPL_ERROR_NULL_INPUT, NULL);
204 cpl_ensure (header, CPL_ERROR_NULL_INPUT, NULL);
231 double * calib_eff_wave;
235 if ( cpl_table_has_column(calib_eff_table ,
"FBAND_WAVE") ) {
236 calib_eff_wave = cpl_table_get_data_double (calib_eff_table,
"FBAND_WAVE");
237 cpl_msg_info(cpl_func,
"calib_eff_wave [0] : %e", calib_eff_wave[0] );
238 cpl_msg_info(cpl_func,
"calib_eff_wave [1] : %e", calib_eff_wave[1] );
239 cpl_msg_info(cpl_func,
"calib_eff_wave [2] : %e", calib_eff_wave[2] );
240 cpl_msg_info(cpl_func,
"calib_eff_wave [3] : %e", calib_eff_wave[3] );
243 cpl_msg_error(cpl_func,
"Cannot get the default values for calib_eff_wave");
253 double gravi_high_lbd_min = cpl_propertylist_get_double (
gravi_data_get_plist(wave_param,GRAVI_PRIMARY_HDR_EXT),
"ESO OIWAVE HIGH LBD MIN");
254 cpl_msg_info (cpl_func,
"gravi_high_lbd_min : %e", gravi_high_lbd_min);
256 double gravi_high_lbd_max = cpl_propertylist_get_double (
gravi_data_get_plist(wave_param,GRAVI_PRIMARY_HDR_EXT),
"ESO OIWAVE HIGH LBD MAX");
257 cpl_msg_info (cpl_func,
"gravi_high_lbd_max : %e", gravi_high_lbd_max);
259 double gravi_med_lbd_min = cpl_propertylist_get_double (
gravi_data_get_plist(wave_param,GRAVI_PRIMARY_HDR_EXT),
"ESO OIWAVE MED LBD MIN");
260 cpl_msg_info (cpl_func,
"gravi_med_lbd_min : %e", gravi_med_lbd_min);
262 double gravi_med_lbd_max = cpl_propertylist_get_double (
gravi_data_get_plist(wave_param,GRAVI_PRIMARY_HDR_EXT),
"ESO OIWAVE MED LBD MAX");
263 cpl_msg_info (cpl_func,
"gravi_med_lbd_max : %e", gravi_med_lbd_max);
265 double gravi_low_lbd_min = cpl_propertylist_get_double (
gravi_data_get_plist(wave_param,GRAVI_PRIMARY_HDR_EXT),
"ESO OIWAVE LOW LBD MIN");
266 cpl_msg_info (cpl_func,
"gravi_low_lbd_min : %e", gravi_low_lbd_min);
268 double gravi_low_lbd_max = cpl_propertylist_get_double (
gravi_data_get_plist(wave_param,GRAVI_PRIMARY_HDR_EXT),
"ESO OIWAVE LOW LBD MAX");
269 cpl_msg_info (cpl_func,
"gravi_low_lbd_max : %e", gravi_low_lbd_max);
278 CPLCHECK_NUL (
"Cannot read the QC MINWAVE MAXWAVE");
281 int n_element = cpl_table_get_column_depth (wave_table,
"DATA1");
282 CPLCHECK_NUL (
"Cannot get the number of elements");
283 double max_wave ,min_wave ;
288 max_wave = gravi_low_lbd_max;
289 min_wave = gravi_low_lbd_min;
290 cpl_msg_info (cpl_func,
"Using Low resolution wavelength table");
295 max_wave = gravi_high_lbd_max;
296 min_wave = gravi_high_lbd_min;
297 cpl_msg_info (cpl_func,
"Using High/Med resolution wavelength table");
299 CPLCHECK_NUL (
"Cannot get the max_wave and min_wave");
303 CPLCHECK_NUL (
"Cannot define the limits");
306 cpl_table * oiwave_table = cpl_table_new (nwave);
308 cpl_table_new_column (oiwave_table,
"EFF_WAVE", CPL_TYPE_FLOAT);
309 cpl_table_set_column_unit (oiwave_table,
"EFF_WAVE",
"m");
311 cpl_table_new_column (oiwave_table,
"EFF_BAND", CPL_TYPE_FLOAT);
312 cpl_table_set_column_unit (oiwave_table,
"EFF_BAND",
"m");
316 for (cpl_size wave = 0; wave < nwave; wave++){
317 double lambda = min_wave + wave * (max_wave-min_wave)/(nwave-1);
318 cpl_table_set (oiwave_table,
"EFF_WAVE", wave, lambda);
320 cpl_table_set (oiwave_table,
"EFF_BAND", wave, (max_wave-min_wave)/(nwave-1)*2);
322 if (nwave == 14) cpl_table_set (oiwave_table,
"EFF_BAND", wave, calib_eff_wave[wave]);
328 gravi_msg_function_exit(1);
347 cpl_table * detector_table,
350 gravi_msg_function_start(1);
351 cpl_ensure (wave_table, CPL_ERROR_NULL_INPUT, NULL);
352 cpl_ensure (detector_table, CPL_ERROR_NULL_INPUT, NULL);
353 cpl_ensure (pol == 0 || pol == 1, CPL_ERROR_ILLEGAL_INPUT, NULL);
356 cpl_size nwave = gravi_spectrum_get_nwave (wave_table);
357 cpl_size nreg = cpl_table_get_nrow (detector_table);
360 cpl_table * oiwave_table = cpl_table_new (nwave);
362 cpl_table_new_column (oiwave_table,
"EFF_WAVE", CPL_TYPE_FLOAT);
363 cpl_table_set_column_unit (oiwave_table,
"EFF_WAVE",
"m");
365 cpl_table_new_column (oiwave_table,
"EFF_BAND", CPL_TYPE_FLOAT);
366 cpl_table_set_column_unit (oiwave_table,
"EFF_BAND",
"m");
369 for (cpl_size wave = 0; wave < nwave; wave++) {
370 double lambda = (wave == nwave-1) ? 1.0 : 0.0;
373 for (
int reg = 0; reg < nreg; reg++) {
375 double value = gravi_table_get_value (wave_table, GRAVI_DATA[reg], 0, wave);
377 if (wave == 0) lambda = CPL_MAX (lambda, value + 0.00001e-6);
378 else if (wave == nwave-1) lambda = CPL_MIN (lambda, value - 0.00001e-6);
379 else lambda += value / 24.0;
381 cpl_msg_info (cpl_func,
"lbd[%lld] = %g [um]", wave, lambda*1e6);
383 cpl_table_set (oiwave_table,
"EFF_WAVE", wave, lambda);
384 cpl_table_set (oiwave_table,
"EFF_BAND", wave, 8.5e-8);
395 gravi_msg_function_exit(1);
416 cpl_table * oiwave_table;
419 gravi_msg_function_start(1);
420 cpl_ensure (wave_map, CPL_ERROR_NULL_INPUT, NULL);
422 cpl_propertylist * wave_header = gravi_data_get_header (wave_map);
423 CPLCHECK_NUL (
"Cannot load data");
430 CPLCHECK_NUL (
"Cannot copy tables");
433 for (
int type_data = 0; type_data < 2 ; type_data++) {
436 if (!gravi_data_has_wave (wave_map, type_data)) {
437 cpl_msg_info (cpl_func,
"No data for %s, skip it", GRAVI_TYPE(type_data));
443 CPLCHECK_NUL (
"Cannot copy tables");
446 cpl_table * wave_table = gravi_data_get_wave_data (wave_map, type_data);
447 cpl_table * detector_table = gravi_data_get_imaging_detector (wave_map, type_data);
448 CPLCHECK_NUL (
"Cannot get data");
455 int n_pol = gravi_spectrum_get_npol (wave_table);
456 for (
int pol = 0 ; pol<n_pol ; pol++) {
458 if (type_data == GRAVI_SC)
471 cpl_propertylist * oiwave_plist = cpl_propertylist_new ();
472 cpl_propertylist_append_int (oiwave_plist,
"NWAVE", cpl_table_get_nrow (oiwave_table));
473 cpl_propertylist_update_int (oiwave_plist,
"OI_REVN", 1);
474 cpl_propertylist_append_string (oiwave_plist,
"INSNAME", GRAVI_INSNAME(type_data,pol,n_pol));
475 cpl_propertylist_append_int (oiwave_plist,
"EXTVER", GRAVI_EXTVER(type_data,pol,n_pol));
479 GRAVI_OI_WAVELENGTH_EXT, oiwave_table);
480 CPLCHECK_NUL (
"Cannot add the table");
486 cpl_size n_wave = cpl_table_get_nrow (oiwave_table);
489 cpl_table * p2vm_table;
493 cpl_propertylist * p2vm_plist = cpl_propertylist_new();
494 CPLCHECK_NUL (
"Cannot create propertylist");
497 const char * extname = (type_data == GRAVI_SC ? GRAVI_P2VM_DATA_SC_EXT : GRAVI_P2VM_DATA_FT_EXT);
500 CPLCHECK_NUL (
"Cannot create P2VM");
503 gravi_msg_function_exit(1);
548 int ** valid_trans,
int ** valid_pair,
549 enum gravi_detector_type det_type)
551 gravi_msg_function_start(1);
552 cpl_ensure_code (p2vm_map, CPL_ERROR_NULL_INPUT);
553 cpl_ensure_code (preproc_data, CPL_ERROR_NULL_INPUT);
560 int init_type_data = 1;
561 int end_type_data = 1;
562 if(det_type == GRAVI_DET_SC || det_type == GRAVI_DET_ALL)
564 if(det_type == GRAVI_DET_FT || det_type == GRAVI_DET_ALL)
566 for (
int type_data = init_type_data; type_data <= end_type_data; type_data++ ) {
569 if (!gravi_data_has_spectrum (preproc_data, type_data)) {
570 cpl_msg_info (cpl_func,
"No data for %s, skip it", GRAVI_TYPE(type_data));
575 cpl_propertylist * preproc_header = gravi_data_get_header (preproc_data);
578 cpl_table * detector_table, * spectrum_table, * p2vm_table;
579 detector_table = gravi_data_get_imaging_detector (preproc_data, type_data);
580 spectrum_table = gravi_data_get_spectrum_data (preproc_data, type_data);
581 p2vm_table = gravi_data_get_p2vm_data (p2vm_map, type_data);
583 cpl_ensure_code (detector_table, CPL_ERROR_ILLEGAL_INPUT);
584 cpl_ensure_code (spectrum_table, CPL_ERROR_ILLEGAL_INPUT);
585 cpl_ensure_code (p2vm_table, CPL_ERROR_ILLEGAL_INPUT);
588 int n_region = cpl_table_get_nrow (detector_table);
589 int npol = n_region > 24 ? npol = 2 : 1;
595 int nwave = cpl_table_get_nrow (oiwave_tables[0]);
598 cpl_array ** transmission, ** coherence, ** phase, ** norma_m;
599 coherence = cpl_table_get_data_array (p2vm_table,
"COHERENCE");
600 phase = cpl_table_get_data_array (p2vm_table,
"PHASE");
601 norma_m = cpl_table_get_data_array (p2vm_table,
"C MATRIX");
602 transmission = cpl_table_get_data_array (p2vm_table,
"TRANSMISSION");
605 int tel = -1, base = -1;
606 if (gravi_check_shutter (preproc_header,1,0,0,0)) tel = 0;
607 if (gravi_check_shutter (preproc_header,0,1,0,0)) tel = 1;
608 if (gravi_check_shutter (preproc_header,0,0,1,0)) tel = 2;
609 if (gravi_check_shutter (preproc_header,0,0,0,1)) tel = 3;
610 if (gravi_check_shutter (preproc_header,1,1,0,0)) base = 0;
611 if (gravi_check_shutter (preproc_header,1,0,1,0)) base = 1;
612 if (gravi_check_shutter (preproc_header,1,0,0,1)) base = 2;
613 if (gravi_check_shutter (preproc_header,0,1,1,0)) base = 3;
614 if (gravi_check_shutter (preproc_header,0,1,0,1)) base = 4;
615 if (gravi_check_shutter (preproc_header,0,0,1,1)) base = 5;
616 cpl_ensure_code (tel>=0 || base>=0, CPL_ERROR_ILLEGAL_INPUT);
622 valid_trans[type_data][tel] = 1;
624 cpl_msg_info (cpl_func,
"Compute the transmission of " 625 "tel %d for %s", tel+1, GRAVI_TYPE(type_data));
628 cpl_image * imgflux = NULL;
629 cpl_image ** spectrum_img;
630 spectrum_img = cpl_calloc (n_region,
sizeof(cpl_image*));
632 for (cpl_size region = 0; region < n_region; region++){
635 cpl_imagelist * spectrum_imglist;
639 spectrum_img[region] = cpl_imagelist_collapse_median_create (spectrum_imglist);
645 imgflux = cpl_image_duplicate (spectrum_img[region]);
647 cpl_image_add (imgflux, spectrum_img[region]);
651 double max_flux = cpl_image_get_flux (imgflux);
654 for (cpl_size region = 0; region < n_region; region++){
657 cpl_image_divide_scalar (spectrum_img[region], max_flux);
660 for (cpl_size wave = 0; wave < nwave; wave++) {
661 double value = cpl_image_get (spectrum_img[region], wave+1, 1, &nv);
662 cpl_array_set (transmission[region],
663 wave + nwave * tel, value);
666 CPLCHECK_MSG (
"Cannot compute transmission");
669 FREELOOP (cpl_image_delete, spectrum_img, n_region);
670 FREE (cpl_image_delete, imgflux);
678 int tel1 = GRAVI_BASE_TEL[base][0];
679 int tel2 = GRAVI_BASE_TEL[base][1];
681 valid_pair[type_data][base] = 1;
683 cpl_msg_info(cpl_func,
"Compute the coherence and " 684 "phase of pair (%d,%d) for %s", tel1+1,
685 tel2+1, GRAVI_TYPE(type_data));
688 int nrow = cpl_table_get_nrow (spectrum_table);
695 cpl_vector * mean_opd;
697 oiwave_tables, NULL, base);
698 CPLCHECK_MSG (
"Cannot compute opd");
704 for (cpl_size wave = 0; wave < nwave; wave++){
714 cpl_matrix ** inv_matrixes = cpl_calloc (npol,
sizeof(cpl_matrix *));
716 for (
int pol = 0; pol < npol; pol ++) {
717 cpl_matrix * model_matrix = cpl_matrix_new (nrow, 3);
719 for (cpl_size row = 0; row < nrow; row++) {
720 cpl_matrix_set (model_matrix, row, 0, 1.0);
721 double lambda = cpl_table_get (oiwave_tables[pol],
"EFF_WAVE", wave, NULL);
722 double phi = cpl_vector_get (mean_opd, row) / lambda * CPL_MATH_2PI;
723 double enveloppe = cpl_vector_get (envelope_vector, row);
724 cpl_matrix_set (model_matrix, row, 1, sin(phi)*enveloppe);
725 cpl_matrix_set (model_matrix, row, 2, cos(phi)*enveloppe);
730 FREE (cpl_matrix_delete, model_matrix);
734 for (cpl_size region = 0; region < n_region; region ++){
738 cpl_vector * y_window;
746 cpl_vector * init_val = cpl_vector_new(3);
748 for (cpl_size j = 0; j < 3; j++){
750 for (cpl_size i = 0; i < nrow; i++){
751 comp += cpl_matrix_get (inv_matrixes[pol], j, i) * cpl_vector_get (y_window, i);
753 cpl_vector_set (init_val, j, comp);
757 double coherence_fit =
758 sqrt( pow (cpl_vector_get(init_val, 2), 2) +
759 pow (cpl_vector_get(init_val, 1), 2));
761 cpl_array_set (coherence[region], wave + nwave *
762 base, coherence_fit);
766 phase_fit = atan2( cpl_vector_get(init_val, 2),
767 cpl_vector_get(init_val, 1));
769 cpl_array_set (phase[region], wave + nwave * base,
773 cpl_array_set (norma_m[region], wave + nwave * base,
774 cpl_vector_get (init_val,0));
776 FREE (cpl_vector_delete, init_val);
777 FREE (cpl_vector_delete, y_window);
780 FREELOOP (cpl_matrix_delete, inv_matrixes, npol);
781 FREE (cpl_vector_delete, envelope_vector);
784 FREE (cpl_vector_delete, mean_opd);
787 FREE (cpl_free, oiwave_tables);
790 CPLCHECK_MSG (
"Cannot compute the P2VM");
794 gravi_msg_function_exit(1);
795 return CPL_ERROR_NONE;
840 int ntel = 4, n_base = 6;
844 gravi_msg_function_start(1);
845 cpl_ensure_code (p2vm_map, CPL_ERROR_NULL_INPUT);
846 cpl_ensure_code (valid_trans, CPL_ERROR_NULL_INPUT);
847 cpl_ensure_code (valid_pair, CPL_ERROR_NULL_INPUT);
849 cpl_propertylist * p2vm_header = gravi_data_get_header (p2vm_map);
854 for (
int type_data = 0; type_data < 2; type_data ++){
857 if (!gravi_data_has_p2vm (p2vm_map, type_data)) {
858 cpl_msg_info (cpl_func,
"No data for %s, skip it", GRAVI_TYPE(type_data));
862 cpl_msg_info (cpl_func,
"Normalisation of P2VM for %s",
863 GRAVI_TYPE(type_data));
866 cpl_table * p2vm_table, * detector_table;
867 detector_table = gravi_data_get_imaging_detector (p2vm_map, type_data);
868 p2vm_table = gravi_data_get_p2vm_data (p2vm_map, type_data);
871 cpl_size n_region = cpl_table_get_nrow (detector_table);
872 int n_pol = n_region > 24 ? 2 : 1;
875 cpl_table * oiwave_table;
876 oiwave_table = gravi_data_get_oi_wave (p2vm_map, type_data, 0, n_pol);
877 cpl_size nwave = cpl_table_get_nrow (oiwave_table);
878 cpl_ensure_code (nwave, CPL_ERROR_ILLEGAL_INPUT);
881 cpl_array ** transmission, ** coherence, ** phase;
882 coherence = cpl_table_get_data_array (p2vm_table,
"COHERENCE");
883 phase = cpl_table_get_data_array (p2vm_table,
"PHASE");
884 transmission = cpl_table_get_data_array (p2vm_table,
"TRANSMISSION");
891 for (
int pol = 0; pol < n_pol; pol++) {
892 for (
int base = 0; base < 6; base++){
895 if ( !valid_pair[type_data][base])
continue;
903 for (cpl_size i = 0; i < cpl_array_get_size(phase[0]); i++){
905 double valA = cpl_array_get (phase[iA], i, NULL);
906 cpl_array_set (phase[iA], i, 0.0);
908 double valB = cpl_array_get (phase[iB], i, NULL) - valA;
909 if (valB < 0) valB += CPL_MATH_2PI;
910 cpl_array_set (phase[iB], i, valB);
912 double valC = cpl_array_get (phase[iC], i, NULL) - valA;
913 if (valC < 0) valC += CPL_MATH_2PI;
914 cpl_array_set (phase[iC], i, valC);
916 double valD = cpl_array_get (phase[iD], i, NULL) - valA;
917 if (valD < 0) valD += CPL_MATH_2PI;
918 cpl_array_set (phase[iD], i, valD);
920 CPLCHECK_MSG (
"Cannot unwrap AC and BD of P2VM");
925 CPLCHECK_MSG (
"Cannot compute P2VM");
932 int ntrans = cpl_array_get_size (transmission[0]);
933 cpl_array * mean_transmission = cpl_array_new (ntrans, CPL_TYPE_FLOAT);
934 cpl_array_fill_window (mean_transmission, 0, ntrans, 0.);
936 for (cpl_size region = 0; region < n_region; region++) {
937 cpl_array_add (mean_transmission,transmission[region]);
939 cpl_array_divide_scalar (mean_transmission, n_region);
942 for (cpl_size region = 0; region < n_region; region++){
943 cpl_array_divide (transmission[region], mean_transmission);
945 FREE (cpl_array_delete, mean_transmission);
952 double mean_flux[4] = {0.0,0.0,0.0,0.0};
953 int n_flux[4] = {0,0,0,0};
956 for (
int base = 0; base < 6; base++) {
957 int tel0 = GRAVI_BASE_TEL[base][0];
958 int tel1 = GRAVI_BASE_TEL[base][1];
961 for (cpl_size wave = 0; wave < nwave; wave++){
964 cpl_matrix * matrix_T = cpl_matrix_new (n_region, 4);
968 cpl_matrix * matrix_c = cpl_matrix_new (n_region, 1);
969 for(cpl_size region = 0; region < n_region; region++) {
970 cpl_matrix_set (matrix_c, region, 0, cpl_vector_get (vector_c, region));
971 for (
int tel = 0; tel < ntel; tel++){
972 cpl_matrix_set (matrix_T, region, tel,
973 cpl_array_get (transmission[region],
974 tel*nwave+wave ,&nv));
977 FREE (cpl_vector_delete, vector_c);
980 cpl_errorstate prestate = cpl_errorstate_get();
982 cpl_matrix * matrix_I = cpl_matrix_solve_normal (matrix_T, matrix_c);
985 if (! strcmp(
"Singular matrix", cpl_error_get_message())){
986 cpl_msg_warning(cpl_func,
"matrix_c or matrix_T " 987 "are singular for tel1 = %d tel2 = %d and wave = %lld",
989 cpl_errorstate_set (prestate);
990 cpl_matrix_delete (matrix_T);
991 cpl_matrix_delete (matrix_I);
992 cpl_matrix_delete (matrix_c);
997 mean_flux[tel0] += cpl_matrix_get (matrix_I, tel0, 0);
998 mean_flux[tel1] += cpl_matrix_get (matrix_I, tel1, 0);
1003 double F0 = cpl_matrix_get (matrix_I, tel0, 0);
1004 double F1 = cpl_matrix_get (matrix_I, tel1, 0);
1005 double coeff = sqrt (fabs(F0*F1));
1009 for (cpl_size region = 0; region < n_region; region++){
1010 double value = cpl_array_get (coherence[region],
1011 wave+nwave*base, &nv);
1012 cpl_array_set (coherence[region],
1018 FREE (cpl_matrix_delete, matrix_c);
1019 FREE (cpl_matrix_delete, matrix_I);
1020 FREE (cpl_matrix_delete, matrix_T);
1031 for (
int tel = 0; tel<4; tel++ ) {
1032 cpl_msg_info (cpl_func,
"Mean flux tel%i = %f (n=%i)", tel, mean_flux[tel] / n_flux[tel], n_flux[tel]);
1033 sprintf (qc_name,
"ESO QC FLUX_%s%i AVG", GRAVI_TYPE(type_data), tel);
1034 cpl_propertylist_append_double (p2vm_header, qc_name, mean_flux[tel] / n_flux[tel]);
1035 cpl_propertylist_set_comment (p2vm_header, qc_name,
"[e/DIT/chanel/output/file] mean flux");
1045 cpl_array * sig_phi_arr = cpl_array_new(n_region, CPL_TYPE_DOUBLE);
1046 cpl_array * sig_coh_arr = cpl_array_new(n_region, CPL_TYPE_DOUBLE);
1047 cpl_array * mean_coh_arr = cpl_array_new(n_region, CPL_TYPE_DOUBLE);
1048 cpl_array * mean_coh_base_arr = cpl_array_new(n_base, CPL_TYPE_DOUBLE);
1049 cpl_array * min_coh_base_arr = cpl_array_new(n_base, CPL_TYPE_DOUBLE);
1050 cpl_array * mean_trans_arr = cpl_array_new(n_region, CPL_TYPE_DOUBLE);
1051 cpl_array * sig_transdiff_arr = cpl_array_new(n_region, CPL_TYPE_DOUBLE);
1053 cpl_array_fill_window (mean_coh_base_arr, 0, n_base, 0);
1054 cpl_array_fill_window (min_coh_base_arr, 0, n_base, 10);
1057 for (cpl_size region = 0; region < n_region; region ++ ) {
1061 int tel0 = GRAVI_BASE_TEL[base][0];
1062 int tel1 = GRAVI_BASE_TEL[base][1];
1065 cpl_array * coh_region = cpl_array_extract (coherence[region],
1067 cpl_array * trans_tel1 = cpl_array_extract (transmission[region],
1069 cpl_array * trans_tel2 = cpl_array_extract (transmission[region],
1071 cpl_array * ph_region = cpl_array_extract (phase[region],
1075 cpl_array_set (mean_coh_arr, region,
1076 cpl_array_get_mean (coh_region));
1078 cpl_array_set (sig_coh_arr, region,
1079 cpl_array_get_stdev (coh_region));
1081 cpl_array_set (mean_trans_arr, region,
1082 (cpl_array_get_mean (trans_tel1) +
1083 cpl_array_get_mean (trans_tel2)) /2);
1085 cpl_array_set (sig_phi_arr, region,
1086 cpl_array_get_stdev (ph_region));
1088 cpl_array * diff_trans;
1089 diff_trans = cpl_array_duplicate (trans_tel1);
1090 cpl_array_subtract (diff_trans, trans_tel2);
1091 cpl_array_set (sig_transdiff_arr, region,
1092 cpl_array_get_stdev (diff_trans));
1093 cpl_array_delete (diff_trans);
1096 cpl_array_power (trans_tel1, 0.5);
1097 cpl_array_power (trans_tel2, 0.5);
1098 cpl_array_divide (coh_region, trans_tel1);
1099 cpl_array_divide (coh_region, trans_tel2);
1100 cpl_array_divide_scalar (coh_region, 2.);
1103 cpl_array_set (mean_coh_base_arr, base,
1104 cpl_array_get (mean_coh_base_arr, base, NULL) +
1105 cpl_array_get_mean (coh_region)/(n_region/6));
1110 if (cpl_array_get(min_coh_base_arr, base, NULL) > min_percentile)
1111 cpl_array_set(min_coh_base_arr, base, min_percentile);
1114 cpl_array_delete (coh_region);
1115 cpl_array_delete (trans_tel2);
1116 cpl_array_delete (trans_tel1);
1117 cpl_array_delete (ph_region);
1121 CPLCHECK_MSG (
"Cannot compute_the averages values per region");
1124 double mean_coh, sig_coh, sig_phi;
1125 mean_coh = cpl_array_get_mean (mean_coh_arr) /
1126 (2*cpl_array_get_mean (mean_trans_arr));
1127 sig_coh = cpl_array_get_mean (sig_coh_arr) /
1128 (2*cpl_array_get_mean (mean_trans_arr));
1129 sig_phi = cpl_array_get_mean (sig_phi_arr);
1130 CPLCHECK_MSG (
"Cannot compute averaged values");
1133 cpl_propertylist_update_double (p2vm_header, (type_data)?QC_MEANCOH_FT:QC_MEANCOH_SC,
1135 cpl_propertylist_update_double (p2vm_header, (type_data)?QC_RMSCOH_FT:QC_RMSCOH_SC,
1137 cpl_propertylist_update_double (p2vm_header, (type_data)?QC_RMSPHASE_FT:QC_RMSPHASE_SC,
1139 cpl_msg_info (cpl_func,
"QC %s COH_AVG = %e COH_RMS %e PHASE_RMS = %e",
1140 GRAVI_TYPE(type_data), mean_coh, (sig_coh), sig_phi);
1143 for (
int base=0; base< n_base; base++){
1144 sprintf (qc_name,
"ESO QC P2VM_COHERENCE_%s%s", GRAVI_TYPE(type_data), GRAVI_BASE_NAME[base]);
1145 cpl_propertylist_update_double (p2vm_header, qc_name,
1146 cpl_array_get (mean_coh_base_arr, base, NULL));
1147 cpl_propertylist_set_comment (p2vm_header, qc_name,
1148 "Avg coh. over lbd per baseline");
1150 sprintf (qc_name,
"ESO QC P2VM_MINCOHERENCE_%s%s", GRAVI_TYPE(type_data), GRAVI_BASE_NAME[base]);
1151 cpl_propertylist_update_double (p2vm_header, qc_name,
1152 cpl_array_get (min_coh_base_arr, base, NULL));
1153 cpl_propertylist_set_comment (p2vm_header, qc_name,
1154 "Min coh. (5 perc) over lbd per baseline");
1156 CPLCHECK_MSG (
"Cannot append QC params");
1158 FREE (cpl_array_delete, sig_phi_arr);
1159 FREE (cpl_array_delete, sig_coh_arr);
1160 FREE (cpl_array_delete, mean_coh_arr);
1161 FREE (cpl_array_delete, mean_trans_arr);
1162 FREE (cpl_array_delete, sig_transdiff_arr);
1163 FREE (cpl_array_delete, mean_coh_base_arr);
1164 FREE (cpl_array_delete, min_coh_base_arr);
1168 gravi_msg_function_exit(1);
1169 return CPL_ERROR_NONE;
1196 gravi_data * p2vmred_data,
1199 gravi_msg_function_start(1);
1200 cpl_ensure_code (p2vm_map, CPL_ERROR_NULL_INPUT);
1201 cpl_ensure_code (p2vmred_data, CPL_ERROR_NULL_INPUT);
1206 cpl_propertylist * p2vmred_header = gravi_data_get_header (p2vmred_data);
1211 for (
int type_data = 0; type_data < 2; type_data ++) {
1214 if (!gravi_data_has_p2vm (p2vm_map, type_data)) {
1215 cpl_msg_info (cpl_func,
"No data for %s in P2VM, skip it", GRAVI_TYPE(type_data));
1219 cpl_msg_info (cpl_func,
"Calibrate the internal phase of %s (%s)",
1220 GRAVI_TYPE(type_data),full_phase?
"full phases":
"closure phases");
1223 cpl_array ** visphase = cpl_calloc (12,
sizeof(cpl_array*));
1226 int npol = gravi_pfits_get_pola_num (p2vmred_header, type_data);
1227 for (
int pol= 0 ; pol < npol ; pol++ ) {
1229 cpl_msg_info (cpl_func,
"Compute correction for pol %i over %i", pol+1, npol);
1232 cpl_table * oi_wave = gravi_data_get_oi_wave (p2vmred_data, type_data, pol, npol);
1233 cpl_table * oi_vis = gravi_data_get_oi_vis (p2vmred_data, type_data, pol, npol);
1234 cpl_array * sigma = gravi_table_create_sigma_array (oi_wave);
1235 cpl_size nrow = cpl_table_get_nrow (oi_vis) / 6;
1238 cpl_array ** visdata = cpl_table_get_data_array (oi_vis,
"VISDATA");
1239 float * wavedata = cpl_table_get_data_float (oi_wave,
"EFF_WAVE");
1240 cpl_size nwave = cpl_array_get_size (visdata[0]);
1241 cpl_size wave0 = nwave/2;
1247 cpl_msg_debug (cpl_func,
"Compute OPLs of beam");
1249 double ** opl = cpl_malloc (
sizeof(
double*) * nrow);
1250 for (cpl_size row=0 ; row<nrow ; row++) {
1251 opl[row] = cpl_malloc (
sizeof(
double) * 4);
1253 for (
int base= 1 ; base < 4 ; base++ ) {
1254 opl[row][base] = carg (cpl_array_get_complex (visdata[row * 6 + base-1], wave0, &nv));
1259 for (
int base= 1 ; base < 4 ; base++ ) {
1260 double wrap = 0.0, ref = opl[0][base];
1261 for (cpl_size row=1 ; row<nrow ; row++) {
1262 if ( (opl[row][base] - ref) < -CPL_MATH_PI ) wrap += 2.*CPL_MATH_PI;
1263 if ( (opl[row][base] - ref) > CPL_MATH_PI ) wrap -= 2.*CPL_MATH_PI;
1264 ref = opl[row][base];
1265 opl[row][base] += wrap;
1270 for (
int base= 1 ; base < 4 ; base++ ) {
1272 for (cpl_size row=0 ; row<nrow ; row++) mean += opl[row][base];
1273 for (cpl_size row=0 ; row<nrow ; row++) opl[row][base] -= mean / nrow;
1276 CPLCHECK_MSG(
"Cannot compute OPL");
1281 cpl_msg_debug (cpl_func,
"Compute coherent integration of VISDATA");
1283 for (
int base = 0 ; base < 6 ; base++ ) {
1285 visphase[base + pol*6] = cpl_array_new (nwave, CPL_TYPE_FLOAT_COMPLEX);
1286 cpl_array_fill_window_complex (visphase[base + pol*6], 0, nwave, 0.0 * I + 0.0);
1289 for (cpl_size row=0 ; row<nrow ; row++) {
1290 double x = opl[row][GRAVI_BASE_TEL[base][1]] - opl[row][GRAVI_BASE_TEL[base][0]];
1291 for (cpl_size wave=0; wave<nwave; wave++)
1292 cpl_array_set_complex (visphase[base + pol*6], wave,
1293 cpl_array_get_complex (visphase[base + pol*6], wave, &nv) +
1294 cpl_array_get_complex (visdata[row * 6 + base], wave, &nv) *
1295 cexp (-1.*I * x * wavedata[wave0] / wavedata[wave]) );
1311 cpl_array ** ref = cpl_malloc (4 *
sizeof(cpl_array*));
1312 ref[0] = cpl_array_new (nwave, CPL_TYPE_DOUBLE_COMPLEX);
1313 cpl_array_fill_window_complex (ref[0], 0, nwave, 0.0 * I + 1.0);
1315 if (full_phase == 0) {
1317 cpl_msg_info (cpl_func,
"Force phiA(lbd) to be zero for baselines (01,02,03) = keep only closures");
1319 for (
int base = 0; base<3 ; base++)
1320 ref[base+1] = cpl_array_duplicate (visphase[base + pol*6]);
1322 }
else if (full_phase == 1) {
1324 cpl_msg_info (cpl_func,
"Force phiA(lbd) to have zero mean and minimum GD for baselines (01,02,03)");
1326 for (
int base = 0; base<3 ; base++) {
1329 &gd, 1, 2e-3, CPL_FALSE);
1330 cpl_array * tmp = cpl_array_duplicate (visphase[base + pol*6]);
1332 gd += carg (cpl_array_get_mean_complex (tmp)) / CPL_MATH_2PI / cpl_array_get_mean (sigma);
1333 cpl_array_delete (tmp);
1337 }
else if (full_phase == 2) {
1339 cpl_msg_info (cpl_func,
"Force phiA(lbd) to have zero-GD for baselines (01,02,03)");
1341 for (
int base = 0; base<3 ; base++) {
1344 &gd, 1, 2e-3, CPL_FALSE);
1348 return cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
"Option for phase calibration out of range");
1353 for (
int base = 0 ; base < 6 ; base++ ) {
1354 cpl_array_multiply (visphase[base + pol*6], ref[GRAVI_BASE_TEL[base][0]]);
1355 gravi_array_multiply_conj (visphase[base + pol*6], ref[GRAVI_BASE_TEL[base][1]]);
1358 FREELOOP (cpl_array_delete, ref, 4);
1359 FREELOOP (cpl_free, opl, nrow);
1360 FREE (cpl_array_delete, sigma);
1363 CPLCHECK_MSG(
"Cannot perform coherent integration");
1368 cpl_msg_info (cpl_func,
"Apply correction to P2VM phases");
1370 cpl_table * p2vm = gravi_data_get_p2vm_data (p2vm_map, type_data);
1371 cpl_array ** phase = cpl_table_get_data_array (p2vm,
"PHASE");
1372 cpl_size nreg = cpl_table_get_nrow (p2vm);
1373 cpl_size nwave = cpl_array_get_size (visphase[0]);
1376 for (cpl_size reg=0; reg<nreg; reg++) {
1383 for (cpl_size wave=0; wave<nwave;wave++) {
1384 double phi = carg ( cexp (1.*I*cpl_array_get (phase[reg], wave + nwave * base, &nv)) *
1385 conj(cpl_array_get_complex (visphase[base + pol*6], wave, &nv) ));
1386 cpl_array_set (phase[reg], wave + nwave * base, (phi>=0.0?phi:phi+CPL_MATH_2PI));
1391 CPLCHECK_MSG(
"Cannot correct P2VM phases");
1392 FREELOOP (cpl_array_delete, visphase, 12);
1396 gravi_msg_function_exit(1);
1397 return CPL_ERROR_NONE;
1418 gravi_msg_function_start(1);
1419 cpl_ensure_code (p2vm_map, CPL_ERROR_NULL_INPUT);
1420 cpl_ensure_code (p2vmred_data, CPL_ERROR_NULL_INPUT);
1422 cpl_propertylist * p2vmred_header = gravi_data_get_header (p2vmred_data);
1425 for (
int type_data = 0; type_data < 2; type_data ++) {
1428 int npol = gravi_pfits_get_pola_num (p2vmred_header, type_data);
1429 for (
int pol = 0; pol < npol; pol++) {
1431 cpl_msg_info (cpl_func,
"Compute the internal transmission of %s (pol %i over %i)",
1432 GRAVI_TYPE(type_data), pol+1, npol);
1435 cpl_table * flux_tbl = gravi_data_get_oi_flux (p2vmred_data, type_data, pol, npol);
1436 cpl_array ** flux = cpl_table_get_data_array (flux_tbl,
"FLUX");
1437 cpl_size nwave = cpl_array_get_size (flux[0]);
1438 cpl_size nrow = cpl_table_get_nrow (flux_tbl) / 4;
1442 cpl_array * flux_mean = cpl_array_new (nwave, CPL_TYPE_DOUBLE);
1444 CPLCHECK_MSG(
"Cannot get data");
1446 for (
int tel = 0; tel < 4; tel++) {
1449 cpl_array_fill_window (flux_mean, 0, nwave, 0.0);
1450 for (cpl_size row = 0; row < nrow; row++) {
1451 cpl_array_add (flux_mean, flux[tel + row*4]);
1455 cpl_array_divide_scalar (flux_mean, cpl_array_get_mean (flux_mean));
1458 cpl_table_set_array (oi_flux,
"FLUX", tel, flux_mean);
1461 cpl_array_fill_window (flux_mean, 0, nwave, 0.0);
1462 cpl_table_set_array (oi_flux,
"FLUXERR", tel, flux_mean);
1466 FREE (cpl_array_delete, flux_mean);
1470 cpl_propertylist * plist = gravi_data_get_oi_flux_plist (p2vmred_data, type_data, pol, npol);
1471 plist = cpl_propertylist_duplicate (plist);
1474 CPLCHECK_MSG(
"Cannot set data");
1478 gravi_msg_function_exit(1);
1479 return CPL_ERROR_NONE;
gravi_data * gravi_data_new(int nb_ext)
Create an empty gravi_data.
int gravi_region_get_pol(cpl_table *imaging_detector, int region)
Return the polarisation id of a region.
int gravi_region_get_base(cpl_table *imaging_detector, int region)
Return the base of a region.
cpl_error_code gravi_data_copy_ext(gravi_data *output, gravi_data *input, const char *name)
Copy extensions from one data to another.
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.
cpl_error_code gravi_p2vm_transmission(gravi_data *p2vm_map, gravi_data *p2vmred_data)
Compute the flux normalisation in the P2VM.
cpl_array * gravi_array_cexp(double complex factor, const cpl_array *input)
Compute the complex exponention of an array: cexp (factor * input)
cpl_table ** gravi_data_get_oiwave_tables(gravi_data *data, int type_data, int npol)
Get pointer to the OI_WAVELENGTH tables of both polarisations.
cpl_error_code gravi_compute_p2vm(gravi_data *p2vm_map, gravi_data *preproc_data, int **valid_trans, int **valid_pair, enum gravi_detector_type det_type)
The given output FITS file contain a p2vm table with the values of the transmission, phase and coherence extract using the p2vm matrix.
cpl_error_code gravi_p2vm_phase_correction(gravi_data *p2vm_map, gravi_data *p2vmred_data, int full_phase)
Correct the phase of the P2VM from internal closure-phases.
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) ...
cpl_table * gravi_data_get_table(gravi_data *self, const char *extname)
Return a pointer on a table extension by its EXTNAME.
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.
cpl_vector * gravi_compute_envelope(const cpl_vector *opd, int wave, int nwave)
Compute the envelope value.
int gravi_get_region(cpl_table *img_det, int base, char phase, int pol)
Find the region matching base, phase and pol.
cpl_matrix * gravi_matrix_invertSV_create(cpl_matrix *a_in)
Invers a matrix with singular value decomposition.
cpl_table * gravi_create_oiwave_table_ft(cpl_table *wave_table, cpl_table *detector_table, int pol)
Create a new oiwave table for FT.
cpl_error_code gravi_imagelist_unwrap_images(cpl_imagelist *imglist)
Unwrap an imagelist an all its images.
double gravi_array_get_quantile(cpl_array *arr, double thr)
Compute the value of the vector corresponding to the quantile 'thr' (0 < thr < 1) ...
cpl_propertylist * gravi_data_get_plist(gravi_data *self, const char *extname)
Get the propertylist from EXTNAME.
cpl_vector * gravi_ellipse_meanopd_create(cpl_table *spectrum_table, cpl_table *detector_table, cpl_table **oiwave_tables, cpl_vector *guess_vector, int base)
Compute the OPD modulation of a baseline from spectrum.
cpl_table * gravi_create_p2vm_table(cpl_table *detector_table, int nwave)
Create a new p2vm table.
cpl_table * gravi_create_oiwave_table_sc(cpl_table *wave_table, cpl_propertylist *header, gravi_data *wave_param)
Create a new oiwave table for SC.
int gravi_wave_get_nlambda(cpl_table *wave_data, double lambda_min, double lambda_max)
Get the number of spectral element between lambdamin et lambdamax.
cpl_error_code gravi_p2vm_normalisation(gravi_data *p2vm_map, int **valid_trans, int **valid_pair)
The given output FITS file contain a p2vm table with the values of the transmission, phase and coherence extract using the p2vm matrix so this function will normalise the p2vm map.
cpl_error_code gravi_data_add_table(gravi_data *self, cpl_propertylist *plist, const char *extname, cpl_table *table)
Add a BINTABLE extension in gravi_data.
gravi_data * gravi_create_p2vm(gravi_data *wave_map, gravi_data *wave_param)
Create a new P2VM map.
cpl_table * gravi_table_oi_create(int nwave, int nrow, const char *oi_name)
Create the oi table (oi_vis, oi_vis2, oi_t3)
cpl_imagelist * gravi_imagelist_wrap_column(cpl_table *table_data, const char *data_x)
Wrap a column array of a table into an imagelist.