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