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