00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00168
00171 #ifdef HAVE_CONFIG_H
00172 # include <config.h>
00173 #endif
00174
00175 #include <uves_orderpos_follow.h>
00176
00177 #include <uves_plot.h>
00178 #include <uves_utils.h>
00179 #include <uves_utils_wrappers.h>
00180 #include <uves_error.h>
00181 #include <uves_msg.h>
00182
00183 #include <cpl.h>
00184 #include <math.h>
00185 #include <float.h>
00186
00187 static cpl_table * trace_order(const cpl_table *ordertable, int order,
00188 const cpl_image *inputimage, const cpl_image *noise,
00189 const cpl_binary *image_bad,
00190 int TRACESTEP,
00191 double MAXGAP);
00192 static int count_orders(const cpl_table *tracetable);
00193 static double fit_order_linear(cpl_table *singletrace, int order, double KAPPA,
00194 double *slope);
00195 static int get_xcenter(int nx, int ny, cpl_table *ordertab, int row);
00196 static int get_ycenter(int nx, int ny, cpl_table *ordertab, int row);
00197 static int get_orderlength(int nx, int ny, cpl_table *ordertab, int row);
00198 static double estimate_threshold(const cpl_image *inputimage,
00199 const cpl_image *nosie,
00200 cpl_table *ordertable,
00201 int row, double relative_threshold);
00202 static bool find_centroid(const cpl_image *inputimage,
00203 const cpl_image *noise,
00204 const cpl_binary *image_bad,
00205 double threshold, int spacing, int x, double *yguess,
00206 double *dY);
00207
00208
00248
00249 cpl_table *
00250 uves_locate_orders(const cpl_image *inputimage,
00251 const cpl_image *noise,
00252 cpl_table *ordertable,
00253 int TRACESTEP,
00254 double MINTHRESH,
00255 double MAXGAP,
00256 double MAXRMS,
00257 int *DEFPOL1,
00258 int *DEFPOL2,
00259 double KAPPA,
00260 polynomial **bivariate_fit,
00261 int *orders_traced)
00262 {
00263 cpl_table *tracetable = NULL;
00264 cpl_table *singletrace = NULL;
00265 cpl_table *temp = NULL;
00266 const cpl_mask *image_badmap = NULL;
00267 const cpl_binary *image_bad = NULL;
00268 int N;
00269
00270 double mse, red_chisq;
00271 int order;
00272
00273
00274 assure_nomsg( inputimage != NULL, CPL_ERROR_NULL_INPUT);
00275 assure_nomsg( noise != NULL, CPL_ERROR_NULL_INPUT);
00276 assure( cpl_image_get_size_x(inputimage) == cpl_image_get_size_x(noise) &&
00277 cpl_image_get_size_y(inputimage) == cpl_image_get_size_y(noise),
00278 CPL_ERROR_INCOMPATIBLE_INPUT,
00279 "Image sizes are %dx%d and %dx%d",
00280 cpl_image_get_size_x(inputimage), cpl_image_get_size_x(noise),
00281 cpl_image_get_size_y(inputimage), cpl_image_get_size_y(noise));
00282
00283 assure_nomsg( ordertable != NULL, CPL_ERROR_NULL_INPUT);
00284 assure( cpl_table_get_ncol(ordertable) == 4,
00285 CPL_ERROR_ILLEGAL_INPUT,
00286 "%d columns found. 4 expected",
00287 cpl_table_get_ncol(ordertable));
00288 assure( cpl_table_has_column(ordertable, "Intersept"),
00289 CPL_ERROR_DATA_NOT_FOUND,
00290 "Missing column Intersept");
00291 assure( cpl_table_has_column(ordertable, "Slope"),
00292 CPL_ERROR_DATA_NOT_FOUND,
00293 "Missing column Slope");
00294 assure( cpl_table_has_column(ordertable, "Order"),
00295 CPL_ERROR_DATA_NOT_FOUND,
00296 "Missing column Order");
00297 assure( cpl_table_has_column(ordertable, "Spacing"),
00298 CPL_ERROR_DATA_NOT_FOUND,
00299 "Missing column Spacing");
00300 assure_nomsg( DEFPOL1 != NULL, CPL_ERROR_NULL_INPUT );
00301 assure_nomsg( DEFPOL2 != NULL, CPL_ERROR_NULL_INPUT );
00302
00303 image_badmap = cpl_image_get_bpm_const(inputimage);
00304 image_bad = cpl_mask_get_data_const(image_badmap);
00305
00306 N = cpl_table_get_nrow(ordertable);
00307
00308 *bivariate_fit = NULL;
00309
00310
00311 check(( tracetable = cpl_table_new(0),
00312 cpl_table_new_column(tracetable, "Order" , CPL_TYPE_INT),
00313 cpl_table_new_column(tracetable, "X" , CPL_TYPE_INT),
00314 cpl_table_new_column(tracetable, "Y" , CPL_TYPE_DOUBLE),
00315 cpl_table_new_column(tracetable, "dY" , CPL_TYPE_DOUBLE),
00316 cpl_table_new_column(tracetable, "Residual_Square", CPL_TYPE_DOUBLE),
00317 cpl_table_new_column(tracetable, "OrderRMS" , CPL_TYPE_DOUBLE),
00318 cpl_table_new_column(tracetable, "OrderSlope" , CPL_TYPE_DOUBLE)),
00319
00320 "Could not initialize order trace table");
00321
00322
00323 check(( cpl_table_new_column(ordertable, "Xcenter", CPL_TYPE_INT),
00324 cpl_table_new_column(ordertable, "Ycenter", CPL_TYPE_INT),
00325 cpl_table_new_column(ordertable, "OrderLength", CPL_TYPE_INT),
00326 cpl_table_new_column(ordertable, "Threshold", CPL_TYPE_DOUBLE),
00327 cpl_table_new_column(ordertable, "MinThreshold", CPL_TYPE_DOUBLE),
00328 cpl_table_new_column(ordertable, "RMS", CPL_TYPE_DOUBLE),
00329 cpl_table_new_column(ordertable, "TraceSlope", CPL_TYPE_DOUBLE)),
00330 "Could not add columns to order table");
00331
00332 *orders_traced = 0;
00333
00334
00335 for (order = 1; order <= N; order++)
00336 {
00337
00338 int nx = cpl_image_get_size_x(inputimage);
00339 int ny = cpl_image_get_size_y(inputimage);
00340 int points_traced = 0;
00341 int xc = get_xcenter (nx, ny, ordertable, order - 1);
00342 int yc = get_ycenter (nx, ny, ordertable, order - 1);
00343
00344 check(( cpl_table_set_int(ordertable, "Xcenter" , order - 1, xc),
00345
00346 cpl_table_set_int(ordertable, "Ycenter" , order - 1, yc),
00347 cpl_table_set_int(ordertable, "OrderLength" , order - 1,
00348 get_orderlength (nx, ny, ordertable, order - 1))),
00349 "Could not calculate order line geometry");
00350
00351 if (!(1 <= xc && xc <= nx && 1 <= yc && yc <= ny))
00352 {
00353 uves_msg_warning("Order %d: Center of order (%d, %d) is outside image "
00354 "(intersept = %.2f, slope = %f)",
00355 order, xc, yc,
00356 cpl_table_get_double(ordertable, "Intersept", order-1, NULL),
00357 cpl_table_get_double(ordertable, "Slope", order-1, NULL));
00358 }
00359 else
00360 {
00361 check( cpl_table_set_double(
00362 ordertable, "Threshold" , order - 1,
00363 estimate_threshold(inputimage, noise, ordertable, order - 1, -1)),
00364 "Could not calculate max. threshold");
00365 check( cpl_table_set_double(
00366 ordertable, "MinThreshold", order - 1,
00367 estimate_threshold(inputimage, noise, ordertable, order - 1, MINTHRESH)),
00368 "Could not calculate min. threshold");
00369 }
00370
00371
00372 uves_free_table(&singletrace);
00373 check( singletrace = trace_order(ordertable,
00374 order,
00375 inputimage,
00376 noise,
00377 image_bad,
00378 TRACESTEP,
00379 MAXGAP),
00380 "Error occured while tracing order #%d", order);
00381
00382 check( points_traced = cpl_table_get_nrow(singletrace), "Could not read table size");
00383
00384 passure( cpl_table_get_ncol(singletrace) == 3, "%d", cpl_table_get_ncol(singletrace));
00385 passure( cpl_table_has_column(singletrace, "X"), " ");
00386 passure( cpl_table_has_column(singletrace, "Y"), " ");
00387 passure( cpl_table_has_column(singletrace, "dY"), " ");
00388
00389
00390
00391 if (points_traced == 0)
00392 {
00393 uves_msg_warning("Could not trace order #%d", order);
00394 check( cpl_table_set_invalid(ordertable, "RMS", order - 1),
00395 "Could not flag order %d RMS as invalid", order);
00396 }
00397 else
00398 {
00399 double rms=0;
00400 double slope=0;
00401
00402
00403
00404 check( rms = fit_order_linear(singletrace, order, KAPPA, &slope),
00405 "Creating linear fit of order #%d failed", order);
00406
00407 check(( cpl_table_set_double(ordertable, "RMS", order - 1, rms),
00408 cpl_table_fill_column_window_double(singletrace, "OrderRMS",
00409 0, points_traced, rms)),
00410 "Could not write RMS of order #%d to tables", order);
00411
00412 check(( cpl_table_set_double(ordertable, "TraceSlope", order - 1, slope),
00413 cpl_table_fill_column_window_double(singletrace, "OrderSlope",
00414 0, points_traced, slope)),
00415 "Could not write slope of order #%d to tables", order);
00416
00417
00418 passure( cpl_table_get_ncol(singletrace) == 7, "%d",
00419 cpl_table_get_ncol(singletrace));
00420 passure( cpl_table_has_column(singletrace, "X"), " ");
00421 passure( cpl_table_has_column(singletrace, "Y"), " ");
00422 passure( cpl_table_has_column(singletrace, "dY"), " ");
00423 passure( cpl_table_has_column(singletrace, "Linear fit"), " ");
00424 passure( cpl_table_has_column(singletrace, "Residual_Square"), " ");
00425 passure( cpl_table_has_column(singletrace, "OrderRMS"), " ");
00426 passure( cpl_table_has_column(singletrace, "OrderSlope"), " ");
00427
00428
00429 check( cpl_table_erase_column(singletrace, "Linear fit"),
00430 "Could not delete column 'Linear fit'");
00431
00432
00433 check(( cpl_table_new_column(singletrace, "Order", CPL_TYPE_INT),
00434 cpl_table_fill_column_window_int(
00435 singletrace, "Order",
00436 0, cpl_table_get_nrow(singletrace), order)
00437 ),
00438 "Could not create new column 'Order'");
00439
00440
00441 passure( cpl_table_compare_structure(singletrace, tracetable) == 0, " ");
00442
00443
00444 check( cpl_table_insert(tracetable, singletrace,
00445 cpl_table_get_nrow(tracetable)),
00446 "Could not append single order #%d to trace table", order);
00447
00448 *orders_traced += 1;
00449 }
00450
00451 }
00452
00453
00454 check( uves_plot_table(tracetable, "X", "Y",
00455 "Initial trace (%d orders)", *orders_traced),
00456 "Plotting failed");
00457
00458
00459 passure( cpl_table_get_ncol(tracetable) == 7, "%d", cpl_table_get_ncol(tracetable));
00460 passure( cpl_table_has_column(tracetable, "X"), " ");
00461 passure( cpl_table_has_column(tracetable, "Order"), " ");
00462 passure( cpl_table_has_column(tracetable, "Y"), " ");
00463 passure( cpl_table_has_column(tracetable, "dY"), " ");
00464 passure( cpl_table_has_column(tracetable, "Residual_Square"), " ");
00465 passure( cpl_table_has_column(tracetable, "OrderRMS"), " ");
00466 passure( cpl_table_has_column(tracetable, "OrderSlope"), " ");
00467
00468 assure(*orders_traced >= 1, CPL_ERROR_ILLEGAL_OUTPUT, "No orders could be traced");
00469
00470
00471 {
00472 double maxrms;
00473 int orders_rejected;
00474 check( maxrms =
00475 uves_max_double(0.05, MAXRMS * cpl_table_get_column_median(ordertable, "RMS")),
00476 "Could not read median RMS");
00477
00478 uves_msg_debug("Maximum admissible RMS is %.2f pixels", maxrms);
00479
00480
00481 check( orders_rejected = uves_select_table_rows(
00482 ordertable, "RMS", CPL_GREATER_THAN, maxrms),
00483 "Could not select rows in order table");
00484
00485
00486 if (orders_rejected > 0)
00487 {
00488 uves_msg_warning("%d order(s) rejected because RMS "
00489 "(from linear fit) was too large", orders_rejected);
00490
00491
00492 check( uves_erase_table_rows(tracetable, "OrderRMS",
00493 CPL_GREATER_THAN, maxrms),
00494 "Could not erase bad orders from trace table");
00495
00496
00497 }
00498 else
00499 {
00500 uves_msg_debug("All RMSs are less than %.2f", maxrms);
00501 }
00502
00503
00504
00505
00506
00507
00508 check_nomsg( orders_rejected =
00509 uves_select_table_rows(
00510 ordertable, "TraceSlope", CPL_GREATER_THAN, 0.5) +
00511 uves_select_table_rows(
00512 ordertable, "TraceSlope", CPL_LESS_THAN, -0.5));
00513
00514 if (orders_rejected > 0) {
00515 uves_msg_warning("%d order(s) rejected because slope was outside [-0.5 ; 0.5]",
00516 orders_rejected);
00517
00518 check_nomsg( uves_erase_table_rows(tracetable, "OrderSlope",
00519 CPL_GREATER_THAN, 0.5));
00520 check_nomsg( uves_erase_table_rows(tracetable, "OrderSlope",
00521 CPL_LESS_THAN, -0.5));
00522 }
00523 else {
00524 uves_msg_debug("All line slopes are within [-0.5 ; 0.5]");
00525 }
00526 }
00527
00528
00529
00530
00531 {
00532 double dy_median = cpl_table_get_column_median(tracetable, "dY");
00533 double threshold = 0.40*dy_median;
00534 int nreject;
00535
00536 check_nomsg( nreject = uves_erase_table_rows(tracetable, "dY", CPL_LESS_THAN,
00537 threshold) );
00538
00539 uves_msg_debug("Rejected %d points with dY less than %f pixels (median = %f pixels)",
00540 nreject, threshold, dy_median);
00541 }
00542
00543
00544
00545
00546 if (*DEFPOL1 < 0 || *DEFPOL2 < 0)
00547 {
00548 int deg1, deg2;
00549 int new_deg1, new_deg2;
00550 double red_chisq1, mse1;
00551 double red_chisq2, mse2;
00552 double red_chisq3, mse3;
00553 bool adjust1 = (*DEFPOL1 < 0);
00554
00555 bool adjust2 = (*DEFPOL2 < 0);
00556 int finished;
00557
00558
00559
00560 int number_of_orders = 0;
00561
00562 int number_of_orders1 = 0;
00563 int number_of_orders2 = 0;
00564 int number_of_orders3 = 0;
00565
00566 if (adjust1)
00567 {
00568
00569 *DEFPOL1 = 1;
00570 deg1 = 1;
00571 }
00572 else
00573 {
00574
00575 deg1 = *DEFPOL1;
00576 }
00577 if (adjust2)
00578 {
00579
00580 *DEFPOL2 = 1;
00581 deg2 = 1;
00582 }
00583 else
00584 {
00585
00586 deg2 = *DEFPOL2;
00587 }
00588
00589 uves_free_table(&temp);
00590 temp = cpl_table_duplicate(tracetable);
00591 uves_polynomial_delete(bivariate_fit);
00592 check( *bivariate_fit = uves_polynomial_regression_2d(
00593 temp,
00594 "X", "Order", "Y", "dY",
00595 deg1,
00596 deg2,
00597 NULL, NULL, NULL,
00598 &mse, &red_chisq,
00599 NULL,
00600 KAPPA, -1),
00601 "Error fitting orders");
00602
00603 check( number_of_orders = count_orders(temp),
00604 "Error counting orders");
00605
00606 uves_msg_low("(%d, %d)-degree: RMS = %.3f pixels. "
00607 "Red.chi^2 = %.2f (%d orders) *",
00608 deg1,
00609 deg2,
00610 sqrt(mse),
00611 red_chisq,
00612 number_of_orders);
00613
00614
00615
00616
00617
00618 do
00619 {
00620 int maxdegree = 6;
00621 finished = 0;
00622
00623 adjust1 = adjust1 && (deg1 + 1 <= maxdegree);
00624 adjust2 = adjust2 && (deg2 + 1 <= maxdegree);
00625
00626
00627 if (adjust1)
00628 {
00629 uves_free_table(&temp);
00630 temp = cpl_table_duplicate(tracetable);
00631 uves_polynomial_delete(bivariate_fit);
00632 *bivariate_fit = uves_polynomial_regression_2d(
00633 temp,
00634 "X", "Order", "Y", "dY",
00635 deg1 + 1,
00636 deg2,
00637 NULL, NULL, NULL,
00638 &mse1, &red_chisq1,
00639 NULL,
00640 KAPPA, -1);
00641
00642 if (cpl_error_get_code() == CPL_ERROR_SINGULAR_MATRIX)
00643 {
00644 uves_error_reset();
00645 mse1 = -1;
00646 red_chisq1 = DBL_MAX/2;
00647 }
00648 else
00649 {
00650 assure( cpl_error_get_code() == CPL_ERROR_NONE,
00651 cpl_error_get_code(),
00652 "Error fitting orders");
00653
00654 check( number_of_orders1 = count_orders(temp),
00655 "Error counting orders");
00656 }
00657 }
00658
00659
00660 if (adjust2)
00661 {
00662 uves_free_table(&temp);
00663 temp = cpl_table_duplicate(tracetable);
00664 uves_polynomial_delete(bivariate_fit);
00665 *bivariate_fit = uves_polynomial_regression_2d(
00666 temp,
00667 "X", "Order", "Y", "dY",
00668 deg1,
00669 deg2 + 1,
00670 NULL, NULL, NULL,
00671 &mse2, &red_chisq2,
00672 NULL,
00673 KAPPA, -1);
00674
00675 if (cpl_error_get_code() == CPL_ERROR_SINGULAR_MATRIX)
00676 {
00677 uves_error_reset();
00678 mse2 = -1;
00679 red_chisq2 = DBL_MAX/2;
00680 }
00681 else
00682 {
00683 assure( cpl_error_get_code() == CPL_ERROR_NONE,
00684 cpl_error_get_code(),
00685 "Error fitting orders");
00686
00687 check( number_of_orders2 = count_orders(temp),
00688 "Error counting orders");
00689 }
00690 }
00691
00692
00693 if (adjust1 && adjust2)
00694 {
00695 uves_free_table(&temp);
00696 temp = cpl_table_duplicate(tracetable);
00697 uves_polynomial_delete(bivariate_fit);
00698 *bivariate_fit = uves_polynomial_regression_2d(
00699 temp,
00700 "X", "Order", "Y", "dY",
00701 deg1 + 1,
00702 deg2 + 1,
00703 NULL, NULL, NULL,
00704 &mse3, &red_chisq3,
00705 NULL,
00706 KAPPA, -1);
00707
00708 if (cpl_error_get_code() == CPL_ERROR_SINGULAR_MATRIX)
00709 {
00710 uves_error_reset();
00711 mse3 = -1;
00712 red_chisq3 = DBL_MAX/2;
00713 }
00714 else
00715 {
00716 assure( cpl_error_get_code() == CPL_ERROR_NONE,
00717 cpl_error_get_code(),
00718 "Error fitting orders");
00719
00720 check( number_of_orders3 = count_orders(temp),
00721 "Error counting orders");
00722 }
00723 }
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 new_deg1 = deg1;
00737 new_deg2 = deg2;
00738 if (adjust1 && mse1 >= 0 && (red_chisq - red_chisq1)/red_chisq > 0.1 &&
00739 red_chisq1 <= red_chisq2)
00740 {
00741 new_deg1++;
00742 mse = mse1;
00743 red_chisq = red_chisq1;
00744 finished = 1;
00745
00746 if (number_of_orders1 >= number_of_orders)
00747 {
00748 *DEFPOL1 = new_deg1;
00749 *DEFPOL2 = new_deg2;
00750 number_of_orders = number_of_orders1;
00751 }
00752 }
00753 else if (adjust2 && mse2 >= 0 && (red_chisq - red_chisq2)/red_chisq > 0.1 &&
00754 red_chisq2 < red_chisq1)
00755 {
00756 new_deg2++;
00757 mse = mse2;
00758 red_chisq = red_chisq2;
00759 finished = 2;
00760
00761 if (number_of_orders2 >= number_of_orders)
00762 {
00763 *DEFPOL1 = new_deg1;
00764 *DEFPOL2 = new_deg2;
00765 number_of_orders = number_of_orders2;
00766 }
00767 }
00768 else if (adjust1 && adjust2 &&
00769 mse3 >= 0 && (red_chisq - red_chisq3)/red_chisq > 0.1)
00770 {
00771 new_deg1++;
00772 new_deg2++;
00773 mse = mse3;
00774 red_chisq = red_chisq3;
00775 finished = 3;
00776
00777 if (number_of_orders3 >= number_of_orders)
00778 {
00779 *DEFPOL1 = new_deg1;
00780 *DEFPOL2 = new_deg2;
00781 number_of_orders = number_of_orders3;
00782 }
00783 }
00784
00785
00786
00787
00788 if (adjust1)
00789 {
00790 if (mse1 >= 0)
00791 {
00792 uves_msg_low("(%d, %d)-degree: RMS = %.3f pixels. "
00793 "Red.chi^2 = %.3f (%d orders)%s",
00794 deg1 + 1,
00795 deg2,
00796 sqrt(mse1),
00797 red_chisq1,
00798 number_of_orders1,
00799 (finished == 1) ? " *" : "");
00800 }
00801 else
00802 {
00803 uves_msg_low("(%d, %d)-degree: Singular matrix",
00804 deg1 + 1,
00805 deg2);
00806 }
00807 }
00808
00809 if (adjust2)
00810 {
00811 if (mse2 >= 0)
00812 {
00813 uves_msg_low("(%d, %d)-degree: RMS = %.3f pixels. "
00814 "Red.chi^2 = %.3f (%d orders)%s",
00815 deg1,
00816 deg2 + 1,
00817 sqrt(mse2),
00818 red_chisq2,
00819 number_of_orders2,
00820 (finished == 2) ? " *" : "");
00821 }
00822 else
00823 {
00824 uves_msg_low("(%d, %d)-degree: Singular matrix",
00825 deg1,
00826 deg2 + 1);
00827 }
00828 }
00829
00830 if (adjust1 && adjust2)
00831 {
00832 if (mse3 >= 0)
00833 {
00834 uves_msg_low("(%d, %d)-degree: RMS = %.3f pixels. "
00835 "Red.chi^2 = %.3f (%d orders)%s",
00836 deg1 + 1,
00837 deg2 + 1,
00838 sqrt(mse3),
00839 red_chisq3,
00840 number_of_orders3,
00841 (finished == 3) ? " *" : "");
00842 }
00843 else
00844 {
00845 uves_msg_low("(%d, %d)-degree: Singular matrix",
00846 deg1 + 1,
00847 deg2 + 1);
00848 }
00849 }
00850
00851 if (finished != 0)
00852 {
00853 uves_msg_debug("Moved to degree (%d, %d), finished = %d, "
00854 "DEFPOL = %d, %d",
00855 new_deg1, new_deg2, finished, *DEFPOL1, *DEFPOL2);
00856 }
00857
00858 deg1 = new_deg1;
00859 deg2 = new_deg2;
00860
00861 } while (finished != 0);
00862
00863 uves_msg_low("Using degree (%d, %d)", *DEFPOL1, *DEFPOL2);
00864
00865 }
00866
00867
00868 uves_polynomial_delete(bivariate_fit);
00869 check( *bivariate_fit = uves_polynomial_regression_2d(tracetable,
00870 "X", "Order", "Y", "dY",
00871 *DEFPOL1,
00872 *DEFPOL2,
00873 "Yfit", NULL, "dYfit_Square",
00874 &mse, &red_chisq,
00875 NULL,
00876 KAPPA, -1),
00877 "Error fitting orders");
00878
00879 uves_msg("RMS error of (%d, %d)-degree fit is %.3f pixels. Reduced chi^2 is %.3f",
00880 *DEFPOL1,
00881 *DEFPOL2,
00882 sqrt(mse),
00883 red_chisq);
00884
00885
00886 if (sqrt(mse) > 0.3)
00887 {
00888 uves_msg_warning("RMS of bivariate fit (%.2f pixels) "
00889 "is larger than 0.3 pixels", sqrt(mse));
00890 }
00891 if (red_chisq < .01)
00892 {
00893 uves_msg_warning("Reduced chi^2 of fit is less than 1/100: %f", red_chisq);
00894 }
00895 if (red_chisq > 100)
00896 {
00897 uves_msg_warning("Reduced chi^2 of fit is greater than 100: %f", red_chisq);
00898 }
00899
00900
00901 check(( cpl_table_duplicate_column(tracetable, "Residual", tracetable, "Y"),
00902 cpl_table_subtract_columns(tracetable, "Residual", "Yfit")),
00903 "Error calculating residuals of fit");
00904
00905
00906 {
00907 check( *orders_traced = count_orders(tracetable),
00908 "Error counting orders");
00909
00910 uves_msg("%d order(s) were traced", *orders_traced);
00911 if (*orders_traced < N)
00912 {
00913 uves_msg_warning("Rejected %d order(s)", N - *orders_traced);
00914 }
00915 }
00916
00917
00918 check( uves_plot_table(tracetable, "X", "Yfit", "%d orders detected", *orders_traced),
00919 "Plotting failed");
00920 check( uves_plot_table(tracetable, "X", "Residual",
00921 "Residual of fit (RMS = %.3f pixels; red.chi^2 = %f)",
00922 sqrt(mse), red_chisq), "Plotting failed");
00923 check( uves_plot_table(tracetable, "Y", "Residual",
00924 "Residual of fit (RMS = %.3f pixels; red.chi^2 = %f)",
00925 sqrt(mse), red_chisq), "Plotting failed");
00926
00927 cleanup:
00928 uves_free_table(&temp);
00929 uves_free_table(&singletrace);
00930 if (cpl_error_get_code() != CPL_ERROR_NONE)
00931 {
00932 uves_free_table(&tracetable);
00933 }
00934
00935 return tracetable;
00936 }
00937
00938
00939
00947 static int
00948 count_orders(const cpl_table *tracetable)
00949 {
00950 int number = 0;
00951 int previous = -1;
00952 int row;
00953
00954 passure( tracetable != NULL, " ");
00955 passure( cpl_table_has_column(tracetable, "Order"), " ");
00956
00957 for (row = 0; row < cpl_table_get_nrow(tracetable); row++)
00958 {
00959 int current;
00960 current = cpl_table_get_int(tracetable, "Order", row, NULL);
00961 if (current != previous)
00962 {
00963 number++;
00964 }
00965 previous = current;
00966 }
00967
00968 cleanup:
00969 return number;
00970
00971 }
00972
00973
00974
00989
00990
00991 static double
00992 fit_order_linear(cpl_table *singletrace,
00993 int order,
00994 double KAPPA,
00995 double *slope)
00996 {
00997 double mse = 0;
00998 double intersept;
00999 cpl_table *temp = NULL;
01000 polynomial *pol = NULL;
01001
01002 passure( slope != NULL, " ");
01003 passure( cpl_table_get_ncol(singletrace) == 3, "%d", cpl_table_get_ncol(singletrace));
01004 passure( cpl_table_has_column(singletrace, "X"), " ");
01005 passure( cpl_table_has_column(singletrace, "Y"), " ");
01006 passure( cpl_table_has_column(singletrace, "dY")," ");
01007
01008 check( temp = cpl_table_duplicate(singletrace),
01009 "Error cloning table");
01010
01011 if (cpl_table_get_nrow(temp) == 1)
01012 {
01013
01014
01015 check(( cpl_table_set_size(temp, 2),
01016 cpl_table_set_int (temp, "X", 1, uves_max_int(
01017 cpl_table_get_int (temp, "X", 0, NULL) - 1, 1)),
01018 cpl_table_set_double(temp, "Y", 1,
01019 cpl_table_get_double(temp, "Y", 0, NULL)),
01020 cpl_table_set_double(temp, "dY", 1,
01021 cpl_table_get_double(temp, "dY",0, NULL))),
01022 "Could not add point");
01023 }
01024
01025
01026
01027 check( pol = uves_polynomial_regression_1d(temp,
01028 "X", "Y", NULL,
01029
01030 1,
01031 NULL, NULL,
01032 &mse,
01033 KAPPA),
01034 "Fitting of order %d failed. You may have to increase value of kappa",
01035 order);
01036
01037 intersept = uves_polynomial_get_coeff_1d(pol, 0);
01038 *slope = uves_polynomial_get_coeff_1d(pol, 1);
01039
01040 uves_msg_debug("The RMS error of order #%d is %.2f pixels; "
01041 "slope = %f; intersept = %f",
01042 order, sqrt(mse),
01043 *slope, intersept);
01044
01045
01046 {
01047 int i;
01048
01049 check(( cpl_table_new_column(singletrace, "Linear fit", CPL_TYPE_DOUBLE),
01050 cpl_table_new_column(singletrace, "Residual_Square", CPL_TYPE_DOUBLE)),
01051 "Error adding table columns");
01052
01053 for (i = 0; i < cpl_table_get_nrow(singletrace); i++)
01054 {
01055 int x = cpl_table_get_int (singletrace, "X", i, NULL);
01056 double y = cpl_table_get_double(singletrace, "Y", i, NULL);
01057
01058 double linear_fit, residual;
01059
01060 check (linear_fit = uves_polynomial_evaluate_1d(pol, x),
01061 "Error evaluating polynomial");
01062
01063 residual = y - linear_fit;
01064
01065 check(( cpl_table_set_double(singletrace, "Linear fit", i, linear_fit),
01066 cpl_table_set_double(singletrace, "Residual_Square",
01067 i, residual*residual)),
01068 "Error updating table");
01069 }
01070 }
01071
01072
01073 check(( cpl_table_new_column(singletrace, "OrderRMS", CPL_TYPE_DOUBLE),
01074 cpl_table_new_column(singletrace, "OrderSlope", CPL_TYPE_DOUBLE),
01075 cpl_table_fill_column_window_double(
01076 singletrace, "OrderRMS", 0, cpl_table_get_nrow(singletrace), sqrt(mse)),
01077 cpl_table_fill_column_window_double(
01078 singletrace, "OrderSlope", 0, cpl_table_get_nrow(singletrace), *slope)),
01079 "Could not create columns OrderRMS and OrderSlope");
01080
01081 passure( cpl_table_get_ncol(singletrace) == 7, "%d", cpl_table_get_ncol(singletrace));
01082 passure( cpl_table_has_column(singletrace, "X"), " ");
01083 passure( cpl_table_has_column(singletrace, "Y"), " ");
01084 passure( cpl_table_has_column(singletrace, "dY")," ");
01085 passure( cpl_table_has_column(singletrace, "Linear fit"), " ");
01086 passure( cpl_table_has_column(singletrace, "Residual_Square"), " ");
01087 passure( cpl_table_has_column(singletrace, "OrderRMS"), " ");
01088 passure( cpl_table_has_column(singletrace, "OrderSlope"), " ");
01089
01090 cleanup:
01091 uves_free_table(&temp);
01092 uves_polynomial_delete(&pol);
01093 return sqrt(mse);
01094
01095 }
01096
01097
01124
01125
01126 static cpl_table *
01127 trace_order(const cpl_table *ordertable, int order,
01128 const cpl_image *inputimage, const cpl_image *noise,
01129 const cpl_binary *image_bad,
01130 int TRACESTEP,
01131 double MAXGAP)
01132 {
01133 cpl_table *singletrace = NULL;
01134 int tracerow;
01135 int DIRECTION;
01136 double slope;
01137 double threshold;
01138 double minthreshold;
01139 int nx;
01140 int xcenter;
01141 int ycenter;
01142 int orderlength;
01143 int order_spacing;
01144 int xmax, xmin;
01145
01146 nx = cpl_image_get_size_x(inputimage);
01147
01148 check(( singletrace =
01149 cpl_table_new(nx/TRACESTEP + 2),
01150 cpl_table_new_column(singletrace, "X", CPL_TYPE_INT),
01151 cpl_table_new_column(singletrace, "Y", CPL_TYPE_DOUBLE),
01152 cpl_table_new_column(singletrace, "dY",CPL_TYPE_DOUBLE),
01153 tracerow = 0),
01154 "Could not initialize tracetable");
01155
01156
01157
01158
01159
01160
01161
01162 check((xcenter = cpl_table_get_int (ordertable, "Xcenter" , order - 1, NULL),
01163 ycenter = cpl_table_get_int (ordertable, "Ycenter" , order - 1, NULL),
01164 orderlength = cpl_table_get_int (ordertable, "OrderLength" , order - 1, NULL),
01165 order_spacing= cpl_table_get_int (ordertable, "Spacing" , order - 1, NULL),
01166 threshold = cpl_table_get_double(ordertable, "Threshold" , order - 1, NULL),
01167 minthreshold = cpl_table_get_double(ordertable, "MinThreshold", order - 1, NULL)),
01168 "Reading order table failed");
01169
01170
01171 threshold = minthreshold;
01172
01173
01174
01175 tracerow = 0;
01176
01177 xmax = xmin = xcenter;
01178
01179
01180 for (DIRECTION = -1; DIRECTION <= 1; DIRECTION += 2) {
01181
01182 int x = xcenter;
01183 double y = (double) ycenter;
01184 double dy = 0;
01185 int gap_size = 0;
01186
01187 check( slope = cpl_table_get_double(
01188 ordertable, "Slope", order - 1, NULL),
01189 "Could not read slope from table");
01190
01191 if (xcenter < nx/10 || xcenter > (nx*99)/100) {
01192
01193 x = 0;
01194
01195
01196
01197 }
01198
01199 while(1 <= x && x <= nx && gap_size < MAXGAP*nx) {
01200 bool found;
01201
01202 check( found = find_centroid(
01203 inputimage, noise, image_bad, threshold,
01204 order_spacing, x, &y, &dy),
01205 "Could not get order line position");
01206
01207
01208
01209
01210 if (found &&
01211 (y - ycenter)/(x - xcenter) > -1 &&
01212 (y - ycenter)/(x - xcenter) < 1) {
01213
01214
01215 xmax = uves_max_int(xmax, x);
01216 xmin = uves_min_int(xmin, x);
01217
01218 uves_msg_debug("(Order, x, y, dy, threshold) = "
01219 "(%d, %d, %f, %f, %f)",
01220 order, x, y, dy, threshold);
01221
01222 if (!(x == xcenter && DIRECTION == 1))
01223
01224
01225
01226
01227 {
01228 cpl_table_set_int (
01229 singletrace, "X", tracerow, x);
01230 cpl_table_set_double(
01231 singletrace, "Y", tracerow, y);
01232 if (dy > 0) {
01233 cpl_table_set_double(
01234 singletrace, "dY", tracerow, dy);
01235 }
01236 else {
01237 cpl_table_set_invalid(
01238 singletrace, "dY", tracerow);
01239 }
01240 tracerow++;
01241 }
01242
01243 gap_size = 0;
01244
01245 }
01246 else {
01247 gap_size += TRACESTEP;
01248 }
01249
01250
01251 x = x + DIRECTION * TRACESTEP;
01252 y = y + slope*DIRECTION * TRACESTEP;
01253
01254 slope = (y - ycenter)/(x - xcenter);
01255
01256 }
01257
01258 }
01259
01260
01261
01262 uves_msg_debug("%d points were traced in order %d", tracerow, order);
01263
01264
01265 check( cpl_table_set_size(singletrace, tracerow), "Could not resize tracetable");
01266
01267
01268
01269
01270 {
01271 double dy_median;
01272
01273 if (cpl_table_has_valid(singletrace, "dY"))
01274 {
01275
01276 dy_median = cpl_table_get_column_median(singletrace, "dY");
01277 }
01278 else
01279 {
01280 dy_median = 1.0;
01281 }
01282
01283
01284 cpl_table_select_all(singletrace);
01285 cpl_table_and_selected_invalid(singletrace, "dY");
01286 {
01287 int i;
01288 for (i = 0; i < cpl_table_get_nrow(singletrace); i++)
01289 {
01290 if (cpl_table_is_selected(singletrace, i))
01291 {
01292 cpl_table_set_double(singletrace, "dY", i, dy_median);
01293 }
01294 }
01295 }
01296 }
01297
01298
01299 check( uves_sort_table_1(singletrace, "X", false), "Could not sort order table");
01300
01301 cleanup:
01302 if (cpl_error_get_code() != CPL_ERROR_NONE)
01303 {
01304 uves_free_table(&singletrace);
01305 }
01306
01307 return singletrace;
01308 }
01309
01310
01323
01324 static int
01325 get_orderlength(int nx, int ny, cpl_table *ordertable, int row)
01326 {
01327 int x0 = 0, y_0, x1 = 0, y_1;
01328 double intersept, slope;
01329
01330 check(( intersept = cpl_table_get_double(ordertable, "Intersept", row, NULL),
01331 slope = cpl_table_get_double(ordertable, "Slope", row, NULL)),
01332 "Could not read line from ordertable");
01333
01334
01335 x0 = 1;
01336 y_0 = uves_round_double(intersept + slope*x0);
01337
01338
01339 if (y_0 < 1)
01340 {
01341 y_0 = 1;
01342 x0 = uves_round_double((y_0 - intersept)/slope);
01343 }
01344
01345
01346 x1 = nx;
01347 y_1 = uves_round_double(intersept + slope*nx);
01348 if (y_1 > ny)
01349 {
01350 y_1 = ny;
01351 x1 = uves_round_double((y_1 - intersept)/slope);
01352 }
01353
01354 cleanup:
01355 return (x1 - x0);
01356 }
01357
01358
01359
01372
01373 static int
01374 get_xcenter(int nx, int ny, cpl_table *ordertable, int row)
01375 {
01376 int x0, y_0, x1, y_1, xc = 0;
01377 double intersept, slope;
01378 check(( intersept = cpl_table_get_double(ordertable, "Intersept", row, NULL),
01379 slope = cpl_table_get_double(ordertable, "Slope", row, NULL)),
01380 "Could not read line from ordertable");
01381
01382
01383 x0 = 1;
01384 y_0 = uves_round_double(intersept + slope*x0);
01385
01386
01387 if (y_0 < 1)
01388 {
01389 y_0 = 1;
01390 x0 = uves_round_double((y_0 - intersept)/slope);
01391
01392 }
01393
01394
01395
01396 x1 = nx;
01397 y_1 = uves_round_double(intersept + slope*nx);
01398
01399
01400 if (y_1 > ny)
01401 {
01402 y_1 = ny;
01403 x1 = uves_round_double((y_1 - intersept)/slope);
01404 }
01405
01406 xc = (x0 + x1)/2;
01407
01408 cleanup:
01409 return xc;
01410 }
01411
01412
01424
01425 static int
01426 get_ycenter(int nx, int ny, cpl_table *ordertable, int row)
01427 {
01428 int xc = 0;
01429 int yc = 0;
01430 check( xc = get_xcenter(nx, ny, ordertable, row), "Could not find x-center of order");
01431
01432 check( yc = uves_round_double(
01433 cpl_table_get_double(ordertable, "Slope" , row, NULL)*xc +
01434 cpl_table_get_double(ordertable, "Intersept", row, NULL)
01435 ), "Could not read line from ordertable");
01436
01437 cleanup:
01438 return yc;
01439 }
01440
01441
01457
01458 static double
01459 estimate_threshold(const cpl_image *inputimage, const cpl_image *noise,
01460 cpl_table *ordertable, int row, double relative_threshold)
01461 {
01462 int yupper = 0;
01463 int ylower = 0;
01464 int xc, yc;
01465 int N;
01466 int ny;
01467 double returnvalue = 0;
01468 cpl_stats *stats = NULL;
01469
01470 passure( inputimage != NULL, " ");
01471 passure( ordertable != NULL, " ");
01472 passure( cpl_table_get_int(ordertable, "Order", row, NULL) == row+1, "%d %d",
01473 cpl_table_get_int(ordertable, "Order", row, NULL), row);
01474
01475 check( ny = cpl_image_get_size_y(inputimage), "Could not read input image dimension");
01476
01477 check( N = cpl_table_get_nrow(ordertable), "Could not read size of ordertable");
01478 assure(N > 1, CPL_ERROR_ILLEGAL_INPUT,
01479 "Cannot calculate orderspacing with less than 2 (i.e. %d) orders.", N);
01480 check( xc = cpl_table_get_int(ordertable, "Xcenter", row, NULL),
01481 "Could not read x-center of order #%d", row+1);
01482 check( yc = cpl_table_get_int(ordertable, "Ycenter", row, NULL),
01483 "Could not find y-center of order #%d", row+1);
01484
01485
01486
01487
01488
01489
01490 if (row < N - 1)
01491 {
01492 double ynext;
01493 check(ynext =
01494 cpl_table_get_double(ordertable, "Slope" , row + 1, NULL)*xc +
01495 cpl_table_get_double(ordertable, "Intersept", row + 1, NULL),
01496 "Could not read line from ordertable row %d", row + 1);
01497
01498 yupper = (int)((yc + (uves_round_double(ynext)-1))/2);
01499
01500 }
01501
01502 if (row > 0)
01503 {
01504 double yprev;
01505 check( yprev =
01506 cpl_table_get_double(ordertable, "Slope" , row - 1, NULL)*xc +
01507 cpl_table_get_double(ordertable, "Intersept", row - 1, NULL),
01508 "Could not read line from ordertable row %d", row - 1);
01509
01510 ylower = (int)((yc + uves_round_double(yprev)-1)/2);
01511
01512 }
01513
01514
01515
01516 if (row == N-1)
01517 {
01518 yupper = yc + (yc - ylower);
01519 }
01520 if (row == 0)
01521 {
01522 ylower = yc - (yupper - yc);
01523 }
01524 yupper = uves_min_int(uves_max_int(yupper, 1), ny);
01525 ylower = uves_min_int(uves_max_int(ylower, 1), ny);
01526
01527
01528
01529
01530
01531 assure(yupper > ylower, CPL_ERROR_ILLEGAL_INPUT,
01532 "Initially detected order lines intersept!");
01533
01534
01535 {
01536 double minval = 0;
01537 double maxval = 0;
01538 double noise_level = 0;
01539
01540
01541 check( stats = cpl_stats_new_from_image_window(
01542 inputimage,
01543 CPL_STATS_MIN | CPL_STATS_MAX | CPL_STATS_MINPOS,
01544 xc, ylower,
01545 xc, yupper),
01546 "Could not get statistics on image sub-window (%d,%d)-(%d,%d)",
01547 xc, ylower, xc, yupper);
01548
01549 check(( minval = cpl_stats_get_min(stats),
01550 maxval = cpl_stats_get_max(stats)),
01551 "Could not get minimum and maximum pixel values");
01552
01553
01554 {
01555 int xpos, ypos, pis_rejected;
01556 xpos = cpl_stats_get_min_x(stats);
01557 ypos = cpl_stats_get_min_y(stats);
01558 noise_level = cpl_image_get(noise, xpos, ypos, &pis_rejected);
01559 }
01560
01561
01562 returnvalue = uves_max_double(minval + relative_threshold * (maxval - minval),
01563 (minval + noise_level) + noise_level);
01564
01565 uves_msg_debug("Order: %d \tThreshold: %f \tMinimum: %f \tMaximum: %f"
01566 " \tNoise: %f \tWindow: (%d, %d)-(%d, %d)",
01567 row+1, returnvalue, minval, maxval, noise_level, xc, ylower, xc, yupper);
01568 }
01569
01570 cleanup:
01571 uves_free_stats(&stats);
01572 return returnvalue;
01573 }
01574
01575
01598
01599 static bool
01600 find_centroid(const cpl_image *inputimage, const cpl_image *noise,
01601 const cpl_binary *image_bad,
01602 double threshold, int spacing, int x, double *yguess, double *dY)
01603 {
01604 bool returnvalue = true;
01605 int nx;
01606 int ny;
01607 int y;
01608 double thisvalue = 0;
01609 int pis_rejected;
01610 int ylow = 0;
01611 int yhigh = 0;
01612 cpl_matrix *covariance = NULL;
01613
01614 passure( inputimage != NULL, " ");
01615
01616 nx = cpl_image_get_size_x(inputimage);
01617 ny = cpl_image_get_size_y(inputimage);
01618
01619 passure( 1 <= x && x <= nx, "%d %d", x, nx);
01620
01621 uves_msg_debug("Order location estimate = (%d, %f)", x, *yguess);
01622
01623
01624
01625 y = uves_round_double(*yguess);
01626 if (y < 1 || y > ny)
01627 {
01628 returnvalue = false;
01629 }
01630 else {
01631 bool cont;
01632
01633 do {
01634 cont = false;
01635 thisvalue = cpl_image_get(inputimage, x, y , &pis_rejected);
01636
01637 if (y < ny) {
01638 double uppervalue = cpl_image_get(inputimage, x, y + 1, &pis_rejected);
01639 if (!pis_rejected && uppervalue > thisvalue)
01640 {
01641 y += 1;
01642 cont = true;
01643 }
01644 }
01645
01646
01647 if (y > 1) {
01648 double lowervalue = cpl_image_get(inputimage, x, y - 1, &pis_rejected);
01649 if (!pis_rejected && lowervalue > thisvalue)
01650 {
01651 y -= 1;
01652 cont = true;
01653 }
01654 }
01655
01656 } while (cont);
01657
01658
01659
01660 uves_msg_debug("Local maximum at (%d, %d) (value = %f)\tthreshold = %f",
01661 x, y, thisvalue, threshold);
01662
01663
01664 if (thisvalue < threshold)
01665 {
01666 uves_msg_debug("Order not traced at (%d, %d) (value = %f)\tthreshold = %f",
01667 x, y, thisvalue, threshold);
01668 returnvalue = false;
01669 }
01670 else
01671 {
01672
01673 double minvalue;
01674 double sigmaY;
01675
01676 double mse, rms, chi_sq;
01677 double background;
01678 double norm;
01679
01680
01681 minvalue = 0.5*thisvalue;
01682
01683
01684 while(y > 1 && cpl_image_get(inputimage, x, y - 1, &pis_rejected) >= minvalue)
01685 {
01686 y--;
01687 }
01688
01689 assure( cpl_error_get_code() == CPL_ERROR_NONE,
01690 cpl_error_get_code(), "Could not read pixel from input image" );
01691
01692
01693 ylow = y;
01694
01695
01696 while(y < ny && cpl_image_get(inputimage, x, y + 1, &pis_rejected) >= minvalue)
01697 {
01698 y++;
01699 }
01700
01701 assure( cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(),
01702 "Could not read pixel from input image" );
01703
01704
01705 yhigh = y;
01706
01707
01708
01709 {
01710 double sum = 0;
01711 double sumy = 0;
01712 double sumy2= 0;
01713 for (y = ylow; y <= yhigh; y++)
01714 {
01715 double flux;
01716 flux = cpl_image_get(inputimage, x, y, &pis_rejected) - minvalue;
01717 if (!pis_rejected && flux > 0)
01718 {
01719 sum += flux;
01720 sumy += flux * (y - *yguess*0);
01721 sumy2 += flux * (y - *yguess*0) * (y - *yguess*0);
01722 }
01723 }
01724 if (sum > 0)
01725 {
01726 *yguess = *yguess*0 + sumy / sum;
01727 sigmaY = sqrt( sumy2 / sum - sumy*sumy/(sum*sum) );
01728
01729 if ( sumy2 / sum - sumy*sumy/(sum*sum) < 0 ||
01730 sigmaY < sqrt(1.0/12) )
01731 {
01732
01733
01734
01735
01736 sigmaY = sqrt(1.0/12);
01737 }
01738
01739
01740
01741 *dY = sigmaY/sqrt(sum);
01742
01743 }
01744 else
01745 {
01746
01747 sigmaY = 1.0;
01748 *dY = .1;
01749
01750 }
01751 }
01752
01753
01754
01755
01756
01757 ylow = uves_max_int(1 , uves_round_double(*yguess - spacing/3));
01758 yhigh = uves_min_int(ny, uves_round_double(*yguess + spacing/3));
01759
01760 assure( yhigh - ylow >= 1, CPL_ERROR_ILLEGAL_INPUT,
01761 "Estimated spacing too small: %d pixel(s)", spacing);
01762
01763
01764 uves_fit_1d_image(inputimage, noise,
01765 image_bad,
01766 false, false, false,
01767 ylow, yhigh, x,
01768 yguess, &sigmaY, &norm, &background, NULL,
01769 &mse, &chi_sq, &covariance,
01770 uves_gauss, uves_gauss_derivative, 4);
01771
01772
01773 if (cpl_error_get_code() == CPL_ERROR_NONE)
01774 {
01775
01776 *dY = sqrt(cpl_matrix_get(covariance, 0, 0));
01777 }
01778 else if (cpl_error_get_code() == CPL_ERROR_CONTINUE)
01779 {
01780
01781 uves_error_reset();
01782 uves_msg_debug("Fitting failed at (x,y) = (%d, %e), "
01783 "using centroid", x, *yguess);
01784 *dY = sigmaY / sqrt(norm);
01785 }
01786 else if (cpl_error_get_code() == CPL_ERROR_SINGULAR_MATRIX)
01787 {
01788 uves_error_reset();
01789
01790
01791 uves_msg_debug("Covariance matrix computation failed");
01792 *dY = sigmaY / sqrt(norm);
01793 }
01794
01795 assure(cpl_error_get_code() == CPL_ERROR_NONE,
01796 cpl_error_get_code(), "Gaussian fitting failed");
01797
01798 rms = sqrt(mse);
01799
01800 uves_msg_debug("dy = %f sigma/sqrt(N) = %f", *dY, sigmaY/(norm));
01801
01802
01803
01804 if ( norm > 10 * rms)
01805 {
01806 returnvalue = true;
01807 }
01808 if ( norm < 2 * rms)
01809 {
01810 returnvalue = false;
01811 }
01812
01813 }
01814
01815 }
01816
01817 cleanup:
01818 cpl_matrix_delete(covariance);
01819 return returnvalue;
01820 }