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
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 #ifdef HAVE_CONFIG_H
00281 # include <config.h>
00282 #endif
00283
00284
00288
00289
00290
00291
00292
00293
00294 #include <uves_orderpos_body.h>
00295
00296 #include <uves_orderpos_hough.h>
00297 #include <uves_orderpos_follow.h>
00298
00299 #include <uves_physmod_chop_otab.h>
00300 #include <uves_corrbadpix.h>
00301 #include <uves_utils.h>
00302 #include <uves_recipe.h>
00303 #include <uves_parameters.h>
00304 #include <uves_backsub.h>
00305 #include <uves_pfits.h>
00306 #include <uves_dfs.h>
00307 #include <uves_qclog.h>
00308 #include <uves_utils_wrappers.h>
00309 #include <uves_utils_cpl.h>
00310 #include <uves_error.h>
00311 #include <uves_msg.h>
00312
00313 #include <cpl.h>
00314
00315 #include <float.h>
00316 #include <string.h>
00317
00318
00319
00320
00321 static void uves_orderpos_qclog(cpl_table* table,
00322 bool flames,
00323 int pord,
00324 int dord,
00325 int samples_per_order,
00326 uves_propertylist* rhead,
00327 enum uves_chip chip,
00328 cpl_table* qclog);
00329
00332
00333
00334
00335
00336 const char * const uves_orderpos_desc_short = "Defines echelle order positions";
00337 const char * const uves_orderpos_desc =
00338 "The recipe defines the order positions in an echelle image. The orders are\n"
00339 "initially detected by means of a Hough transformation, the orders are then \n"
00340 "traced, and the positions are finally fitted with a global polynomial.\n"
00341 "\n"
00342 "Expected input frames are narrow flat fields, ORDER_FLAT_xxx, or standard \n"
00343 "stars, STANDARD_xxx, where xxx is 'BLUE' or 'RED', and optionally for each \n"
00344 "chip a DRS setup table (DRS_TABLE_BLUE, DRS_TABLE_REDL, DRS_TABLE_REDU) or \n"
00345 "guess order table (ORDER_GUESS_TAB_BLUE, ORDER_GUESS_TAB_REDL, \n"
00346 "ORDER_GUESS_TAB_REDU, \n"
00347 "or, for backward compatibility, ORDER_TABLE_BLUE, ORDER_TABLE_REDL, \n"
00348 "ORDER_TABLE_REDU). The recipe processes only the first raw frame found.\n"
00349 "\n"
00350 "Output is one (or two if input is a red frame) order table(s) \n"
00351 "(UVES: ORDER_TABLE_(BLUE|REDL|REDU); FLAMES: FIB_ORDEF_(REDL|REDU) contaning\n"
00352 "the columns:\n"
00353 "X : Position along x\n"
00354 "Order : Relative order number\n"
00355 "Y : Order line centroid location\n"
00356 "Yfit : The fitted order location\n"
00357 "dY : Uncertainty of Y\n"
00358 "dYfit_Square : Variance of Yfit\n"
00359 "Residual : Y - Yfit\n"
00360 "Residual_Square : Residual^2\n"
00361 "OrderRMS : Root mean squared residual of initial\n"
00362 " one-dimensional linear fit of order\n"
00363 "\n"
00364 "The bivariate fit polynomial itself is stored in table extension no. 2.\n"
00365 "The 3rd table extension contains a table that defines the active fibre traces\n"
00366 "and their positions (for support of FLAMES/UVES)\n";
00367
00368
00369
00370
00371
00372
00379
00380 int
00381 uves_orderpos_define_parameters_body(cpl_parameterlist *parameters,
00382 const char *recipe_id)
00383 {
00384 const char *subcontext;
00385 double min_thresh=0.2;
00386
00387
00388
00389
00390
00391 if (uves_define_global_parameters(parameters) != CPL_ERROR_NONE)
00392 {
00393 return -1;
00394 }
00395
00396
00397
00398
00399
00400 subcontext = "preproc";
00401
00402
00403 uves_par_new_enum("use_guess_tab",
00404 CPL_TYPE_INT,
00405 "If a Guess order table is provided this parameter set how it is used:"
00406 "0: No usage, "
00407 "1: use it to set lower/upper Y raws where order are searched "
00408 "2: the order table try to fully match the guess",
00409 1, 3, 0, 1, 2);
00410
00411
00412
00413
00414 uves_par_new_range("radx",
00415 CPL_TYPE_INT,
00416 "Half X size of median filtering window",
00417 2, 0, INT_MAX);
00418
00419 uves_par_new_range("rady",
00420 CPL_TYPE_INT,
00421 "Half Y size of median filtering window",
00422 1, 0, INT_MAX);
00423
00424
00425 uves_par_new_enum("mmethod",
00426 CPL_TYPE_STRING,
00427 "Background subtraction method. If equal "
00428 "to 'median' the background is sampled using "
00429 "the median of a sub-window. If 'minimum', "
00430 "the minimum sub-window value is used. If "
00431 "'no', no background subtraction is done.",
00432 "median",
00433 3,
00434 "median", "minimum", "no");
00435
00436
00437 uves_par_new_range("backsubgrid",
00438 CPL_TYPE_INT,
00439 "Number of grid points (in x- and y-direction) "
00440 "used to estimate "
00441 "the background (mode=poly).",
00442 50, 10, INT_MAX);
00443
00444
00445 uves_par_new_range("backsubradiusy",
00446 CPL_TYPE_INT,
00447 "The height (in pixels) of the background "
00448 "sampling window is (2*radiusy + 1). "
00449 "This parameter is not corrected for binning.",
00450 2, 0, INT_MAX);
00451
00452
00453 uves_par_new_range("backsubkappa",
00454 CPL_TYPE_DOUBLE,
00455 "The value of kappa in the one-sided kappa-sigma "
00456 "clipping used to "
00457 "estimate the background (mode=poly).",
00458 4.0, 0.0, DBL_MAX);
00459
00460
00461 uves_par_new_range("backsubdegx",
00462 CPL_TYPE_INT,
00463 "Degree (in x) of polynomial used "
00464 "to estimate the background (mode=poly).",
00465 2, 1, INT_MAX);
00466
00467 uves_par_new_range("backsubdegy",
00468 CPL_TYPE_INT,
00469 "Degree (in y) of polynomial used "
00470 "to estimate the background (mode=poly).",
00471 2, 1, INT_MAX);
00472
00473
00474
00475
00476 subcontext = "hough";
00477
00478
00479 uves_par_new_range("samplewidth",
00480 CPL_TYPE_INT,
00481 "Separation of sample traces "
00482 "(used by Hough transform) in input image",
00483 50, 1, INT_MAX);
00484
00485
00486 uves_par_new_range("minslope",
00487 CPL_TYPE_DOUBLE,
00488 "Minimum possible line slope. This should "
00489 "be the 'physical' slope on the chip, "
00490 "i.e. not taking binning factors into "
00491 "account, which is handled by the recipe",
00492 0.0, 0.0, DBL_MAX);
00493
00494 uves_par_new_range("maxslope",
00495 CPL_TYPE_DOUBLE,
00496 "Maximum possible line slope",
00497 0.2, 0.0, DBL_MAX);
00498
00499
00500 uves_par_new_range("sloperes",
00501 CPL_TYPE_INT,
00502 "Resolution (width in pixels) of Hough space",
00503 120, 1, INT_MAX);
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 uves_par_new_range("pthres",
00524 CPL_TYPE_DOUBLE,
00525 "In automatic mode, or if the number of orders "
00526 "to detect is read from a guess table, the detection "
00527 "of new lines stops when the intensity of a candidate "
00528 "line drops to less than 'pthres' times the intensity "
00529 "of the previous detection. "
00530
00531
00532
00533
00534
00535
00536 ,
00537 0.2, 0.0, 1.0);
00538
00539
00540
00541
00542 subcontext = "trace";
00543
00544
00545 uves_par_new_range("tracestep",
00546 CPL_TYPE_INT,
00547 "The step size used when tracing the orders",
00548 10, 1, INT_MAX);
00549
00550
00551 if(strstr(recipe_id,"flames") != NULL) {
00552 min_thresh=0.01;
00553 } else {
00554 min_thresh=0.2;
00555 }
00556 uves_par_new_range("minthresh",
00557 CPL_TYPE_DOUBLE,
00558 "The minimum threshold value is (min + "
00559 "minthres*(max - min)). Here 'min' "
00560 "and 'max' are the lowest and highest pixel "
00561 "values in the central bin of the order",
00562 min_thresh, 0.0, 1.0);
00563
00564
00565 uves_par_new_range("maxgap",
00566 CPL_TYPE_DOUBLE,
00567 "If the order line drops below detection "
00568 "threshold, the order tracing algorithm "
00569 "will try to jump a gap of maximum size 'maxgap' "
00570 "multiplied by the image width",
00571 .2, 0.0, 1.0);
00572
00573
00574
00575
00576
00577 subcontext = "reject";
00578
00579
00580 uves_par_new_range("maxrms",
00581 CPL_TYPE_DOUBLE,
00582 "When fitting the orders with straight lines, "
00583 "this is the maximum allowed RMS relative to "
00584 "the median RMS of all orders",
00585 100.0, 0.0, DBL_MAX);
00586
00587
00588
00589
00590 uves_par_new_range("defpol1",
00591 CPL_TYPE_INT,
00592 "The degree of the bivarite fit (cross "
00593 "dispersion direction). If negative, "
00594 "the degree is optimized to give the best fit",
00595 -1,
00596 -1, INT_MAX);
00597
00598
00599 uves_par_new_range("defpol2",
00600 CPL_TYPE_INT,
00601 "The degree of the bivarite fit (order number). "
00602 "If negative, "
00603 "the degree is optimized to give the best fit",
00604 -1,
00605 -1, INT_MAX);
00606
00607
00608 uves_par_new_range("kappa",
00609 CPL_TYPE_DOUBLE,
00610 "Used for kappa-sigma clipping of the final "
00611 "polynomial fit. If negative, no clipping is done",
00612 4.0, -2.0, DBL_MAX);
00613
00614 return (cpl_error_get_code() != CPL_ERROR_NONE);
00615 }
00616
00617
00667
00668 static cpl_table *
00669 uves_orderpos_process_chip(const cpl_image *raw_image,
00670 uves_propertylist *raw_header,
00671 const uves_propertylist *rotated_header,
00672 enum uves_chip chip,
00673 int binx, int biny,
00674
00675 bool DEBUG,
00676
00677 int USE_GUESS_TAB,
00678 int RADX,
00679 int RADY,
00680 background_measure_method BM_METHOD,
00681 int BACKSUBGRID,
00682 int BACKSUBRADIUSY,
00683 double BACKSUBKAPPA,
00684 int BACKSUBDEGX,
00685 int BACKSUBDEGY,
00686
00687 int SAMPLEWIDTH,
00688 double MINSLOPE,
00689 double MAXSLOPE,
00690 int SLOPERES,
00691 int NORDERS,
00692 bool norders_is_guess,
00693 double PTHRES,
00694
00695 int TRACESTEP,
00696 double MINTHRESH,
00697 double MAXGAP,
00698
00699 double MAXRMS,
00700 int *DEFPOL1,
00701 int *DEFPOL2,
00702 double KAPPA,
00703
00704 polynomial **bivariate_fit,
00705 int *norders,
00706 cpl_table* guess_table)
00707 {
00708
00709 cpl_table *tracetable = NULL;
00710
00711 cpl_image *noise = NULL;
00712
00713 cpl_image *back_subbed = NULL;
00714 cpl_image *hough_trans = NULL;
00715 polynomial *guess_locations = NULL;
00716
00717
00718 cpl_image *inputlines = NULL;
00719
00720 cpl_table *ordertable = NULL;
00721
00722 cpl_image *hough_original = NULL;
00723 int abs_ord_min=0;
00724 int abs_ord_max=0;
00725 int badpixels_marked = 0;
00726 int ymin = 0;
00727 int ymax = 0;
00728 int ord_min=0;
00729 bool red_ccd_is_new=0;
00730 check_nomsg(red_ccd_is_new=uves_ccd_is_new(raw_header));
00731
00732 check( back_subbed = cpl_image_duplicate(raw_image), "Error duplicating image");
00733 ymin = 1;
00734 ymax = cpl_image_get_size_y(back_subbed);
00735 uves_msg("===============");
00736
00737
00738 if(guess_table != NULL)
00739 {
00740 if(USE_GUESS_TAB == 1) {
00741 int ymin_guess=ymin;
00742 int ymax_guess=ymax;
00743 int omin=0;
00744 int omax=0;
00745 cpl_table* tmp_tbl=NULL;
00746
00747 uves_msg("Use input guess order table to define the detector area");
00748 uves_msg("where to locate orders");
00749
00750
00751 tmp_tbl=cpl_table_duplicate(guess_table);
00752 uves_physmod_chop_otab(raw_header,chip,&tmp_tbl,"Order",&omin,&omax);
00753
00754 uves_msg("On Guess Found %d orders.",omax-omin+1);
00755 if(omax < cpl_table_get_column_max(guess_table,"Order")) {
00756 uves_free_table(&tmp_tbl);
00757 check(tmp_tbl=uves_extract_table_rows(guess_table,"Order",
00758 CPL_EQUAL_TO,omax+1),
00759 "Error selecting Order");
00760
00761 check(ymax_guess=(int)cpl_table_get_column_min(tmp_tbl,"Yfit")-1,
00762 "error getting ymax_guess");
00763 uves_free_table(&tmp_tbl);
00764 }
00765
00766 if(omin > cpl_table_get_column_min(guess_table,"Order")) {
00767 uves_free_table(&tmp_tbl);
00768 check(tmp_tbl=uves_extract_table_rows(guess_table,"Order",
00769 CPL_EQUAL_TO,omin-1),
00770 "Error selecting Order");
00771
00772 check(ymin_guess=(int)cpl_table_get_column_max(tmp_tbl,"Yfit")+1,
00773 "error getting ymin_guess");
00774
00775 uves_free_table(&tmp_tbl);
00776 }
00777 ymin = (ymin_guess>ymin) ? ymin_guess : ymin;
00778 ymax = (ymax_guess<ymax) ? ymax_guess : ymax;
00779
00780 uves_msg("Serching them in the region [ymin,ymax]=[%d,%d]",ymin,ymax);
00781 uves_free_table(&tmp_tbl);
00782
00783
00784 } else if (USE_GUESS_TAB == 2) {
00785
00786
00787
00788
00789 int minorder = uves_round_double(
00790 cpl_table_get_column_min(guess_table, "Order"));
00791 int maxorder = uves_round_double(
00792 cpl_table_get_column_max(guess_table, "Order"));
00793 int nx = cpl_image_get_size_x(back_subbed);
00794 int order;
00795
00796
00797 uves_msg("Create a table with order lines in the same format as the");
00798 uves_msg("Hough transform would do it, ");
00799 uves_msg("i.e. intersept + slope for each order.");
00800
00801 {
00802 double kappa = 4;
00803 int max_degree = 6;
00804 double min_rms = 0.1;
00805 double mse;
00806 check( guess_locations = uves_polynomial_regression_2d_autodegree(
00807 guess_table,
00808 "X", "Order", "Yfit", NULL,
00809 NULL, NULL, NULL,
00810 &mse, NULL, NULL,
00811 kappa,
00812 max_degree, max_degree, min_rms, -1,
00813 false,
00814 NULL, NULL, -1, NULL),
00815 "Could not fit polynomial to provided table");
00816
00817 uves_msg("Provided table contains orders %d - %d. RMS = %.3f pixels",
00818 minorder, maxorder, sqrt(mse));
00819 }
00820
00821
00822
00823 ordertable = cpl_table_new(maxorder - minorder + 1);
00824 cpl_table_new_column(ordertable, "Order", CPL_TYPE_INT);
00825 cpl_table_new_column(ordertable, "Intersept", CPL_TYPE_DOUBLE);
00826 cpl_table_new_column(ordertable, "Slope", CPL_TYPE_DOUBLE);
00827 cpl_table_new_column(ordertable, "Spacing", CPL_TYPE_INT);
00828
00829 for (order = minorder; order <= maxorder; order++)
00830 {
00831 int row = order - minorder;
00832 double slope =
00833 uves_polynomial_derivative_2d(guess_locations, nx/2, order, 1);
00834 double intersept = uves_polynomial_evaluate_2d(guess_locations, nx/2, order)
00835 - slope*(nx/2);
00836 int spacing =
00837 uves_round_double(uves_polynomial_derivative_2d(
00838 guess_locations, nx/2, order, 2));
00839
00840 cpl_table_set_int (ordertable, "Order", row, order);
00841 cpl_table_set_double(ordertable, "Slope", row, slope);
00842 cpl_table_set_int (ordertable, "Spacing", row, spacing);
00843 cpl_table_set_double(ordertable, "Intersept", row, intersept);
00844 }
00845
00846 }
00847
00848 }
00849 if( (guess_table == NULL) || (USE_GUESS_TAB != 2) )
00850 {
00851
00852
00853 uves_msg("Detect orders from scratch ");
00854
00855
00856
00857
00858
00859
00860
00861 {
00862 bool extrapolate_border = true;
00863
00864
00865
00866
00867 uves_msg("Applying %dx%d median filter", RADX*2+1, RADY*2+1);
00868 check( uves_filter_image_median(&back_subbed, RADX, RADY, extrapolate_border),
00869 "Could not filter image");
00870 }
00871
00872
00873 uves_msg("Subtracting background (grid sampling)");
00874
00875 check( uves_backsub_poly(back_subbed,
00876 NULL, NULL,
00877 BM_METHOD,
00878 BACKSUBGRID,
00879 BACKSUBRADIUSY,
00880 BACKSUBDEGX,
00881 BACKSUBDEGY,
00882 BACKSUBKAPPA),
00883 "Could not subtract background");
00884
00885 check( ordertable = uves_hough(back_subbed,
00886 ymin, ymax,
00887 NORDERS, norders_is_guess,
00888 SAMPLEWIDTH,
00889 PTHRES,
00890 MINSLOPE,
00891 MAXSLOPE,
00892 SLOPERES,
00893 true,
00894 &hough_trans,
00895 &hough_original),
00896 "Could not locate echelle orders");
00897
00898 if (DEBUG)
00899 {
00900
00901 check(uves_propertylist_copy_property_regexp((uves_propertylist*)rotated_header, raw_header,
00902 "^ESO ", 0),
00903 "Error copying hieararch keys");
00904
00905 check( uves_save_image_local("Hough transform", "hough",
00906 hough_original, chip, -1, -1,
00907 rotated_header, true),
00908 "Error saving hough image");
00909
00910 check( uves_save_image_local("Hough transform (peaks deleted)",
00911 "hough_delete", hough_trans,
00912 chip, -1, -1, rotated_header,
00913 true),
00914 "Error saving hough image");
00915
00916
00917
00918 check( inputlines = cpl_image_duplicate(raw_image),
00919 "Could not duplicate image");
00920 check( uves_draw_orders(ordertable, inputlines),
00921 "Could not draw hough orders on image");
00922
00923 check( uves_save_image_local("Lines detected by Hough transform",
00924 "inputlines", inputlines, chip, -1, -1, rotated_header, true),
00925 "Error saving hough image");
00926
00927 uves_free_image(&inputlines);
00928 }
00929
00930
00931 uves_free_image(&hough_trans);
00932 uves_free_image(&hough_original);
00933 }
00934
00935
00936
00937 check(( uves_free_image(&back_subbed),
00938 back_subbed = cpl_image_duplicate(raw_image)),
00939 "Error duplicating image");
00940
00941 uves_msg("Subtracting background (inter-order sampling)");
00942 check( uves_backsub_poly(back_subbed,
00943 ordertable, NULL,
00944 BM_METHOD,
00945 BACKSUBGRID,
00946 BACKSUBRADIUSY,
00947 BACKSUBDEGX,
00948 BACKSUBDEGY,
00949 BACKSUBKAPPA),
00950 "Could not subtract background");
00951
00952
00953
00954
00955
00956
00957
00958 check( noise = uves_define_noise(back_subbed, raw_header, 1, chip),
00959 "Error creating noise image");
00960
00961 if (DEBUG)
00962 {
00963
00964
00965 check( uves_save_image_local("Pre-processed raw frame", "preproc",
00966 back_subbed, chip, -1, -1, rotated_header, true),
00967 "Error saving image");
00968
00969
00970 check( uves_save_image_local("Noise of pre-processed image",
00971 "preproc_noise",
00972 noise, chip, -1, -1, rotated_header, true),
00973 "Error saving image");
00974 }
00975
00976
00977 check( badpixels_marked =
00978 uves_correct_badpix_all(back_subbed,
00979 raw_header,
00980 chip,
00981 binx, biny,
00982 true,
00983 red_ccd_is_new
00984 ),
00985 "Error marking bad pixels");
00986
00987 uves_msg("%d pixels marked as bad", badpixels_marked);
00988
00989
00990
00991 uves_msg("norders=%d",*norders);
00992 if(USE_GUESS_TAB==2) {
00993 ord_min=cpl_table_get_column_min(ordertable,"Order");
00994 if (ord_min>1) {
00995 cpl_table_subtract_scalar(ordertable,"Order",ord_min-1);
00996 }
00997 }
00998
00999 check( tracetable = uves_locate_orders(back_subbed,
01000 noise,
01001 ordertable,
01002 TRACESTEP,
01003 MINTHRESH,
01004 MAXGAP,
01005 MAXRMS,
01006 DEFPOL1, DEFPOL2,
01007 KAPPA,
01008 bivariate_fit,
01009 norders), "Could not trace orders");
01010
01011 if(USE_GUESS_TAB==2) {
01012 if (ord_min>1) {
01013 cpl_table_add_scalar(ordertable,"Order",ord_min-1);
01014 }
01015 }
01016
01017 if (false)
01018
01019
01020
01021 {
01022 check(uves_physmod_chop_otab(raw_header,chip,&tracetable,"Order",
01023 &abs_ord_min,&abs_ord_max),
01024 "Could not run uves_physmod_chop_otab on trace order table");
01025 }
01026
01027
01028
01029
01030
01031
01032 if (DEBUG) check( uves_save_table_local("Basic order table", "basic",
01033 ordertable, chip, -1, -1, raw_header, NULL),
01034 "Error saving table");
01035
01036 cleanup:
01037 uves_free_image(&back_subbed);
01038 uves_free_image(&noise);
01039 uves_free_image(&hough_trans);
01040 uves_polynomial_delete(&guess_locations);
01041
01042
01043 uves_free_image(&hough_original);
01044 uves_free_image(&inputlines);
01045 uves_free_table(&ordertable);
01046
01047 return tracetable;
01048 }
01049
01050
01065
01066 void
01067 uves_orderpos_exe_body(cpl_frameset *frames,
01068 bool flames,
01069 const char *recipe_id,
01070 const cpl_parameterlist *parameters,
01071 const char *starttime)
01072 {
01073
01074
01075
01076
01077
01078 bool DEBUG;
01079
01080 int USE_GUESS_TAB, RADX, RADY;
01081 background_measure_method BM_METHOD;
01082 int BACKSUBGRID;
01083 int BACKSUBRADIUSY;
01084 double BACKSUBKAPPA;
01085 int BACKSUBDEGX;
01086 int BACKSUBDEGY;
01087
01088 int SAMPLEWIDTH;
01089 double MINSLOPE, MAXSLOPE;
01090 int SLOPERES;
01091 int NORDERS=0;
01092 double PTHRES;
01093
01094 int TRACESTEP;
01095 double MINTHRESH;
01096 double MAXGAP;
01097
01098 double MAXRMS;
01099 int DEFPOL1_par;
01100 int DEFPOL2_par;
01101 double KAPPA;
01102 const char* PROCESS_CHIP=NULL;
01103
01104
01105 cpl_image *master_bias = NULL;
01106 uves_propertylist *master_bias_header = NULL;
01107
01108
01109
01110 cpl_image *raw_image[2] = {NULL, NULL};
01111 uves_propertylist *raw_header[2] = {NULL, NULL};
01112 uves_propertylist *rotated_header[2] = {NULL, NULL};
01113 cpl_image *raw_image_int = NULL;
01114
01115
01116 uves_propertylist *guess_header = NULL;
01117 cpl_table *guess_table = NULL;
01118
01119
01120 cpl_table *tracetable = NULL;
01121 polynomial *bivariate_fit = NULL;
01122 cpl_table *traces = NULL;
01123 uves_propertylist *product_header = NULL;
01124 cpl_table* qclog[2] = {NULL, NULL};
01125
01126
01127 const char *raw_filename = "";
01128 char *product_filename = NULL;
01129 int ord_predict = 0;
01130 bool norders_is_guess = false;
01131 bool blue;
01132 enum uves_chip chip;
01133 int binx = 0;
01134 int biny = 0;
01135
01136
01137 const char *guess_filename = "";
01138 const char *chip_name = "";
01139 const char *master_bias_filename = "";
01140
01141 int raw_index =0;
01142 int norders = 0;
01143
01144 int DEFPOL1 = 0;
01145 int DEFPOL2 = 0;
01146
01147 bool load_guess = false;
01148
01149 int plate_no;
01150
01151 int samples_per_order =0;
01152 char values[80];
01153
01154 int i=0;
01155 int j=0;
01156
01157
01158
01159 {
01160
01161 check( uves_get_parameter(parameters, NULL, "uves", "debug", CPL_TYPE_BOOL, &DEBUG),
01162 "Could not read parameter");
01163 check( uves_get_parameter(parameters, NULL, "uves", "process_chip", CPL_TYPE_STRING, &PROCESS_CHIP),
01164 "Could not read parameter");
01165 uves_string_toupper((char*)PROCESS_CHIP);
01166
01167
01168 check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.use_guess_tab",
01169 CPL_TYPE_INT , &USE_GUESS_TAB), "Could not read parameter");
01170 check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.radx",
01171 CPL_TYPE_INT , &RADX), "Could not read parameter");
01172 check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.rady",
01173 CPL_TYPE_INT , &RADY), "Could not read parameter");
01174
01175 check( BM_METHOD = uves_get_bm_method(parameters, recipe_id, "preproc"),
01176 "Could not read background measuring method");
01177
01178 check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.backsubgrid",
01179 CPL_TYPE_INT , &BACKSUBGRID),
01180 "Could not read parameter");
01181 check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.backsubradiusy",
01182 CPL_TYPE_INT, &BACKSUBRADIUSY), "Could not read parameter");
01183 check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.backsubkappa",
01184 CPL_TYPE_DOUBLE,&BACKSUBKAPPA), "Could not read parameter");
01185 check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.backsubdegx",
01186 CPL_TYPE_INT , &BACKSUBDEGX), "Could not read parameter");
01187 check( uves_get_parameter(parameters, NULL, recipe_id, "preproc.backsubdegy",
01188 CPL_TYPE_INT , &BACKSUBDEGY), "Could not read parameter");
01189
01190 check( uves_get_parameter(parameters, NULL, recipe_id, "hough.samplewidth" ,
01191 CPL_TYPE_INT , &SAMPLEWIDTH), "Could not read parameter");
01192 check( uves_get_parameter(parameters, NULL, recipe_id, "hough.minslope" ,
01193 CPL_TYPE_DOUBLE, &MINSLOPE ), "Could not read parameter");
01194 check( uves_get_parameter(parameters, NULL, recipe_id, "hough.maxslope" ,
01195 CPL_TYPE_DOUBLE, &MAXSLOPE ), "Could not read parameter");
01196 check( uves_get_parameter(parameters, NULL, recipe_id, "hough.sloperes" ,
01197 CPL_TYPE_INT , &SLOPERES ), "Could not read parameter");
01198
01199
01200
01201
01202 check( uves_get_parameter(parameters, NULL, recipe_id, "hough.pthres" ,
01203 CPL_TYPE_DOUBLE, &PTHRES ), "Could not read parameter");
01204
01205 check( uves_get_parameter(parameters, NULL, recipe_id, "trace.tracestep" ,
01206 CPL_TYPE_INT , &TRACESTEP ), "Could not read parameter");
01207 check( uves_get_parameter(parameters, NULL, recipe_id, "trace.minthresh" ,
01208 CPL_TYPE_DOUBLE, &MINTHRESH ), "Could not read parameter");
01209 check( uves_get_parameter(parameters, NULL, recipe_id, "trace.maxgap" ,
01210 CPL_TYPE_DOUBLE, &MAXGAP ), "Could not read parameter");
01211
01212 check( uves_get_parameter(parameters, NULL, recipe_id, "reject.maxrms" ,
01213 CPL_TYPE_DOUBLE, &MAXRMS ), "Could not read parameter");
01214 check( uves_get_parameter(parameters, NULL, recipe_id, "reject.defpol1" ,
01215 CPL_TYPE_INT , &DEFPOL1_par ), "Could not read parameter");
01216 check( uves_get_parameter(parameters, NULL, recipe_id, "reject.defpol2" ,
01217 CPL_TYPE_INT , &DEFPOL2_par), "Could not read parameter");
01218 check( uves_get_parameter(parameters, NULL, recipe_id, "reject.kappa" ,
01219 CPL_TYPE_DOUBLE, &KAPPA ), "Could not read parameter");
01220
01221
01222
01223 assure( MINSLOPE < MAXSLOPE , CPL_ERROR_ILLEGAL_INPUT,
01224 "Minimum slope must be smaller than maximum slope (min = %f; max = %f)",
01225 MINSLOPE, MAXSLOPE);
01226 if (MAXSLOPE > 0.5){
01227 uves_msg_warning("Hough transformation might fail when searching for "
01228 "lines with slope larger than 0.5 (maxslope = %f)", MAXSLOPE);
01229 }
01230
01231 if (DEFPOL1_par >= 6 || DEFPOL2_par >= 6)
01232 {
01233 uves_msg_warning("Polynomial fitting might be unstable with "
01234 "polynomial degrees higher than 5");
01235 }
01236
01237 }
01238
01239
01240 check( uves_load_orderpos(frames,
01241 flames,
01242 &raw_filename, raw_image,
01243 raw_header, rotated_header, &blue), "Error loading raw frame");
01244
01245
01246 check (binx = uves_pfits_get_binx(raw_header[0]),
01247 "Could not read x binning factor from input header");
01248 check (biny = uves_pfits_get_biny(raw_header[0]),
01249 "Could not read y binning factor from input header");
01250
01251
01252
01253
01254
01255
01256
01257 MINSLOPE = (MINSLOPE*biny)/binx;
01258 MAXSLOPE = (MAXSLOPE*biny)/binx;
01259
01260 ord_predict = NORDERS;
01261
01262
01263 for (chip = uves_chip_get_first(blue);
01264 chip != UVES_CHIP_INVALID;
01265 chip = uves_chip_get_next(chip))
01266 {
01267
01268 if(strcmp(PROCESS_CHIP,"REDU") == 0) {
01269 chip = uves_chip_get_next(chip);
01270 }
01271
01272
01273
01274 raw_index = uves_chip_get_index(chip);
01275 norders = 0;
01276
01277 DEFPOL1 = DEFPOL1_par;
01278 DEFPOL2 = DEFPOL2_par;
01279
01280 uves_msg("Processing %s chip in '%s'",
01281 uves_chip_tostring_upper(chip), raw_filename);
01282
01283 check_nomsg( chip_name = uves_pfits_get_chipid(raw_header[raw_index], chip));
01284
01285 uves_msg_debug("Binning = %dx%d", binx, biny);
01286
01287
01288
01289
01290
01291
01292 if (NORDERS == 0)
01293 {
01294
01295
01296
01297 norders_is_guess = true;
01298
01299 uves_free_propertylist(&guess_header);
01300
01301 if (cpl_frameset_find(frames, UVES_DRS_SETUP(flames, chip)) != NULL)
01302 {
01303 uves_msg_low("No guess order table found");
01304
01305 check( uves_load_drs(frames, flames, chip_name, &guess_filename,
01306 &guess_header, chip),
01307 "Error loading setup table");
01308
01309 uves_msg("Using setup table in '%s'", guess_filename);
01310
01311 check( ord_predict = uves_pfits_get_ordpred(guess_header),
01312 "Could not read predicted number "
01313 "of orders from DRS table header");
01314 }
01315 else if (cpl_frameset_find(frames,
01316 UVES_ORDER_TABLE(flames, chip)) != NULL ||
01317 cpl_frameset_find(frames,
01318 UVES_GUESS_ORDER_TABLE(flames, chip)) != NULL)
01319 {
01320 load_guess = (
01321 cpl_frameset_find(frames,
01322 UVES_GUESS_ORDER_TABLE(flames, chip))
01323 != NULL);
01324
01325 uves_free_table(&guess_table);
01326
01327 check( uves_load_ordertable(
01328 frames,
01329 flames,
01330 chip_name,
01331 &guess_filename,
01332 &guess_table,
01333 &guess_header,
01334 NULL,
01335 NULL,
01336 NULL,
01337 NULL, NULL,
01338 NULL, NULL,
01339 chip,
01340 load_guess),
01341 "Error loading guess order table");
01342
01343 uves_msg("Using guess order table in '%s'", guess_filename);
01344
01345 check( ord_predict = uves_pfits_get_ordpred(guess_header),
01346 "Could not read predicted number of orders from "
01347 "guess order table header");
01348 }
01349 else
01350 {
01351 uves_msg("No guess table found");
01352 }
01353 }
01354 else
01355 {
01356
01357
01358
01359
01360 norders_is_guess = false;
01361 }
01362
01363
01364 uves_free_image(&master_bias);
01365 uves_free_propertylist(&master_bias_header);
01366 if (cpl_frameset_find(frames, UVES_MASTER_BIAS(chip)) != NULL)
01367 {
01368 uves_free_image(&master_bias);
01369 uves_free_propertylist(&master_bias_header);
01370 check( uves_load_mbias(frames,
01371 chip_name,
01372 &master_bias_filename, &master_bias,
01373 &master_bias_header, chip),
01374 "Error loading master bias");
01375
01376 uves_msg_low("Using master bias in '%s'", master_bias_filename);
01377 cpl_image_subtract(raw_image[raw_index],master_bias);
01378
01379 }
01380 else
01381 {
01382 uves_msg_low("No master bias in SOF. Bias subtraction not done");
01383 }
01384
01385
01386 check((uves_free_table (&tracetable),
01387 uves_polynomial_delete(&bivariate_fit),
01388 tracetable = uves_orderpos_process_chip(
01389 raw_image[raw_index],
01390 raw_header[raw_index],
01391 rotated_header[raw_index],
01392 chip, binx, biny,
01393 DEBUG,
01394 USE_GUESS_TAB,
01395 RADX, RADY,
01396 BM_METHOD,
01397 BACKSUBGRID,
01398 BACKSUBRADIUSY,
01399 BACKSUBKAPPA,
01400 BACKSUBDEGX, BACKSUBDEGY,
01401 SAMPLEWIDTH,
01402 MINSLOPE, MAXSLOPE,
01403 SLOPERES,
01404 ord_predict,
01405 norders_is_guess,
01406 PTHRES,
01407 TRACESTEP,
01408 MINTHRESH,
01409 MAXGAP,
01410 MAXRMS,
01411 &DEFPOL1,
01412 &DEFPOL2,
01413 KAPPA,
01414 &bivariate_fit,
01415 &norders,
01416 guess_table)),
01417 "Error processing chip");
01418
01419
01420 uves_msg("Saving products...");
01421
01422
01423
01424
01425 uves_free_propertylist(&product_header);
01426 product_header = uves_propertylist_new();
01427
01428
01429 check( uves_pfits_set_ordpred( product_header, norders),
01430 "Error writing number of detected orders");
01431
01432 if (flames)
01433 {
01434
01435 check( plate_no = uves_flames_pfits_get_plateid(raw_header[raw_index]),
01436 "Error reading plate id");
01437
01438 uves_flames_pfits_set_newplateid(product_header, plate_no);
01439 }
01440
01441
01442 {
01443 samples_per_order =
01444 cpl_image_get_size_x(raw_image[raw_index]) / TRACESTEP;
01445
01446 uves_qclog_delete(&qclog[0]);
01447 qclog[0] = uves_qclog_init(raw_header[raw_index], chip);
01448 check_nomsg( uves_orderpos_qclog(tracetable,
01449 flames,
01450 ord_predict,
01451 norders,
01452 samples_per_order,
01453 raw_header[raw_index],chip,qclog[0]));
01454 }
01455
01456 if (flames) {
01457
01458
01459
01460
01461 snprintf(values, 80, "-1 -1 -1 -1 -1 %d %d", DEFPOL1, DEFPOL2);
01462
01463 uves_propertylist_append_string(product_header,
01464 "HISTORY", "'COEFFI','I*4'");
01465 uves_propertylist_append_string(product_header,
01466 "HISTORY", values);
01467 uves_propertylist_append_string(product_header,
01468 "HISTORY", " ");
01469
01470
01471 uves_propertylist_append_string(product_header,
01472 "HISTORY", "'COEFFD','R*8'");
01473 {
01474
01475 for (j = 0; j <= DEFPOL2; j++) {
01476 for (i = 0; i <= DEFPOL1; i++) {
01477 snprintf(values, 80, "%g",
01478 uves_polynomial_get_coeff_2d(bivariate_fit, i, j));
01479 uves_propertylist_append_string(product_header,
01480 "HISTORY", values);
01481 }
01482 }
01483 }
01484 uves_propertylist_append_string(product_header,
01485 "HISTORY", " ");
01486
01487
01488 uves_propertylist_append_string(product_header,
01489 "HISTORY", "'COEFFR','R*4'");
01490 snprintf(values, 80, "%g %g",
01491 cpl_table_get_column_min(tracetable, "X"),
01492 cpl_table_get_column_max(tracetable, "X"));
01493 uves_propertylist_append_string(product_header,
01494 "HISTORY", values);
01495
01496 snprintf(values, 80, "%g %g",
01497 cpl_table_get_column_min(tracetable, "Order"),
01498 cpl_table_get_column_max(tracetable, "Order"));
01499 uves_propertylist_append_string(product_header,
01500 "HISTORY", values);
01501
01502 uves_propertylist_append_string(product_header,
01503 "HISTORY", " ");
01504 }
01505
01506 check(( cpl_free(product_filename),
01507 product_filename = uves_order_table_filename(chip),
01508 uves_frameset_insert(frames,
01509 tracetable,
01510 CPL_FRAME_GROUP_PRODUCT,
01511 CPL_FRAME_TYPE_TABLE,
01512 CPL_FRAME_LEVEL_INTERMEDIATE,
01513 product_filename,
01514 UVES_ORD_TAB(flames, chip),
01515 raw_header[raw_index],
01516 product_header,
01517 NULL,
01518 parameters,
01519 recipe_id,
01520 PACKAGE "/" PACKAGE_VERSION,
01521 qclog,
01522 starttime, true, 0)),
01523 "Could not add trace table %s to frameset", product_filename);
01524 uves_qclog_delete(&qclog[0]);
01525 uves_msg("Trace table %s added to frameset", product_filename);
01526
01527
01528 check( uves_save_polynomial(bivariate_fit, product_filename, NULL),
01529 "Could not write polynomial to file %s", product_filename);
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540 {
01541
01542 uves_free_table(&traces);
01543 traces = uves_ordertable_traces_new();
01544 uves_ordertable_traces_add(traces, 0, 0.0, 1);
01545
01546 check( cpl_table_save(traces,
01547 NULL,
01548
01549 NULL,
01550 product_filename,
01551
01552 CPL_IO_EXTEND),
01553 "Error appending table to file '%s'", product_filename);
01554 }
01555
01556
01557 if (flames) {
01558
01559
01560
01561 uves_free_image(&raw_image_int);
01562 raw_image_int = cpl_image_cast(raw_image[raw_index],
01563 CPL_TYPE_INT);
01564
01565 check(( cpl_free(product_filename),
01566 product_filename = uves_ordef_filename(chip),
01567 uves_frameset_insert(frames,
01568 raw_image_int,
01569 CPL_FRAME_GROUP_PRODUCT,
01570 CPL_FRAME_TYPE_IMAGE,
01571 CPL_FRAME_LEVEL_INTERMEDIATE,
01572 product_filename,
01573 FLAMES_ORDEF(flames, chip),
01574 raw_header[raw_index],
01575 rotated_header[raw_index],
01576 NULL,
01577 parameters,
01578 recipe_id,
01579 PACKAGE "/" PACKAGE_VERSION,
01580 NULL,
01581 starttime, false,
01582 CPL_STATS_MIN | CPL_STATS_MAX)),
01583 "Could not add raw frame %s to frameset", product_filename);
01584
01585 uves_msg("Raw frame %s added to frameset", product_filename);
01586 uves_free_image(&raw_image_int);
01587 }
01588
01589 if(strcmp(PROCESS_CHIP,"REDL") == 0) {
01590 chip = uves_chip_get_next(chip);
01591 }
01592
01593
01594 }
01595
01596 cleanup:
01597
01598 uves_free_image(&(raw_image[0]));
01599 uves_free_image(&(raw_image[1]));
01600 uves_free_image(&raw_image_int);
01601 uves_free_propertylist(&(raw_header[0]));
01602 uves_free_propertylist(&(raw_header[1]));
01603 uves_free_propertylist(&(rotated_header[0]));
01604 uves_free_propertylist(&(rotated_header[1]));
01605
01606
01607 uves_free_image(&master_bias);
01608 uves_free_propertylist(&master_bias_header);
01609
01610
01611 uves_free_propertylist(&guess_header);
01612 uves_free_table (&guess_table);
01613
01614
01615 uves_qclog_delete(&qclog[0]);
01616 uves_free_table (&tracetable);
01617 uves_polynomial_delete(&bivariate_fit);
01618 uves_free_table (&traces);
01619 uves_free_propertylist(&product_header);
01620 cpl_free(product_filename);
01621
01622 return;
01623 }
01634 static void uves_orderpos_qclog(cpl_table* table,
01635 bool flames,
01636 int pord,
01637 int dord,
01638 int samples_per_order,
01639 uves_propertylist* raw_header,
01640 enum uves_chip chip,
01641 cpl_table* qclog)
01642 {
01643 const char* chip_name;
01644 const char* grat_name;
01645 const char* ins_mode;
01646 double grat_wlen=0;
01647
01648 uves_qclog_add_string(qclog,
01649 "QC TEST1 ID",
01650 flames ?
01651 "Single-Fibre-Order-Definition-Results" :
01652 "Order-Definition-Results",
01653 "Name of QC test",
01654 "%s");
01655
01656 check_nomsg( chip_name=uves_pfits_get_chip_name(raw_header,chip) );
01657
01658
01659 uves_qclog_add_string(qclog,
01660 uves_remove_string_prefix(UVES_CHIP_NAME(chip),"ESO "),
01661 chip_name,
01662 "Grating unique ID",
01663 "%s");
01664
01665
01666 check_nomsg(grat_name=uves_pfits_get_gratname(raw_header,chip));
01667
01668
01669
01670 uves_qclog_add_string(qclog,
01671 uves_remove_string_prefix(UVES_GRATNAME(chip),"ESO "),
01672 grat_name,
01673 "Cross disperser ID",
01674 "%s");
01675
01676
01677 check_nomsg(ins_mode=uves_pfits_get_insmode(raw_header));
01678 uves_qclog_add_string(qclog,
01679 uves_remove_string_prefix(UVES_INSMODE,"ESO "),
01680 ins_mode,
01681 "Instrument mode used.",
01682 "%s");
01683
01684
01685 check_nomsg(grat_wlen=uves_pfits_get_gratwlen(raw_header,chip));
01686 uves_qclog_add_double(qclog,
01687 uves_remove_string_prefix(UVES_GRATWLEN(chip),"ESO "),
01688 grat_wlen,
01689 "Grating central wavelength [nm]",
01690 "%.1f");
01691
01692 uves_msg_debug("chip_name=%s grat_name=%s ins_mode=%s grat_wlen=%f",
01693 chip_name,grat_name,ins_mode,grat_wlen);
01694
01695 uves_qclog_add_double(qclog,
01696 "QC ORD RESIDMIN",
01697 cpl_table_get_column_min(table,"Residual"),
01698 "min resid in ord def",
01699 "%8.4f");
01700
01701 uves_qclog_add_double(qclog,
01702 "QC ORD RESIDMAX",
01703 cpl_table_get_column_max(table,"Residual"),
01704 "max resid in ord def",
01705 "%8.4f");
01706
01707 uves_qclog_add_double(qclog,
01708 "QC ORD RESIDAVG",
01709 cpl_table_get_column_mean(table,"Residual"),
01710 "mean resid in ord def",
01711 "%8.4f");
01712
01713 uves_qclog_add_double(qclog,
01714 "QC ORD RESIDRMS",
01715 cpl_table_get_column_stdev(table,"Residual"),
01716 "rms resid in ord def",
01717 "%8.4f");
01718
01719 uves_qclog_add_int(qclog,
01720 "QC ORD NPRED",
01721 pord,
01722 "predicted number of orders",
01723 "%d");
01724
01725 uves_qclog_add_int(qclog,
01726 "QC ORD NDET",
01727 dord,
01728 "detected number of orders",
01729 "%d");
01730
01731 uves_qclog_add_int(qclog,
01732 "QC ORD NPOSALL",
01733 dord * samples_per_order,
01734 "Number of position found",
01735 "%d");
01736
01737 uves_qclog_add_int(qclog,
01738 "QC ORD NPOSSEL",
01739 cpl_table_get_nrow(table),
01740 "Number of position selected",
01741 "%d");
01742
01743 uves_qclog_add_int(qclog,
01744 "QC ORDMIN",
01745 cpl_table_get_column_min(table,"Order"),
01746 "Number of position selected",
01747 "%d");
01748
01749 uves_qclog_add_int(qclog,
01750 "QC ORDMAX",
01751 cpl_table_get_column_max(table,"Order"),
01752 "Number of position selected",
01753 "%d");
01754
01755
01756
01757
01758
01759 check_nomsg(uves_qclog_add_string(qclog,
01760 uves_remove_string_prefix(UVES_READ_SPEED,"ESO "),
01761 uves_pfits_get_readspeed(raw_header),
01762 "Readout speed",
01763 "%s"));
01764
01765 check_nomsg(uves_qclog_add_int(qclog,
01766 uves_remove_string_prefix(UVES_BINX, "ESO "),
01767 uves_pfits_get_binx(raw_header),
01768 "Binning factor along X",
01769 "%d"));
01770
01771 check_nomsg(uves_qclog_add_int(qclog,
01772 uves_remove_string_prefix(UVES_BINY, "ESO "),
01773 uves_pfits_get_biny(raw_header),
01774 "Binning factor along Y",
01775 "%d"));
01776
01777 check_nomsg(uves_qclog_add_string(qclog,
01778 uves_remove_string_prefix(UVES_INSPATH,"ESO "),
01779 uves_pfits_get_inspath(raw_header),
01780 "Optical path used (h).",
01781 "%s"));
01782
01783 cleanup:
01784 return;
01785
01786 }