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 #ifdef HAVE_CONFIG_H
00178 # include <config.h>
00179 #endif
00180
00184
00185
00186 #include <uves_wavecal_body.h>
00187
00188
00189 #include <uves.h>
00190
00191
00192 #include <uves_extract.h>
00193 #include <uves_flatfield.h>
00194 #include <uves_wavecal_search.h>
00195 #include <uves_wavecal_firstsolution.h>
00196 #include <uves_wavecal_identify.h>
00197 #include <uves_rebin.h>
00198 #include <uves_merge.h>
00199
00200
00201 #include <uves_wavecal_utils.h>
00202 #include <uves_utils.h>
00203 #include <uves_utils_wrappers.h>
00204 #include <uves_plot.h>
00205 #include <uves_parameters.h>
00206 #include <uves_dfs.h>
00207 #include <uves_pfits.h>
00208 #include <uves_qclog.h>
00209 #include <uves_recipe.h>
00210 #include <uves_error.h>
00211
00212 #include <irplib_access.h>
00213 #include <cpl.h>
00214
00215 #include <stdbool.h>
00216 #include <float.h>
00217
00218
00219
00220
00221
00222 #define DRS_PTHRES_MAX 55000
00223 #define DRS_PTHRES_MIN -20
00224 #define DRS_CVEL_MIN -6.
00225 #define DRS_CVEL_MAX +6.
00226
00227
00228
00229
00230 static void uves_wavecal_qclog(const cpl_table* table,
00231 int firstabs,
00232 int lastabs,
00233 const cpl_image *arclamp,
00234 const uves_propertylist* raw_header,
00235 bool flames,
00236 int trace_number,
00237 int fibre_mask,
00238 double offset,
00239 enum uves_chip chip,
00240 cpl_table* qclog);
00241
00242 static void uves_wavecal_qclog_intmon(cpl_table* table,
00243 const cpl_table *line_intmon,
00244 const uves_propertylist* raw_header,
00245 bool flames,
00246 int fibre,
00247 enum uves_chip chip,
00248 cpl_table* qclog);
00249
00250
00251
00252
00253
00254 const char * const uves_wavecal_desc_short = "Performs the wavelength calibration";
00255
00256 const char * const uves_wavecal_desc =
00257 "The recipe performs a wavelength calibration for each extraction window.\n"
00258 "Conceptually, each chip contains a number of order lines, each of which\n"
00259 "contains a number of fibre traces, each of which contains a number of\n"
00260 "extraction windows. For UVES data, there is only one trace per order and\n"
00261 "three extraction windows (sky, object, sky). For FLAMES/UVES data there\n"
00262 "are multiple traces per order but only one extraction window per trace.\n"
00263 "The number of traces is defined in the order table while the geometry of\n"
00264 "the extraction windows is specified by recipe parameters (see below).\n"
00265 "\n"
00266 "Expected input for this recipe is an arc lamp frame, ARC_LAMP_xxx or\n"
00267 "ECH_ARC_LAMP_xxx (where xxx=BLUE, RED), order table(s) for each chip,\n"
00268 "ORDER_TABLE_xxxx (where xxxx=BLUE, REDL, REDU), 'guess' line table(s)\n"
00269 "for each chip, LINE_TABLE_xxxx, a wavelength catalogue table, \n"
00270 "LINE_REFER_TABLE, and optionally a wavelength table of bright lines,\n"
00271 "LINE_INTMON_TABLE, used only for computing Quality Control parameters.\n"
00272 "\n"
00273 "The output line table(s), LINE_TABLE_xxxx, contains the columns\n"
00274 "X : Horizontal position (from Gaussian fit) of detected line\n"
00275 "dX : Uncertainty (one sigma) of X\n"
00276 "Ynew : Vertical position of detected line\n"
00277 "XWidth : Width (in pixels) of detected line from Gaussian fit\n"
00278 "Peak : Intensity of detected line\n"
00279 "Background : Fitted background (ADU) of detected line\n"
00280 "Slope : Linear background slope (ADU/pixel) of detected line\n"
00281 " from Gaussian fit\n"
00282 "Intensity : Intensity of detected line scaled to unit exposure\n"
00283 " time. (This column only present if a LINE_INTMON_TABLE\n"
00284 " is provided.)\n"
00285 "Order : Absolute order number of detected line\n"
00286 "Y : Relative order number of detected line\n"
00287 " (it's not a very descriptive column name)\n"
00288 "WaveC : Wavelength of this line (computed using the resulting\n"
00289 " dispersion relation)\n"
00290 "dLambdaC : Uncertainty (one sigma) of 'WaveC'.\n"
00291 "Pixel : The width in w.l.u. of a pixel (computed locally).\n"
00292 "Residual : Residual (in w.l.u.) of this line\n"
00293 "Residual_pix : Residual (in pixels) of this line\n"
00294 "Lambda_candidate : Nearest line in catalogue\n"
00295 "dLambda_cat_sq : Squared distance to nearest catalogue line\n"
00296 "dLambda_nn_sq : Squared distance to nearest neighbour multiplied by ALPHA\n"
00297 "Ident : The wavelength associated with this emission line,\n"
00298 " or invalid if this line was not identified\n"
00299 "dIdent : Uncertainty of catalogue wavelength\n"
00300 "Select : 1 if the line was identified, 0 otherwise\n"
00301 "NLinSol : 1 if the line was identified and accepted for the\n"
00302 " polynomial fit, 0 otherwise\n"
00303 "Intensity : Intensity of detected line scaled to unit exposure\n"
00304 " time. (This column is present only if a LINE_INTMON_TABLE\n"
00305 " is provided.)\n"
00306 "\n"
00307 "The 2nd table extension contains the dispersion relation (a 2d polynomial).\n"
00308 "The 3rd table extension contains the map from (pixel, pixel)-space to\n"
00309 " physical order numbers (used internally by the calibration recipe; \n"
00310 "another 2d polynomial).\n"
00311 "\n"
00312 "If there is more than one extraction window, the results of each calibration\n"
00313 "is stored in subsequent table extensions of the same FITS file. For \n"
00314 "example, extensions 4, 5 and 6 would contain the resulting line table \n"
00315 "(and its two associated polynomials) for the second extraction window. \n"
00316 "The results for the calibration of the n'th extraction window is stored \n"
00317 "in extensions (3*n - 2) to 3*n.\n";
00320
00321
00322
00323
00324
00332
00333 int
00334 uves_wavecal_define_parameters_body(cpl_parameterlist *parameters,
00335 const char *recipe_id, double slit)
00336 {
00337 const char *subcontext;
00338
00339
00340
00341
00342
00343 if (uves_define_global_parameters(parameters) != CPL_ERROR_NONE)
00344 {
00345 return -1;
00346 }
00347
00348
00349
00350
00351
00352 subcontext = NULL;
00353
00354
00355 uves_par_new_range("nwindows",
00356 CPL_TYPE_INT,
00357 "Number of extraction windows per trace. "
00358 "The windows will be aligned (i.e. no overlap "
00359 "and no spacing between adjacent windows). "
00360 "Unless an offset is specified, the middle "
00361 "window(s) is centered on the trace",
00362 strcmp(recipe_id, "flames_cal_wavecal") == 0 ?
00363 1 : 3,
00364 1, INT_MAX);
00365
00366
00367 uves_par_new_range("length",
00368 CPL_TYPE_DOUBLE,
00369 "Length (in pixels) of each extraction window. "
00370 "This parameter is also equal to the seperation of "
00371 "adjacent window centers, causing the extraction "
00372 "windows to always be aligned. The parameter is "
00373 "automatically adjusted according to the binning "
00374 "of the input raw frame. If negative, the extraction "
00375 "window length is determined automatically "
00376 "to cover the full slit",
00377 slit, -2.0, DBL_MAX);
00378
00379
00380 uves_par_new_range("offset",
00381 CPL_TYPE_DOUBLE,
00382 "A global offset (in pixels) of all extraction windows",
00383 0.0, 0.0, DBL_MAX);
00384
00385
00386 if (uves_propagate_parameters_step(UVES_EXTRACT_ID, parameters,
00387 recipe_id, NULL) != 0)
00388 {
00389 return -1;
00390 }
00391
00392
00393 #if 0
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 {
00406 const char *profile = "constant";
00407 double kappa = -1;
00408
00409 if (uves_set_parameter_default(parameters,
00410 recipe_id, UVES_EXTRACT_ID ".profile",
00411 CPL_TYPE_STRING, &profile)
00412 != CPL_ERROR_NONE)
00413 {
00414 return -1;
00415 }
00416
00417
00418
00419 if (uves_set_parameter_default(parameters,
00420 recipe_id, UVES_EXTRACT_ID ".kappa",
00421 CPL_TYPE_DOUBLE, &kappa)
00422 != CPL_ERROR_NONE)
00423 {
00424 return -1;
00425 }
00426 }
00427 #else
00428 {
00429 const char *method = "average";
00430
00431 if (uves_set_parameter_default(parameters,
00432 recipe_id, UVES_EXTRACT_ID ".method",
00433 CPL_TYPE_STRING, &method)
00434 != CPL_ERROR_NONE)
00435 {
00436 return -1;
00437 }
00438
00439 }
00440 #endif
00441
00442
00443
00444
00445
00446 subcontext = "search";
00447
00448
00449 uves_par_new_range("range",
00450 CPL_TYPE_INT,
00451 "Width (in pixels) of search window is 2*range + 1. "
00452 "This parameter is automatically adjusted "
00453 "according to binning.",
00454 8, 1, INT_MAX);
00455
00456
00457 uves_par_new_range("minlines",
00458 CPL_TYPE_INT,
00459 "Minimum number of lines to detect. If zero, "
00460 "the default value (2000 for BLUE/REDL chips; "
00461 "1000 for REDU chip) is used.",
00462 0, 0, INT_MAX);
00463
00464
00465 uves_par_new_range("maxlines",
00466 CPL_TYPE_INT,
00467 "Maximum number of lines to detect. If zero, "
00468 "the default value (2400 for BLUE/REDL chip; "
00469 "1400 for REDU chip) is used.",
00470 0, 0, INT_MAX);
00471
00472
00473 uves_par_new_enum("centeringmethod",
00474 CPL_TYPE_STRING,
00475 "Line centering method",
00476 "gaussian",
00477 2,
00478 "gaussian", "gravity");
00479
00480
00481
00482
00483
00484
00485 subcontext = "first";
00486
00487
00488 uves_par_new_range("shiftmax",
00489 CPL_TYPE_DOUBLE,
00490 "The maximum shift (in pixels) compared to "
00491 "guess solution. This parameter is automatically "
00492 "corrected for binning",
00493 10.0, 0.0, DBL_MAX);
00494
00495
00496 uves_par_new_range("shiftstep",
00497 CPL_TYPE_DOUBLE,
00498 "The step size (in pixels) used when searching "
00499 "for the optimum shift. This parameter is "
00500 "automatically corrected for binning",
00501 0.1, 0.0, DBL_MAX);
00502
00503
00504 uves_par_new_range("shifttoler",
00505 CPL_TYPE_DOUBLE,
00506 "Tolerance (in pixels) when matching shifted lines. "
00507 "This parameter is not adjusted according to binning",
00508 0.05, 0.0, DBL_MAX);
00509
00510
00511
00512
00513
00514
00515 subcontext = "identify";
00516
00517
00518 uves_par_new_range("alpha",
00519 CPL_TYPE_DOUBLE,
00520 "The parameter that controls the distance to the "
00521 "nearest neighbours",
00522 0.1, 0.0, 1.0);
00523
00524
00525 uves_par_new_range("maxerror",
00526 CPL_TYPE_DOUBLE,
00527 "This parameter controls the graceful exit of "
00528 "the identification loop. If the RMS of the "
00529 "global fit exceeds this value (in pixels) the "
00530 "iteration stops",
00531 20.0, 0.0, DBL_MAX);
00532
00533
00534 uves_par_new_range("degree",
00535 CPL_TYPE_INT,
00536 "Degrees of the global 2d dispersion polynomial. If "
00537 "a negative number is specified, the polynomial "
00538 "degrees are automatically selected by starting from "
00539 "(1, 1) and inreasing the degrees as long as the RMS "
00540 "residual decreases significantly",
00541 5, -2, INT_MAX);
00542
00543
00544
00545
00546
00547
00548 subcontext = "calibrate";
00549
00550
00551 uves_par_new_value("tolerance",
00552 CPL_TYPE_DOUBLE,
00553 "Tolerance of fit. If positive, the tolerance "
00554 "is in pixel units. If negative, abs(tolerance) "
00555 "is in wavelength units. Lines with residuals "
00556 "worse than the tolerance are excluded from the "
00557 "final fit. Unlike in previous versions, this "
00558 "parameter is not corrected for CCD binning. "
00559 "This rejection based on the absolute residual in "
00560 "pixel can be effectively disabled by setting the "
00561 "tolerance to a very large number (e.g. 9999). In "
00562 "that case outliers will be rejected using only "
00563 "kappa sigma clipping.",
00564 0.6);
00565
00566
00567
00568
00569
00570 uves_par_new_value("kappa",
00571 CPL_TYPE_DOUBLE,
00572 "Lines with residuals more then kappa stdev "
00573 "are rejected from the final fit",
00574 4.0);
00575
00576
00577
00578
00579 if (uves_propagate_parameters_step(UVES_REBIN_ID, parameters,
00580 recipe_id, NULL) != 0)
00581 {
00582 return -1;
00583 }
00584
00585 return (cpl_error_get_code() != CPL_ERROR_NONE);
00586 }
00587
00588
00657
00658 static cpl_table *
00659 uves_wavecal_process_window(const cpl_image *arclamp,
00660 const cpl_image *arclamp_noise,
00661 const uves_propertylist *rotated_header,
00662 const cpl_table *ordertable,
00663 const polynomial *order_locations,
00664 bool flat_fielded,
00665
00666 const cpl_table *guess,
00667 const cpl_table *line_refer,
00668 bool flames,
00669 int tab_in_out_oshift,
00670 double tab_in_out_yshift,
00671 enum uves_chip chip, int bin_disp,
00672 int trace, int window,
00673
00674 bool DEBUG,
00675
00676 double offset,
00677 double slitlength,
00678 const cpl_parameterlist *parameters,
00679 const char *recipe_id,
00680
00681 int RANGE,
00682 int MINLINES,
00683 int MAXLINES,
00684 centering_method CENTERING_METHOD,
00685
00686 double SHIFT_MAX,
00687 double SHIFT_STEP,
00688 double SHIFT_TOLERANCE,
00689
00690 double ALPHA,
00691 double MAXERROR,
00692 int DEGREE,
00693
00694 double TOLERANCE,
00695 double kappa,
00696
00697 polynomial **dispersion_relation,
00698 polynomial **absolute_order,
00699 int *first_absolute_order,
00700 int *last_absolute_order)
00701 {
00702 cpl_table *linetable = NULL;
00703 cpl_table *temp = NULL;
00704 cpl_image *spectrum = NULL;
00705 cpl_image *spectrum_noise = NULL;
00706 cpl_image *debug_image = NULL;
00707 polynomial *initial_dispersion = NULL;
00708 int *relative_order = NULL;
00709
00710 uves_propertylist *spectrum_header = NULL;
00711
00712 cpl_image *rebinned = NULL;
00713
00714 cpl_image *rebinned_noise = NULL;
00715
00716 uves_propertylist *rebinned_header = NULL;
00717 cpl_image *merged = NULL;
00718 cpl_image *merged_noise = NULL;
00719 uves_propertylist *merged_header = NULL;
00720 cpl_table *info_tbl = NULL;
00721
00722
00723 cpl_image *weights = NULL;
00724 cpl_table *cr_table = NULL;
00725 cpl_image *cr_image = NULL;
00726 cpl_table *order_trace = NULL;
00727
00728 merge_method m_method = flat_fielded ? MERGE_OPTIMAL : MERGE_SUM;
00729
00730
00731 uves_free_table(&info_tbl);
00732
00733 check( spectrum = uves_extract((cpl_image *)arclamp,
00734
00735
00736
00737 (cpl_image *)arclamp_noise,
00738 NULL,
00739 ordertable,
00740 order_locations,
00741 slitlength,
00742 offset,
00743 parameters,
00744 recipe_id,
00745 true,
00746 DEBUG,
00747 chip,
00748 &spectrum_header,
00749 &spectrum_noise,
00750 NULL,
00751 NULL,
00752 &cr_table,
00753 &cr_image,
00754 NULL,
00755 &weights,
00756 &info_tbl,
00757 &order_trace),
00758 "Error extracting spectrum");
00759 uves_free_table(&info_tbl);
00760
00761
00762
00763
00764 cpl_image_fill_rejected(spectrum, 0);
00765 cpl_image_accept_all(spectrum);
00766 cpl_image_fill_rejected(spectrum_noise, 1);
00767 cpl_image_accept_all(spectrum_noise);
00768
00769
00770 if (DEBUG)
00771 {
00772 check( uves_save_image_local("Extracted spectrum", "spectrum",
00773 spectrum, chip, trace, window, spectrum_header),
00774 "Error saving spectrum");
00775
00776 check( uves_save_image_local("Extracted spectrum noise", "spectrum_noise",
00777 spectrum_noise, chip, trace, window, spectrum_header),
00778 "Error saving spectrum");
00779 }
00780
00781
00782 debug_image = cpl_image_duplicate(arclamp);
00783 check( linetable = uves_wavecal_search(spectrum,
00784 spectrum_noise,
00785 spectrum_header,
00786 flat_fielded,
00787 order_locations,
00788 debug_image,
00789 RANGE,
00790 MINLINES,
00791 MAXLINES,
00792 CENTERING_METHOD,
00793 bin_disp),
00794 "Line search failed");
00795
00796 if (flames)
00797 {
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836 }
00837
00838
00839 {
00840 int degree = 5;
00841
00842
00843 uves_polynomial_delete(&initial_dispersion);
00844 cpl_free(relative_order);
00845 check( initial_dispersion = uves_wavecal_firstsolution(linetable,
00846 guess,
00847 absolute_order,
00848 ordertable,
00849 order_locations,
00850 flames,
00851 offset,
00852 &relative_order,
00853 degree,
00854 SHIFT_MAX,
00855 SHIFT_STEP,
00856 SHIFT_TOLERANCE,
00857 MAXERROR,
00858 first_absolute_order,
00859 last_absolute_order),
00860 "Could not get first solution");
00861 }
00862
00863
00864 if (flames)
00865 {
00866
00867
00868
00869
00870
00871
00872
00873 cpl_table_add_scalar(linetable, "Y", tab_in_out_oshift);
00874 cpl_table_add_scalar(linetable, "Ynew", - tab_in_out_yshift - offset);
00875 }
00876
00877
00878 check( *dispersion_relation = uves_wavecal_identify(linetable,
00879 line_refer,
00880 initial_dispersion,
00881 DEGREE,
00882 TOLERANCE, ALPHA, MAXERROR,
00883 kappa),
00884 "Could not calibrate orders");
00885
00886 if (flames)
00887 {
00888
00889
00890
00891
00892
00893 cpl_table_add_scalar(linetable, "Ynew", + tab_in_out_yshift + offset);
00894 }
00895
00896
00897
00898
00899 if (flames || (trace == 0 && window == 2))
00900 {
00901
00902 check(( cpl_table_duplicate_column(linetable, "deltaX", linetable, "Xwidth"),
00903 cpl_table_multiply_scalar (linetable, "deltaX", TWOSQRT2LN2)),
00904 "Error creating FWHM column");
00905
00906
00907 check_nomsg( temp = uves_extract_table_rows(
00908 linetable, "NLinSol", CPL_NOT_EQUAL_TO, 0) );
00909
00910 check( uves_plot_table(temp, "Order", LINETAB_RESIDUAL, "Residual of fit"),
00911 "Plotting failed");
00912
00913 check( uves_plot_table(temp, "X", "deltaX", "line FWHM (mean = %.2f pixels)",
00914 cpl_table_get_column_mean(linetable, "deltaX")),
00915 "Plotting failed");
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928 {
00929
00930 double wavestep;
00931 double lambda_start = 0;
00932 int n_traces = 1;
00933
00934
00935 int i, nbins;
00936 bool threshold_to_positive = true;
00937
00938 cpl_table_new_column(linetable, "deltaLambda", CPL_TYPE_DOUBLE);
00939
00940 check( rebinned_noise = uves_rebin(spectrum_noise,
00941 parameters,
00942 recipe_id,
00943 linetable,
00944 *dispersion_relation,
00945 *first_absolute_order,
00946 *last_absolute_order,
00947 n_traces,
00948 threshold_to_positive,
00949 &rebinned_header),
00950 "Could not rebin noise of arc lamp spectrum");
00951
00952 threshold_to_positive = false;
00953 uves_free_propertylist(&rebinned_header);
00954 check( rebinned = uves_rebin(spectrum,
00955 parameters,
00956 recipe_id,
00957 linetable,
00958 *dispersion_relation,
00959 *first_absolute_order,
00960 *last_absolute_order,
00961 n_traces,
00962 threshold_to_positive,
00963 &rebinned_header),
00964 "Could not rebin arc lamp spectrum");
00965
00966
00967 if (DEBUG)
00968 {
00969 check( uves_save_image_local("Rebinned spectrum",
00970 "wxb", rebinned, chip,
00971 trace, window, rebinned_header),
00972 "Error saving rebinned spectrum");
00973
00974 check( uves_save_image_local("Noise of rebinned spectrum",
00975 "errwxb", rebinned_noise, chip,
00976 trace, window, rebinned_header),
00977 "Error saving noise of rebinned spectrum");
00978 }
00979
00980 check( merged = uves_merge_orders(rebinned,
00981 rebinned_noise,
00982 rebinned_header,
00983 m_method,
00984 n_traces,
00985 &merged_header,
00986 &merged_noise),
00987 "Could not merge arc lamp spectrum");
00988
00989 check( uves_plot_image_rows(merged, 1, 1, 1,
00990 "Wavelength (arbitrary units)",
00991 "Flux", "Resampled arc lamp spectrum"),
00992 "Plotting failed");
00993
00994
00995 if (DEBUG)
00996 {
00997 check( uves_save_image_local("Rebinned, merged spectrum",
00998 "merged", merged, chip,
00999 trace, window, merged_header),
01000 "Error saving merged spectrum");
01001 }
01002
01003 nbins = cpl_image_get_size_x(merged);
01004
01005 check( wavestep = uves_pfits_get_cdelt1(merged_header),
01006 "Error reading resampling step size");
01007
01008 check( lambda_start = uves_pfits_get_crval1(merged_header),
01009 "Could not read start wavelength of merged spectrum");
01010
01011
01012
01013 for (i = 0; i < cpl_table_get_nrow(linetable); i++)
01014 {
01015 double lambda = cpl_table_get_double(
01016 linetable, LINETAB_LAMBDAC, i, NULL);
01017 double width =
01018 cpl_table_get_double(linetable, "Xwidth" , i, NULL) *
01019 fabs(cpl_table_get_double(linetable, LINETAB_PIXELSIZE, i, NULL));
01020
01021
01022
01023 int bin = 1 +
01024 uves_round_double((lambda - lambda_start) / wavestep);
01025 double width_bin = width / wavestep;
01026
01027
01028 int first_bin = uves_max_int( 1, uves_round_double(bin - 5*width_bin));
01029 int last_bin = uves_min_int(nbins, uves_round_double(bin + 5*width_bin));
01030
01031 double my, sigma, norm, background;
01032 double lambda_fwhm;
01033
01034 if (cpl_table_is_valid(linetable, "Ident", i))
01035 {
01036
01037 uves_fit_1d_image(merged,
01038 #if 1
01039 merged_noise,
01040 #else
01041 NULL,
01042 #endif
01043 NULL,
01044 true,
01045 false,
01046 false,
01047 first_bin,
01048 last_bin,
01049 1,
01050 &my,
01051 &sigma,
01052 &norm,
01053 &background, NULL,
01054 NULL,
01055 NULL,
01056 NULL,
01057
01058 uves_gauss,
01059 uves_gauss_derivative,
01060 4);
01061
01062 if (cpl_error_get_code() == CPL_ERROR_CONTINUE)
01063 {
01064 uves_error_reset();
01065 uves_msg_debug("Gaussian fitting failed "
01066 "at lambda = %f wlu, bins = "
01067 "%d - %d, ignoring line",
01068 lambda, first_bin, last_bin);
01069
01070 cpl_table_set_invalid(linetable, "deltaLambda", i);
01071
01072 }
01073 else
01074 {
01075 assure(cpl_error_get_code() == CPL_ERROR_NONE,
01076 cpl_error_get_code(), "Gaussian fitting failed");
01077
01078
01079 lambda_fwhm = TWOSQRT2LN2 * sigma * wavestep;
01080
01081 cpl_table_set_double(linetable, "deltaLambda",
01082 i, lambda_fwhm);
01083
01084 }
01085 }
01086 else
01087 {
01088 cpl_table_set_invalid(linetable, "deltaLambda", i);
01089 }
01090 }
01091
01092
01093
01094 check(( cpl_table_duplicate_column(linetable, "Resol",
01095 linetable, LINETAB_LAMBDAC),
01096 cpl_table_divide_columns (linetable, "Resol",
01097 "deltaLambda")),
01098 "Error creating 'Resol' column");
01099
01100
01101 {
01102 double resol_avg = cpl_table_get_column_median(linetable, "Resol");
01103 double resol_stdev = cpl_table_get_column_stdev (linetable, "Resol");
01104 double kappar = 10.0;
01105
01106 for (i = 0; i < cpl_table_get_nrow(linetable); i++)
01107 {
01108 double r = cpl_table_get_double(linetable, "Resol", i, NULL);
01109 if (r < resol_avg - kappar*resol_stdev ||
01110 r > resol_avg + kappar*resol_stdev)
01111 {
01112 cpl_table_set_invalid(linetable, "Resol", i);
01113 cpl_table_set_invalid(linetable, "deltaLambda", i);
01114 }
01115 }
01116 }
01117
01118
01119
01120
01121
01122
01123
01124 check( uves_plot_table(linetable, LINETAB_LAMBDAC, "Resol",
01125 "(l, l / dl)"), "Plotting failed");
01126 }
01127
01128
01129 uves_free_table(&temp);
01130 check( temp = cpl_table_duplicate(linetable),
01131 "Error copying line table");
01132 check( uves_erase_invalid_table_rows(temp, "Ident"),
01133 "Error removing un-identified lines");
01134 check( uves_plot_table(temp, "X", "Ynew",
01135 "Line identifications"),
01136 "Plotting failed");
01137 uves_free_table(&temp);
01138
01139 }
01140
01141 if (DEBUG)
01142 {
01143
01144
01145
01146
01147 if (0) check( uves_draw_lines(debug_image, initial_dispersion,
01148 order_locations, guess,
01149 "Ident", "Order", relative_order,
01150 -1, -1,
01151 false,
01152 12), "Error drawing guess solution");
01153
01154
01155 check( uves_draw_lines(debug_image, initial_dispersion, order_locations,
01156 line_refer, "Wave", NULL, relative_order,
01157 uves_min_int(*first_absolute_order, *last_absolute_order),
01158 uves_max_int(*first_absolute_order, *last_absolute_order),
01159 true,
01160 8), "Error drawing catalogue lines");
01161
01162
01163 check( uves_draw_lines(debug_image, *dispersion_relation, order_locations,
01164 line_refer, "Wave", NULL, relative_order,
01165 uves_min_int(*first_absolute_order, *last_absolute_order),
01166 uves_max_int(*first_absolute_order, *last_absolute_order),
01167 true,
01168 16), "Error drawing catalogue lines");
01169
01170
01171 if (0) check( uves_draw_lines(debug_image, initial_dispersion,
01172 order_locations, linetable,
01173 LINETAB_LAMBDAC, "Order", relative_order,
01174 -1, -1,
01175 false,
01176 -16), "Error drawing detected lines");
01177
01178
01179 uves_free_table(&temp);
01180 check(( temp = cpl_table_duplicate(linetable),
01181
01182 uves_erase_invalid_table_rows(temp, "Ident")),
01183 "Error duplicating table");
01184
01185 check( uves_draw_lines(debug_image, *dispersion_relation, order_locations,
01186 temp, LINETAB_LAMBDAC, "Order", relative_order,
01187 -1, -1,
01188 true,
01189 0), "Error drawing detected lines");
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218 check( uves_save_image_local("Debug image", "rawdebug",
01219 debug_image, chip, trace, window,
01220 rotated_header),
01221 "Error saving spectrum");
01222 }
01223
01224 if (flames)
01225 {
01226 int start = 0;
01227 int count = cpl_table_get_nrow(linetable);
01228
01229 check_nomsg( cpl_table_new_column(linetable, "Fibre", CPL_TYPE_INT) );
01230
01231 cpl_table_fill_column_window(linetable, "Fibre",
01232 start, count,
01233 trace + 1);
01234 }
01235
01236 cleanup:
01237 uves_free_table(&info_tbl);
01238 uves_free_table(&temp);
01239 uves_free_image(&weights);
01240 uves_free_table(&cr_table);
01241 uves_free_image(&cr_image);
01242 uves_free_image(&spectrum);
01243 uves_free_image(&spectrum_noise);
01244 uves_free_image(&debug_image);
01245 uves_free_image(&rebinned);
01246 uves_free_image(&rebinned_noise);
01247 uves_free_image(&merged);
01248 uves_free_image(&merged_noise);
01249 uves_free_propertylist(&spectrum_header);
01250 uves_free_propertylist(&rebinned_header);
01251 uves_free_propertylist(&merged_header);
01252 cpl_free(relative_order);
01253 uves_polynomial_delete(&initial_dispersion);
01254 uves_free_table(&order_trace);
01255
01256 return linetable;
01257 }
01258
01259
01260
01261
01286
01287 void
01288 uves_wavecal_exe_body(cpl_frameset *frames,
01289 bool flames,
01290 const char *recipe_id,
01291 const cpl_parameterlist *parameters,
01292 const char *starttime)
01293 {
01294
01295
01296
01297
01298
01299 bool DEBUG;
01300
01301
01302 int NWINDOWS;
01303 double OFFSET;
01304 double SLITLENGTH_par;
01305
01306
01307 int RANGE;
01308 int MAXLINES;
01309 int MINLINES;
01310 centering_method CENTERING_METHOD;
01311
01312
01313 double SHIFT_MAX;
01314 double SHIFT_STEP;
01315 double SHIFT_TOLERANCE;
01316
01317
01318 double ALPHA;
01319 double MAXERROR;
01320 int DEGREE;
01321
01322 double TOLERANCE;
01323 double KAPPA;
01324
01325
01326 cpl_image *arclamp[2] = {NULL, NULL};
01327 cpl_image *arclamp_noise = NULL;
01328 uves_propertylist *arclamp_header[2] = {NULL, NULL};
01329 uves_propertylist *rotated_header[2] = {NULL, NULL};
01330
01331
01332 cpl_table *ordertable = NULL;
01333 uves_propertylist *ordertable_header = NULL;
01334 polynomial *order_locations = NULL;
01335 cpl_table *traces = NULL;
01336
01337
01338 cpl_image *master_bias = NULL;
01339 uves_propertylist *master_bias_header = NULL;
01340
01341
01342 cpl_image *master_flat = NULL;
01343 cpl_image *mflat_noise = NULL;
01344 uves_propertylist *master_flat_header = NULL;
01345
01346
01347
01348
01349
01350
01351
01352
01353 int* fibres_mask=NULL;
01354 double* fibres_pos=NULL;
01355
01356
01357 cpl_table *guess = NULL;
01358 polynomial *absolute_order = NULL;
01359
01360
01361 cpl_table *corvel = NULL;
01362 uves_propertylist *corvel_header = NULL;
01363
01364
01365 cpl_table *line_refer = NULL;
01366 cpl_table *line_intmon = NULL;
01367
01368
01369 lt_type *linetable = NULL;
01370
01371 uves_propertylist *primary_header = NULL;
01372 uves_propertylist *table_header = NULL;
01373
01374 cpl_table *qclog[3] = {NULL, NULL, NULL};
01375
01376
01377 cpl_image *absorder_image = NULL;
01378 const char *arclamp_filename = "";
01379 const char *line_refer_filename = "";
01380 const char *line_intmon_filename = "";
01381 char *product_filename = NULL;
01382 char *temp = NULL;
01383 bool blue = false;
01384 bool sim_cal = false;
01385 enum uves_chip chip;
01386 int binx = 0;
01387 int biny = 0;
01388 bool drs_cvel_sw=false;
01389
01390
01391 {
01392 extract_method em;
01393 const char *centering_m = "";
01394 const char *profile = "";
01395
01396
01397 check( uves_get_parameter(parameters, NULL, "uves", "debug",
01398 CPL_TYPE_BOOL, &DEBUG), "Could not read parameter");
01399
01400
01401 check( uves_get_parameter(parameters, NULL, recipe_id, "nwindows",
01402 CPL_TYPE_INT , &NWINDOWS ), "Could not read parameter");
01403 check( uves_get_parameter(parameters, NULL, recipe_id, "length",
01404 CPL_TYPE_DOUBLE, &SLITLENGTH_par), "Could not read parameter");
01405 check( uves_get_parameter(parameters, NULL, recipe_id, "offset",
01406 CPL_TYPE_DOUBLE, &OFFSET ), "Could not read parameter");
01407
01408
01409
01410 temp = uves_sprintf("%s.%s", recipe_id, UVES_EXTRACT_ID);
01411 check( em = uves_get_extract_method(parameters, NULL, temp),
01412 "Could not read extraction method");
01413
01414 check( uves_get_parameter(parameters, NULL, recipe_id, UVES_EXTRACT_ID ".profile",
01415 CPL_TYPE_STRING, &profile), "Could not read parameter");
01416
01417 assure( em == EXTRACT_LINEAR || em == EXTRACT_AVERAGE ||
01418 (em == EXTRACT_OPTIMAL && strcmp(profile, "constant") == 0),
01419 CPL_ERROR_UNSUPPORTED_MODE,
01420 "Only linear/average/optimal(constant profile) extraction methods are supported by this recipe");
01421
01422
01423 check( uves_get_parameter(parameters, NULL, recipe_id, "search.range",
01424 CPL_TYPE_INT , &RANGE ), "Could not read parameter");
01425 check( uves_get_parameter(parameters, NULL, recipe_id, "search.minlines",
01426 CPL_TYPE_INT , &MINLINES ), "Could not read parameter");
01427 check( uves_get_parameter(parameters, NULL, recipe_id, "search.maxlines",
01428 CPL_TYPE_INT , &MAXLINES ), "Could not read parameter");
01429 check( uves_get_parameter(parameters, NULL, recipe_id, "search.centeringmethod",
01430 CPL_TYPE_STRING, ¢ering_m ), "Could not read parameter");
01431 if (strcmp(centering_m, "gravity" ) == 0) CENTERING_METHOD = CENTERING_GRAVITY;
01432 else if (strcmp(centering_m, "gaussian") == 0) CENTERING_METHOD = CENTERING_GAUSSIAN;
01433 else
01434 {
01435 assure(false, CPL_ERROR_ILLEGAL_INPUT,
01436 "Unrecognized parameter value '%s'", centering_m);
01437 }
01438
01439
01440 check( uves_get_parameter(parameters, NULL, recipe_id, "first.shiftmax",
01441 CPL_TYPE_DOUBLE , &SHIFT_MAX ),
01442 "Could not read parameter");
01443 check( uves_get_parameter(parameters, NULL, recipe_id, "first.shiftstep",
01444 CPL_TYPE_DOUBLE , &SHIFT_STEP ),
01445 "Could not read parameter");
01446 check( uves_get_parameter(parameters, NULL, recipe_id, "first.shifttoler",
01447 CPL_TYPE_DOUBLE , &SHIFT_TOLERANCE),
01448 "Could not read parameter");
01449
01450
01451 check( uves_get_parameter(parameters, NULL, recipe_id, "identify.alpha",
01452 CPL_TYPE_DOUBLE , &ALPHA ), "Could not read parameter");
01453 check( uves_get_parameter(parameters, NULL, recipe_id, "identify.maxerror",
01454 CPL_TYPE_DOUBLE , &MAXERROR ), "Could not read parameter");
01455 check( uves_get_parameter(parameters, NULL, recipe_id, "identify.degree",
01456 CPL_TYPE_INT , &DEGREE ), "Could not read parameter");
01457
01458
01459 check( uves_get_parameter(parameters, NULL, recipe_id, "calibrate.tolerance",
01460 CPL_TYPE_DOUBLE, &TOLERANCE ), "Could not read parameter");
01461 check( uves_get_parameter(parameters, NULL, recipe_id, "calibrate.kappa",
01462 CPL_TYPE_DOUBLE, &KAPPA ), "Could not read parameter");
01463
01464
01465 if (CENTERING_METHOD == CENTERING_GRAVITY)
01466 {
01467 uves_msg_warning("Centering method 'gravity' might lead to inaccurate "
01468 "results. Recommended is 'gaussian'");
01469 }
01470 }
01471
01472
01473 check( uves_load_arclamp(frames, flames, &arclamp_filename, arclamp, arclamp_header,
01474 rotated_header, &blue, &sim_cal), "Error loading raw frame");
01475
01476
01477 check( uves_load_linerefertable(frames, &line_refer_filename, &line_refer, NULL),
01478 "Could not load line reference table");
01479 uves_msg("Using line reference table '%s'", line_refer_filename);
01480
01481
01482 if (irplib_frameset_find(frames, UVES_LINE_INTMON_TABLE) != NULL)
01483 {
01484 uves_free_table(&line_intmon);
01485 check( uves_load_lineintmon(frames, &line_intmon_filename,
01486 &line_intmon),
01487 "Error loading line reference table");
01488
01489 uves_msg("Using bright line table '%s'", line_intmon_filename);
01490 }
01491
01492
01493
01494
01495 check (binx = uves_pfits_get_binx(arclamp_header[0]),
01496 "Could not read x binning factor from input header");
01497 check (biny = uves_pfits_get_biny(arclamp_header[0]),
01498 "Could not read y binning factor from input header");
01499 SLITLENGTH_par /= (1.0*binx);
01500 RANGE /= (1.0*biny);
01501 SHIFT_MAX /= (1.0*binx);
01502 SHIFT_STEP /= (1.0*binx);
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513 for (chip = uves_chip_get_first(blue);
01514 chip != UVES_CHIP_INVALID;
01515 chip = uves_chip_get_next(chip)) {
01516
01517 const char *ordertable_filename = "";
01518 const char *corvel_filename = "";
01519 const char *master_flat_filename = "";
01520 const char *master_bias_filename = "";
01521
01522 const char *guess_filename = "";
01523 const char *chip_name = "";
01524 int ntraces;
01525 int tracerow;
01526 int raw_index = uves_chip_get_index(chip);
01527 int current_linetable_extension;
01528 int tab_in_out_oshift = -1;
01529 double tab_in_out_yshift = -1;
01530 double slitlength;
01531
01532 uves_msg("Processing %s chip in '%s'",
01533 uves_chip_tostring_upper(chip), arclamp_filename);
01534
01535 check_nomsg( chip_name = uves_pfits_get_chipid(arclamp_header[raw_index], chip));
01536
01537
01538 uves_msg_debug("binning = %dx%d", binx, biny);
01539
01540
01541
01542 uves_free_table (&ordertable);
01543 uves_free_propertylist(&ordertable_header);
01544 uves_polynomial_delete(&order_locations);
01545 uves_free_table (&traces);
01546
01547
01548 check( uves_load_ordertable(frames,
01549 flames,
01550 chip_name,
01551 &ordertable_filename,
01552 &ordertable,
01553 &ordertable_header,
01554 NULL,
01555 &order_locations,
01556 &traces,
01557 (flames) ? &tab_in_out_oshift : NULL,
01558 (flames) ? &tab_in_out_yshift : NULL,
01559 &fibres_mask,
01560 &fibres_pos,
01561 chip,
01562 false ),
01563 "Could not load order table");
01564 uves_msg("Using order table in '%s'", ordertable_filename);
01565 ntraces = cpl_table_get_nrow(traces);
01566 uves_free_double(&fibres_pos);
01567 uves_free_int(&fibres_mask);
01568
01569
01570 uves_free_image(&master_bias);
01571 uves_free_propertylist(&master_bias_header);
01572 if (irplib_frameset_find(frames, UVES_MASTER_BIAS(chip)) != NULL)
01573 {
01574 check( uves_load_mbias(frames, chip_name, &master_bias_filename, &master_bias,
01575 &master_bias_header, chip),
01576 "Error loading master bias");
01577
01578 uves_msg_low("Using master bias in '%s'", master_bias_filename);
01579 }
01580 else
01581 {
01582 uves_msg_warning("Master bias not provided. Bias subtraction not done");
01583 }
01584
01585
01586
01587 uves_free_image(&master_flat);
01588 uves_free_propertylist(&master_flat_header);
01589 if ((irplib_frameset_find(frames, UVES_MASTER_FLAT(chip)) != NULL ||
01590 irplib_frameset_find(frames, UVES_MASTER_DFLAT(chip)) != NULL ||
01591 irplib_frameset_find(frames, UVES_MASTER_IFLAT(chip)) != NULL ||
01592 irplib_frameset_find(frames, UVES_MASTER_TFLAT(chip)) != NULL))
01593 {
01594 check( uves_load_mflat(frames, chip_name, &master_flat_filename, &master_flat,
01595 &master_flat_header, chip, NULL),
01596 "Error loading master flat");
01597
01598 uves_msg_low("Using master flat in '%s'", master_flat_filename);
01599 }
01600 else
01601 {
01602 uves_msg_warning("Master flat not provided. Flat-fielding not done");
01603 }
01604
01605
01606 if (flames)
01607
01608 {
01609 if (irplib_frameset_find(frames, FLAMES_CORVEL(chip)))
01610 {
01611 check( uves_load_corvel(frames, chip,
01612 &corvel, &corvel_header,
01613 &corvel_filename),
01614 "Could not load velocity correction table");
01615
01616 uves_msg("Using velocity correction table %s", corvel_filename);
01617
01618 drs_cvel_sw=true;
01619
01620
01621 }
01622 else
01623 {
01624 uves_msg("No corvel table found. Switch off corvel");
01625 corvel = NULL;
01626 }
01627 }
01628
01629
01630 uves_lt_delete(&linetable);
01631 linetable = uves_lt_new(NWINDOWS, ntraces);
01632
01633
01634
01635 uves_qclog_delete(&qclog[0]); qclog[0] = uves_qclog_init(arclamp_header[raw_index], chip);
01636 uves_qclog_delete(&qclog[1]); qclog[1] = uves_qclog_init(arclamp_header[raw_index], chip);
01637
01638
01639 if (DEBUG) check( uves_save_image_local("Arc lamp frame", "raw",
01640 arclamp[raw_index],
01641 chip, -1, -1, rotated_header[raw_index]),
01642 "Error saving arc lamp frame");
01643
01644 if (master_bias != NULL)
01645 {
01646 uves_msg("Subtracting master bias");
01647
01648 check( uves_subtract_bias(arclamp[raw_index], master_bias),
01649 "Error during bias subtraction");
01650 }
01651 else {
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661 }
01662
01663
01664
01665 uves_free_image(&arclamp_noise);
01666 check( arclamp_noise = uves_define_noise(arclamp[raw_index],
01667 arclamp_header[raw_index], 1, chip),
01668 "Could not set arc lamp noise");
01669
01670 if (master_flat != NULL)
01671 {
01672 uves_msg("Dividing by master flat");
01673
01674 uves_free_image(&mflat_noise);
01675 check( mflat_noise =
01676 uves_define_noise(master_flat, master_flat_header,
01677 uves_pfits_get_datancom(master_flat_header),
01678 chip),
01679 "Could not set master flat error bars");
01680
01681 check( uves_flatfielding(arclamp[raw_index], arclamp_noise,
01682 master_flat, mflat_noise),
01683 "Error while dividing by flat field");
01684 }
01685
01686 if (DEBUG) check( uves_save_image_local("Pre-processed arc lamp frame",
01687 "preproc",
01688 arclamp[raw_index], chip, -1, -1,
01689 rotated_header[raw_index]),
01690 "Error saving arc lamp frame");
01691
01692
01693 if (SLITLENGTH_par < 0) {
01694
01695 double header_full_slit;
01696
01697 check( header_full_slit =
01698 uves_pfits_get_slitlength_pixels(arclamp_header[raw_index], chip),
01699 "Could not read slit length");
01700
01701
01702
01703
01704 slitlength = uves_max_double(1.0, (header_full_slit - 2)/NWINDOWS);
01705
01706 uves_msg("Full slit = %.2f pixels", header_full_slit);
01707 }
01708 else {
01709 slitlength = SLITLENGTH_par;
01710 }
01711
01712
01713
01714 for(tracerow = 0; tracerow < ntraces; tracerow++) {
01715 double trace_offset;
01716 int trace_number;
01717 int trace_enabled;
01718
01719 trace_offset = cpl_table_get_double(traces, "Offset" , tracerow, NULL);
01720 trace_number = cpl_table_get_int (traces, "TraceID" , tracerow, NULL);
01721 trace_enabled = cpl_table_get_int (traces, "Tracemask", tracerow, NULL);
01722
01723 if (ntraces > 1) {
01724 uves_msg("Processing trace %d", trace_number);
01725 }
01726
01727 if (flames && sim_cal)
01728 {
01729
01730 trace_enabled = (trace_number == 1) ? 1 : 0;
01731 }
01732
01733 uves_msg_low("Trace offset = %.2f pixels ; enabled = %d",
01734 trace_offset, trace_enabled);
01735
01736 assure( flames || trace_number == 0, CPL_ERROR_ILLEGAL_INPUT,
01737 "%s: UVES trace number must be 0, it is %d",
01738 ordertable_filename, trace_number );
01739
01740
01741 if (trace_enabled != 0) {
01742 int window;
01743
01744
01745 uves_free_table (&guess);
01746 uves_polynomial_delete(&absolute_order);
01747
01748 check( uves_load_linetable(
01749 frames, flames, chip_name, order_locations,
01750 cpl_table_get_column_min(ordertable, "Order"),
01751 cpl_table_get_column_max(ordertable, "Order"),
01752 &guess_filename, &guess,
01753 NULL, NULL,
01754 &absolute_order, chip, trace_number, -1),
01755 "Could not load guess line table for trace number %d",
01756 trace_number);
01757 uves_msg("Using guess line table '%s'", guess_filename);
01758
01759 if (DEBUG)
01760 {
01761
01762
01763
01764 int x, y;
01765
01766 absorder_image = cpl_image_new(cpl_image_get_size_x(arclamp[raw_index]),
01767 cpl_image_get_size_y(arclamp[raw_index]),
01768 CPL_TYPE_FLOAT);
01769 assure_mem(absorder_image);
01770
01771 for (y = 1; y <= cpl_image_get_size_y(arclamp[raw_index]); y++)
01772 {
01773 for (x = 1; x <= cpl_image_get_size_x(arclamp[raw_index]); x++)
01774 {
01775 double absorder =
01776 uves_polynomial_evaluate_2d(absolute_order, x, y);
01777
01778 cpl_image_set(absorder_image, x, y, absorder);
01779 }
01780 }
01781
01782 check( uves_save_image_local("Absolute order image", "absord",
01783 absorder_image, chip, trace_number,
01784 1, rotated_header[raw_index]),
01785 "Error saving absolute order image");
01786
01787 uves_free_image(&absorder_image);
01788 }
01789
01790
01791 for (window = 1; window <= NWINDOWS; window ++) {
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805 double window_offset =
01806 slitlength * (window - (NWINDOWS+1) / 2.0);
01807
01808
01809 double offset = trace_offset + window_offset + OFFSET;
01810
01811
01812
01813 #if 0
01814 int lines_min = (MINLINES >= 1) ? MINLINES :
01815 (chip == UVES_CHIP_REDU) ? 1000 : 2000;
01816 int lines_max = (MAXLINES >= 1) ? MAXLINES :
01817 (chip == UVES_CHIP_REDU) ? 1400 : 2400;
01818 #else
01819
01820 int lines_min = (MINLINES >= 1) ? MINLINES :
01821 (chip == UVES_CHIP_REDU) ? 1000 : 1200;
01822 int lines_max = (MAXLINES >= 1) ? MAXLINES :
01823 (chip == UVES_CHIP_REDU) ? 1400 : 1600;
01824 #endif
01825
01826 assure( lines_min <= lines_max , CPL_ERROR_ILLEGAL_INPUT,
01827 "Minimum and maximum number of requested line "
01828 "detections don't make sense (min = %d; max = %d)",
01829 lines_min, lines_max);
01830
01831 uves_msg("Processing window %d of %d", window, NWINDOWS);
01832
01833 passure( *(uves_lt_get_disprel(linetable, window, trace_number))
01834 == NULL, "%d %d", window, trace_number);
01835 passure( *(uves_lt_get_absord (linetable, window, trace_number))
01836 == NULL, "%d %d", window, trace_number);
01837
01838
01839 *uves_lt_get_absord(linetable, window, trace_number) =
01840 uves_polynomial_duplicate(absolute_order);
01841
01842
01843 check( *uves_lt_get_table(linetable, window, trace_number) =
01844 uves_wavecal_process_window(
01845
01846 arclamp[raw_index],
01847 arclamp_noise,
01848 rotated_header[raw_index],
01849
01850 ordertable, order_locations,
01851 master_flat != NULL,
01852
01853 guess,
01854 line_refer,
01855 flames,
01856 tab_in_out_oshift,
01857 tab_in_out_yshift,
01858
01859 chip, biny, trace_number, window,
01860
01861 DEBUG,
01862
01863 offset, slitlength, parameters, recipe_id,
01864
01865 RANGE, lines_min, lines_max, CENTERING_METHOD,
01866
01867 SHIFT_MAX, SHIFT_STEP, SHIFT_TOLERANCE,
01868
01869 ALPHA, MAXERROR, DEGREE,
01870
01871 TOLERANCE, KAPPA,
01872
01873 uves_lt_get_disprel(linetable, window, trace_number),
01874 uves_lt_get_absord (linetable, window, trace_number),
01875 uves_lt_get_firstabs(linetable, window, trace_number),
01876 uves_lt_get_lastabs(linetable, window, trace_number)),
01877 "Wavelength calibration failed");
01878
01879
01880
01881
01882
01883
01884 if(drs_cvel_sw) {
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909 int ord_min=0;
01910 int ord_max=0;
01911 double rsample=0;
01912 double old_cvel_min=DRS_CVEL_MIN;
01913 double old_cvel_max=DRS_CVEL_MAX;
01914 double drs_cvel_min=old_cvel_min;
01915 double drs_cvel_max=old_cvel_max;
01916
01917
01918
01919
01920
01921
01922 ord_min = ord_min;
01923 ord_max = ord_max;
01924 rsample = rsample;
01925 drs_cvel_min=old_cvel_min;
01926 drs_cvel_max=old_cvel_max;
01927
01928 }
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945 if (flames ||
01946 (window == 2 && trace_number == 0)) {
01947
01948
01949 check( uves_wavecal_qclog(
01950 *uves_lt_get_table(
01951 linetable,
01952 window,
01953 trace_number),
01954 *uves_lt_get_firstabs(linetable, window, trace_number),
01955 *uves_lt_get_lastabs(linetable, window, trace_number),
01956 arclamp[raw_index],
01957 arclamp_header[raw_index],
01958 flames,
01959 trace_number, trace_enabled, trace_offset,
01960 chip,
01961 qclog[0]),
01962 "Could not calculate resolution QC parameters");
01963
01964 if (line_intmon != NULL) {
01965 check( uves_wavecal_qclog_intmon(
01966 *uves_lt_get_table(
01967 linetable,
01968 window,
01969 trace_number),
01970 line_intmon,
01971 arclamp_header[raw_index],
01972 flames, trace_number,
01973 chip,
01974 qclog[1]),
01975 "Could not calculate int.mon. QC parameters");
01976 }
01977 else
01978 {
01979
01980 uves_qclog_delete(&qclog[1]);
01981 }
01982 }
01983
01984
01985
01986
01987
01988 }
01989
01990 }
01991 else
01992 {
01993 uves_msg("Skipping trace number %d", trace_number);
01994 }
01995 }
01996
01997
01998
01999
02000
02001 cpl_free(product_filename);
02002 check( product_filename = uves_line_table_filename(chip), "Error getting filename");
02003 current_linetable_extension = 1;
02004
02005
02006 for(tracerow = 0; tracerow < cpl_table_get_nrow(traces); tracerow++)
02007 {
02008 int trace_number;
02009 double trace_offset;
02010 int trace_enabled;
02011
02012 trace_offset = cpl_table_get_double(traces, "Offset" , tracerow, NULL);
02013 trace_number = cpl_table_get_int (traces, "TraceID" , tracerow, NULL);
02014 trace_enabled = cpl_table_get_int (traces, "Tracemask" , tracerow, NULL);
02015
02016 if (trace_enabled != 0)
02017 {
02018 int window;
02019
02020
02021 for (window = 1; window <= NWINDOWS; window ++)
02022 {
02023 double window_offset =
02024 slitlength * (window - (NWINDOWS+1) / 2.0);
02025
02026 double offset = trace_offset + window_offset + OFFSET;
02027
02028
02029 uves_free_propertylist(&table_header);
02030 table_header = uves_propertylist_new();
02031 check( uves_pfits_set_traceid ( table_header, trace_number),
02032 "Error writing trace ID to product header");
02033 check( uves_pfits_set_offset ( table_header, offset),
02034 "Error writing trace offset to product header");
02035 check( uves_pfits_set_windownumber( table_header, window),
02036 "Error writing window number to product header");
02037 check( uves_pfits_set_firstabsorder( table_header,
02038 *uves_lt_get_firstabs(
02039 linetable,
02040 window,
02041 trace_number)),
02042 "Error writing order number to product header");
02043 check( uves_pfits_set_lastabsorder( table_header,
02044 *uves_lt_get_lastabs(
02045 linetable,
02046 window,
02047 trace_number)),
02048 "Error writing order number to product header");
02049
02050
02051
02052 if (current_linetable_extension == 1)
02053 {
02054 uves_free_propertylist(&primary_header);
02055 primary_header = uves_propertylist_new();
02056
02057 if (flames)
02058 {
02059
02060
02061
02062 check_nomsg( uves_flames_pfits_set_ccfposmax(
02063 primary_header, 0.0) );
02064 }
02065
02066 uves_msg("Creating line table '%s'", product_filename);
02067 check( uves_frameset_insert(
02068 frames,
02069 *uves_lt_get_table(
02070 linetable,
02071 window,
02072 trace_number),
02073 CPL_FRAME_GROUP_PRODUCT,
02074 CPL_FRAME_TYPE_TABLE,
02075 CPL_FRAME_LEVEL_INTERMEDIATE,
02076 product_filename,
02077 UVES_LINE_TABLE(flames, chip),
02078 arclamp_header[raw_index],
02079 primary_header,
02080 table_header,
02081 parameters,
02082 recipe_id,
02083 PACKAGE "/" PACKAGE_VERSION,
02084 qclog, starttime, true, 0),
02085 "Could not add line table '%s' (%s) to frameset",
02086 product_filename, UVES_LINE_TABLE(flames, chip));
02087
02088 uves_msg("Line table '%s' (%s) added to frameset",
02089 product_filename, UVES_LINE_TABLE(flames, chip));
02090 }
02091 else
02092
02093 {
02094 check( uves_table_save(
02095 *uves_lt_get_table(linetable,
02096 window,
02097 trace_number),
02098 NULL,
02099
02100
02101 table_header,
02102 product_filename,
02103
02104 CPL_IO_EXTEND),
02105
02106 "Error appending table to file '%s'",
02107 product_filename);
02108 }
02109 current_linetable_extension += 1;
02110
02111
02112 check( uves_save_polynomial(*uves_lt_get_disprel(
02113 linetable,
02114 window,
02115 trace_number),
02116 product_filename,
02117 table_header),
02118 "Could not write polynomial to file '%s'",
02119 product_filename);
02120 current_linetable_extension += 1;
02121
02122
02123 check( uves_save_polynomial(*uves_lt_get_absord(
02124 linetable,
02125 window,
02126 trace_number),
02127 product_filename,
02128 table_header),
02129 "Could not write polynomial to file '%s'",
02130 product_filename);
02131 current_linetable_extension += 1;
02132
02133 uves_msg("Line table for trace %d, window #%d "
02134 "saved to extensions %d-%d of '%s'",
02135 trace_number, window,
02136 current_linetable_extension - 3,
02137 current_linetable_extension - 1,
02138 product_filename);
02139
02140 }
02141 }
02142 }
02143 }
02144
02145 cleanup:
02146
02147 uves_free_image(&arclamp[0]);
02148 uves_free_image(&arclamp[1]);
02149 uves_free_image(&arclamp_noise);
02150 uves_free_image(&absorder_image);
02151 uves_free_propertylist(&arclamp_header[0]);
02152 uves_free_propertylist(&arclamp_header[1]);
02153 uves_free_propertylist(&rotated_header[0]);
02154 uves_free_propertylist(&rotated_header[1]);
02155
02156 uves_free_table(&ordertable);
02157 uves_free_propertylist(&ordertable_header);
02158 uves_free_table(&corvel);
02159 uves_free_propertylist(&corvel_header);
02160 uves_polynomial_delete(&order_locations);
02161 uves_polynomial_delete(&absolute_order);
02162 uves_free_table(&traces);
02163
02164 uves_free_image(&master_bias);
02165 uves_free_propertylist(&master_bias_header);
02166 uves_free_image(&master_flat);
02167 uves_free_image(&mflat_noise);
02168 uves_free_propertylist(&master_flat_header);
02169
02170
02171
02172
02173
02174
02175 uves_free_table(&guess);
02176
02177 uves_free_table(&line_refer);
02178 uves_free_table(&line_intmon);
02179
02180
02181 uves_lt_delete(&linetable);
02182 uves_free_propertylist(&primary_header);
02183 uves_free_propertylist(&table_header);
02184 uves_qclog_delete(&qclog[0]);
02185 uves_qclog_delete(&qclog[1]);
02186
02187 cpl_free(product_filename);
02188 cpl_free(temp);
02189
02190 return;
02191 }
02192
02193
02206 static void uves_wavecal_qclog(const cpl_table* linetable,
02207 int firstabs,
02208 int lastabs,
02209 const cpl_image *arclamp,
02210 const uves_propertylist* raw_header,
02211 bool flames,
02212 int trace_number,
02213 int fibre_mask,
02214 double offset,
02215 enum uves_chip chip,
02216 cpl_table* qclog)
02217 {
02218
02219 const char *qc_fib_drsno_name= uves_qclog_get_qc_name("DRSNO", flames, trace_number);
02220 const char *qc_fib_seq_name = uves_qclog_get_qc_name("SEQ", flames, trace_number);
02221 const char *qc_fib_pos_name = uves_qclog_get_qc_name("POS", flames, trace_number);
02222 const char *qc_fib_msk_name = uves_qclog_get_qc_name("MSK", flames, trace_number);
02223 const char *qc_fwhmavg_name = uves_qclog_get_qc_name("FWHMAVG", flames, trace_number);
02224 const char *qc_fwhmrms_name = uves_qclog_get_qc_name("FWHMRMS", flames, trace_number);
02225 const char *qc_fwhmmed_name = uves_qclog_get_qc_name("FWHMMED", flames, trace_number);
02226 const char *qc_resolavg_name = uves_qclog_get_qc_name("RESOLAVG", flames, trace_number);
02227 const char *qc_resolrms_name = uves_qclog_get_qc_name("RESOLRMS", flames, trace_number);
02228 const char *qc_resolmed_name = uves_qclog_get_qc_name("RESOLMED", flames, trace_number);
02229 const char *qc_wlenmin_name = uves_qclog_get_qc_name("WLENMIN", flames, trace_number);
02230 const char *qc_wlenmax_name = uves_qclog_get_qc_name("WLENMAX", flames, trace_number);
02231 const char *qc_ordmin_name = uves_qclog_get_qc_name("ORDMIN", flames, trace_number);
02232 const char *qc_ordmax_name = uves_qclog_get_qc_name("ORDMAX", flames, trace_number);
02233 const char *qc_nlintot_name = uves_qclog_get_qc_name("NLINTOT", flames, trace_number);
02234 const char *qc_nlinsel_name = uves_qclog_get_qc_name("NLINSEL", flames, trace_number);
02235 const char *qc_nlinsol_name = uves_qclog_get_qc_name("NLINSOL", flames, trace_number);
02236 const char *qc_nlinres1_name = uves_qclog_get_qc_name("NLINRES1", flames, trace_number);
02237 const char *qc_lineresidavg_name =
02238 uves_qclog_get_qc_name("LINE RESIDAVG", flames, trace_number);
02239 const char *qc_lineresidrms_name =
02240 uves_qclog_get_qc_name("LINE RESIDRMS", flames, trace_number);
02241
02242 cpl_table *selected = NULL;
02243 polynomial *pol = NULL;
02244 const char *test_id = uves_sprintf("%sResolution-Test-Results",
02245 flames ? "Fibre-" : "");
02246
02247 check_nomsg(uves_qclog_add_string(qclog,
02248 "QC TEST1 ID",
02249 test_id,
02250 "Name of QC test",
02251 "%s"));
02252
02253 check_nomsg( uves_qclog_add_common_wave(raw_header, chip, qclog) );
02254
02255 if (flames)
02256 {
02257
02258
02259 check_nomsg(uves_qclog_add_int(qclog,
02260 qc_fib_drsno_name,
02261 trace_number + 1,
02262 "DRS det. fibre seq. pos.",
02263 "%d"));
02264
02265
02266
02267 check_nomsg(uves_qclog_add_int(qclog,
02268 qc_fib_seq_name,
02269 trace_number + 1,
02270 "det. fibre seq. no.",
02271 "%d"));
02272
02273
02274 check_nomsg(uves_qclog_add_double(qclog,
02275 qc_fib_pos_name,
02276 offset,
02277 "det. fibre seq. rel. pos.",
02278 "%.4f"));
02279
02280
02281
02282 check_nomsg(uves_qclog_add_int(qclog,
02283 qc_fib_msk_name,
02284 fibre_mask,
02285 "DRS det. fibre mask value",
02286 "%d"));
02287
02288 {
02289
02290
02291
02292
02293
02294
02295
02296 double exptime;
02297
02298 check( exptime = uves_flames_pfits_get_dit(raw_header),
02299 "Error reading exposure time");
02300
02301 check_nomsg(uves_qclog_add_double(qclog,
02302 "QC FIB ABSTRANS",
02303 cpl_image_get_flux(arclamp) / exptime,
02304 "abs. trans. countrate",
02305 "%.4f"));
02306 }
02307
02308 {
02309 int n_hpix;
02310 int x, y;
02311
02312 n_hpix = 0;
02313 for (y = 1; y <= cpl_image_get_size_y(arclamp); y++)
02314 for (x = 1; x <= cpl_image_get_size_x(arclamp); x++)
02315 {
02316 int pis_rejected;
02317 int value = cpl_image_get(arclamp, x, y, &pis_rejected);
02318
02319 if (!pis_rejected &&
02320 (value < DRS_PTHRES_MIN || value > DRS_PTHRES_MAX))
02321 {
02322 n_hpix += 1;
02323 }
02324 }
02325
02326 check_nomsg(uves_qclog_add_int(qclog,
02327 "QC NHOTPIX",
02328 n_hpix,
02329 "no. of hot pixels",
02330 "%d"));
02331
02332 }
02333
02334 {
02335 int plate_id;
02336
02337
02338 check( plate_id = uves_flames_pfits_get_plateid(raw_header),
02339 "Error reading plate ID");
02340 check_nomsg(uves_qclog_add_int(qclog,
02341 "QC PLATENO",
02342 plate_id,
02343 "Plate Id.",
02344 "%d"));
02345 }
02346
02347 }
02348
02349
02350
02351 selected = uves_extract_table_rows(linetable, "NLinSol", CPL_NOT_EQUAL_TO, 0);
02352
02353
02354 check_nomsg(uves_qclog_add_double(qclog,
02355 qc_fwhmavg_name,
02356 cpl_table_get_column_mean(selected,"Xwidth")*TWOSQRT2LN2,
02357 "average FWHM in X of lines selected",
02358 "%.2f"));
02359
02360 check_nomsg(uves_qclog_add_double(qclog,
02361 qc_fwhmrms_name,
02362 cpl_table_get_column_stdev(selected,"Xwidth")*TWOSQRT2LN2,
02363 "stdev FWHM in X of lines selected",
02364 "%.4f"));
02365
02366 check_nomsg(uves_qclog_add_double(qclog,
02367 qc_fwhmmed_name,
02368 cpl_table_get_column_median(selected,"Xwidth")*TWOSQRT2LN2,
02369 "median FWHM in X of lines selected",
02370 "%.4f"));
02371
02372 check_nomsg(uves_qclog_add_double(qclog,
02373 qc_resolavg_name,
02374 cpl_table_get_column_mean(selected,"Resol"),
02375 "average resolving power of lines selected",
02376 "%.4f"));
02377
02378 check_nomsg(uves_qclog_add_double(qclog,
02379 qc_resolrms_name,
02380 cpl_table_get_column_stdev(selected,"Resol"),
02381 "stdev resolving power of lines selected",
02382 "%.4f"));
02383
02384 check_nomsg(uves_qclog_add_double(qclog,
02385 qc_resolmed_name,
02386 cpl_table_get_column_median(selected,"Resol"),
02387 "median resolving power of lines selected",
02388 "%.4f"));
02389
02390
02391 check_nomsg(uves_qclog_add_double(qclog,
02392 qc_lineresidavg_name,
02393 cpl_table_get_column_mean(selected, LINETAB_RESIDUAL)*100,
02394 "mean resid of line pos to fit",
02395 "%.4f"));
02396
02397 check_nomsg(uves_qclog_add_double(qclog,
02398 qc_lineresidrms_name,
02399 cpl_table_get_column_stdev(selected, LINETAB_RESIDUAL)*100,
02400 "sigma resid of line pos to fit",
02401 "%.4f"));
02402
02403
02404 check_nomsg(uves_qclog_add_double(qclog,
02405 qc_wlenmin_name,
02406 cpl_table_get_column_min(linetable,LINETAB_LAMBDAC)/10.0,
02407 "minimum wavelength",
02408 "%.4f"));
02409
02410 check_nomsg(uves_qclog_add_double(qclog,
02411 qc_wlenmax_name,
02412 cpl_table_get_column_max(linetable,LINETAB_LAMBDAC)/10.0,
02413 "maximum wavelength",
02414 "%.4f"));
02415
02416 check_nomsg(uves_qclog_add_int(qclog,
02417 qc_ordmin_name,
02418 uves_min_int(firstabs, lastabs),
02419 "minimum order number detected",
02420 "%d"));
02421
02422 check_nomsg(uves_qclog_add_int(qclog,
02423 qc_ordmax_name,
02424 uves_max_int(firstabs, lastabs),
02425 "maximum order number detected",
02426 "%d"));
02427
02428 check_nomsg(uves_qclog_add_int(qclog,
02429 qc_nlintot_name,
02430 cpl_table_get_nrow(linetable),
02431 "No of lines found",
02432 "%d"));
02433
02434 check_nomsg(uves_qclog_add_int(qclog,
02435 qc_nlinsel_name,
02436 cpl_table_get_nrow(linetable) -
02437 cpl_table_count_invalid(linetable, "Ident"),
02438 "No of lines selected",
02439 "%d"));
02440
02441 check_nomsg(uves_qclog_add_int(qclog,
02442 qc_nlinsol_name,
02443 cpl_table_get_nrow(selected),
02444 "No of lines used",
02445 "%d"));
02446
02447 uves_free_table(&selected);
02448 selected = cpl_table_duplicate(linetable);
02449 assure_mem( selected );
02450
02451
02452
02453 check_nomsg( uves_erase_invalid_table_rows(selected, "Ident") );
02454 check_nomsg( uves_erase_table_rows(selected, LINETAB_RESIDUAL,
02455 CPL_NOT_LESS_THAN,
02456 1.0) );
02457
02458 check_nomsg(uves_qclog_add_int(qclog,
02459 qc_nlinres1_name,
02460 cpl_table_get_nrow(selected),
02461 "No of lines with residuals < 0.1 nm",
02462 "%d"));
02463
02464
02465 cleanup:
02466 uves_free_string_const(&qc_fib_drsno_name);
02467 uves_free_string_const(&qc_fib_seq_name);
02468 uves_free_string_const(&qc_fib_pos_name);
02469 uves_free_string_const(&qc_fib_msk_name);
02470
02471 uves_free_string_const(&test_id);
02472 uves_free_string_const(&qc_fwhmavg_name);
02473 uves_free_string_const(&qc_fwhmrms_name);
02474 uves_free_string_const(&qc_fwhmmed_name);
02475
02476 uves_free_string_const(&qc_resolavg_name);
02477 uves_free_string_const(&qc_resolrms_name);
02478 uves_free_string_const(&qc_resolmed_name);
02479 uves_free_string_const(&qc_wlenmin_name);
02480 uves_free_string_const(&qc_wlenmax_name);
02481 uves_free_string_const(&qc_ordmin_name);
02482 uves_free_string_const(&qc_ordmax_name);
02483 uves_free_string_const(&qc_nlintot_name);
02484 uves_free_string_const(&qc_nlinsel_name);
02485 uves_free_string_const(&qc_nlinsol_name);
02486 uves_free_string_const(&qc_nlinres1_name);
02487 uves_free_string_const(&qc_lineresidavg_name);
02488 uves_free_string_const(&qc_lineresidrms_name);
02489
02490 uves_free_table(&selected);
02491 uves_polynomial_delete(&pol);
02492 return;
02493
02494 }
02495
02504 static void uves_wavecal_qclog_intmon(cpl_table* table,
02505 const cpl_table *line_intmon,
02506 const uves_propertylist* raw_header,
02507 bool flames,
02508 int fibre,
02509 enum uves_chip chip,
02510 cpl_table* qclog)
02511 {
02512 const char *qc_intavg_name = NULL;
02513 const char *qc_nlinint_name = NULL;
02514
02515 cpl_table *temp = NULL;
02516
02517 check_nomsg(uves_qclog_add_string(qclog,
02518 "QC TEST2 ID",
02519 "Line-Intensity-Test-Results",
02520 "Name of QC test",
02521 "%s"));
02522
02523 check_nomsg( uves_qclog_add_common_wave(raw_header,
02524 chip, qclog) );
02525
02526 {
02527 double tolerance = 0.001;
02528
02529
02530
02531
02532
02533
02534 double exptime;
02535
02536 int N_bright = cpl_table_get_nrow(line_intmon);
02537 int i;
02538
02539 check( exptime = uves_pfits_get_exptime(raw_header),
02540 "Could not get exposure time");
02541
02542 cpl_table_new_column(table, "Intensity", CPL_TYPE_DOUBLE);
02543 for (i = 0; i < cpl_table_get_nrow(table); i++)
02544 {
02545 int is_null;
02546 double ident = cpl_table_get_double(table, "Ident", i, &is_null);
02547
02548 if (!is_null)
02549 {
02550 int bright_index = uves_wavecal_find_nearest(
02551 line_intmon, ident, 0, N_bright-1);
02552
02553 double bright = cpl_table_get_double(
02554 line_intmon, "Wave", bright_index, NULL);
02555
02556 if (fabs(bright - ident) < tolerance)
02557 {
02558 double peak = cpl_table_get_double(table, "Peak", i, NULL);
02559 double pixelsize =
02560 fabs(cpl_table_get_double(table, LINETAB_PIXELSIZE, i, NULL));
02561
02562 double lambda_fwhm = cpl_table_get_double(table, "Xwidth", i, NULL)
02563 * TWOSQRT2LN2 * pixelsize;
02564
02565
02566 double intensity = peak * lambda_fwhm / exptime;
02567
02568
02569 cpl_table_set_double(table, "Intensity", i, intensity);
02570 }
02571 else
02572 {
02573 cpl_table_set_invalid(table, "Intensity", i);
02574 }
02575 }
02576 else
02577 {
02578 cpl_table_set_invalid(table, "Intensity", i);
02579 }
02580 }
02581 }
02582
02583 uves_free_table(&temp);
02584 temp = cpl_table_duplicate(table);
02585 uves_erase_invalid_table_rows(temp, "Intensity");
02586
02587 {
02588 double mean;
02589 if (cpl_table_get_nrow(temp) == 0)
02590 {
02591 uves_msg_warning("No bright lines found!");
02592 mean = 0;
02593 }
02594 else
02595 {
02596 mean = cpl_table_get_column_mean(temp, "Intensity");
02597 }
02598
02599 if (flames)
02600 {
02601 qc_intavg_name = uves_sprintf("QC FIB%d INTAVG", fibre+1);
02602 qc_nlinint_name = uves_sprintf("QC FIB%d NLININT", fibre+1);
02603 }
02604 else
02605 {
02606 qc_intavg_name = uves_sprintf("QC INTAVG");
02607 qc_nlinint_name = uves_sprintf("QC NLININT");
02608 }
02609
02610 check_nomsg(uves_qclog_add_double(qclog,
02611 qc_intavg_name,
02612 mean,
02613 "average intensity of line list",
02614 "%.4f"));
02615
02616 check_nomsg(uves_qclog_add_int(qclog,
02617 qc_nlinint_name,
02618 cpl_table_get_nrow(temp),
02619 "No of lines to measure INTAVG",
02620 "%d"));
02621 }
02622
02623 cleanup:
02624 uves_free_string_const(&qc_intavg_name);
02625 uves_free_string_const(&qc_nlinint_name);
02626 uves_free_table(&temp);
02627 return;
02628 }
02629