30#include "cr2res_dfs.h"
31#include "cr2res_etalon.h"
32#include "cr2res_wave.h"
33#include "cr2res_pfits.h"
39#define SPEED_OF_LIGHT 299792.458
40#define modulo(x, y) ((x) - ((y) * trunc((x)/(y))))
41#define min(a,b) (((a)<(b))?(a):(b))
42#define max(a,b) (((a)>(b))?(a):(b))
44#define CR2RES_ETALON_GAP_H 9.9950e6
45#define CR2RES_ETALON_GAP_J 9.9900e6
46#define CR2RES_ETALON_GAP_K 9.9999e6
47#define CR2RES_ETALON_GAP_Y 9.9913e6
49#define CR2RES_ETALON_DEGREE_H 2
50#define CR2RES_ETALON_DEGREE_J 1
51#define CR2RES_ETALON_DEGREE_K 1
52#define CR2RES_ETALON_DEGREE_Y 2
59static cpl_mask * cr2res_etalon_binary_image(
const cpl_image *) ;
61static cpl_vector * cr2res_etalon_get_peaks_gaussian(
62 cpl_bivector * spectra,
63 cpl_bivector * spectra_err,
64 cpl_polynomial * wavesol_init,
65 cpl_array * wavesol_init_err,
69 cpl_vector ** heights,
70 cpl_vector ** fit_error);
87cpl_image * cr2res_etalon_computation(
const cpl_image * in)
92 cpl_apertures * aperts ;
95 if ((mask = cr2res_etalon_binary_image(in)) == NULL) {
96 cpl_msg_error(__func__,
"Cannot Binarise the image") ;
101 cpl_mask_save(mask,
"mask.fits", NULL, CPL_IO_CREATE) ;
104 if ((labels = cpl_image_labelise_mask_create(mask, &nlabels))==NULL) {
105 cpl_msg_error(cpl_func,
"Cannot Labelise") ;
106 cpl_mask_delete(mask) ;
109 cpl_mask_delete(mask) ;
111 cpl_msg_debug(__func__,
"Number of Apertures: %"CPL_SIZE_FORMAT, nlabels) ;
114 if ((aperts = cpl_apertures_new_from_image(in, labels)) == NULL) {
115 cpl_msg_error(cpl_func,
"Cannot Compute the apertures") ;
116 cpl_image_delete(labels) ;
121 cpl_apertures_dump(aperts, stdout) ;
124 cpl_apertures_delete(aperts) ;
137static cpl_mask * cr2res_etalon_binary_image(
const cpl_image * in)
140 cpl_vector * collapsed_vec ;
141 cpl_image * collapsed_im ;
142 cpl_vector * local_maxima ;
147 if (in == NULL)
return NULL;
153 collapsed_im = cpl_image_collapse_create(in, 0) ;
159 collapsed_vec = cpl_vector_new_from_image_row(collapsed_im, 1) ;
160 cpl_image_delete(collapsed_im) ;
163 cpl_plot_vector(NULL,
"w lines", NULL, collapsed_vec) ;
166 local_maxima = cr2res_etalon_get_maxpos(collapsed_vec) ;
167 pmax = cpl_vector_get_data(local_maxima) ;
168 cpl_vector_delete(collapsed_vec) ;
171 mask = cpl_mask_new(cpl_image_get_size_x(in), cpl_image_get_size_y(in)) ;
174 for (i = 0; i < cpl_vector_get_size(local_maxima); i++) {
175 cpl_image *blob_image;
178 int j, start_x, end_x;
182 end_x = cpl_image_get_size_x(in) ;
184 start_x = (int)(pmax[i-1] + (pmax[i]-pmax[i-1])/2.) ;
185 if (i<cpl_vector_get_size(local_maxima)-1)
186 end_x = (
int)(pmax[i] + (pmax[i+1]-pmax[i])/2.) ;
188 cpl_msg_debug(__func__,
"Extract %d -> %d", start_x, end_x) ;
191 blob_image = cpl_image_extract(in, start_x, 1, end_x,
192 cpl_image_get_size_y(in)) ;
196 threshold = cpl_image_get_mean(blob_image) ;
198 cpl_msg_debug(__func__,
"Threshold: %g", threshold) ;
201 blob_mask = cpl_mask_threshold_image_create(blob_image, threshold,
203 cpl_image_delete(blob_image);
206 for (j=0 ; j<cpl_mask_get_size_y(blob_mask) ; j++)
207 cpl_mask_set(blob_mask, 1, j+1, CPL_BINARY_0) ;
210 cpl_mask_copy(mask, blob_mask, start_x, 1);
212 cpl_mask_delete(blob_mask) ;
215 cpl_vector_delete(local_maxima) ;
228cpl_vector * cr2res_etalon_get_maxpos(
const cpl_vector * in)
231 cpl_vector * maxima_pos ;
236 if (in==NULL)
return NULL ;
239 pin = cpl_vector_get_data_const(in) ;
243 for (i=1 ; i<cpl_vector_get_size(in)-1 ; i++) {
244 if (pin[i] > pin[i+1] && pin[i] > pin[i-1]) nb_max++ ;
248 maxima_pos = cpl_vector_new(nb_max) ;
249 pmax = cpl_vector_get_data(maxima_pos) ;
251 for (i=1 ; i<cpl_vector_get_size(in)-1 ; i++) {
252 if (pin[i] > pin[i+1] && pin[i] > pin[i-1]) {
279 const cpl_vector * in,
280 cpl_vector ** left_edges,
281 cpl_vector ** right_edges){
308 cpl_vector * midpoints;
309 int m, i, i_ahead, i_max;
311 int width = cpl_vector_get_size(in);
314 midpoints = cpl_vector_new(width / 2);
315 *left_edges = cpl_vector_new(width / 2);
316 *right_edges = cpl_vector_new(width / 2);
323 if (cpl_vector_get(in, i - 1) < cpl_vector_get(in, i)){
327 while (i_ahead < i_max && cpl_vector_get(in, i_ahead) == cpl_vector_get(in, i)){
332 if (cpl_vector_get(in, i_ahead) < cpl_vector_get(in, i)){
333 cpl_vector_set(*left_edges, m, i);
334 cpl_vector_set(*right_edges, m, i_ahead - 1);
335 cpl_vector_set(midpoints, m, (i + i_ahead - 1) / 2);
345 cpl_msg_warning(__func__,
"Cannot find maxima");
346 cpl_vector_delete(midpoints);
347 cpl_vector_delete(*left_edges);
348 cpl_vector_delete(*right_edges);
352 cpl_vector_set_size(midpoints, m);
354 cpl_vector_set_size(*left_edges, m);
355 cpl_vector_set_size(*right_edges, m);
370 const cpl_vector * peak_heights,
398 cpl_vector * priority_to_position;
399 cpl_bivector * bivector_tmp;
400 int i, k, peaks_size, distance_;
402 peaks_size = cpl_vector_get_size(peaks);
404 distance_ = distance;
406 keep = cpl_vector_new(peaks_size);
407 cpl_vector_fill(keep, 1);
414 bivector_tmp = cpl_bivector_new(peaks_size);
415 priority_to_position = cpl_bivector_get_x(bivector_tmp);
417 for (i = 0; i < peaks_size; i++){
418 cpl_vector_set(priority_to_position, i, i);
420 cpl_vector_copy(cpl_bivector_get_y(bivector_tmp), peak_heights);
422 cpl_bivector_sort(bivector_tmp, bivector_tmp, CPL_SORT_ASCENDING, CPL_SORT_BY_Y);
426 for (i = peaks_size - 1; i> -1; i--){
430 j = cpl_vector_get(priority_to_position, i);
431 if (cpl_vector_get(keep, j) == 0){
438 while (0 <= k && cpl_vector_get(peaks, j) - cpl_vector_get(peaks,k) < distance_){
439 cpl_vector_set(keep, k, 0);
445 while (k < peaks_size && cpl_vector_get(peaks, k) - cpl_vector_get(peaks, j) < distance_){
446 cpl_vector_set(keep, k, 0);
450 cpl_bivector_delete(bivector_tmp);
467 const cpl_vector * in,
471 cpl_vector * right_edges;
472 cpl_vector * left_edges;
474 cpl_vector * peak_heights;
475 cpl_vector * peaks_out;
476 cpl_vector * peak_distance;
478 double peak, peak_height ;
483 if (peaks == NULL)
return NULL;
484 npeaks = cpl_vector_get_size(peaks);
486 peak_heights = cpl_vector_new(npeaks);
487 for (cpl_size i = 0; i < npeaks; i++)
489 peak = cpl_vector_get(peaks, i);
490 peak_height = cpl_vector_get(in, peak);
491 cpl_vector_set(peak_heights, i, peak_height);
495 peak_heights, distance);
498 peaks_out = cpl_vector_new(npeaks);
500 for (cpl_size i = 0; i < npeaks; i++)
502 peak = cpl_vector_get(peaks, i);
503 peak_height = cpl_vector_get(in, peak);
505 if ((peak_height > height) && (cpl_vector_get(peak_distance, i))){
506 cpl_vector_set(peaks_out, k, peak);
510 cpl_vector_set_size(peaks_out, k);
511 cpl_vector_delete(peaks);
512 cpl_vector_delete(left_edges);
513 cpl_vector_delete(right_edges);
514 cpl_vector_delete(peak_heights);
515 cpl_vector_delete(peak_distance);
520static cpl_vector * cr2res_etalon_get_peaks_gaussian(
521 cpl_bivector * spectra,
522 cpl_bivector * spectra_err,
523 cpl_polynomial * wavesol_init,
524 cpl_array * wavesol_init_err,
528 cpl_vector ** heights,
529 cpl_vector ** fit_error)
531 cpl_bivector * linelist;
534 cpl_vector * sigma_loc;
535 cpl_vector * heights_loc;
536 cpl_vector * fit_error_loc;
537 cpl_vector * wavelength;
538 cpl_vector * peak_height;
539 cpl_vector * new_peaks;
540 const cpl_vector * in;
543 in = cpl_bivector_get_y_const(spectra);
544 npeaks = cpl_vector_get_size(peaks);
545 linelist = cpl_bivector_new(npeaks);
547 wavelength = cpl_bivector_get_x(linelist);
548 peak_height = cpl_bivector_get_y(linelist);
549 for (j = 0; j < npeaks; j++)
552 wave = cpl_polynomial_eval_1d(wavesol_init,
553 cpl_vector_get(peaks, j), NULL);
554 height = cpl_vector_get(in, (cpl_size) cpl_vector_get(peaks, j));
555 cpl_vector_set(wavelength, j, wave);
556 cpl_vector_set(peak_height, j, height);
559 if (cr2res_wave_extract_lines(spectra, spectra_err, wavesol_init,
560 wavesol_init_err, linelist, 40, 4, display, &px, &py, &sigma_loc,
561 &heights_loc, &fit_error_loc) == -1)
564 cpl_msg_warning(__func__,
"No lines could be found");
565 cpl_bivector_delete(linelist);
570 npeaks = cpl_matrix_get_nrow(px);
571 new_peaks = cpl_vector_wrap(npeaks, cpl_matrix_get_data(px));
572 cpl_matrix_unwrap(px);
574 cpl_bivector_delete(linelist);
575 cpl_vector_delete(py);
577 if (sigma != NULL) *sigma = sigma_loc;
578 else cpl_vector_delete(sigma_loc);
579 if (heights != NULL) *heights = heights_loc;
580 else cpl_vector_delete(heights_loc);
581 if (fit_error_loc != NULL) *fit_error = fit_error_loc;
582 else cpl_vector_delete(fit_error_loc);
587#define signum(x) ((x > 0) ? 1 : ((x < 0) ? -1 : 0))
601 cpl_vector * tmp_vec;
603 for (j=0;j<ndata;j++) arr[j]=y[j]-b*x[j];
604 tmp_vec = cpl_vector_wrap(ndata, arr);
605 *a = cpl_vector_get_median(tmp_vec);
606 cpl_vector_unwrap(tmp_vec);
609 for (j=0;j<ndata;j++)
613 *abdev += *abdev + fabs(d);
616 if (fabs(d) > DBL_EPSILON)
617 sum += (d >= 0.0 ? x[j] : -x[j]);
624cpl_polynomial * cr2res_robust_polynomial_fit(cpl_matrix *px, cpl_vector *py)
633 double b1, del, f1, sigb;
634 double sx=0.0, sy=0.0, sxy=0.0, sxx=0.0, chisq=0.0;
637 cpl_polynomial * poly;
640 x = cpl_matrix_get_data(px);
641 y = cpl_vector_get_data(py);
642 ndata = cpl_vector_get_size(py);
649 for (j=0;j<ndata;j++)
656 del = ndata * sxx - sx * sx;
657 a = (sxx * sy - sx * sxy) / del;
658 b = (ndata * sxy - sx * sy) / del;
660 for (j = 0; j < ndata; j++){
662 temp = y[j] - (a + b * x[j]);
663 chisq += temp * temp;
665 sigb = sqrt(chisq / del);
669 f1 = rofunc(x, y, ndata, &a, &abdev, b1);
674 b2 = b + 3.0 * sigb * signum(f1);
675 f2 = rofunc(x, y, ndata, &a, &abdev, b2);
679 poly = cpl_polynomial_new(1);
681 cpl_polynomial_set_coeff(poly, °, a);
683 cpl_polynomial_set_coeff(poly, °, b);
687 while (f1 * f2 > 0.0)
689 b = b2 + 1.6 * (b2-b1);
693 f2 = rofunc(x, y, ndata, &a, &abdev, b2);
696 while (fabs(b2 - b1) > sigb)
699 b = b1 + 0.5 * (b2 - b1);
700 if (b == b1 || b == b2)
702 f=rofunc(x, y, ndata, &a, &abdev, b);
715 poly = cpl_polynomial_new(1);
717 cpl_polynomial_set_coeff(poly, °, a);
719 cpl_polynomial_set_coeff(poly, °, b);
742 cpl_bivector ** spectra,
743 cpl_bivector ** spectra_err,
744 cpl_polynomial ** wavesol_init,
745 cpl_array ** wavesol_init_err,
753 cpl_array ** wavelength_error,
754 cpl_table ** line_diagnostics)
756 const cpl_vector * in;
758 cpl_vector * peaks_new;
762 cpl_polynomial * poly;
767 cpl_vector ** heights;
768 cpl_vector ** sigmas;
769 cpl_vector ** fit_errors;
770 cpl_vector ** fpe_xobs;
771 cpl_vector ** fpe_wobs;
772 cpl_vector ** fpe_freq;
773 cpl_vector ** fpe_mord;
774 cpl_vector ** fpe_cord;
775 cpl_polynomial * result;
779 cpl_vector * tmp_vec;
781 cpl_size degree_2d[2];
782 cpl_size i, j, k, deg, npeaks, npeaks_total, npoints, setting_deg;
783 double wave, gap, tmp;
786 cpl_table * lines_diagnostics_loc;
791 if (spectra==NULL || spectra_err==NULL || wavesol_init==NULL ||
794 for (i=0 ; i<ninputs ; i++) {
795 if (spectra[i]==NULL || spectra_err[i]==NULL || wavesol_init[i]==NULL)
798 *wavelength_error = NULL;
802 tmp = cpl_polynomial_get_coeff(wavesol_init[0], °);
803 switch ((
int)(tmp/100))
808 gap = CR2RES_ETALON_GAP_Y;
809 setting_deg = CR2RES_ETALON_DEGREE_Y;
814 gap = CR2RES_ETALON_GAP_J;
815 setting_deg = CR2RES_ETALON_DEGREE_J;
820 gap = CR2RES_ETALON_GAP_H;
821 setting_deg = CR2RES_ETALON_DEGREE_H;
826 gap = CR2RES_ETALON_GAP_K;
827 setting_deg = CR2RES_ETALON_DEGREE_K;
836 fpe_xobs = cpl_malloc(ninputs *
sizeof(cpl_vector *));
837 fpe_wobs = cpl_malloc(ninputs *
sizeof(cpl_vector *));
838 fpe_freq = cpl_malloc(ninputs *
sizeof(cpl_vector *));
839 fpe_mord = cpl_malloc(ninputs *
sizeof(cpl_vector *));
840 fpe_cord = cpl_malloc(ninputs *
sizeof(cpl_vector *));
842 heights = cpl_malloc(ninputs *
sizeof(cpl_vector *));
843 sigmas = cpl_malloc(ninputs *
sizeof(cpl_vector *));
844 fit_errors = cpl_malloc(ninputs *
sizeof(cpl_vector *));
849 for (i = 0; i < ninputs; i++){
850 if (spectra[i] == NULL){
859 fit_errors[i] = NULL;
863 in = cpl_bivector_get_y_const(spectra[i]);
873 fit_errors[i] = NULL;
878 if ((peaks_new = cr2res_etalon_get_peaks_gaussian(spectra[i], spectra_err[i],
879 wavesol_init[i], wavesol_init_err[i], peaks, display,
880 &sigmas[i], &heights[i], &fit_errors[i])) == NULL){
881 cpl_vector_delete(peaks);
889 fit_errors[i] = NULL;
892 cpl_vector_delete(peaks);
893 npeaks = cpl_vector_get_size(peaks_new);
894 npeaks_total += npeaks;
922 freq = cpl_vector_new(npeaks);
923 wcen = cpl_vector_new(npeaks);
924 for ( j = 0; j < npeaks; j++)
926 wave = cpl_polynomial_eval_1d(wavesol_init[i],
927 cpl_vector_get(peaks_new, j), NULL);
928 cpl_vector_set(freq, j, SPEED_OF_LIGHT / wave);
929 cpl_vector_set(wcen, j, wave);
933 tmp_vec = cpl_vector_new(npeaks - 1);
934 for ( j = 0; j < npeaks - 1; j++)
936 cpl_vector_set(tmp_vec, j,
937 cpl_vector_get(freq, j + 1)
938 - cpl_vector_get(freq, j));
940 fr = fabs(cpl_vector_get_median(tmp_vec));
941 cpl_vector_delete(tmp_vec);
944 tmp_vec = cpl_vector_new(npeaks);
945 for (j = 0; j < npeaks; j++)
947 cpl_vector_set(tmp_vec, j,
948 modulo(cpl_vector_get(freq, j), fr));
950 f0 = cpl_vector_get_median(tmp_vec);
951 cpl_vector_delete(tmp_vec);
955 px = cpl_matrix_new(1, npeaks);
956 for (j = 0; j < npeaks; j++)
958 m = (cpl_vector_get(freq, j) - f0) / fr;
959 cpl_matrix_set(px, 0, j, round(m));
963 poly = cpl_polynomial_new(1);
964 cpl_polynomial_fit(poly, px, NULL, freq, NULL, CPL_FALSE, NULL, °);
966 for ( j = 0; j < npeaks; j++)
968 m = cpl_matrix_get(px, 0, j);
970 wave = cpl_polynomial_eval_1d(poly, m, NULL);
971 cpl_vector_set(freq, j, wave);
972 cpl_vector_set(wcen, j, SPEED_OF_LIGHT / wave);
978 cpl_polynomial_delete(poly);
980 mpos = cpl_vector_new(npeaks);
981 for ( j = 0; j < npeaks; j++)
985 m = cpl_matrix_get(px, 0, j);
986 cpl_vector_set(mpos, j, round(m));
992 cpl_matrix_delete(px);
995 tmp_vec = cpl_vector_new(npeaks);
996 for (j = 1; j < npeaks; j++){
997 m = cpl_vector_get(wcen, j-1)/
998 fabs(cpl_vector_get(wcen, j) - cpl_vector_get(wcen, j-1));
999 cpl_vector_set(tmp_vec, j, m - cpl_vector_get(mpos, j));
1001 offset = cpl_vector_get_median(tmp_vec);
1002 cpl_vector_add_scalar(mpos, round(offset));
1003 cpl_vector_delete(tmp_vec);
1006 fpe_xobs[i] = peaks_new;
1011 fpe_cord[i] = cpl_vector_new(npeaks);
1012 cpl_vector_fill(fpe_cord[i], orders[i] + zp_order);
1015 if (npeaks_total == 0){
1016 cpl_msg_error(__func__,
"No peaks found for Etalon wavecal");
1017 for (i = 0; i < ninputs; i++)
1019 if (fpe_mord[i] == NULL)
continue;
1020 cpl_vector_delete(fpe_xobs[i]);
1021 cpl_vector_delete(fpe_wobs[i]);
1022 cpl_vector_delete(fpe_freq[i]);
1023 cpl_vector_delete(fpe_mord[i]);
1024 cpl_vector_delete(fpe_cord[i]);
1025 cpl_vector_delete(heights[i]);
1026 cpl_vector_delete(sigmas[i]);
1027 cpl_vector_delete(fit_errors[i]);
1036 cpl_free(fit_errors);
1040 if (cpl_msg_get_level() == CPL_MSG_DEBUG){
1041 path = cpl_sprintf(
"debug_etalon_mord.fits");
1042 cpl_vector_save(fpe_mord[0], path, CPL_TYPE_DOUBLE, NULL, CPL_IO_CREATE);
1043 for (i = 1; i < ninputs; i++)
1045 cpl_vector_save(fpe_mord[i], path, CPL_TYPE_DOUBLE, NULL, CPL_IO_EXTEND);
1048 path = cpl_sprintf(
"debug_etalon_wobs.fits");
1049 cpl_vector_save(fpe_wobs[0], path, CPL_TYPE_DOUBLE, NULL, CPL_IO_CREATE);
1050 for (i = 1; i < ninputs; i++)
1052 cpl_vector_save(fpe_wobs[i], path, CPL_TYPE_DOUBLE, NULL, CPL_IO_EXTEND);
1065 cpl_vector * fpe_gap;
1067 fpe_gap = cpl_vector_new(npeaks_total);
1068 for (i = 0; i < ninputs; i++)
1070 if (fpe_mord[i] == NULL)
continue;
1071 for (j = 0; j < cpl_vector_get_size(fpe_mord[i]); j++)
1073 cpl_vector_set(fpe_gap, k,
1074 cpl_vector_get(fpe_mord[i], j)
1075 * cpl_vector_get(fpe_wobs[i], j));
1079 gap = cpl_vector_get_median(fpe_gap);
1080 cpl_vector_delete(fpe_gap);
1081 cpl_msg_debug(__func__,
"Median gap is: %g", gap);
1085 corr = cpl_vector_new(ninputs);
1086 for (i = 0; i < ninputs; i++)
1088 if (fpe_mord[i] == NULL)
continue;
1089 tmp_vec = cpl_vector_new(cpl_vector_get_size(fpe_mord[i]));
1090 for (j = 0; j < cpl_vector_get_size(fpe_mord[i]); j++)
1092 m = cpl_vector_get(fpe_mord[i], j);
1093 wave = cpl_vector_get(fpe_wobs[i], j);
1094 tmp = gap / wave - m;
1095 cpl_vector_set(tmp_vec, j, tmp);
1097 cpl_vector_set(corr, i, round(cpl_vector_get_median(tmp_vec)));
1098 cpl_vector_delete(tmp_vec);
1100 cpl_vector_add_scalar(fpe_mord[i], cpl_vector_get(corr, i));
1102 cpl_vector_delete(corr);
1107 pad = min(2, ninputs-2);
1108 for (i = pad; i < ninputs - pad; i++)
1110 if (fpe_mord[i] == NULL)
continue;
1111 npoints += cpl_vector_get_size(fpe_mord[i]);
1114 py = cpl_vector_new(npoints);
1115 px = cpl_matrix_new(1, npoints);
1117 for (i = pad; i < ninputs - pad; i++)
1119 if (fpe_mord[i] == NULL)
continue;
1120 for (j = 0; j < cpl_vector_get_size(fpe_mord[i]); j++)
1122 wave = cpl_vector_get(fpe_wobs[i], j);
1123 m = cpl_vector_get(fpe_mord[i], j);
1124 cpl_matrix_set(px, 0, k, m);
1125 cpl_vector_set(py, k, m * wave);
1129 poly = cpl_polynomial_new(1);
1131 cpl_polynomial_fit(poly, px, NULL, py, NULL, CPL_FALSE, NULL, °);
1132 cpl_matrix_delete(px);
1133 cpl_vector_delete(py);
1136 corr = cpl_vector_new(ninputs);
1137 for (i = 0; i < ninputs; i++)
1139 if (fpe_mord[i] == NULL)
continue;
1140 npeaks = cpl_vector_get_size(fpe_mord[i]);
1141 tmp_vec = cpl_vector_new(npeaks);
1142 for (j = 0; j < npeaks; j++)
1144 m = cpl_vector_get(fpe_mord[i], j);
1145 wave = cpl_vector_get(fpe_wobs[i], j);
1146 gap = cpl_polynomial_eval_1d(poly, m, NULL);
1147 tmp = gap / wave - m;
1148 cpl_vector_set(tmp_vec, j, tmp);
1150 cpl_vector_set(corr, i, round(cpl_vector_get_median(tmp_vec)));
1151 cpl_vector_delete(tmp_vec);
1153 cpl_vector_add_scalar(fpe_mord[i], cpl_vector_get(corr, i));
1155 cpl_vector_delete(corr);
1156 cpl_polynomial_delete(poly);
1162 py = cpl_vector_new(npeaks_total);
1163 px = cpl_matrix_new(1, npeaks_total);
1165 for (i = 0; i < ninputs; i++)
1167 if (fpe_mord[i] == NULL)
continue;
1168 for (j = 0; j < cpl_vector_get_size(fpe_mord[i]); j++)
1170 wave = cpl_vector_get(fpe_wobs[i], j);
1171 m = cpl_vector_get(fpe_mord[i], j);
1172 cpl_matrix_set(px, 0, k, m);
1173 cpl_vector_set(py, k, m * wave);
1178 if (setting_deg == 1){
1180 cpl_matrix * px_tmp;
1181 cpl_vector * py_tmp;
1183 double m0, ymax, ymin;
1188 px_tmp = cpl_matrix_duplicate(px);
1189 py_tmp = cpl_vector_duplicate(py);
1191 m0 = cpl_matrix_get_min(px_tmp);
1192 cpl_matrix_subtract_scalar(px_tmp, m0);
1193 ymin = cpl_vector_get_min(py_tmp);
1194 cpl_vector_subtract_scalar(py_tmp, ymin);
1195 ymax = cpl_vector_get_max(py_tmp);
1196 cpl_vector_divide_scalar(py_tmp, ymax);
1197 poly = cr2res_robust_polynomial_fit(px_tmp, py_tmp);
1199 cpl_matrix_delete(px_tmp);
1200 cpl_vector_delete(py_tmp);
1204 for (i = 0; i < ninputs; i++)
1207 if (fpe_mord[i] == NULL)
continue;
1210 for (j = 0; j < cpl_vector_get_size(fpe_mord[i]); j++)
1212 m = cpl_vector_get(fpe_mord[i], j);
1213 wave = cpl_vector_get(fpe_wobs[i], j);
1216 tmp1 /= cpl_vector_get_size(fpe_mord[i]);
1220 for (j = 0; j < cpl_vector_get_size(fpe_mord[i]); j++)
1222 m = cpl_vector_get(fpe_mord[i], j);
1224 tmp2 += cpl_polynomial_eval_1d(poly, m - m0, NULL) * ymax + ymin;
1226 tmp2 /= cpl_vector_get_size(fpe_mord[i]);
1228 cpl_msg_debug(__func__,
1229 "Difference between measured and expected in order %lli: %f",
1230 i, fabs(tmp1 - tmp2));
1232 for (j = 0; j < cpl_vector_get_size(fpe_mord[i]); j++)
1234 wave = cpl_vector_get(fpe_wobs[i], j);
1235 m = cpl_vector_get(fpe_mord[i], j);
1236 wave += (tmp2 - tmp1) / m;
1237 cpl_vector_set(py, k, m * wave);
1238 cpl_vector_set(fpe_wobs[i], j, wave);
1239 cpl_vector_set(fpe_freq[i], j, SPEED_OF_LIGHT / wave);
1243 cpl_polynomial_delete(poly);
1249 poly = cpl_polynomial_new(1);
1250 cpl_polynomial_fit(poly, px, NULL, py, NULL, CPL_FALSE, NULL, °);
1252 cpl_matrix_delete(px);
1253 cpl_vector_delete(py);
1255 for (i = 0; i < ninputs; i++)
1257 if (fpe_mord[i] == NULL)
continue;
1258 for (j = 0; j < cpl_vector_get_size(fpe_mord[i]); j++)
1260 m = cpl_vector_get(fpe_mord[i], j);
1261 wave = cpl_polynomial_eval_1d(poly, m, NULL) / m;
1262 cpl_vector_set(fpe_freq[i], j, SPEED_OF_LIGHT / wave);
1263 cpl_vector_set(fpe_wobs[i], j, wave);
1266 cpl_polynomial_delete(poly);
1270 pxa = cpl_vector_new(npeaks_total);
1271 pxb = cpl_vector_new(npeaks_total);
1272 py = cpl_vector_new(npeaks_total);
1274 for (i = 0; i < ninputs; i++)
1276 if (fpe_mord[i] == NULL)
continue;
1277 npeaks = cpl_vector_get_size(fpe_mord[i]);
1278 for (j = 0; j < npeaks; j++){
1279 cpl_vector_set(pxa, k, cpl_vector_get(fpe_xobs[i], j));
1280 cpl_vector_set(pxb, k, orders[i] + zp_order);
1281 cpl_vector_set(py, k, cpl_vector_get(fpe_wobs[i], j));
1286 degree_2d[0] = degree_x ;
1287 degree_2d[1] = degree_y ;
1288 result = cr2res_polyfit_2d(pxa, pxb, py, degree_2d);
1291 if (result == NULL){
1292 cpl_msg_error(__func__,
"Error in Etalon polynomial fit");
1294 cpl_vector_delete(pxa);
1295 cpl_vector_delete(pxb);
1296 cpl_vector_delete(py);
1297 for (i = 0; i < ninputs; i++)
1299 if (fpe_mord[i] == NULL)
continue;
1300 cpl_vector_delete(fpe_xobs[i]);
1301 cpl_vector_delete(fpe_wobs[i]);
1302 cpl_vector_delete(fpe_freq[i]);
1303 cpl_vector_delete(fpe_mord[i]);
1304 cpl_vector_delete(fpe_cord[i]);
1305 cpl_vector_delete(heights[i]);
1306 cpl_vector_delete(sigmas[i]);
1307 cpl_vector_delete(fit_errors[i]);
1316 cpl_free(fit_errors);
1320 if (cpl_msg_get_level() == CPL_MSG_DEBUG){
1321 cpl_table * tmp_table;
1322 path = cpl_sprintf(
"debug_etalon_final_mord.fits");
1323 cpl_vector_save(fpe_mord[0], path, CPL_TYPE_DOUBLE, NULL, CPL_IO_CREATE);
1324 for (i = 1; i < ninputs; i++)
1326 cpl_vector_save(fpe_mord[i], path, CPL_TYPE_DOUBLE, NULL, CPL_IO_EXTEND);
1329 path = cpl_sprintf(
"debug_etalon_final_wobs.fits");
1330 cpl_vector_save(fpe_wobs[0], path, CPL_TYPE_DOUBLE, NULL, CPL_IO_CREATE);
1331 for (i = 1; i < ninputs; i++)
1333 cpl_vector_save(fpe_wobs[i], path, CPL_TYPE_DOUBLE, NULL, CPL_IO_EXTEND);
1336 path = cpl_sprintf(
"debug_etalon_final_xobs.fits");
1337 cpl_vector_save(fpe_xobs[0], path, CPL_TYPE_DOUBLE, NULL, CPL_IO_CREATE);
1338 for (i = 1; i < ninputs; i++)
1340 cpl_vector_save(fpe_xobs[i], path, CPL_TYPE_DOUBLE, NULL, CPL_IO_EXTEND);
1343 path = cpl_sprintf(
"debug_etalon_final_cord.fits");
1344 cpl_vector_save(fpe_cord[0], path, CPL_TYPE_DOUBLE, NULL, CPL_IO_CREATE);
1345 for (i = 1; i < ninputs; i++)
1347 cpl_vector_save(fpe_cord[i], path, CPL_TYPE_DOUBLE, NULL, CPL_IO_EXTEND);
1351 tmp_table = cpl_table_new((degree_x + 1) * (degree_y + 1));
1352 cpl_table_new_column(tmp_table,
"DEGREE_X", CPL_TYPE_INT);
1353 cpl_table_new_column(tmp_table,
"DEGREE_Y", CPL_TYPE_INT);
1354 cpl_table_new_column(tmp_table,
"COEFFICIENT", CPL_TYPE_DOUBLE);
1356 for (i = 0; i <= degree_x; i++)
1358 for (j = 0; j <= degree_y; j++)
1362 tmp = cpl_polynomial_get_coeff(result, °ree_2d[0]);
1363 cpl_table_set_int(tmp_table,
"DEGREE_X", k, i);
1364 cpl_table_set_int(tmp_table,
"DEGREE_Y", k, j);
1365 cpl_table_set_double(tmp_table,
"COEFFICIENT", k, tmp);
1369 path = cpl_sprintf(
"debug_etalon_final_poly.fits");
1370 cpl_table_save(tmp_table, NULL, NULL, path, CPL_IO_CREATE);
1371 cpl_table_delete(tmp_table);
1376 if (line_diagnostics != NULL) {
1377 *line_diagnostics = NULL;
1378 cpl_msg_debug(__func__,
"Number of lines: %"CPL_SIZE_FORMAT, npeaks_total);
1379 for (i = 0; i < ninputs; i++)
1381 cpl_polynomial * wavesol_loc;
1382 if (fpe_mord[i] == NULL)
continue;
1383 npeaks = cpl_vector_get_size(fpe_mord[i]);
1385 lines_diagnostics_loc =
1388 orders[i] + zp_order);
1390 for (j=0 ; j < npeaks ; j++) {
1391 double pix_pos, lambda_cat, lambda_meas, line_width, line_intens, fit_error;
1392 pix_pos = cpl_vector_get(fpe_xobs[i], j);
1393 lambda_cat = cpl_vector_get(fpe_wobs[i], j) ;
1394 lambda_meas = cpl_polynomial_eval_1d(wavesol_loc, pix_pos,
1396 line_width = cpl_vector_get(sigmas[i], j) ;
1397 line_intens = cpl_vector_get(heights[i], j) ;
1398 fit_error = cpl_vector_get(fit_errors[i], j) ;
1399 m = cpl_vector_get(fpe_mord[i], j);
1400 cpl_table_set_int(lines_diagnostics_loc,
1401 CR2RES_COL_ORDER, j, orders[i]) ;
1402 cpl_table_set_int(lines_diagnostics_loc,
1403 CR2RES_COL_TRACENB, j, traces_nb[i]) ;
1404 cpl_table_set_double(lines_diagnostics_loc,
1405 CR2RES_COL_MEASURED_LAMBDA, j, lambda_meas) ;
1406 cpl_table_set_double(lines_diagnostics_loc,
1407 CR2RES_COL_CATALOG_LAMBDA, j, lambda_cat);
1408 cpl_table_set_double(lines_diagnostics_loc,
1409 CR2RES_COL_DELTA_LAMBDA, j, lambda_cat-lambda_meas);
1410 cpl_table_set_double(lines_diagnostics_loc,
1411 CR2RES_COL_MEASURED_PIXEL, j, pix_pos);
1412 cpl_table_set_double(lines_diagnostics_loc,
1413 CR2RES_COL_LINE_WIDTH, j, line_width) ;
1414 cpl_table_set_double(lines_diagnostics_loc,
1415 CR2RES_COL_FIT_QUALITY, j, fit_error) ;
1416 cpl_table_set_double(lines_diagnostics_loc,
1417 CR2RES_COL_INTENSITY, j, line_intens) ;
1418 cpl_table_set_double(lines_diagnostics_loc,
1419 CR2RES_COL_FPET_M, j, m) ;
1421 cpl_polynomial_delete(wavesol_loc);
1423 if (*line_diagnostics == NULL) {
1424 *line_diagnostics = lines_diagnostics_loc ;
1425 lines_diagnostics_loc = NULL ;
1426 }
else if (lines_diagnostics_loc != NULL) {
1428 cpl_table_insert(*line_diagnostics, lines_diagnostics_loc,
1429 cpl_table_get_nrow(*line_diagnostics)) ;
1430 cpl_table_delete(lines_diagnostics_loc) ;
1434 cpl_msg_debug(__func__,
"%s",cpl_error_get_where());
1435 npeaks = cpl_vector_get_size(py);
1439 diff = cpl_vector_new(npeaks);
1440 pos = cpl_vector_new(2);
1441 for (i = 0; i < npeaks; i++){
1442 cpl_vector_set(pos, 0, cpl_vector_get(pxa, i));
1443 cpl_vector_set(pos, 1, cpl_vector_get(pxb, i));
1444 cpl_vector_set(diff, i, fabs(
1445 cpl_polynomial_eval(result, pos)
1446 - cpl_vector_get(py, i)));
1449 if (*wavelength_error == NULL)
1450 *wavelength_error = cpl_array_new(2, CPL_TYPE_DOUBLE);
1451 cpl_array_set_double(*wavelength_error, 0,
1452 cpl_vector_get_mean(diff));
1453 cpl_array_set_double(*wavelength_error, 1,
1454 cpl_vector_get_max(diff));
1456 cpl_vector_delete(diff);
1457 cpl_vector_delete(pos);
1459 cpl_vector_delete(pxa);
1460 cpl_vector_delete(pxb);
1461 cpl_vector_delete(py);
1463 for (i = 0; i < ninputs; i++)
1465 if (fpe_mord[i] == NULL)
continue;
1466 cpl_vector_delete(fpe_xobs[i]);
1467 cpl_vector_delete(fpe_wobs[i]);
1468 cpl_vector_delete(fpe_freq[i]);
1469 cpl_vector_delete(fpe_mord[i]);
1470 cpl_vector_delete(fpe_cord[i]);
1471 cpl_vector_delete(heights[i]);
1472 cpl_vector_delete(sigmas[i]);
1473 cpl_vector_delete(fit_errors[i]);
1482 cpl_free(fit_errors);
cpl_table * cr2res_dfs_create_lines_diagnostics_table(int nrows)
Create an empty LINES DIAGNOSTICS table.
cpl_polynomial * cr2res_etalon_wave_2d(cpl_bivector **spectra, cpl_bivector **spectra_err, cpl_polynomial **wavesol_init, cpl_array **wavesol_init_err, int *orders, int *traces_nb, int ninputs, cpl_size degree_x, cpl_size degree_y, int zp_order, int display, cpl_array **wavelength_error, cpl_table **line_diagnostics)
Create the 2d wavecal fit using etalon peaks.
cpl_vector * cr2res_etalon_find_peaks(const cpl_vector *in, double height, double distance)
Detect peaks from a 1d periodic signal and store their positions.
cpl_vector * cr2res_etalon_get_local_maxima(const cpl_vector *in, cpl_vector **left_edges, cpl_vector **right_edges)
Find local maxima in a 1D array. This function finds all local maxima in a 1D array and returns the i...
cpl_vector * cr2res_etalon_select_by_peak_distance(const cpl_vector *peaks, const cpl_vector *peak_heights, float distance)
Selects the highest peaks that are atleast distance pixel apart.
cpl_polynomial * cr2res_wave_poly_2d_to_1d(cpl_polynomial *poly_2d, int order)
Create a 1D Wavelength Polynomial out of a 2D one.