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