98 #include <uves_cd_align_impl.h>
101 #include <uves_plot.h>
102 #include <uves_parameters.h>
103 #include <uves_dfs.h>
104 #include <uves_pfits.h>
105 #include <uves_qclog.h>
106 #include <uves_recipe.h>
107 #include <uves_utils_cpl.h>
108 #include <uves_utils_wrappers.h>
109 #include <uves_error.h>
110 #include <uves_msg.h>
119 uves_cal_cd_align_define_parameters(cpl_parameterlist *parameters);
124 #define cpl_plugin_get_info uves_cal_cd_align_get_info
126 UVES_CD_ALIGN_ID, UVES_CD_ALIGN_DOM, uves_cal_cd_align_define_parameters,
127 "Jonas M. Larsen",
"cpl@eso.org",
128 "Measures the reproducability of the cross disperser positioning",
129 "Given two input frames (CD_ALIGN_xxx where xxx = BLUE or RED) which contain only\n"
130 "one echelle order, this recipe measures the shift in the cross-dispersion \n"
131 "direction of that order. For RED input frames, only the lower chip is processed.\n"
133 "The recipe produces a CD_ALIGN_TABLE_xxxx (with xxxx = BLUE or REDL) with columns\n"
135 "YCENi: Centroid from Gaussian fit (for i = 1,2)\n"
136 "SIGMAi: Stdev from Gaussian fit\n"
137 "BACKi: Constant background from Gaussian fit\n"
138 "NORMi: Normalization constant from Gaussian fit\n"
139 "YDIFF: Difference YCEN2 - YCEN1 of centroid positions\n"
141 "and the QC-parameters ESO.QC.YDIFF(AVG|MED|RMS), which are the average,\n"
142 "median and root-mean-square of the y-shift, respectively.\n");
149 uves_cal_cd_align_define_parameters(cpl_parameterlist *parameters)
151 const char *subcontext = NULL;
152 const char *recipe_id = make_str(UVES_CD_ALIGN_ID);
157 if (uves_define_global_parameters(parameters) != CPL_ERROR_NONE)
163 uves_par_new_range(
"steps",
165 "Step size in pixels",
169 uves_par_new_range(
"xborder",
171 "Exclude a border region of this size (pixels)",
175 uves_par_new_range(
"window",
177 "The half window height used for Gaussian fitting",
180 return (cpl_error_get_code() != CPL_ERROR_NONE);
202 uves_cd_align_process(
const cpl_image *im1,
203 const cpl_image *im2,
212 cpl_table *result = NULL;
214 const cpl_image *images[2];
215 cpl_image *rows = NULL;
218 cpl_size num_fits, fit_succeeded;
222 nx = cpl_image_get_size_x(images[0]);
223 ny = cpl_image_get_size_y(images[0]);
225 if (debug_mode)
check( uves_save_image_local(
"CD alignment frame",
"cd_align1",
226 images[0], chip, -1, -1,
227 rotated_header1,
true),
228 "Error saving 1st CD aligment frame");
230 if (debug_mode)
check( uves_save_image_local(
"CD alignment frame",
"cd_align2",
231 images[1], chip, -1, -1,
232 rotated_header2,
true),
233 "Error saving 2nd CD aligment frame");
235 assure( cpl_image_get_size_x(images[0]) == cpl_image_get_size_x(images[1]) &&
236 cpl_image_get_size_y(images[0]) == cpl_image_get_size_y(images[1]),
237 CPL_ERROR_INCOMPATIBLE_INPUT,
238 "Images sizes: %" CPL_SIZE_FORMAT
"x%" CPL_SIZE_FORMAT
" and %" CPL_SIZE_FORMAT
"x%" CPL_SIZE_FORMAT
"",
239 cpl_image_get_size_x(images[0]),
240 cpl_image_get_size_y(images[0]),
241 cpl_image_get_size_x(images[1]),
242 cpl_image_get_size_y(images[1]) );
245 result = cpl_table_new(nx); row = 0;
246 cpl_table_new_column(result,
"X" , CPL_TYPE_INT);
247 cpl_table_new_column(result,
"YCEN1", CPL_TYPE_DOUBLE);
248 cpl_table_new_column(result,
"YCEN2", CPL_TYPE_DOUBLE);
249 cpl_table_new_column(result,
"SIGMA1", CPL_TYPE_DOUBLE);
250 cpl_table_new_column(result,
"SIGMA2", CPL_TYPE_DOUBLE);
251 cpl_table_new_column(result,
"BACK1", CPL_TYPE_DOUBLE);
252 cpl_table_new_column(result,
"BACK2", CPL_TYPE_DOUBLE);
253 cpl_table_new_column(result,
"NORM1", CPL_TYPE_DOUBLE);
254 cpl_table_new_column(result,
"NORM2", CPL_TYPE_DOUBLE);
260 for (im = 0; im < 2; im++)
265 uves_free_image(&rows);
266 rows = cpl_image_collapse_create(images[im], direction);
268 cpl_image_get_maxpos(rows, &max_col, &(max_row[im]));
269 uves_msg(
"Row of max flux (%" CPL_SIZE_FORMAT
". image) = %" CPL_SIZE_FORMAT
"", (cpl_size)im+1, max_row[im]);
271 assure( max_col == 1, CPL_ERROR_ILLEGAL_OUTPUT,
272 "Something went wrong, max_col in collapsed image is = %" CPL_SIZE_FORMAT
"", max_col);
279 for (x = 1 + xborder; x <= nx - xborder; x += steps)
282 for (im = 0; im < 2; im++)
284 bool horizontal =
false;
285 bool fix_background =
false;
286 bool fit_background =
false;
287 int number_of_parameters = 4;
288 double y_0, sigma, norm, background;
289 int ylow = uves_max_int(1, uves_min_int(ny, max_row[im] - window));
290 int yhigh = uves_max_int(1, uves_min_int(ny, max_row[im] + window));
292 uves_fit_1d_image(images[im],
294 horizontal, fix_background, fit_background,
296 &y_0, &sigma, &norm, &background, NULL,
300 number_of_parameters);
303 if (cpl_error_get_code() == CPL_ERROR_CONTINUE)
307 uves_msg_warning(
"Fitting window (%" CPL_SIZE_FORMAT
", %" CPL_SIZE_FORMAT
") - (%" CPL_SIZE_FORMAT
", %" CPL_SIZE_FORMAT
") failed",
308 (cpl_size)x, (cpl_size)ylow,
309 (cpl_size)x, (cpl_size)yhigh);
315 assure( cpl_error_get_code() == CPL_ERROR_NONE,
316 cpl_error_get_code(),
317 "Gaussian fitting failed");
319 cpl_table_set_int (result,
"X" , row, x);
320 cpl_table_set_double(result, (im == 0) ?
"YCEN1" :
"YCEN2", row, y_0);
321 cpl_table_set_double(result, (im == 0) ?
"SIGMA1":
"SIGMA2", row, sigma);
322 cpl_table_set_double(result, (im == 0) ?
"BACK1" :
"BACK2", row, norm);
323 cpl_table_set_double(result, (im == 0) ?
"NORM1" :
"NORM2", row, background);
329 cpl_table_set_size(result, row);
331 uves_msg_low(
"Was able to fit %" CPL_SIZE_FORMAT
" of %" CPL_SIZE_FORMAT
" columns", fit_succeeded, num_fits);
333 check(( cpl_table_duplicate_column(result,
"YDIFF", result,
"YCEN2"),
334 cpl_table_subtract_columns(result,
"YDIFF",
"YCEN1")),
335 "Error calculating residuals of fit");
338 cpl_size num_valid = cpl_table_get_nrow(result) - cpl_table_count_invalid(result,
"YDIFF");
340 assure( num_valid >= 1, CPL_ERROR_ILLEGAL_OUTPUT,
341 "Only %" CPL_SIZE_FORMAT
" valid YDIFF value(s), 1 or more needed",
347 uves_free_image(&rows);
363 cd_align_qclog(
const cpl_table *cdalign,
367 cpl_table *qclog = NULL;
368 double mean, sigma, median;
371 "Error during QC initialization");
373 mean = cpl_table_get_column_mean (cdalign,
"YDIFF");
374 sigma = cpl_table_get_column_stdev (cdalign,
"YDIFF");
375 median = cpl_table_get_column_median(cdalign,
"YDIFF");
379 "Test-of-CD-Alignment",
386 "Average Y difference",
392 "Median Y difference",
402 uves_msg(
"Average shift = %.4f +- %.4f pixels",
420 avg_flux(
const cpl_image *im)
423 cpl_image *median_filt = NULL;
424 bool extrapolate_border =
true;
439 median_filt = cpl_image_duplicate(im);
446 cpl_image_get_mean (median_filt) -
447 cpl_image_get_median(median_filt);
450 uves_free_image(&median_filt);
464 uves_cal_cd_align_exe(cpl_frameset *frames,
const cpl_parameterlist *parameters,
465 const char *starttime)
468 cpl_image *raw_images[2][2] = {{NULL, NULL}, {NULL, NULL}};
483 cpl_table* qclog[2] = {NULL, NULL};
487 cpl_table *cd_align = NULL;
490 int steps, xborder, window;
494 const char *product_filename = NULL;
497 const char *raw_filename[2];
500 const char* PROCESS_CHIP=NULL;
502 check( uves_get_parameter(parameters, NULL,
"uves",
"debug",
503 CPL_TYPE_BOOL, &debug_mode),
"Could not read parameter");
505 check( uves_get_parameter(parameters, NULL,
"uves",
"process_chip", CPL_TYPE_STRING, &PROCESS_CHIP),
506 "Could not read parameter");
509 check( uves_get_parameter(parameters, NULL, make_str(UVES_CD_ALIGN_ID),
"steps",
510 CPL_TYPE_INT , &steps),
"Could not read parameter");
511 check( uves_get_parameter(parameters, NULL, make_str(UVES_CD_ALIGN_ID),
"xborder",
512 CPL_TYPE_INT , &xborder),
"Could not read parameter");
513 check( uves_get_parameter(parameters, NULL, make_str(UVES_CD_ALIGN_ID),
"window",
514 CPL_TYPE_INT , &window),
"Could not read parameter");
517 check( uves_load_cd_align(frames,
527 "Error loading raw frame");
529 uves_msg(
"Using %s", raw_filename[0]);
530 uves_msg(
"Using %s", raw_filename[1]);
535 chip = UVES_CHIP_BLUE;
544 uves_msg(
"1. REDL average flux per pixel = %f ADU", avg_flux(raw_images[0][raw_index_l]));
545 uves_msg(
"2. REDL average flux per pixel = %f ADU", avg_flux(raw_images[1][raw_index_l]));
547 uves_msg(
"1. REDU average flux per pixel = %f ADU", avg_flux(raw_images[0][raw_index_u]));
548 uves_msg(
"2. REDU average flux per pixel = %f ADU", avg_flux(raw_images[1][raw_index_u]));
551 chip = UVES_CHIP_REDL;
559 check( cd_align = uves_cd_align_process(raw_images[0][raw_index],
560 raw_images[1][raw_index],
561 rotated_headers[0][raw_index],
562 rotated_headers[1][raw_index],
568 "Error during processing");
570 check( qclog[0] = cd_align_qclog(cd_align,
571 raw_headers[0][raw_index],
573 "Could not compute QC");
576 product_filename = uves_cd_align_filename(chip);
577 check( uves_frameset_insert(frames,
579 CPL_FRAME_GROUP_PRODUCT,
580 CPL_FRAME_TYPE_TABLE,
581 CPL_FRAME_LEVEL_FINAL,
583 UVES_CD_ALIGN_TABLE(blue),
584 raw_headers[0][raw_index],
588 make_str(UVES_CD_ALIGN_ID),
589 PACKAGE
"/" PACKAGE_VERSION,
593 "Could not add CD align table %s to frameset", product_filename);
595 uves_msg(
"CD align table %s (%s) added to frameset",
596 product_filename, UVES_CD_ALIGN_TABLE(blue));
599 uves_free_image(&raw_images[0][0]);
600 uves_free_image(&raw_images[0][1]);
601 uves_free_image(&raw_images[1][0]);
602 uves_free_image(&raw_images[1][1]);
603 uves_free_propertylist(&raw_headers[0][0]);
604 uves_free_propertylist(&raw_headers[0][1]);
605 uves_free_propertylist(&raw_headers[1][0]);
606 uves_free_propertylist(&raw_headers[1][1]);
607 uves_free_propertylist(&rotated_headers[0][0]);
608 uves_free_propertylist(&rotated_headers[0][1]);
609 uves_free_propertylist(&rotated_headers[1][0]);
610 uves_free_propertylist(&rotated_headers[1][1]);
612 uves_free_table(&qclog[0]);
613 uves_free_string_const(&product_filename);
614 uves_free_table(&cd_align);
615 uves_free_propertylist(&product_header);