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() );
241 if (cpl_error_get_code() != CPL_ERROR_NONE)
243 er_msg = uves_sprintf(
"%s", cpl_error_get_message());
246 uves_msg_warning(
"Could not make global fit of absolute order number (%s). "
247 "Polynomial is not updated",
259 cpl_table_add_scalar(linetable,
"Ynew", + offset);
264 uves_sort_table_2(linetable,
"Order",
"X",
false,
false);
268 check( shift = calculate_shift(guess, linetable,
"X",
"Order",
269 CORREL_RANGE, CORREL_STEP, CORREL_TOLERANCE),
270 "Could not calculate shift of position w.r.t. guess solution");
279 check( initial_dispersion = apply_shift(guess, shift, DEGREE, &mse),
280 "Could not calculate initial dispersion relation");
285 if(mse > MAXERROR*MAXERROR)
288 "than tolerance (%f pixels)", sqrt(mse), MAXERROR);
292 uves_free_string_const(&er_msg);
294 if (cpl_error_get_code() != CPL_ERROR_NONE)
299 return initial_dispersion;
319 apply_shift(
const cpl_table *guess,
double shift,
int degree,
double *mse)
325 check( t = cpl_table_duplicate(guess),
326 "Error duplicating table");
329 check(( cpl_table_duplicate_column(t,
"ident_order", t,
"Ident"),
330 cpl_table_multiply_columns(t,
"ident_order",
"Order")),
332 "Error creating auxillary column");
335 check( cpl_table_add_scalar(t,
"X", shift),
"Error shifting column 'X'");
346 if (cpl_error_get_code() != CPL_ERROR_NONE)
350 assure(
false, CPL_ERROR_SINGULAR_MATRIX,
351 "Polynomial fitting failed");
385 calculate_shift(
const cpl_table *linetable,
const cpl_table *guess,
const char *column,
386 const char *reference_column,
double range,
double step,
double tolerance)
389 int minorder, maxorder;
391 double shift, max_corr, median_corr, maxpos = 0;
392 cpl_table *temp = NULL;
394 assure( cpl_table_has_column(linetable, column),
395 CPL_ERROR_ILLEGAL_INPUT,
"Table has no '%s' column", column);
396 assure( cpl_table_has_column(guess , column),
397 CPL_ERROR_ILLEGAL_INPUT,
"Table has no '%s' column", column);
398 assure( cpl_table_has_column(linetable, reference_column),
399 CPL_ERROR_ILLEGAL_INPUT,
"Table has no '%s' column", reference_column);
400 assure( cpl_table_has_column(guess , reference_column),
401 CPL_ERROR_ILLEGAL_INPUT,
"Table has no '%s' column", reference_column);
402 assure( range > 0, CPL_ERROR_ILLEGAL_INPUT,
"Range = %f", range);
404 t = cpl_table_get_column_type(linetable, column);
405 assure( t == CPL_TYPE_DOUBLE, CPL_ERROR_TYPE_MISMATCH,
408 t = cpl_table_get_column_type(guess, column);
409 assure( t == CPL_TYPE_DOUBLE, CPL_ERROR_TYPE_MISMATCH,
412 t = cpl_table_get_column_type(linetable, reference_column);
413 assure( t == CPL_TYPE_INT, CPL_ERROR_TYPE_MISMATCH,
414 "Ref. column '%s' has type '%s'. Integer expected",
417 t = cpl_table_get_column_type(guess, reference_column);
418 assure( t == CPL_TYPE_INT, CPL_ERROR_TYPE_MISMATCH,
419 "Ref. column '%s' has type '%s'. Integer expected",
424 uves_max_int(cpl_table_get_column_min(guess, reference_column),
425 cpl_table_get_column_min(linetable, reference_column)),
427 uves_min_int(cpl_table_get_column_max(guess, reference_column),
428 cpl_table_get_column_max(linetable, reference_column))),
429 "Error reading column '%s'", reference_column);
431 assure(maxorder >= minorder, CPL_ERROR_ILLEGAL_INPUT,
"No common orders found");
433 uves_msg(
"Min/max common absolute orders = %d - %d", minorder, maxorder);
444 for (shift = -range; shift <= range; shift += step)
449 temp = cpl_table_new(N);
450 cpl_table_new_column(temp,
"Corr", CPL_TYPE_DOUBLE);
454 for (shift = -range, i = 0;
459 check( corr = cross_correlation(shift, linetable, guess, column,
460 reference_column, minorder, maxorder, tolerance),
461 "Error calculating spectrum cross correlation for shift = %f pixel(s)",
465 check( cpl_table_set_double(temp,
"Corr", i, corr),
466 "Error updating table");
482 median_corr = cpl_table_get_column_median(temp,
"Corr");
485 if (median_corr < 0.5)
490 uves_msg(
"Estimated shift compared to guess solution is %f pixels (%.2f sigma detection)",
491 maxpos, max_corr / median_corr);
497 if (max_corr / median_corr < 10)
500 "only %f times no correlation (usually >30). "
501 "Make sure that the guess solution is within ~10 pixels "
502 "of the real dispersion relation; otherwise the following "
503 "wavelength calibration is likely to fail or converge "
504 "to a wrong solution",
505 max_corr / median_corr);
509 uves_free_table(&temp);
537 cross_correlation(
double shift,
538 const cpl_table *t1,
const cpl_table *t2,
539 const char *column,
const char* reference_column,
540 int minref,
int maxref,
double tolerance)
547 const double *col1 = cpl_table_get_data_double_const(t1, column);
548 const double *col2 = cpl_table_get_data_double_const(t2, column);
549 const int *ref1 = cpl_table_get_data_int_const(t1, reference_column);
550 const int *ref2 = cpl_table_get_data_int_const(t2, reference_column);
552 int N1 = cpl_table_get_nrow(t1);
553 int N2 = cpl_table_get_nrow(t2);
555 assure( cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(),
556 "Error reading input table");
559 while (i1 < N1 && ref1[i1] <= maxref &&
560 i2 < N2 && ref2[i2] <= maxref) {
561 if (i1 < minref || ref1[i1] < ref2[i2])
563 else if (i2 < minref || ref1[i1] > ref2[i2])
567 double difference = col2[i2] - (col1[i1] + shift);
569 if (difference > tolerance)
573 else if (difference < -tolerance)
613 write_physical_order(cpl_table *linetable,
const polynomial *absolute_order,
614 const cpl_table *ordertable,
616 int *first_abs_order,
int *last_abs_order)
618 int *relative_order = NULL;
619 int *physical_order = NULL;
620 int minorder, maxorder;
622 cpl_table *temp = NULL;
630 check( cpl_table_new_column(linetable,
"Order", CPL_TYPE_INT),
631 "Error creating column");
633 check( cpl_table_new_column(linetable,
"AbsOrder", CPL_TYPE_DOUBLE),
634 "Error creating column");
636 check(( minorder = cpl_table_get_column_min(ordertable,
"Order"),
637 maxorder = cpl_table_get_column_max(ordertable,
"Order")),
638 "Could not read min. and max. order numbers");
640 assure( minorder > 0, CPL_ERROR_ILLEGAL_INPUT,
641 "Non-positive order number (%d) in linetable", minorder);
643 physical_order = cpl_calloc(maxorder + 1,
sizeof(
int));
648 for (i = 0; i < cpl_table_get_nrow(linetable); i++) {
653 order = cpl_table_get_int (linetable,
"Y", i, NULL);
656 x = cpl_table_get_double(linetable,
"X", i, NULL);
665 cpl_table_set_double(linetable,
"AbsOrder", i, absorder);
677 "Y",
"AbsOrder", NULL,
679 NULL, NULL, NULL, -1));
681 relorder_median = uves_round_double(cpl_table_get_column_median(linetable,
"Y"));
691 coeff1 = absorder_median - coeff2 * relorder_median;
693 uves_msg_debug(
"Assuming relation: abs.order = %d + (%d) * rel.order",
697 for (order = minorder; order <= maxorder; order++) {
698 physical_order[order] = coeff1 + coeff2 * order;
700 assure(physical_order[order] > 0, CPL_ERROR_ILLEGAL_OUTPUT,
701 "Estimated physical order number is non-positive (%d)",
702 physical_order[order]);
704 if (physical_order[order] > maxphysical)
706 maxphysical = physical_order[order];
709 uves_msg_debug(
"Mapping relative order #%d to absolute order #%d",
710 order, physical_order[order]);
714 *first_abs_order = physical_order[minorder];
715 *last_abs_order = physical_order[maxorder];
717 passure( *first_abs_order - *last_abs_order == coeff2*(minorder - maxorder),
719 *first_abs_order, *last_abs_order, coeff2, minorder, maxorder);
724 for (i = 0; i < cpl_table_get_nrow(linetable); i++) {
726 order = cpl_table_get_int (linetable,
"Y", i, NULL);
727 cpl_table_set_int(linetable,
"Order", i, physical_order[order]);
731 relative_order = cpl_calloc(maxphysical + 1,
sizeof(
int));
732 for (i = 0; i <= maxorder; i++)
734 relative_order[physical_order[i]] = i;
738 uves_free_table(&temp);
741 cpl_free(physical_order);
744 return relative_order;