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