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