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),
00672 "Line search failed");
00673
00674
00675 {
00676 int degree = 5;
00677
00678
00679 uves_polynomial_delete(&initial_dispersion);
00680 cpl_free(relative_order);
00681 check( initial_dispersion = uves_wavecal_firstsolution(linetable,
00682 guess,
00683 absolute_order,
00684 ordertable,
00685 order_locations,
00686 flames,
00687 offset,
00688 &relative_order,
00689 degree,
00690 SHIFT_MAX,
00691 SHIFT_STEP,
00692 SHIFT_TOLERANCE,
00693 MAXERROR,
00694 first_absolute_order,
00695 last_absolute_order),
00696 "Could not get first solution");
00697 }
00698
00699
00700 if (flames)
00701 {
00702
00703
00704
00705
00706
00707
00708
00709 cpl_table_add_scalar(linetable, "Y", tab_in_out_oshift);
00710 cpl_table_add_scalar(linetable, "Ynew", - tab_in_out_yshift - offset);
00711 }
00712
00713
00714 check( *dispersion_relation = uves_wavecal_identify(linetable,
00715 line_refer,
00716 initial_dispersion,
00717 DEGREE,
00718 TOLERANCE, ALPHA, MAXERROR,
00719 kappa),
00720 "Could not calibrate orders");
00721
00722 if (flames)
00723 {
00724
00725
00726
00727
00728
00729 cpl_table_add_scalar(linetable, "Ynew", + tab_in_out_yshift + offset);
00730 }
00731
00732
00733
00734
00735 if (flames || (trace == 0 && window == 2)|| (window == 1 && NWINDOWS == 1))
00736 {
00737
00738 check(( cpl_table_duplicate_column(linetable, "deltaX", linetable, "Xwidth"),
00739 cpl_table_multiply_scalar (linetable, "deltaX", TWOSQRT2LN2)),
00740 "Error creating FWHM column");
00741
00742
00743 check_nomsg( temp = uves_extract_table_rows(
00744 linetable, "NLinSol", CPL_NOT_EQUAL_TO, 0) );
00745
00746 check( uves_plot_table(temp, "Order", LINETAB_RESIDUAL, "Residual of fit"),
00747 "Plotting failed");
00748
00749 check( uves_plot_table(temp, "X", "deltaX", "line FWHM (mean = %.2f pixels)",
00750 cpl_table_get_column_mean(linetable, "deltaX")),
00751 "Plotting failed");
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764 {
00765
00766 double wavestep;
00767 double lambda_start = 0;
00768 int n_traces = 1;
00769
00770
00771 int i, nbins;
00772 bool threshold_to_positive = true;
00773
00774 cpl_table_new_column(linetable, "deltaLambda", CPL_TYPE_DOUBLE);
00775
00776 check( rebinned_noise = uves_rebin(spectrum_noise,
00777 parameters,
00778 recipe_id,
00779 linetable,
00780 *dispersion_relation,
00781 *first_absolute_order,
00782 *last_absolute_order,
00783 n_traces,
00784 threshold_to_positive,
00785 true,
00786 &rebinned_header),
00787 "Could not rebin noise of arc lamp spectrum");
00788
00789 threshold_to_positive = false;
00790 uves_free_propertylist(&rebinned_header);
00791 check( rebinned = uves_rebin(spectrum,
00792 parameters,
00793 recipe_id,
00794 linetable,
00795 *dispersion_relation,
00796 *first_absolute_order,
00797 *last_absolute_order,
00798 n_traces,
00799 threshold_to_positive,
00800 false,
00801 &rebinned_header),
00802 "Could not rebin arc lamp spectrum");
00803
00804
00805 if (DEBUG)
00806 {
00807 check( uves_save_image_local("Rebinned spectrum",
00808 "wxb", rebinned, chip,
00809 trace, window, rebinned_header, true),
00810 "Error saving rebinned spectrum");
00811
00812 check( uves_save_image_local("Noise of rebinned spectrum",
00813 "errwxb", rebinned_noise, chip,
00814 trace, window, rebinned_header, true),
00815 "Error saving noise of rebinned spectrum");
00816 }
00817
00818 check( merged = uves_merge_orders(rebinned,
00819 rebinned_noise,
00820 rebinned_header,
00821 m_method,
00822 n_traces,
00823 &merged_header,
00824 0,0,chip,
00825 &merged_noise),
00826 "Could not merge arc lamp spectrum");
00827
00828 check( uves_plot_image_rows(merged, 1, 1, 1,
00829 "Wavelength (arbitrary units)",
00830 "Flux", "Resampled arc lamp spectrum"),
00831 "Plotting failed");
00832
00833
00834 if (DEBUG)
00835 {
00836 check( uves_save_image_local("Rebinned, merged spectrum",
00837 "merged", merged, chip,
00838 trace, window, merged_header, true),
00839 "Error saving merged spectrum");
00840 }
00841
00842 nbins = cpl_image_get_size_x(merged);
00843
00844 check( wavestep = uves_pfits_get_cdelt1(merged_header),
00845 "Error reading resampling step size");
00846
00847 check( lambda_start = uves_pfits_get_crval1(merged_header),
00848 "Could not read start wavelength of merged spectrum");
00849
00850
00851
00852
00853 if (flames && trace == 0 && corvel_frm != NULL)
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
00893
00894
00895 const char* drs_base_name=NULL;
00896 const char* prefid=NULL;
00897 double ccf_posmax_zero_point=0;
00898 double ccf_posmax_zero_point_iter0=0;
00899 double cvel_max=0;
00900 double cvel_sig=0;
00901 if(chip == UVES_CHIP_REDL) {
00902 prefid="l";
00903 } else {
00904 prefid="u";
00905 }
00906 const char* name=NULL;
00907 const char* file=NULL;
00908 cpl_propertylist* plist=NULL;
00909 double drs_cvel_min=0;
00910 double drs_cvel_max=0;
00911
00912
00913 check( uves_save_image_local("Rebinned spectrum",
00914 "wxb", rebinned, chip,
00915 trace, window, rebinned_header, true),
00916 "Error saving rebinned spectrum");
00917
00918 check( uves_save_image_local("Rebinned, merged spectrum",
00919 "mwxb", merged, chip,
00920 trace, window, merged_header, true),
00921 "Error saving merged spectrum");
00922
00923
00924 check( file = uves_local_filename("wxb", chip, trace, window),
00925 "Error getting filename");
00926 check_nomsg(plist=cpl_propertylist_load(file,0));
00927
00928 name=uves_sprintf("wfxb_%s%s%4.4d%s",prefid,"_raw",1,".fits");
00929 drs_base_name=uves_sprintf("fxb_%s",prefid);
00930
00931 cpl_image_save(rebinned,name, CPL_BPP_IEEE_FLOAT,plist,
00932 CPL_IO_DEFAULT);
00933
00934
00935 name=uves_sprintf("mwfxb_%s%s%4.4d%s",prefid,"_raw",1,".fits");
00936 cpl_image_save(merged,name, CPL_BPP_IEEE_FLOAT,plist,
00937 CPL_IO_DEFAULT);
00938
00939 cpl_propertylist_delete(plist);
00940
00941
00942 int ord_max=(*first_absolute_order-*last_absolute_order)+1;
00943
00944 uves_msg("cvel max:%g %g",DRS_CVEL_MAX,DRS_CVEL_MIN);
00945 drs_cvel_max =DRS_CVEL_MAX;
00946 drs_cvel_min =DRS_CVEL_MIN;
00947
00948 check_nomsg(flames_reduce_vcorrel(drs_base_name,
00949 "cvel2",
00950 prefid,
00951 ord_max,
00952 corvel_frm,
00953 "_raw0001",
00954 "_raw0001",
00955 DRS_CVEL_MIN,
00956 DRS_CVEL_MAX,
00957 &ccf_posmax_zero_point,
00958 &cvel_max,
00959 &cvel_sig,
00960 flames_qclog[0]));
00961
00962 drs_cvel_max +=cvel_max;
00963 drs_cvel_min +=cvel_max;
00964 ccf_posmax_zero_point_iter0 =cvel_max;
00965 uves_msg("cvel max:%g %g",drs_cvel_max,drs_cvel_min);
00966
00967 check_nomsg(flames_reduce_vcorrel(drs_base_name,
00968 "cvel2",
00969 prefid,
00970 ord_max,
00971 corvel_frm,
00972 "_raw0001",
00973 "_raw0001",
00974 drs_cvel_min,
00975 drs_cvel_max,
00976 &ccf_posmax_zero_point,
00977 &cvel_max,
00978 &cvel_sig,
00979 flames_qclog[1]));
00980
00981 drs_cvel_max +=cvel_max;
00982 drs_cvel_min +=cvel_max;
00983 ccf_posmax_zero_point =ccf_posmax_zero_point_iter0;
00984 ck0_nomsg(uves_qclog_add_double(flames_qclog[1],
00985 "QC CCF POSOFF",
00986 ccf_posmax_zero_point,
00987 "CCF pos avg from ThAr calibration",
00988 "%f"));
00989
00990
00991 uves_msg("cvel max:%g min: %g zp: %g",
00992 drs_cvel_max,drs_cvel_min,ccf_posmax_zero_point);
00993
00994
00995 }
00996
00997
00998
00999
01000
01001 for (i = 0; i < cpl_table_get_nrow(linetable); i++)
01002 {
01003 double lambda = cpl_table_get_double(
01004 linetable, LINETAB_LAMBDAC, i, NULL);
01005 double width =
01006 cpl_table_get_double(linetable, "Xwidth" , i, NULL) *
01007 fabs(cpl_table_get_double(linetable, LINETAB_PIXELSIZE, i, NULL));
01008
01009
01010
01011 int bin = 1 +
01012 uves_round_double((lambda - lambda_start) / wavestep);
01013 double width_bin = width / wavestep;
01014
01015
01016 int first_bin = uves_max_int( 1, uves_round_double(bin - 5*width_bin));
01017 int last_bin = uves_min_int(nbins, uves_round_double(bin + 5*width_bin));
01018
01019 double my, sigma, norm, background;
01020 double lambda_fwhm;
01021
01022 if (cpl_table_is_valid(linetable, "Ident", i) && first_bin < last_bin)
01023 {
01024
01025 uves_fit_1d_image(merged,
01026 #if 1
01027 merged_noise,
01028 #else
01029 NULL,
01030 #endif
01031 NULL,
01032 true,
01033 false,
01034 false,
01035 first_bin,
01036 last_bin,
01037 1,
01038 &my,
01039 &sigma,
01040 &norm,
01041 &background, NULL,
01042 NULL,
01043 NULL,
01044 NULL,
01045
01046 uves_gauss,
01047 uves_gauss_derivative,
01048 4);
01049
01050 if (cpl_error_get_code() == CPL_ERROR_CONTINUE)
01051 {
01052 uves_error_reset();
01053 uves_msg_debug("Gaussian fitting failed "
01054 "at lambda = %f wlu, bins = "
01055 "%d - %d, ignoring line",
01056 lambda, first_bin, last_bin);
01057
01058 cpl_table_set_invalid(linetable, "deltaLambda", i);
01059
01060 }
01061 else
01062 {
01063 assure(cpl_error_get_code() == CPL_ERROR_NONE,
01064 cpl_error_get_code(), "Gaussian fitting failed");
01065
01066
01067 lambda_fwhm = TWOSQRT2LN2 * sigma * wavestep;
01068
01069 cpl_table_set_double(linetable, "deltaLambda",
01070 i, lambda_fwhm);
01071
01072 }
01073 }
01074 else
01075 {
01076 cpl_table_set_invalid(linetable, "deltaLambda", i);
01077 }
01078 }
01079
01080
01081
01082 check(( cpl_table_duplicate_column(linetable, "Resol",
01083 linetable, LINETAB_LAMBDAC),
01084 cpl_table_divide_columns (linetable, "Resol",
01085 "deltaLambda")),
01086 "Error creating 'Resol' column");
01087
01088
01089 {
01090
01091 int ninvalid=0;
01092 int nrows=0;
01093 double resol_avg = 0;
01094 double resol_stdev = 0;
01095 double kappar = 10.0;
01096 nrows=cpl_table_get_nrow(linetable);
01097 ninvalid=cpl_table_count_invalid(linetable,"Resol");
01098 assure(ninvalid < nrows,CPL_ERROR_ILLEGAL_INPUT,
01099 "No valid elements in Resol column. "
01100 "You must decrease parameter rebin.wavestep");
01101 check_nomsg(resol_avg=cpl_table_get_column_median(linetable, "Resol"));
01102 check_nomsg(resol_stdev=cpl_table_get_column_stdev (linetable, "Resol"));
01103
01104 for (i = 0; i < cpl_table_get_nrow(linetable); i++)
01105 {
01106 double r = cpl_table_get_double(linetable, "Resol", i, NULL);
01107 if (r < resol_avg - kappar*resol_stdev ||
01108 r > resol_avg + kappar*resol_stdev)
01109 {
01110 cpl_table_set_invalid(linetable, "Resol", i);
01111 cpl_table_set_invalid(linetable, "deltaLambda", i);
01112 }
01113 }
01114 }
01115
01116
01117
01118
01119
01120
01121 check( uves_plot_table(linetable, LINETAB_LAMBDAC, "Resol",
01122 "(l, l / dl)"), "Plotting failed");
01123 }
01124
01125
01126 uves_free_table(&temp);
01127 check( temp = cpl_table_duplicate(linetable),
01128 "Error copying line table");
01129 check( uves_erase_invalid_table_rows(temp, "Ident"),
01130 "Error removing un-identified lines");
01131 check( uves_plot_table(temp, "X", "Ynew",
01132 "Line identifications"),
01133 "Plotting failed");
01134 uves_free_table(&temp);
01135
01136 }
01137
01138 if (DEBUG)
01139 {
01140
01141
01142
01143
01144 if (0) check( uves_draw_lines(debug_image, initial_dispersion,
01145 order_locations, guess,
01146 "Ident", "Order", relative_order,
01147 -1, -1,
01148 false,
01149 12), "Error drawing guess solution");
01150
01151
01152 check( uves_draw_lines(debug_image, initial_dispersion, order_locations,
01153 line_refer, "Wave", NULL, relative_order,
01154 uves_min_int(*first_absolute_order, *last_absolute_order),
01155 uves_max_int(*first_absolute_order, *last_absolute_order),
01156 true,
01157 8), "Error drawing catalogue lines");
01158
01159
01160 check( uves_draw_lines(debug_image, *dispersion_relation, order_locations,
01161 line_refer, "Wave", NULL, relative_order,
01162 uves_min_int(*first_absolute_order, *last_absolute_order),
01163 uves_max_int(*first_absolute_order, *last_absolute_order),
01164 true,
01165 16), "Error drawing catalogue lines");
01166
01167
01168 if (0) check( uves_draw_lines(debug_image, initial_dispersion,
01169 order_locations, linetable,
01170 LINETAB_LAMBDAC, "Order", relative_order,
01171 -1, -1,
01172 false,
01173 -16), "Error drawing detected lines");
01174
01175
01176 uves_free_table(&temp);
01177 check(( temp = cpl_table_duplicate(linetable),
01178
01179 uves_erase_invalid_table_rows(temp, "Ident")),
01180 "Error duplicating table");
01181
01182 check( uves_draw_lines(debug_image, *dispersion_relation, order_locations,
01183 temp, LINETAB_LAMBDAC, "Order", relative_order,
01184 -1, -1,
01185 true,
01186 0), "Error drawing detected lines");
01187
01188
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 check( uves_save_image_local("Debug image", "rawdebug",
01216 debug_image, chip, trace, window,
01217 rotated_header, true),
01218 "Error saving spectrum");
01219 }
01220
01221 if (flames)
01222 {
01223 int start = 0;
01224 int count = cpl_table_get_nrow(linetable);
01225
01226 check_nomsg( cpl_table_new_column(linetable, "Fibre", CPL_TYPE_INT) );
01227
01228 cpl_table_fill_column_window(linetable, "Fibre",
01229 start, count,
01230 trace + 1);
01231 }
01232
01233 cleanup:
01234
01235 uves_free_table(&info_tbl);
01236 uves_free_table(&temp);
01237 uves_free_image(&weights_opt);
01238 uves_free_table(&cr_table);
01239 uves_free_image(&cr_image);
01240 uves_free_image(&spectrum);
01241 uves_free_image(&spectrum_noise);
01242 uves_free_image(&debug_image);
01243 uves_free_image(&rebinned);
01244 uves_free_image(&rebinned_noise);
01245 uves_free_image(&merged);
01246 uves_free_image(&merged_noise);
01247 uves_free_propertylist(&spectrum_header);
01248 uves_free_propertylist(&rebinned_header);
01249 uves_free_propertylist(&merged_header);
01250 cpl_free(relative_order);
01251 uves_polynomial_delete(&initial_dispersion);
01252 uves_free_table(&order_trace);
01253
01254 return linetable;
01255 }
01256
01257
01258
01259
01284
01285 void
01286 uves_wavecal_exe_body(cpl_frameset *frames,
01287 bool flames,
01288 const char *recipe_id,
01289 const cpl_parameterlist *parameters,
01290 const char *starttime)
01291 {
01292
01293
01294
01295
01296
01297 bool DEBUG;
01298
01299
01300 int NWINDOWS;
01301 double OFFSET;
01302 double SLITLENGTH_par;
01303
01304
01305 int RANGE;
01306 int MAXLINES;
01307 int MINLINES;
01308 centering_method CENTERING_METHOD;
01309
01310
01311 double SHIFT_MAX;
01312 double SHIFT_STEP;
01313 double SHIFT_TOLERANCE;
01314
01315
01316 double ALPHA;
01317 double MAXERROR;
01318 int DEGREE;
01319
01320 double TOLERANCE;
01321 double KAPPA;
01322
01323
01324 cpl_image *arclamp[2] = {NULL, NULL};
01325 cpl_image *arclamp_noise = NULL;
01326 uves_propertylist *arclamp_header[2] = {NULL, NULL};
01327 uves_propertylist *rotated_header[2] = {NULL, NULL};
01328
01329
01330 cpl_table *ordertable = NULL;
01331 uves_propertylist *ordertable_header = NULL;
01332 polynomial *order_locations = NULL;
01333 cpl_table *traces = NULL;
01334
01335
01336 cpl_image *master_bias = NULL;
01337 uves_propertylist *master_bias_header = NULL;
01338
01339
01340 cpl_image *master_flat = NULL;
01341 cpl_image *mflat_noise = NULL;
01342 uves_propertylist *master_flat_header = NULL;
01343
01344
01345 cpl_image *weights = NULL;
01346
01347
01348
01349
01350
01351
01352
01353
01354 int* fibres_mask=NULL;
01355 double* fibres_pos=NULL;
01356
01357
01358 cpl_table *guess = NULL;
01359 polynomial *absolute_order = NULL;
01360
01361
01362 cpl_table *corvel = NULL;
01363 cpl_frame *corvel_frm = NULL;
01364 uves_propertylist *corvel_header = NULL;
01365
01366
01367 cpl_table *line_refer = NULL;
01368 cpl_table *line_intmon = NULL;
01369
01370
01371 lt_type *linetable = NULL;
01372
01373 uves_propertylist *primary_header = NULL;
01374 uves_propertylist *table_header = NULL;
01375
01376 cpl_table *qclog[3] = {NULL, NULL, NULL};
01377
01378
01379 cpl_image *absorder_image = NULL;
01380 const char *arclamp_filename = "";
01381 const char *line_refer_filename = "";
01382 const char *line_intmon_filename = "";
01383 char *product_filename = NULL;
01384 char *temp = NULL;
01385 bool blue = false;
01386 bool sim_cal = false;
01387 enum uves_chip chip;
01388 int binx = 0;
01389 int biny = 0;
01390 bool drs_cvel_sw=false;
01391 const char* PROCESS_CHIP=NULL;
01392 extract_method em;
01393
01394
01395 {
01396 const char *centering_m = "gaussian";
01397 const char *profile = "";
01398
01399
01400
01401
01402 check( uves_get_parameter(parameters, NULL, "uves", "debug",
01403 CPL_TYPE_BOOL, &DEBUG), "Could not read parameter");
01404
01405 check( uves_get_parameter(parameters, NULL, "uves", "process_chip", CPL_TYPE_STRING, &PROCESS_CHIP),
01406 "Could not read parameter");
01407 uves_string_toupper((char*)PROCESS_CHIP);
01408
01409
01410 check( uves_get_parameter(parameters, NULL, recipe_id, "nwindows",
01411 CPL_TYPE_INT , &NWINDOWS ), "Could not read parameter");
01412 check( uves_get_parameter(parameters, NULL, recipe_id, "length",
01413 CPL_TYPE_DOUBLE, &SLITLENGTH_par), "Could not read parameter");
01414 check( uves_get_parameter(parameters, NULL, recipe_id, "offset",
01415 CPL_TYPE_DOUBLE, &OFFSET ), "Could not read parameter");
01416
01417
01418
01419 temp = uves_sprintf("%s.%s", recipe_id, UVES_EXTRACT_ID);
01420 check( em = uves_get_extract_method(parameters, NULL, temp),
01421 "Could not read extraction method");
01422
01423 check( uves_get_parameter(parameters, NULL, recipe_id, UVES_EXTRACT_ID ".profile",
01424 CPL_TYPE_STRING, &profile), "Could not read parameter");
01425
01426 assure( em == EXTRACT_LINEAR || em == EXTRACT_AVERAGE || em == EXTRACT_WEIGHTED ||
01427 (em == EXTRACT_OPTIMAL && strcmp(profile, "constant") == 0),
01428 CPL_ERROR_UNSUPPORTED_MODE,
01429 "Only linear/average/weighted/optimal(constant profile) extraction "
01430 "methods are supported by this recipe");
01431
01432
01433 check( uves_get_parameter(parameters, NULL, recipe_id, "search.range",
01434 CPL_TYPE_INT , &RANGE ), "Could not read parameter");
01435 check( uves_get_parameter(parameters, NULL, recipe_id, "search.minlines",
01436 CPL_TYPE_INT , &MINLINES ), "Could not read parameter");
01437 check( uves_get_parameter(parameters, NULL, recipe_id, "search.maxlines",
01438 CPL_TYPE_INT , &MAXLINES ), "Could not read parameter");
01439
01440
01441
01442
01443 if (strcmp(centering_m, "gravity" ) == 0) CENTERING_METHOD = CENTERING_GRAVITY;
01444 else if (strcmp(centering_m, "gaussian") == 0) CENTERING_METHOD = CENTERING_GAUSSIAN;
01445 else
01446 {
01447 assure(false, CPL_ERROR_ILLEGAL_INPUT,
01448 "Unrecognized parameter value '%s'", centering_m);
01449 }
01450
01451
01452 check( uves_get_parameter(parameters, NULL, recipe_id, "first.shiftmax",
01453 CPL_TYPE_DOUBLE , &SHIFT_MAX ),
01454 "Could not read parameter");
01455 check( uves_get_parameter(parameters, NULL, recipe_id, "first.shiftstep",
01456 CPL_TYPE_DOUBLE , &SHIFT_STEP ),
01457 "Could not read parameter");
01458 check( uves_get_parameter(parameters, NULL, recipe_id, "first.shifttoler",
01459 CPL_TYPE_DOUBLE , &SHIFT_TOLERANCE),
01460 "Could not read parameter");
01461
01462
01463 check( uves_get_parameter(parameters, NULL, recipe_id, "identify.alpha",
01464 CPL_TYPE_DOUBLE , &ALPHA ), "Could not read parameter");
01465 check( uves_get_parameter(parameters, NULL, recipe_id, "identify.maxerror",
01466 CPL_TYPE_DOUBLE , &MAXERROR ), "Could not read parameter");
01467 check( uves_get_parameter(parameters, NULL, recipe_id, "identify.degree",
01468 CPL_TYPE_INT , &DEGREE ), "Could not read parameter");
01469
01470
01471 check( uves_get_parameter(parameters, NULL, recipe_id, "calibrate.tolerance",
01472 CPL_TYPE_DOUBLE, &TOLERANCE ), "Could not read parameter");
01473 check( uves_get_parameter(parameters, NULL, recipe_id, "calibrate.kappa",
01474 CPL_TYPE_DOUBLE, &KAPPA ), "Could not read parameter");
01475
01476
01477 if (CENTERING_METHOD == CENTERING_GRAVITY)
01478 {
01479 uves_msg_warning("Centering method 'gravity' might lead to inaccurate "
01480 "results. Recommended is 'gaussian'");
01481 }
01482 }
01483
01484
01485 check( uves_load_arclamp(frames, flames, &arclamp_filename, arclamp, arclamp_header,
01486 rotated_header, &blue, &sim_cal), "Error loading raw frame");
01487
01488
01489 check( uves_load_linerefertable(frames, &line_refer_filename, &line_refer, NULL),
01490 "Could not load line reference table");
01491 uves_msg("Using line reference table '%s'", line_refer_filename);
01492
01493
01494 if (cpl_frameset_find(frames, UVES_LINE_INTMON_TABLE) != NULL)
01495 {
01496 uves_free_table(&line_intmon);
01497 check( uves_load_lineintmon(frames, &line_intmon_filename,
01498 &line_intmon),
01499 "Error loading line reference table");
01500
01501 uves_msg("Using bright line table '%s'", line_intmon_filename);
01502 }
01503
01504
01505
01506
01507 check (binx = uves_pfits_get_binx(arclamp_header[0]),
01508 "Could not read x binning factor from input header");
01509 check (biny = uves_pfits_get_biny(arclamp_header[0]),
01510 "Could not read y binning factor from input header");
01511 SLITLENGTH_par /= (1.0*binx);
01512 RANGE /= (1.0*biny);
01513 SHIFT_MAX /= (1.0*binx);
01514 SHIFT_STEP /= (1.0*binx);
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525 for (chip = uves_chip_get_first(blue);
01526 chip != UVES_CHIP_INVALID;
01527 chip = uves_chip_get_next(chip)) {
01528
01529
01530 if(strcmp(PROCESS_CHIP,"REDU") == 0) {
01531 chip = uves_chip_get_next(chip);
01532 }
01533
01534 const char *ordertable_filename = "";
01535 const char *corvel_filename = "";
01536 const char *master_flat_filename = "";
01537 const char *master_bias_filename = "";
01538 const char *weights_filename = "";
01539
01540 const char *guess_filename = "";
01541 const char *chip_name = "";
01542 int ntraces;
01543 int tracerow;
01544 int raw_index = uves_chip_get_index(chip);
01545 int current_linetable_extension;
01546 int tab_in_out_oshift = -1;
01547 double tab_in_out_yshift = -1;
01548 double slitlength;
01549
01550 uves_msg("Processing %s chip in '%s'",
01551 uves_chip_tostring_upper(chip), arclamp_filename);
01552
01553 check_nomsg( chip_name = uves_pfits_get_chipid(arclamp_header[raw_index], chip));
01554
01555
01556 uves_msg_debug("binning = %dx%d", binx, biny);
01557
01558
01559
01560 uves_free_table (&ordertable);
01561 uves_free_propertylist(&ordertable_header);
01562 uves_polynomial_delete(&order_locations);
01563 uves_free_table (&traces);
01564
01565
01566 check( uves_load_ordertable(frames,
01567 flames,
01568 chip_name,
01569 &ordertable_filename,
01570 &ordertable,
01571 &ordertable_header,
01572 NULL,
01573 &order_locations,
01574 &traces,
01575 (flames) ? &tab_in_out_oshift : NULL,
01576 (flames) ? &tab_in_out_yshift : NULL,
01577 &fibres_mask,
01578 &fibres_pos,
01579 chip,
01580 false ),
01581 "Could not load order table");
01582 uves_msg("Using order table in '%s'", ordertable_filename);
01583 ntraces = cpl_table_get_nrow(traces);
01584 uves_free_double(&fibres_pos);
01585 uves_free_int(&fibres_mask);
01586
01587
01588 uves_free_image(&master_bias);
01589 uves_free_propertylist(&master_bias_header);
01590 if (cpl_frameset_find(frames, UVES_MASTER_BIAS(chip)) != NULL)
01591 {
01592 check( uves_load_mbias(frames, chip_name, &master_bias_filename, &master_bias,
01593 &master_bias_header, chip),
01594 "Error loading master bias");
01595
01596 uves_msg_low("Using master bias in '%s'", master_bias_filename);
01597 }
01598 else
01599 {
01600 uves_msg_warning("Master bias not provided. Bias subtraction not done");
01601 }
01602
01603
01604
01605 uves_free_image(&master_flat);
01606 uves_free_propertylist(&master_flat_header);
01607 if ((cpl_frameset_find(frames, UVES_MASTER_FLAT(chip)) != NULL ||
01608 cpl_frameset_find(frames, UVES_MASTER_DFLAT(chip)) != NULL ||
01609 cpl_frameset_find(frames, UVES_MASTER_IFLAT(chip)) != NULL ||
01610 cpl_frameset_find(frames, UVES_MASTER_TFLAT(chip)) != NULL))
01611 {
01612 check( uves_load_mflat(frames, chip_name, &master_flat_filename, &master_flat,
01613 &master_flat_header, chip, NULL),
01614 "Error loading master flat");
01615
01616 uves_msg_low("Using master flat in '%s'", master_flat_filename);
01617 }
01618 else
01619 {
01620 uves_msg_warning("Master flat not provided. Flat-fielding not done");
01621 }
01622
01623
01624 if (em == EXTRACT_WEIGHTED) {
01625 uves_free_image(&weights);
01626 check( weights = uves_load_weights(frames, &weights_filename, chip),
01627 "Error loading weight map");
01628
01629 uves_msg_low("Using weight map %s", weights_filename);
01630 }
01631
01632 if (flames)
01633
01634 {
01635 if ((corvel_frm=cpl_frameset_find(frames, FLAMES_CORVEL_MASK)))
01636 {
01637 check( uves_load_corvel(frames,
01638 &corvel, &corvel_header,
01639 &corvel_filename),
01640 "Could not load velocity correction table");
01641
01642 uves_msg("Using velocity correction table %s", corvel_filename);
01643 drs_cvel_sw=true;
01644
01645
01646 }
01647 else
01648 {
01649 uves_msg("No corvel table found. Switch off corvel");
01650 corvel = NULL;
01651 }
01652 }
01653
01654
01655 uves_lt_delete(&linetable);
01656 linetable = uves_lt_new(NWINDOWS, ntraces);
01657
01658
01659
01660 uves_qclog_delete(&qclog[0]); qclog[0] = uves_qclog_init(arclamp_header[raw_index], chip);
01661 uves_qclog_delete(&qclog[1]); qclog[1] = uves_qclog_init(arclamp_header[raw_index], chip);
01662
01663
01664 if (DEBUG) check( uves_save_image_local("Arc lamp frame", "raw",
01665 arclamp[raw_index],
01666 chip, -1, -1, rotated_header[raw_index], true),
01667 "Error saving arc lamp frame");
01668
01669 if (master_bias != NULL)
01670 {
01671 uves_msg("Subtracting master bias");
01672
01673 check( uves_subtract_bias(arclamp[raw_index], master_bias),
01674 "Error during bias subtraction");
01675 }
01676 else {
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686 }
01687
01688
01689
01690 uves_free_image(&arclamp_noise);
01691 check( arclamp_noise = uves_define_noise(arclamp[raw_index],
01692 arclamp_header[raw_index], 1, chip),
01693 "Could not set arc lamp noise");
01694
01695 if (master_flat != NULL)
01696 {
01697 uves_msg("Dividing by master flat");
01698
01699 uves_free_image(&mflat_noise);
01700 check( mflat_noise =
01701 uves_define_noise(master_flat, master_flat_header,
01702 uves_pfits_get_datancom(master_flat_header),
01703 chip),
01704 "Could not set master flat error bars");
01705
01706 check( uves_flatfielding(arclamp[raw_index], arclamp_noise,
01707 master_flat, mflat_noise),
01708 "Error while dividing by flat field");
01709 }
01710
01711 if (DEBUG) check( uves_save_image_local("Pre-processed arc lamp frame",
01712 "preproc",
01713 arclamp[raw_index], chip, -1, -1,
01714 rotated_header[raw_index], true),
01715 "Error saving arc lamp frame");
01716
01717
01718 if (SLITLENGTH_par < 0) {
01719
01720 double header_full_slit;
01721
01722 check( header_full_slit =
01723 uves_pfits_get_slitlength_pixels(arclamp_header[raw_index], chip),
01724 "Could not read slit length");
01725
01726
01727
01728
01729 slitlength = uves_max_double(1.0, (header_full_slit - 2)/NWINDOWS);
01730
01731 uves_msg("Full slit = %.2f pixels", header_full_slit);
01732 }
01733 else {
01734 slitlength = SLITLENGTH_par;
01735 }
01736
01737
01738
01739 for(tracerow = 0; tracerow < ntraces; tracerow++) {
01740 double trace_offset;
01741 int trace_number;
01742 int trace_enabled;
01743
01744 trace_offset = cpl_table_get_double(traces, "Offset" , tracerow, NULL);
01745 trace_number = cpl_table_get_int (traces, "TraceID" , tracerow, NULL);
01746 trace_enabled = cpl_table_get_int (traces, "Tracemask", tracerow, NULL);
01747
01748 if (ntraces > 1) {
01749 uves_msg("Processing trace %d", trace_number);
01750 }
01751
01752 if (flames && sim_cal)
01753 {
01754
01755 trace_enabled = (trace_number == 1) ? 1 : 0;
01756 }
01757
01758 uves_msg_low("Trace offset = %.2f pixels ; enabled = %d",
01759 trace_offset, trace_enabled);
01760
01761 assure( flames || trace_number == 0, CPL_ERROR_ILLEGAL_INPUT,
01762 "%s: UVES trace number must be 0, it is %d",
01763 ordertable_filename, trace_number );
01764
01765
01766 if (trace_enabled != 0) {
01767 int window;
01768
01769
01770 uves_free_table (&guess);
01771 uves_polynomial_delete(&absolute_order);
01772
01773 check( uves_load_linetable(
01774 frames, flames, chip_name, order_locations,
01775 cpl_table_get_column_min(ordertable, "Order"),
01776 cpl_table_get_column_max(ordertable, "Order"),
01777 &guess_filename, &guess,
01778 NULL, NULL,
01779 &absolute_order, chip, trace_number, -1),
01780 "Could not load guess line table for trace number %d",
01781 trace_number);
01782 uves_msg("Using guess line table '%s'", guess_filename);
01783
01784 if (DEBUG)
01785 {
01786
01787
01788
01789 int x, y;
01790
01791 absorder_image = cpl_image_new(cpl_image_get_size_x(arclamp[raw_index]),
01792 cpl_image_get_size_y(arclamp[raw_index]),
01793 CPL_TYPE_FLOAT);
01794 assure_mem(absorder_image);
01795
01796 for (y = 1; y <= cpl_image_get_size_y(arclamp[raw_index]); y++)
01797 {
01798 for (x = 1; x <= cpl_image_get_size_x(arclamp[raw_index]); x++)
01799 {
01800 double absorder =
01801 uves_polynomial_evaluate_2d(absolute_order, x, y);
01802
01803 cpl_image_set(absorder_image, x, y, absorder);
01804 }
01805 }
01806
01807 check( uves_save_image_local("Absolute order image", "absord",
01808 absorder_image, chip, trace_number,
01809 1, rotated_header[raw_index], true),
01810 "Error saving absolute order image");
01811
01812 uves_free_image(&absorder_image);
01813 }
01814
01815
01816 for (window = 1; window <= NWINDOWS; window ++) {
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830 double window_offset =
01831 slitlength * (window - (NWINDOWS+1) / 2.0);
01832
01833
01834 double offset = trace_offset + window_offset + OFFSET;
01835
01836
01837
01838 #if 0
01839 int lines_min = (MINLINES >= 1) ? MINLINES :
01840 (chip == UVES_CHIP_REDU) ? 1000 : 2000;
01841 int lines_max = (MAXLINES >= 1) ? MAXLINES :
01842 (chip == UVES_CHIP_REDU) ? 1400 : 2400;
01843 #else
01844
01845 int lines_min = (MINLINES >= 1) ? MINLINES :
01846 (chip == UVES_CHIP_REDU) ? 1000 : 1100;
01847 int lines_max = (MAXLINES >= 1) ? MAXLINES :
01848 (chip == UVES_CHIP_REDU) ? 1400 : 1600;
01849 #endif
01850
01851 assure( lines_min <= lines_max , CPL_ERROR_ILLEGAL_INPUT,
01852 "Minimum and maximum number of requested line "
01853 "detections don't make sense (min = %d; max = %d)",
01854 lines_min, lines_max);
01855
01856 if (NWINDOWS > 1) {
01857 uves_msg("Processing window %d of %d", window, NWINDOWS);
01858 }
01859
01860 passure( *(uves_lt_get_disprel(linetable, window, trace_number))
01861 == NULL, "%d %d", window, trace_number);
01862 passure( *(uves_lt_get_absord (linetable, window, trace_number))
01863 == NULL, "%d %d", window, trace_number);
01864
01865
01866 if (weights != NULL) {
01867
01868 offset = 0;
01869 }
01870
01871
01872 *uves_lt_get_absord(linetable, window, trace_number) =
01873 uves_polynomial_duplicate(absolute_order);
01874
01875
01876 check( *uves_lt_get_table(linetable, window, trace_number) =
01877 uves_wavecal_process_window(
01878
01879 arclamp[raw_index],
01880 arclamp_noise,
01881 rotated_header[raw_index],
01882
01883 ordertable, order_locations,
01884 master_flat != NULL,
01885 weights,
01886
01887 guess,
01888 line_refer,
01889 flames,
01890 tab_in_out_oshift,
01891 tab_in_out_yshift,
01892
01893 chip, biny, trace_number, window,NWINDOWS,
01894
01895 DEBUG,
01896
01897 offset, slitlength, parameters, recipe_id,
01898
01899 RANGE, lines_min, lines_max, CENTERING_METHOD,
01900
01901 SHIFT_MAX, SHIFT_STEP, SHIFT_TOLERANCE,
01902
01903 ALPHA, MAXERROR, DEGREE,
01904
01905 TOLERANCE, KAPPA,
01906 corvel_frm,qclog,
01907
01908 uves_lt_get_disprel(linetable, window, trace_number),
01909 uves_lt_get_absord (linetable, window, trace_number),
01910 uves_lt_get_firstabs(linetable, window, trace_number),
01911 uves_lt_get_lastabs(linetable, window, trace_number)),
01912 "Wavelength calibration failed");
01913
01914
01915
01916
01917 if(drs_cvel_sw) {
01918
01919
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 if (flames ||
01948 (window == 2 && trace_number == 0)||
01949 (window == 1 && NWINDOWS == 1)) {
01950
01951 check( uves_wavecal_qclog(
01952 *uves_lt_get_table(
01953 linetable,
01954 window,
01955 trace_number),
01956 *uves_lt_get_firstabs(linetable, window, trace_number),
01957 *uves_lt_get_lastabs(linetable, window, trace_number),
01958 arclamp[raw_index],
01959 arclamp_header[raw_index],
01960 flames,
01961 trace_number, trace_enabled, trace_offset,
01962 chip,
01963 qclog[0]),
01964 "Could not calculate resolution QC parameters");
01965
01966 if (line_intmon != NULL) {
01967 check( uves_wavecal_qclog_intmon(
01968 *uves_lt_get_table(
01969 linetable,
01970 window,
01971 trace_number),
01972 line_intmon,
01973 arclamp_header[raw_index],
01974 flames, trace_number,
01975 chip,
01976 qclog[1]),
01977 "Could not calculate int.mon. QC parameters");
01978 }
01979 else
01980 {
01981
01982 uves_qclog_delete(&qclog[1]);
01983 }
01984 }
01985
01986
01987
01988
01989
01990 }
01991
01992 }
01993 else
01994 {
01995 uves_msg("Skipping trace number %d", trace_number);
01996 }
01997 }
01998
01999
02000
02001
02002
02003 cpl_free(product_filename);
02004 check( product_filename = uves_line_table_filename(chip), "Error getting filename");
02005 current_linetable_extension = 1;
02006
02007
02008 for(tracerow = 0; tracerow < cpl_table_get_nrow(traces); tracerow++)
02009 {
02010 int trace_number;
02011 double trace_offset;
02012 int trace_enabled;
02013
02014 trace_offset = cpl_table_get_double(traces, "Offset" , tracerow, NULL);
02015 trace_number = cpl_table_get_int (traces, "TraceID" , tracerow, NULL);
02016 trace_enabled = cpl_table_get_int (traces, "Tracemask" , tracerow, NULL);
02017
02018 if (trace_enabled != 0)
02019 {
02020 int window;
02021
02022
02023 for (window = 1; window <= NWINDOWS; window ++)
02024 {
02025 double window_offset =
02026 slitlength * (window - (NWINDOWS+1) / 2.0);
02027
02028 double offset = trace_offset + window_offset + OFFSET;
02029
02030
02031 uves_free_propertylist(&table_header);
02032 table_header = uves_propertylist_new();
02033 check( uves_pfits_set_traceid ( table_header, trace_number),
02034 "Error writing trace ID to product header");
02035 check( uves_pfits_set_offset ( table_header, offset),
02036 "Error writing trace offset to product header");
02037 check( uves_pfits_set_windownumber( table_header, window),
02038 "Error writing window number to product header");
02039 check( uves_pfits_set_firstabsorder( table_header,
02040 *uves_lt_get_firstabs(
02041 linetable,
02042 window,
02043 trace_number)),
02044 "Error writing order number to product header");
02045 check( uves_pfits_set_lastabsorder( table_header,
02046 *uves_lt_get_lastabs(
02047 linetable,
02048 window,
02049 trace_number)),
02050 "Error writing order number to product header");
02051
02052
02053
02054 if (current_linetable_extension == 1) {
02055 uves_free_propertylist(&primary_header);
02056 primary_header = uves_propertylist_new();
02057
02058 if (flames)
02059 {
02060 char values[80];
02061
02062
02063
02064 check_nomsg( uves_flames_pfits_set_ccfposmax(
02065 primary_header, 0.0) );
02066
02067
02068
02069 uves_propertylist_append_string(primary_header,
02070 "HISTORY",
02071 "'FIBREMASK','I*4'");
02072
02073 {
02074 int i;
02075 for (i = 0; i < N_FIBRES_MAX; i++) {
02076 snprintf(values, 80, "%1.1d ",
02077 cpl_table_get_int(traces,"Tracemask",
02078 i,NULL));
02079 uves_propertylist_append_string(primary_header,
02080 "HISTORY", values);
02081 uves_msg_debug("value=%d",
02082 cpl_table_get_int(traces,
02083 "Tracemask",
02084 i,NULL));
02085 }
02086 }
02087 uves_propertylist_append_string(primary_header,
02088 "HISTORY", " ");
02089
02090
02091
02092 double pixelsize;
02093 double wavestep;
02094
02095 check( pixelsize =
02096 cpl_table_get_column_mean(
02097 *uves_lt_get_table(
02098 linetable,
02099 window,
02100 trace_number),
02101 LINETAB_PIXELSIZE),
02102 "Error reading mean pixelsize");
02103 uves_msg_warning("Average pixelsize = %f w.l.u.",
02104 pixelsize);
02105
02106 wavestep = pixelsize*2.0/3;
02107
02108 uves_propertylist_append_string(primary_header,
02109 "HISTORY",
02110 "'PIXEL','R*4'");
02111 snprintf(values,80,"%14.7g %14.7g",pixelsize,pixelsize);
02112 uves_propertylist_append_string(primary_header,
02113 "HISTORY", values);
02114 uves_propertylist_append_string(primary_header,
02115 "HISTORY", " ");
02116
02117
02118
02119 }
02120
02121 uves_msg("Creating line table '%s'", product_filename);
02122 check( uves_frameset_insert(
02123 frames,
02124 *uves_lt_get_table(
02125 linetable,
02126 window,
02127 trace_number),
02128 CPL_FRAME_GROUP_PRODUCT,
02129 CPL_FRAME_TYPE_TABLE,
02130 CPL_FRAME_LEVEL_INTERMEDIATE,
02131 product_filename,
02132 UVES_LINE_TABLE(flames, chip),
02133 arclamp_header[raw_index],
02134 primary_header,
02135 table_header,
02136 parameters,
02137 recipe_id,
02138 PACKAGE "/" PACKAGE_VERSION,
02139 qclog, starttime, true, 0),
02140 "Could not add line table '%s' (%s) to frameset",
02141 product_filename, UVES_LINE_TABLE(flames, chip));
02142
02143 uves_msg("Line table '%s' (%s) added to frameset",
02144 product_filename, UVES_LINE_TABLE(flames, chip));
02145 }
02146 else
02147
02148 {
02149 check( uves_table_save(
02150 *uves_lt_get_table(linetable,
02151 window,
02152 trace_number),
02153 NULL,
02154
02155
02156 table_header,
02157 product_filename,
02158
02159 CPL_IO_EXTEND),
02160
02161 "Error appending table to file '%s'",
02162 product_filename);
02163 }
02164 current_linetable_extension += 1;
02165
02166
02167 check( uves_save_polynomial(*uves_lt_get_disprel(
02168 linetable,
02169 window,
02170 trace_number),
02171 product_filename,
02172 table_header),
02173 "Could not write polynomial to file '%s'",
02174 product_filename);
02175 current_linetable_extension += 1;
02176
02177
02178 check( uves_save_polynomial(*uves_lt_get_absord(
02179 linetable,
02180 window,
02181 trace_number),
02182 product_filename,
02183 table_header),
02184 "Could not write polynomial to file '%s'",
02185 product_filename);
02186 current_linetable_extension += 1;
02187
02188 uves_msg("Line table for trace %d, window #%d "
02189 "saved to extensions %d-%d of '%s'",
02190 trace_number, window,
02191 current_linetable_extension - 3,
02192 current_linetable_extension - 1,
02193 product_filename);
02194
02195 }
02196 }
02197 }
02198
02199 if(strcmp(PROCESS_CHIP,"REDL") == 0) {
02200 chip = uves_chip_get_next(chip);
02201 }
02202
02203
02204 }
02205
02206 cleanup:
02207
02208
02209 uves_free_image(&arclamp[0]);
02210 uves_free_image(&arclamp[1]);
02211 uves_free_image(&arclamp_noise);
02212 uves_free_image(&absorder_image);
02213 uves_free_propertylist(&arclamp_header[0]);
02214 uves_free_propertylist(&arclamp_header[1]);
02215 uves_free_propertylist(&rotated_header[0]);
02216 uves_free_propertylist(&rotated_header[1]);
02217
02218
02219 uves_free_table(&ordertable);
02220 uves_free_propertylist(&ordertable_header);
02221 uves_free_table(&corvel);
02222 uves_free_propertylist(&corvel_header);
02223 uves_polynomial_delete(&order_locations);
02224 uves_polynomial_delete(&absolute_order);
02225 uves_free_table(&traces);
02226
02227
02228 uves_free_image(&master_bias);
02229 uves_free_propertylist(&master_bias_header);
02230 uves_free_image(&master_flat);
02231 uves_free_image(&mflat_noise);
02232 uves_free_propertylist(&master_flat_header);
02233 uves_free_image(&weights);
02234
02235
02236
02237
02238
02239
02240
02241 uves_free_table(&guess);
02242
02243 uves_free_table(&line_refer);
02244 uves_free_table(&line_intmon);
02245
02246
02247
02248 uves_lt_delete(&linetable);
02249 uves_free_propertylist(&primary_header);
02250 uves_free_propertylist(&table_header);
02251 uves_qclog_delete(&qclog[0]);
02252 uves_qclog_delete(&qclog[1]);
02253
02254 cpl_free(product_filename);
02255 cpl_free(temp);
02256
02257 return;
02258 }
02259
02260
02273 static void uves_wavecal_qclog(const cpl_table* linetable,
02274 int firstabs,
02275 int lastabs,
02276 const cpl_image *arclamp,
02277 const uves_propertylist* raw_header,
02278 bool flames,
02279 int trace_number,
02280 int fibre_mask,
02281 double offset,
02282 enum uves_chip chip,
02283 cpl_table* qclog)
02284 {
02285
02286 const char *qc_fib_drsno_name= uves_qclog_get_qc_name("DRSNO", flames, trace_number);
02287 const char *qc_fib_seq_name = uves_qclog_get_qc_name("SEQ", flames, trace_number);
02288 const char *qc_fib_pos_name = uves_qclog_get_qc_name("POS", flames, trace_number);
02289 const char *qc_fib_msk_name = uves_qclog_get_qc_name("MSK", flames, trace_number);
02290 const char *qc_fwhmavg_name = uves_qclog_get_qc_name("FWHMAVG", flames, trace_number);
02291 const char *qc_fwhmrms_name = uves_qclog_get_qc_name("FWHMRMS", flames, trace_number);
02292 const char *qc_fwhmmed_name = uves_qclog_get_qc_name("FWHMMED", flames, trace_number);
02293 const char *qc_resolavg_name = uves_qclog_get_qc_name("RESOLAVG", flames, trace_number);
02294 const char *qc_resolrms_name = uves_qclog_get_qc_name("RESOLRMS", flames, trace_number);
02295 const char *qc_resolmed_name = uves_qclog_get_qc_name("RESOLMED", flames, trace_number);
02296 const char *qc_wlenmin_name = uves_qclog_get_qc_name("WLENMIN", flames, trace_number);
02297 const char *qc_wlenmax_name = uves_qclog_get_qc_name("WLENMAX", flames, trace_number);
02298 const char *qc_ordmin_name = uves_qclog_get_qc_name("ORDMIN", flames, trace_number);
02299 const char *qc_ordmax_name = uves_qclog_get_qc_name("ORDMAX", flames, trace_number);
02300 const char *qc_nlintot_name = uves_qclog_get_qc_name("NLINTOT", flames, trace_number);
02301 const char *qc_nlinsel_name = uves_qclog_get_qc_name("NLINSEL", flames, trace_number);
02302 const char *qc_nlinsol_name = uves_qclog_get_qc_name("NLINSOL", flames, trace_number);
02303 const char *qc_nlinres1_name = uves_qclog_get_qc_name("NLINRES1", flames, trace_number);
02304 const char *qc_lineresidavg_name =
02305 uves_qclog_get_qc_name("LINE RESIDAVG", flames, trace_number);
02306 const char *qc_lineresidrms_name =
02307 uves_qclog_get_qc_name("LINE RESIDRMS", flames, trace_number);
02308 char comment[80];
02309 cpl_table *selected = NULL;
02310
02311 char test_id[80];
02312 sprintf(test_id,"%sResolution-Test-Results",flames ? "Fibre-" : "");
02313
02314 check_nomsg(uves_qclog_add_string(qclog,
02315 "QC TEST1 ID",
02316 test_id,
02317 "Name of QC test",
02318 "%s"));
02319
02320 check_nomsg( uves_qclog_add_common_wave(raw_header, chip, qclog) );
02321
02322 if (flames)
02323 {
02324
02325 check_nomsg(uves_qclog_add_int(qclog,
02326 qc_fib_drsno_name,
02327 trace_number + 1,
02328 "DRS det. fibre seq. pos.",
02329 "%d"));
02330
02331
02332 check_nomsg(uves_qclog_add_int(qclog,
02333 qc_fib_seq_name,
02334 trace_number + 1,
02335 "det. fibre seq. no.",
02336 "%d"));
02337
02338 check_nomsg(uves_qclog_add_double(qclog,
02339 qc_fib_pos_name,
02340 offset,
02341 "det. fibre seq. rel. pos.",
02342 "%.4f"));
02343
02344 check_nomsg(uves_qclog_add_int(qclog,
02345 qc_fib_msk_name,
02346 fibre_mask,
02347 "DRS det. fibre mask value",
02348 "%d"));
02349
02350 {
02351
02352 double exptime;
02353
02354 check( exptime = uves_flames_pfits_get_dit(raw_header),
02355 "Error reading exposure time");
02356
02357 check_nomsg(uves_qclog_add_double(qclog,
02358 "QC FIB ABSTRANS",
02359 cpl_image_get_flux(arclamp) / exptime,
02360 "abs. trans. countrate",
02361 "%.4f"));
02362 }
02363 {
02364 int n_hpix;
02365 int x, y;
02366
02367 n_hpix = 0;
02368 for (y = 1; y <= cpl_image_get_size_y(arclamp); y++)
02369 for (x = 1; x <= cpl_image_get_size_x(arclamp); x++)
02370 {
02371 int pis_rejected;
02372 int value = cpl_image_get(arclamp, x, y, &pis_rejected);
02373
02374 if (!pis_rejected &&
02375 (value < DRS_PTHRES_MIN || value > DRS_PTHRES_MAX))
02376 {
02377 n_hpix += 1;
02378 }
02379 }
02380
02381 check_nomsg(uves_qclog_add_int(qclog,
02382 "QC NHOTPIX",
02383 n_hpix,
02384 "no. of hot pixels",
02385 "%d"));
02386
02387 }
02388
02389 {
02390 int plate_id;
02391 check( plate_id = uves_flames_pfits_get_plateid(raw_header),
02392 "Error reading plate ID");
02393 check_nomsg(uves_qclog_add_int(qclog,
02394 "QC PLATENO",
02395 plate_id,
02396 "Plate Id.",
02397 "%d"));
02398 }
02399
02400 }
02401
02402
02403 selected = uves_extract_table_rows(linetable, "NLinSol", CPL_NOT_EQUAL_TO, 0);
02404
02405 sprintf(comment,"average FWHM in X of lines selected on trace %d",trace_number+1);
02406 check_nomsg(uves_qclog_add_double(qclog,
02407 qc_fwhmavg_name,
02408 cpl_table_get_column_mean(selected,"Xwidth")*TWOSQRT2LN2,
02409 comment,
02410 "%.2f"));
02411
02412 sprintf(comment,"stdev FWHM in X of lines selected on trace %d",trace_number+1);
02413 check_nomsg(uves_qclog_add_double(qclog,
02414 qc_fwhmrms_name,
02415 cpl_table_get_column_stdev(selected,"Xwidth")*TWOSQRT2LN2,
02416 comment,
02417 "%.4f"));
02418
02419 sprintf(comment,"median FWHM in X of lines selected on trace %d",trace_number+1);
02420 check_nomsg(uves_qclog_add_double(qclog,
02421 qc_fwhmmed_name,
02422 cpl_table_get_column_median(selected,"Xwidth")*TWOSQRT2LN2,
02423 comment,
02424 "%.4f"));
02425
02426 sprintf(comment,"mean resol power of lines selected on trace %d",trace_number+1);
02427 check_nomsg(uves_qclog_add_double(qclog,
02428 qc_resolavg_name,
02429 cpl_table_get_column_mean(selected,"Resol"),
02430 comment,
02431 "%.4f"));
02432
02433 sprintf(comment,"stdev resol power of lines selected on trace %d",trace_number+1);
02434 check_nomsg(uves_qclog_add_double(qclog,
02435 qc_resolrms_name,
02436 cpl_table_get_column_stdev(selected,"Resol"),
02437 comment,
02438 "%.4f"));
02439
02440 sprintf(comment,"median resol power of lines selected on trace %d",trace_number+1);
02441 check_nomsg(uves_qclog_add_double(qclog,
02442 qc_resolmed_name,
02443 cpl_table_get_column_median(selected,"Resol"),
02444 comment,
02445 "%.4f"));
02446
02447
02448 sprintf(comment,"mean resid of line pos to fit on trace %d",trace_number+1);
02449 check_nomsg(uves_qclog_add_double(qclog,
02450 qc_lineresidavg_name,
02451 cpl_table_get_column_mean(selected, LINETAB_RESIDUAL)*100,
02452 comment,
02453 "%.4f"));
02454
02455 sprintf(comment,"sigma resid of line pos to fit on trace %d",trace_number+1);
02456 check_nomsg(uves_qclog_add_double(qclog,
02457 qc_lineresidrms_name,
02458 cpl_table_get_column_stdev(selected, LINETAB_RESIDUAL)*100,
02459 comment,
02460 "%.4f"));
02461
02462
02463 sprintf(comment,"minimum wavelength on trace %d",trace_number+1);
02464 check_nomsg(uves_qclog_add_double(qclog,
02465 qc_wlenmin_name,
02466 cpl_table_get_column_min(linetable,LINETAB_LAMBDAC)/10.0,
02467 comment,
02468 "%.4f"));
02469
02470 sprintf(comment,"maximum wavelength on trace %d",trace_number+1);
02471 check_nomsg(uves_qclog_add_double(qclog,
02472 qc_wlenmax_name,
02473 cpl_table_get_column_max(linetable,LINETAB_LAMBDAC)/10.0,
02474 comment,
02475 "%.4f"));
02476 sprintf(comment,"minimum order number detected on trace %d",trace_number+1);
02477 check_nomsg(uves_qclog_add_int(qclog,
02478 qc_ordmin_name,
02479 uves_min_int(firstabs, lastabs),
02480 comment,
02481 "%d"));
02482
02483 sprintf(comment,"maximum order number detected on trace %d",trace_number+1);
02484 check_nomsg(uves_qclog_add_int(qclog,
02485 qc_ordmax_name,
02486 uves_max_int(firstabs, lastabs),
02487 comment,
02488 "%d"));
02489
02490 sprintf(comment,"No of lines found on trace %d",trace_number+1);
02491 check_nomsg(uves_qclog_add_int(qclog,
02492 qc_nlintot_name,
02493 cpl_table_get_nrow(linetable),
02494 comment,
02495 "%d"));
02496
02497 sprintf(comment,"No of lines selected on trace %d",trace_number+1);
02498 check_nomsg(uves_qclog_add_int(qclog,
02499 qc_nlinsel_name,
02500 cpl_table_get_nrow(linetable) -
02501 cpl_table_count_invalid(linetable, "Ident"),
02502 comment,
02503 "%d"));
02504
02505 sprintf(comment,"No of lines used on trace %d",trace_number+1);
02506 check_nomsg(uves_qclog_add_int(qclog,
02507 qc_nlinsol_name,
02508 cpl_table_get_nrow(selected),
02509 comment,
02510 "%d"));
02511
02512 uves_free_table(&selected);
02513 selected = cpl_table_duplicate(linetable);
02514 assure_mem( selected );
02515
02516
02517
02518 check_nomsg( uves_erase_invalid_table_rows(selected, "Ident") );
02519 check_nomsg( uves_erase_table_rows(selected, LINETAB_RESIDUAL,
02520 CPL_NOT_LESS_THAN,
02521 1.0) );
02522
02523 sprintf(comment,"No of lines with residuals < 0.1 nm on trace %d",trace_number+1);
02524 check_nomsg(uves_qclog_add_int(qclog,
02525 qc_nlinres1_name,
02526 cpl_table_get_nrow(selected),
02527 comment,
02528 "%d"));
02529
02530
02531 cleanup:
02532
02533 uves_free_string_const(&qc_fib_drsno_name);
02534 uves_free_string_const(&qc_fib_seq_name);
02535 uves_free_string_const(&qc_fib_pos_name);
02536 uves_free_string_const(&qc_fib_msk_name);
02537 uves_free_string_const(&qc_fwhmavg_name);
02538 uves_free_string_const(&qc_fwhmrms_name);
02539 uves_free_string_const(&qc_fwhmmed_name);
02540
02541 uves_free_string_const(&qc_resolavg_name);
02542 uves_free_string_const(&qc_resolrms_name);
02543 uves_free_string_const(&qc_resolmed_name);
02544 uves_free_string_const(&qc_wlenmin_name);
02545 uves_free_string_const(&qc_wlenmax_name);
02546 uves_free_string_const(&qc_ordmin_name);
02547 uves_free_string_const(&qc_ordmax_name);
02548 uves_free_string_const(&qc_nlintot_name);
02549 uves_free_string_const(&qc_nlinsel_name);
02550 uves_free_string_const(&qc_nlinsol_name);
02551 uves_free_string_const(&qc_nlinres1_name);
02552 uves_free_string_const(&qc_lineresidavg_name);
02553 uves_free_string_const(&qc_lineresidrms_name);
02554
02555 uves_free_table(&selected);
02556
02557 return;
02558
02559 }
02560
02569 static void uves_wavecal_qclog_intmon(cpl_table* table,
02570 const cpl_table *line_intmon,
02571 const uves_propertylist* raw_header,
02572 bool flames,
02573 int fibre,
02574 enum uves_chip chip,
02575 cpl_table* qclog)
02576 {
02577 const char *qc_intavg_name = NULL;
02578 const char *qc_nlinint_name = NULL;
02579
02580 cpl_table *temp = NULL;
02581
02582 check_nomsg(uves_qclog_add_string(qclog,
02583 "QC TEST2 ID",
02584 flames ? "Fibre-Line-Intensity-Test-Results"
02585 : "Line-Intensity-Test-Results",
02586 "Name of QC test",
02587 "%s"));
02588
02589 check_nomsg( uves_qclog_add_common_wave(raw_header,
02590 chip, qclog) );
02591
02592 {
02593 double tolerance = 0.001;
02594
02595
02596
02597
02598
02599
02600 double exptime;
02601
02602 int N_bright = cpl_table_get_nrow(line_intmon);
02603 int i;
02604
02605 check( exptime = uves_pfits_get_exptime(raw_header),
02606 "Could not get exposure time");
02607
02608 cpl_table_new_column(table, "Intensity", CPL_TYPE_DOUBLE);
02609 for (i = 0; i < cpl_table_get_nrow(table); i++)
02610 {
02611 int is_null;
02612 double ident = cpl_table_get_double(table, "Ident", i, &is_null);
02613
02614 if (!is_null)
02615 {
02616 int bright_index = uves_wavecal_find_nearest(
02617 line_intmon, ident, 0, N_bright-1);
02618
02619 double bright = cpl_table_get_double(
02620 line_intmon, "Wave", bright_index, NULL);
02621
02622 if (fabs(bright - ident) < tolerance)
02623 {
02624 double peak = cpl_table_get_double(table, "Peak", i, NULL);
02625 double pixelsize =
02626 fabs(cpl_table_get_double(table, LINETAB_PIXELSIZE, i, NULL));
02627
02628 double lambda_fwhm = cpl_table_get_double(table, "Xwidth", i, NULL)
02629 * TWOSQRT2LN2 * pixelsize;
02630
02631
02632 double intensity = peak * lambda_fwhm / exptime;
02633
02634
02635 cpl_table_set_double(table, "Intensity", i, intensity);
02636 }
02637 else
02638 {
02639 cpl_table_set_invalid(table, "Intensity", i);
02640 }
02641 }
02642 else
02643 {
02644 cpl_table_set_invalid(table, "Intensity", i);
02645 }
02646 }
02647 }
02648
02649 uves_free_table(&temp);
02650 temp = cpl_table_duplicate(table);
02651 uves_erase_invalid_table_rows(temp, "Intensity");
02652
02653 {
02654 double mean;
02655 if (cpl_table_get_nrow(temp) == 0)
02656 {
02657 uves_msg_warning("No bright lines found!");
02658 mean = 0;
02659 }
02660 else
02661 {
02662 mean = cpl_table_get_column_mean(temp, "Intensity");
02663 }
02664
02665 if (flames)
02666 {
02667 qc_intavg_name = uves_sprintf("QC FIB%d INTAVG", fibre+1);
02668 qc_nlinint_name = uves_sprintf("QC FIB%d NLININT", fibre+1);
02669 }
02670 else
02671 {
02672 qc_intavg_name = uves_sprintf("QC INTAVG");
02673 qc_nlinint_name = uves_sprintf("QC NLININT");
02674 }
02675
02676 check_nomsg(uves_qclog_add_double(qclog,
02677 qc_intavg_name,
02678 mean,
02679 "average intensity of line list",
02680 "%.4f"));
02681
02682 check_nomsg(uves_qclog_add_int(qclog,
02683 qc_nlinint_name,
02684 cpl_table_get_nrow(temp),
02685 "No of lines to measure INTAVG",
02686 "%d"));
02687 }
02688
02689 cleanup:
02690 uves_free_string_const(&qc_intavg_name);
02691 uves_free_string_const(&qc_nlinint_name);
02692 uves_free_table(&temp);
02693 return;
02694 }
02695
02696