158 cpl_ensure (spectrum_table, CPL_ERROR_NULL_INPUT, NULL);
161 cpl_size nwave = cpl_table_get_column_depth (spectrum_table,
"DATA1");
165 cpl_msg_info (cpl_func,
"spectrum_table = %lld",cpl_table_get_column_depth (spectrum_table,
"DATA1"));
172 cpl_size nlines = 14;
173 double plines_str[] = {60,
189 double plines_lbd[] = {1.982291,
205 cpl_vector * lines_lbd = cpl_vector_wrap (nlines,plines_lbd);
206 cpl_vector * lines_str = cpl_vector_wrap (nlines,plines_str);
207 cpl_bivector * lines = cpl_bivector_wrap_vectors (lines_lbd, lines_str);
210 cpl_wlcalib_slitmodel * model = cpl_wlcalib_slitmodel_new ();
211 cpl_wlcalib_slitmodel_set_wslit (model, 0.1);
212 cpl_wlcalib_slitmodel_set_wfwhm (model, 1.25);
213 cpl_wlcalib_slitmodel_set_threshold (model, 5.0);
214 cpl_wlcalib_slitmodel_set_catalog (model, lines);
217 double values_hr[] = {1.97048,0.2228e-3,2.7728e-08,-4.72e-12};
218 double values_mr[] = {1.9697,0.2179e-2,2.5e-07,-5e-10};
219 double * values = nwave > 1000 ? values_hr : values_mr;
222 cpl_polynomial * dispersion0 = cpl_polynomial_new (1);
223 for (cpl_size order = 0 ; order < 4 ; order ++) {
224 cpl_polynomial_set_coeff (dispersion0, &order, values[order]);
228 double minwave = -1e10;
229 double maxwave = +1e10;
231 cpl_vector * spectrum = cpl_vector_new (nwave);
232 cpl_vector * input_spectrum = cpl_vector_new (nwave);
233 cpl_vector * model_spectrum = cpl_vector_new (nwave);
236 cpl_table * fit_table = cpl_table_new (nregion);
242 cpl_polynomial * dispersion = cpl_polynomial_duplicate (dispersion0);
245 for (cpl_size reg = 0; reg < nregion ; reg ++ ) {
246 cpl_msg_info (cpl_func,
"Fit region %lld over %lld", reg+1, nregion);
249 const cpl_array * data = cpl_table_get_array (spectrum_table,
GRAVI_DATA[reg], 0);
250 for (cpl_size wave=0; wave < nwave; wave ++) {
251 cpl_vector_set (spectrum, wave, log (CPL_MAX (cpl_array_get (data, wave, NULL), 1.0)));
252 cpl_vector_set (input_spectrum, wave, cpl_array_get (data, wave, NULL));
260 int maxdeg = 3, nmaxima = 0, linelim = 99;
261 int maxite = 100 * maxdeg, maxfail = 10, maxcont = 10;
262 int hsize = (reg == 0 ? 40 : 5);
263 double pixtol = 1e-6, pixstep = 0.5, pxc = 0.0;
267 irplib_polynomial_find_1d_from_correlation_all (dispersion, maxdeg, spectrum,
269 (irplib_base_spectrum_model*)model,
270 &irplib_vector_fill_logline_spectrum,
272 hsize, maxite, maxfail, maxcont,
277 irplib_vector_fill_line_spectrum (model_spectrum, dispersion, (
void *)model);
278 cpl_polynomial_dump (dispersion, stdout);
281 cpl_array *
wave_data = cpl_array_new (nwave, CPL_TYPE_DOUBLE);
282 for (cpl_size pix = 0; pix < nwave ; pix++)
283 cpl_array_set (
wave_data, pix, cpl_polynomial_eval_1d (dispersion, (
double)pix, NULL) * 1e-6);
286 minwave = CPL_MAX (cpl_array_get_min (
wave_data), minwave);
287 maxwave = CPL_MIN (cpl_array_get_max (
wave_data), maxwave);
295 cpl_array * tmp_array;
296 tmp_array = cpl_array_wrap_double (cpl_vector_get_data (input_spectrum), nwave);
297 cpl_table_set_array (fit_table,
"DATA", reg, tmp_array);
298 cpl_array_unwrap (tmp_array);
299 tmp_array = cpl_array_wrap_double (cpl_vector_get_data (model_spectrum), nwave);
300 cpl_table_set_array (fit_table,
"DATA_MODEL", reg, tmp_array);
301 cpl_array_unwrap (tmp_array);
302 tmp_array = cpl_array_new (nwave, CPL_TYPE_DOUBLE);
303 for (cpl_size wave = 0; wave < nwave; wave ++)
304 cpl_array_set (tmp_array, wave, cpl_polynomial_eval_1d (dispersion, (
double)wave, NULL) * 1e-6);
305 cpl_table_set_array (fit_table,
"DATA_WAVE", reg, tmp_array);
306 cpl_array_delete (tmp_array);
312 FREE (cpl_table_delete, fit_table);
315 FREE (cpl_vector_delete, spectrum);
316 FREE (cpl_vector_delete, input_spectrum);
317 FREE (cpl_vector_delete, model_spectrum);
318 FREE (cpl_polynomial_delete, dispersion0);
319 FREE (cpl_polynomial_delete, dispersion);
468 cpl_ensure (ft_table, CPL_ERROR_NULL_INPUT, NULL);
472 cpl_size nrow = cpl_table_get_nrow (ft_table) /
GRAVI_NBASE;
475 double * opd_sc = cpl_table_get_data_double (ft_table,
"OPD_SC");
476 double * opd_ft = cpl_table_get_data_double (ft_table,
"OPD");
477 double * phase_met = cpl_table_get_data_double (ft_table,
"PHASE_MET_FC");
481 cpl_size nrow_valid = 0;
482 for (cpl_size row = 0; row < nrow; row++)
if (opd_sc[row*
GRAVI_NBASE] != 0) nrow_valid++;
483 cpl_msg_info (cpl_func,
"nrow_valid = %lld", nrow_valid);
485 cpl_ensure (nrow_valid > 100, CPL_ERROR_ILLEGAL_INPUT, NULL);
489 cpl_matrix * rhs_matrix = cpl_matrix_new (nrow_valid*
GRAVI_NBASE, 1);
493 cpl_size row_valid = 0;
495 for (cpl_size row=0; row<nrow; row++) {
502 cpl_matrix_set (rhs_matrix, idv, 0, phase_met[
id] * lbd_met / CPL_MATH_2PI);
506 cpl_matrix_set (model_matrix, idv, 0, 1*opd_sc[
id]);
507 cpl_matrix_set (model_matrix, idv, 1, -1*opd_ft[
id]);
511 cpl_matrix_set (model_matrix, idv, 2 + base, 1.0);
519 cpl_matrix * res_matrix = cpl_matrix_solve_normal (model_matrix, rhs_matrix);
522 cpl_matrix * residual_matrix = cpl_matrix_product_create (model_matrix, res_matrix);
523 cpl_matrix_subtract (residual_matrix, rhs_matrix);
524 double rms_fit = cpl_matrix_get_stdev (residual_matrix);
528 cpl_msg_info (cpl_func,
"coeff SC = %.20g ", cpl_matrix_get (res_matrix, 0, 0));
529 cpl_msg_info (cpl_func,
"coeff FT = %.20g ", cpl_matrix_get (res_matrix, 1, 0));
530 cpl_msg_info (cpl_func,
"residual stdev = %.20g [m]", rms_fit);
533 cpl_vector * opd_coeff = cpl_vector_new(3);
534 cpl_vector_set (opd_coeff,
GRAVI_SC, cpl_matrix_get (res_matrix, 0, 0));
535 cpl_vector_set (opd_coeff,
GRAVI_FT, cpl_matrix_get (res_matrix, 1, 0));
536 cpl_vector_set (opd_coeff, 2, rms_fit);
539 FREE (cpl_matrix_delete, residual_matrix);
540 FREE (cpl_matrix_delete, res_matrix);
541 FREE (cpl_matrix_delete, model_matrix);
542 FREE (cpl_matrix_delete, rhs_matrix);
827 cpl_table * met_table,
828 const cpl_parameterlist * parlist)
831 cpl_ensure_code (spectrum_data, CPL_ERROR_NULL_INPUT);
832 cpl_ensure_code (met_table, CPL_ERROR_NULL_INPUT);
864 cpl_msg_info (cpl_func,
"Compute OPD of FT from ellipse");
866 cpl_table * ft_table;
870 cpl_msg_info (cpl_func,
"Compute OPD of SC from ellipse");
872 cpl_table * guess_table;
875 cpl_table * sc_table;
878 FREE (cpl_table_delete, guess_table);
886 cpl_msg_info (cpl_func,
"Fit MET = a.SC - b.FT + c to get absolute modulation");
891 CPLCHECK_MSG (
"Cannot resample SC or MET at the FT frequency");
903 cpl_vector_get (coeff_vector, 2));
904 cpl_propertylist_set_comment (spectrum_header,
QC_PHASECHI2,
905 "chi2 of a.SC-b.FT+c=MET");
908 for (
int type_data = 0; type_data < 2; type_data++) {
909 double tmp = cpl_vector_get (coeff_vector, type_data);
910 cpl_propertylist_update_float (spectrum_header,
OPD_COEFF_SIGN(type_data), tmp);
911 cpl_propertylist_set_comment (spectrum_header,
OPD_COEFF_SIGN(type_data),
"wavelength correction");
915 if (cpl_vector_get (coeff_vector, 2) > 1e-7) {
919 if (cpl_vector_get (coeff_vector, 2) > 1.2e-7) {
920 cpl_msg_warning (cpl_func,
"*************************************************");
921 cpl_msg_warning (cpl_func,
"**** !!! residuals of the fit too high !!! ****");
922 cpl_msg_warning (cpl_func,
"**** Residuals are:%7.0f nm ****",cpl_vector_get (coeff_vector, 2)*1e9);
923 cpl_msg_warning (cpl_func,
"**** SC and RMN may be desynchronized ****");
924 cpl_msg_warning (cpl_func,
"**** (or out of the envelope in LOW) ****");
925 cpl_msg_warning (cpl_func,
"*************************************************");
933 double coeff_sc = cpl_vector_get (coeff_vector,
GRAVI_SC);
934 cpl_table_multiply_scalar (sc_table,
"OPD", coeff_sc);
936 double coeff_ft = cpl_vector_get (coeff_vector,
GRAVI_FT);
937 cpl_table_multiply_scalar (ft_table,
"OPD", coeff_ft);
939 FREE (cpl_vector_delete, coeff_vector);
940 CPLCHECK_MSG (
"Cannot correct OPDs from scaling coefficients");
966 return CPL_ERROR_NONE;
996 cpl_table * detector_table,
997 cpl_table * opd_table)
1000 cpl_ensure (spectrum_table, CPL_ERROR_NULL_INPUT, NULL);
1001 cpl_ensure (detector_table, CPL_ERROR_NULL_INPUT, NULL);
1002 cpl_ensure (opd_table, CPL_ERROR_NULL_INPUT, NULL);
1007 cpl_table * wave_fibre = cpl_table_new (1);
1010 cpl_size nwave = cpl_table_get_column_depth (spectrum_table,
"DATA1");
1011 cpl_size n_region = cpl_table_get_nrow (detector_table);
1012 cpl_size nrow = cpl_table_get_nrow (spectrum_table);
1014 int npol = (n_region > 24 ? 2 : 1);
1020 for (
int pol = 0; pol < npol; pol++) {
1022 cpl_msg_info (cpl_func,
"Compute wave fibre for pol %i over %i, base %i over %i",
1030 if (iA<0 || iB<0 || iC<0 || iD<0){
1031 cpl_msg_warning (cpl_func,
"Don't found the A, B, C or D !!!");
1038 cpl_matrix * opd_matrix = cpl_matrix_new (1, nrow);
1039 cpl_vector * opd_vector = cpl_vector_new (nrow);
1040 for (cpl_size row = 0; row < nrow; row ++ ) {
1041 double value = cpl_table_get (opd_table,
"OPD", row*
GRAVI_NBASE+base, NULL);
1042 cpl_matrix_set (opd_matrix, 0, row, value);
1043 cpl_vector_set (opd_vector, row, value);
1048 cpl_array * wavelength = cpl_array_new (nwave, CPL_TYPE_DOUBLE);
1049 cpl_array * wavechi2 = cpl_array_new (nwave, CPL_TYPE_DOUBLE);
1050 cpl_array_fill_window (wavelength, 0, nwave, 0.0);
1051 cpl_array_fill_window (wavechi2, 0, nwave, 1e10);
1056 for (cpl_size wave = 0; wave < nwave; wave++) {
1058 cpl_vector * vector_T = NULL, * vector_X, * vector_Y;
1063 cpl_vector_subtract (vector_X, vector_T);
1064 FREE (cpl_vector_delete, vector_T);
1069 cpl_vector_subtract (vector_Y, vector_T);
1070 FREE (cpl_vector_delete, vector_T);
1081 FREE (cpl_vector_delete, vector_X);
1082 FREE (cpl_vector_delete, vector_Y);
1083 FREE (cpl_vector_delete, envelope_vector);
1086 if (phase == NULL) {
1087 cpl_msg_warning (cpl_func,
"Cannot compute wave for channel %lld and base %d", wave, base);
1092 cpl_vector_multiply_scalar (phase, phi_sign);
1095 double lbd_channel = 1.95e-6 + (2.46e-6 - 1.95e-6) / nwave * wave;
1100 const cpl_size mindeg = 0, maxdeg = 1;
1101 cpl_polynomial * fit_slope = cpl_polynomial_new (1);
1102 cpl_polynomial_fit (fit_slope, opd_matrix, NULL, phase, NULL, CPL_FALSE, &mindeg, &maxdeg);
1105 cpl_vector * residuals = cpl_vector_new (nwave);
1107 cpl_vector_fill_polynomial_fit_residual (residuals, phase, NULL, fit_slope, opd_matrix, &rechisq);
1111 char gnuplot_str[200];
1112 sprintf (gnuplot_str,
"set title 'Wavelength (base %d)'; set xlabel 'Phase [rad]'; set ylabel 'OPD (m)';", base);
1113 cpl_plot_vector (gnuplot_str, NULL, NULL, opd_vector);
1114 sprintf (gnuplot_str,
"set title 'Wavelength residuals (base %d)'; set xlabel 'Phase [rad]'; set ylabel 'OPD (m)';", base);
1115 cpl_plot_vector (gnuplot_str, NULL, NULL, residuals);
1122 const cpl_size pow_slope = 1;
1123 double slope = cpl_polynomial_get_coeff (fit_slope, &pow_slope);
1126 if (slope < 0.0 && wave == 0) {
1127 cpl_msg_warning (cpl_func,
"Negative wavelength!! "
1128 "Report to DRS team");
1132 cpl_array_set (wavechi2, wave, sqrt(rechisq));
1133 cpl_array_set (wavelength, wave, CPL_MATH_2PI / fabs(slope));
1136 cpl_vector_delete (phase);
1137 cpl_vector_delete (residuals);
1138 cpl_polynomial_delete (fit_slope);
1142 cpl_matrix_delete (opd_matrix);
1143 cpl_vector_delete (opd_vector);
1147 cpl_table_new_column_array (wave_fibre, name, CPL_TYPE_DOUBLE, nwave);
1148 cpl_table_set_column_unit (wave_fibre, name,
"m");
1149 cpl_table_set_array (wave_fibre, name, 0, wavelength);
1150 cpl_array_delete (wavelength);
1154 cpl_table_new_column_array (wave_fibre, name, CPL_TYPE_DOUBLE, nwave);
1155 cpl_table_set_array (wave_fibre, name, 0, wavechi2);
1156 cpl_array_delete (wavechi2);
1186 cpl_table * detector_table,
1188 cpl_size fullstartx,
1191 double * rms_residuals)
1194 cpl_ensure (wavefibre_table, CPL_ERROR_NULL_INPUT, NULL);
1195 cpl_ensure (detector_table, CPL_ERROR_NULL_INPUT, NULL);
1201 cpl_size n_region = cpl_table_get_nrow (detector_table);
1202 int npol = n_region > 24 ? 2 : 1;
1203 cpl_size nwave = cpl_table_get_column_depth (wavefibre_table, npol > 1 ?
"BASE_12_S" :
"BASE_12_C");
1210 cpl_vector * odd_index = cpl_vector_new (nwave);
1211 for (
int i = fullstartx; i < fullstartx + nwave; i++) {
1212 if (nwave >
GRAVI_LBD_FTSC) cpl_vector_set (odd_index, i - fullstartx, ((i/64)%2 == 0) ? 0 : 1);
1213 else cpl_vector_set (odd_index, i - fullstartx, 0);
1219 cpl_polynomial ** coef_poly = cpl_calloc (npol,
sizeof (cpl_polynomial*));
1222 for (
int pol = 0; pol < npol; pol++) {
1226 cpl_vector * coord_X = cpl_vector_new (
GRAVI_NBASE * nwave);
1227 cpl_vector * coord_Y = cpl_vector_new (
GRAVI_NBASE * nwave);
1229 cpl_vector * all_wavelength = cpl_vector_new (
GRAVI_NBASE * nwave);
1230 cpl_vector * all_wavechi2 = cpl_vector_new (
GRAVI_NBASE * nwave);
1231 cpl_vector * all_valid = cpl_vector_new (
GRAVI_NBASE * nwave);
1247 cpl_array * wavelength = cpl_table_get_data_array (wavefibre_table, name)[0];
1250 cpl_array * wavechi2 = cpl_table_get_data_array (wavefibre_table, name)[0];
1253 for (cpl_size wave = 0; wave < nwave; wave++) {
1254 cpl_size pos = base * nwave + wave;
1258 double wave_value = cpl_array_get (wavelength, wave, &nv);
1259 double chi2_value = cpl_array_get (wavechi2, wave, &nv);
1262 cpl_vector_set (all_valid, pos, 1);
1266 if ((chi2_value > M_PI_4 ||
1269 cpl_vector_set (all_valid, pos, 0);
1271 else if (nwave > 100) {
1273 if ((chi2_value > M_PI_4 ||
1276 cpl_vector_set (all_valid, pos, 0);
1280 if ((chi2_value > M_PI_4 ||
1284 wave == 0 || wave == nwave-1))
1285 cpl_vector_set (all_valid, pos, 0);
1289 if ((chi2_value > M_PI_4 ||
1291 wave_value < 1.99e-6 ||
1292 wave_value > 2.5e-6))
1293 cpl_vector_set (all_valid, pos, 0);
1297 cpl_vector_set (all_wavelength, pos, wave_value);
1298 cpl_vector_set (all_wavechi2, pos, chi2_value);
1301 cpl_vector_set (coord_X, pos, (
double)(iA + iB + iC + iD) / 4.);
1305 cpl_vector_set (coord_Y, pos, wave + cpl_vector_get (odd_index, wave)*0.15);
1315 cpl_size nvalid = cpl_vector_get_sum (all_valid);
1320 cpl_vector * vector = cpl_vector_new (nvalid);
1321 cpl_matrix * matrix = cpl_matrix_new (2, nvalid);
1323 for (cpl_size c = 0, i = 0 ; i < nwave *
GRAVI_NBASE; i ++) {
1324 if (!cpl_vector_get (all_valid, i))
continue;
1325 cpl_vector_set (vector, c, cpl_vector_get (all_wavelength, i));
1326 cpl_matrix_set (matrix, 0, c, cpl_vector_get (coord_X, i));
1327 cpl_matrix_set (matrix, 1, c, cpl_vector_get (coord_Y, i));
1337 cpl_size deg2d[2] = {2, 3};
1338 if ( (nwave < 20) && (nwave > 8) ) {deg2d[0] = 2; deg2d[1] = 7;}
1339 deg2d[0] = spatial_order;
1340 deg2d[1] = spectral_order;
1342 cpl_msg_info (cpl_func,
"Fit a 2d polynomial {%lli..%lli} to the wavelengths map", deg2d[0], deg2d[1]);
1344 cpl_polynomial * fit2d = cpl_polynomial_new (2);
1345 cpl_polynomial_fit (fit2d, matrix, NULL, vector, NULL, CPL_TRUE, NULL, deg2d);
1346 coef_poly[pol] = fit2d;
1353 double rechisq = 0.0;
1354 cpl_vector * residuals = cpl_vector_new (nvalid);
1355 cpl_vector_fill_polynomial_fit_residual (residuals, vector, NULL, fit2d, matrix, &rechisq);
1356 *rms_residuals += cpl_vector_get_stdev(residuals)/npol;
1357 FREE (cpl_vector_delete, residuals);
1361 FREE (cpl_matrix_delete, matrix);
1362 FREE (cpl_vector_delete, vector);
1363 FREE (cpl_vector_delete, all_wavelength);
1364 FREE (cpl_vector_delete, all_wavechi2);
1365 FREE (cpl_vector_delete, all_valid);
1366 FREE (cpl_vector_delete, coord_X);
1367 FREE (cpl_vector_delete, coord_Y);
1376 cpl_table * wavedata_table = cpl_table_new (1);
1377 cpl_vector * pos = cpl_vector_new (2);
1378 cpl_array * value = cpl_array_new (nwave, CPL_TYPE_DOUBLE);
1380 for (cpl_size region = 0 ; region < n_region; region ++) {
1384 for (cpl_size wave = 0; wave < nwave; wave ++) {
1387 cpl_vector_set (pos, 0, region);
1388 cpl_vector_set (pos, 1, wave + cpl_vector_get (odd_index, wave)*0.15);
1390 double result = cpl_polynomial_eval (coef_poly[pol], pos);
1391 cpl_array_set (value, wave, result);
1395 double previous_wave = cpl_array_get(value, nwave/2, NULL);
1396 for (cpl_size wave_loop = nwave/2 ; wave_loop >= 0 ; 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);
1402 previous_wave = cpl_array_get(value, nwave/2, NULL);
1403 for (cpl_size wave_loop = nwave/2 ; wave_loop < nwave ; wave_loop ++){
1404 if (previous_wave > cpl_array_get(value, wave_loop, NULL))
1405 cpl_array_set(value, wave_loop, previous_wave);
1406 else previous_wave = cpl_array_get(value, wave_loop, NULL);
1411 cpl_table_new_column_array (wavedata_table, data_x, CPL_TYPE_DOUBLE, nwave);
1412 cpl_table_set_array (wavedata_table, data_x, 0, value);
1417 FREE (cpl_vector_delete, pos);
1418 FREE (cpl_array_delete, value);
1419 FREELOOP (cpl_polynomial_delete, coef_poly, npol);
1420 FREE (cpl_vector_delete, odd_index);
1423 return wavedata_table;
1495 cpl_table * spectrum_table, cpl_table * detector_table, cpl_table * opd_table
1498 cpl_ensure (spectrum_table, CPL_ERROR_NULL_INPUT, NULL);
1499 cpl_ensure (detector_table, CPL_ERROR_NULL_INPUT, NULL);
1500 cpl_ensure (opd_table, CPL_ERROR_NULL_INPUT, NULL);
1503 cpl_size nwave = cpl_table_get_column_depth (spectrum_table,
"DATA1");
1504 cpl_size nrow = cpl_table_get_nrow (spectrum_table);
1505 cpl_size n_region = cpl_table_get_nrow (detector_table);
1506 const int npol = (n_region > 24 ? 2 : 1);
1509 cpl_table * wave_bandpass = cpl_table_new (1);
1512 const double wave_min = 1.8 * 1e-6;
1513 const double wave_max = 2.8 * 1e-6;
1516 const cpl_size ngrid = 1000;
1517 const double delta_wavenumber = ((1.0 / wave_max) - (1.0 / wave_min)) / ngrid;
1519 cpl_vector *wavenumber = cpl_vector_new (ngrid);
1520 for (
int i = 0; i < ngrid; i++) {
1521 double wn = (1.0 / wave_min) + i * delta_wavenumber;
1522 cpl_vector_set (wavenumber, i, wn);
1526 for (
int reg = 0; reg < n_region; reg++) {
1527 cpl_table_new_column_array (wave_bandpass,
GRAVI_DATA[reg], CPL_TYPE_DOUBLE, nwave);
1533 for (
int pol = 0; pol < npol; pol++) {
1535 cpl_msg_info (cpl_func,
"Compute bandpass for pol %i over %i, base %i over %i",
1539 cpl_vector * opd_vector = cpl_vector_new (nrow);
1540 for (cpl_size row = 0; row < nrow; row ++ ) {
1541 double value = cpl_table_get (opd_table,
"OPD", row*
GRAVI_NBASE+base, NULL);
1542 cpl_vector_set (opd_vector, row, value);
1546 for (
char pha =
'A'; pha <=
'D'; pha++) {
1549 cpl_msg_warning (cpl_func,
"Don't found the A, B, C or D !!!");
1553 cpl_array *reg_array = cpl_array_new(nwave, CPL_TYPE_DOUBLE);
1554 for (
int wave = 0; wave < nwave; wave++) {
1556 cpl_array *ftrans =
my_ft_discrete (opd_vector, counts, wavenumber);
1558 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_OUTPUT);
1564 cpl_array_abs (ftrans);
1565 cpl_array_get_maxpos (ftrans, &argmax);
1567 if (argmax != 0 && argmax != ngrid - 1) {
1604 cpl_array_set (reg_array, wave, 1.0 / cpl_vector_get(wavenumber, argmax));
1607 cpl_array_set (reg_array, wave, 0.0);
1610 cpl_vector_delete (counts);
1611 cpl_array_delete (ftrans);
1614 cpl_table_set_array(wave_bandpass,
GRAVI_DATA[reg], 0, reg_array);
1615 cpl_array_delete(reg_array);
1618 cpl_vector_delete(opd_vector);
1622 cpl_vector_delete(wavenumber);
1625 for (
int reg = 0; reg < n_region; reg++) {
1626 cpl_array *reg_arr = cpl_table_get_data_array(wave_bandpass,
GRAVI_DATA[reg])[0];
1627 for (
int wave = 0; wave < nwave; wave++) {
1629 if (cpl_vector_get_sum(counts) == 0.0) {
1630 cpl_msg_warning(cpl_func,
"region %s, pixel %d has no counts",
GRAVI_DATA[reg], wave);
1633 cpl_array_set(reg_arr, wave, cpl_array_get(reg_arr, 1, NULL));
1634 else if (wave == nwave - 1)
1635 cpl_array_set(reg_arr, wave, cpl_array_get(reg_arr, nwave - 2, NULL));
1637 cpl_msg_error(cpl_func,
"Invalid wave on intermediate pixel");
1639 cpl_vector_delete (counts);
1644 return wave_bandpass;
1654 cpl_table * weight_individual_table,
1655 cpl_table * wave_fitted_table,
1656 cpl_table * opd_table,
1657 cpl_table * spectrum_table,
1658 cpl_table * detector_table,
1659 double n0,
double n1,
double n2)
1664 cpl_ensure (wave_individual_table, CPL_ERROR_NULL_INPUT, NULL);
1665 cpl_ensure (weight_individual_table, CPL_ERROR_NULL_INPUT, NULL);
1666 cpl_ensure (wave_fitted_table, CPL_ERROR_NULL_INPUT, NULL);
1667 cpl_ensure (opd_table, CPL_ERROR_NULL_INPUT, NULL);
1668 cpl_ensure (spectrum_table, CPL_ERROR_NULL_INPUT, NULL);
1669 cpl_ensure (detector_table, CPL_ERROR_NULL_INPUT, NULL);
1672 cpl_size nwave = cpl_table_get_column_depth (spectrum_table,
"DATA1");
1673 cpl_size n_region = cpl_table_get_nrow (detector_table);
1674 cpl_size nrow = cpl_table_get_nrow (spectrum_table);
1675 int npol = (n_region > 24 ? 2 : 1);
1676 cpl_size nwave_ref=3000;
1677 if (nwave<10) nwave_ref=600;
1687 cpl_array * wave_individual_array = cpl_array_new (nwave, CPL_TYPE_DOUBLE);
1688 cpl_array * weight_individual_array = cpl_array_new (nwave, CPL_TYPE_DOUBLE);
1689 cpl_matrix * data_flux_matrix = cpl_matrix_new (nrow, nwave);
1690 cpl_matrix * vis_to_flux_matrix = cpl_matrix_new (nrow, 3);
1691 cpl_matrix * signal_matrix = cpl_matrix_new (nwave, nwave_ref);
1692 cpl_matrix * residual_matrix = cpl_matrix_new (nwave, nwave_ref);
1693 cpl_array * wave_reference_array = cpl_array_new (nwave_ref, CPL_TYPE_DOUBLE);
1697 cpl_matrix_fill_column(vis_to_flux_matrix,1,2);
1698 for (cpl_size wave_ref = 0; wave_ref < nwave_ref; wave_ref+=1)
1701 double wave_value=1.95e-6+wave_ref*0.6e-6/((double) nwave_ref);
1702 cpl_array_set_double(wave_reference_array,wave_ref,wave_value);
1705 CPLCHECK_NUL (
"Cannot initialize arrays for wavelength fit");
1708 for (cpl_size region = 0 ; region < n_region; region ++) {
1713 cpl_msg_info_overwritable (cpl_func,
"Least square fitting of wavelength for region %s", data_x);
1716 for (cpl_size row = 0; row < nrow; row ++ ) {
1717 cpl_array * flux_array= cpl_table_get_data_array(spectrum_table,data_x)[row];
1718 for (cpl_size wave = 0; wave < nwave; wave ++) {
1719 cpl_matrix_set (data_flux_matrix, row, wave, cpl_array_get(flux_array,wave, NULL));
1724 for (cpl_size wave_ref = 0; wave_ref < nwave_ref; wave_ref+=1)
1727 double wave_value=cpl_array_get(wave_reference_array,wave_ref,NULL);
1729 for (cpl_size row = 0; row < nrow; row ++ ) {
1730 double opd = cpl_table_get (opd_table,
"OPD", row*
GRAVI_NBASE+base, NULL);
1731 double coherence_loss=1;
1732 if (fabs(opd) > 1e-9)
1736 coherence_loss=sin(opd*19500)/(opd*19500);
1739 cpl_matrix_set(vis_to_flux_matrix,row,0,cos(opd*6.28318530718/wave_value)*coherence_loss);
1740 cpl_matrix_set(vis_to_flux_matrix,row,1,sin(opd*6.28318530718/wave_value)*coherence_loss);
1743 cpl_matrix * coef_vis = cpl_matrix_solve_normal(vis_to_flux_matrix,data_flux_matrix);
1744 cpl_matrix * data_flux_fit = cpl_matrix_product_create(vis_to_flux_matrix,coef_vis);
1745 cpl_matrix * residuals_fit = cpl_matrix_duplicate(data_flux_fit);
1746 cpl_matrix_subtract (residuals_fit,data_flux_matrix);
1748 for (cpl_size wave = 0; wave < nwave; wave ++ ) {
1749 cpl_matrix * temp_matrix = cpl_matrix_extract_column (data_flux_fit, wave);
1750 cpl_matrix_set(signal_matrix,wave,wave_ref,cpl_matrix_get_stdev(temp_matrix));
1751 FREE (cpl_matrix_delete, temp_matrix);
1752 cpl_matrix * temp_matrix2 = cpl_matrix_extract_column (residuals_fit, wave);
1753 cpl_matrix_set(residual_matrix,wave,wave_ref,cpl_matrix_get_stdev(temp_matrix2));
1754 FREE (cpl_matrix_delete, temp_matrix2);
1757 FREE (cpl_matrix_delete, coef_vis);
1758 FREE (cpl_matrix_delete, data_flux_fit);
1759 FREE (cpl_matrix_delete, residuals_fit);
1761 CPLCHECK_NUL (
"Cannot do Matrix inversion to calculate optimum wavelength");
1766 cpl_size wave_ref=1;
1767 cpl_size discarded=1;
1768 for (cpl_size wave = 0; wave < nwave; wave ++ ) {
1770 cpl_matrix * chi2_extract=cpl_matrix_extract_row(residual_matrix,wave);
1772 cpl_matrix_get_minpos(chi2_extract,&discarded, &wave_ref );
1774 double wave_value = cpl_array_get(wave_reference_array, wave_ref, NULL );
1775 double weight_value = cpl_matrix_get(signal_matrix, wave , wave_ref )/(0.1+cpl_matrix_get(residual_matrix, wave, wave_ref ));
1777 cpl_array_set_double (wave_individual_array, wave, wave_value);
1778 cpl_array_set_double (weight_individual_array, wave, weight_value);
1780 FREE (cpl_matrix_delete, chi2_extract);
1785 cpl_table_new_column_array (wave_individual_table, data_x, CPL_TYPE_DOUBLE, nwave);
1786 cpl_table_set_array (wave_individual_table, data_x, 0, wave_individual_array);
1787 cpl_table_new_column_array (weight_individual_table, data_x, CPL_TYPE_DOUBLE, nwave);
1788 cpl_table_set_array (weight_individual_table, data_x, 0, weight_individual_array);
1789 cpl_table_new_column_array (wave_fitted_table, data_x, CPL_TYPE_DOUBLE, nwave);
1790 cpl_table_set_array (wave_fitted_table, data_x, 0, wave_individual_array);
1793 CPLCHECK_NUL (
"Cannot get individual wavelength for each pixel");
1795 FREE (cpl_array_delete ,wave_individual_array);
1796 FREE (cpl_array_delete ,weight_individual_array);
1797 FREE (cpl_array_delete ,wave_reference_array);
1798 FREE (cpl_matrix_delete ,data_flux_matrix);
1799 FREE (cpl_matrix_delete ,vis_to_flux_matrix);
1800 FREE (cpl_matrix_delete ,signal_matrix);
1801 FREE (cpl_matrix_delete ,residual_matrix);
1803 cpl_msg_info (cpl_func,
"Now fitting polynomials on wavelength channels");
1805 cpl_matrix * coef_to_wave = cpl_matrix_new (n_region / npol,5);
1806 cpl_matrix * coef_to_wave_weight = cpl_matrix_new (n_region / npol,n_region / npol);
1807 cpl_matrix * wavelength = cpl_matrix_new(n_region / npol,1);
1810 for (cpl_size region = 0 ; region < n_region/ npol; region ++)
1812 double mean_region = region - (n_region/npol-1)*0.5;
1813 cpl_matrix_set (coef_to_wave, region, 0, 1);
1814 cpl_matrix_set (coef_to_wave, region, 1, mean_region);
1815 cpl_matrix_set (coef_to_wave, region, 2, mean_region*mean_region);
1816 cpl_matrix_set (coef_to_wave, region, 3, mean_region*mean_region*mean_region);
1817 cpl_matrix_set (coef_to_wave, region, 4, mean_region*mean_region*mean_region*mean_region);
1820 for (
int pol = 0; pol < npol; pol++) {
1822 cpl_msg_info (cpl_func,
"Looping for polyfit now, with pol: %i",(
int) pol);
1824 for (cpl_size wave = 0; wave < nwave; wave ++) {
1827 for (cpl_size region = 0 ; region < n_region/ npol; region ++) {
1833 const cpl_array * wave_array = cpl_table_get_array (wave_individual_table, data_x, 0);
1834 const cpl_array * weight_array = cpl_table_get_array (weight_individual_table, data_x, 0);
1837 cpl_matrix_set (wavelength, region, 0, cpl_array_get(wave_array,wave,NULL));
1838 double weight_value=cpl_array_get(weight_array,wave,NULL);
1839 cpl_matrix_set (coef_to_wave_weight, region, region, weight_value*weight_value);
1844 cpl_matrix * coef_to_wave2 = cpl_matrix_product_create(coef_to_wave_weight,coef_to_wave);
1845 cpl_matrix * wavelength2 = cpl_matrix_product_create(coef_to_wave_weight,wavelength);
1848 cpl_matrix * coeff = cpl_matrix_solve_normal(coef_to_wave2, wavelength2);
1849 cpl_matrix * wavelength_fitted = cpl_matrix_product_create(coef_to_wave, coeff);
1851 CPLCHECK_NUL (
"Cannot do Matrix inversion to calculate optimum polynomial for wavelength");
1854 for (cpl_size region = 0 ; region < n_region/ npol; region ++) {
1858 cpl_array * wave_array = cpl_table_get_data_array (wave_fitted_table, data_x)[0];
1860 cpl_array_set_double(wave_array,wave,cpl_matrix_get(wavelength_fitted,region,0));
1864 FREE (cpl_matrix_delete ,coef_to_wave2);
1865 FREE (cpl_matrix_delete ,wavelength2);
1866 FREE (cpl_matrix_delete ,coeff);
1867 FREE (cpl_matrix_delete ,wavelength_fitted);
1871 FREE (cpl_matrix_delete ,coef_to_wave);
1872 FREE (cpl_matrix_delete ,coef_to_wave_weight);
1873 FREE (cpl_matrix_delete ,wavelength);
1875 CPLCHECK_NUL (
"Cannot fit individual wavelength with 3rd order polynomial");
1877 cpl_msg_info (cpl_func,
"Correcting for wavelength error");
1881 for (cpl_size region = 0 ; region < n_region; region ++)
1884 cpl_array * wavelength_fitted = cpl_table_get_data_array (wave_fitted_table, data_x)[0];
1885 cpl_size nwave_fitted = cpl_array_get_size (wavelength_fitted);
1886 for (cpl_size wave = 0 ; wave < nwave_fitted ; wave ++ ) {
1888 double result = cpl_array_get (wavelength_fitted, wave, NULL);
1890 cpl_array_set (wavelength_fitted, wave, result * (n0 + n1*d_met + n2*d_met*d_met));
1893 for (cpl_size wave = nwave_fitted/2 ; wave < nwave_fitted-1 ; wave ++ ) {
1894 double result = cpl_array_get (wavelength_fitted, wave, NULL);
1895 double result2 = cpl_array_get (wavelength_fitted, wave+1, NULL);
1896 if (result2<result+2e-10) {
1897 result2=result+2e-10;
1898 cpl_array_set (wavelength_fitted, wave+1, result2);
1901 for (cpl_size wave = nwave_fitted/2 ; wave > 0 ; wave -- ) {
1902 double result = cpl_array_get (wavelength_fitted, wave, NULL);
1903 double result2 = cpl_array_get (wavelength_fitted, wave-1, NULL);
1904 if (result2>result-2e-10) {
1905 result2=result-2e-10;
1906 cpl_array_set (wavelength_fitted, wave-1, result2);
1914 return wave_fitted_table;
2028 cpl_table * wavefibre_table,
2029 cpl_table * profile_table,
2030 cpl_table * detector_table)
2033 cpl_ensure (wavedata_table, CPL_ERROR_NULL_INPUT, NULL);
2034 cpl_ensure (wavefibre_table, CPL_ERROR_NULL_INPUT, NULL);
2035 cpl_ensure (detector_table, CPL_ERROR_NULL_INPUT, NULL);
2036 cpl_ensure (profile_table, CPL_ERROR_NULL_INPUT, NULL);
2041 cpl_size n_region = cpl_table_get_nrow (detector_table);
2042 int npol = (n_region > 24 ? 2 : 1);
2047 cpl_size sizex = cpl_table_get_column_dimension (profile_table,
"DATA1", 0);
2048 cpl_size sizey = cpl_table_get_column_dimension (profile_table,
"DATA1", 1);
2050 cpl_image * profilesum_image = cpl_image_new (sizex, sizey, CPL_TYPE_DOUBLE);
2051 cpl_image_fill_window (profilesum_image, 1, 1, sizex, sizey, 0.0);
2053 cpl_image * wave_image = cpl_image_new (sizex, sizey, CPL_TYPE_DOUBLE);
2054 cpl_image_fill_window (wave_image, 1, 1, sizex, sizey, 0.0);
2056 cpl_image * realwave_image = cpl_image_new (sizex, sizey, CPL_TYPE_DOUBLE);
2057 cpl_image_fill_window (realwave_image, 1, 1, sizex, sizey, 0.0);
2062 for (cpl_size region = 0 ; region < n_region; region ++) {
2066 cpl_image * profile_image = cpl_imagelist_get (profile_imglist, 0);
2071 cpl_image_add (profilesum_image, profile_image);
2076 const cpl_array * wavelength;
2077 wavelength = cpl_table_get_array (wavedata_table,
GRAVI_DATA[region], 0);
2080 for (cpl_size x = 0; x < sizex; x ++){
2081 for (cpl_size y = 0; y < sizey; y ++){
2082 if (cpl_image_get (profile_image, x+1, y+1, &nv) > 0.01)
2083 cpl_image_set (wave_image, x+1, y+1,
2084 cpl_array_get (wavelength, x, NULL));
2095 wavelength = cpl_table_get_array (wavefibre_table, name, 0);
2098 for (cpl_size x = 0; x < sizex; x ++){
2099 for (cpl_size y = 0; y < sizey; y ++){
2100 if (cpl_image_get (profile_image, x+1, y+1, &nv) > 0.01)
2101 cpl_image_set (realwave_image, x+1, y+1,
2102 cpl_array_get (wavelength, x, NULL));
2111 cpl_imagelist * testwave_imglist = cpl_imagelist_new ();
2112 cpl_imagelist_set (testwave_imglist, wave_image, 0);
2113 cpl_imagelist_set (testwave_imglist, profilesum_image, 1);
2114 cpl_imagelist_set (testwave_imglist, realwave_image, 2);
2117 return testwave_imglist;
2281 int type_data,
const cpl_parameterlist * parlist,
2285 cpl_ensure_code (wave_map, CPL_ERROR_NULL_INPUT);
2286 cpl_ensure_code (spectrum_data, CPL_ERROR_NULL_INPUT);
2288 CPL_ERROR_ILLEGAL_INPUT);
2296 cpl_propertylist_append (wave_header, raw_header);
2313 cpl_table * wavefibre_table;
2314 wavefibre_table =
gravi_wave_fibre (spectrum_table, detector_table, opd_table);
2323 double n0 = 1.0, n1 = -0.0165448, n2 = 0.00256002;
2324 cpl_msg_info (cpl_func,
"Rescale wavelengths with dispersion (%g,%g,%g)",n0,n1,n2);
2326 cpl_propertylist_update_string (wave_header,
"ESO QC WAVE_CORR",
"lbd*(N0+N1*(lbd-lbd0)/lbd0+N2*(lbd-lbd0)^2/lbd0^2)");
2345 cpl_table * wavedata_table;
2346 int spatial_order=2;
2347 int spectral_order=3;
2348 double rms_residuals;
2351 cpl_msg_info (cpl_func,
"Option force-waveFT-equal applied");
2362 fullstartx, spatial_order, spectral_order, &rms_residuals);
2367 double rms_fit=cpl_propertylist_get_double (raw_header,
QC_PHASECHI2);
2369 cpl_propertylist_set_comment (wave_header,
QC_CHI2WAVE(type_data),
"[nm]rms a.SC-b.FT+c=MET");
2380 char *wave_mode = cpl_strdup(cpl_parameter_get_string(
2381 cpl_parameterlist_find_const(parlist,
"gravity.calib.wave-mode")));
2383 for(
int i = 0; wave_mode[i]; i++)
2384 wave_mode[i] = toupper(wave_mode[i]);
2386 if (!strcmp(wave_mode,
"INDIVIDUAL")) {
2387 cpl_msg_info (cpl_func,
"Wave calibration using independent polynomial fit");
2388 cpl_table * wave_individual_table = cpl_table_new (1);
2389 cpl_table * weight_individual_table = cpl_table_new (1);
2390 cpl_table * wave_fitted_table = cpl_table_new (1);
2393 weight_individual_table,
2403 "WAVE_INDIV_SC", wave_individual_table);
2405 "WAVE_WEIGHT_SC", weight_individual_table);
2407 "WAVE_FITTED_SC", wavedata_table);
2413 }
else if (!strcmp(wave_mode,
"BANDPASS")) {
2414 cpl_msg_info (cpl_func,
"Wave calibration using bandpass");
2417 spectrum_table, detector_table, opd_table);
2422 "WAVE_FITTED_SC", wavedata_table);
2430 cpl_free(wave_mode);
2435 cpl_msg_info (cpl_func,
"Add WAVE_FIBRE and WAVE_DATA in wave_map");
2448 return CPL_ERROR_NONE;