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
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 #ifdef HAVE_CONFIG_H
00209 # include <config.h>
00210 #endif
00211
00212
00216
00217
00218
00219
00220
00221
00222 #include <uves_orderpos_body.h>
00223
00224 #include <uves_orderpos_hough.h>
00225 #include <uves_orderpos_follow.h>
00226
00227 #include <uves_physmod_chop_otab.h>
00228 #include <uves_corrbadpix.h>
00229 #include <uves_utils.h>
00230 #include <uves_recipe.h>
00231 #include <uves_parameters.h>
00232 #include <uves_backsub.h>
00233 #include <uves_pfits.h>
00234 #include <uves_dfs.h>
00235 #include <uves_qclog.h>
00236 #include <uves_utils_wrappers.h>
00237 #include <uves_utils_cpl.h>
00238 #include <uves_error.h>
00239 #include <uves_msg.h>
00240
00241 #include <irplib_access.h>
00242 #include <cpl.h>
00243
00244 #include <float.h>
00245
00246
00247
00248
00249
00250 static void uves_orderpos_qclog(cpl_table* table,
00251 bool flames,
00252 int pord,
00253 int dord,
00254 int samples_per_order,
00255 uves_propertylist* rhead,
00256 enum uves_chip chip,
00257 cpl_table* qclog);
00258
00261
00262
00263
00264
00265 const char * const uves_orderpos_desc_short = "Defines echelle order positions";
00266 const char * const uves_orderpos_desc =
00267 "The recipe defines the order positions in an echelle image. The orders are\n"
00268 "initially detected by means of a Hough transformation, the orders are then \n"
00269 "traced, and the positions are finally fitted with a global polynomial.\n"
00270 "\n"
00271 "Expected input frames are narrow flat fields, ORDER_FLAT_xxx, or standard \n"
00272 "stars, STANDARD_xxx, where xxx is 'BLUE' or 'RED', and optionally for each \n"
00273 "chip a DRS setup table (DRS_TABLE_BLUE, DRS_TABLE_REDL, DRS_TABLE_REDU) or \n"
00274 "guess order table (ORDER_GUESS_TAB_BLUE, ORDER_GUESS_TAB_REDL, \n"
00275 "ORDER_GUESS_TAB_REDU, \n"
00276 "or, for backward compatibility, ORDER_TABLE_BLUE, ORDER_TABLE_REDL, \n"
00277 "ORDER_TABLE_REDU). The recipe processes only the first raw frame found.\n"
00278 "\n"
00279 "Output is one (or two if input is a red frame) order table(s) \n"
00280 "(UVES: ORDER_TABLE_(BLUE|REDL|REDU); FLAMES: FIB_ORDEF_(REDL|REDU) contaning\n"
00281 "the columns:\n"
00282 "X : Position along x\n"
00283 "Order : Relative order number\n"
00284 "Y : Order line centroid location\n"
00285 "Yfit : The fitted order location\n"
00286 "dY : Uncertainty of Y\n"
00287 "dYfit_Square : Variance of Yfit\n"
00288 "Residual : Y - Yfit\n"
00289 "Residual_Square : Residual^2\n"
00290 "OrderRMS : Root mean squared residual of initial\n"
00291 " one-dimensional linear fit of order\n"
00292 "\n"
00293 "The bivariate fit polynomial itself is stored in table extension no. 2.\n"
00294 "The 3rd table extension contains a table that defines the active fibre traces\n"
00295 "and their positions (for support of FLAMES/UVES)\n";
00296
00297
00298
00299
00300
00301
00308
00309 int
00310 uves_orderpos_define_parameters_body(cpl_parameterlist *parameters,
00311 const char *recipe_id)
00312 {
00313 const char *subcontext;
00314
00315
00316
00317
00318
00319 if (uves_define_global_parameters(parameters) != CPL_ERROR_NONE)
00320 {
00321 return -1;
00322 }
00323
00324
00325
00326
00327
00328 subcontext = "preproc";
00329
00330
00331 uves_par_new_range("radx",
00332 CPL_TYPE_INT,
00333 "X-radius of median filtering window",
00334 2, 0, INT_MAX);
00335
00336 uves_par_new_range("rady",
00337 CPL_TYPE_INT,
00338 "Y-radius of median filtering window",
00339 1, 0, INT_MAX);
00340
00341
00342 uves_par_new_enum("mmethod",
00343 CPL_TYPE_STRING,
00344 "Background subtraction method. If equal "
00345 "to 'median' the background is sampled using "
00346 "the median of a sub-window. If 'minimum', "
00347 "the minimum sub-window value is used. If "
00348 "'no', no background subtraction is done.",
00349 "median",
00350 3,
00351 "median", "minimum", "no");
00352
00353
00354 uves_par_new_range("backsubgrid",
00355 CPL_TYPE_INT,
00356 "Number of grid points (in x- and y-direction) "
00357 "used to estimate "
00358 "the background (mode=poly).",
00359 50, 1, INT_MAX);
00360
00361
00362 uves_par_new_range("backsubradiusy",
00363 CPL_TYPE_INT,
00364 "The height (in pixels) of the background "
00365 "sampling window is (2*radiusy + 1). "
00366 "This parameter is not corrected for binning.",
00367 2, 0, INT_MAX);
00368
00369
00370 uves_par_new_range("backsubkappa",
00371 CPL_TYPE_DOUBLE,
00372 "The value of kappa in the one-sided kappa-sigma "
00373 "clipping used to "
00374 "estimate the background (mode=poly).",
00375 4.0, 0.0, DBL_MAX);
00376
00377
00378 uves_par_new_range("backsubdegx",
00379 CPL_TYPE_INT,
00380 "Degree (in x) of polynomial used "
00381 "to estimate the background (mode=poly).",
00382 2, 1, INT_MAX);
00383
00384 uves_par_new_range("backsubdegy",
00385 CPL_TYPE_INT,
00386 "Degree (in y) of polynomial used "
00387 "to estimate the background (mode=poly).",
00388 2, 1, INT_MAX);
00389
00390
00391
00392
00393 subcontext = "hough";
00394
00395
00396 uves_par_new_range("samplewidth",
00397 CPL_TYPE_INT,
00398 "Separation of sample traces "
00399 "(used by Hough transform) in input image",
00400 50, 1, INT_MAX);
00401
00402
00403 uves_par_new_range("minslope",
00404 CPL_TYPE_DOUBLE,
00405 "Minimum possible line slope. This should "
00406 "be the 'physical' slope on the chip, "
00407 "i.e. not taking binning factors into "
00408 "account, which is handled by the recipe",
00409 0.0, 0.0, DBL_MAX);
00410
00411 uves_par_new_range("maxslope",
00412 CPL_TYPE_DOUBLE,
00413 "Maximum possible line slope",
00414 0.2, 0.0, DBL_MAX);
00415
00416
00417 uves_par_new_range("sloperes",
00418 CPL_TYPE_INT,
00419 "Resolution (width in pixels) of Hough space",
00420 120, 1, INT_MAX);
00421
00422
00423 uves_par_new_range("norders",
00424 CPL_TYPE_INT,
00425 "Number of echelle orders to detect. If "
00426 "set to 0 the predicted number of orders will "
00427 "be read from the guess order table. If no "
00428 "guess order table is given, the recipe will "
00429 "try to autodetect the number of orders. If "
00430 "the raw frame is a red chip and this parameter "
00431 "is specified, the given value will be used "
00432 "for both red chips",
00433 0, 0, INT_MAX);
00434
00435
00436 uves_par_new_range("pthres",
00437 CPL_TYPE_DOUBLE,
00438 "In automatic mode, or if the number of orders "
00439 "to detect is read from a guess table, the detection "
00440 "of new lines stops when the intensity of a candidate "
00441 "line drops to less than 'pthres' times the intensity "
00442 "of the previous detection. Otherwise - i.e. if the "
00443 "number of orders to detect was specified by setting "
00444 "the 'norders' parameters - this parameter is "
00445 "ignored.",
00446 0.2, 0.0, 1.0);
00447
00448
00449
00450
00451 subcontext = "trace";
00452
00453
00454 uves_par_new_range("tracestep",
00455 CPL_TYPE_INT,
00456 "The step size used when tracing the orders",
00457 10, 1, INT_MAX);
00458
00459
00460 uves_par_new_range("minthresh",
00461 CPL_TYPE_DOUBLE,
00462 "The minimum threshold value is (min + "
00463 "minthres*(max - min)). Here 'min' "
00464 "and 'max' are the lowest and highest pixel "
00465 "values in the central bin of the order",
00466 0.2, 0.0, 1.0);
00467
00468
00469 uves_par_new_range("maxgap",
00470 CPL_TYPE_DOUBLE,
00471 "If the order line drops below detection "
00472 "threshold, the order tracing algorithm "
00473 "will try to jump a gap of maximum size 'maxgap' "
00474 "multiplied by the image width",
00475 .2, 0.0, 1.0);
00476
00477
00478
00479
00480
00481 subcontext = "reject";
00482
00483
00484 uves_par_new_range("maxrms",
00485 CPL_TYPE_DOUBLE,
00486 "When fitting the orders with straight lines, "
00487 "this is the maximum allowed RMS relative to "
00488 "the median RMS of all orders",
00489 100.0, 0.0, DBL_MAX);
00490
00491
00492
00493
00494 uves_par_new_range("defpol1",
00495 CPL_TYPE_INT,
00496 "The degree of the bivarite fit (cross "
00497 "dispersion direction). If negative, "
00498 "the degree is optimized to give the best fit",
00499 -1,
00500 -1, INT_MAX);
00501
00502
00503 uves_par_new_range("defpol2",
00504 CPL_TYPE_INT,
00505 "The degree of the bivarite fit (order number). "
00506 "If negative, "
00507 "the degree is optimized to give the best fit",
00508 -1,
00509 -1, INT_MAX);
00510
00511
00512 uves_par_new_range("kappa",
00513 CPL_TYPE_DOUBLE,
00514 "Used for kappa-sigma clipping of the final "
00515 "polynomial fit. If negative, no clipping is done",
00516 6.0, -2.0, DBL_MAX);
00517
00518 return (cpl_error_get_code() != CPL_ERROR_NONE);
00519 }
00520
00521
00569
00570 static cpl_table *
00571 uves_orderpos_process_chip(const cpl_image *raw_image, uves_propertylist *raw_header,
00572 const uves_propertylist *rotated_header,
00573 enum uves_chip chip, int binx, int biny,
00574
00575 bool DEBUG,
00576
00577 int RADX,
00578 int RADY,
00579 background_measure_method BM_METHOD,
00580 int BACKSUBGRID,
00581 int BACKSUBRADIUSY,
00582 double BACKSUBKAPPA,
00583 int BACKSUBDEGX,
00584 int BACKSUBDEGY,
00585
00586 int SAMPLEWIDTH,
00587 double MINSLOPE,
00588 double MAXSLOPE,
00589 int SLOPERES,
00590 int NORDERS,
00591 bool norders_is_guess,
00592 double PTHRES,
00593
00594 int TRACESTEP,
00595 double MINTHRESH,
00596 double MAXGAP,
00597
00598 double MAXRMS,
00599 int DEFPOL1,
00600 int DEFPOL2,
00601 double KAPPA,
00602
00603 polynomial **bivariate_fit,
00604 int *norders,
00605 cpl_table* guess_table)
00606 {
00607
00608 cpl_table *tracetable = NULL;
00609
00610 cpl_image *noise = NULL;
00611
00612 cpl_image *back_subbed = NULL;
00613 cpl_image *hough_trans = NULL;
00614 polynomial *guess_locations = NULL;
00615
00616
00617 cpl_image *inputlines = NULL;
00618
00619 cpl_table *ordertable = NULL;
00620
00621 cpl_image *hough_original = NULL;
00622 int abs_ord_min=0;
00623 int abs_ord_max=0;
00624 int badpixels_marked = 0;
00625
00626 check( back_subbed = cpl_image_duplicate(raw_image), "Error duplicating image");
00627
00628
00629 if(guess_table != NULL)
00630 {
00631
00632
00633
00634 int minorder = uves_round_double(
00635 cpl_table_get_column_min(guess_table, "Order"));
00636 int maxorder = uves_round_double(
00637 cpl_table_get_column_max(guess_table, "Order"));
00638 int nx = cpl_image_get_size_x(back_subbed);
00639 int order;
00640
00641 {
00642 double kappa = 4;
00643 int max_degree = 6;
00644 double min_rms = 0.1;
00645 double mse;
00646 check( guess_locations = uves_polynomial_regression_2d_autodegree(
00647 guess_table,
00648 "X", "Order", "Yfit", NULL,
00649 NULL, NULL, NULL,
00650 &mse, NULL, NULL,
00651 kappa,
00652 max_degree, max_degree, min_rms, -1,
00653 false,
00654 NULL, NULL, -1, NULL),
00655 "Could not fit polynomial to provided table");
00656
00657 uves_msg("Provided table contains orders %d - %d. RMS = %.3f pixels",
00658 minorder, maxorder, sqrt(mse));
00659 }
00660
00661
00662
00663 ordertable = cpl_table_new(maxorder - minorder + 1);
00664 cpl_table_new_column(ordertable, "Order", CPL_TYPE_INT);
00665 cpl_table_new_column(ordertable, "Intersept", CPL_TYPE_DOUBLE);
00666 cpl_table_new_column(ordertable, "Slope", CPL_TYPE_DOUBLE);
00667 cpl_table_new_column(ordertable, "Spacing", CPL_TYPE_INT);
00668
00669 for (order = minorder; order <= maxorder; order++)
00670 {
00671 int row = order - minorder;
00672 double slope =
00673 uves_polynomial_derivative_2d(guess_locations, nx/2, order, 1);
00674 double intersept = uves_polynomial_evaluate_2d(guess_locations, nx/2, order)
00675 - slope*(nx/2);
00676 int spacing =
00677 uves_round_double(uves_polynomial_derivative_2d(
00678 guess_locations, nx/2, order, 2));
00679
00680 cpl_table_set_int (ordertable, "Order", row, order);
00681 cpl_table_set_double(ordertable, "Slope", row, slope);
00682 cpl_table_set_int (ordertable, "Spacing", row, spacing);
00683 cpl_table_set_double(ordertable, "Intersept", row, intersept);
00684 }
00685 }
00686 else
00687 {
00688
00689 int ymin = 1;
00690 int ymax = cpl_image_get_size_y(back_subbed);
00691
00692
00693
00694
00695
00696 {
00697 bool extrapolate_border = true;
00698
00699
00700
00701
00702 uves_msg("Applying %dx%d median filter", RADX*2+1, RADY*2+1);
00703 check( uves_filter_image_median(&back_subbed, RADX, RADY, extrapolate_border),
00704 "Could not filter image");
00705 }
00706
00707
00708 uves_msg("Subtracting background (grid sampling)");
00709
00710 check( uves_backsub_poly(back_subbed,
00711 NULL, NULL,
00712 BM_METHOD,
00713 BACKSUBGRID,
00714 BACKSUBRADIUSY,
00715 BACKSUBDEGX,
00716 BACKSUBDEGY,
00717 BACKSUBKAPPA),
00718 "Could not subtract background");
00719
00720 check( ordertable = uves_hough(back_subbed,
00721 ymin, ymax,
00722 NORDERS, norders_is_guess,
00723 SAMPLEWIDTH,
00724 PTHRES,
00725 MINSLOPE,
00726 MAXSLOPE,
00727 SLOPERES,
00728 true,
00729 &hough_trans,
00730 &hough_original),
00731 "Could not locate echelle orders");
00732
00733 if (DEBUG)
00734 {
00735 check( uves_save_image_local("Hough transform", "hough",
00736 hough_original, chip, -1, -1, NULL),
00737 "Error saving hough image");
00738
00739 check( uves_save_image_local("Hough transform (peaks deleted)",
00740 "hough_delete", hough_trans, chip, -1, -1, NULL),
00741 "Error saving hough image");
00742
00743
00744
00745 check( inputlines = cpl_image_duplicate(raw_image),
00746 "Could not duplicate image");
00747 check( uves_draw_orders(ordertable, inputlines),
00748 "Could not draw hough orders on image");
00749
00750 check( uves_save_image_local("Lines detected by Hough transform",
00751 "inputlines", inputlines, chip, -1, -1, rotated_header),
00752 "Error saving hough image");
00753
00754 uves_free_image(&inputlines);
00755 }
00756
00757
00758 uves_free_image(&hough_trans);
00759 uves_free_image(&hough_original);
00760 }
00761
00762
00763
00764 check(( uves_free_image(&back_subbed),
00765 back_subbed = cpl_image_duplicate(raw_image)),
00766 "Error duplicating image");
00767
00768 uves_msg("Subtracting background (inter-order sampling)");
00769 check( uves_backsub_poly(back_subbed,
00770 ordertable, NULL,
00771 BM_METHOD,
00772 BACKSUBGRID,
00773 BACKSUBRADIUSY,
00774 BACKSUBDEGX,
00775 BACKSUBDEGY,
00776 BACKSUBKAPPA),
00777 "Could not subtract background");
00778
00779
00780
00781
00782
00783
00784
00785 check( noise = uves_define_noise(back_subbed, raw_header, 1, chip),
00786 "Error creating noise image");
00787
00788 if (DEBUG)
00789 {
00790
00791
00792 check( uves_save_image_local("Pre-processed raw frame", "preproc",
00793 back_subbed, chip, -1, -1, rotated_header),
00794 "Error saving image");
00795
00796
00797 check( uves_save_image_local("Noise of pre-processed image",
00798 "preproc_noise",
00799 noise, chip, -1, -1, rotated_header),
00800 "Error saving image");
00801 }
00802
00803
00804 check( badpixels_marked =
00805 uves_correct_badpix_all(back_subbed,
00806 raw_header,
00807 chip,
00808 binx, biny,
00809 true
00810 ),
00811 "Error marking bad pixels");
00812
00813 uves_msg("%d pixels marked as bad", badpixels_marked);
00814
00815
00816
00817 check( tracetable = uves_locate_orders(back_subbed,
00818 noise,
00819 ordertable,
00820 TRACESTEP,
00821 MINTHRESH,
00822 MAXGAP,
00823 MAXRMS,
00824 DEFPOL1, DEFPOL2,
00825 KAPPA,
00826 bivariate_fit,
00827 norders), "Could not trace orders");
00828
00829
00830
00831 if (false)
00832
00833
00834
00835 {
00836 check(uves_physmod_chop_otab(raw_header,chip,&tracetable,"Order",
00837 &abs_ord_min,&abs_ord_max),
00838 "Could not run uves_physmod_chop_otab on trace order table");
00839 }
00840
00841
00842
00843
00844
00845
00846 if (DEBUG) check( uves_save_table_local("Basic order table", "basic",
00847 ordertable, chip, -1, -1, NULL, NULL),
00848 "Error saving table");
00849
00850 cleanup:
00851 uves_free_image(&back_subbed);
00852 uves_free_image(&noise);
00853 uves_free_image(&hough_trans);
00854 uves_polynomial_delete(&guess_locations);
00855
00856
00857 uves_free_image(&hough_original);
00858 uves_free_image(&inputlines);
00859 uves_free_table(&ordertable);
00860
00861 return tracetable;
00862 }
00863
00864
00879
00880 void
00881 uves_orderpos_exe_body(cpl_frameset *frames,
00882 bool flames,
00883 const char *recipe_id,
00884 const cpl_parameterlist *parameters,
00885 const char *starttime)
00886 {
00887
00888
00889
00890
00891
00892 bool DEBUG;
00893
00894 int RADX, RADY;
00895 background_measure_method BM_METHOD;
00896 int BACKSUBGRID;
00897 int BACKSUBRADIUSY;
00898 double BACKSUBKAPPA;
00899 int BACKSUBDEGX;
00900 int BACKSUBDEGY;
00901
00902 int SAMPLEWIDTH;
00903 double MINSLOPE, MAXSLOPE;
00904 int SLOPERES;
00905 int NORDERS;
00906 double PTHRES;
00907
00908 int TRACESTEP;
00909 double MINTHRESH;
00910 double MAXGAP;
00911
00912 double MAXRMS;
00913 int DEFPOL1;
00914 int DEFPOL2;
00915 double KAPPA;
00916
00917
00918 cpl_image *raw_image[2] = {NULL, NULL};
00919 uves_propertylist *raw_header[2] = {NULL, NULL};
00920 uves_propertylist *rotated_header[2] = {NULL, NULL};
00921 cpl_image *raw_image_int = NULL;
00922
00923
00924 uves_propertylist *guess_header = NULL;
00925 cpl_table *guess_table = NULL;
00926
00927
00928 cpl_table *tracetable = NULL;
00929 polynomial *bivariate_fit = NULL;
00930 cpl_table *traces = NULL;
00931 uves_propertylist *product_header = NULL;
00932 cpl_table* qclog[2] = {NULL, NULL};
00933
00934
00935 const char *raw_filename = "";
00936 char *product_filename = NULL;
00937 int ord_predict = 0;
00938 bool norders_is_guess = false;
00939 bool blue;
00940 enum uves_chip chip;
00941 int binx = 0;
00942 int biny = 0;
00943
00944
00945 {
00946
00947 check( uves_get_parameter(parameters, NULL, "uves", "debug", CPL_TYPE_BOOL, &DEBUG),
00948 "Could not read parameter");
00949
00950
00951 check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.radx",
00952 CPL_TYPE_INT , &RADX), "Could not read parameter");
00953 check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.rady",
00954 CPL_TYPE_INT , &RADY), "Could not read parameter");
00955
00956 check( BM_METHOD = uves_get_bm_method(parameters, recipe_id, "preproc"),
00957 "Could not read background measuring method");
00958
00959 check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.backsubgrid",
00960 CPL_TYPE_INT , &BACKSUBGRID),
00961 "Could not read parameter");
00962 check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.backsubradiusy",
00963 CPL_TYPE_INT, &BACKSUBRADIUSY), "Could not read parameter");
00964 check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.backsubkappa",
00965 CPL_TYPE_DOUBLE,&BACKSUBKAPPA), "Could not read parameter");
00966 check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.backsubdegx",
00967 CPL_TYPE_INT , &BACKSUBDEGX), "Could not read parameter");
00968 check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.backsubdegy",
00969 CPL_TYPE_INT , &BACKSUBDEGY), "Could not read parameter");
00970
00971 check( uves_get_parameter(parameters, NULL, recipe_id, "hough.samplewidth" ,
00972 CPL_TYPE_INT , &SAMPLEWIDTH), "Could not read parameter");
00973 check( uves_get_parameter(parameters, NULL, recipe_id, "hough.minslope" ,
00974 CPL_TYPE_DOUBLE, &MINSLOPE ), "Could not read parameter");
00975 check( uves_get_parameter(parameters, NULL, recipe_id, "hough.maxslope" ,
00976 CPL_TYPE_DOUBLE, &MAXSLOPE ), "Could not read parameter");
00977 check( uves_get_parameter(parameters, NULL, recipe_id, "hough.sloperes" ,
00978 CPL_TYPE_INT , &SLOPERES ), "Could not read parameter");
00979 check( uves_get_parameter(parameters, NULL, recipe_id, "hough.norders" ,
00980 CPL_TYPE_INT , &NORDERS ), "Could not read parameter");
00981 check( uves_get_parameter(parameters, NULL, recipe_id, "hough.pthres" ,
00982 CPL_TYPE_DOUBLE, &PTHRES ), "Could not read parameter");
00983
00984 check( uves_get_parameter(parameters, NULL, recipe_id, "trace.tracestep" ,
00985 CPL_TYPE_INT , &TRACESTEP ), "Could not read parameter");
00986 check( uves_get_parameter(parameters, NULL, recipe_id, "trace.minthresh" ,
00987 CPL_TYPE_DOUBLE, &MINTHRESH ), "Could not read parameter");
00988 check( uves_get_parameter(parameters, NULL, recipe_id, "trace.maxgap" ,
00989 CPL_TYPE_DOUBLE, &MAXGAP ), "Could not read parameter");
00990
00991 check( uves_get_parameter(parameters, NULL, recipe_id, "reject.maxrms" ,
00992 CPL_TYPE_DOUBLE, &MAXRMS ), "Could not read parameter");
00993 check( uves_get_parameter(parameters, NULL, recipe_id, "reject.defpol1" ,
00994 CPL_TYPE_INT , &DEFPOL1 ), "Could not read parameter");
00995 check( uves_get_parameter(parameters, NULL, recipe_id, "reject.defpol2" ,
00996 CPL_TYPE_INT , &DEFPOL2 ), "Could not read parameter");
00997 check( uves_get_parameter(parameters, NULL, recipe_id, "reject.kappa" ,
00998 CPL_TYPE_DOUBLE, &KAPPA ), "Could not read parameter");
00999
01000
01001
01002 assure( MINSLOPE < MAXSLOPE , CPL_ERROR_ILLEGAL_INPUT,
01003 "Minimum slope must be smaller than maximum slope (min = %f; max = %f)",
01004 MINSLOPE, MAXSLOPE);
01005 if (MAXSLOPE > 0.5){
01006 uves_msg_warning("Hough transformation might fail when searching for "
01007 "lines with slope larger than 0.5 (maxslope = %f)", MAXSLOPE);
01008 }
01009
01010 if (DEFPOL1 >= 6 || DEFPOL2 >= 6)
01011 {
01012 uves_msg_warning("Polynomial fitting might be unstable with "
01013 "polynomial degrees higher than 5");
01014 }
01015
01016 }
01017
01018
01019 check( uves_load_orderpos(frames,
01020 flames,
01021 &raw_filename, raw_image,
01022 raw_header, rotated_header, &blue), "Error loading raw frame");
01023
01024
01025 check (binx = uves_pfits_get_binx(raw_header[0]),
01026 "Could not read x binning factor from input header");
01027 check (biny = uves_pfits_get_biny(raw_header[0]),
01028 "Could not read y binning factor from input header");
01029
01030
01031
01032
01033
01034
01035
01036 MINSLOPE = (MINSLOPE*biny)/binx;
01037 MAXSLOPE = (MAXSLOPE*biny)/binx;
01038
01039 ord_predict = NORDERS;
01040
01041
01042 for (chip = uves_chip_get_first(blue);
01043 chip != UVES_CHIP_INVALID;
01044 chip = uves_chip_get_next(chip))
01045 {
01046 const char *guess_filename = "";
01047 const char *chip_name = "";
01048
01049 int raw_index = uves_chip_get_index(chip);
01050 int norders = 0;
01051
01052 uves_msg("Processing %s chip in '%s'",
01053 uves_chip_tostring_upper(chip), raw_filename);
01054
01055 check_nomsg( chip_name = uves_pfits_get_chipid(raw_header[raw_index], chip));
01056
01057 uves_msg_debug("Binning = %dx%d", binx, biny);
01058
01059
01060
01061
01062
01063
01064 if (NORDERS == 0)
01065 {
01066
01067
01068
01069 norders_is_guess = true;
01070
01071 uves_free_propertylist(&guess_header);
01072
01073 if (irplib_frameset_find(frames, UVES_DRS_SETUP(flames, chip)) != NULL)
01074 {
01075 uves_msg_low("No guess order table found");
01076
01077 check( uves_load_drs(frames, flames, chip_name, &guess_filename,
01078 &guess_header, chip),
01079 "Error loading setup table");
01080
01081 uves_msg("Using setup table in '%s'", guess_filename);
01082
01083 check( ord_predict = uves_pfits_get_ordpred(guess_header),
01084 "Could not read predicted number "
01085 "of orders from DRS table header");
01086 }
01087 else if (irplib_frameset_find(frames,
01088 UVES_ORDER_TABLE(flames, chip)) != NULL ||
01089 irplib_frameset_find(frames,
01090 UVES_GUESS_ORDER_TABLE(flames, chip)) != NULL)
01091 {
01092 bool load_guess = (
01093 irplib_frameset_find(frames,
01094 UVES_GUESS_ORDER_TABLE(flames, chip))
01095 != NULL);
01096
01097 uves_free_table(&guess_table);
01098
01099 check( uves_load_ordertable(
01100 frames,
01101 flames,
01102 chip_name,
01103 &guess_filename,
01104 &guess_table,
01105 &guess_header,
01106 NULL,
01107 NULL,
01108 NULL,
01109 NULL, NULL,
01110 NULL, NULL,
01111 chip,
01112 load_guess),
01113 "Error loading guess order table");
01114
01115 uves_msg("Using guess order table in '%s'", guess_filename);
01116
01117 check( ord_predict = uves_pfits_get_ordpred(guess_header),
01118 "Could not read predicted number of orders from "
01119 "guess order table header");
01120 }
01121 else
01122 {
01123 uves_msg("No guess table found");
01124 }
01125 }
01126 else
01127 {
01128
01129
01130
01131
01132 norders_is_guess = false;
01133 }
01134
01135
01136 check((uves_free_table (&tracetable),
01137 uves_polynomial_delete(&bivariate_fit),
01138 tracetable = uves_orderpos_process_chip(
01139 raw_image[raw_index],
01140 raw_header[raw_index],
01141 rotated_header[raw_index],
01142 chip, binx, biny,
01143 DEBUG,
01144 RADX, RADY,
01145 BM_METHOD,
01146 BACKSUBGRID,
01147 BACKSUBRADIUSY,
01148 BACKSUBKAPPA,
01149 BACKSUBDEGX, BACKSUBDEGY,
01150 SAMPLEWIDTH,
01151 MINSLOPE, MAXSLOPE,
01152 SLOPERES,
01153 ord_predict,
01154 norders_is_guess,
01155 PTHRES,
01156 TRACESTEP,
01157 MINTHRESH,
01158 MAXGAP,
01159 MAXRMS,
01160 DEFPOL1,
01161 DEFPOL2,
01162 KAPPA,
01163 &bivariate_fit,
01164 &norders,
01165 guess_table)),
01166 "Error processing chip");
01167
01168
01169 uves_msg("Saving products...");
01170
01171
01172
01173
01174 uves_free_propertylist(&product_header);
01175 product_header = uves_propertylist_new();
01176
01177
01178 check( uves_pfits_set_ordpred( product_header, norders),
01179 "Error writing number of detected orders");
01180
01181 if (flames)
01182 {
01183 int plate_no;
01184
01185 check( plate_no = uves_flames_pfits_get_plateid(raw_header[raw_index]),
01186 "Error reading plate id");
01187
01188 uves_flames_pfits_set_newplateid(product_header, plate_no);
01189 }
01190
01191
01192 {
01193 int samples_per_order =
01194 cpl_image_get_size_x(raw_image[raw_index]) / TRACESTEP;
01195
01196 uves_qclog_delete(&qclog[0]);
01197 qclog[0] = uves_qclog_init(raw_header[raw_index], chip);
01198 check_nomsg( uves_orderpos_qclog(tracetable,
01199 flames,
01200 ord_predict,
01201 norders,
01202 samples_per_order,
01203 raw_header[raw_index],chip,qclog[0]));
01204 }
01205
01206 check(( cpl_free(product_filename),
01207 product_filename = uves_order_table_filename(chip),
01208 uves_frameset_insert(frames,
01209 tracetable,
01210 CPL_FRAME_GROUP_PRODUCT,
01211 CPL_FRAME_TYPE_TABLE,
01212 CPL_FRAME_LEVEL_INTERMEDIATE,
01213 product_filename,
01214 flames ?
01215 UVES_GUESS_ORDER_TABLE(flames, chip) :
01216
01217 UVES_ORDER_TABLE(flames, chip),
01218 raw_header[raw_index],
01219 product_header,
01220 NULL,
01221 parameters,
01222 recipe_id,
01223 PACKAGE "/" PACKAGE_VERSION,
01224 qclog,
01225 starttime, true, 0)),
01226 "Could not add trace table %s to frameset", product_filename);
01227 uves_qclog_delete(&qclog[0]);
01228 uves_msg("Trace table %s added to frameset", product_filename);
01229
01230
01231 check( uves_save_polynomial(bivariate_fit, product_filename, NULL),
01232 "Could not write polynomial to file %s", product_filename);
01233
01234
01235
01236
01237 {
01238
01239
01240 uves_free_table(&traces);
01241 traces = uves_ordertable_traces_new();
01242 uves_ordertable_traces_add(traces, 0, 0.0, 1);
01243
01244 check( cpl_table_save(traces,
01245 NULL,
01246
01247 NULL,
01248 product_filename,
01249
01250 CPL_IO_EXTEND),
01251 "Error appending table to file '%s'", product_filename);
01252 }
01253
01254
01255 if (flames)
01256
01257
01258 {
01259
01260
01261 uves_free_image(&raw_image_int);
01262 raw_image_int = cpl_image_cast(raw_image[raw_index],
01263 CPL_TYPE_INT);
01264
01265 check(( cpl_free(product_filename),
01266 product_filename = uves_ordef_filename(chip),
01267 uves_frameset_insert(frames,
01268 raw_image_int,
01269 CPL_FRAME_GROUP_PRODUCT,
01270 CPL_FRAME_TYPE_IMAGE,
01271 CPL_FRAME_LEVEL_INTERMEDIATE,
01272 product_filename,
01273 FLAMES_ORDEF(flames, chip),
01274 raw_header[raw_index],
01275 rotated_header[raw_index],
01276 NULL,
01277 parameters,
01278 recipe_id,
01279 PACKAGE "/" PACKAGE_VERSION,
01280 NULL,
01281 starttime, false,
01282 CPL_STATS_MIN | CPL_STATS_MAX)),
01283 "Could not add raw frame %s to frameset", product_filename);
01284
01285 uves_msg("Raw frame %s added to frameset", product_filename);
01286 uves_free_image(&raw_image_int);
01287 }
01288
01289 }
01290
01291 cleanup:
01292
01293 uves_free_image(&(raw_image[0]));
01294 uves_free_image(&(raw_image[1]));
01295 uves_free_image(&raw_image_int);
01296 uves_free_propertylist(&(raw_header[0]));
01297 uves_free_propertylist(&(raw_header[1]));
01298 uves_free_propertylist(&(rotated_header[0]));
01299 uves_free_propertylist(&(rotated_header[1]));
01300
01301
01302 uves_free_propertylist(&guess_header);
01303 uves_free_table (&guess_table);
01304
01305
01306 uves_qclog_delete(&qclog[0]);
01307 uves_free_table (&tracetable);
01308 uves_polynomial_delete(&bivariate_fit);
01309 uves_free_table (&traces);
01310 uves_free_propertylist(&product_header);
01311 cpl_free(product_filename);
01312
01313 return;
01314 }
01325 static void uves_orderpos_qclog(cpl_table* table,
01326 bool flames,
01327 int pord,
01328 int dord,
01329 int samples_per_order,
01330 uves_propertylist* raw_header,
01331 enum uves_chip chip,
01332 cpl_table* qclog)
01333 {
01334 const char* chip_name;
01335 const char* grat_name;
01336 const char* ins_mode;
01337 double grat_wlen=0;
01338
01339 uves_qclog_add_string(qclog,
01340 "QC TEST1 ID",
01341 flames ?
01342 "Fibre-Order-Definition-Results" :
01343 "Order-Definition-Results",
01344 "Name of QC test",
01345 "%s");
01346
01347 check_nomsg( chip_name=uves_pfits_get_chip_name(raw_header,chip) );
01348
01349
01350 uves_qclog_add_string(qclog,
01351 uves_remove_string_prefix(UVES_CHIP_NAME(chip),"ESO "),
01352 chip_name,
01353 "Grating unique ID",
01354 "%s");
01355
01356
01357 check_nomsg(grat_name=uves_pfits_get_gratname(raw_header,chip));
01358
01359
01360
01361 uves_qclog_add_string(qclog,
01362 uves_remove_string_prefix(UVES_GRATNAME(chip),"ESO "),
01363 grat_name,
01364 "Cross disperser ID",
01365 "%s");
01366
01367
01368 check_nomsg(ins_mode=uves_pfits_get_insmode(raw_header));
01369 uves_qclog_add_string(qclog,
01370 uves_remove_string_prefix(UVES_INSMODE,"ESO "),
01371 ins_mode,
01372 "Instrument mode used.",
01373 "%s");
01374
01375
01376 check_nomsg(grat_wlen=uves_pfits_get_gratwlen(raw_header,chip));
01377 uves_qclog_add_double(qclog,
01378 uves_remove_string_prefix(UVES_GRATWLEN(chip),"ESO "),
01379 grat_wlen,
01380 "Grating central wavelength [nm]",
01381 "%.1f");
01382
01383 uves_msg_debug("chip_name=%s grat_name=%s ins_mode=%s grat_wlen=%f",
01384 chip_name,grat_name,ins_mode,grat_wlen);
01385
01386 uves_qclog_add_double(qclog,
01387 "QC ORD RESIDMIN",
01388 cpl_table_get_column_min(table,"Residual"),
01389 "min resid in ord def",
01390 "%8.4f");
01391
01392 uves_qclog_add_double(qclog,
01393 "QC ORD RESIDMAX",
01394 cpl_table_get_column_max(table,"Residual"),
01395 "max resid in ord def",
01396 "%8.4f");
01397
01398 uves_qclog_add_double(qclog,
01399 "QC ORD RESIDAVG",
01400 cpl_table_get_column_mean(table,"Residual"),
01401 "mean resid in ord def",
01402 "%8.4f");
01403
01404 uves_qclog_add_double(qclog,
01405 "QC ORD RESIDRMS",
01406 cpl_table_get_column_stdev(table,"Residual"),
01407 "rms resid in ord def",
01408 "%8.4f");
01409
01410 uves_qclog_add_int(qclog,
01411 "QC ORD NPRED",
01412 pord,
01413 "predicted number of orders",
01414 "%d");
01415
01416 uves_qclog_add_int(qclog,
01417 "QC ORD NDET",
01418 dord,
01419 "detected number of orders",
01420 "%d");
01421
01422 uves_qclog_add_int(qclog,
01423 "QC ORD NPOSALL",
01424 dord * samples_per_order,
01425 "Number of position found",
01426 "%d");
01427
01428 uves_qclog_add_int(qclog,
01429 "QC ORD NPOSSEL",
01430 cpl_table_get_nrow(table),
01431 "Number of position selected",
01432 "%d");
01433
01434 uves_qclog_add_int(qclog,
01435 "QC ORDMIN",
01436 cpl_table_get_column_min(table,"Order"),
01437 "Number of position selected",
01438 "%d");
01439
01440 uves_qclog_add_int(qclog,
01441 "QC ORDMAX",
01442 cpl_table_get_column_max(table,"Order"),
01443 "Number of position selected",
01444 "%d");
01445
01446
01447
01448
01449
01450 check_nomsg(uves_qclog_add_string(qclog,
01451 uves_remove_string_prefix(UVES_READ_SPEED,"ESO "),
01452 uves_pfits_get_readspeed(raw_header),
01453 "Readout speed",
01454 "%s"));
01455
01456 check_nomsg(uves_qclog_add_int(qclog,
01457 uves_remove_string_prefix(UVES_BINX, "ESO "),
01458 uves_pfits_get_binx(raw_header),
01459 "Binning factor along X",
01460 "%d"));
01461
01462 check_nomsg(uves_qclog_add_int(qclog,
01463 uves_remove_string_prefix(UVES_BINY, "ESO "),
01464 uves_pfits_get_biny(raw_header),
01465 "Binning factor along Y",
01466 "%d"));
01467
01468 check_nomsg(uves_qclog_add_string(qclog,
01469 uves_remove_string_prefix(UVES_INSPATH,"ESO "),
01470 uves_pfits_get_inspath(raw_header),
01471 "Optical path used (h).",
01472 "%s"));
01473
01474 cleanup:
01475 return;
01476
01477 }