32#include "cr2res_dfs.h"
33#include "cr2res_trace.h"
34#include "cr2res_pfits.h"
36#include "cr2res_wave.h"
37#include "cr2res_utils.h"
42#define min(a,b) (((a)<(b))?(a):(b))
43#define any(arr, f) ({ \
45 for (cpl_size i = 0; i < cpl_array_get_size(arr); i++) \
47 isError = f(cpl_array_get(arr, i, NULL));\
63static int cr2res_trace_new_trace(
64 const cpl_array * slit_fraction_in,
65 const cpl_array ** trace_in,
67 const cpl_array * slit_fraction_wished,
68 cpl_array ** trace_all_new,
69 cpl_array ** trace_upper_new,
70 cpl_array ** trace_lower_new) ;
71static int cr2res_trace_check_slit_fraction(
const cpl_array * slit_fraction) ;
72static cpl_array * cr2res_trace_get_slit_frac(
73 const cpl_table * traces,
75 cr2res_decker decker_pos) ;
76static cpl_mask * cr2res_trace_signal_detect(
77 const cpl_image * image,
81static cpl_table * cr2res_trace_fit_traces(
82 cpl_table * clustertable,
84static cpl_array * cr2res_trace_fit_trace(
87static cpl_table * cr2res_trace_restore_edge_traces(
88 cpl_table * trace_table) ;
89static cpl_table * cr2res_trace_convert_labels_to_cluster(cpl_image * labels) ;
90static cpl_mask * cr2res_trace_clean_blobs(
93static int cr2res_trace_extract_edges(
94 cpl_table * pixels_table,
95 cpl_table ** edge_lower_table,
96 cpl_table ** edge_upper_table) ;
97static int cr2res_trace_get_subtrace(
98 cpl_table * trace_wave,
107static int cr2res_trace_filter_keep(
108 const char * setting,
110static double cr2res_trace_calculate_pixel_shift(
116 cpl_polynomial * poly_lower,
117 cpl_polynomial * poly_all,
118 cpl_polynomial * poly_upper,
119 cpl_polynomial * poly_a,
120 cpl_polynomial * poly_b,
121 cpl_polynomial * poly_c,
125 double * pix_shift_y);
173 cpl_mask * mask_clean ;
175 cpl_table * clustertable ;
176 cpl_table * trace_table ;
177 cpl_table * restored_trace_table ;
181 if (ima == NULL)
return NULL ;
184 cpl_msg_info(__func__,
"Detect the signal") ;
185 if ((mask = cr2res_trace_signal_detect(ima, smooth_x, smooth_y,
186 threshold)) == NULL) {
187 cpl_msg_error(__func__,
"Detection failed") ;
191 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
192 if (cpl_mask_save(mask,
"debug_mask_before_cleaning.fits", NULL,
193 CPL_IO_CREATE) != CPL_ERROR_NONE)
197 cpl_msg_info(__func__,
"Traces cleaning") ;
199 cpl_msg_error(__func__,
"Cannot clean the traces") ;
200 cpl_mask_delete(mask) ;
203 cpl_mask_delete(mask) ;
206 cpl_msg_info(__func__,
"Labelise the traces") ;
207 if ((labels=cpl_image_labelise_mask_create(mask_clean, &nlabels)) == NULL) {
208 cpl_msg_error(__func__,
"Cannot labelise") ;
209 cpl_mask_delete(mask_clean);
213 cpl_msg_error(__func__,
"Found no labels");
214 cpl_image_delete(labels);
215 cpl_mask_delete(mask_clean);
218 cpl_mask_delete(mask_clean);
221 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
222 if (cpl_image_get_max(labels) != 0){
223 cpl_apertures * aperts ;
224 aperts = cpl_apertures_new_from_image(ima, labels);
225 cpl_apertures_dump(aperts, stdout) ;
226 cpl_apertures_delete(aperts) ;
228 cpl_msg_debug(__func__,
"No labels found, can not create aperture");
233 clustertable = cr2res_trace_convert_labels_to_cluster(labels) ;
236 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
237 if (cpl_image_save(labels,
"debug_labels.fits",
238 CPL_TYPE_INT, NULL, CPL_IO_CREATE) != CPL_ERROR_NONE)
240 if (cpl_table_save(clustertable, NULL, NULL,
"debug_cluster_table.fits",
241 CPL_IO_CREATE) != CPL_ERROR_NONE)
244 cpl_image_delete(labels) ;
247 cpl_msg_info(__func__,
"Fit the trace edges") ;
248 if ((trace_table = cr2res_trace_fit_traces(clustertable, degree)) == NULL) {
249 cpl_msg_error(__func__,
"Failed to Fit") ;
250 cpl_table_delete(clustertable);
255 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
256 if (cpl_table_save(trace_table, NULL, NULL,
257 "debug_trace_table.fits", CPL_IO_CREATE) != CPL_ERROR_NONE)
262 cpl_msg_info(__func__,
"Restore the trace edges") ;
263 if ((restored_trace_table = cr2res_trace_restore_edge_traces(
264 trace_table)) == NULL) {
265 cpl_msg_error(__func__,
"Failed to Restore the edge traces") ;
266 cpl_table_delete(clustertable);
267 cpl_table_delete(trace_table);
270 cpl_table_delete(trace_table);
271 cpl_table_delete(clustertable);
274 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
275 if (cpl_table_save(restored_trace_table, NULL, NULL,
276 "debug_restored_trace_table.fits", CPL_IO_CREATE)
280 return restored_trace_table ;
297 cpl_mask * new_mask ;
298 cpl_mask * clean_mask ;
301 if (mask == NULL)
return NULL ;
302 if ((opening != 0) & (opening != 1))
return NULL;
307 cpl_mask * mask_kernel ;
308 cpl_mask * diff_mask ;
310 cpl_msg_info(__func__,
"Apply Opening to cleanup the traces") ;
311 mask_kernel = cpl_mask_new(5, 1) ;
312 cpl_mask_not(mask_kernel);
313 new_mask = cpl_mask_duplicate(mask) ;
314 cpl_mask_filter(new_mask, mask, mask_kernel, CPL_FILTER_OPENING,
316 cpl_mask_delete(mask_kernel) ;
319 diff_mask = cpl_mask_duplicate(mask) ;
320 cpl_mask_xor(diff_mask, new_mask) ;
321 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
322 if (cpl_mask_save(diff_mask,
"debug_diff_mask.fits", NULL,
323 CPL_IO_CREATE) != CPL_ERROR_NONE)
326 cpl_mask_delete(diff_mask) ;
328 new_mask = cpl_mask_duplicate(mask) ;
332 cpl_msg_info(__func__,
"Remove the small blobs (<= %d pixels)",
334 if ((clean_mask = cr2res_trace_clean_blobs(new_mask, min_cluster)) == NULL){
335 cpl_msg_error(__func__,
"Cannot clean the blobs") ;
336 cpl_mask_delete(new_mask) ;
339 cpl_mask_delete(new_mask) ;
342 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
343 if (cpl_mask_save(clean_mask,
"debug_mask.fits",
344 NULL, CPL_IO_CREATE) != CPL_ERROR_NONE)
370 cpl_size j, k, y_pos_lower, y_pos_upper ;
373 if (trace == NULL)
return NULL ;
374 if (nx < 1 || ny < 1)
return NULL ;
377 out = cpl_image_new(nx, ny, CPL_TYPE_INT) ;
378 cpl_image_add_scalar(out, -1.0) ;
379 pout = cpl_image_get_data_int(out) ;
382 for (i=0 ; i<cpl_table_get_nrow(trace) ; i++) {
384 const cpl_array * coeffs_upper ;
385 const cpl_array * coeffs_lower ;
386 cpl_polynomial * poly_upper ;
387 cpl_polynomial * poly_lower ;
389 if (cpl_table_has_column(trace, CR2RES_COL_ORDER))
390 order_idx = cpl_table_get(trace, CR2RES_COL_ORDER, i, NULL) ;
395 coeffs_upper = cpl_table_get_array(trace, CR2RES_COL_UPPER, i) ;
399 coeffs_lower = cpl_table_get_array(trace, CR2RES_COL_LOWER, i) ;
403 for (j=0 ; j<nx ; j++) {
404 y_pos_lower = (cpl_size)cpl_polynomial_eval_1d(poly_lower,
406 y_pos_upper = (cpl_size)cpl_polynomial_eval_1d(poly_upper,
408 for (k = y_pos_lower-1 ; k < y_pos_upper ; k++)
410 pout[j+k*nx] = order_idx ;
413 cpl_polynomial_delete(poly_upper) ;
414 cpl_polynomial_delete(poly_lower) ;
432 const cpl_table * trace,
433 int * nb_order_idx_values)
435 const int * porder_idx_values ;
436 int nrows, count_order_idx_values;
442 if (trace == NULL || nb_order_idx_values == NULL)
return NULL ;
445 nrows = cpl_table_get_nrow(trace) ;
446 porder_idx_values = cpl_table_get_data_int_const(trace, CR2RES_COL_ORDER);
449 tmp_out = cpl_malloc(nrows *
sizeof(
int)) ;
452 count_order_idx_values = 0 ;
453 for (i=0 ; i<nrows ; i++) {
457 for (j=0 ; j<count_order_idx_values ; j++)
458 if (tmp_out[j] == porder_idx_values[i])
463 tmp_out[count_order_idx_values] = porder_idx_values[i] ;
464 count_order_idx_values ++ ;
469 out = cpl_malloc(count_order_idx_values *
sizeof(
int)) ;
470 for (i=0 ; i<count_order_idx_values ; i++) out[i] = tmp_out[i] ;
474 *nb_order_idx_values = count_order_idx_values ;
487 const cpl_table * trace_wave,
490 cpl_size nrows, i, count ;
493 if (trace_wave == NULL)
return -1 ;
497 nrows = cpl_table_get_nrow(trace_wave) ;
500 for (i=0 ; i<nrows ; i++)
501 if (cpl_table_get(trace_wave, CR2RES_COL_ORDER, i, NULL)==order_idx) {
518 const cpl_table * trace_wave,
522 cpl_size nrows, i, k;
526 if (trace_wave == NULL)
return NULL ;
529 if (number_traces == -1)
return NULL ;
534 nrows = cpl_table_get_nrow(trace_wave) ;
535 traces = cpl_malloc(number_traces *
sizeof(
int));
538 for (i=0 ; i<nrows ; i++)
539 if (cpl_table_get(trace_wave, CR2RES_COL_ORDER, i, NULL)==order_idx) {
540 traces[k] = cpl_table_get(trace_wave, CR2RES_COL_TRACENB, i, NULL);
544 if (nb_traces != NULL) *nb_traces = number_traces;
546 if (k != number_traces){
547 cpl_msg_warning(__func__,
"Not all expected traces found");
561cpl_size cr2res_get_nb_traces_with_wavelength(
562 const cpl_table * trace_wave,
565 cpl_size nrows, i, count ;
568 if (trace_wave == NULL)
return -1 ;
572 nrows = cpl_table_get_nrow(trace_wave) ;
575 for (i=0 ; i<nrows ; i++) {
576 const cpl_array * wave_array ;
577 wave_array = cpl_table_get_array(trace_wave, CR2RES_COL_WAVELENGTH, i) ;
578 if (cpl_table_get(trace_wave, CR2RES_COL_ORDER, i, NULL) == order_idx
579 && wave_array != NULL) count ++ ;
593 const cpl_table * trace_wave1,
594 const cpl_table * trace_wave2)
597 int * order_idx_values ;
598 int norder_idx_values, j;
602 if (trace_wave1 == NULL || trace_wave2 == NULL)
return NULL ;
603 nrows = cpl_table_get_nrow(trace_wave1) ;
606 merged = cpl_table_duplicate(trace_wave1) ;
609 if (cpl_table_insert(merged, trace_wave2, nrows) != CPL_ERROR_NONE) {
610 cpl_msg_error(__func__,
"Failed merging the tables") ;
611 cpl_table_delete(merged) ;
616 nrows = cpl_table_get_nrow(merged) ;
620 &norder_idx_values) ;
624 for (j=0 ; j<norder_idx_values ; j++) {
630 for (i=0 ; i<nrows ; i++) {
632 if (cpl_table_get(merged, CR2RES_COL_ORDER, i,
633 NULL)==order_idx_values[j]) {
634 cpl_table_set(merged, CR2RES_COL_TRACENB, i, cur_trace_id);
639 cpl_free(order_idx_values) ;
653 const cpl_table * trace_wave,
660 if (trace_wave == NULL)
return -1 ;
663 nrows = cpl_table_get_nrow(trace_wave) ;
666 for (i=0 ; i<nrows ; i++) {
667 if (cpl_table_get(trace_wave, CR2RES_COL_ORDER,i,NULL)==order_idx &&
668 cpl_table_get(trace_wave, CR2RES_COL_TRACENB,i,NULL)==trace_nb)
686 const cpl_table * trace_wave,
687 const char * poly_column,
691 const cpl_array * wave_arr ;
692 cpl_polynomial * wave_poly ;
696 if (trace_wave == NULL)
return NULL ;
697 if (strcmp(poly_column, CR2RES_COL_WAVELENGTH) &&
698 strcmp(poly_column, CR2RES_COL_UPPER) &&
699 strcmp(poly_column, CR2RES_COL_LOWER) &&
700 strcmp(poly_column, CR2RES_COL_ALL) &&
701 strcmp(poly_column, CR2RES_COL_SLIT_CURV_A) &&
702 strcmp(poly_column, CR2RES_COL_SLIT_CURV_B) &&
703 strcmp(poly_column, CR2RES_COL_SLIT_CURV_C))
return NULL ;
707 if (index == -1)
return NULL;
710 wave_arr = cpl_table_get_array(trace_wave, poly_column, index) ;
711 if (wave_arr == NULL)
return NULL ;
731 const cpl_table * trace_wave,
737 cpl_polynomial * wl_poly;
740 if (trace_wave == NULL || size < 1)
return NULL ;
744 order_idx, trace_nb) ;
745 if (wl_poly == NULL)
return NULL ;
748 out = cpl_vector_new(size) ;
749 if (cpl_vector_fill_polynomial(out, wl_poly, 1, 1) != CPL_ERROR_NONE) {
750 cpl_vector_delete(out);
751 cpl_polynomial_delete(wl_poly);
754 cpl_polynomial_delete(wl_poly);
770 const cpl_table * trace,
776 cpl_polynomial * pos_poly;
778 if (trace == NULL || size < 1)
return NULL ;
782 order_idx, trace_nb) ;
783 if (pos_poly == NULL)
return NULL ;
786 out = cpl_vector_new(size) ;
787 if (cpl_vector_fill_polynomial(out, pos_poly, 1, 1) != CPL_ERROR_NONE) {
788 cpl_vector_delete(out);
789 cpl_polynomial_delete(pos_poly);
792 cpl_polynomial_delete(pos_poly);
806 const cpl_table * trace,
811 cpl_polynomial * poly_upper ;
812 cpl_polynomial * poly_lower ;
815 if (trace == NULL)
return -1 ;
819 order_idx, trace_nb);
821 order_idx, trace_nb);
822 if (poly_upper == NULL || poly_lower == NULL)
return -1;
826 CR2RES_DETECTOR_SIZE);
828 cpl_polynomial_delete(poly_upper);
829 cpl_polynomial_delete(poly_lower);
832 cpl_msg_warning(__func__,
"Computed height unreasonably large");
852 cpl_polynomial * trace1,
853 cpl_polynomial * trace2,
857 cpl_polynomial * tmp;
859 if (trace1 == NULL || trace2 == NULL || vector_size < 1){
863 out = cpl_vector_new(vector_size) ;
864 tmp = cpl_polynomial_new(1);
865 cpl_polynomial_add(tmp, trace1, trace2);
866 cpl_polynomial_multiply_scalar(tmp, tmp, 0.5);
868 cpl_vector_fill_polynomial(out, tmp, 1, 1);
869 cpl_polynomial_delete(tmp);
887 cpl_polynomial * trace1,
888 cpl_polynomial * trace2,
891 cpl_polynomial * diff_poly;
892 cpl_vector * diff_vec ;
896 if (trace1 == NULL || trace2 == NULL || vector_size < 1)
return -1 ;
898 diff_poly = cpl_polynomial_new(1);
899 diff_vec = cpl_vector_new(vector_size);
900 cpl_polynomial_subtract(diff_poly, trace1, trace2);
901 cpl_vector_fill_polynomial(diff_vec, diff_poly, 1, 1);
902 height = (int)ceil(fabs( cpl_vector_get_mean(diff_vec) ));
903 cpl_polynomial_delete(diff_poly) ;
905 if (cpl_vector_get_stdev(diff_vec) > 10){
906 cpl_msg_warning(__func__,
"Stdev of extraction height is large: %.1f",
907 cpl_vector_get_stdev(diff_vec));
909 cpl_vector_delete(diff_vec) ;
911 cpl_msg_debug(__func__,
"Computed height is %d pix.", height);
924 const cpl_table * traces,
927 const cpl_array * coeffs ;
928 cpl_polynomial * poly ;
932 if (traces == NULL)
return -1.0 ;
933 if (idx < 0)
return -1.0 ;
934 if (idx >= cpl_table_get_nrow(traces))
return -1.0 ;
937 coeffs = cpl_table_get_array(traces, CR2RES_COL_ALL, idx) ;
941 ypos = cpl_polynomial_eval_1d(poly, CR2RES_DETECTOR_SIZE / 2, NULL) ;
942 cpl_polynomial_delete(poly) ;
977 cpl_propertylist * ext_plist ;
978 cpl_propertylist * main_plist ;
979 int * order_idx_values ;
980 cpl_array * array_id ;
981 cpl_array * array_zero ;
982 cpl_array * array_neg ;
983 cr2res_decker decker_pos ;
984 int order_idx, nb_order_idx_values,
987 if (traces == NULL)
return -1;
990 main_plist = cpl_propertylist_load(infile, 0) ;
991 ext_plist = cpl_propertylist_load(infile,
993 if (ext_plist == NULL || main_plist == 0) {
995 cpl_propertylist_delete(main_plist);
996 cpl_propertylist_delete(ext_plist);
1002 cpl_propertylist_delete(main_plist) ;
1005 cpl_table_new_column(traces, CR2RES_COL_ORDER, CPL_TYPE_INT) ;
1008 for (i=0 ; i<cpl_table_get_nrow(traces) ; i++) {
1017 cpl_table_set(traces, CR2RES_COL_ORDER, i, order_idx);
1019 cpl_propertylist_delete(ext_plist) ;
1022 cpl_table_new_column(traces, CR2RES_COL_TRACENB, CPL_TYPE_INT);
1025 &nb_order_idx_values) ;
1026 for (i=0 ; i<nb_order_idx_values ; i++) {
1031 for (j=0 ; j<cpl_table_get_nrow(traces) ; j++) {
1032 if (cpl_table_get(traces, CR2RES_COL_ORDER, j, NULL) ==
1033 order_idx_values[i]) {
1034 cpl_table_set(traces, CR2RES_COL_TRACENB, j, trace_nb);
1039 cpl_free(order_idx_values) ;
1042 cpl_table_new_column_array(traces, CR2RES_COL_WAVELENGTH,
1043 CPL_TYPE_DOUBLE, 3) ;
1044 cpl_table_new_column_array(traces, CR2RES_COL_WAVELENGTH_ERROR,
1045 CPL_TYPE_DOUBLE, 2) ;
1048 for (i=0 ; i<cpl_table_get_nrow(traces) ; i++) {
1049 cpl_array * wl_array ;
1051 order_idx = cpl_table_get(traces, CR2RES_COL_ORDER, i, NULL) ;
1055 order_idx)) == NULL) {
1056 cpl_msg_warning(__func__,
1057 "No Wavelength estimate for Detector %d / order_idx %d",
1058 det_nr, order_idx) ;
1060 cpl_table_set_array(traces, CR2RES_COL_WAVELENGTH, i, NULL);
1061 cpl_table_set_array(traces, CR2RES_COL_WAVELENGTH_ERROR, i, NULL);
1064 cpl_table_set_array(traces, CR2RES_COL_WAVELENGTH, i, wl_array);
1065 cpl_array_delete(wl_array) ;
1067 wl_array = cpl_array_new(2, CPL_TYPE_DOUBLE) ;
1068 cpl_array_set(wl_array, 0, CR2RES_WAVELENGTH_ERROR_DEFAULT) ;
1069 cpl_array_set(wl_array, 1, CR2RES_WAVELENGTH_ERROR_DEFAULT) ;
1070 cpl_table_set_array(traces, CR2RES_COL_WAVELENGTH_ERROR,i,wl_array);
1071 cpl_array_delete(wl_array) ;
1081 cpl_table_new_column_array(traces,CR2RES_COL_SLIT_CURV_A,CPL_TYPE_DOUBLE,3);
1082 cpl_table_new_column_array(traces,CR2RES_COL_SLIT_CURV_B,CPL_TYPE_DOUBLE,3);
1083 cpl_table_new_column_array(traces,CR2RES_COL_SLIT_CURV_C,CPL_TYPE_DOUBLE,3);
1084 array_id = cpl_array_new(3, CPL_TYPE_DOUBLE) ;
1085 cpl_array_set(array_id, 0, 0.0) ;
1086 cpl_array_set(array_id, 1, 1.0) ;
1087 cpl_array_set(array_id, 2, 0.0) ;
1088 array_zero = cpl_array_new(3, CPL_TYPE_DOUBLE) ;
1089 cpl_array_set(array_zero, 0, 0.0) ;
1090 cpl_array_set(array_zero, 1, 0.0) ;
1091 cpl_array_set(array_zero, 2, 0.0) ;
1094 for (i=0 ; i<cpl_table_get_nrow(traces) ; i++) {
1095 cpl_table_set_array(traces, CR2RES_COL_SLIT_CURV_A, i, array_id);
1096 cpl_table_set_array(traces, CR2RES_COL_SLIT_CURV_B, i, array_zero);
1097 cpl_table_set_array(traces, CR2RES_COL_SLIT_CURV_C, i, array_zero);
1099 cpl_array_delete(array_id) ;
1100 cpl_array_delete(array_zero) ;
1105 cpl_table_new_column_array(traces,CR2RES_COL_SLIT_FRACTION,
1107 array_neg = cpl_array_new(3, CPL_TYPE_DOUBLE) ;
1108 cpl_array_set(array_neg, 0, -1.0) ;
1109 cpl_array_set(array_neg, 1, -1.0) ;
1110 cpl_array_set(array_neg, 2, -1.0) ;
1111 for (i=0 ; i<cpl_table_get_nrow(traces) ; i++) {
1112 cpl_array * slit_frac ;
1114 slit_frac = cr2res_trace_get_slit_frac(traces, i, decker_pos) ;
1115 if (slit_frac == NULL) {
1116 cpl_table_set_array(traces, CR2RES_COL_SLIT_FRACTION, i, array_neg);
1117 cpl_msg_warning(__func__,
"Cannot assign slit fraction.");
1119 cpl_table_set_array(traces, CR2RES_COL_SLIT_FRACTION, i, slit_frac);
1120 cpl_array_delete(slit_frac) ;
1123 cpl_array_delete(array_neg) ;
1153 const cpl_table * traces,
1154 const cpl_array * new_slit_fraction)
1157 const cpl_array * slit_frac_old;
1158 const cpl_array * trace_all_old ;
1159 const cpl_array * trace_upper_old ;
1160 const cpl_array * trace_lower_old ;
1161 const cpl_array ** trace_old;
1162 cpl_array * trace_all_new ;
1163 cpl_array * trace_upper_new ;
1164 cpl_array * trace_lower_new ;
1166 const cpl_array * const_wave ;
1167 const cpl_array * const_wave_err;
1168 cpl_array * wave_err ;
1169 cpl_array * slit_curv_a ;
1170 cpl_array * slit_curv_b ;
1171 cpl_array * slit_curv_c ;
1172 const cpl_array * const_slit_curv_a;
1173 const cpl_array * const_slit_curv_b;
1174 const cpl_array * const_slit_curv_c;
1175 cpl_polynomial * poly_lower;
1176 cpl_polynomial * poly_all;
1177 cpl_polynomial * poly_upper;
1178 cpl_polynomial * poly_a ;
1179 cpl_polynomial * poly_b ;
1180 cpl_polynomial * poly_c ;
1181 cpl_matrix * samppos;
1185 cpl_size i, j, k, m, n, nrows, degree ;
1186 int nb_order_idx_values, nb_traces;
1187 int * order_idx_values;
1189 double sf_lower, sf_upper, sf_all, sf_new;
1190 double pix_shift_x, pix_shift_y;
1193 if (traces == NULL || new_slit_fraction == NULL)
return NULL ;
1195 cpl_msg_error(__func__,
"The traces table is incomplete") ;
1198 if (cpl_array_get_size(new_slit_fraction) != 3){
1199 cpl_msg_error(__func__,
1200 "New slitfraction must have 3 components (Upper, Middle, Lower)");
1207 &nb_order_idx_values);
1208 out = cpl_table_new(nb_order_idx_values);
1209 cpl_table_copy_structure(out, traces);
1210 cpl_table_select_all(out);
1213 for (i=0 ; i<nb_order_idx_values; i++) {
1215 cpl_array * slit_frac_old_trace ;
1216 int * trace_numbers;
1219 trace_old = cpl_malloc(nb_traces * 3 *
sizeof(cpl_array*));
1220 for (j = 0; j < nb_traces * 3; j++) trace_old[j] = NULL;
1221 slit_frac_old_trace = cpl_array_new(nb_traces * 3, CPL_TYPE_DOUBLE);
1223 for(j = m = 0; j < nb_traces; j++, m++) {
1227 slit_frac_old = cpl_table_get_array(traces,
1228 CR2RES_COL_SLIT_FRACTION, k) ;
1229 trace_all_old = cpl_table_get_array(traces, CR2RES_COL_ALL, k) ;
1230 trace_upper_old = cpl_table_get_array(traces, CR2RES_COL_UPPER, k) ;
1231 trace_lower_old = cpl_table_get_array(traces, CR2RES_COL_LOWER, k) ;
1235 if (cpl_table_is_selected(out, i) == 0 ||
1236 cr2res_trace_check_slit_fraction(slit_frac_old) != 1 ||
1237 trace_upper_old == NULL || trace_lower_old == NULL ||
1238 trace_all_old == NULL) {
1239 cpl_table_unselect_row(out, i) ;
1243 trace_old[3 * m + 0] = trace_lower_old;
1244 trace_old[3 * m + 1] = trace_all_old;
1245 trace_old[3 * m + 2] = trace_upper_old;
1246 cpl_array_set(slit_frac_old_trace, 3 * m + 0, cpl_array_get(slit_frac_old, 0, NULL));
1247 cpl_array_set(slit_frac_old_trace, 3 * m + 1, cpl_array_get(slit_frac_old, 1, NULL));
1248 cpl_array_set(slit_frac_old_trace, 3 * m + 2, cpl_array_get(slit_frac_old, 2, NULL));
1252 cpl_msg_error(__func__,
1253 "No valid traces found for order %i", order_idx_values[i]) ;
1254 cpl_array_delete(slit_frac_old_trace);
1255 cpl_free(trace_numbers);
1256 cpl_free(trace_old);
1260 trace_old = cpl_realloc(trace_old, m * 3 *
sizeof(cpl_array*));
1261 cpl_array_set_size(slit_frac_old_trace, m * 3);
1264 cpl_table_set_array(out, CR2RES_COL_SLIT_FRACTION, i,new_slit_fraction);
1265 cpl_table_set_int(out, CR2RES_COL_ORDER, i, order_idx_values[i]);
1266 cpl_table_set_int(out, CR2RES_COL_TRACENB, i, 1);
1269 if (cr2res_trace_new_trace(slit_frac_old_trace, trace_old, nb_traces,
1270 new_slit_fraction, &trace_all_new, &trace_upper_new,
1271 &trace_lower_new) == -1) {
1272 cpl_msg_error(__func__,
1273 "Cannot compute the new trace for order %i",
1274 order_idx_values[i]) ;
1275 cpl_free(trace_old);
1276 cpl_free(trace_numbers);
1277 cpl_array_delete(slit_frac_old_trace);
1280 cpl_array_delete(slit_frac_old_trace);
1283 cpl_table_set_array(out, CR2RES_COL_ALL, i, trace_all_new);
1284 cpl_table_set_array(out, CR2RES_COL_UPPER, i, trace_upper_new);
1285 cpl_table_set_array(out, CR2RES_COL_LOWER, i, trace_lower_new);
1286 cpl_array_delete(trace_all_new) ;
1287 cpl_array_delete(trace_upper_new) ;
1288 cpl_array_delete(trace_lower_new) ;
1294 const_wave = cpl_table_get_array(traces, CR2RES_COL_WAVELENGTH, k) ;
1295 const_wave_err = cpl_table_get_array(traces, CR2RES_COL_WAVELENGTH_ERROR, k) ;
1297 const_slit_curv_a = cpl_table_get_array(traces, CR2RES_COL_SLIT_CURV_A,
1299 const_slit_curv_b = cpl_table_get_array(traces, CR2RES_COL_SLIT_CURV_B,
1301 const_slit_curv_c = cpl_table_get_array(traces, CR2RES_COL_SLIT_CURV_C,
1307 slit_frac_old = cpl_table_get_array(traces, CR2RES_COL_SLIT_FRACTION,k);
1308 trace_lower_old = trace_old[0];
1309 trace_all_old = trace_old[1];
1310 trace_upper_old = trace_old[2];
1316 sf_lower = cpl_array_get_double(slit_frac_old, 0, NULL);
1317 sf_all = cpl_array_get_double(slit_frac_old, 1, NULL);
1318 sf_upper = cpl_array_get_double(slit_frac_old, 2, NULL);
1319 sf_new = cpl_array_get_double(new_slit_fraction, 1, NULL);
1320 cpl_msg_debug(__func__,
"New Slitfunction %f", sf_new);
1327 samppos = cpl_matrix_new(1, CR2RES_DETECTOR_SIZE);
1328 a_vec = cpl_vector_new(CR2RES_DETECTOR_SIZE);
1329 b_vec = cpl_vector_new(CR2RES_DETECTOR_SIZE);
1330 c_vec = cpl_vector_new(CR2RES_DETECTOR_SIZE);
1332 for (n = 0; n < CR2RES_DETECTOR_SIZE; n++)
1334 pix_shift_x = cr2res_trace_calculate_pixel_shift(n, sf_lower,
1335 sf_all, sf_upper, sf_new, poly_lower, poly_all,
1336 poly_upper, poly_a, poly_b, poly_c, &a, &b, &c, &pix_shift_y);
1339 cpl_matrix_set(samppos, 0, n, n + 1 - pix_shift_x);
1341 cpl_vector_set(a_vec, n, a);
1342 cpl_vector_set(b_vec, n, b);
1343 cpl_vector_set(c_vec, n, c);
1346 cpl_polynomial_delete(poly_lower);
1347 cpl_polynomial_delete(poly_all);
1348 cpl_polynomial_delete(poly_upper);
1350 degree = cpl_polynomial_get_degree(poly_a);
1351 cpl_polynomial_fit(poly_a, samppos, NULL, a_vec, NULL,
1352 CPL_FALSE, NULL, °ree);
1354 degree = cpl_polynomial_get_degree(poly_b);
1355 cpl_polynomial_fit(poly_b, samppos, NULL, b_vec, NULL,
1356 CPL_FALSE, NULL, °ree);
1358 degree = cpl_polynomial_get_degree(poly_c);
1359 cpl_polynomial_fit(poly_c, samppos, NULL, c_vec, NULL,
1360 CPL_FALSE, NULL, °ree);
1362 if (cpl_error_get_code() != CPL_ERROR_NONE){
1363 cpl_msg_error(__func__,
1364 "Could not calculate the new trace polynomial. %s",
1365 cpl_error_get_message());
1368 cpl_polynomial_delete(poly_a);
1369 cpl_polynomial_delete(poly_b);
1370 cpl_polynomial_delete(poly_c);
1371 cpl_free(trace_numbers);
1372 cpl_free(trace_old);
1373 cpl_matrix_delete(samppos);
1374 cpl_vector_delete(a_vec);
1375 cpl_vector_delete(b_vec);
1376 cpl_vector_delete(c_vec);
1380 cpl_matrix_delete(samppos);
1381 cpl_vector_delete(a_vec);
1382 cpl_vector_delete(b_vec);
1383 cpl_vector_delete(c_vec);
1386 cpl_array_get_size(const_slit_curv_a));
1388 cpl_array_get_size(const_slit_curv_b));
1390 cpl_array_get_size(const_slit_curv_c));
1392 cpl_polynomial_delete(poly_a);
1393 cpl_polynomial_delete(poly_b);
1394 cpl_polynomial_delete(poly_c);
1398 wave = cpl_array_duplicate(const_wave);
1399 wave_err = cpl_array_duplicate(const_wave_err);
1400 cpl_table_set_array(out, CR2RES_COL_WAVELENGTH, i, wave);
1401 cpl_table_set_array(out, CR2RES_COL_WAVELENGTH_ERROR, i, wave_err);
1402 cpl_array_delete(wave) ;
1403 cpl_array_delete(wave_err) ;
1407 cpl_table_set_array(out, CR2RES_COL_SLIT_CURV_A, i, slit_curv_a);
1408 cpl_table_set_array(out, CR2RES_COL_SLIT_CURV_B, i, slit_curv_b);
1409 cpl_table_set_array(out, CR2RES_COL_SLIT_CURV_C, i, slit_curv_c);
1410 cpl_array_delete(slit_curv_a) ;
1411 cpl_array_delete(slit_curv_b) ;
1412 cpl_array_delete(slit_curv_c) ;
1414 cpl_free(trace_numbers);
1415 cpl_free(trace_old);
1417 cpl_free(order_idx_values);
1420 cpl_table_not_selected(out) ;
1421 cpl_table_erase_selected(out) ;
1424 if (cpl_table_get_nrow(out) == 0) {
1425 cpl_table_delete(out) ;
1428 cpl_table_not_selected(out) ;
1431 nrows = cpl_table_get_nrow(out);
1432 for (k = 0; k < nrows; k++)
1434 int order, trace_id;
1435 order = cpl_table_get_int(out, CR2RES_COL_ORDER, k, NULL);
1436 trace_id = cpl_table_get_int(out, CR2RES_COL_TRACENB, k, NULL);
1437 out = cr2res_trace_shift_wavelength(out, 0.5, order, trace_id);
1443static double cr2res_trace_calculate_pixel_shift(
1449 cpl_polynomial * poly_lower,
1450 cpl_polynomial * poly_all,
1451 cpl_polynomial * poly_upper,
1452 cpl_polynomial * poly_a,
1453 cpl_polynomial * poly_b,
1454 cpl_polynomial * poly_c,
1458 double * pix_shift_y)
1460 double pix_lower, pix_upper, pix_all;
1463 pix_lower = cpl_polynomial_eval_1d(poly_lower, n + 1, NULL);
1464 pix_upper = cpl_polynomial_eval_1d(poly_upper, n + 1, NULL);
1465 pix_all = cpl_polynomial_eval_1d(poly_all, n + 1, NULL);
1467 *a = cpl_polynomial_eval_1d(poly_a, n + 1, NULL);
1468 *b = cpl_polynomial_eval_1d(poly_b, n + 1, NULL);
1469 *c = cpl_polynomial_eval_1d(poly_c, n + 1, NULL);
1474 *b += 2 * (*c) * pix_all;
1477 *pix_shift_y = (pix_upper - pix_lower) /
1478 (sf_upper - sf_lower) * (sf_all - sf_new);
1480 pix_shift_x = *a + (*c * (*pix_shift_y) + *b) * (*pix_shift_y);
1484 *b -= 2 * (*c) * (*pix_shift_y + pix_all);
1489cpl_table * cr2res_trace_shift_wavelength(
1491 double old_slit_fraction,
1495 cpl_vector * wave_vec;
1496 cpl_polynomial * poly_wave;
1498 cpl_matrix * samppos;
1499 const cpl_array * const_wave;
1500 const cpl_array * slit_frac_old;
1501 const cpl_array * trace_all_old;
1502 const cpl_array * trace_lower_old;
1503 const cpl_array * trace_upper_old;
1504 const cpl_array * const_slit_curv_a;
1505 const cpl_array * const_slit_curv_b;
1506 const cpl_array * const_slit_curv_c;
1507 cpl_polynomial * poly_lower;
1508 cpl_polynomial * poly_all;
1509 cpl_polynomial * poly_upper;
1510 cpl_polynomial * poly_a;
1511 cpl_polynomial * poly_b;
1512 cpl_polynomial * poly_c;
1517 double sf_lower, sf_all, sf_upper, sf_new;
1522 const_wave = cpl_table_get_array(traces, CR2RES_COL_WAVELENGTH, k) ;
1523 if (isnan(cpl_array_get(const_wave,0,NULL))) {
1524 cpl_msg_warning(__func__,
1525 "Invalid input wavelength in order %d, trace %d",
1532 slit_frac_old = cpl_table_get_array(traces,
1533 CR2RES_COL_SLIT_FRACTION, k);
1534 trace_all_old = cpl_table_get_array(traces, CR2RES_COL_ALL, k) ;
1535 trace_upper_old = cpl_table_get_array(traces, CR2RES_COL_UPPER, k) ;
1536 trace_lower_old = cpl_table_get_array(traces, CR2RES_COL_LOWER, k) ;
1537 const_slit_curv_a = cpl_table_get_array(traces,
1538 CR2RES_COL_SLIT_CURV_A, k) ;
1539 const_slit_curv_b = cpl_table_get_array(traces,
1540 CR2RES_COL_SLIT_CURV_B, k) ;
1541 const_slit_curv_c = cpl_table_get_array(traces,
1542 CR2RES_COL_SLIT_CURV_C, k) ;
1550 sf_lower = cpl_array_get_double(slit_frac_old, 0, NULL);
1551 sf_new = cpl_array_get_double(slit_frac_old, 1, NULL);
1552 sf_upper = cpl_array_get_double(slit_frac_old, 2, NULL);
1553 sf_all = old_slit_fraction;
1560 wave_vec = cpl_vector_new(CR2RES_DETECTOR_SIZE);
1561 samppos = cpl_matrix_new(1, CR2RES_DETECTOR_SIZE);
1564 for (n = 0; n < CR2RES_DETECTOR_SIZE; n++)
1567 cpl_vector_set(wave_vec, n,
1568 cpl_polynomial_eval_1d(poly_wave, n + 1, NULL));
1570 pix_shift_x = cr2res_trace_calculate_pixel_shift(n, sf_lower,
1571 sf_all, sf_upper, sf_new, poly_lower, poly_all,
1572 poly_upper, poly_a, poly_b, poly_c, &a, &b, &c,
1575 cpl_matrix_set(samppos, 0, n, n + 1 - pix_shift_x);
1578 cpl_polynomial_delete(poly_a);
1579 cpl_polynomial_delete(poly_b);
1580 cpl_polynomial_delete(poly_c);
1581 cpl_polynomial_delete(poly_lower);
1582 cpl_polynomial_delete(poly_all);
1583 cpl_polynomial_delete(poly_upper);
1585 degree = cpl_polynomial_get_degree(poly_wave);
1586 cpl_polynomial_fit(poly_wave, samppos, NULL, wave_vec, NULL,
1587 CPL_FALSE, NULL, °ree);
1589 if (cpl_error_get_code() != CPL_ERROR_NONE){
1590 cpl_msg_error(__func__,
1591 "Could not calculate the new wavelength polynomial. %s. %s",
1592 cpl_error_get_message(), cpl_error_get_where());
1594 cpl_vector_delete(wave_vec);
1595 cpl_polynomial_delete(poly_wave);
1596 cpl_matrix_delete(samppos);
1601 cpl_array_get_size(const_wave));
1603 cpl_table_set_array(traces, CR2RES_COL_WAVELENGTH, k, wave);
1605 cpl_vector_delete(wave_vec);
1606 cpl_polynomial_delete(poly_wave);
1607 cpl_array_delete(wave);
1608 cpl_matrix_delete(samppos);
1622cpl_table * cr2res_trace_adjust(
1623 const cpl_table * trace_wave,
1624 const cpl_frameset * flat_raw,
1627 hdrl_imagelist * imlist ;
1628 hdrl_image * collapsed ;
1629 cpl_image * contrib ;
1630 cpl_table * new_traces ;
1631 const char * first_file ;
1632 cpl_table * corrected_traces ;
1633 int trace_opening, trace_degree,
1634 trace_min_cluster, trace_smooth_x, trace_smooth_y ;
1635 double trace_threshold, traces_shift ;
1638 if (trace_wave == NULL || flat_raw == NULL ||
1639 det_nr < 1 || det_nr > CR2RES_NB_DETECTORS)
1643 trace_smooth_x = 200 ;
1644 trace_smooth_y = 11 ;
1645 trace_threshold = 5.0 ;
1648 trace_min_cluster = 10000 ;
1652 if (imlist == NULL) {
1653 cpl_msg_error(__func__,
"Failed to load the RAW flat frames") ;
1658 cpl_msg_info(__func__,
"Collapse the input images") ;
1661 cpl_msg_error(__func__,
"Failed to Collapse") ;
1663 cpl_msg_indent_less() ;
1667 cpl_image_delete(contrib) ;
1670 cpl_msg_info(__func__,
"Compute the traces") ;
1672 trace_smooth_x, trace_smooth_y, trace_threshold,
1673 trace_opening, trace_degree, trace_min_cluster)) == NULL) {
1674 cpl_msg_error(__func__,
"Failed compute the traces") ;
1676 cpl_msg_indent_less() ;
1682 first_file = cpl_frame_get_filename(
1683 cpl_frameset_get_position_const(flat_raw, 0)) ;
1687 cpl_msg_info(__func__,
"Compute the Shift between 2 traces tables") ;
1688 traces_shift = cr2res_trace_compute_shift(trace_wave, new_traces) ;
1689 cpl_table_delete(new_traces) ;
1692 corrected_traces = cpl_table_duplicate(trace_wave) ;
1693 cpl_msg_error(__func__,
"Apply correction shift of %g pixels",
1695 cr2res_trace_apply_shift(corrected_traces, traces_shift) ;
1698 return corrected_traces ;
1711 const cpl_array * slit_frac,
1715 cr2res_decker decker_pos ;
1718 if (up_or_down != NULL) *up_or_down=-1 ;
1721 if (slit_frac == NULL)
return CR2RES_DECKER_INVALID ;
1724 down = cpl_array_get(slit_frac, 0, NULL) ;
1726 up = cpl_array_get(slit_frac, 2, NULL) ;
1727 if (cpl_error_get_code())
return CR2RES_DECKER_INVALID ;
1729 if ((fabs(down-0.0)<1e-3) && (fabs(up-1.0)<1e-3)) {
1730 decker_pos = CR2RES_DECKER_NONE ;
1731 if (up_or_down != NULL) *up_or_down=0 ;
1732 }
else if ((fabs(down-0.750)<1e-3) && (fabs(up-1.000)<1e-3)) {
1733 decker_pos = CR2RES_DECKER_1_3 ;
1734 if (up_or_down != NULL) *up_or_down=1 ;
1735 }
else if ((fabs(down-0.250)<1e-3) && (fabs(up-0.500)<1e-3)) {
1736 decker_pos = CR2RES_DECKER_1_3 ;
1737 if (up_or_down != NULL) *up_or_down=2 ;
1738 }
else if ((fabs(down-0.500)<1e-3) && (fabs(up-0.750)<1e-3)) {
1739 decker_pos = CR2RES_DECKER_2_4 ;
1740 if (up_or_down != NULL) *up_or_down=1 ;
1741 }
else if ((fabs(down-0.000)<1e-3) && (fabs(up-0.250)<1e-3)) {
1742 decker_pos = CR2RES_DECKER_2_4 ;
1743 if (up_or_down != NULL) *up_or_down=2 ;
1745 decker_pos = CR2RES_DECKER_INVALID ;
1746 if (up_or_down != NULL) *up_or_down=-1 ;
1761 cr2res_decker decker_position,
1764 cpl_array * slit_frac ;
1767 if (decker_position != CR2RES_DECKER_NONE &&
1768 decker_position != CR2RES_DECKER_1_3 &&
1769 decker_position != CR2RES_DECKER_2_4)
1771 if (up_or_down != 0 && up_or_down != 1 && up_or_down != 2)
1775 slit_frac = cpl_array_new(3, CPL_TYPE_DOUBLE) ;
1777 if (decker_position == CR2RES_DECKER_NONE) {
1779 cpl_array_set(slit_frac, 0, 0.0) ;
1780 cpl_array_set(slit_frac, 1, 0.5) ;
1781 cpl_array_set(slit_frac, 2, 1.0) ;
1782 }
else if (decker_position == CR2RES_DECKER_1_3) {
1784 if (up_or_down == 1) {
1786 cpl_array_set(slit_frac, 0, 0.750) ;
1787 cpl_array_set(slit_frac, 1, 0.875) ;
1788 cpl_array_set(slit_frac, 2, 1.000) ;
1789 }
else if (up_or_down == 2) {
1791 cpl_array_set(slit_frac, 0, 0.250) ;
1792 cpl_array_set(slit_frac, 1, 0.375) ;
1793 cpl_array_set(slit_frac, 2, 0.500) ;
1795 cpl_array_delete(slit_frac) ;
1798 }
else if (decker_position == CR2RES_DECKER_2_4) {
1800 if (up_or_down == 1) {
1802 cpl_array_set(slit_frac, 0, 0.500) ;
1803 cpl_array_set(slit_frac, 1, 0.625) ;
1804 cpl_array_set(slit_frac, 2, 0.750) ;
1805 }
else if (up_or_down == 2) {
1807 cpl_array_set(slit_frac, 0, 0.000) ;
1808 cpl_array_set(slit_frac, 1, 0.125) ;
1809 cpl_array_set(slit_frac, 2, 0.250) ;
1811 cpl_array_delete(slit_frac) ;
1835 cpl_table * trace_wave,
1839 cpl_table * sub_trace_wave ;
1840 cpl_size i, j, k, table_index;
1841 cpl_array * bottom, *center, *top, *
fraction, *wave ;
1842 const cpl_array * wave_err, *slit_a, *slit_b, *slit_c;
1843 double height = 1. / (nb_subtraces * 2.);
1846 int nb_order_idx_values, nb_traces, size_new_tw,
1848 int * order_idx_values,
1851 if (trace_wave == NULL || nb_subtraces <= 0)
return NULL ;
1854 &nb_order_idx_values);
1857 if (order_idx == -100)
1858 size_new_tw = nb_subtraces * nb_order_idx_values;
1860 size_new_tw = nb_subtraces;
1861 sub_trace_wave = cpl_table_new(size_new_tw);
1862 cpl_table_copy_structure(sub_trace_wave, trace_wave);
1866 for (j = 0; j < nb_order_idx_values; j++){
1869 if (order_idx == -100) ord = order_idx_values[j];
1870 else if (order_idx != order_idx_values[j])
continue;
1875 wave_err = cpl_table_get_array(trace_wave, CR2RES_COL_WAVELENGTH_ERROR,
1877 slit_a = cpl_table_get_array(trace_wave, CR2RES_COL_SLIT_CURV_A, i);
1878 slit_b = cpl_table_get_array(trace_wave, CR2RES_COL_SLIT_CURV_B, i);
1879 slit_c = cpl_table_get_array(trace_wave, CR2RES_COL_SLIT_CURV_C, i);
1882 for (i = 0; i < nb_subtraces; i++){
1884 pos = height + 2 * height * i;
1885 ndegree = cpl_table_get_column_dimension(trace_wave, CR2RES_COL_ALL,
1887 bottom = cpl_array_new(ndegree, CPL_TYPE_DOUBLE);
1888 top = cpl_array_new(ndegree, CPL_TYPE_DOUBLE);
1889 center = cpl_array_new(ndegree, CPL_TYPE_DOUBLE);
1890 fraction = cpl_array_new(3, CPL_TYPE_DOUBLE);
1891 ndegree = cpl_table_get_column_dimension(trace_wave,
1892 CR2RES_COL_WAVELENGTH, 0);
1893 wave = cpl_array_new(ndegree, CPL_TYPE_DOUBLE);
1895 res = cr2res_trace_get_subtrace(trace_wave, pos, height, ord,
1899 cpl_array_delete(bottom);
1900 cpl_array_delete(center);
1901 cpl_array_delete(top);
1903 cpl_array_delete(wave);
1908 cpl_table_set_int(sub_trace_wave, CR2RES_COL_ORDER, table_index,
1911 cpl_table_set_int(sub_trace_wave, CR2RES_COL_TRACENB, table_index,
1915 cpl_table_set_array(sub_trace_wave, CR2RES_COL_ALL, table_index,
1917 cpl_table_set_array(sub_trace_wave, CR2RES_COL_LOWER, table_index,
1919 cpl_table_set_array(sub_trace_wave, CR2RES_COL_UPPER, table_index,
1921 cpl_table_set_array(sub_trace_wave, CR2RES_COL_SLIT_FRACTION,
1923 cpl_table_set_array(sub_trace_wave, CR2RES_COL_WAVELENGTH,
1927 cpl_table_set_array(sub_trace_wave, CR2RES_COL_WAVELENGTH_ERROR,
1928 table_index, wave_err);
1931 cpl_table_set_array(sub_trace_wave, CR2RES_COL_SLIT_CURV_A,
1932 table_index, slit_a);
1933 cpl_table_set_array(sub_trace_wave, CR2RES_COL_SLIT_CURV_B,
1934 table_index, slit_b);
1935 cpl_table_set_array(sub_trace_wave, CR2RES_COL_SLIT_CURV_C,
1936 table_index, slit_c);
1939 cpl_array_delete(bottom);
1940 cpl_array_delete(center);
1941 cpl_array_delete(top);
1943 cpl_array_delete(wave);
1945 if (res == -1)
break;
1947 cpl_free(order_idx_values);
1950 cpl_table_delete(sub_trace_wave);
1953 return sub_trace_wave ;
1966 const cpl_table * tw,
1967 const char * setting,
1970 cpl_table * selected_tw ;
1971 cpl_table * filtered_tw ;
1974 selected_tw = cpl_table_duplicate(tw) ;
1975 nrows = cpl_table_get_nrow(selected_tw) ;
1976 for (i=0 ; i<nrows ; i++) {
1977 int order_idx, order_real ;
1978 order_idx = cpl_table_get(selected_tw, CR2RES_COL_ORDER, i, NULL) ;
1980 if (cr2res_trace_filter_keep(setting, order_real)) {
1981 cpl_table_select_row(selected_tw, i) ;
1983 cpl_table_unselect_row(selected_tw, i) ;
1986 filtered_tw = cpl_table_extract_selected(selected_tw) ;
1987 cpl_table_delete(selected_tw) ;
1988 return filtered_tw ;
2007static double cr2res_trace_compute_shift(
2008 const cpl_table * traces1,
2009 const cpl_table * traces2)
2013 for (i=0 ; i<cpl_table_get_nrow(traces1) ; i++) {
2015 order_idx = cpl_table_get(traces1, CR2RES_COL_ORDER, i, NULL) ;
2016 if (order_idx >= 0) {
2020 cpl_msg_warning(__func__,
"NOT YET IMPLEMENTED") ;
2032static int cr2res_trace_apply_shift(
2056static cpl_array * cr2res_trace_get_slit_frac(
2057 const cpl_table * traces,
2059 cr2res_decker decker_pos)
2061 cpl_array * slit_frac ;
2063 cpl_size nb_traces, other_idx, i ;
2064 double center_pos_curr, center_pos_other ;
2067 order_idx = cpl_table_get(traces, CR2RES_COL_ORDER, idx, NULL) ;
2073 if (nb_traces == 1 && decker_pos == CR2RES_DECKER_NONE) {
2076 }
else if (nb_traces == 2 &&
2077 (decker_pos==CR2RES_DECKER_1_3 || decker_pos==CR2RES_DECKER_2_4)) {
2083 for (i=0 ; i<cpl_table_get_nrow(traces) ; i++) {
2084 if (cpl_table_get(traces, CR2RES_COL_ORDER, i, NULL)==order_idx &&
2085 i != idx) other_idx = i ;
2087 if (other_idx < 0)
return NULL ;
2093 if (center_pos_curr < center_pos_other) {
2121static cpl_mask * cr2res_trace_signal_detect(
2122 const cpl_image * image,
2127 cpl_image *smx_image;
2128 cpl_image *smxy_image;
2129 int kernel_x, kernel_y;
2134 if (image == NULL)
return NULL;
2135 if (cpl_image_get_type(image) != CPL_TYPE_DOUBLE) {
2136 cpl_msg_error(__func__,
"Expecting double image.");
2139 if (smooth_x < 0 || smooth_y < 0)
return NULL;
2142 kernel_x = smooth_x;
2143 if (kernel_x % 2 == 0) kernel_x++;
2144 kernel_y = smooth_y ;
2145 if (kernel_y % 2 == 0) kernel_y++;
2148 kernel = cpl_mask_new(kernel_x, 1);
2149 cpl_mask_not(kernel);
2151 smx_image = cpl_image_duplicate(image);
2152 if (cpl_image_filter_mask(smx_image, image, kernel, CPL_FILTER_AVERAGE_FAST,
2153 CPL_BORDER_FILTER) != CPL_ERROR_NONE) {
2154 cpl_msg_error(__func__,
"Cannot filter the image");
2155 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT);
2156 cpl_mask_delete(kernel);
2157 cpl_image_delete(smx_image);
2160 cpl_mask_delete(kernel);
2161 #ifndef CR2RES_UNUSED
2164 double img_min = cpl_image_get_min(smx_image) - 1.0;
2165 cpl_image_subtract_scalar(smx_image, img_min);
2166 smxy_image = cpl_image_logarithm_create(smx_image, CPL_MATH_E);
2169 cpl_image *tmp_image;
2170 kernel = cpl_mask_new(1, kernel_y);
2171 cpl_mask_not(kernel);
2172 tmp_image = cpl_image_duplicate(smxy_image);
2173 if (cpl_image_filter_mask(smxy_image, tmp_image, kernel,
2174 CPL_FILTER_AVERAGE_FAST,
2175 CPL_BORDER_FILTER) != CPL_ERROR_NONE) {
2176 cpl_msg_error(__func__,
"Cannot filter the image");
2177 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT);
2178 cpl_mask_delete(kernel);
2179 cpl_image_delete(smx_image);
2180 cpl_image_delete(tmp_image);
2183 cpl_mask_delete(kernel);
2184 cpl_image_delete(tmp_image);
2187 if (cpl_image_exponential(smxy_image, CPL_MATH_E) != CPL_ERROR_NONE)
2188 cpl_msg_error(__func__,
"Cannot exponentiate the smxy_image");
2191 #ifdef CR2RES_UNUSED
2197 cpl_size icol, ncols, irow, nrows;
2198 int log, opt_filter;
2205 double img_min = cpl_image_get_min(smx_image)-1.0;
2206 cpl_image_subtract_scalar(smx_image, img_min);
2207 smxy_image = cpl_image_logarithm_create(smx_image, CPL_MATH_E);
2209 smxy_image = cpl_image_duplicate(smx_image);
2214 cpl_mask *smxy_mask;
2215 cpl_binary *smxy_mskdata;
2219 ncols = cpl_image_get_size_x(image);
2220 nrows = cpl_image_get_size_y(image);
2222 options[0]=options[2]=0;
2224 smxy_mask = cpl_image_get_bpm(smxy_image);
2225 smxy_mskdata = cpl_mask_get_data(smxy_mask);
2226 smxy_data = cpl_image_get_data_double(smxy_image);
2227 img_column = (
double *)cpl_malloc(nrows*
sizeof(
double));
2228 wgt_column = (
double *)cpl_malloc(nrows*
sizeof(
double));
2230 for (icol=0; icol<ncols; icol++) {
2231 for (irow=0; irow<nrows; irow++) {
2232 img_column[irow] = smxy_data[icol+irow*ncols];
2233 wgt_column[irow] = !smxy_mskdata[icol+irow*ncols];
2235 if (cr2res_util_optimal_filter_1d(img_column, (
double)smooth_y,
2236 img_column, nrows, options,
2237 NULL, wgt_column, 0.) != CPL_ERROR_NONE) {
2238 cpl_msg_error(__func__,
"Cannot filter the image");
2239 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT);
2240 cpl_image_delete(smx_image);
2241 cpl_image_delete(smxy_image);
2242 cpl_free(img_column);
2243 cpl_free(wgt_column);
2246 for (irow=0; irow<nrows; irow++)
2247 smxy_data[icol+irow*ncols] = img_column[irow];
2249 cpl_free(img_column);
2250 cpl_free(wgt_column);
2253 cpl_image *tmp_image;
2254 kernel = cpl_mask_new(1, kernel_y);
2255 cpl_mask_not(kernel);
2256 tmp_image = cpl_image_duplicate(smxy_image);
2257 if (cpl_image_filter_mask(smxy_image, tmp_image, kernel,
2258 CPL_FILTER_AVERAGE_FAST,
2259 CPL_BORDER_FILTER) != CPL_ERROR_NONE) {
2260 cpl_msg_error(__func__,
"Cannot filter the image");
2261 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT);
2262 cpl_mask_delete(kernel);
2263 cpl_image_delete(smx_image);
2264 cpl_image_delete(tmp_image);
2267 cpl_mask_delete(kernel);
2268 cpl_image_delete(tmp_image);
2273 if (cpl_image_exponential(smxy_image, CPL_MATH_E) != CPL_ERROR_NONE)
2274 cpl_msg_error(__func__,
"Cannot exponentiate the smxy_image");
2279 cpl_image_subtract(smx_image, smxy_image);
2281 if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
2282 if (cpl_image_save(smxy_image,
"debug_smxyimage.fits", CPL_TYPE_DOUBLE,
2283 NULL, CPL_IO_CREATE) != CPL_ERROR_NONE)
2285 if (cpl_image_save(smx_image,
"debug_smximage.fits", CPL_TYPE_DOUBLE,
2286 NULL, CPL_IO_CREATE) != CPL_ERROR_NONE)
2291 mask = cpl_mask_threshold_image_create(smx_image, thresh, DBL_MAX);
2292 cpl_image_delete(smx_image);
2293 cpl_image_delete(smxy_image);
2309static cpl_table * cr2res_trace_restore_edge_traces(
2310 cpl_table * trace_table)
2312 cpl_table * restored_trace_table ;
2313 const cpl_array * coeffs_upper ;
2314 const cpl_array * coeffs_lower ;
2315 cpl_array * new_trace ;
2316 cpl_vector * heights ;
2317 cpl_vector * heights_tmp ;
2318 double height_med, threshold, lowest_pos,
2320 cpl_size ntraces, i, lowest_idx, uppest_idx ;
2323 if (trace_table == NULL)
return NULL ;
2326 lowest_idx = uppest_idx = -1 ;
2327 lowest_pos = 2048.0 ;
2331 ntraces = cpl_table_get_nrow(trace_table) ;
2332 heights = cpl_vector_new(ntraces) ;
2333 for (i=0 ; i<ntraces ; i++) {
2334 cpl_polynomial * poly_upper ;
2335 cpl_polynomial * poly_lower ;
2339 coeffs_upper = cpl_table_get_array(trace_table, CR2RES_COL_UPPER, i) ;
2343 coeffs_lower = cpl_table_get_array(trace_table, CR2RES_COL_LOWER, i) ;
2347 curr_pos = cpl_polynomial_eval_1d(poly_lower, CR2RES_DETECTOR_SIZE/2.0,
2349 if (curr_pos < lowest_pos) {
2350 lowest_pos = curr_pos ;
2353 if (curr_pos > uppest_pos) {
2354 uppest_pos = curr_pos ;
2360 CR2RES_DETECTOR_SIZE);
2361 cpl_polynomial_delete(poly_upper) ;
2362 cpl_polynomial_delete(poly_lower) ;
2363 cpl_vector_set(heights, i, height) ;
2367 heights_tmp = cpl_vector_duplicate(heights) ;
2368 height_med = cpl_vector_get_median(heights_tmp) ;
2369 cpl_vector_delete(heights_tmp) ;
2370 threshold = 0.95 * height_med ;
2371 cpl_msg_debug(__func__,
"Height Median / Threshold: %g / %g",
2372 height_med, threshold) ;
2375 restored_trace_table = cpl_table_duplicate(trace_table) ;
2376 for (i=0 ; i<ntraces ; i++) {
2377 if (cpl_vector_get(heights, i) < threshold) {
2378 coeffs_upper=cpl_table_get_array(trace_table, CR2RES_COL_UPPER, i) ;
2379 coeffs_lower=cpl_table_get_array(trace_table, CR2RES_COL_LOWER, i) ;
2380 if (i == uppest_idx) {
2381 cpl_msg_warning(__func__,
"Restore Upper trace") ;
2382 new_trace = cpl_array_duplicate(coeffs_lower) ;
2383 cpl_array_set(new_trace, 0, cpl_array_get(coeffs_lower,
2384 0, NULL) + height_med);
2385 cpl_table_set_array(restored_trace_table, CR2RES_COL_UPPER, i,
2387 cpl_array_set(new_trace, 0, cpl_array_get(coeffs_lower,
2388 0, NULL) + height_med/2.0);
2389 cpl_table_set_array(restored_trace_table, CR2RES_COL_ALL, i,
2391 cpl_array_delete(new_trace) ;
2392 }
else if (i == lowest_idx) {
2393 cpl_msg_warning(__func__,
"Restore Lower trace") ;
2394 new_trace = cpl_array_duplicate(coeffs_upper) ;
2395 cpl_array_set(new_trace, 0, cpl_array_get(coeffs_upper,
2396 0, NULL) - height_med);
2397 cpl_table_set_array(restored_trace_table, CR2RES_COL_LOWER, i,
2399 cpl_array_set(new_trace, 0, cpl_array_get(coeffs_upper,
2400 0, NULL) - height_med/2.0);
2401 cpl_table_set_array(restored_trace_table, CR2RES_COL_ALL, i,
2403 cpl_array_delete(new_trace) ;
2405 cpl_msg_warning(__func__,
2406 "Incomplete traces only expected on the lower or upper zones");
2410 cpl_vector_delete(heights) ;
2411 return restored_trace_table ;
2429static cpl_table * cr2res_trace_fit_traces(
2430 cpl_table * clustertable,
2433 cpl_table * traces_table;
2434 cpl_table * edge_upper_table = NULL;
2435 cpl_table * edge_lower_table = NULL;
2439 if (clustertable == NULL)
return NULL ;
2440 if (degree < 0)
return NULL;
2441 if (cpl_table_get_nrow(clustertable) == 0)
return NULL;
2442 if (cpl_table_has_column(clustertable, CR2RES_COL_CLUSTERS) == 0)
return NULL;
2445 nclusters = cpl_table_get_column_max(clustertable, CR2RES_COL_CLUSTERS);
2447 traces_table = cpl_table_new(nclusters);
2448 cpl_table_new_column_array(traces_table, CR2RES_COL_ALL, CPL_TYPE_DOUBLE,
2450 cpl_table_new_column_array(traces_table, CR2RES_COL_UPPER, CPL_TYPE_DOUBLE,
2452 cpl_table_new_column_array(traces_table, CR2RES_COL_LOWER, CPL_TYPE_DOUBLE,
2456 for (i=1 ; i<=nclusters ; i++) {
2458 cpl_array * fitparams_all;
2459 cpl_array * fitparams_upper;
2460 cpl_array * fitparams_lower;
2461 cpl_table * trace_table;
2462 cpl_size nclusters_cur;
2464 nclusters_cur = cpl_table_and_selected_int(clustertable,
2465 CR2RES_COL_CLUSTERS, CPL_EQUAL_TO, i);
2466 cpl_msg_debug(__func__,
"Cluster %d has %"CPL_SIZE_FORMAT
" pixels",
2470 trace_table = cpl_table_extract_selected(clustertable);
2473 fitparams_all = cr2res_trace_fit_trace(trace_table, degree);
2474 cpl_table_set_array(traces_table,
"All", i-1, fitparams_all);
2475 cpl_array_delete(fitparams_all);
2478 cr2res_trace_extract_edges(trace_table, &edge_lower_table,
2479 &edge_upper_table) ;
2482 fitparams_upper = cr2res_trace_fit_trace(edge_upper_table, degree);
2483 cpl_table_delete(edge_upper_table);
2484 cpl_table_set_array(traces_table, CR2RES_COL_UPPER, i-1,
2486 cpl_array_delete(fitparams_upper);
2489 fitparams_lower = cr2res_trace_fit_trace(edge_lower_table, degree);
2490 cpl_table_delete(edge_lower_table);
2491 cpl_table_set_array(traces_table, CR2RES_COL_LOWER, i-1,
2493 cpl_array_delete(fitparams_lower);
2495 cpl_table_delete(trace_table);
2498 cpl_table_select_all(clustertable);
2500 return traces_table;
2518static cpl_array * cr2res_trace_fit_trace(
2524 cpl_polynomial * poly1 ;
2525 cpl_array * result ;
2529 cpl_size i, degree_local, n ;
2532 if (table == NULL || degree < 0)
return NULL ;
2535 n = cpl_table_get_nrow(table) ;
2536 degree_local = (cpl_size)degree ;
2537 x_min = x_max = -1 ;
2540 x = cpl_matrix_new(1, n) ;
2541 y = cpl_vector_new(n) ;
2543 xs = cpl_table_get_data_int(table, CR2RES_COL_XS);
2544 ys = cpl_table_get_data_int(table, CR2RES_COL_YS);
2545 for (i=0 ; i<n ; i++) {
2547 if (x_min < 0 || xs[i] < x_min) x_min = xs[i] ;
2548 if (x_max < 0 || xs[i] > x_max) x_max = xs[i] ;
2551 cpl_matrix_set(x, 0, i, xs[i]) ;
2552 cpl_vector_set(y, i, (
double)ys[i]) ;
2557 if (x_max - x_min < 1500) degree_local = 1 ;
2560 poly1 = cpl_polynomial_new(1) ;
2561 if (cpl_polynomial_fit(poly1, x, NULL, y, NULL, CPL_FALSE, NULL,
2562 °ree_local) != CPL_ERROR_NONE) {
2563 cpl_msg_error(__func__,
"Cannot fit the data") ;
2564 cpl_matrix_delete(x);
2565 cpl_vector_delete(y);
2566 cpl_polynomial_delete(poly1);
2570 cpl_matrix_delete(x);
2571 cpl_vector_delete(y);
2575 cpl_polynomial_delete(poly1);
2590static cpl_table * cr2res_trace_convert_labels_to_cluster(cpl_image * labels)
2592 const int * plabels ;
2593 cpl_table * clustertable ;
2594 int nb_table_entries, nx, ny, i, j ;
2597 if (labels == NULL)
return NULL;
2599 nb_table_entries = 0 ;
2600 plabels = cpl_image_get_data_int_const(labels) ;
2601 nx = cpl_image_get_size_x(labels) ;
2602 ny = cpl_image_get_size_y(labels) ;
2603 for (i=0 ; i<nx*ny ; i++)
2604 if (plabels[i] > 0.5) nb_table_entries ++ ;
2605 cpl_msg_debug(__func__,
"Number of table entries: %d", nb_table_entries) ;
2608 clustertable = cpl_table_new(nb_table_entries);
2609 cpl_table_new_column(clustertable, CR2RES_COL_XS, CPL_TYPE_INT) ;
2610 cpl_table_new_column(clustertable, CR2RES_COL_YS, CPL_TYPE_INT) ;
2611 cpl_table_new_column(clustertable, CR2RES_COL_CLUSTERS, CPL_TYPE_INT) ;
2612 nb_table_entries = 0 ;
2613 for (j=0 ; j<ny ; j++) {
2614 for (i=0 ; i<nx ; i++) {
2615 if (plabels[i+j*nx] > 0.5) {
2616 cpl_table_set_int(clustertable, CR2RES_COL_XS, nb_table_entries,
2618 cpl_table_set_int(clustertable, CR2RES_COL_YS, nb_table_entries,
2620 cpl_table_set_int(clustertable, CR2RES_COL_CLUSTERS,
2621 nb_table_entries, plabels[i+j*nx]) ;
2622 nb_table_entries ++ ;
2626 return clustertable ;
2637static cpl_mask * cr2res_trace_clean_blobs(
2641 cpl_mask * new_mask ;
2642 cpl_image * labels ;
2644 cpl_binary * pnew_mask ;
2645 const int * plabels ;
2646 int i, curr_label, npix ;
2649 if (mask == NULL)
return NULL ;
2650 if (min_cluster < 0)
return NULL;
2653 if ((labels = cpl_image_labelise_mask_create(mask, &nlabels)) == NULL) {
2654 cpl_msg_error(__func__,
"Failed to labelise") ;
2657 if (nlabels > 10000) {
2658 cpl_msg_error(__func__,
"Too many labels resulting from mask") ;
2659 cpl_image_delete(labels) ;
2662 plabels = cpl_image_get_data_int_const(labels) ;
2665 npix = cpl_mask_get_size_x(mask) * cpl_mask_get_size_y(mask) ;
2668 new_mask=cpl_mask_new(cpl_mask_get_size_x(mask),cpl_mask_get_size_y(mask));
2669 pnew_mask = cpl_mask_get_data(new_mask) ;
2672 for (curr_label=1 ; curr_label<=nlabels ; curr_label++) {
2677 for (i=0 ; i<npix ; i++) {
2678 if (plabels[i] == curr_label) pix_count++ ;
2679 if (pix_count >= min_cluster)
break;
2683 if (pix_count >= min_cluster) {
2685 for (i=0 ; i<npix ; i++)
2686 if (plabels[i] == curr_label) pnew_mask[i] = CPL_BINARY_1 ;
2689 cpl_image_delete(labels) ;
2706static int cr2res_trace_extract_edges(
2707 cpl_table * pixels_table,
2708 cpl_table ** edge_lower_table,
2709 cpl_table ** edge_upper_table)
2711 cpl_table * upper_sel ;
2712 cpl_table * lower_sel ;
2720 if (pixels_table == NULL || edge_lower_table == NULL ||
2721 edge_upper_table == NULL)
return -1 ;
2724 pxs = cpl_table_get_data_int_const(pixels_table, CR2RES_COL_XS) ;
2725 pys = cpl_table_get_data_int_const(pixels_table, CR2RES_COL_YS) ;
2728 max_x = (int)cpl_table_get_column_max(pixels_table, CR2RES_COL_XS) ;
2731 min_y = cpl_malloc(max_x *
sizeof(
int)) ;
2732 max_y = cpl_malloc(max_x *
sizeof(
int)) ;
2733 for (i=0 ; i<max_x ; i++) min_y[i] = max_y[i] = -1 ;
2736 for (i=0 ; i<cpl_table_get_nrow(pixels_table) ; i++) {
2737 if (pys[i] < min_y[pxs[i]-1] || min_y[pxs[i]-1] < 0)
2738 min_y[pxs[i]-1] = pys[i] ;
2739 if (pys[i] > max_y[pxs[i]-1] || max_y[pxs[i]-1] < 0)
2740 max_y[pxs[i]-1] = pys[i] ;
2744 upper_sel = cpl_table_duplicate(pixels_table) ;
2745 cpl_table_unselect_all(upper_sel) ;
2746 pxs = cpl_table_get_data_int_const(upper_sel, CR2RES_COL_XS) ;
2747 pys = cpl_table_get_data_int_const(upper_sel, CR2RES_COL_YS) ;
2748 for (i=0 ; i<cpl_table_get_nrow(upper_sel) ; i++)
2749 if (max_y[pxs[i]-1] == pys[i])
2750 cpl_table_select_row(upper_sel, i) ;
2752 *edge_upper_table = cpl_table_extract_selected(upper_sel) ;
2753 cpl_table_delete(upper_sel) ;
2756 lower_sel = cpl_table_duplicate(pixels_table) ;
2757 cpl_table_unselect_all(lower_sel) ;
2758 pxs = cpl_table_get_data_int_const(lower_sel, CR2RES_COL_XS) ;
2759 pys = cpl_table_get_data_int_const(lower_sel, CR2RES_COL_YS) ;
2760 for (i=0 ; i<cpl_table_get_nrow(lower_sel) ; i++)
2761 if (min_y[pxs[i]-1] == pys[i])
2762 cpl_table_select_row(lower_sel, i) ;
2764 *edge_lower_table = cpl_table_extract_selected(lower_sel) ;
2765 cpl_table_delete(lower_sel) ;
2767 return CPL_ERROR_NONE ;
2778static int cr2res_trace_check_slit_fraction(
const cpl_array * slit_fraction)
2780 double low, mid, up ;
2783 if (slit_fraction == NULL)
return -1;
2786 low = cpl_array_get(slit_fraction, 0, NULL) ;
2787 mid = cpl_array_get(slit_fraction, 1, NULL) ;
2788 up = cpl_array_get(slit_fraction, 2, NULL) ;
2790 if (cpl_error_get_code() != CPL_ERROR_NONE)
return -1 ;
2792 if (up<0.0 || low<0.0 || mid<0.0 || up>1.0 || low>1.0 || mid>1.0)
2794 if (low>mid || mid > up)
2814static int cr2res_trace_new_trace(
2815 const cpl_array * slit_fraction_in,
2816 const cpl_array ** trace_in,
2817 const int nb_traces,
2818 const cpl_array * slit_fraction_wished,
2819 cpl_array ** trace_all_new,
2820 cpl_array ** trace_upper_new,
2821 cpl_array ** trace_lower_new)
2823 cpl_polynomial ** poly_in ;
2824 cpl_polynomial * poly_slit;
2825 cpl_polynomial * poly_upper_out ;
2826 cpl_polynomial * poly_lower_out ;
2827 cpl_polynomial * poly_all_out ;
2828 const cpl_size power = 0 ;
2829 cpl_array * trace_all_out ;
2830 cpl_array * trace_upper_out ;
2831 cpl_array * trace_lower_out ;
2832 cpl_matrix * sf_matrix;
2833 cpl_error_code error;
2835 const double * sf_in;
2836 cpl_vector * pix_in;
2837 double sf_out_l, sf_out_m, sf_out_u, pix_out_l, pix_out_u,
2838 pix_out_m, new_coeff ;
2841 if (slit_fraction_in==NULL || trace_in==NULL || slit_fraction_wished==NULL
2842 || trace_all_new==NULL || trace_upper_new==NULL
2843 || trace_lower_new==NULL || nb_traces <= 0)
return -1;
2847 if (cpl_array_get_size(slit_fraction_in) != 3 * nb_traces ||
2848 cpl_array_get_size(slit_fraction_wished) != 3)
return -1;
2853 sf_out_l = cpl_array_get(slit_fraction_wished, 0, NULL) ;
2854 sf_out_m = cpl_array_get(slit_fraction_wished, 1, NULL) ;
2855 sf_out_u = cpl_array_get(slit_fraction_wished, 2, NULL) ;
2858 poly_in = cpl_malloc(3 * nb_traces *
sizeof(cpl_polynomial*));
2859 for (cpl_size i = 0; i < nb_traces * 3; i++) poly_in[i] = NULL;
2860 pix_in = cpl_vector_new(3 * nb_traces);
2863 for(cpl_size i = 0; i < nb_traces * 3; i++)
2866 cpl_vector_set(pix_in, i, cpl_polynomial_eval_1d(poly_in[i],
2867 (
double)(CR2RES_DETECTOR_SIZE/2.0), NULL));
2871 poly_slit = cpl_polynomial_new(1);
2873 sf_in = cpl_array_get_data_double_const(slit_fraction_in);
2874 sf_matrix = cpl_matrix_wrap(1, nb_traces * 3, (
double*)sf_in);
2876 error = cpl_polynomial_fit(poly_slit, sf_matrix, NULL, pix_in, NULL,
2877 CPL_FALSE, NULL, &fitdeg);
2878 cpl_matrix_unwrap(sf_matrix);
2881 if (error != CPL_ERROR_NONE){
2882 cpl_polynomial_delete(poly_slit);
2883 for(cpl_size i = 0; i < nb_traces*3; i++)
2885 cpl_polynomial_delete(poly_in[i]);
2888 cpl_vector_delete(pix_in);
2894 pix_out_l = cpl_polynomial_eval_1d(poly_slit, sf_out_l, NULL);
2895 pix_out_m = cpl_polynomial_eval_1d(poly_slit, sf_out_m, NULL);
2896 pix_out_u = cpl_polynomial_eval_1d(poly_slit, sf_out_u, NULL);
2899 cpl_msg_debug(__func__,
2900 "Slit fraction: [%g-%g-%g]->[%g-%g-%g] - Pixel positions: [%g-%g-%g]->[%g-%g-%g]",
2901 sf_in[0], sf_in[1], sf_in[2], sf_out_l, sf_out_m, sf_out_u,
2902 cpl_vector_get(pix_in, 0), cpl_vector_get(pix_in, 1),
2903 cpl_vector_get(pix_in, 2), pix_out_l, pix_out_m, pix_out_u) ;
2906 poly_upper_out = cpl_polynomial_duplicate(poly_in[2]) ;
2907 poly_lower_out = cpl_polynomial_duplicate(poly_in[0]) ;
2908 poly_all_out = cpl_polynomial_duplicate(poly_in[1]) ;
2910 new_coeff = cpl_polynomial_get_coeff(poly_upper_out, &power) + pix_out_u
2911 - cpl_vector_get(pix_in, 2) ;
2912 cpl_polynomial_set_coeff(poly_upper_out, &power, new_coeff) ;
2913 new_coeff = cpl_polynomial_get_coeff(poly_lower_out, &power) + pix_out_l
2914 - cpl_vector_get(pix_in, 0) ;
2915 cpl_polynomial_set_coeff(poly_lower_out, &power, new_coeff) ;
2916 new_coeff = cpl_polynomial_get_coeff(poly_all_out, &power) + pix_out_m
2917 - cpl_vector_get(pix_in, 1) ;
2918 cpl_polynomial_set_coeff(poly_all_out, &power, new_coeff) ;
2920 for(cpl_size i = 0; i < nb_traces*3; i++)
2922 cpl_polynomial_delete(poly_in[i]);
2925 cpl_vector_delete(pix_in);
2926 cpl_polynomial_delete(poly_slit);
2931 cpl_array_get_size(trace_in[1]));
2933 cpl_array_get_size(trace_in[2]));
2935 cpl_array_get_size(trace_in[0]));
2936 cpl_polynomial_delete(poly_all_out) ;
2937 cpl_polynomial_delete(poly_upper_out) ;
2938 cpl_polynomial_delete(poly_lower_out) ;
2941 if (cpl_error_get_code() != CPL_ERROR_NONE) {
2942 cpl_array_delete(trace_all_out) ;
2943 cpl_array_delete(trace_upper_out) ;
2944 cpl_array_delete(trace_lower_out) ;
2949 *trace_all_new = trace_all_out ;
2950 *trace_upper_new = trace_upper_out ;
2951 *trace_lower_new = trace_lower_out ;
2976static int cr2res_trace_get_subtrace(
2977 cpl_table * trace_wave,
2981 cpl_array ** bottom,
2982 cpl_array ** center,
2988 if (slit_pos < 0 || slit_pos > 1)
return -1;
2989 if (bottom != NULL && *bottom == NULL)
return -1;
2990 if (center != NULL && *center == NULL)
return -1;
2991 if (top != NULL && *top == NULL)
return -1;
2993 if (wave != NULL && *wave == NULL)
return -1;
2999 if (traces == NULL)
return -1;
3001 const cpl_array * bounds[3], *old_fraction;
3003 cpl_size i, j, k, ndegree;
3005 cpl_matrix * samppos;
3006 cpl_vector *fitvals;
3007 cpl_polynomial * poly;
3010 cpl_size maxdeg = 2;
3011 cpl_error_code error = CPL_ERROR_NONE;
3014 ndegree = cpl_table_get_column_dimension(trace_wave, CR2RES_COL_ALL, 0);
3015 samppos = cpl_matrix_new(1, 3 * nb_traces);
3016 fitvals = cpl_vector_new(3 * nb_traces);
3017 poly = cpl_polynomial_new(1);
3019 for (i = 0; i < ndegree; i++){
3020 for (k = 0; k < nb_traces; k++){
3023 bounds[0] = cpl_table_get_array(trace_wave, CR2RES_COL_LOWER, j);
3024 bounds[1] = cpl_table_get_array(trace_wave, CR2RES_COL_ALL, j);
3025 bounds[2] = cpl_table_get_array(trace_wave, CR2RES_COL_UPPER, j);
3026 old_fraction = cpl_table_get_array(trace_wave,
3027 CR2RES_COL_SLIT_FRACTION, j);
3029 for (j = 0; j < 3; j++){
3030 res = cpl_array_get_double(old_fraction, j, NULL);
3031 if (res == -1) res = 0.5 * j;
3032 cpl_matrix_set(samppos, 0, k * 3 + j, res);
3033 cpl_vector_set(fitvals, k * 3 + j,
3034 cpl_array_get_double(bounds[j], i, NULL));
3038 error = cpl_polynomial_fit(poly, samppos, NULL, fitvals, NULL, 1,
3041 if (center != NULL){
3042 res = cpl_polynomial_eval_1d(poly, slit_pos, NULL);
3043 cpl_array_set_double(*center, i, res);
3047 res = cpl_polynomial_eval_1d(poly, slit_pos + height, NULL);
3048 cpl_array_set_double(*top, i, res);
3051 if (bottom != NULL){
3052 res = cpl_polynomial_eval_1d(poly, slit_pos - height, NULL);
3053 cpl_array_set_double(*bottom, i, res);
3057 cpl_matrix_delete(samppos);
3058 cpl_vector_delete(fitvals);
3059 cpl_polynomial_delete(poly);
3062 cpl_array_set_double(*
fraction, 0, slit_pos-height);
3063 cpl_array_set_double(*
fraction, 1, slit_pos);
3064 cpl_array_set_double(*
fraction, 2, slit_pos+height);
3069 const cpl_array *old_wave;
3070 if (nb_traces == 1){
3072 old_wave = cpl_table_get_array(trace_wave, CR2RES_COL_WAVELENGTH, j);
3073 cpl_array_copy_data_double(*wave,
3074 cpl_array_get_data_double_const(old_wave));
3076 ndegree = cpl_table_get_column_dimension(trace_wave, CR2RES_COL_WAVELENGTH, 0);
3077 maxdeg = min(2, nb_traces - 1);
3078 samppos = cpl_matrix_new(1, nb_traces);
3079 fitvals = cpl_vector_new(nb_traces);
3080 poly = cpl_polynomial_new(1);
3081 for (i = 0; i < ndegree; i++){
3082 for (k = 0; k < nb_traces; k++){
3085 old_fraction = cpl_table_get_array(trace_wave,
3086 CR2RES_COL_SLIT_FRACTION, j);
3087 old_wave = cpl_table_get_array(trace_wave,
3088 CR2RES_COL_WAVELENGTH, j);
3090 res = cpl_array_get_double(old_fraction, j, NULL);
3091 if (res == -1) res = 0.5 * j;
3093 cpl_matrix_set(samppos, 0, k, res);
3094 cpl_vector_set(fitvals, k, cpl_array_get_double(old_wave, i,
3097 error = cpl_polynomial_fit(poly, samppos, NULL, fitvals, NULL, 1,
3099 res = cpl_polynomial_eval_1d(poly, slit_pos, NULL);
3100 cpl_array_set_double(*wave, i, res);
3102 cpl_matrix_delete(samppos);
3103 cpl_vector_delete(fitvals);
3104 cpl_polynomial_delete(poly);
3109 if (error != CPL_ERROR_NONE){
3124static int cr2res_trace_filter_keep(
3125 const char * setting,
3129 if (setting == NULL)
return -1 ;
3131 cpl_msg_debug(__func__,
"Real order : %d setting : %s",real_order,setting) ;
3134 cpl_msg_debug(__func__,
"Filtering not implemented - Keep everything") ;
3137 if (!strcmp(setting,
"H1559")) { first = 10 ; last = 20 ; }
3138 else if (!strcmp(setting,
"H1567")) { first = 10 ; last = 20 ; }
3139 else if (!strcmp(setting,
"H1575")) { first = 10 ; last = 20 ; }
3140 else if (!strcmp(setting,
"H1582")) { first = 10 ; last = 20 ; }
3141 else if (!strcmp(setting,
"J1226")) { first = 10 ; last = 20 ; }
3142 else if (!strcmp(setting,
"J1228")) { first = 10 ; last = 20 ; }
3143 else if (!strcmp(setting,
"J1232")) { first = 10 ; last = 20 ; }
3144 else if (!strcmp(setting,
"K2148")) { first = 10 ; last = 20 ; }
3145 else if (!strcmp(setting,
"K2166")) { first = 10 ; last = 20 ; }
3146 else if (!strcmp(setting,
"K2192")) { first = 10 ; last = 20 ; }
3147 else if (!strcmp(setting,
"K2217")) { first = 10 ; last = 20 ; }
3148 else if (!strcmp(setting,
"L3244")) { first = 10 ; last = 20 ; }
3149 else if (!strcmp(setting,
"L3262")) { first = 10 ; last = 20 ; }
3150 else if (!strcmp(setting,
"L3302")) { first = 10 ; last = 20 ; }
3151 else if (!strcmp(setting,
"L3340")) { first = 10 ; last = 20 ; }
3152 else if (!strcmp(setting,
"L3377")) { first = 10 ; last = 20 ; }
3153 else if (!strcmp(setting,
"L3412")) { first = 10 ; last = 20 ; }
3154 else if (!strcmp(setting,
"L3426")) { first = 10 ; last = 20 ; }
3155 else if (!strcmp(setting,
"M4187")) { first = 10 ; last = 20 ; }
3156 else if (!strcmp(setting,
"M4211")) { first = 10 ; last = 20 ; }
3157 else if (!strcmp(setting,
"M4266")) { first = 10 ; last = 20 ; }
3158 else if (!strcmp(setting,
"M4318")) { first = 10 ; last = 20 ; }
3159 else if (!strcmp(setting,
"M4368")) { first = 10 ; last = 20 ; }
3160 else if (!strcmp(setting,
"M4416")) { first = 10 ; last = 20 ; }
3161 else if (!strcmp(setting,
"M4461")) { first = 10 ; last = 20 ; }
3162 else if (!strcmp(setting,
"M4504")) { first = 10 ; last = 20 ; }
3163 else if (!strcmp(setting,
"M4519")) { first = 10 ; last = 20 ; }
3164 else if (!strcmp(setting,
"Y1028")) { first = 10 ; last = 20 ; }
3165 else if (!strcmp(setting,
"Y1029")) { first = 10 ; last = 20 ; }
3167 if (real_order >= first && real_order <= last)
return 1 ;
int cr2res_dfs_check_traces_table(const cpl_table *traces)
Check completeness of trace table.
hdrl_imagelist * cr2res_io_load_image_list_from_set(const cpl_frameset *in, int detector)
Load an hdrl image list from an images frameset.
int cr2res_io_get_ext_idx(const char *filename, int detector, int data)
Get the wished extension number for a detector.
cr2res_decker cr2res_pfits_get_decker_position(const cpl_propertylist *plist)
find out the decker position
int cr2res_pfits_get_order_idx(const cpl_propertylist *plist, double yposition)
find out the order_idx closest to the passed y position
cpl_vector * cr2res_trace_get_ycen(const cpl_table *trace, int order_idx, int trace_nb, int size)
Retrieves the middle (All) polynomial from trace table and evaluates.
cpl_vector * cr2res_trace_compute_middle(cpl_polynomial *trace1, cpl_polynomial *trace2, int vector_size)
Computes the positions between 2 trace polynomials.
cpl_table * cr2res_trace_filter(const cpl_table *tw, const char *setting, int zp_order)
Only keep the predefined orders of the setting.
cpl_image * cr2res_trace_gen_image(cpl_table *trace, int nx, int ny)
Make an image out of the trace solution.
cpl_size cr2res_get_nb_traces(const cpl_table *trace_wave, int order_idx)
Get the number of traces for a specified order_idx.
double cr2res_trace_get_trace_ypos(const cpl_table *traces, int idx)
Compute the y position of the trace.
int cr2res_trace_get_height(const cpl_table *trace, cpl_size order_idx, cpl_size trace_nb)
Computes the average height (pix) of an order, from trace polys.
cpl_table * cr2res_trace_split(cpl_table *trace_wave, int order_idx, int nb_subtraces)
Splits full slit traces into several sub traces.
cr2res_decker cr2res_trace_slit_fraction_info(const cpl_array *slit_frac, int *up_or_down)
Get a standard slit fraction information.
cpl_table * cr2res_trace(cpl_image *ima, int smooth_x, int smooth_y, double threshold, int opening, int degree, int min_cluster)
Main function for running all parts of the trace algorithm.
cpl_size cr2res_get_trace_table_index(const cpl_table *trace_wave, int order_idx, int trace_nb)
Get the index in a TRACE_WAVE table.
cpl_table * cr2res_trace_new_slit_fraction(const cpl_table *traces, const cpl_array *new_slit_fraction)
Recompute the traces at a newly specified slit fraction.
int cr2res_trace_compute_height(cpl_polynomial *trace1, cpl_polynomial *trace2, int vector_size)
Computes extraction height between 2 trace polynomials.
int * cr2res_get_trace_numbers(const cpl_table *trace_wave, int order_idx, int *nb_traces)
Get the trace numbers for a specified order_idx.
cpl_polynomial * cr2res_get_trace_wave_poly(const cpl_table *trace_wave, const char *poly_column, int order_idx, int trace_nb)
Get a polynomial from a TRACE_WAVE table.
cpl_vector * cr2res_trace_get_wl(const cpl_table *trace_wave, int order_idx, int trace_nb, int size)
Get the Wavelength vector from a TRACE_WAVE table.
cpl_mask * cr2res_trace_clean(cpl_mask *mask, int opening, int min_cluster)
Clean small blobs.
int cr2res_trace_add_extra_columns(cpl_table *traces, const char *infile, int det_nr)
Add extra columns to the plain trace table.
int * cr2res_trace_get_order_idx_values(const cpl_table *trace, int *nb_order_idx_values)
Count and return the different order_idx values from a TW table.
cpl_array * cr2res_trace_slit_fraction_create(cr2res_decker decker_position, int up_or_down)
Get a standard slit fraction.
cpl_table * cr2res_trace_merge(const cpl_table *trace_wave1, const cpl_table *trace_wave2)
Merge 2 trace_wave tables.
cpl_polynomial * cr2res_convert_array_to_poly(const cpl_array *arr)
Convert an array to polynomial.
int cr2res_order_idx_to_real(int order_idx, int order_zp)
Convert the order_idx into order_real.
cpl_array * cr2res_convert_poly_to_array(const cpl_polynomial *poly, int size)
Convert a polynomial to array.
cpl_array * cr2res_wave_get_estimate(const char *filename, int detector, int order)
Compute the wavelength estimate.
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
void hdrl_image_delete(hdrl_image *himg)
delete hdrl_image
cpl_error_code hdrl_imagelist_collapse_mean(const hdrl_imagelist *himlist, hdrl_image **out, cpl_image **contrib)
Mean collapsing of image list.
void hdrl_imagelist_delete(hdrl_imagelist *himlist)
Free all memory used by a hdrl_imagelist object including the images.
double fraction(double x, double y, double r_out)
Fraction of pixel bounded.