52#include "cpl_wlcalib.h"
53#include "irplib_wavecal.h"
78#define PLOT_WAVE_PHASE_VS_OPD 0
86 cpl_table * opdft_table,
87 cpl_table * met_table,
92 cpl_table * detector_table,
93 cpl_table * opdguess_table);
101 cpl_table * detector_table,
102 cpl_table * opd_table);
105 cpl_table * detector_table,
110 double * rms_residuals);
113 cpl_table * weight_individual_table,
114 cpl_table * wave_fitted_table,
115 cpl_table * opd_table,
116 cpl_table * spectrum_table,
117 cpl_table * detector_table,
118 double n0,
double n1,
double n2);
121 double n0,
double n1,
double n2);
124 cpl_table * wavefibre_table,
125 cpl_table * profile_table,
126 cpl_table * detector_table);
151 cpl_ensure (spectrum_table, CPL_ERROR_NULL_INPUT, NULL);
154 cpl_size nwave = cpl_table_get_column_depth (spectrum_table,
"DATA1");
158 cpl_msg_info (cpl_func,
"spectrum_table = %lld",cpl_table_get_column_depth (spectrum_table,
"DATA1"));
165 cpl_size nlines = 14;
166 double plines_str[] = {60,
182 double plines_lbd[] = {1.982291,
198 cpl_vector * lines_lbd = cpl_vector_wrap (nlines,plines_lbd);
199 cpl_vector * lines_str = cpl_vector_wrap (nlines,plines_str);
200 cpl_bivector * lines = cpl_bivector_wrap_vectors (lines_lbd, lines_str);
203 cpl_wlcalib_slitmodel * model = cpl_wlcalib_slitmodel_new ();
204 cpl_wlcalib_slitmodel_set_wslit (model, 0.1);
205 cpl_wlcalib_slitmodel_set_wfwhm (model, 1.25);
206 cpl_wlcalib_slitmodel_set_threshold (model, 5.0);
207 cpl_wlcalib_slitmodel_set_catalog (model, lines);
210 double values_hr[] = {1.97048,0.2228e-3,2.7728e-08,-4.72e-12};
211 double values_mr[] = {1.9697,0.2179e-2,2.5e-07,-5e-10};
212 double * values = nwave > 1000 ? values_hr : values_mr;
215 cpl_polynomial * dispersion0 = cpl_polynomial_new (1);
216 for (cpl_size order = 0 ; order < 4 ; order ++) {
217 cpl_polynomial_set_coeff (dispersion0, &order, values[order]);
221 double minwave = -1e10;
222 double maxwave = +1e10;
224 cpl_vector * spectrum = cpl_vector_new (nwave);
225 cpl_vector * input_spectrum = cpl_vector_new (nwave);
226 cpl_vector * model_spectrum = cpl_vector_new (nwave);
229 cpl_table * fit_table = cpl_table_new (nregion);
235 cpl_polynomial * dispersion = cpl_polynomial_duplicate (dispersion0);
238 for (cpl_size reg = 0; reg < nregion ; reg ++ ) {
239 cpl_msg_info (cpl_func,
"Fit region %lld over %lld", reg+1, nregion);
242 const cpl_array * data = cpl_table_get_array (spectrum_table,
GRAVI_DATA[reg], 0);
243 for (cpl_size wave=0; wave < nwave; wave ++) {
244 cpl_vector_set (spectrum, wave, log (CPL_MAX (cpl_array_get (data, wave, NULL), 1.0)));
245 cpl_vector_set (input_spectrum, wave, cpl_array_get (data, wave, NULL));
253 int maxdeg = 3, nmaxima = 0, linelim = 99;
254 int maxite = 100 * maxdeg, maxfail = 10, maxcont = 10;
255 int hsize = (reg == 0 ? 40 : 5);
256 double pixtol = 1e-6, pixstep = 0.5, pxc = 0.0;
260 irplib_polynomial_find_1d_from_correlation_all (dispersion, maxdeg, spectrum,
262 (irplib_base_spectrum_model*)model,
263 &irplib_vector_fill_logline_spectrum,
265 hsize, maxite, maxfail, maxcont,
270 irplib_vector_fill_line_spectrum (model_spectrum, dispersion, (
void *)model);
271 cpl_polynomial_dump (dispersion, stdout);
274 cpl_array *
wave_data = cpl_array_new (nwave, CPL_TYPE_DOUBLE);
275 for (cpl_size pix = 0; pix < nwave ; pix++)
276 cpl_array_set (
wave_data, pix, cpl_polynomial_eval_1d (dispersion, (
double)pix, NULL) * 1e-6);
279 minwave = CPL_MAX (cpl_array_get_min (
wave_data), minwave);
280 maxwave = CPL_MIN (cpl_array_get_max (
wave_data), maxwave);
288 cpl_array * tmp_array;
289 tmp_array = cpl_array_wrap_double (cpl_vector_get_data (input_spectrum), nwave);
290 cpl_table_set_array (fit_table,
"DATA", reg, tmp_array);
291 cpl_array_unwrap (tmp_array);
292 tmp_array = cpl_array_wrap_double (cpl_vector_get_data (model_spectrum), nwave);
293 cpl_table_set_array (fit_table,
"DATA_MODEL", reg, tmp_array);
294 cpl_array_unwrap (tmp_array);
295 tmp_array = cpl_array_new (nwave, CPL_TYPE_DOUBLE);
296 for (cpl_size wave = 0; wave < nwave; wave ++)
297 cpl_array_set (tmp_array, wave, cpl_polynomial_eval_1d (dispersion, (
double)wave, NULL) * 1e-6);
298 cpl_table_set_array (fit_table,
"DATA_WAVE", reg, tmp_array);
299 cpl_array_delete (tmp_array);
305 FREE (cpl_table_delete, fit_table);
308 FREE (cpl_vector_delete, spectrum);
309 FREE (cpl_vector_delete, input_spectrum);
310 FREE (cpl_vector_delete, model_spectrum);
311 FREE (cpl_polynomial_delete, dispersion0);
312 FREE (cpl_polynomial_delete, dispersion);
357 cpl_ensure_code (phase_table, CPL_ERROR_NULL_INPUT);
358 cpl_ensure_code (name, CPL_ERROR_NULL_INPUT);
361 cpl_size nrow = cpl_table_get_nrow (phase_table) /
GRAVI_NBASE;
364 double * phase = cpl_table_get_data_double (phase_table, name);
369 cpl_matrix * rhs_matrix = cpl_matrix_new (nrow * nclo, 1);
370 cpl_matrix * model_matrix = cpl_matrix_new (nrow * nclo,
GRAVI_NBASE-1 + nclo);
372 for (cpl_size row = 0; row < nrow; row++) {
373 for (
int clo = 0; clo < nclo; clo++) {
382 cpl_matrix_set (rhs_matrix, row*nclo+clo, 0, closure);
386 cpl_matrix_set (model_matrix, row*nclo+clo, clo, 1.0);
390 if (b0 <
GRAVI_NBASE-1) cpl_matrix_set (model_matrix, row*nclo+clo, nclo+b0,
392 if (b1 <
GRAVI_NBASE-1) cpl_matrix_set (model_matrix, row*nclo+clo, nclo+b1,
394 if (b2 <
GRAVI_NBASE-1) cpl_matrix_set (model_matrix, row*nclo+clo, nclo+b2,
401 cpl_matrix * res_matrix = cpl_matrix_solve_normal (model_matrix, rhs_matrix);
405 cpl_matrix * residual_matrix = cpl_matrix_product_create (model_matrix, res_matrix);
406 cpl_matrix_subtract (residual_matrix, rhs_matrix);
407 double rms_fit = cpl_matrix_get_stdev (residual_matrix);
410 for (
int base = 0; base <
GRAVI_NBASE - 1; base ++) {
411 double f = cpl_matrix_get (res_matrix, nclo + base, 0);
412 cpl_msg_info (cpl_func,
"correction factor f = 1 %+.20f", -1*f);
413 for (cpl_size row = 0; row < nrow; row++) phase[row*
GRAVI_NBASE+base] *= 1 - f;
417 const char * unit = cpl_table_get_column_unit (phase_table, name);
418 cpl_msg_info (cpl_func,
"residual stdev = %.20g [%s]", rms_fit, unit);
421 FREE (cpl_matrix_delete, residual_matrix);
422 FREE (cpl_matrix_delete, res_matrix);
423 FREE (cpl_matrix_delete, model_matrix);
424 FREE (cpl_matrix_delete, rhs_matrix);
427 return CPL_ERROR_NONE;
461 cpl_ensure (ft_table, CPL_ERROR_NULL_INPUT, NULL);
465 cpl_size nrow = cpl_table_get_nrow (ft_table) /
GRAVI_NBASE;
468 double * opd_sc = cpl_table_get_data_double (ft_table,
"OPD_SC");
469 double * opd_ft = cpl_table_get_data_double (ft_table,
"OPD");
470 double * phase_met = cpl_table_get_data_double (ft_table,
"PHASE_MET_FC");
474 cpl_size nrow_valid = 0;
475 for (cpl_size row = 0; row < nrow; row++)
if (opd_sc[row*
GRAVI_NBASE] != 0) nrow_valid++;
476 cpl_msg_info (cpl_func,
"nrow_valid = %lld", nrow_valid);
478 cpl_ensure (nrow_valid > 100, CPL_ERROR_ILLEGAL_INPUT, NULL);
482 cpl_matrix * rhs_matrix = cpl_matrix_new (nrow_valid*
GRAVI_NBASE, 1);
486 cpl_size row_valid = 0;
488 for (cpl_size row=0; row<nrow; row++) {
495 cpl_matrix_set (rhs_matrix, idv, 0, phase_met[
id] * lbd_met / CPL_MATH_2PI);
499 cpl_matrix_set (model_matrix, idv, 0, 1*opd_sc[
id]);
500 cpl_matrix_set (model_matrix, idv, 1, -1*opd_ft[
id]);
504 cpl_matrix_set (model_matrix, idv, 2 + base, 1.0);
512 cpl_matrix * res_matrix = cpl_matrix_solve_normal (model_matrix, rhs_matrix);
515 cpl_matrix * residual_matrix = cpl_matrix_product_create (model_matrix, res_matrix);
516 cpl_matrix_subtract (residual_matrix, rhs_matrix);
517 double rms_fit = cpl_matrix_get_stdev (residual_matrix);
521 cpl_msg_info (cpl_func,
"coeff SC = %.20g ", cpl_matrix_get (res_matrix, 0, 0));
522 cpl_msg_info (cpl_func,
"coeff FT = %.20g ", cpl_matrix_get (res_matrix, 1, 0));
523 cpl_msg_info (cpl_func,
"residual stdev = %.20g [m]", rms_fit);
526 cpl_vector * opd_coeff = cpl_vector_new(3);
527 cpl_vector_set (opd_coeff,
GRAVI_SC, cpl_matrix_get (res_matrix, 0, 0));
528 cpl_vector_set (opd_coeff,
GRAVI_FT, cpl_matrix_get (res_matrix, 1, 0));
529 cpl_vector_set (opd_coeff, 2, rms_fit);
532 FREE (cpl_matrix_delete, residual_matrix);
533 FREE (cpl_matrix_delete, res_matrix);
534 FREE (cpl_matrix_delete, model_matrix);
535 FREE (cpl_matrix_delete, rhs_matrix);
566 cpl_table * ft_table,
567 cpl_table * vismet_table,
572 cpl_ensure (spectrumsc_table, CPL_ERROR_NULL_INPUT, NULL);
573 cpl_ensure (ft_table, CPL_ERROR_NULL_INPUT, NULL);
574 cpl_ensure (vismet_table, CPL_ERROR_NULL_INPUT, NULL);
575 cpl_ensure (dit_sc>0, CPL_ERROR_ILLEGAL_INPUT, NULL);
579 cpl_size nrow = cpl_table_get_nrow (spectrumsc_table);
580 cpl_size nrow_met = cpl_table_get_nrow (vismet_table) /
ntel;
581 cpl_size nrow_ft = cpl_table_get_nrow (ft_table) /
GRAVI_NBASE;
582 int * time_SC = cpl_table_get_data_int (spectrumsc_table,
"TIME");
586 int * time_MET = cpl_table_get_data_int (vismet_table,
"TIME");
587 double * phase_MET = cpl_table_get_data_double (vismet_table,
"PHASE_FC_DRS");
591 int * time_FT = cpl_table_get_data_int (ft_table,
"TIME");
592 double * opd_FT = cpl_table_get_data_double (ft_table,
"OPD");
596 cpl_table * guess_table = cpl_table_new (nrow *
GRAVI_NBASE);
605 cpl_size row_met = 0, row_ft = 0;
606 for (cpl_size row = 0 ; row < nrow ; row++) {
612 double opd_met = 0.0;
613 while (time_MET[row_met*
ntel] < (time_SC[row] + dit_sc/2.)) {
614 if ((time_MET[row_met*
ntel] > (time_SC[row] - dit_sc/2.)) && (row_met < nrow_met)) {
615 opd_met += phase_MET[row_met*
ntel+tel1] - phase_MET[row_met*
ntel+tel0];
620 if (row_met > nrow_met - 2) {
621 cpl_msg_warning (cpl_func,
"Not enough data to synchronise the MET with SC");
628 opd_met = opd_met * lbd_met / CPL_MATH_2PI / counter_met;
635 while (time_FT[row_ft*
GRAVI_NBASE+base] < (time_SC[row] + dit_sc/2.)) {
636 if ((time_FT[row_ft*
GRAVI_NBASE+base] > (time_SC[row] - dit_sc/2.)) && (row_ft < nrow_ft)) {
642 if (row_ft > nrow_ft - 2) {
643 cpl_msg_warning (cpl_func,
"Not enough data to synchronise the FT with SC");
650 opd_ft = opd_ft / counter_ft;
653 cpl_table_set (guess_table,
"OPD", row*
GRAVI_NBASE+base, opd_ft - opd_met);
661 cpl_msg_info (cpl_func,
"Remove the mean from opdguess table");
698 cpl_table * detector_table,
699 cpl_table * guess_table)
703 cpl_ensure (spectrum_table, CPL_ERROR_NULL_INPUT, NULL);
704 cpl_ensure (detector_table, CPL_ERROR_NULL_INPUT, NULL);
708 cpl_msg_info (cpl_func,
"Solve linearly the ellipse X,Y");
711 cpl_msg_info (cpl_func,
"Solve non-linearly the ellipse X,Y");
715 cpl_size nrow = cpl_table_get_nrow (spectrum_table);
723 cpl_table ** oiwave_tables = cpl_calloc (npol,
sizeof (cpl_table *));
724 for (
int pol = 0; pol < npol; pol++) {
725 oiwave_tables[pol] = cpl_table_new (nwave);
726 cpl_table_new_column (oiwave_tables[pol],
"EFF_WAVE", CPL_TYPE_DOUBLE);
727 for (cpl_size wave = 0; wave < nwave; wave++) {
728 double value = 1.97e-6 + (2.48e-6 - 1.97e-6) / nwave * wave;
729 cpl_table_set (oiwave_tables[pol],
"EFF_WAVE", wave, value);
734 cpl_table * output_table = cpl_table_new (
GRAVI_NBASE * nrow);
739 for (cpl_size row = 0; row < nrow; row++) {
740 double value = cpl_table_get (spectrum_table,
"TIME", row, NULL);
742 cpl_table_set (output_table,
"TIME", row*
GRAVI_NBASE+base, value);
749 cpl_vector * opd_guess = NULL;
751 opd_guess = cpl_vector_new (nrow);
752 for (cpl_size row = 0; row < nrow; row++) {
753 double value = cpl_table_get (guess_table,
"OPD", row*
GRAVI_NBASE+base, NULL);
754 cpl_vector_set (opd_guess, row, value);
761 cpl_vector * mean_opd;
763 oiwave_tables, opd_guess, base);
767 for (cpl_size row = 0; row < nrow; row++) {
768 double value = cpl_vector_get (mean_opd, row);
769 cpl_table_set (output_table,
"OPD", row*
GRAVI_NBASE+base, value);
773 FREE (cpl_vector_delete, mean_opd);
774 FREE (cpl_vector_delete, opd_guess);
778 FREELOOP (cpl_table_delete, oiwave_tables, npol);
820 cpl_table * met_table,
821 const cpl_parameterlist * parlist)
824 cpl_ensure_code (spectrum_data, CPL_ERROR_NULL_INPUT);
825 cpl_ensure_code (met_table, CPL_ERROR_NULL_INPUT);
857 cpl_msg_info (cpl_func,
"Compute OPD of FT from ellipse");
859 cpl_table * ft_table;
863 cpl_msg_info (cpl_func,
"Compute OPD of SC from ellipse");
865 cpl_table * guess_table;
868 cpl_table * sc_table;
871 FREE (cpl_table_delete, guess_table);
879 cpl_msg_info (cpl_func,
"Fit MET = a.SC - b.FT + c to get absolute modulation");
884 CPLCHECK_MSG (
"Cannot resample SC or MET at the FT frequency");
896 cpl_vector_get (coeff_vector, 2));
897 cpl_propertylist_set_comment (spectrum_header,
QC_PHASECHI2,
898 "chi2 of a.SC-b.FT+c=MET");
901 for (
int type_data = 0; type_data < 2; type_data++) {
902 double tmp = cpl_vector_get (coeff_vector, type_data);
903 cpl_propertylist_update_float (spectrum_header,
OPD_COEFF_SIGN(type_data), tmp);
904 cpl_propertylist_set_comment (spectrum_header,
OPD_COEFF_SIGN(type_data),
"wavelength correction");
908 if (cpl_vector_get (coeff_vector, 2) > 1e-7) {
912 if (cpl_vector_get (coeff_vector, 2) > 1.2e-7) {
913 cpl_msg_warning (cpl_func,
"*************************************************");
914 cpl_msg_warning (cpl_func,
"**** !!! residuals of the fit too high !!! ****");
915 cpl_msg_warning (cpl_func,
"**** Residuals are:%7.0f nm ****",cpl_vector_get (coeff_vector, 2)*1e9);
916 cpl_msg_warning (cpl_func,
"**** SC and RMN may be desynchronized ****");
917 cpl_msg_warning (cpl_func,
"**** (or out of the envelope in LOW) ****");
918 cpl_msg_warning (cpl_func,
"*************************************************");
926 double coeff_sc = cpl_vector_get (coeff_vector,
GRAVI_SC);
927 cpl_table_multiply_scalar (sc_table,
"OPD", coeff_sc);
929 double coeff_ft = cpl_vector_get (coeff_vector,
GRAVI_FT);
930 cpl_table_multiply_scalar (ft_table,
"OPD", coeff_ft);
932 FREE (cpl_vector_delete, coeff_vector);
933 CPLCHECK_MSG (
"Cannot correct OPDs from scaling coefficients");
959 return CPL_ERROR_NONE;
989 cpl_table * detector_table,
990 cpl_table * opd_table)
993 cpl_ensure (spectrum_table, CPL_ERROR_NULL_INPUT, NULL);
994 cpl_ensure (detector_table, CPL_ERROR_NULL_INPUT, NULL);
995 cpl_ensure (opd_table, CPL_ERROR_NULL_INPUT, NULL);
1000 cpl_table * wave_fibre = cpl_table_new (1);
1003 cpl_size nwave = cpl_table_get_column_depth (spectrum_table,
"DATA1");
1004 cpl_size n_region = cpl_table_get_nrow (detector_table);
1005 cpl_size nrow = cpl_table_get_nrow (spectrum_table);
1007 int npol = (n_region > 24 ? 2 : 1);
1013 for (
int pol = 0; pol < npol; pol++) {
1015 cpl_msg_info (cpl_func,
"Compute wave fibre for pol %i over %i, base %i over %i",
1023 if (iA<0 || iB<0 || iC<0 || iD<0){
1024 cpl_msg_warning (cpl_func,
"Don't found the A, B, C or D !!!");
1031 cpl_matrix * opd_matrix = cpl_matrix_new (1, nrow);
1032 cpl_vector * opd_vector = cpl_vector_new (nrow);
1033 for (cpl_size row = 0; row < nrow; row ++ ) {
1034 double value = cpl_table_get (opd_table,
"OPD", row*
GRAVI_NBASE+base, NULL);
1035 cpl_matrix_set (opd_matrix, 0, row, value);
1036 cpl_vector_set (opd_vector, row, value);
1041 cpl_array * wavelength = cpl_array_new (nwave, CPL_TYPE_DOUBLE);
1042 cpl_array * wavechi2 = cpl_array_new (nwave, CPL_TYPE_DOUBLE);
1043 cpl_array_fill_window (wavelength, 0, nwave, 0.0);
1044 cpl_array_fill_window (wavechi2, 0, nwave, 1e10);
1049 for (cpl_size wave = 0; wave < nwave; wave++) {
1051 cpl_vector * vector_T = NULL, * vector_X, * vector_Y;
1056 cpl_vector_subtract (vector_X, vector_T);
1057 FREE (cpl_vector_delete, vector_T);
1062 cpl_vector_subtract (vector_Y, vector_T);
1063 FREE (cpl_vector_delete, vector_T);
1074 FREE (cpl_vector_delete, vector_X);
1075 FREE (cpl_vector_delete, vector_Y);
1076 FREE (cpl_vector_delete, envelope_vector);
1079 if (phase == NULL) {
1080 cpl_msg_warning (cpl_func,
"Cannot compute wave for %lld and base %d", wave, base);
1085 cpl_vector_multiply_scalar (phase, phi_sign);
1088 double lbd_channel = 1.95e-6 + (2.46e-6 - 1.95e-6) / nwave * wave;
1093 const cpl_size mindeg = 0, maxdeg = 1;
1094 cpl_polynomial * fit_slope = cpl_polynomial_new (1);
1095 cpl_polynomial_fit (fit_slope, opd_matrix, NULL, phase, NULL, CPL_FALSE, &mindeg, &maxdeg);
1098 cpl_vector * residuals = cpl_vector_new (nwave);
1100 cpl_vector_fill_polynomial_fit_residual (residuals, phase, NULL, fit_slope, opd_matrix, &rechisq);
1104 char gnuplot_str[200];
1105 sprintf (gnuplot_str,
"set title 'Wavelength (base %d)'; set xlabel 'Phase [rad]'; set ylabel 'OPD (m)';", base);
1106 cpl_plot_vector (gnuplot_str, NULL, NULL, opd_vector);
1107 sprintf (gnuplot_str,
"set title 'Wavelength residuals (base %d)'; set xlabel 'Phase [rad]'; set ylabel 'OPD (m)';", base);
1108 cpl_plot_vector (gnuplot_str, NULL, NULL, residuals);
1115 const cpl_size pow_slope = 1;
1116 double slope = cpl_polynomial_get_coeff (fit_slope, &pow_slope);
1119 if (slope < 0.0 && wave == 0) {
1120 cpl_msg_warning (cpl_func,
"Negative wavelength!! "
1121 "Report to DRS team");
1125 cpl_array_set (wavechi2, wave, sqrt(rechisq));
1126 cpl_array_set (wavelength, wave, CPL_MATH_2PI / fabs(slope));
1129 cpl_vector_delete (phase);
1130 cpl_vector_delete (residuals);
1131 cpl_polynomial_delete (fit_slope);
1135 cpl_matrix_delete (opd_matrix);
1136 cpl_vector_delete (opd_vector);
1140 cpl_table_new_column_array (wave_fibre, name, CPL_TYPE_DOUBLE, nwave);
1141 cpl_table_set_column_unit (wave_fibre, name,
"m");
1142 cpl_table_set_array (wave_fibre, name, 0, wavelength);
1143 cpl_array_delete (wavelength);
1147 cpl_table_new_column_array (wave_fibre, name, CPL_TYPE_DOUBLE, nwave);
1148 cpl_table_set_array (wave_fibre, name, 0, wavechi2);
1149 cpl_array_delete (wavechi2);
1179 cpl_table * detector_table,
1181 cpl_size fullstartx,
1184 double * rms_residuals)
1187 cpl_ensure (wavefibre_table, CPL_ERROR_NULL_INPUT, NULL);
1188 cpl_ensure (detector_table, CPL_ERROR_NULL_INPUT, NULL);
1194 cpl_size n_region = cpl_table_get_nrow (detector_table);
1195 int npol = n_region > 24 ? 2 : 1;
1196 cpl_size nwave = cpl_table_get_column_depth (wavefibre_table, npol > 1 ?
"BASE_12_S" :
"BASE_12_C");
1203 cpl_vector * odd_index = cpl_vector_new (nwave);
1204 for (
int i = fullstartx; i < fullstartx + nwave; i++) {
1205 if (nwave >
GRAVI_LBD_FTSC) cpl_vector_set (odd_index, i - fullstartx, ((i/64)%2 == 0) ? 0 : 1);
1206 else cpl_vector_set (odd_index, i - fullstartx, 0);
1212 cpl_polynomial ** coef_poly = cpl_calloc (npol,
sizeof (cpl_polynomial*));
1215 for (
int pol = 0; pol < npol; pol++) {
1219 cpl_vector * coord_X = cpl_vector_new (
GRAVI_NBASE * nwave);
1220 cpl_vector * coord_Y = cpl_vector_new (
GRAVI_NBASE * nwave);
1222 cpl_vector * all_wavelength = cpl_vector_new (
GRAVI_NBASE * nwave);
1223 cpl_vector * all_wavechi2 = cpl_vector_new (
GRAVI_NBASE * nwave);
1224 cpl_vector * all_valid = cpl_vector_new (
GRAVI_NBASE * nwave);
1240 cpl_array * wavelength = cpl_table_get_data_array (wavefibre_table, name)[0];
1243 cpl_array * wavechi2 = cpl_table_get_data_array (wavefibre_table, name)[0];
1246 for (cpl_size wave = 0; wave < nwave; wave++) {
1247 cpl_size pos = base * nwave + wave;
1251 double wave_value = cpl_array_get (wavelength, wave, &nv);
1252 double chi2_value = cpl_array_get (wavechi2, wave, &nv);
1255 cpl_vector_set (all_valid, pos, 1);
1259 if ((chi2_value > M_PI_4 ||
1262 cpl_vector_set (all_valid, pos, 0);
1264 else if (nwave > 100) {
1266 if ((chi2_value > M_PI_4 ||
1269 cpl_vector_set (all_valid, pos, 0);
1273 if ((chi2_value > M_PI_4 ||
1277 wave == 0 || wave == nwave-1))
1278 cpl_vector_set (all_valid, pos, 0);
1282 if ((chi2_value > M_PI_4 ||
1284 wave_value < 1.99e-6 ||
1285 wave_value > 2.5e-6))
1286 cpl_vector_set (all_valid, pos, 0);
1290 cpl_vector_set (all_wavelength, pos, wave_value);
1291 cpl_vector_set (all_wavechi2, pos, chi2_value);
1294 cpl_vector_set (coord_X, pos, (
double)(iA + iB + iC + iD) / 4.);
1298 cpl_vector_set (coord_Y, pos, wave + cpl_vector_get (odd_index, wave)*0.15);
1308 cpl_size nvalid = cpl_vector_get_sum (all_valid);
1313 cpl_vector * vector = cpl_vector_new (nvalid);
1314 cpl_matrix * matrix = cpl_matrix_new (2, nvalid);
1316 for (cpl_size c = 0, i = 0 ; i < nwave *
GRAVI_NBASE; i ++) {
1317 if (!cpl_vector_get (all_valid, i))
continue;
1318 cpl_vector_set (vector, c, cpl_vector_get (all_wavelength, i));
1319 cpl_matrix_set (matrix, 0, c, cpl_vector_get (coord_X, i));
1320 cpl_matrix_set (matrix, 1, c, cpl_vector_get (coord_Y, i));
1330 cpl_size deg2d[2] = {2, 3};
1331 if ( (nwave < 20) && (nwave > 8) ) {deg2d[0] = 2; deg2d[1] = 7;}
1332 deg2d[0] = spatial_order;
1333 deg2d[1] = spectral_order;
1335 cpl_msg_info (cpl_func,
"Fit a 2d polynomial {%lli..%lli} to the wavelengths map", deg2d[0], deg2d[1]);
1337 cpl_polynomial * fit2d = cpl_polynomial_new (2);
1338 cpl_polynomial_fit (fit2d, matrix, NULL, vector, NULL, CPL_TRUE, NULL, deg2d);
1339 coef_poly[pol] = fit2d;
1346 double rechisq = 0.0;
1347 cpl_vector * residuals = cpl_vector_new (nvalid);
1348 cpl_vector_fill_polynomial_fit_residual (residuals, vector, NULL, fit2d, matrix, &rechisq);
1349 *rms_residuals += cpl_vector_get_stdev(residuals)/npol;
1350 FREE (cpl_vector_delete, residuals);
1354 FREE (cpl_matrix_delete, matrix);
1355 FREE (cpl_vector_delete, vector);
1356 FREE (cpl_vector_delete, all_wavelength);
1357 FREE (cpl_vector_delete, all_wavechi2);
1358 FREE (cpl_vector_delete, all_valid);
1359 FREE (cpl_vector_delete, coord_X);
1360 FREE (cpl_vector_delete, coord_Y);
1369 cpl_table * wavedata_table = cpl_table_new (1);
1370 cpl_vector * pos = cpl_vector_new (2);
1371 cpl_array * value = cpl_array_new (nwave, CPL_TYPE_DOUBLE);
1373 for (cpl_size region = 0 ; region < n_region; region ++) {
1377 for (cpl_size wave = 0; wave < nwave; wave ++) {
1380 cpl_vector_set (pos, 0, region);
1381 cpl_vector_set (pos, 1, wave + cpl_vector_get (odd_index, wave)*0.15);
1383 double result = cpl_polynomial_eval (coef_poly[pol], pos);
1384 cpl_array_set (value, wave, result);
1388 double previous_wave = cpl_array_get(value, nwave/2, NULL);
1389 for (cpl_size wave_loop = nwave/2 ; wave_loop >= 0 ; wave_loop --){
1390 if (previous_wave < cpl_array_get(value, wave_loop, NULL))
1391 cpl_array_set(value, wave_loop, previous_wave);
1392 else previous_wave = cpl_array_get(value, wave_loop, NULL);
1395 previous_wave = cpl_array_get(value, nwave/2, NULL);
1396 for (cpl_size wave_loop = nwave/2 ; wave_loop < nwave ; wave_loop ++){
1397 if (previous_wave > cpl_array_get(value, wave_loop, NULL))
1398 cpl_array_set(value, wave_loop, previous_wave);
1399 else previous_wave = cpl_array_get(value, wave_loop, NULL);
1404 cpl_table_new_column_array (wavedata_table, data_x, CPL_TYPE_DOUBLE, nwave);
1405 cpl_table_set_array (wavedata_table, data_x, 0, value);
1410 FREE (cpl_vector_delete, pos);
1411 FREE (cpl_array_delete, value);
1412 FREELOOP (cpl_polynomial_delete, coef_poly, npol);
1413 FREE (cpl_vector_delete, odd_index);
1416 return wavedata_table;
1428 cpl_table * weight_individual_table,
1429 cpl_table * wave_fitted_table,
1430 cpl_table * opd_table,
1431 cpl_table * spectrum_table,
1432 cpl_table * detector_table,
1433 double n0,
double n1,
double n2)
1438 cpl_ensure (wave_individual_table, CPL_ERROR_NULL_INPUT, NULL);
1439 cpl_ensure (weight_individual_table, CPL_ERROR_NULL_INPUT, NULL);
1440 cpl_ensure (wave_fitted_table, CPL_ERROR_NULL_INPUT, NULL);
1441 cpl_ensure (opd_table, CPL_ERROR_NULL_INPUT, NULL);
1442 cpl_ensure (spectrum_table, CPL_ERROR_NULL_INPUT, NULL);
1443 cpl_ensure (detector_table, CPL_ERROR_NULL_INPUT, NULL);
1446 cpl_size nwave = cpl_table_get_column_depth (spectrum_table,
"DATA1");
1447 cpl_size n_region = cpl_table_get_nrow (detector_table);
1448 cpl_size nrow = cpl_table_get_nrow (spectrum_table);
1449 int npol = (n_region > 24 ? 2 : 1);
1450 cpl_size nwave_ref=3000;
1451 if (nwave<10) nwave_ref=600;
1461 cpl_array * wave_individual_array = cpl_array_new (nwave, CPL_TYPE_DOUBLE);
1462 cpl_array * weight_individual_array = cpl_array_new (nwave, CPL_TYPE_DOUBLE);
1463 cpl_matrix * data_flux_matrix = cpl_matrix_new (nrow, nwave);
1464 cpl_matrix * vis_to_flux_matrix = cpl_matrix_new (nrow, 3);
1465 cpl_matrix * signal_matrix = cpl_matrix_new (nwave, nwave_ref);
1466 cpl_matrix * residual_matrix = cpl_matrix_new (nwave, nwave_ref);
1467 cpl_array * wave_reference_array = cpl_array_new (nwave_ref, CPL_TYPE_DOUBLE);
1471 cpl_matrix_fill_column(vis_to_flux_matrix,1,2);
1472 for (cpl_size wave_ref = 0; wave_ref < nwave_ref; wave_ref+=1)
1475 double wave_value=1.95e-6+wave_ref*0.6e-6/((double) nwave_ref);
1476 cpl_array_set_double(wave_reference_array,wave_ref,wave_value);
1479 CPLCHECK_NUL (
"Cannot initialize arrays for wavelength fit");
1482 for (cpl_size region = 0 ; region < n_region; region ++) {
1487 cpl_msg_info_overwritable (cpl_func,
"Least square fitting of wavelength for region %s", data_x);
1490 for (cpl_size row = 0; row < nrow; row ++ ) {
1491 cpl_array * flux_array= cpl_table_get_data_array(spectrum_table,data_x)[row];
1492 for (cpl_size wave = 0; wave < nwave; wave ++) {
1493 cpl_matrix_set (data_flux_matrix, row, wave, cpl_array_get(flux_array,wave, NULL));
1498 for (cpl_size wave_ref = 0; wave_ref < nwave_ref; wave_ref+=1)
1501 double wave_value=cpl_array_get(wave_reference_array,wave_ref,NULL);
1503 for (cpl_size row = 0; row < nrow; row ++ ) {
1504 double opd = cpl_table_get (opd_table,
"OPD", row*
GRAVI_NBASE+base, NULL);
1505 double coherence_loss=1;
1506 if (fabs(opd) > 1e-9)
1510 coherence_loss=sin(opd*19500)/(opd*19500);
1513 cpl_matrix_set(vis_to_flux_matrix,row,0,cos(opd*6.28318530718/wave_value)*coherence_loss);
1514 cpl_matrix_set(vis_to_flux_matrix,row,1,sin(opd*6.28318530718/wave_value)*coherence_loss);
1517 cpl_matrix * coef_vis = cpl_matrix_solve_normal(vis_to_flux_matrix,data_flux_matrix);
1518 cpl_matrix * data_flux_fit = cpl_matrix_product_create(vis_to_flux_matrix,coef_vis);
1519 cpl_matrix * residuals_fit = cpl_matrix_duplicate(data_flux_fit);
1520 cpl_matrix_subtract (residuals_fit,data_flux_matrix);
1522 for (cpl_size wave = 0; wave < nwave; wave ++ ) {
1523 cpl_matrix * temp_matrix = cpl_matrix_extract_column (data_flux_fit, wave);
1524 cpl_matrix_set(signal_matrix,wave,wave_ref,cpl_matrix_get_stdev(temp_matrix));
1525 FREE (cpl_matrix_delete, temp_matrix);
1526 cpl_matrix * temp_matrix2 = cpl_matrix_extract_column (residuals_fit, wave);
1527 cpl_matrix_set(residual_matrix,wave,wave_ref,cpl_matrix_get_stdev(temp_matrix2));
1528 FREE (cpl_matrix_delete, temp_matrix2);
1531 FREE (cpl_matrix_delete, coef_vis);
1532 FREE (cpl_matrix_delete, data_flux_fit);
1533 FREE (cpl_matrix_delete, residuals_fit);
1535 CPLCHECK_NUL (
"Cannot do Matrix inversion to calculate optimum wavelength");
1540 cpl_size wave_ref=1;
1541 cpl_size discarded=1;
1542 for (cpl_size wave = 0; wave < nwave; wave ++ ) {
1544 cpl_matrix * chi2_extract=cpl_matrix_extract_row(residual_matrix,wave);
1546 cpl_matrix_get_minpos(chi2_extract,&discarded, &wave_ref );
1548 double wave_value = cpl_array_get(wave_reference_array, wave_ref, NULL );
1549 double weight_value = cpl_matrix_get(signal_matrix, wave , wave_ref )/(0.1+cpl_matrix_get(residual_matrix, wave, wave_ref ));
1551 cpl_array_set_double (wave_individual_array, wave, wave_value);
1552 cpl_array_set_double (weight_individual_array, wave, weight_value);
1554 FREE (cpl_matrix_delete, chi2_extract);
1559 cpl_table_new_column_array (wave_individual_table, data_x, CPL_TYPE_DOUBLE, nwave);
1560 cpl_table_set_array (wave_individual_table, data_x, 0, wave_individual_array);
1561 cpl_table_new_column_array (weight_individual_table, data_x, CPL_TYPE_DOUBLE, nwave);
1562 cpl_table_set_array (weight_individual_table, data_x, 0, weight_individual_array);
1563 cpl_table_new_column_array (wave_fitted_table, data_x, CPL_TYPE_DOUBLE, nwave);
1564 cpl_table_set_array (wave_fitted_table, data_x, 0, wave_individual_array);
1567 CPLCHECK_NUL (
"Cannot get individual wavelength for each pixel");
1569 FREE (cpl_array_delete ,wave_individual_array);
1570 FREE (cpl_array_delete ,weight_individual_array);
1571 FREE (cpl_array_delete ,wave_reference_array);
1572 FREE (cpl_matrix_delete ,data_flux_matrix);
1573 FREE (cpl_matrix_delete ,vis_to_flux_matrix);
1574 FREE (cpl_matrix_delete ,signal_matrix);
1575 FREE (cpl_matrix_delete ,residual_matrix);
1577 cpl_msg_info (cpl_func,
"Now fitting polynomials on wavelength channels");
1579 cpl_matrix * coef_to_wave = cpl_matrix_new (n_region / npol,5);
1580 cpl_matrix * coef_to_wave_weight = cpl_matrix_new (n_region / npol,n_region / npol);
1581 cpl_matrix * wavelength = cpl_matrix_new(n_region / npol,1);
1584 for (cpl_size region = 0 ; region < n_region/ npol; region ++)
1586 double mean_region = region - (n_region/npol-1)*0.5;
1587 cpl_matrix_set (coef_to_wave, region, 0, 1);
1588 cpl_matrix_set (coef_to_wave, region, 1, mean_region);
1589 cpl_matrix_set (coef_to_wave, region, 2, mean_region*mean_region);
1590 cpl_matrix_set (coef_to_wave, region, 3, mean_region*mean_region*mean_region);
1591 cpl_matrix_set (coef_to_wave, region, 4, mean_region*mean_region*mean_region*mean_region);
1594 for (
int pol = 0; pol < npol; pol++) {
1596 cpl_msg_info (cpl_func,
"Looping for polyfit now, with pol: %i",(
int) pol);
1598 for (cpl_size wave = 0; wave < nwave; wave ++) {
1601 for (cpl_size region = 0 ; region < n_region/ npol; region ++) {
1607 const cpl_array * wave_array = cpl_table_get_array (wave_individual_table, data_x, 0);
1608 const cpl_array * weight_array = cpl_table_get_array (weight_individual_table, data_x, 0);
1611 cpl_matrix_set (wavelength, region, 0, cpl_array_get(wave_array,wave,NULL));
1612 double weight_value=cpl_array_get(weight_array,wave,NULL);
1613 cpl_matrix_set (coef_to_wave_weight, region, region, weight_value*weight_value);
1618 cpl_matrix * coef_to_wave2 = cpl_matrix_product_create(coef_to_wave_weight,coef_to_wave);
1619 cpl_matrix * wavelength2 = cpl_matrix_product_create(coef_to_wave_weight,wavelength);
1622 cpl_matrix * coeff = cpl_matrix_solve_normal(coef_to_wave2, wavelength2);
1623 cpl_matrix * wavelength_fitted = cpl_matrix_product_create(coef_to_wave, coeff);
1625 CPLCHECK_NUL (
"Cannot do Matrix inversion to calculate optimum polynomial for wavelength");
1628 for (cpl_size region = 0 ; region < n_region/ npol; region ++) {
1632 cpl_array * wave_array = cpl_table_get_data_array (wave_fitted_table, data_x)[0];
1634 cpl_array_set_double(wave_array,wave,cpl_matrix_get(wavelength_fitted,region,0));
1638 FREE (cpl_matrix_delete ,coef_to_wave2);
1639 FREE (cpl_matrix_delete ,wavelength2);
1640 FREE (cpl_matrix_delete ,coeff);
1641 FREE (cpl_matrix_delete ,wavelength_fitted);
1645 FREE (cpl_matrix_delete ,coef_to_wave);
1646 FREE (cpl_matrix_delete ,coef_to_wave_weight);
1647 FREE (cpl_matrix_delete ,wavelength);
1649 CPLCHECK_NUL (
"Cannot fit individual wavelength with 3rd order polynomial");
1651 cpl_msg_info (cpl_func,
"Correcting for wavelength error");
1655 for (cpl_size region = 0 ; region < n_region; region ++)
1658 cpl_array * wavelength_fitted = cpl_table_get_data_array (wave_fitted_table, data_x)[0];
1659 cpl_size nwave_fitted = cpl_array_get_size (wavelength_fitted);
1660 for (cpl_size wave = 0 ; wave < nwave_fitted ; wave ++ ) {
1662 double result = cpl_array_get (wavelength_fitted, wave, NULL);
1664 cpl_array_set (wavelength_fitted, wave, result * (n0 + n1*d_met + n2*d_met*d_met));
1667 for (cpl_size wave = nwave_fitted/2 ; wave < nwave_fitted-1 ; wave ++ ) {
1668 double result = cpl_array_get (wavelength_fitted, wave, NULL);
1669 double result2 = cpl_array_get (wavelength_fitted, wave+1, NULL);
1670 if (result2<result+2e-10) {
1671 result2=result+2e-10;
1672 cpl_array_set (wavelength_fitted, wave+1, result2);
1675 for (cpl_size wave = nwave_fitted/2 ; wave > 0 ; wave -- ) {
1676 double result = cpl_array_get (wavelength_fitted, wave, NULL);
1677 double result2 = cpl_array_get (wavelength_fitted, wave-1, NULL);
1678 if (result2>result-2e-10) {
1679 result2=result-2e-10;
1680 cpl_array_set (wavelength_fitted, wave-1, result2);
1688 return wave_fitted_table;
1704 double n0,
double n1,
double n2)
1707 cpl_ensure_code (wave_fibre, CPL_ERROR_NULL_INPUT);
1712 int npol = cpl_table_has_column (wave_fibre,
"BASE_12_P") ? 2 : 1;
1715 for (
int pol = 0; pol < npol; pol ++) {
1720 cpl_array * wavelength = cpl_table_get_data_array (wave_fibre, name)[0];
1724 cpl_size nwave = cpl_array_get_size (wavelength);
1725 for (cpl_size wave = 0 ; wave < nwave ; wave ++ ) {
1728 double result = cpl_array_get (wavelength, wave, NULL);
1730 cpl_array_set (wavelength, wave, result * (n0 + n1*d_met + n2*d_met*d_met));
1737 return CPL_ERROR_NONE;
1751 cpl_ensure_code (vis_data, CPL_ERROR_NULL_INPUT);
1754 cpl_propertylist * oiwave_header = NULL;
1755 cpl_table * oiwave_table = NULL;
1759 for (
int type_data = 0; type_data < ntype_data ; type_data ++) {
1763 for (
int pol = 0 ; pol<npol ; pol++) {
1783 return CPL_ERROR_NONE;
1802 cpl_table * wavefibre_table,
1803 cpl_table * profile_table,
1804 cpl_table * detector_table)
1807 cpl_ensure (wavedata_table, CPL_ERROR_NULL_INPUT, NULL);
1808 cpl_ensure (wavefibre_table, CPL_ERROR_NULL_INPUT, NULL);
1809 cpl_ensure (detector_table, CPL_ERROR_NULL_INPUT, NULL);
1810 cpl_ensure (profile_table, CPL_ERROR_NULL_INPUT, NULL);
1815 cpl_size n_region = cpl_table_get_nrow (detector_table);
1816 int npol = (n_region > 24 ? 2 : 1);
1821 cpl_size sizex = cpl_table_get_column_dimension (profile_table,
"DATA1", 0);
1822 cpl_size sizey = cpl_table_get_column_dimension (profile_table,
"DATA1", 1);
1824 cpl_image * profilesum_image = cpl_image_new (sizex, sizey, CPL_TYPE_DOUBLE);
1825 cpl_image_fill_window (profilesum_image, 1, 1, sizex, sizey, 0.0);
1827 cpl_image * wave_image = cpl_image_new (sizex, sizey, CPL_TYPE_DOUBLE);
1828 cpl_image_fill_window (wave_image, 1, 1, sizex, sizey, 0.0);
1830 cpl_image * realwave_image = cpl_image_new (sizex, sizey, CPL_TYPE_DOUBLE);
1831 cpl_image_fill_window (realwave_image, 1, 1, sizex, sizey, 0.0);
1836 for (cpl_size region = 0 ; region < n_region; region ++) {
1840 cpl_image * profile_image = cpl_imagelist_get (profile_imglist, 0);
1845 cpl_image_add (profilesum_image, profile_image);
1850 const cpl_array * wavelength;
1851 wavelength = cpl_table_get_array (wavedata_table,
GRAVI_DATA[region], 0);
1854 for (cpl_size x = 0; x < sizex; x ++){
1855 for (cpl_size y = 0; y < sizey; y ++){
1856 if (cpl_image_get (profile_image, x+1, y+1, &nv) > 0.01)
1857 cpl_image_set (wave_image, x+1, y+1,
1858 cpl_array_get (wavelength, x, NULL));
1869 wavelength = cpl_table_get_array (wavefibre_table, name, 0);
1872 for (cpl_size x = 0; x < sizex; x ++){
1873 for (cpl_size y = 0; y < sizey; y ++){
1874 if (cpl_image_get (profile_image, x+1, y+1, &nv) > 0.01)
1875 cpl_image_set (realwave_image, x+1, y+1,
1876 cpl_array_get (wavelength, x, NULL));
1885 cpl_imagelist * testwave_imglist = cpl_imagelist_new ();
1886 cpl_imagelist_set (testwave_imglist, wave_image, 0);
1887 cpl_imagelist_set (testwave_imglist, profilesum_image, 1);
1888 cpl_imagelist_set (testwave_imglist, realwave_image, 2);
1891 return testwave_imglist;
1909 cpl_ensure_code (wave_map, CPL_ERROR_NULL_INPUT);
1916 for (
int type_data = 0; type_data < 2; type_data ++ ) {
1921 cpl_size n_region = cpl_table_get_nrow (detector_table);
1932 double minwave = -1e10;
1933 double maxwave = 1e10;
1935 for (
int region = 0; region < n_region; region++) {
1938 minwave = CPL_MAX (minwave, cpl_array_get_min (wavelength));
1939 maxwave = CPL_MIN (maxwave, cpl_array_get_max (wavelength));
1956 int qc_reg[3] = {0,23,47};
1957 double qc_wave[2] = {2.099184e-6, 2.313952e-6};
1960 for (
int reg = 0; reg < (n_region > 24 ? 3 : 2); reg++) {
1961 cpl_size region = qc_reg[reg];
1964 cpl_size nwave = cpl_array_get_size (wavelength);
1965 const double * wave_tab = cpl_array_get_data_double_const (wavelength);
1969 for (
int iqc = 0 ; iqc < 2 ; iqc++) {
1971 if ( wave_tab[0] < wave_tab[nwave-1]) {
while (wave_tab[l2] < qc_wave[iqc]) l2 ++;}
1972 else {
while (wave_tab[l2] > qc_wave[iqc]) l2 ++;}
1974 if (l2-1 < 0 || l2 > nwave-1) {
1975 cpl_msg_error (cpl_func,
"Cannot find the QC position for lbd=%g", qc_wave[iqc]);
1980 double qc_pos = 0.0;
1981 qc_pos = fullstartx + (l2-1) + (qc_wave[iqc] - wave_tab[l2-1]) / (wave_tab[l2] - wave_tab[l2-1]);
1983 sprintf (name,
"ESO QC REFWAVE%i", iqc+1);
1985 cpl_propertylist_set_comment (wave_header, name,
"[m] value of ref wave");
1987 sprintf (name,
"ESO QC REFPOS%i %s%lli", iqc+1,
GRAVI_TYPE(type_data),region+1);
1989 cpl_propertylist_set_comment (wave_header, name,
"[pix] position of ref wave");
1991 cpl_msg_info (cpl_func,
"%s = %f [pix] for %e [m]", name, qc_pos, qc_wave[iqc]);
2007 cpl_imagelist * testwave_imglist;
2009 profile_table, detector_table);
2015 "TEST_WAVE", testwave_imglist);
2020 return CPL_ERROR_NONE;
2055 int type_data,
const cpl_parameterlist * parlist,
2059 cpl_ensure_code (wave_map, CPL_ERROR_NULL_INPUT);
2060 cpl_ensure_code (spectrum_data, CPL_ERROR_NULL_INPUT);
2062 CPL_ERROR_ILLEGAL_INPUT);
2070 cpl_propertylist_append (wave_header, raw_header);
2087 cpl_table * wavefibre_table;
2088 wavefibre_table =
gravi_wave_fibre (spectrum_table, detector_table, opd_table);
2097 double n0 = 1.0, n1 = -0.0165448, n2 = 0.00256002;
2098 cpl_msg_info (cpl_func,
"Rescale wavelengths with dispersion (%g,%g,%g)",n0,n1,n2);
2100 cpl_propertylist_update_string (wave_header,
"ESO QC WAVE_CORR",
"lbd*(N0+N1*(lbd-lbd0)/lbd0+N2*(lbd-lbd0)^2/lbd0^2)");
2119 cpl_table * wavedata_table;
2120 int spatial_order=2;
2121 int spectral_order=3;
2122 double rms_residuals;
2125 cpl_msg_info (cpl_func,
"Option force-waveFT-equal applied");
2136 fullstartx, spatial_order, spectral_order, &rms_residuals);
2141 double rms_fit=cpl_propertylist_get_double (raw_header,
QC_PHASECHI2);
2143 cpl_propertylist_set_comment (wave_header,
QC_CHI2WAVE(type_data),
"[nm]rms a.SC-b.FT+c=MET");
2154 cpl_table * wave_individual_table = cpl_table_new (1);
2155 cpl_table * weight_individual_table = cpl_table_new (1);
2156 cpl_table * wave_fitted_table = cpl_table_new (1);
2159 weight_individual_table,
2169 "WAVE_INDIV_SC", wave_individual_table);
2171 "WAVE_WEIGHT_SC", weight_individual_table);
2173 "WAVE_FITTED_SC", wavedata_table);
2183 cpl_msg_info (cpl_func,
"Add WAVE_FIBRE and WAVE_DATA in wave_map");
2199 return CPL_ERROR_NONE;
#define GRAVI_PRIMARY_HDR_EXT
typedefCPL_BEGIN_DECLS struct _gravi_data_ gravi_data
#define gravi_data_get_spectrum_data(data, type)
#define gravi_data_get_wave_data_plist(data, type)
#define gravi_data_get_wave_data(data, type)
#define gravi_data_get_spectrum_data_plist(data, type)
#define gravi_data_get_header(data)
#define gravi_data_get_oi_wave(data, type, pol, npol)
#define gravi_data_get_imaging_detector(data, type)
#define gravi_data_get_wave_fibre(data, type)
#define gravi_data_get_oi_wave_plist(data, type, pol, npol)
#define USE_LINEAR_ELLIPSE
cpl_msg_info(cpl_func, "Compute WAVE_SCAN for %s", GRAVI_TYPE(type_data))
cpl_propertylist_update_double(header, "ESO QC MINWAVE SC", cpl_propertylist_get_double(plist, "ESO QC MINWAVE SC"))
gravi_vis_create_met_ft(phase_ft, vis_met)
#define GRAVI_OI_VIS_MET_EXT
#define GRAVI_IMAGING_DETECTOR_FT_EXT
#define QC_MINWAVE_UM(type)
#define GRAVI_PROFILE_DATA_EXT
#define GRAVI_WAVE_FIBRE_EXT(type)
#define QC_MAXWAVE_UM(type)
#define OPD_COEFF_SIGN(type)
#define QC_CHI2WAVE(type)
#define GRAVI_WAVE_DATA_EXT(type)
#define QC_RMS_RESIDUALS_UM(type)
#define GRAVI_IMAGING_DETECTOR_SC_EXT
#define QC_RMS_RESIDUALS(type)
#define GRAVI_POLAR(pol, npol)
#define gravi_spectrum_get_npol(table)
#define gravi_msg_function_exit(flag)
#define FREE(function, variable)
#define CPLCHECK_NUL(msg)
#define gravi_msg_function_start(flag)
#define CPLCHECK_MSG(msg)
#define FREELOOP(function, variable, n)
double gravi_table_get_column_mean(cpl_table *table, const char *name, int base, int nbase)
cpl_error_code gravi_table_new_column(cpl_table *table, const char *name, const char *unit, cpl_type type)
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...
cpl_imagelist * gravi_imagelist_wrap_column(cpl_table *table_data, const char *data_x)
Wrap a column array of a table into an imagelist.
cpl_error_code gravi_imagelist_unwrap_images(cpl_imagelist *imglist)
Unwrap an imagelist an all its images.
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_table_add_scalar(cpl_table *table, const char *name, int base, int nbase, double value)
Multply scalar or array column by scalar.
cpl_error_code gravi_table_new_column_array(cpl_table *table, const char *name, const char *unit, cpl_type type, cpl_size size)
cpl_error_code gravi_data_add_cube(gravi_data *self, cpl_propertylist *plist, const char *extname, cpl_imagelist *imglist)
Add an IMAGE (imagelist) extension in gravi_data.
cpl_propertylist * gravi_data_get_plist(gravi_data *self, const char *extname)
Get the propertylist from EXTNAME.
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.
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_data_copy_ext(gravi_data *output, gravi_data *input, const char *name)
Copy extensions from one data to another.
int gravi_param_get_bool(const cpl_parameterlist *parlist, const char *name)
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_vector * gravi_ellipse_phase_create(cpl_vector *vectCA, cpl_vector *vectDB, cpl_vector *envelope)
Compute the phase atan{X',Y'}, unwraped from first sample.
cpl_table * gravi_metrology_create(cpl_table *metrology_table, cpl_propertylist *header)
Create the VIS_MET table.
cpl_error_code gravi_metrology_drs(cpl_table *metrology_table, cpl_table *vismet_table, cpl_propertylist *header, const cpl_parameterlist *parlist)
Fill the VIS_MET table with the DRS algorithm.
cpl_error_code gravi_metrology_tac(cpl_table *metrology_table, cpl_table *vismet_table, cpl_propertylist *header)
Compute the metrology signal from TAC algorithm.
int gravi_pfits_get_pola_num(const cpl_propertylist *plist, int type_data)
int gravi_pfits_get_fullstartx(const cpl_propertylist *plist)
cpl_error_code gravi_pfits_add_check(cpl_propertylist *header, const char *msg)
Add a QC.CHECK keyword to the header.
const char * gravi_pfits_get_spec_res(const cpl_propertylist *plist)
double gravi_pfits_get_dit_sc(const cpl_propertylist *plist)
double gravi_pfits_get_met_wavelength_mean(const cpl_propertylist *plist, cpl_table *met_table)
double gravi_pfits_get_double_default(const cpl_propertylist *plist, const char *name, double def)
cpl_error_code gravi_vis_create_opdsc_ft(cpl_table *vis_FT, cpl_table *vis_SC, double dit_sc)
Compute the resampled SC signal for each FT DIT per base.
int gravi_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.
char GRAVI_BASE_NAME[6][3]
cpl_size gravi_spectrum_get_nwave(const cpl_table *table)
cpl_size gravi_spectrum_get_nregion(const cpl_table *table)
cpl_vector * gravi_compute_envelope(const cpl_vector *opd, int wave, int nwave)
Compute the envelope value.
int GRAVI_BASE_TEL[GRAVI_NBASE][2]
int gravi_get_region(cpl_table *img_det, int base, char phase, int pol)
Find the region matching base, phase and pol.
int gravi_region_get_base_sign(cpl_table *imaging_detector, int base)
Return the sign of a base by looking at the PORT order.
cpl_table * gravi_opds_calibration(cpl_table *spectrum_table, cpl_table *detector_table, cpl_table *opdguess_table)
Compute the mean opd of each baseline from spectrum.
cpl_vector * gravi_opds_fit_opdmet(cpl_table *opd_ft, double lbd_met)
Compute the absolute scaling coefficients of SC and FT OPDs.
cpl_table * gravi_wave_fibre(cpl_table *spectrum_table, cpl_table *detector_table, cpl_table *opd_table)
Compute the wavelength of each channel for each 6 baselines.
cpl_table * gravi_wave_fit_2d(cpl_table *wavefibre_table, cpl_table *detector_table, gravi_data *wave_param, cpl_size fullstartx, int spatial_order, int spectral_order, double *rms_residuals)
Compute the WAVE_DATA table (1 wavelength per region) from the WAVE_FIBRE table (1 wavelength per bas...
#define PLOT_WAVE_PHASE_VS_OPD
cpl_error_code gravi_wave_compute_opds(gravi_data *spectrum_data, cpl_table *met_table, const cpl_parameterlist *parlist)
Recover the OPD modulation from a spectrum_data and vismet_table.
cpl_error_code gravi_opds_correct_closures(cpl_table *opd_sc, const char *name)
Correct the input table to ensure constant closure phase.
cpl_error_code gravi_compute_wave(gravi_data *wave_map, gravi_data *spectrum_data, int type_data, const cpl_parameterlist *parlist, gravi_data *wave_param)
Create the WAVE calibration map.
cpl_table * gravi_compute_argon_wave(cpl_table *spectrum_table)
Compute a WAVE calibration from the ARGON data (SC only)
cpl_table * gravi_wave_fit_individual(cpl_table *wave_individual_table, cpl_table *weight_individual_table, cpl_table *wave_fitted_table, cpl_table *opd_table, cpl_table *spectrum_table, cpl_table *detector_table, double n0, double n1, double n2)
cpl_error_code gravi_wave_qc(gravi_data *wave_map, gravi_data *profile_map)
Compute the QC parameters of the WAVE product.
cpl_error_code gravi_wave_correct_dispersion(cpl_table *wave_fibre, double n0, double n1, double n2)
Correct the WAVE_FIBRE table from a harcoded dispersion model.
cpl_error_code gravi_wave_correct_color(gravi_data *vis_data)
Create a OI_WAVELENGTH_CORR table with color corrected wavelength.
cpl_imagelist * gravi_wave_test_image(cpl_table *wavedata_table, cpl_table *wavefibre_table, cpl_table *profile_table, cpl_table *detector_table)
Compute the (useless) TEST_WAVE table from the WAVE_FIBRE and the PROFILE maps.
cpl_table * gravi_opds_compute_guess(cpl_table *spectrumsc_table, cpl_table *opdft_table, cpl_table *met_table, double dit_sc, double lbd_met)
Compute a guess of the OPD modulation of SC from FT and MET.