175 #include <uves_orderpos_follow.h>
177 #include <uves_plot.h>
178 #include <uves_utils.h>
179 #include <uves_utils_wrappers.h>
180 #include <uves_error.h>
181 #include <uves_msg.h>
187 static cpl_table * trace_order(
const cpl_table *ordertable,
int order,
188 const cpl_image *inputimage,
const cpl_image *noise,
189 const cpl_binary *image_bad,
192 static int count_orders(
const cpl_table *tracetable);
193 static double fit_order_linear(cpl_table *singletrace,
int order,
double KAPPA,
195 static int get_xcenter(
int nx,
int ny, cpl_table *ordertab,
int row);
196 static int get_ycenter(
int nx,
int ny, cpl_table *ordertab,
int row);
197 static int get_orderlength(
int nx,
int ny, cpl_table *ordertab,
int row);
198 static double estimate_threshold(
const cpl_image *inputimage,
199 const cpl_image *nosie,
200 cpl_table *ordertable,
201 int row,
double relative_threshold);
202 static bool find_centroid(
const cpl_image *inputimage,
203 const cpl_image *noise,
204 const cpl_binary *image_bad,
205 double threshold,
int spacing,
int x,
double *yguess,
251 const cpl_image *noise,
252 cpl_table *ordertable,
263 cpl_table *tracetable = NULL;
264 cpl_table *singletrace = NULL;
265 cpl_table *temp = NULL;
266 const cpl_mask *image_badmap = NULL;
267 const cpl_binary *image_bad = NULL;
270 double mse, red_chisq;
274 assure_nomsg( inputimage != NULL, CPL_ERROR_NULL_INPUT);
276 assure( cpl_image_get_size_x(inputimage) == cpl_image_get_size_x(noise) &&
277 cpl_image_get_size_y(inputimage) == cpl_image_get_size_y(noise),
278 CPL_ERROR_INCOMPATIBLE_INPUT,
279 "Image sizes are %" CPL_SIZE_FORMAT
"x%" CPL_SIZE_FORMAT
" and %" CPL_SIZE_FORMAT
"x%" CPL_SIZE_FORMAT
"",
280 cpl_image_get_size_x(inputimage), cpl_image_get_size_x(noise),
281 cpl_image_get_size_y(inputimage), cpl_image_get_size_y(noise));
283 assure_nomsg( ordertable != NULL, CPL_ERROR_NULL_INPUT);
284 assure( cpl_table_get_ncol(ordertable) == 4,
285 CPL_ERROR_ILLEGAL_INPUT,
286 "%" CPL_SIZE_FORMAT
" columns found. 4 expected",
287 cpl_table_get_ncol(ordertable));
288 assure( cpl_table_has_column(ordertable,
"Intersept"),
289 CPL_ERROR_DATA_NOT_FOUND,
290 "Missing column Intersept");
291 assure( cpl_table_has_column(ordertable,
"Slope"),
292 CPL_ERROR_DATA_NOT_FOUND,
293 "Missing column Slope");
294 assure( cpl_table_has_column(ordertable,
"Order"),
295 CPL_ERROR_DATA_NOT_FOUND,
296 "Missing column Order");
297 assure( cpl_table_has_column(ordertable,
"Spacing"),
298 CPL_ERROR_DATA_NOT_FOUND,
299 "Missing column Spacing");
303 image_badmap = cpl_image_get_bpm_const(inputimage);
304 image_bad = cpl_mask_get_data_const(image_badmap);
306 N = cpl_table_get_nrow(ordertable);
308 *bivariate_fit = NULL;
311 check(( tracetable = cpl_table_new(0),
312 cpl_table_new_column(tracetable,
"Order" , CPL_TYPE_INT),
313 cpl_table_new_column(tracetable,
"X" , CPL_TYPE_INT),
314 cpl_table_new_column(tracetable,
"Y" , CPL_TYPE_DOUBLE),
315 cpl_table_new_column(tracetable,
"dY" , CPL_TYPE_DOUBLE),
316 cpl_table_new_column(tracetable,
"Residual_Square", CPL_TYPE_DOUBLE),
317 cpl_table_new_column(tracetable,
"OrderRMS" , CPL_TYPE_DOUBLE),
318 cpl_table_new_column(tracetable,
"OrderSlope" , CPL_TYPE_DOUBLE)),
320 "Could not initialize order trace table");
323 check(( cpl_table_new_column(ordertable,
"Xcenter", CPL_TYPE_INT),
324 cpl_table_new_column(ordertable,
"Ycenter", CPL_TYPE_INT),
325 cpl_table_new_column(ordertable,
"OrderLength", CPL_TYPE_INT),
326 cpl_table_new_column(ordertable,
"Threshold", CPL_TYPE_DOUBLE),
327 cpl_table_new_column(ordertable,
"MinThreshold", CPL_TYPE_DOUBLE),
328 cpl_table_new_column(ordertable,
"RMS", CPL_TYPE_DOUBLE),
329 cpl_table_new_column(ordertable,
"TraceSlope", CPL_TYPE_DOUBLE)),
330 "Could not add columns to order table");
335 for (order = 1; order <= N; order++)
338 int nx = cpl_image_get_size_x(inputimage);
339 int ny = cpl_image_get_size_y(inputimage);
340 int points_traced = 0;
341 int xc = get_xcenter (nx, ny, ordertable, order - 1);
342 int yc = get_ycenter (nx, ny, ordertable, order - 1);
344 check(( cpl_table_set_int(ordertable,
"Xcenter" , order - 1, xc),
346 cpl_table_set_int(ordertable,
"Ycenter" , order - 1, yc),
347 cpl_table_set_int(ordertable,
"OrderLength" , order - 1,
348 get_orderlength (nx, ny, ordertable, order - 1))),
349 "Could not calculate order line geometry");
351 if (!(1 <= xc && xc <= nx && 1 <= yc && yc <= ny))
354 "(intersept = %.2f, slope = %f)",
356 cpl_table_get_double(ordertable,
"Intersept", order-1, NULL),
357 cpl_table_get_double(ordertable,
"Slope", order-1, NULL));
361 check( cpl_table_set_double(
362 ordertable,
"Threshold" , order - 1,
363 estimate_threshold(inputimage, noise, ordertable, order - 1, -1)),
364 "Could not calculate max. threshold");
365 check( cpl_table_set_double(
366 ordertable,
"MinThreshold", order - 1,
367 estimate_threshold(inputimage, noise, ordertable, order - 1, MINTHRESH)),
368 "Could not calculate min. threshold");
372 uves_free_table(&singletrace);
373 check( singletrace = trace_order(ordertable,
380 "Error occured while tracing order #%d", order);
382 check( points_traced = cpl_table_get_nrow(singletrace),
"Could not read table size");
384 passure( cpl_table_get_ncol(singletrace) == 3,
"%" CPL_SIZE_FORMAT
"", cpl_table_get_ncol(singletrace));
385 passure( cpl_table_has_column(singletrace,
"X"),
" ");
386 passure( cpl_table_has_column(singletrace,
"Y"),
" ");
387 passure( cpl_table_has_column(singletrace,
"dY"),
" ");
391 if (points_traced == 0)
394 check( cpl_table_set_invalid(ordertable,
"RMS", order - 1),
395 "Could not flag order %d RMS as invalid", order);
404 check( rms = fit_order_linear(singletrace, order, KAPPA, &slope),
405 "Creating linear fit of order #%d failed", order);
407 check(( cpl_table_set_double(ordertable,
"RMS", order - 1, rms),
408 cpl_table_fill_column_window_double(singletrace,
"OrderRMS",
409 0, points_traced, rms)),
410 "Could not write RMS of order #%d to tables", order);
412 check(( cpl_table_set_double(ordertable,
"TraceSlope", order - 1, slope),
413 cpl_table_fill_column_window_double(singletrace,
"OrderSlope",
414 0, points_traced, slope)),
415 "Could not write slope of order #%d to tables", order);
418 passure( cpl_table_get_ncol(singletrace) == 7,
"%" CPL_SIZE_FORMAT
"",
419 cpl_table_get_ncol(singletrace));
420 passure( cpl_table_has_column(singletrace,
"X"),
" ");
421 passure( cpl_table_has_column(singletrace,
"Y"),
" ");
422 passure( cpl_table_has_column(singletrace,
"dY"),
" ");
423 passure( cpl_table_has_column(singletrace,
"Linear fit"),
" ");
424 passure( cpl_table_has_column(singletrace,
"Residual_Square"),
" ");
425 passure( cpl_table_has_column(singletrace,
"OrderRMS"),
" ");
426 passure( cpl_table_has_column(singletrace,
"OrderSlope"),
" ");
429 check( cpl_table_erase_column(singletrace,
"Linear fit"),
430 "Could not delete column 'Linear fit'");
433 check(( cpl_table_new_column(singletrace,
"Order", CPL_TYPE_INT),
434 cpl_table_fill_column_window_int(
435 singletrace,
"Order",
436 0, cpl_table_get_nrow(singletrace), order)
438 "Could not create new column 'Order'");
441 passure( cpl_table_compare_structure(singletrace, tracetable) == 0,
" ");
444 check( cpl_table_insert(tracetable, singletrace,
445 cpl_table_get_nrow(tracetable)),
446 "Could not append single order #%d to trace table", order);
454 check( uves_plot_table(tracetable,
"X",
"Y",
455 "Initial trace (%d orders)", *orders_traced),
459 passure( cpl_table_get_ncol(tracetable) == 7,
"%" CPL_SIZE_FORMAT
"", cpl_table_get_ncol(tracetable));
460 passure( cpl_table_has_column(tracetable,
"X"),
" ");
461 passure( cpl_table_has_column(tracetable,
"Order"),
" ");
462 passure( cpl_table_has_column(tracetable,
"Y"),
" ");
463 passure( cpl_table_has_column(tracetable,
"dY"),
" ");
464 passure( cpl_table_has_column(tracetable,
"Residual_Square"),
" ");
465 passure( cpl_table_has_column(tracetable,
"OrderRMS"),
" ");
466 passure( cpl_table_has_column(tracetable,
"OrderSlope"),
" ");
468 assure(*orders_traced >= 1, CPL_ERROR_ILLEGAL_OUTPUT,
"No orders could be traced");
475 uves_max_double(0.05, MAXRMS * cpl_table_get_column_median(ordertable,
"RMS")),
476 "Could not read median RMS");
481 check( orders_rejected = uves_select_table_rows(
482 ordertable,
"RMS", CPL_GREATER_THAN, maxrms),
483 "Could not select rows in order table");
486 if (orders_rejected > 0)
489 "(from linear fit) was too large", orders_rejected);
492 check( uves_erase_table_rows(tracetable,
"OrderRMS",
493 CPL_GREATER_THAN, maxrms),
494 "Could not erase bad orders from trace table");
509 uves_select_table_rows(
510 ordertable,
"TraceSlope", CPL_GREATER_THAN, 0.5) +
511 uves_select_table_rows(
512 ordertable,
"TraceSlope", CPL_LESS_THAN, -0.5));
514 if (orders_rejected > 0) {
515 uves_msg_warning(
"%d order(s) rejected because slope was outside [-0.5 ; 0.5]",
518 check_nomsg( uves_erase_table_rows(tracetable,
"OrderSlope",
519 CPL_GREATER_THAN, 0.5));
520 check_nomsg( uves_erase_table_rows(tracetable,
"OrderSlope",
521 CPL_LESS_THAN, -0.5));
532 double dy_median = cpl_table_get_column_median(tracetable,
"dY");
533 double threshold = 0.40*dy_median;
536 check_nomsg( nreject = uves_erase_table_rows(tracetable,
"dY", CPL_LESS_THAN,
539 uves_msg_debug(
"Rejected %d points with dY less than %f pixels (median = %f pixels)",
540 nreject, threshold, dy_median);
546 if (*DEFPOL1 < 0 || *DEFPOL2 < 0)
549 int new_deg1, new_deg2;
550 double red_chisq1, mse1;
551 double red_chisq2, mse2;
552 double red_chisq3, mse3;
553 bool adjust1 = (*DEFPOL1 < 0);
555 bool adjust2 = (*DEFPOL2 < 0);
560 int number_of_orders = 0;
562 int number_of_orders1 = 0;
563 int number_of_orders2 = 0;
564 int number_of_orders3 = 0;
589 uves_free_table(&temp);
590 temp = cpl_table_duplicate(tracetable);
594 "X",
"Order",
"Y",
"dY",
601 "Error fitting orders");
603 check( number_of_orders = count_orders(temp),
604 "Error counting orders");
607 "Red.chi^2 = %.2f (%d orders) *",
623 adjust1 = adjust1 && (deg1 + 1 <= maxdegree);
624 adjust2 = adjust2 && (deg2 + 1 <= maxdegree);
629 uves_free_table(&temp);
630 temp = cpl_table_duplicate(tracetable);
634 "X",
"Order",
"Y",
"dY",
642 if (cpl_error_get_code() == CPL_ERROR_SINGULAR_MATRIX)
646 red_chisq1 = DBL_MAX/2;
650 assure( cpl_error_get_code() == CPL_ERROR_NONE,
651 cpl_error_get_code(),
652 "Error fitting orders");
654 check( number_of_orders1 = count_orders(temp),
655 "Error counting orders");
662 uves_free_table(&temp);
663 temp = cpl_table_duplicate(tracetable);
667 "X",
"Order",
"Y",
"dY",
675 if (cpl_error_get_code() == CPL_ERROR_SINGULAR_MATRIX)
679 red_chisq2 = DBL_MAX/2;
683 assure( cpl_error_get_code() == CPL_ERROR_NONE,
684 cpl_error_get_code(),
685 "Error fitting orders");
687 check( number_of_orders2 = count_orders(temp),
688 "Error counting orders");
693 if (adjust1 && adjust2)
695 uves_free_table(&temp);
696 temp = cpl_table_duplicate(tracetable);
700 "X",
"Order",
"Y",
"dY",
708 if (cpl_error_get_code() == CPL_ERROR_SINGULAR_MATRIX)
712 red_chisq3 = DBL_MAX/2;
716 assure( cpl_error_get_code() == CPL_ERROR_NONE,
717 cpl_error_get_code(),
718 "Error fitting orders");
720 check( number_of_orders3 = count_orders(temp),
721 "Error counting orders");
738 if (adjust1 && mse1 >= 0 && (red_chisq - red_chisq1)/red_chisq > 0.1 &&
739 red_chisq1 <= red_chisq2)
743 red_chisq = red_chisq1;
746 if (number_of_orders1 >= number_of_orders)
750 number_of_orders = number_of_orders1;
753 else if (adjust2 && mse2 >= 0 && (red_chisq - red_chisq2)/red_chisq > 0.1 &&
754 red_chisq2 < red_chisq1)
758 red_chisq = red_chisq2;
761 if (number_of_orders2 >= number_of_orders)
765 number_of_orders = number_of_orders2;
768 else if (adjust1 && adjust2 &&
769 mse3 >= 0 && (red_chisq - red_chisq3)/red_chisq > 0.1)
774 red_chisq = red_chisq3;
777 if (number_of_orders3 >= number_of_orders)
781 number_of_orders = number_of_orders3;
793 "Red.chi^2 = %.3f (%d orders)%s",
799 (finished == 1) ?
" *" :
"");
814 "Red.chi^2 = %.3f (%d orders)%s",
820 (finished == 2) ?
" *" :
"");
830 if (adjust1 && adjust2)
835 "Red.chi^2 = %.3f (%d orders)%s",
841 (finished == 3) ?
" *" :
"");
855 new_deg1, new_deg2, finished, *DEFPOL1, *DEFPOL2);
861 }
while (finished != 0);
863 uves_msg_low(
"Using degree (%d, %d)", *DEFPOL1, *DEFPOL2);
870 "X",
"Order",
"Y",
"dY",
873 "Yfit", NULL,
"dYfit_Square",
877 "Error fitting orders");
879 uves_msg(
"RMS error of (%d, %d)-degree fit is %.3f pixels. Reduced chi^2 is %.3f",
889 "is larger than 0.3 pixels", sqrt(mse));
897 uves_msg_warning(
"Reduced chi^2 of fit is greater than 100: %f", red_chisq);
901 check(( cpl_table_duplicate_column(tracetable,
"Residual", tracetable,
"Y"),
902 cpl_table_subtract_columns(tracetable,
"Residual",
"Yfit")),
903 "Error calculating residuals of fit");
907 check( *orders_traced = count_orders(tracetable),
908 "Error counting orders");
910 uves_msg(
"%d order(s) were traced", *orders_traced);
911 if (*orders_traced < N)
917 cpl_table_set_column_unit(tracetable,
"Order",
"");
918 cpl_table_set_column_unit(tracetable,
"X",
"pix");
919 cpl_table_set_column_unit(tracetable,
"Y",
"pix");
920 cpl_table_set_column_unit(tracetable,
"dY",
"pix");
921 cpl_table_set_column_unit(tracetable,
"Residual_Square",
"pix*pix");
923 cpl_table_set_column_unit(tracetable,
"Yfit",
"pix");
924 cpl_table_set_column_unit(tracetable,
"dYfit_Square",
"pix");
925 cpl_table_set_column_unit(tracetable,
"Residual",
"pix");
929 check( uves_plot_table(tracetable,
"X",
"Yfit",
"%d orders detected", *orders_traced),
931 check( uves_plot_table(tracetable,
"X",
"Residual",
932 "Residual of fit (RMS = %.3f pixels; red.chi^2 = %f)",
933 sqrt(mse), red_chisq),
"Plotting failed");
934 check( uves_plot_table(tracetable,
"Y",
"Residual",
935 "Residual of fit (RMS = %.3f pixels; red.chi^2 = %f)",
936 sqrt(mse), red_chisq),
"Plotting failed");
939 uves_free_table(&temp);
940 uves_free_table(&singletrace);
941 if (cpl_error_get_code() != CPL_ERROR_NONE)
943 uves_free_table(&tracetable);
959 count_orders(
const cpl_table *tracetable)
965 passure( tracetable != NULL,
" ");
966 passure( cpl_table_has_column(tracetable,
"Order"),
" ");
968 for (row = 0; row < cpl_table_get_nrow(tracetable); row++)
971 current = cpl_table_get_int(tracetable,
"Order", row, NULL);
972 if (current != previous)
1003 fit_order_linear(cpl_table *singletrace,
1010 cpl_table *temp = NULL;
1014 passure( cpl_table_get_ncol(singletrace) == 3,
"%" CPL_SIZE_FORMAT
"", cpl_table_get_ncol(singletrace));
1015 passure( cpl_table_has_column(singletrace,
"X"),
" ");
1016 passure( cpl_table_has_column(singletrace,
"Y"),
" ");
1017 passure( cpl_table_has_column(singletrace,
"dY"),
" ");
1019 check( temp = cpl_table_duplicate(singletrace),
1020 "Error cloning table");
1022 if (cpl_table_get_nrow(temp) == 1)
1026 check(( cpl_table_set_size(temp, 2),
1027 cpl_table_set_int (temp,
"X", 1, uves_max_int(
1028 cpl_table_get_int (temp,
"X", 0, NULL) - 1, 1)),
1029 cpl_table_set_double(temp,
"Y", 1,
1030 cpl_table_get_double(temp,
"Y", 0, NULL)),
1031 cpl_table_set_double(temp,
"dY", 1,
1032 cpl_table_get_double(temp,
"dY",0, NULL))),
1033 "Could not add point");
1045 "Fitting of order %d failed. You may have to increase value of kappa",
1052 "slope = %f; intersept = %f",
1060 check(( cpl_table_new_column(singletrace,
"Linear fit", CPL_TYPE_DOUBLE),
1061 cpl_table_new_column(singletrace,
"Residual_Square", CPL_TYPE_DOUBLE)),
1062 "Error adding table columns");
1064 for (i = 0; i < cpl_table_get_nrow(singletrace); i++)
1066 int x = cpl_table_get_int (singletrace,
"X", i, NULL);
1067 double y = cpl_table_get_double(singletrace,
"Y", i, NULL);
1069 double linear_fit, residual;
1072 "Error evaluating polynomial");
1074 residual = y - linear_fit;
1076 check(( cpl_table_set_double(singletrace,
"Linear fit", i, linear_fit),
1077 cpl_table_set_double(singletrace,
"Residual_Square",
1078 i, residual*residual)),
1079 "Error updating table");
1084 check(( cpl_table_new_column(singletrace,
"OrderRMS", CPL_TYPE_DOUBLE),
1085 cpl_table_new_column(singletrace,
"OrderSlope", CPL_TYPE_DOUBLE),
1086 cpl_table_fill_column_window_double(
1087 singletrace,
"OrderRMS", 0, cpl_table_get_nrow(singletrace), sqrt(mse)),
1088 cpl_table_fill_column_window_double(
1089 singletrace,
"OrderSlope", 0, cpl_table_get_nrow(singletrace), *slope)),
1090 "Could not create columns OrderRMS and OrderSlope");
1092 passure( cpl_table_get_ncol(singletrace) == 7,
"%" CPL_SIZE_FORMAT
"", cpl_table_get_ncol(singletrace));
1093 passure( cpl_table_has_column(singletrace,
"X"),
" ");
1094 passure( cpl_table_has_column(singletrace,
"Y"),
" ");
1095 passure( cpl_table_has_column(singletrace,
"dY"),
" ");
1096 passure( cpl_table_has_column(singletrace,
"Linear fit"),
" ");
1097 passure( cpl_table_has_column(singletrace,
"Residual_Square"),
" ");
1098 passure( cpl_table_has_column(singletrace,
"OrderRMS"),
" ");
1099 passure( cpl_table_has_column(singletrace,
"OrderSlope"),
" ");
1102 uves_free_table(&temp);
1138 trace_order(
const cpl_table *ordertable,
int order,
1139 const cpl_image *inputimage,
const cpl_image *noise,
1140 const cpl_binary *image_bad,
1144 cpl_table *singletrace = NULL;
1149 double minthreshold;
1157 nx = cpl_image_get_size_x(inputimage);
1159 check(( singletrace =
1160 cpl_table_new(nx/TRACESTEP + 2),
1161 cpl_table_new_column(singletrace,
"X", CPL_TYPE_INT),
1162 cpl_table_new_column(singletrace,
"Y", CPL_TYPE_DOUBLE),
1163 cpl_table_new_column(singletrace,
"dY",CPL_TYPE_DOUBLE),
1165 "Could not initialize tracetable");
1173 check((xcenter = cpl_table_get_int (ordertable,
"Xcenter" , order - 1, NULL),
1174 ycenter = cpl_table_get_int (ordertable,
"Ycenter" , order - 1, NULL),
1175 orderlength = cpl_table_get_int (ordertable,
"OrderLength" , order - 1, NULL),
1176 order_spacing= cpl_table_get_int (ordertable,
"Spacing" , order - 1, NULL),
1177 threshold = cpl_table_get_double(ordertable,
"Threshold" , order - 1, NULL),
1178 minthreshold = cpl_table_get_double(ordertable,
"MinThreshold", order - 1, NULL)),
1179 "Reading order table failed");
1182 threshold = minthreshold;
1191 for (DIRECTION = -1; DIRECTION <= 1; DIRECTION += 2) {
1194 double y = (double) ycenter;
1198 check( slope = cpl_table_get_double(
1199 ordertable,
"Slope", order - 1, NULL),
1200 "Could not read slope from table");
1202 if (xcenter < nx/10 || xcenter > (nx*99)/100) {
1210 while(1 <= x && x <= nx && gap_size < MAXGAP*nx) {
1213 check( found = find_centroid(
1214 inputimage, noise, image_bad, threshold,
1215 order_spacing, x, &y, &dy),
1216 "Could not get order line position");
1222 (y - ycenter)/(x - xcenter) > -1 &&
1223 (y - ycenter)/(x - xcenter) < 1) {
1226 xmax = uves_max_int(xmax, x);
1227 xmin = uves_min_int(xmin, x);
1230 "(%d, %d, %f, %f, %f)",
1231 order, x, y, dy, threshold);
1233 if (!(x == xcenter && DIRECTION == 1))
1240 singletrace,
"X", tracerow, x);
1241 cpl_table_set_double(
1242 singletrace,
"Y", tracerow, y);
1244 cpl_table_set_double(
1245 singletrace,
"dY", tracerow, dy);
1248 cpl_table_set_invalid(
1249 singletrace,
"dY", tracerow);
1258 gap_size += TRACESTEP;
1262 x = x + DIRECTION * TRACESTEP;
1263 y = y + slope*DIRECTION * TRACESTEP;
1265 slope = (y - ycenter)/(x - xcenter);
1273 uves_msg_debug(
"%d points were traced in order %d", tracerow, order);
1276 check( cpl_table_set_size(singletrace, tracerow),
"Could not resize tracetable");
1284 if (cpl_table_has_valid(singletrace,
"dY"))
1287 dy_median = cpl_table_get_column_median(singletrace,
"dY");
1295 cpl_table_select_all(singletrace);
1296 cpl_table_and_selected_invalid(singletrace,
"dY");
1299 for (i = 0; i < cpl_table_get_nrow(singletrace); i++)
1301 if (cpl_table_is_selected(singletrace, i))
1303 cpl_table_set_double(singletrace,
"dY", i, dy_median);
1310 check( uves_sort_table_1(singletrace,
"X",
false),
"Could not sort order table");
1313 if (cpl_error_get_code() != CPL_ERROR_NONE)
1315 uves_free_table(&singletrace);
1336 get_orderlength(
int nx,
int ny, cpl_table *ordertable,
int row)
1338 int x0 = 0, y_0, x1 = 0, y_1;
1339 double intersept, slope;
1341 check(( intersept = cpl_table_get_double(ordertable,
"Intersept", row, NULL),
1342 slope = cpl_table_get_double(ordertable,
"Slope", row, NULL)),
1343 "Could not read line from ordertable");
1347 y_0 = uves_round_double(intersept + slope*x0);
1353 x0 = uves_round_double((y_0 - intersept)/slope);
1358 y_1 = uves_round_double(intersept + slope*nx);
1362 x1 = uves_round_double((y_1 - intersept)/slope);
1385 get_xcenter(
int nx,
int ny, cpl_table *ordertable,
int row)
1387 int x0, y_0, x1, y_1, xc = 0;
1388 double intersept, slope;
1389 check(( intersept = cpl_table_get_double(ordertable,
"Intersept", row, NULL),
1390 slope = cpl_table_get_double(ordertable,
"Slope", row, NULL)),
1391 "Could not read line from ordertable");
1395 y_0 = uves_round_double(intersept + slope*x0);
1401 x0 = uves_round_double((y_0 - intersept)/slope);
1408 y_1 = uves_round_double(intersept + slope*nx);
1414 x1 = uves_round_double((y_1 - intersept)/slope);
1437 get_ycenter(
int nx,
int ny, cpl_table *ordertable,
int row)
1441 check( xc = get_xcenter(nx, ny, ordertable, row),
"Could not find x-center of order");
1443 check( yc = uves_round_double(
1444 cpl_table_get_double(ordertable,
"Slope" , row, NULL)*xc +
1445 cpl_table_get_double(ordertable,
"Intersept", row, NULL)
1446 ),
"Could not read line from ordertable");
1470 estimate_threshold(
const cpl_image *inputimage,
const cpl_image *noise,
1471 cpl_table *ordertable,
int row,
double relative_threshold)
1478 double returnvalue = 0;
1479 cpl_stats *stats = NULL;
1481 passure( inputimage != NULL,
" ");
1482 passure( ordertable != NULL,
" ");
1483 passure( cpl_table_get_int(ordertable,
"Order", row, NULL) == row+1,
"%d %d",
1484 cpl_table_get_int(ordertable,
"Order", row, NULL), row);
1486 check( ny = cpl_image_get_size_y(inputimage),
"Could not read input image dimension");
1488 check( N = cpl_table_get_nrow(ordertable),
"Could not read size of ordertable");
1489 assure(N > 1, CPL_ERROR_ILLEGAL_INPUT,
1490 "Cannot calculate orderspacing with less than 2 (i.e. %d) orders.", N);
1491 check( xc = cpl_table_get_int(ordertable,
"Xcenter", row, NULL),
1492 "Could not read x-center of order #%d", row+1);
1493 check( yc = cpl_table_get_int(ordertable,
"Ycenter", row, NULL),
1494 "Could not find y-center of order #%d", row+1);
1505 cpl_table_get_double(ordertable,
"Slope" , row + 1, NULL)*xc +
1506 cpl_table_get_double(ordertable,
"Intersept", row + 1, NULL),
1507 "Could not read line from ordertable row %d", row + 1);
1509 yupper = (int)((yc + (uves_round_double(ynext)-1))/2);
1517 cpl_table_get_double(ordertable,
"Slope" , row - 1, NULL)*xc +
1518 cpl_table_get_double(ordertable,
"Intersept", row - 1, NULL),
1519 "Could not read line from ordertable row %d", row - 1);
1521 ylower = (int)((yc + uves_round_double(yprev)-1)/2);
1529 yupper = yc + (yc - ylower);
1533 ylower = yc - (yupper - yc);
1535 yupper = uves_min_int(uves_max_int(yupper, 1), ny);
1536 ylower = uves_min_int(uves_max_int(ylower, 1), ny);
1542 assure(yupper > ylower, CPL_ERROR_ILLEGAL_INPUT,
1543 "Initially detected order lines intersept!");
1549 double noise_level = 0;
1552 check( stats = cpl_stats_new_from_image_window(
1554 CPL_STATS_MIN | CPL_STATS_MAX | CPL_STATS_MINPOS,
1557 "Could not get statistics on image sub-window (%d,%d)-(%d,%d)",
1558 xc, ylower, xc, yupper);
1560 check(( minval = cpl_stats_get_min(stats),
1561 maxval = cpl_stats_get_max(stats)),
1562 "Could not get minimum and maximum pixel values");
1566 int xpos, ypos, pis_rejected;
1567 xpos = cpl_stats_get_min_x(stats);
1568 ypos = cpl_stats_get_min_y(stats);
1569 noise_level = cpl_image_get(noise, xpos, ypos, &pis_rejected);
1573 returnvalue = uves_max_double(minval + relative_threshold * (maxval - minval),
1574 (minval + noise_level) + noise_level);
1576 uves_msg_debug(
"Order: %d \tThreshold: %f \tMinimum: %f \tMaximum: %f"
1577 " \tNoise: %f \tWindow: (%d, %d)-(%d, %d)",
1578 row+1, returnvalue, minval, maxval, noise_level, xc, ylower, xc, yupper);
1582 uves_free_stats(&stats);
1611 find_centroid(
const cpl_image *inputimage,
const cpl_image *noise,
1612 const cpl_binary *image_bad,
1613 double threshold,
int spacing,
int x,
double *yguess,
double *dY)
1615 bool returnvalue =
true;
1619 double thisvalue = 0;
1623 cpl_matrix *covariance = NULL;
1625 passure( inputimage != NULL,
" ");
1627 nx = cpl_image_get_size_x(inputimage);
1628 ny = cpl_image_get_size_y(inputimage);
1630 passure( 1 <= x && x <= nx,
"%d %d", x, nx);
1632 uves_msg_debug(
"Order location estimate = (%d, %f)", x, *yguess);
1636 y = uves_round_double(*yguess);
1637 if (y < 1 || y > ny)
1639 returnvalue =
false;
1646 thisvalue = cpl_image_get(inputimage, x, y , &pis_rejected);
1649 double uppervalue = cpl_image_get(inputimage, x, y + 1, &pis_rejected);
1650 if (!pis_rejected && uppervalue > thisvalue)
1659 double lowervalue = cpl_image_get(inputimage, x, y - 1, &pis_rejected);
1660 if (!pis_rejected && lowervalue > thisvalue)
1671 uves_msg_debug(
"Local maximum at (%d, %d) (value = %f)\tthreshold = %f",
1672 x, y, thisvalue, threshold);
1675 if (thisvalue < threshold)
1677 uves_msg_debug(
"Order not traced at (%d, %d) (value = %f)\tthreshold = %f",
1678 x, y, thisvalue, threshold);
1679 returnvalue =
false;
1687 double mse, rms, chi_sq;
1692 minvalue = 0.5*thisvalue;
1695 while(y > 1 && cpl_image_get(inputimage, x, y - 1, &pis_rejected) >= minvalue)
1700 assure( cpl_error_get_code() == CPL_ERROR_NONE,
1701 cpl_error_get_code(),
"Could not read pixel from input image" );
1707 while(y < ny && cpl_image_get(inputimage, x, y + 1, &pis_rejected) >= minvalue)
1712 assure( cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(),
1713 "Could not read pixel from input image" );
1724 for (y = ylow; y <= yhigh; y++)
1727 flux = cpl_image_get(inputimage, x, y, &pis_rejected) - minvalue;
1728 if (!pis_rejected && flux > 0)
1731 sumy += flux * (y - *yguess*0);
1732 sumy2 += flux * (y - *yguess*0) * (y - *yguess*0);
1737 *yguess = *yguess*0 + sumy / sum;
1738 sigmaY = sqrt( sumy2 / sum - sumy*sumy/(sum*sum) );
1740 if ( sumy2 / sum - sumy*sumy/(sum*sum) < 0 ||
1741 sigmaY < sqrt(1.0/12) )
1747 sigmaY = sqrt(1.0/12);
1752 *dY = sigmaY/sqrt(sum);
1768 ylow = uves_max_int(1 , uves_round_double(*yguess - spacing/3));
1769 yhigh = uves_min_int(ny, uves_round_double(*yguess + spacing/3));
1771 assure( yhigh - ylow >= 1, CPL_ERROR_ILLEGAL_INPUT,
1772 "Estimated spacing too small: %d pixel(s)", spacing);
1775 uves_fit_1d_image(inputimage, noise,
1777 false,
false,
false,
1779 yguess, &sigmaY, &norm, &background, NULL,
1780 &mse, &chi_sq, &covariance,
1784 if (cpl_error_get_code() == CPL_ERROR_NONE)
1787 *dY = sqrt(cpl_matrix_get(covariance, 0, 0));
1789 else if (cpl_error_get_code() == CPL_ERROR_CONTINUE)
1794 "using centroid", x, *yguess);
1795 *dY = sigmaY / sqrt(norm);
1797 else if (cpl_error_get_code() == CPL_ERROR_SINGULAR_MATRIX)
1803 *dY = sigmaY / sqrt(norm);
1806 assure(cpl_error_get_code() == CPL_ERROR_NONE,
1807 cpl_error_get_code(),
"Gaussian fitting failed");
1811 uves_msg_debug(
"dy = %f sigma/sqrt(N) = %f", *dY, sigmaY/(norm));
1815 if ( norm > 10 * rms)
1819 if ( norm < 2 * rms)
1821 returnvalue =
false;
1829 cpl_matrix_delete(covariance);
void uves_polynomial_delete(polynomial **p)
Delete a polynomial.
#define uves_msg_warning(...)
Print an warning message.
#define passure(BOOL,...)
int uves_gauss_derivative(const double x[], const double a[], double result[])
Evaluate the derivatives of a gaussian.
cpl_table * uves_locate_orders(const cpl_image *inputimage, const cpl_image *noise, cpl_table *ordertable, int TRACESTEP, double MINTHRESH, double MAXGAP, double MAXRMS, int *DEFPOL1, int *DEFPOL2, double KAPPA, polynomial **bivariate_fit, int *orders_traced)
Trace all orders.
#define uves_msg(...)
Print a message on 'info' or 'debug' level.
int uves_gauss(const double x[], const double a[], double *result)
Evaluate a gaussian.
polynomial * uves_polynomial_regression_2d(cpl_table *t, const char *X1, const char *X2, const char *Y, const char *sigmaY, int degree1, int degree2, const char *polynomial_fit, const char *residual_square, const char *variance_fit, double *mse, double *red_chisq, polynomial **variance, double kappa, double min_reject)
Fit a 2d polynomial to three table columns.
static double xcenter(const cpl_image *image, const cpl_image *noise, int xlo, int xhi, int row, centering_method CENTERING_METHOD, int bin_disp, double *sigma, double *intensity, double *dx0, double *slope, double *background)
Refine the center position of an initially detected emission line.
double uves_polynomial_evaluate_1d(const polynomial *p, double x)
Evaluate a 1d polynomial.
double uves_polynomial_get_coeff_1d(const polynomial *p, int degree)
Get a coefficient of a 1D polynomial.
polynomial * uves_polynomial_regression_1d(cpl_table *t, const char *X, const char *Y, const char *sigmaY, int degree, const char *polynomial_fit, const char *residual_square, double *mean_squared_error, double kappa)
Fit a 1d polynomial to two table columns.
#define uves_error_reset()
#define uves_msg_low(...)
Print a message on a lower message level.
#define uves_msg_debug(...)
Print a debug message.
#define assure_nomsg(BOOL, CODE)