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