102 #include <uves_wavecal_firstsolution.h>
104 #include <uves_utils.h>
105 #include <uves_utils_wrappers.h>
106 #include <uves_dump.h>
107 #include <uves_error.h>
108 #include <uves_msg.h>
115 write_physical_order(cpl_table *linetable,
117 const cpl_table *ordertable,
119 int *first_abs_order,
int *last_abs_order);
122 calculate_shift(
const cpl_table *linetable,
const cpl_table *previous,
123 const char *column,
const char *reference_column,
124 double range,
double step,
double tolerance);
127 cross_correlation(
double shift,
128 const cpl_table *t1,
const cpl_table *t2,
129 const char *column,
const char* reference_column,
130 int minref,
int maxref,
double tolerance);
132 static polynomial *apply_shift(
const cpl_table *previous,
133 const double shift,
const int degree,
double *mse);
184 uves_wavecal_firstsolution(cpl_table *linetable,
185 const cpl_table *guess,
187 const cpl_table *ordertable,
191 int **relative_order,
192 int DEGREE,
double CORREL_RANGE,
double CORREL_STEP,
193 double CORREL_TOLERANCE,
double MAXERROR,
194 int *first_abs_order,
int *last_abs_order)
198 const char *er_msg = NULL;
203 check( *relative_order = write_physical_order(linetable, *absolute_order,
208 "Could not calculate absolute order numbers");
215 cpl_table_new_column(linetable,
"Ynew", CPL_TYPE_DOUBLE);
216 for (row = 0; row < cpl_table_get_nrow(linetable); row++)
221 int order = cpl_table_get_int (linetable,
"Y", row, NULL);
222 double x = cpl_table_get_double(linetable,
"X", row, NULL);
224 cpl_table_set_double(
225 linetable,
"Ynew", row,
230 cpl_error_get_code() );
240 cpl_table_set_column_unit(linetable,
"X",
"pix");
241 cpl_table_set_column_unit(linetable,
"Ynew",
"pix");
242 cpl_table_set_column_unit(linetable,
"Order",
" ");
244 if (cpl_error_get_code() != CPL_ERROR_NONE)
246 er_msg = uves_sprintf(
"%s", cpl_error_get_message());
249 uves_msg_warning(
"Could not make global fit of absolute order number (%s). "
250 "Polynomial is not updated",
262 cpl_table_add_scalar(linetable,
"Ynew", + offset);
267 uves_sort_table_2(linetable,
"Order",
"X",
false,
false);
271 check( shift = calculate_shift(guess, linetable,
"X",
"Order",
272 CORREL_RANGE, CORREL_STEP, CORREL_TOLERANCE),
273 "Could not calculate shift of position w.r.t. guess solution");
282 check( initial_dispersion = apply_shift(guess, shift, DEGREE, &mse),
283 "Could not calculate initial dispersion relation");
288 if(mse > MAXERROR*MAXERROR)
291 "than tolerance (%f pixels)", sqrt(mse), MAXERROR);
295 uves_free_string_const(&er_msg);
297 if (cpl_error_get_code() != CPL_ERROR_NONE)
302 return initial_dispersion;
322 apply_shift(
const cpl_table *guess,
double shift,
int degree,
double *mse)
328 check( t = cpl_table_duplicate(guess),
329 "Error duplicating table");
332 check(( cpl_table_duplicate_column(t,
"ident_order", t,
"Ident"),
333 cpl_table_multiply_columns(t,
"ident_order",
"Order")),
335 "Error creating auxillary column");
338 check( cpl_table_add_scalar(t,
"X", shift),
"Error shifting column 'X'");
349 if (cpl_error_get_code() != CPL_ERROR_NONE)
353 assure(
false, CPL_ERROR_SINGULAR_MATRIX,
354 "Polynomial fitting failed");
388 calculate_shift(
const cpl_table *linetable,
const cpl_table *guess,
const char *column,
389 const char *reference_column,
double range,
double step,
double tolerance)
392 int minorder, maxorder;
394 double shift, max_corr, median_corr, maxpos = 0;
395 cpl_table *temp = NULL;
397 assure( cpl_table_has_column(linetable, column),
398 CPL_ERROR_ILLEGAL_INPUT,
"Table has no '%s' column", column);
399 assure( cpl_table_has_column(guess , column),
400 CPL_ERROR_ILLEGAL_INPUT,
"Table has no '%s' column", column);
401 assure( cpl_table_has_column(linetable, reference_column),
402 CPL_ERROR_ILLEGAL_INPUT,
"Table has no '%s' column", reference_column);
403 assure( cpl_table_has_column(guess , reference_column),
404 CPL_ERROR_ILLEGAL_INPUT,
"Table has no '%s' column", reference_column);
405 assure( range > 0, CPL_ERROR_ILLEGAL_INPUT,
"Range = %f", range);
407 t = cpl_table_get_column_type(linetable, column);
408 assure( t == CPL_TYPE_DOUBLE, CPL_ERROR_TYPE_MISMATCH,
411 t = cpl_table_get_column_type(guess, column);
412 assure( t == CPL_TYPE_DOUBLE, CPL_ERROR_TYPE_MISMATCH,
415 t = cpl_table_get_column_type(linetable, reference_column);
416 assure( t == CPL_TYPE_INT, CPL_ERROR_TYPE_MISMATCH,
417 "Ref. column '%s' has type '%s'. Integer expected",
420 t = cpl_table_get_column_type(guess, reference_column);
421 assure( t == CPL_TYPE_INT, CPL_ERROR_TYPE_MISMATCH,
422 "Ref. column '%s' has type '%s'. Integer expected",
427 uves_max_int(cpl_table_get_column_min(guess, reference_column),
428 cpl_table_get_column_min(linetable, reference_column)),
430 uves_min_int(cpl_table_get_column_max(guess, reference_column),
431 cpl_table_get_column_max(linetable, reference_column))),
432 "Error reading column '%s'", reference_column);
434 assure(maxorder >= minorder, CPL_ERROR_ILLEGAL_INPUT,
"No common orders found");
436 uves_msg(
"Min/max common absolute orders = %d - %d", minorder, maxorder);
447 for (shift = -range; shift <= range; shift += step)
452 temp = cpl_table_new(N);
453 cpl_table_new_column(temp,
"Corr", CPL_TYPE_DOUBLE);
457 for (shift = -range, i = 0;
462 check( corr = cross_correlation(shift, linetable, guess, column,
463 reference_column, minorder, maxorder, tolerance),
464 "Error calculating spectrum cross correlation for shift = %f pixel(s)",
468 check( cpl_table_set_double(temp,
"Corr", i, corr),
469 "Error updating table");
485 median_corr = cpl_table_get_column_median(temp,
"Corr");
488 if (median_corr < 0.5)
493 uves_msg(
"Estimated shift compared to guess solution is %f pixels (%.2f sigma detection)",
494 maxpos, max_corr / median_corr);
500 if (max_corr / median_corr < 10)
503 "only %f times no correlation (usually >30). "
504 "Make sure that the guess solution is within ~10 pixels "
505 "of the real dispersion relation; otherwise the following "
506 "wavelength calibration is likely to fail or converge "
507 "to a wrong solution",
508 max_corr / median_corr);
512 uves_free_table(&temp);
540 cross_correlation(
double shift,
541 const cpl_table *t1,
const cpl_table *t2,
542 const char *column,
const char* reference_column,
543 int minref,
int maxref,
double tolerance)
550 const double *col1 = cpl_table_get_data_double_const(t1, column);
551 const double *col2 = cpl_table_get_data_double_const(t2, column);
552 const int *ref1 = cpl_table_get_data_int_const(t1, reference_column);
553 const int *ref2 = cpl_table_get_data_int_const(t2, reference_column);
555 int N1 = cpl_table_get_nrow(t1);
556 int N2 = cpl_table_get_nrow(t2);
558 assure( cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(),
559 "Error reading input table");
562 while (i1 < N1 && ref1[i1] <= maxref &&
563 i2 < N2 && ref2[i2] <= maxref) {
564 if (i1 < minref || ref1[i1] < ref2[i2])
566 else if (i2 < minref || ref1[i1] > ref2[i2])
570 double difference = col2[i2] - (col1[i1] + shift);
572 if (difference > tolerance)
576 else if (difference < -tolerance)
616 write_physical_order(cpl_table *linetable,
const polynomial *absolute_order,
617 const cpl_table *ordertable,
619 int *first_abs_order,
int *last_abs_order)
621 int *relative_order = NULL;
622 int *physical_order = NULL;
623 int minorder, maxorder;
625 cpl_table *temp = NULL;
633 check( cpl_table_new_column(linetable,
"Order", CPL_TYPE_INT),
634 "Error creating column");
636 check( cpl_table_new_column(linetable,
"AbsOrder", CPL_TYPE_DOUBLE),
637 "Error creating column");
639 check(( minorder = cpl_table_get_column_min(ordertable,
"Order"),
640 maxorder = cpl_table_get_column_max(ordertable,
"Order")),
641 "Could not read min. and max. order numbers");
643 assure( minorder > 0, CPL_ERROR_ILLEGAL_INPUT,
644 "Non-positive order number (%d) in linetable", minorder);
646 physical_order = cpl_calloc(maxorder + 1,
sizeof(
int));
651 for (i = 0; i < cpl_table_get_nrow(linetable); i++) {
656 order = cpl_table_get_int (linetable,
"Y", i, NULL);
659 x = cpl_table_get_double(linetable,
"X", i, NULL);
668 cpl_table_set_double(linetable,
"AbsOrder", i, absorder);
680 "Y",
"AbsOrder", NULL,
682 NULL, NULL, NULL, -1));
684 relorder_median = uves_round_double(cpl_table_get_column_median(linetable,
"Y"));
694 coeff1 = absorder_median - coeff2 * relorder_median;
696 uves_msg_debug(
"Assuming relation: abs.order = %d + (%d) * rel.order",
700 for (order = minorder; order <= maxorder; order++) {
701 physical_order[order] = coeff1 + coeff2 * order;
703 assure(physical_order[order] > 0, CPL_ERROR_ILLEGAL_OUTPUT,
704 "Estimated physical order number is non-positive (%d)",
705 physical_order[order]);
707 if (physical_order[order] > maxphysical)
709 maxphysical = physical_order[order];
712 uves_msg_debug(
"Mapping relative order #%d to absolute order #%d",
713 order, physical_order[order]);
717 *first_abs_order = physical_order[minorder];
718 *last_abs_order = physical_order[maxorder];
720 passure( *first_abs_order - *last_abs_order == coeff2*(minorder - maxorder),
722 *first_abs_order, *last_abs_order, coeff2, minorder, maxorder);
727 for (i = 0; i < cpl_table_get_nrow(linetable); i++) {
729 order = cpl_table_get_int (linetable,
"Y", i, NULL);
730 cpl_table_set_int(linetable,
"Order", i, physical_order[order]);
734 relative_order = cpl_calloc(maxphysical + 1,
sizeof(
int));
735 for (i = 0; i <= maxorder; i++)
737 relative_order[physical_order[i]] = i;
741 uves_free_table(&temp);
744 cpl_free(physical_order);
747 return relative_order;
double uves_polynomial_derivative_1d(const polynomial *p, double x)
Evaluate the derivative of a 1d polynomial.
void uves_polynomial_delete(polynomial **p)
Delete a polynomial.
#define uves_msg_warning(...)
Print an warning message.
#define passure(BOOL,...)
#define uves_msg(...)
Print a message on 'info' or 'debug' level.
polynomial * uves_polynomial_duplicate(const polynomial *p)
Copy a polynomial.
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.
void uves_polynomial_delete_const(const polynomial **p)
Delete a const polynomial.
double uves_polynomial_evaluate_2d(const polynomial *p, double x1, double x2)
Evaluate a 2d polynomial.
double uves_polynomial_evaluate_1d(const polynomial *p, double x)
Evaluate 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.
const char * uves_tostring_cpl_type(cpl_type t)
Convert a CPL type to a string.
#define uves_error_reset()
#define uves_msg_debug(...)
Print a debug message.
#define assure_nomsg(BOOL, CODE)