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