41 #include <uves_wavecal_body.h>
47 #include <uves_extract.h>
48 #include <uves_flatfield.h>
49 #include <uves_wavecal_search.h>
50 #include <uves_wavecal_firstsolution.h>
51 #include <uves_wavecal_identify.h>
52 #include <uves_rebin.h>
53 #include <uves_merge.h>
56 #include <uves_wavecal_utils.h>
57 #include <uves_utils.h>
58 #include <uves_utils_wrappers.h>
59 #include <uves_plot.h>
60 #include <uves_parameters.h>
62 #include <uves_pfits.h>
63 #include <uves_qclog.h>
64 #include <uves_recipe.h>
65 #include <uves_error.h>
66 #include <flames_reduce_vcorrel.h>
77 #define DRS_PTHRES_MAX 55000
78 #define DRS_PTHRES_MIN -20
79 #define DRS_CVEL_MIN -6.
80 #define DRS_CVEL_MAX +6.
81 #define N_FIBRES_MAX 9
85 static void uves_wavecal_qclog(
const cpl_table* table,
88 const cpl_image *arclamp,
97 static void uves_wavecal_qclog_intmon(cpl_table* table,
98 const cpl_table *line_intmon,
109 const char *
const uves_wavecal_desc_short =
"Performs the wavelength calibration";
111 const char *
const uves_wavecal_desc =
112 "The recipe performs a wavelength calibration for each extraction window.\n"
113 "Conceptually, each chip contains a number of order lines, each of which\n"
114 "contains a number of fibre traces, each of which contains a number of\n"
115 "extraction windows. For UVES data, there is only one trace per order and\n"
116 "three extraction windows (sky, object, sky). For FLAMES/UVES data there\n"
117 "are multiple traces per order but only one extraction window per trace.\n"
118 "The number of traces is defined in the order table while the geometry of\n"
119 "the extraction windows is specified by recipe parameters (see below).\n"
121 "Expected input for this recipe is an arc lamp frame, ARC_LAMP_xxx or\n"
122 "ECH_ARC_LAMP_xxx (where xxx=BLUE, RED), order table(s) for each chip,\n"
123 "ORDER_TABLE_xxxx (where xxxx=BLUE, REDL, REDU), 'guess' line table(s)\n"
124 "for each chip, LINE_TABLE_xxxx, a wavelength catalogue table, \n"
125 "LINE_REFER_TABLE, and optionally a wavelength table of bright lines,\n"
126 "LINE_INTMON_TABLE, used only for computing Quality Control parameters.\n"
128 "The output line table(s), LINE_TABLE_xxxx, contains the columns\n"
129 "X : Horizontal position (from Gaussian fit) of detected line\n"
130 "dX : Uncertainty (one sigma) of X\n"
131 "Ynew : Vertical position of detected line\n"
132 "XWidth : Width (in pixels) of detected line from Gaussian fit\n"
133 "Peak : Intensity of detected line\n"
134 "Background : Fitted background (ADU) of detected line\n"
135 "Slope : Linear background slope (ADU/pixel) of detected line\n"
136 " from Gaussian fit\n"
137 "Intensity : Intensity of detected line scaled to unit exposure\n"
138 " time. (This column only present if a LINE_INTMON_TABLE\n"
140 "Order : Absolute order number of detected line\n"
141 "Y : Relative order number of detected line\n"
142 " (it's not a very descriptive column name)\n"
143 "WaveC : Wavelength of this line (computed using the resulting\n"
144 " dispersion relation)\n"
145 "dLambdaC : Uncertainty (one sigma) of 'WaveC'.\n"
146 "Pixel : The width in w.l.u. of a pixel (computed locally).\n"
147 "Residual : Residual (in w.l.u.) of this line\n"
148 "Residual_pix : Residual (in pixels) of this line\n"
149 "Lambda_candidate : Nearest line in catalogue\n"
150 "dLambda_cat_sq : Squared distance to nearest catalogue line\n"
151 "dLambda_nn_sq : Squared distance to nearest neighbour multiplied by ALPHA\n"
152 "Ident : The wavelength associated with this emission line,\n"
153 " or invalid if this line was not identified\n"
154 "dIdent : Uncertainty of catalogue wavelength\n"
155 "Select : 1 if the line was identified, 0 otherwise\n"
156 "NLinSol : 1 if the line was identified and accepted for the\n"
157 " polynomial fit, 0 otherwise\n"
158 "Intensity : Intensity of detected line scaled to unit exposure\n"
159 " time. (This column is present only if a LINE_INTMON_TABLE\n"
162 "The 2nd table extension contains the dispersion relation (a 2d polynomial).\n"
163 "The 3rd table extension contains the map from (pixel, pixel)-space to\n"
164 " physical order numbers (used internally by the calibration recipe; \n"
165 "another 2d polynomial).\n"
167 "If there is more than one extraction window, the results of each calibration\n"
168 "is stored in subsequent table extensions of the same FITS file. For \n"
169 "example, extensions 4, 5 and 6 would contain the resulting line table \n"
170 "(and its two associated polynomials) for the second extraction window. \n"
171 "The results for the calibration of the n'th extraction window is stored \n"
172 "in extensions (3*n - 2) to 3*n.\n";
189 uves_wavecal_define_parameters_body(cpl_parameterlist *parameters,
190 const char *recipe_id,
double slit)
192 const char *subcontext;
198 if (uves_define_global_parameters(parameters) != CPL_ERROR_NONE)
210 uves_par_new_range(
"nwindows",
212 "Number of extraction windows per trace. "
213 "The windows will be aligned (i.e. no overlap "
214 "and no spacing between adjacent windows). "
215 "Unless an offset is specified, the middle "
216 "window(s) is centered on the trace",
217 strcmp(recipe_id,
"flames_cal_wavecal") == 0 ?
222 uves_par_new_range(
"length",
224 "Length (in pixels) of each extraction window. "
225 "This parameter is also equal to the seperation of "
226 "adjacent window centers, causing the extraction "
227 "windows to always be aligned. The parameter is "
228 "automatically adjusted according to the binning "
229 "of the input raw frame. If negative, the extraction "
230 "window length is determined automatically "
231 "to cover the full slit",
232 slit, -2.0, DBL_MAX);
235 uves_par_new_range(
"offset",
237 "A global offset (in pixels) of all extraction windows",
241 if (uves_propagate_parameters_step(UVES_EXTRACT_ID, parameters,
242 recipe_id, NULL) != 0)
261 const char *profile =
"constant";
264 if (uves_set_parameter_default(parameters,
265 recipe_id, UVES_EXTRACT_ID
".profile",
266 CPL_TYPE_STRING, &profile)
274 if (uves_set_parameter_default(parameters,
275 recipe_id, UVES_EXTRACT_ID
".kappa",
276 CPL_TYPE_DOUBLE, &kappa)
284 const char *method =
"average";
286 if (uves_set_parameter_default(parameters,
287 recipe_id, UVES_EXTRACT_ID
".method",
288 CPL_TYPE_STRING, &method)
301 subcontext =
"search";
304 uves_par_new_range(
"range",
306 "Width (pix) of search window is 2*range + 1. "
307 "This parameter is automatically adjusted "
308 "according to binning.",
312 uves_par_new_range(
"minlines",
314 "Minimum number of lines to detect. If zero, "
315 "the default value (1100 for BLUE/REDL chips; "
316 "1000 for REDU chip) is used.",
320 uves_par_new_range(
"maxlines",
322 "Maximum number of lines to detect. If zero, "
323 "the default value (1600 for BLUE/REDL chip; "
324 "1400 for REDU chip) is used.",
345 subcontext =
"first";
348 uves_par_new_range(
"shiftmax",
350 "The maximum shift (pix) in either direction compared to "
351 "guess solution. This parameter is automatically "
352 "corrected for binning",
356 uves_par_new_range(
"shiftstep",
358 "The step size (pix) used when searching "
359 "for the optimum shift. This parameter is "
360 "automatically corrected for binning",
364 uves_par_new_range(
"shifttoler",
366 "Tolerance (pix) when matching shifted lines. "
367 "This parameter is not adjusted according to binning",
375 subcontext =
"identify";
378 uves_par_new_range(
"alpha",
380 "The parameter that controls the distance to the "
381 "nearest neighbours",
385 uves_par_new_range(
"maxerror",
387 "This parameter controls the graceful exit of "
388 "the identification loop. If the RMS of the "
389 "global fit exceeds this value (pix) the "
394 uves_par_new_range(
"degree",
396 "Degrees of the global 2d dispersion polynomial. If "
397 "a negative number is specified, the polynomial "
398 "degrees are automatically selected by starting from "
399 "(1, 1) and inreasing the degrees as long as the RMS "
400 "residual decreases significantly",
408 subcontext =
"calibrate";
411 uves_par_new_value(
"tolerance",
413 "Tolerance of fit. If positive, the tolerance "
414 "is in pixel units. If negative, abs(tolerance) "
415 "is in wavelength units. Lines with residuals "
416 "worse than the tolerance are excluded from the "
417 "final fit. Unlike in previous versions, this "
418 "parameter is not corrected for CCD binning. "
419 "This rejection based on the absolute residual in "
420 "pixel can be effectively disabled by setting the "
421 "tolerance to a very large number (e.g. 9999). In "
422 "that case outliers will be rejected using only "
423 "kappa sigma clipping.",
430 uves_par_new_range(
"kappa",
432 "Lines with residuals more then kappa stdev "
433 "are rejected from the final fit",
439 if (uves_propagate_parameters_step(UVES_REBIN_ID, parameters,
440 recipe_id, NULL) != 0)
445 return (cpl_error_get_code() != CPL_ERROR_NONE);
521 uves_wavecal_process_window(
const cpl_image *arclamp,
522 const cpl_image *arclamp_noise,
524 const cpl_table *ordertable,
529 const cpl_table *guess,
530 const cpl_table *line_refer,
532 int tab_in_out_oshift,
533 double tab_in_out_yshift,
534 enum uves_chip chip,
int bin_disp,
535 int trace,
int window,
int NWINDOWS,
541 const cpl_parameterlist *parameters,
542 const char *recipe_id,
547 centering_method CENTERING_METHOD,
551 double SHIFT_TOLERANCE,
559 cpl_frame* corvel_frm,
560 cpl_table** flames_qclog,
564 int *first_absolute_order,
565 int *last_absolute_order)
567 cpl_table *linetable = NULL;
568 cpl_table *temp = NULL;
569 cpl_image *spectrum = NULL;
570 cpl_image *spectrum_noise = NULL;
571 cpl_image *debug_image = NULL;
573 int *relative_order = NULL;
577 cpl_image *rebinned = NULL;
579 cpl_image *rebinned_noise = NULL;
582 cpl_image *merged = NULL;
583 cpl_image *merged_noise = NULL;
585 cpl_table *info_tbl = NULL;
588 cpl_image *weights_opt = NULL;
589 cpl_table *cr_table = NULL;
590 cpl_image *cr_image = NULL;
591 cpl_table *order_trace = NULL;
593 merge_method m_method = flat_fielded ? MERGE_OPTIMAL : MERGE_SUM;
596 uves_free_table(&info_tbl);
603 (cpl_image *)arclamp_noise,
622 (weights != NULL) ? &weights : &weights_opt,
625 "Error extracting spectrum");
626 uves_free_table(&info_tbl);
631 "^ESO ", 0),
"error copying hierarch keys");
636 cpl_image_fill_rejected(spectrum, 0);
637 cpl_image_accept_all(spectrum);
638 cpl_image_fill_rejected(spectrum_noise, 1);
639 cpl_image_accept_all(spectrum_noise);
648 "Error copying hieararch keys");
650 check( uves_save_image_local(
"Extracted spectrum",
"spectrum",
651 spectrum, chip, trace, window, spectrum_header,
true),
652 "Error saving spectrum");
654 check( uves_save_image_local(
"Extracted spectrum noise",
"spectrum_noise",
655 spectrum_noise, chip, trace, window, spectrum_header,
true),
656 "Error saving spectrum");
660 debug_image = cpl_image_duplicate(arclamp);
671 bin_disp,trace,window,
673 "Line search failed");
681 cpl_free(relative_order);
682 check( initial_dispersion = uves_wavecal_firstsolution(linetable,
695 first_absolute_order,
696 last_absolute_order),
697 "Could not get first solution");
710 cpl_table_add_scalar(linetable,
"Y", tab_in_out_oshift);
711 cpl_table_add_scalar(linetable,
"Ynew", - tab_in_out_yshift - offset);
721 kappa,trace,window,flames_qclog[0]),
722 "Could not calibrate orders");
731 cpl_table_add_scalar(linetable,
"Ynew", + tab_in_out_yshift + offset);
737 if (flames || (trace == 0 && window == 2)|| (window == 1 && NWINDOWS == 1))
740 check(( cpl_table_duplicate_column(linetable,
"deltaX", linetable,
"Xwidth"),
741 cpl_table_multiply_scalar (linetable,
"deltaX", TWOSQRT2LN2)),
742 "Error creating FWHM column");
746 linetable,
"NLinSol", CPL_NOT_EQUAL_TO, 0) );
748 check( uves_plot_table(temp,
"Order", LINETAB_RESIDUAL,
"Residual of fit"),
751 check( uves_plot_table(temp,
"X",
"deltaX",
"line FWHM (mean = %.2f pixels)",
752 cpl_table_get_column_mean(linetable,
"deltaX")),
769 double lambda_start = 0;
774 bool threshold_to_positive =
true;
776 cpl_table_new_column(linetable,
"deltaLambda", CPL_TYPE_DOUBLE);
782 *dispersion_relation,
783 *first_absolute_order,
784 *last_absolute_order,
786 threshold_to_positive,
789 "Could not rebin noise of arc lamp spectrum");
791 threshold_to_positive =
false;
792 uves_free_propertylist(&rebinned_header);
797 *dispersion_relation,
798 *first_absolute_order,
799 *last_absolute_order,
801 threshold_to_positive,
804 "Could not rebin arc lamp spectrum");
809 check( uves_save_image_local(
"Rebinned spectrum",
810 "wxb", rebinned, chip,
811 trace, window, rebinned_header,
true),
812 "Error saving rebinned spectrum");
814 check( uves_save_image_local(
"Noise of rebinned spectrum",
815 "errwxb", rebinned_noise, chip,
816 trace, window, rebinned_header,
true),
817 "Error saving noise of rebinned spectrum");
828 "Could not merge arc lamp spectrum");
830 check( uves_plot_image_rows(merged, 1, 1, 1,
831 "Wavelength (arbitrary units)",
832 "Flux",
"Resampled arc lamp spectrum"),
838 check( uves_save_image_local(
"Rebinned, merged spectrum",
839 "merged", merged, chip,
840 trace, window, merged_header,
true),
841 "Error saving merged spectrum");
844 nbins = cpl_image_get_size_x(merged);
847 "Error reading resampling step size");
850 "Could not read start wavelength of merged spectrum");
855 if (flames && trace == 0 && corvel_frm != NULL)
897 const char* drs_base_name=NULL;
898 const char* prefid=NULL;
899 double ccf_posmax_zero_point=0;
900 double ccf_posmax_zero_point_iter0=0;
903 if(chip == UVES_CHIP_REDL) {
908 const char* name=NULL;
909 const char* file=NULL;
910 cpl_propertylist* plist=NULL;
911 double drs_cvel_min=0;
912 double drs_cvel_max=0;
915 check( uves_save_image_local(
"Rebinned spectrum",
916 "wxb", rebinned, chip,
917 trace, window, rebinned_header,
true),
918 "Error saving rebinned spectrum");
920 check( uves_save_image_local(
"Rebinned, merged spectrum",
921 "mwxb", merged, chip,
922 trace, window, merged_header,
true),
923 "Error saving merged spectrum");
926 check( file = uves_local_filename(
"wxb", chip, trace, window),
927 "Error getting filename");
930 name=uves_sprintf(
"wfxb_%s%s%4.4d%s",prefid,
"_raw",1,
".fits");
931 drs_base_name=uves_sprintf(
"fxb_%s",prefid);
933 cpl_image_save(rebinned,name, CPL_BPP_IEEE_FLOAT,plist,
937 name=uves_sprintf(
"mwfxb_%s%s%4.4d%s",prefid,
"_raw",1,
".fits");
938 cpl_image_save(merged,name, CPL_BPP_IEEE_FLOAT,plist,
941 cpl_propertylist_delete(plist);
944 int ord_max=(*first_absolute_order-*last_absolute_order)+1;
946 uves_msg(
"cvel max:%g %g",DRS_CVEL_MAX,DRS_CVEL_MIN);
947 drs_cvel_max =DRS_CVEL_MAX;
948 drs_cvel_min =DRS_CVEL_MIN;
959 &ccf_posmax_zero_point,
964 drs_cvel_max +=cvel_max;
965 drs_cvel_min +=cvel_max;
966 ccf_posmax_zero_point_iter0 =cvel_max;
967 uves_msg(
"cvel max:%g %g",drs_cvel_max,drs_cvel_min);
978 &ccf_posmax_zero_point,
983 drs_cvel_max +=cvel_max;
984 drs_cvel_min +=cvel_max;
985 ccf_posmax_zero_point =ccf_posmax_zero_point_iter0;
988 ccf_posmax_zero_point,
989 "CCF pos avg from ThAr calibration",
993 uves_msg(
"cvel max:%g min: %g zp: %g",
994 drs_cvel_max,drs_cvel_min,ccf_posmax_zero_point);
1003 for (i = 0; i < cpl_table_get_nrow(linetable); i++)
1005 double lambda = cpl_table_get_double(
1006 linetable, LINETAB_LAMBDAC, i, NULL);
1008 cpl_table_get_double(linetable,
"Xwidth" , i, NULL) *
1009 fabs(cpl_table_get_double(linetable, LINETAB_PIXELSIZE, i, NULL));
1014 uves_round_double((lambda - lambda_start) / wavestep);
1015 double width_bin = width / wavestep;
1018 int first_bin = uves_max_int( 1, uves_round_double(bin - 5*width_bin));
1019 int last_bin = uves_min_int(nbins, uves_round_double(bin + 5*width_bin));
1021 double my, sigma, norm, background;
1024 if (cpl_table_is_valid(linetable,
"Ident", i) && first_bin < last_bin)
1027 uves_fit_1d_image(merged,
1052 if (cpl_error_get_code() == CPL_ERROR_CONTINUE)
1056 "at lambda = %f wlu, bins = "
1057 "%d - %d, ignoring line",
1058 lambda, first_bin, last_bin);
1060 cpl_table_set_invalid(linetable,
"deltaLambda", i);
1065 assure(cpl_error_get_code() == CPL_ERROR_NONE,
1066 cpl_error_get_code(),
"Gaussian fitting failed");
1069 lambda_fwhm = TWOSQRT2LN2 * sigma * wavestep;
1071 cpl_table_set_double(linetable,
"deltaLambda",
1078 cpl_table_set_invalid(linetable,
"deltaLambda", i);
1084 check(( cpl_table_duplicate_column(linetable,
"Resol",
1085 linetable, LINETAB_LAMBDAC),
1086 cpl_table_divide_columns (linetable,
"Resol",
1088 "Error creating 'Resol' column");
1095 double resol_avg = 0;
1096 double resol_stdev = 0;
1097 double kappar = 10.0;
1098 nrows=cpl_table_get_nrow(linetable);
1099 ninvalid=cpl_table_count_invalid(linetable,
"Resol");
1100 assure(ninvalid < nrows,CPL_ERROR_ILLEGAL_INPUT,
1101 "No valid elements in Resol column. "
1102 "You must decrease parameter rebin.wavestep");
1103 check_nomsg(resol_avg=cpl_table_get_column_median(linetable,
"Resol"));
1104 check_nomsg(resol_stdev=cpl_table_get_column_stdev (linetable,
"Resol"));
1106 for (i = 0; i < cpl_table_get_nrow(linetable); i++)
1108 double r = cpl_table_get_double(linetable,
"Resol", i, NULL);
1109 if (r < resol_avg - kappar*resol_stdev ||
1110 r > resol_avg + kappar*resol_stdev)
1112 cpl_table_set_invalid(linetable,
"Resol", i);
1113 cpl_table_set_invalid(linetable,
"deltaLambda", i);
1123 check( uves_plot_table(linetable, LINETAB_LAMBDAC,
"Resol",
1124 "(l, l / dl)"),
"Plotting failed");
1128 uves_free_table(&temp);
1129 check( temp = cpl_table_duplicate(linetable),
1130 "Error copying line table");
1131 check( uves_erase_invalid_table_rows(temp,
"Ident"),
1132 "Error removing un-identified lines");
1133 check( uves_plot_table(temp,
"X",
"Ynew",
1134 "Line identifications"),
1136 uves_free_table(&temp);
1147 order_locations, guess,
1148 "Ident",
"Order", relative_order,
1151 12),
"Error drawing guess solution");
1155 line_refer,
"Wave", NULL, relative_order,
1156 uves_min_int(*first_absolute_order, *last_absolute_order),
1157 uves_max_int(*first_absolute_order, *last_absolute_order),
1159 8),
"Error drawing catalogue lines");
1163 line_refer,
"Wave", NULL, relative_order,
1164 uves_min_int(*first_absolute_order, *last_absolute_order),
1165 uves_max_int(*first_absolute_order, *last_absolute_order),
1167 16),
"Error drawing catalogue lines");
1171 order_locations, linetable,
1172 LINETAB_LAMBDAC,
"Order", relative_order,
1175 -16),
"Error drawing detected lines");
1178 uves_free_table(&temp);
1179 check(( temp = cpl_table_duplicate(linetable),
1181 uves_erase_invalid_table_rows(temp,
"Ident")),
1182 "Error duplicating table");
1185 temp, LINETAB_LAMBDAC,
"Order", relative_order,
1188 0),
"Error drawing detected lines");
1217 check( uves_save_image_local(
"Debug image",
"rawdebug",
1218 debug_image, chip, trace, window,
1219 rotated_header,
true),
1220 "Error saving spectrum");
1226 int count = cpl_table_get_nrow(linetable);
1228 check_nomsg( cpl_table_new_column(linetable,
"Fibre", CPL_TYPE_INT) );
1230 cpl_table_fill_column_window(linetable,
"Fibre",
1237 uves_free_table(&info_tbl);
1238 uves_free_table(&temp);
1239 uves_free_image(&weights_opt);
1240 uves_free_table(&cr_table);
1241 uves_free_image(&cr_image);
1242 uves_free_image(&spectrum);
1243 uves_free_image(&spectrum_noise);
1244 uves_free_image(&debug_image);
1245 uves_free_image(&rebinned);
1246 uves_free_image(&rebinned_noise);
1247 uves_free_image(&merged);
1248 uves_free_image(&merged_noise);
1249 uves_free_propertylist(&spectrum_header);
1250 uves_free_propertylist(&rebinned_header);
1251 uves_free_propertylist(&merged_header);
1252 cpl_free(relative_order);
1254 uves_free_table(&order_trace);
1288 uves_wavecal_exe_body(cpl_frameset *frames,
1290 const char *recipe_id,
1291 const cpl_parameterlist *parameters,
1292 const char *starttime)
1304 double SLITLENGTH_par;
1310 centering_method CENTERING_METHOD;
1315 double SHIFT_TOLERANCE;
1326 cpl_image *arclamp[2] = {NULL, NULL};
1327 cpl_image *arclamp_noise = NULL;
1332 cpl_table *ordertable = NULL;
1335 cpl_table *traces = NULL;
1338 cpl_image *master_bias = NULL;
1342 cpl_image *master_flat = NULL;
1343 cpl_image *mflat_noise = NULL;
1347 cpl_image *weights = NULL;
1356 int* fibres_mask=NULL;
1357 double* fibres_pos=NULL;
1360 cpl_table *guess = NULL;
1364 cpl_table *corvel = NULL;
1365 cpl_frame *corvel_frm = NULL;
1369 cpl_table *line_refer = NULL;
1370 cpl_table *line_intmon = NULL;
1378 cpl_table *qclog[3] = {NULL, NULL, NULL};
1381 cpl_image *absorder_image = NULL;
1382 const char *arclamp_filename =
"";
1383 const char *line_refer_filename =
"";
1384 const char *line_intmon_filename =
"";
1385 char *product_filename = NULL;
1388 bool sim_cal =
false;
1389 enum uves_chip chip;
1392 bool drs_cvel_sw=
false;
1393 const char* PROCESS_CHIP=NULL;
1398 const char *centering_m =
"gaussian";
1399 const char *profile =
"";
1404 check( uves_get_parameter(parameters, NULL,
"uves",
"debug",
1405 CPL_TYPE_BOOL, &debug_mode),
"Could not read parameter");
1407 check( uves_get_parameter(parameters, NULL,
"uves",
"process_chip", CPL_TYPE_STRING, &PROCESS_CHIP),
1408 "Could not read parameter");
1412 check( uves_get_parameter(parameters, NULL, recipe_id,
"nwindows",
1413 CPL_TYPE_INT , &NWINDOWS ),
"Could not read parameter");
1414 check( uves_get_parameter(parameters, NULL, recipe_id,
"length",
1415 CPL_TYPE_DOUBLE, &SLITLENGTH_par),
"Could not read parameter");
1416 check( uves_get_parameter(parameters, NULL, recipe_id,
"offset",
1417 CPL_TYPE_DOUBLE, &OFFSET ),
"Could not read parameter");
1421 temp = uves_sprintf(
"%s.%s", recipe_id, UVES_EXTRACT_ID);
1423 "Could not read extraction method");
1425 check( uves_get_parameter(parameters, NULL, recipe_id, UVES_EXTRACT_ID
".profile",
1426 CPL_TYPE_STRING, &profile),
"Could not read parameter");
1428 assure( em == EXTRACT_LINEAR || em == EXTRACT_AVERAGE || em == EXTRACT_WEIGHTED ||
1429 (em == EXTRACT_OPTIMAL && strcmp(profile,
"constant") == 0),
1430 CPL_ERROR_UNSUPPORTED_MODE,
1431 "Only linear/average/weighted/optimal(constant profile) extraction "
1432 "methods are supported by this recipe");
1435 check( uves_get_parameter(parameters, NULL, recipe_id,
"search.range",
1436 CPL_TYPE_INT , &RANGE ),
"Could not read parameter");
1437 check( uves_get_parameter(parameters, NULL, recipe_id,
"search.minlines",
1438 CPL_TYPE_INT , &MINLINES ),
"Could not read parameter");
1439 check( uves_get_parameter(parameters, NULL, recipe_id,
"search.maxlines",
1440 CPL_TYPE_INT , &MAXLINES ),
"Could not read parameter");
1445 if (strcmp(centering_m,
"gravity" ) == 0) CENTERING_METHOD = CENTERING_GRAVITY;
1446 else if (strcmp(centering_m,
"gaussian") == 0) CENTERING_METHOD = CENTERING_GAUSSIAN;
1449 assure(
false, CPL_ERROR_ILLEGAL_INPUT,
1450 "Unrecognized parameter value '%s'", centering_m);
1454 check( uves_get_parameter(parameters, NULL, recipe_id,
"first.shiftmax",
1455 CPL_TYPE_DOUBLE , &SHIFT_MAX ),
1456 "Could not read parameter");
1457 check( uves_get_parameter(parameters, NULL, recipe_id,
"first.shiftstep",
1458 CPL_TYPE_DOUBLE , &SHIFT_STEP ),
1459 "Could not read parameter");
1460 check( uves_get_parameter(parameters, NULL, recipe_id,
"first.shifttoler",
1461 CPL_TYPE_DOUBLE , &SHIFT_TOLERANCE),
1462 "Could not read parameter");
1465 check( uves_get_parameter(parameters, NULL, recipe_id,
"identify.alpha",
1466 CPL_TYPE_DOUBLE , &ALPHA ),
"Could not read parameter");
1467 check( uves_get_parameter(parameters, NULL, recipe_id,
"identify.maxerror",
1468 CPL_TYPE_DOUBLE , &MAXERROR ),
"Could not read parameter");
1469 check( uves_get_parameter(parameters, NULL, recipe_id,
"identify.degree",
1470 CPL_TYPE_INT , &DEGREE ),
"Could not read parameter");
1473 check( uves_get_parameter(parameters, NULL, recipe_id,
"calibrate.tolerance",
1474 CPL_TYPE_DOUBLE, &TOLERANCE ),
"Could not read parameter");
1475 check( uves_get_parameter(parameters, NULL, recipe_id,
"calibrate.kappa",
1476 CPL_TYPE_DOUBLE, &KAPPA ),
"Could not read parameter");
1479 if (CENTERING_METHOD == CENTERING_GRAVITY)
1482 "results. Recommended is 'gaussian'");
1487 check( uves_load_arclamp(frames, flames, &arclamp_filename, arclamp, arclamp_header,
1488 rotated_header, &blue, &sim_cal),
"Error loading raw frame");
1491 check( uves_load_linerefertable(frames, &line_refer_filename, &line_refer, NULL),
1492 "Could not load line reference table");
1493 uves_msg(
"Using line reference table '%s'", line_refer_filename);
1496 if (cpl_frameset_find(frames, UVES_LINE_INTMON_TABLE) != NULL)
1498 uves_free_table(&line_intmon);
1499 check( uves_load_lineintmon(frames, &line_intmon_filename,
1501 "Error loading line reference table");
1503 uves_msg(
"Using bright line table '%s'", line_intmon_filename);
1510 "Could not read x binning factor from input header");
1512 "Could not read y binning factor from input header");
1513 SLITLENGTH_par /= (1.0*binx);
1514 RANGE /= (1.0*biny);
1515 SHIFT_MAX /= (1.0*binx);
1516 SHIFT_STEP /= (1.0*binx);
1528 chip != UVES_CHIP_INVALID;
1532 if(strcmp(PROCESS_CHIP,
"REDU") == 0) {
1536 const char *ordertable_filename =
"";
1537 const char *corvel_filename =
"";
1538 const char *master_flat_filename =
"";
1539 const char *master_bias_filename =
"";
1540 const char *weights_filename =
"";
1542 const char *guess_filename =
"";
1543 const char *chip_name =
"";
1547 int current_linetable_extension;
1548 int tab_in_out_oshift = -1;
1549 double tab_in_out_yshift = -1;
1552 uves_msg(
"Processing %s chip in '%s'",
1562 uves_free_table (&ordertable);
1563 uves_free_propertylist(&ordertable_header);
1565 uves_free_table (&traces);
1568 check( uves_load_ordertable(frames,
1571 &ordertable_filename,
1577 (flames) ? &tab_in_out_oshift : NULL,
1578 (flames) ? &tab_in_out_yshift : NULL,
1583 "Could not load order table");
1584 uves_msg(
"Using order table in '%s'", ordertable_filename);
1585 ntraces = cpl_table_get_nrow(traces);
1586 uves_free_double(&fibres_pos);
1587 uves_free_int(&fibres_mask);
1590 uves_free_image(&master_bias);
1591 uves_free_propertylist(&master_bias_header);
1592 if (cpl_frameset_find(frames, UVES_MASTER_BIAS(chip)) != NULL)
1594 check( uves_load_mbias(frames, chip_name, &master_bias_filename, &master_bias,
1595 &master_bias_header, chip),
1596 "Error loading master bias");
1598 uves_msg_low(
"Using master bias in '%s'", master_bias_filename);
1607 uves_free_image(&master_flat);
1608 uves_free_propertylist(&master_flat_header);
1609 if ((cpl_frameset_find(frames, UVES_MASTER_FLAT(chip)) != NULL ||
1610 cpl_frameset_find(frames, UVES_MASTER_DFLAT(chip)) != NULL ||
1611 cpl_frameset_find(frames, UVES_MASTER_IFLAT(chip)) != NULL ||
1612 cpl_frameset_find(frames, UVES_MASTER_TFLAT(chip)) != NULL))
1614 check( uves_load_mflat(frames, chip_name, &master_flat_filename, &master_flat,
1615 &master_flat_header, chip, NULL),
1616 "Error loading master flat");
1618 uves_msg_low(
"Using master flat in '%s'", master_flat_filename);
1626 if (em == EXTRACT_WEIGHTED) {
1627 uves_free_image(&weights);
1628 check( weights = uves_load_weights(frames, &weights_filename, chip),
1629 "Error loading weight map");
1637 if ((corvel_frm=cpl_frameset_find(frames, FLAMES_CORVEL_MASK)))
1639 check( uves_load_corvel(frames,
1640 &corvel, &corvel_header,
1642 "Could not load velocity correction table");
1644 uves_msg(
"Using velocity correction table %s", corvel_filename);
1651 uves_msg(
"No corvel table found. Switch off corvel");
1666 if (debug_mode)
check( uves_save_image_local(
"Arc lamp frame",
"raw",
1668 chip, -1, -1, rotated_header[raw_index],
true),
1669 "Error saving arc lamp frame");
1671 if (master_bias != NULL)
1673 uves_msg(
"Subtracting master bias");
1676 "Error during bias subtraction");
1692 uves_free_image(&arclamp_noise);
1694 arclamp_header[raw_index], 1, chip),
1695 "Could not set arc lamp noise");
1697 if (master_flat != NULL)
1699 uves_msg(
"Dividing by master flat");
1701 uves_free_image(&mflat_noise);
1702 check( mflat_noise =
1706 "Could not set master flat error bars");
1709 master_flat, mflat_noise),
1710 "Error while dividing by flat field");
1713 if (debug_mode)
check( uves_save_image_local(
"Pre-processed arc lamp frame",
1715 arclamp[raw_index], chip, -1, -1,
1716 rotated_header[raw_index],
true),
1717 "Error saving arc lamp frame");
1720 if (SLITLENGTH_par < 0) {
1722 double header_full_slit;
1724 check( header_full_slit =
1726 "Could not read slit length");
1731 slitlength = uves_max_double(1.0, (header_full_slit - 2)/NWINDOWS);
1733 uves_msg(
"Full slit = %.2f pixels", header_full_slit);
1736 slitlength = SLITLENGTH_par;
1741 for(tracerow = 0; tracerow < ntraces; tracerow++) {
1742 double trace_offset;
1746 trace_offset = cpl_table_get_double(traces,
"Offset" , tracerow, NULL);
1747 trace_number = cpl_table_get_int (traces,
"TraceID" , tracerow, NULL);
1748 trace_enabled = cpl_table_get_int (traces,
"Tracemask", tracerow, NULL);
1751 uves_msg(
"Processing trace %d", trace_number);
1754 if (flames && sim_cal)
1757 trace_enabled = (trace_number == 1) ? 1 : 0;
1760 uves_msg_low(
"Trace offset = %.2f pixels ; enabled = %d",
1761 trace_offset, trace_enabled);
1763 assure( flames || trace_number == 0, CPL_ERROR_ILLEGAL_INPUT,
1764 "%s: UVES trace number must be 0, it is %d",
1765 ordertable_filename, trace_number );
1768 if (trace_enabled != 0) {
1772 uves_free_table (&guess);
1775 check( uves_load_linetable(
1776 frames, flames, chip_name, order_locations,
1777 cpl_table_get_column_min(ordertable,
"Order"),
1778 cpl_table_get_column_max(ordertable,
"Order"),
1779 &guess_filename, &guess,
1781 &absolute_order, chip, trace_number, -1),
1782 "Could not load guess line table for trace number %d",
1784 uves_msg(
"Using guess line table '%s'", guess_filename);
1793 absorder_image = cpl_image_new(cpl_image_get_size_x(arclamp[raw_index]),
1794 cpl_image_get_size_y(arclamp[raw_index]),
1798 for (y = 1; y <= cpl_image_get_size_y(arclamp[raw_index]); y++)
1800 for (x = 1; x <= cpl_image_get_size_x(arclamp[raw_index]); x++)
1805 cpl_image_set(absorder_image, x, y, absorder);
1809 check( uves_save_image_local(
"Absolute order image",
"absord",
1810 absorder_image, chip, trace_number,
1811 1, rotated_header[raw_index],
true),
1812 "Error saving absolute order image");
1814 uves_free_image(&absorder_image);
1818 for (window = 1; window <= NWINDOWS; window ++) {
1832 double window_offset =
1833 slitlength * (window - (NWINDOWS+1) / 2.0);
1836 double offset = trace_offset + window_offset + OFFSET;
1841 int lines_min = (MINLINES >= 1) ? MINLINES :
1842 (chip == UVES_CHIP_REDU) ? 1000 : 2000;
1843 int lines_max = (MAXLINES >= 1) ? MAXLINES :
1844 (chip == UVES_CHIP_REDU) ? 1400 : 2400;
1847 int lines_min = (MINLINES >= 1) ? MINLINES :
1848 (chip == UVES_CHIP_REDU) ? 1000 : 1100;
1849 int lines_max = (MAXLINES >= 1) ? MAXLINES :
1850 (chip == UVES_CHIP_REDU) ? 1400 : 1600;
1853 assure( lines_min <= lines_max , CPL_ERROR_ILLEGAL_INPUT,
1854 "Minimum and maximum number of requested line "
1855 "detections don't make sense (min = %d; max = %d)",
1856 lines_min, lines_max);
1859 uves_msg(
"Processing window %d of %d", window, NWINDOWS);
1863 == NULL,
"%d %d", window, trace_number);
1865 == NULL,
"%d %d", window, trace_number);
1868 if (weights != NULL) {
1879 uves_wavecal_process_window(
1883 rotated_header[raw_index],
1885 ordertable, order_locations,
1886 master_flat != NULL,
1895 chip, biny, trace_number, window,NWINDOWS,
1899 offset, slitlength, parameters, recipe_id,
1901 RANGE, lines_min, lines_max, CENTERING_METHOD,
1903 SHIFT_MAX, SHIFT_STEP, SHIFT_TOLERANCE,
1905 ALPHA, MAXERROR, DEGREE,
1914 "Wavelength calibration failed");
1950 (window == 2 && trace_number == 0)||
1951 (window == 1 && NWINDOWS == 1)) {
1953 check( uves_wavecal_qclog(
1961 arclamp_header[raw_index],
1963 trace_number, trace_enabled, trace_offset,
1966 "Could not calculate resolution QC parameters");
1968 if (line_intmon != NULL) {
1969 check( uves_wavecal_qclog_intmon(
1975 arclamp_header[raw_index],
1976 flames, trace_number,
1979 "Could not calculate int.mon. QC parameters");
1997 uves_msg(
"Skipping trace number %d", trace_number);
2005 cpl_free(product_filename);
2006 check( product_filename = uves_line_table_filename(chip),
"Error getting filename");
2007 current_linetable_extension = 1;
2011 for(tracerow = 0; tracerow < cpl_table_get_nrow(traces); tracerow++)
2014 double trace_offset;
2017 trace_offset = cpl_table_get_double(traces,
"Offset" , tracerow, NULL);
2018 trace_number = cpl_table_get_int (traces,
"TraceID" , tracerow, NULL);
2019 trace_enabled = cpl_table_get_int (traces,
"Tracemask" , tracerow, NULL);
2021 if (trace_enabled != 0)
2026 for (window = 1; window <= NWINDOWS; window ++)
2028 double window_offset =
2029 slitlength * (window - (NWINDOWS+1) / 2.0);
2031 double offset = trace_offset + window_offset + OFFSET;
2034 uves_free_propertylist(&table_header);
2037 "Error writing trace ID to product header");
2039 "Error writing trace offset to product header");
2041 "Error writing window number to product header");
2043 sprintf(extname,
"LINE_T%d_W%d_X%d",trace_number,window,
2044 current_linetable_extension);
2052 "Error writing order number to product header");
2058 "Error writing order number to product header");
2062 if (current_linetable_extension == 1) {
2063 uves_free_propertylist(&primary_header);
2073 primary_header, 0.0) );
2077 uves_propertylist_append_string(primary_header,
2079 "'FIBREMASK','I*4'");
2083 for (i = 0; i < N_FIBRES_MAX; i++) {
2084 snprintf(values, 80,
"%1.1d ",
2085 cpl_table_get_int(traces,
"Tracemask",
2087 uves_propertylist_append_string(primary_header,
2090 cpl_table_get_int(traces,
2095 uves_propertylist_append_string(primary_header,
2104 cpl_table_get_column_mean(
2110 "Error reading mean pixelsize");
2114 wavestep = pixelsize*2.0/3;
2116 uves_propertylist_append_string(primary_header,
2119 snprintf(values,80,
"%14.7g %14.7g",pixelsize,pixelsize);
2120 uves_propertylist_append_string(primary_header,
2122 uves_propertylist_append_string(primary_header,
2129 uves_msg(
"Creating line table '%s'", product_filename);
2131 sprintf(extname,
"LINE_T%d_W%d_X%d",trace_number,window,
2132 current_linetable_extension);
2135 check( uves_frameset_insert(
2141 CPL_FRAME_GROUP_PRODUCT,
2142 CPL_FRAME_TYPE_TABLE,
2143 CPL_FRAME_LEVEL_INTERMEDIATE,
2145 UVES_LINE_TABLE(flames, chip),
2146 arclamp_header[raw_index],
2151 PACKAGE
"/" PACKAGE_VERSION,
2152 qclog, starttime,
true, 0),
2153 "Could not add line table '%s' (%s) to frameset",
2154 product_filename, UVES_LINE_TABLE(flames, chip));
2156 uves_msg(
"Line table '%s' (%s) added to frameset",
2157 product_filename, UVES_LINE_TABLE(flames, chip));
2162 check( uves_table_save(
2174 "Error appending table to file '%s'",
2177 current_linetable_extension += 1;
2178 sprintf(extname,
"LINE_T%d_W%d_X%d",trace_number,window,
2179 current_linetable_extension);
2188 "Could not write polynomial to file '%s'",
2190 current_linetable_extension += 1;
2191 sprintf(extname,
"LINE_T%d_W%d_X%d",trace_number,window,
2192 current_linetable_extension);
2201 "Could not write polynomial to file '%s'",
2203 current_linetable_extension += 1;
2205 uves_msg(
"Line table for trace %d, window #%d "
2206 "saved to extensions %d-%d of '%s'",
2207 trace_number, window,
2208 current_linetable_extension - 3,
2209 current_linetable_extension - 1,
2216 if(strcmp(PROCESS_CHIP,
"REDL") == 0) {
2226 uves_free_image(&arclamp[0]);
2227 uves_free_image(&arclamp[1]);
2228 uves_free_image(&arclamp_noise);
2229 uves_free_image(&absorder_image);
2230 uves_free_propertylist(&arclamp_header[0]);
2231 uves_free_propertylist(&arclamp_header[1]);
2232 uves_free_propertylist(&rotated_header[0]);
2233 uves_free_propertylist(&rotated_header[1]);
2236 uves_free_table(&ordertable);
2237 uves_free_propertylist(&ordertable_header);
2238 uves_free_table(&corvel);
2239 uves_free_propertylist(&corvel_header);
2242 uves_free_table(&traces);
2245 uves_free_image(&master_bias);
2246 uves_free_propertylist(&master_bias_header);
2247 uves_free_image(&master_flat);
2248 uves_free_image(&mflat_noise);
2249 uves_free_propertylist(&master_flat_header);
2250 uves_free_image(&weights);
2258 uves_free_table(&guess);
2260 uves_free_table(&line_refer);
2261 uves_free_table(&line_intmon);
2266 uves_free_propertylist(&primary_header);
2267 uves_free_propertylist(&table_header);
2271 cpl_free(product_filename);
2290 static void uves_wavecal_qclog(
const cpl_table* linetable,
2293 const cpl_image *arclamp,
2299 enum uves_chip chip,
2325 const char *qc_lineresidavg_name =
2327 const char *qc_lineresidrms_name =
2330 cpl_table *selected = NULL;
2337 sprintf(test_id,
"%sResolution-Test-Results",flames ?
"Fibre-" :
"");
2353 "DRS det. fibre seq. pos.",
2360 "det. fibre seq. no.",
2366 "det. fibre seq. rel. pos.",
2372 "DRS det. fibre mask value",
2380 "Error reading exposure time");
2384 cpl_image_get_flux(arclamp) / exptime,
2385 "abs. trans. countrate",
2393 for (y = 1; y <= cpl_image_get_size_y(arclamp); y++)
2394 for (x = 1; x <= cpl_image_get_size_x(arclamp); x++)
2397 int value = cpl_image_get(arclamp, x, y, &pis_rejected);
2399 if (!pis_rejected &&
2400 (value < DRS_PTHRES_MIN || value > DRS_PTHRES_MAX))
2409 "no. of hot pixels",
2417 "Error reading plate ID");
2428 selected = uves_extract_table_rows(linetable,
"NLinSol", CPL_NOT_EQUAL_TO, 0);
2430 sprintf(comment,
"average FWHM in X of sel lines on TRACE%d WIN2 [pix]",trace_number);
2433 cpl_table_get_column_mean(selected,
"Xwidth")*TWOSQRT2LN2,
2437 sprintf(comment,
"stdev FWHM in X of sel lines on TRACE%d WIN2 [pix]",trace_number);
2440 cpl_table_get_column_stdev(selected,
"Xwidth")*TWOSQRT2LN2,
2444 sprintf(comment,
"median FWHM in X of sel lines on TRACE%d WIN2 [pix]",trace_number);
2447 cpl_table_get_column_median(selected,
"Xwidth")*TWOSQRT2LN2,
2451 sprintf(comment,
"mean R of sel lines on TRACE%d WIN2",trace_number);
2454 cpl_table_get_column_mean(selected,
"Resol"),
2458 sprintf(comment,
"stdev R of sel lines on TRACE%d WIN2",trace_number);
2461 cpl_table_get_column_stdev(selected,
"Resol"),
2465 sprintf(comment,
"median R of sel lines on TRACE%d WIN2",trace_number);
2468 cpl_table_get_column_median(selected,
"Resol"),
2473 sprintf(comment,
"mean line pos resid on TRACE%d WIN2 [pm]",trace_number);
2475 qc_lineresidavg_name,
2476 cpl_table_get_column_mean(selected, LINETAB_RESIDUAL)*100,
2480 sprintf(comment,
"sigma line pos resid on TRACE%d WIN2 [pm]",trace_number);
2482 qc_lineresidrms_name,
2483 cpl_table_get_column_stdev(selected, LINETAB_RESIDUAL)*100,
2488 wmin=cpl_table_get_column_min(linetable,LINETAB_LAMBDAC)/10.0;
2489 sprintf(comment,
"minimum wavelength on TRACE%d WIN2 [nm]",trace_number);
2496 wmax=cpl_table_get_column_max(linetable,LINETAB_LAMBDAC)/10.0;
2497 sprintf(comment,
"maximum wavelength on TRACE%d WIN2 [nm]",trace_number);
2504 sprintf(comment,
"minimum order number expected on TRACE%d WIN2",trace_number);
2507 uves_min_int(firstabs, lastabs),
2511 sprintf(comment,
"maximum order number expected on TRACE%d WIN2",trace_number);
2514 uves_max_int(firstabs, lastabs),
2519 sprintf(comment,
"minimum order number detected on TRACE%d WIN2",trace_number);
2521 qc_detected_ordmin_name,
2522 cpl_table_get_column_min(linetable,
"Order"),
2526 sprintf(comment,
"maximum order number detected on TRACE%d WIN2",trace_number);
2528 qc_detected_ordmax_name,
2529 cpl_table_get_column_max(linetable,
"Order"),
2533 sprintf(comment,
"No. of lines found on TRACE%d WIN2",trace_number);
2536 cpl_table_get_nrow(linetable),
2540 sprintf(comment,
"No. of lines selected on TRACE%d WIN2",trace_number);
2543 cpl_table_get_nrow(linetable) -
2544 cpl_table_count_invalid(linetable,
"Ident"),
2548 nfinal=cpl_table_get_nrow(selected);
2549 sprintf(comment,
"Final No. of lines used on TRACE%d WIN2",trace_number);
2556 cpl_table* extracted=NULL;
2558 const char* rms_wlu_alpha=NULL;
2559 double lines_sqrt=0;
2560 double lines_werr=0;
2562 wcen=0.5*(wmin+wmax);
2563 check_nomsg(next=cpl_table_and_selected_string(qclog,
"key_name",
2565 "QC LINE RESIDRMS WLU"));
2566 check_nomsg(extracted=cpl_table_extract_selected(qclog));
2568 check_nomsg(rms_wlu_alpha=cpl_table_get_string(extracted,
"key_value",0));
2569 rms_wlu=atof(rms_wlu_alpha);
2570 lines_sqrt=sqrt(nfinal);
2571 lines_werr=rms_wlu/lines_sqrt;
2572 sprintf(comment,
"Wavelength error on TRACE%d [Angstrom]",trace_number);
2579 uves_free_table(&extracted);
2580 uves_free_table(&selected);
2581 selected = cpl_table_duplicate(linetable);
2585 sprintf(comment,
"Wavelength systematic error on TRACE%d [Angstrom]",trace_number);
2588 wcen*100./SPEED_OF_LIGHT,
2595 check_nomsg( uves_erase_invalid_table_rows(selected,
"Ident") );
2596 check_nomsg( uves_erase_table_rows(selected, LINETAB_RESIDUAL,
2600 sprintf(comment,
"No. of lines with residuals < 0.1 nm on TRACE%d",trace_number);
2603 cpl_table_get_nrow(selected),
2610 uves_free_string_const(&qc_fib_drsno_name);
2611 uves_free_string_const(&qc_fib_seq_name);
2612 uves_free_string_const(&qc_fib_pos_name);
2613 uves_free_string_const(&qc_fib_msk_name);
2614 uves_free_string_const(&qc_fwhmavg_name);
2615 uves_free_string_const(&qc_fwhmrms_name);
2616 uves_free_string_const(&qc_fwhmmed_name);
2618 uves_free_string_const(&qc_resolavg_name);
2619 uves_free_string_const(&qc_resolrms_name);
2620 uves_free_string_const(&qc_resolmed_name);
2621 uves_free_string_const(&qc_wlenmin_name);
2622 uves_free_string_const(&qc_wlenmax_name);
2623 uves_free_string_const(&qc_ordmin_name);
2624 uves_free_string_const(&qc_ordmax_name);
2625 uves_free_string_const(&qc_nlintot_name);
2626 uves_free_string_const(&qc_nlinsel_name);
2627 uves_free_string_const(&qc_line_werr_name);
2628 uves_free_string_const(&qc_line_wsys_name);
2629 uves_free_string_const(&qc_nlinsol_name);
2630 uves_free_string_const(&qc_nlinres1_name);
2631 uves_free_string_const(&qc_lineresidavg_name);
2632 uves_free_string_const(&qc_lineresidrms_name);
2633 uves_free_string_const(&qc_detected_ordmin_name);
2634 uves_free_string_const(&qc_detected_ordmax_name);
2636 uves_free_table(&selected);
2650 static void uves_wavecal_qclog_intmon(cpl_table* table,
2651 const cpl_table *line_intmon,
2655 enum uves_chip chip,
2658 const char *qc_intavg_name = NULL;
2659 const char *qc_nlinint_name = NULL;
2661 cpl_table *temp = NULL;
2665 flames ?
"Fibre-Line-Intensity-Test-Results"
2666 :
"Line-Intensity-Test-Results",
2674 double tolerance = 0.001;
2683 int N_bright = cpl_table_get_nrow(line_intmon);
2687 "Could not get exposure time");
2689 cpl_table_new_column(table,
"Intensity", CPL_TYPE_DOUBLE);
2690 for (i = 0; i < cpl_table_get_nrow(table); i++)
2693 double ident = cpl_table_get_double(table,
"Ident", i, &is_null);
2698 line_intmon, ident, 0, N_bright-1);
2700 double bright = cpl_table_get_double(
2701 line_intmon,
"Wave", bright_index, NULL);
2703 if (fabs(bright - ident) < tolerance)
2705 double peak = cpl_table_get_double(table,
"Peak", i, NULL);
2707 fabs(cpl_table_get_double(table, LINETAB_PIXELSIZE, i, NULL));
2709 double lambda_fwhm = cpl_table_get_double(table,
"Xwidth", i, NULL)
2710 * TWOSQRT2LN2 * pixelsize;
2713 double intensity = peak * lambda_fwhm / exptime;
2716 cpl_table_set_double(table,
"Intensity", i, intensity);
2720 cpl_table_set_invalid(table,
"Intensity", i);
2725 cpl_table_set_invalid(table,
"Intensity", i);
2730 uves_free_table(&temp);
2731 temp = cpl_table_duplicate(table);
2732 uves_erase_invalid_table_rows(temp,
"Intensity");
2736 if (cpl_table_get_nrow(temp) == 0)
2743 mean = cpl_table_get_column_mean(temp,
"Intensity");
2748 qc_intavg_name = uves_sprintf(
"QC FIB%d INTAVG", fibre+1);
2749 qc_nlinint_name = uves_sprintf(
"QC FIB%d NLININT", fibre+1);
2753 qc_intavg_name = uves_sprintf(
"QC INTAVG");
2754 qc_nlinint_name = uves_sprintf(
"QC NLININT");
2760 "average intensity of line list on TRACE0 WIN2",
2765 cpl_table_get_nrow(temp),
2766 "No. of lines to measure INTAVG on TRACE0 WIN2",
2771 uves_free_string_const(&qc_intavg_name);
2772 uves_free_string_const(&qc_nlinint_name);
2773 uves_free_table(&temp);
cpl_table ** uves_lt_get_table(const lt_type *lt, int window, int trace)
Get the table structure.
int uves_pfits_get_datancom(const uves_propertylist *plist)
Find out the number of input raw frames.
void uves_polynomial_delete(polynomial **p)
Delete a polynomial.
#define uves_msg_warning(...)
Print an warning message.
int uves_flames_pfits_get_plateid(const uves_propertylist *raw_header)
read the plate id
void uves_pfits_set_windownumber(uves_propertylist *plist, int window_number)
Write the window number.
double uves_pfits_get_slitlength_pixels(const uves_propertylist *plist, enum uves_chip chip)
Read the slit length in pixels.
int * uves_lt_get_lastabs(const lt_type *lt, int window, int trace)
Get last absolute order.
int uves_qclog_add_string(cpl_table *table, const char *key_name, const char *value, const char *key_help, const char *format)
Add string key to QC-LOG table.
cpl_image * uves_define_noise(const cpl_image *image, const uves_propertylist *image_header, int ncom, enum uves_chip chip)
Create noise image.
lt_type * uves_lt_new(int windows, int traces)
Allocate line table.
cpl_error_code uves_subtract_bias(cpl_image *image, const cpl_image *master_bias)
Subtract bias.
int uves_qclog_delete(cpl_table **table)
delete QC-LOG table
#define passure(BOOL,...)
int uves_gauss_derivative(const double x[], const double a[], double result[])
Evaluate the derivatives of a gaussian.
int uves_qclog_add_double(cpl_table *table, const char *key_name, const double value, const char *key_help, const char *format)
Add double key to QC-LOG table.
int uves_qclog_add_int(cpl_table *table, const char *key_name, const int value, const char *key_help, const char *format)
Add integer key to QC-LOG table.
polynomial ** uves_lt_get_disprel(const lt_type *lt, int window, int trace)
Get dispersion relation.
uves_propertylist * uves_propertylist_new(void)
Create an empty property list.
int uves_pfits_get_binx(const uves_propertylist *plist)
Find out the x binning factor.
#define uves_msg(...)
Print a message on 'info' or 'debug' level.
int uves_gauss(const double x[], const double a[], double *result)
Evaluate a gaussian.
void uves_pfits_set_traceid(uves_propertylist *plist, int trace_id)
Write the trace ID.
polynomial * uves_polynomial_duplicate(const polynomial *p)
Copy a polynomial.
polynomial * uves_wavecal_identify(cpl_table *linetable, const cpl_table *line_refer, const polynomial *guess_dispersion, int DEGREE, double TOLERANCE, double ALPHA, double MAXERROR, double kappa, const int trace, const int window, cpl_table *qclog)
Obtain final dispersion relation.
int uves_pfits_get_biny(const uves_propertylist *plist)
Find out the y binning factor.
cpl_error_code uves_propertylist_copy_property_regexp(uves_propertylist *self, const uves_propertylist *other, const char *regexp, int invert)
Copy matching properties from another property list.
double uves_flames_pfits_get_dit(const uves_propertylist *plist)
Find out the integration time.
cpl_error_code uves_draw_lines(cpl_image *image, polynomial *dispersion, const polynomial *order_locations, const cpl_table *t, const char *lambda_column, const char *abs_order, const int *relative_order, int minorder, int maxorder, bool vertical, int offset)
Draw lines in an echelle image.
double uves_pfits_get_exptime(const uves_propertylist *plist)
Find out the exposure time in seconds.
cpl_table * uves_wavecal_search(const cpl_image *spectrum, const cpl_image *noise, const uves_propertylist *spectrum_header, bool flat_fielded, const polynomial *order_locations, cpl_image *arcframe, int RANGE, int MINLINES, int MAXLINES, centering_method CENTERING_METHOD, int bin_disp, const int trace, const int window, cpl_table *qclog)
Search for a given number of emission lines.
double uves_polynomial_evaluate_2d(const polynomial *p, double x1, double x2)
Evaluate a 2d polynomial.
int uves_chip_get_index(enum uves_chip chip)
Convert to integer.
int * uves_lt_get_firstabs(const lt_type *lt, int window, int trace)
Get first absolute order.
enum uves_chip uves_chip_get_first(bool blue)
Get first chip for blue or red arm.
cpl_error_code uves_pfits_set_extname(uves_propertylist *plist, const char *extname)
Write the EXTNAME keyword.
cpl_image * uves_rebin(const cpl_image *spectrum, const cpl_parameterlist *parameters, const char *context, const cpl_table *linetable, const polynomial *dispersion_relation, int first_abs_order, int last_abs_order, int n_traces, bool threshold_to_positive, bool is_noise, uves_propertylist **rebinned_header)
Rebin a spectrum.
void uves_lt_delete(lt_type **lt)
Deallocate line table.
cpl_image * uves_merge_orders(const cpl_image *spectrum, const cpl_image *spectrum_noise, const uves_propertylist *spectrum_header, merge_method m_method, int n_traces, uves_propertylist **merged_header, const double delt1, const double delt2, enum uves_chip chip, cpl_image **merged_noise)
Merge orders.
#define uves_error_reset()
#define uves_msg_low(...)
Print a message on a lower message level.
void uves_pfits_set_lastabsorder(uves_propertylist *plist, int last_abs_order)
Write the last absolute order number.
enum uves_chip uves_chip_get_next(enum uves_chip chip)
Get next chip.
#define uves_msg_debug(...)
Print a debug message.
const char * uves_chip_tostring_upper(enum uves_chip chip)
Convert to string.
double uves_pfits_get_cdelt1(const uves_propertylist *plist)
Find out the cdelt1.
int uves_wavecal_find_nearest(const cpl_table *line_refer, double lambda, int lo, int hi)
Find best matching catalogue wavelength.
double uves_pfits_get_crval1(const uves_propertylist *plist)
Find out the crval1.
const char * uves_string_toupper(char *s)
Convert all lowercase characters in a string into uppercase characters.
void uves_qclog_add_common_wave(const uves_propertylist *raw_header, enum uves_chip chip, cpl_table *qclog)
Write common QC parameters.
cpl_error_code uves_flatfielding(cpl_image *image, cpl_image *noise, const cpl_image *master_flat, const cpl_image *mflat_noise)
Divide by flat field.
cpl_table * uves_qclog_init(const uves_propertylist *raw_header, enum uves_chip chip)
Init QC-LOG table.
polynomial ** uves_lt_get_absord(const lt_type *lt, int window, int trace)
Get absolute order polynomial.
const char * uves_qclog_get_qc_name(const char *name, bool flames, int trace_number)
Create QC parameter name.
const char * uves_pfits_get_chipid(const uves_propertylist *plist, enum uves_chip chip)
Find out the chip ID.
void uves_pfits_set_firstabsorder(uves_propertylist *plist, int first_abs_order)
Write the first absolute order number.
void uves_flames_pfits_set_ccfposmax(uves_propertylist *plist, double ccfposmax)
Write the ccfposmax keyword (what is it?)
void uves_pfits_set_offset(uves_propertylist *plist, double trace_offset)
Write the trace offset.