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