00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 #ifdef HAVE_CONFIG_H
00080 # include <config.h>
00081 #endif
00082
00083
00090
00091
00092
00093
00094
00095 #include <uves_cd_align_impl.h>
00096
00097 #include <uves.h>
00098 #include <uves_plot.h>
00099 #include <uves_parameters.h>
00100 #include <uves_dfs.h>
00101 #include <uves_pfits.h>
00102 #include <uves_qclog.h>
00103 #include <uves_recipe.h>
00104 #include <uves_utils_cpl.h>
00105 #include <uves_utils_wrappers.h>
00106 #include <uves_error.h>
00107 #include <uves_msg.h>
00108
00109 #include <cpl.h>
00110
00111
00112
00113
00114
00115 static int
00116 uves_cal_cd_align_define_parameters(cpl_parameterlist *parameters);
00117
00118
00119
00120
00121 #define cpl_plugin_get_info uves_cal_cd_align_get_info
00122 UVES_RECIPE_DEFINE(
00123 UVES_CD_ALIGN_ID, UVES_CD_ALIGN_DOM, uves_cal_cd_align_define_parameters,
00124 "Jonas M. Larsen", "cpl@eso.org",
00125 "Measures the reproducability of the cross disperser positioning",
00126 "Given two input frames (CD_ALIGN_xxx where xxx = BLUE or RED) which contain only\n"
00127 "one echelle order, this recipe measures the shift in the cross-dispersion \n"
00128 "direction of that order. For RED input frames, only the lower chip is processed.\n"
00129 "\n"
00130 "The recipe produces a CD_ALIGN_TABLE_xxxx (with xxxx = BLUE or REDL) with columns\n"
00131 "X: Column number\n"
00132 "YCENi: Centroid from Gaussian fit (for i = 1,2)\n"
00133 "SIGMAi: Stdev from Gaussian fit\n"
00134 "BACKi: Constant background from Gaussian fit\n"
00135 "NORMi: Normalization constant from Gaussian fit\n"
00136 "YDIFF: Difference YCEN2 - YCEN1 of centroid positions\n"
00137 "\n"
00138 "and the QC-parameters ESO.QC.YDIFF(AVG|MED|RMS), which are the average,\n"
00139 "median and root-mean-square of the y-shift, respectively.\n");
00140
00141
00142
00143
00145 static int
00146 uves_cal_cd_align_define_parameters(cpl_parameterlist *parameters)
00147 {
00148 const char *subcontext = NULL;
00149 const char *recipe_id = make_str(UVES_CD_ALIGN_ID);
00150
00151
00152
00153
00154 if (uves_define_global_parameters(parameters) != CPL_ERROR_NONE)
00155 {
00156 return -1;
00157 }
00158
00159
00160 uves_par_new_range("steps",
00161 CPL_TYPE_INT,
00162 "Step size in pixels",
00163 100, 1, INT_MAX);
00164
00165
00166 uves_par_new_range("xborder",
00167 CPL_TYPE_INT,
00168 "Exclude a border region of this size (pixels)",
00169 200, 0, INT_MAX);
00170
00171
00172 uves_par_new_range("window",
00173 CPL_TYPE_INT,
00174 "The half window height used for Gaussian fitting",
00175 50, 1, INT_MAX);
00176
00177 return (cpl_error_get_code() != CPL_ERROR_NONE);
00178 }
00179
00180
00197
00198 cpl_table *
00199 uves_cd_align_process(const cpl_image *im1,
00200 const cpl_image *im2,
00201 const uves_propertylist *rotated_header1,
00202 const uves_propertylist *rotated_header2,
00203 int steps,
00204 int xborder,
00205 int window,
00206 bool DEBUG,
00207 enum uves_chip chip)
00208 {
00209 cpl_table *result = NULL;
00210 int row = 0;
00211 const cpl_image *images[2];
00212 cpl_image *rows = NULL;
00213 cpl_size max_row[2];
00214 int nx, ny, x;
00215 cpl_size num_fits, fit_succeeded;
00216
00217 images[0] = im1;
00218 images[1] = im2;
00219 nx = cpl_image_get_size_x(images[0]);
00220 ny = cpl_image_get_size_y(images[0]);
00221
00222 if (DEBUG) check( uves_save_image_local("CD alignment frame", "cd_align1",
00223 images[0], chip, -1, -1,
00224 rotated_header1, true),
00225 "Error saving 1st CD aligment frame");
00226
00227 if (DEBUG) check( uves_save_image_local("CD alignment frame", "cd_align2",
00228 images[1], chip, -1, -1,
00229 rotated_header2, true),
00230 "Error saving 2nd CD aligment frame");
00231
00232 assure( cpl_image_get_size_x(images[0]) == cpl_image_get_size_x(images[1]) &&
00233 cpl_image_get_size_y(images[0]) == cpl_image_get_size_y(images[1]),
00234 CPL_ERROR_INCOMPATIBLE_INPUT,
00235 "Images sizes: %" CPL_SIZE_FORMAT "x%" CPL_SIZE_FORMAT " and %" CPL_SIZE_FORMAT "x%" CPL_SIZE_FORMAT "",
00236 cpl_image_get_size_x(images[0]),
00237 cpl_image_get_size_y(images[0]),
00238 cpl_image_get_size_x(images[1]),
00239 cpl_image_get_size_y(images[1]) );
00240
00241
00242 result = cpl_table_new(nx); row = 0;
00243 cpl_table_new_column(result, "X" , CPL_TYPE_INT);
00244 cpl_table_new_column(result, "YCEN1", CPL_TYPE_DOUBLE);
00245 cpl_table_new_column(result, "YCEN2", CPL_TYPE_DOUBLE);
00246 cpl_table_new_column(result, "SIGMA1", CPL_TYPE_DOUBLE);
00247 cpl_table_new_column(result, "SIGMA2", CPL_TYPE_DOUBLE);
00248 cpl_table_new_column(result, "BACK1", CPL_TYPE_DOUBLE);
00249 cpl_table_new_column(result, "BACK2", CPL_TYPE_DOUBLE);
00250 cpl_table_new_column(result, "NORM1", CPL_TYPE_DOUBLE);
00251 cpl_table_new_column(result, "NORM2", CPL_TYPE_DOUBLE);
00252 assure_mem( result );
00253
00254
00255 {
00256 int im;
00257 for (im = 0; im < 2; im++)
00258 {
00259 int direction = 1;
00260 cpl_size max_col;
00261
00262 uves_free_image(&rows);
00263 rows = cpl_image_collapse_create(images[im], direction);
00264
00265 cpl_image_get_maxpos(rows, &max_col, &(max_row[im]));
00266 uves_msg("Row of max flux (%" CPL_SIZE_FORMAT ". image) = %" CPL_SIZE_FORMAT "", (cpl_size)im+1, max_row[im]);
00267
00268 assure( max_col == 1, CPL_ERROR_ILLEGAL_OUTPUT,
00269 "Something went wrong, max_col in collapsed image is = %" CPL_SIZE_FORMAT "", max_col);
00270 }
00271 }
00272
00273
00274 num_fits = 0;
00275 fit_succeeded = 0;
00276 for (x = 1 + xborder; x <= nx - xborder; x += steps)
00277 {
00278 int im;
00279 for (im = 0; im < 2; im++)
00280 {
00281 bool horizontal = false;
00282 bool fix_background = false;
00283 bool fit_background = false;
00284 int number_of_parameters = 4;
00285 double y_0, sigma, norm, background;
00286 int ylow = uves_max_int(1, uves_min_int(ny, max_row[im] - window));
00287 int yhigh = uves_max_int(1, uves_min_int(ny, max_row[im] + window));
00288
00289 uves_fit_1d_image(images[im],
00290 NULL, NULL,
00291 horizontal, fix_background, fit_background,
00292 ylow, yhigh, x,
00293 &y_0, &sigma, &norm, &background, NULL,
00294 NULL, NULL,
00295 NULL,
00296 uves_gauss, uves_gauss_derivative,
00297 number_of_parameters);
00298
00299 num_fits += 1;
00300 if (cpl_error_get_code() == CPL_ERROR_CONTINUE)
00301 {
00302 uves_error_reset();
00303
00304 uves_msg_warning("Fitting window (%" CPL_SIZE_FORMAT ", %" CPL_SIZE_FORMAT ") - (%" CPL_SIZE_FORMAT ", %" CPL_SIZE_FORMAT ") failed",
00305 (cpl_size)x, (cpl_size)ylow,
00306 (cpl_size)x, (cpl_size)yhigh);
00307 }
00308 else
00309 {
00310 fit_succeeded += 1;
00311
00312 assure( cpl_error_get_code() == CPL_ERROR_NONE,
00313 cpl_error_get_code(),
00314 "Gaussian fitting failed");
00315
00316 cpl_table_set_int (result, "X" , row, x);
00317 cpl_table_set_double(result, (im == 0) ? "YCEN1" : "YCEN2", row, y_0);
00318 cpl_table_set_double(result, (im == 0) ? "SIGMA1": "SIGMA2", row, sigma);
00319 cpl_table_set_double(result, (im == 0) ? "BACK1" : "BACK2", row, norm);
00320 cpl_table_set_double(result, (im == 0) ? "NORM1" : "NORM2", row, background);
00321 }
00322 }
00323 row++;
00324 }
00325
00326 cpl_table_set_size(result, row);
00327
00328 uves_msg_low("Was able to fit %" CPL_SIZE_FORMAT " of %" CPL_SIZE_FORMAT " columns", fit_succeeded, num_fits);
00329
00330 check(( cpl_table_duplicate_column(result, "YDIFF", result, "YCEN2"),
00331 cpl_table_subtract_columns(result, "YDIFF", "YCEN1")),
00332 "Error calculating residuals of fit");
00333
00334 {
00335 cpl_size num_valid = cpl_table_get_nrow(result) - cpl_table_count_invalid(result, "YDIFF");
00336
00337 assure( num_valid >= 1, CPL_ERROR_ILLEGAL_OUTPUT,
00338 "Only %" CPL_SIZE_FORMAT " valid YDIFF value(s), 1 or more needed",
00339 num_valid);
00340 }
00341
00342
00343 cleanup:
00344 uves_free_image(&rows);
00345 return result;
00346 }
00347
00348
00357
00358
00359 static cpl_table*
00360 cd_align_qclog(const cpl_table *cdalign,
00361 const uves_propertylist *raw_header,
00362 enum uves_chip chip)
00363 {
00364 cpl_table *qclog = NULL;
00365 double mean, sigma, median;
00366
00367 check( qclog = uves_qclog_init(raw_header, chip),
00368 "Error during QC initialization");
00369
00370 mean = cpl_table_get_column_mean (cdalign, "YDIFF");
00371 sigma = cpl_table_get_column_stdev (cdalign, "YDIFF");
00372 median = cpl_table_get_column_median(cdalign, "YDIFF");
00373
00374 uves_qclog_add_string(qclog,
00375 "QC TEST1 ID",
00376 "Test-of-CD-Alignment",
00377 "Name of QC test",
00378 "%s");
00379
00380 uves_qclog_add_double(qclog,
00381 "QC YDIFFAVG",
00382 mean,
00383 "Average Y difference",
00384 "%8.4f");
00385
00386 uves_qclog_add_double(qclog,
00387 "QC YDIFFMED",
00388 median,
00389 "Median Y difference",
00390 "%8.4f");
00391
00392 uves_qclog_add_double(qclog,
00393 "QC YDIFFRMS",
00394 sigma,
00395 "RMS Y difference",
00396 "%8.4f");
00397
00398
00399 uves_msg("Average shift = %.4f +- %.4f pixels",
00400 mean, sigma);
00401
00402
00403 cleanup:
00404 return qclog;
00405 }
00406
00407
00415
00416 static double
00417 avg_flux(const cpl_image *im)
00418 {
00419 double result = 0;
00420 cpl_image *median_filt = NULL;
00421 bool extrapolate_border = true;
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436 median_filt = cpl_image_duplicate(im);
00437 assure_mem( median_filt );
00438
00439 uves_filter_image_median(&median_filt, 1, 1,
00440 extrapolate_border);
00441
00442 result =
00443 cpl_image_get_mean (median_filt) -
00444 cpl_image_get_median(median_filt);
00445
00446 cleanup:
00447 uves_free_image(&median_filt);
00448 return result;
00449 }
00450
00451
00459
00460 static void
00461 uves_cal_cd_align_exe(cpl_frameset *frames, const cpl_parameterlist *parameters,
00462 const char *starttime)
00463 {
00464
00465 cpl_image *raw_images[2][2] = {{NULL, NULL}, {NULL, NULL}};
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 uves_propertylist *raw_headers[2][2] = {{NULL, NULL}, {NULL, NULL}};
00478 uves_propertylist *rotated_headers[2][2] = {{NULL, NULL}, {NULL, NULL}};
00479
00480 cpl_table* qclog[2] = {NULL, NULL};
00481
00482
00483 uves_propertylist *product_header = NULL;
00484 cpl_table *cd_align = NULL;
00485
00486
00487 int steps, xborder, window;
00488 bool DEBUG;
00489
00490
00491 const char *product_filename = NULL;
00492 bool blue;
00493 enum uves_chip chip;
00494 const char *raw_filename[2];
00495 int raw_index;
00496
00497 const char* PROCESS_CHIP=NULL;
00498
00499 check( uves_get_parameter(parameters, NULL, "uves", "debug",
00500 CPL_TYPE_BOOL, &DEBUG), "Could not read parameter");
00501
00502 check( uves_get_parameter(parameters, NULL, "uves", "process_chip", CPL_TYPE_STRING, &PROCESS_CHIP),
00503 "Could not read parameter");
00504 uves_string_toupper((char*)PROCESS_CHIP);
00505
00506 check( uves_get_parameter(parameters, NULL, make_str(UVES_CD_ALIGN_ID), "steps",
00507 CPL_TYPE_INT , &steps), "Could not read parameter");
00508 check( uves_get_parameter(parameters, NULL, make_str(UVES_CD_ALIGN_ID), "xborder",
00509 CPL_TYPE_INT , &xborder), "Could not read parameter");
00510 check( uves_get_parameter(parameters, NULL, make_str(UVES_CD_ALIGN_ID), "window",
00511 CPL_TYPE_INT , &window), "Could not read parameter");
00512
00513
00514 check( uves_load_cd_align(frames,
00515 &raw_filename[0],
00516 &raw_filename[1],
00517 raw_images[0],
00518 raw_images[1],
00519 raw_headers[0],
00520 raw_headers[1],
00521 rotated_headers[0],
00522 rotated_headers[1],
00523 &blue),
00524 "Error loading raw frame");
00525
00526 uves_msg("Using %s", raw_filename[0]);
00527 uves_msg("Using %s", raw_filename[1]);
00528
00529
00530 if (blue)
00531 {
00532 chip = UVES_CHIP_BLUE;
00533 }
00534 else
00535 {
00536 if (DEBUG)
00537 {
00538 int raw_index_l = uves_chip_get_index(UVES_CHIP_REDL);
00539 int raw_index_u = uves_chip_get_index(UVES_CHIP_REDU);
00540
00541 uves_msg("1. REDL average flux per pixel = %f ADU", avg_flux(raw_images[0][raw_index_l]));
00542 uves_msg("2. REDL average flux per pixel = %f ADU", avg_flux(raw_images[1][raw_index_l]));
00543
00544 uves_msg("1. REDU average flux per pixel = %f ADU", avg_flux(raw_images[0][raw_index_u]));
00545 uves_msg("2. REDU average flux per pixel = %f ADU", avg_flux(raw_images[1][raw_index_u]));
00546 }
00547
00548 chip = UVES_CHIP_REDL;
00549 }
00550
00551 raw_index = uves_chip_get_index(chip);
00552
00553 uves_msg("Processing %s chip",
00554 uves_chip_tostring_upper(chip));
00555
00556 check( cd_align = uves_cd_align_process(raw_images[0][raw_index],
00557 raw_images[1][raw_index],
00558 rotated_headers[0][raw_index],
00559 rotated_headers[1][raw_index],
00560 steps,
00561 xborder,
00562 window,
00563 DEBUG,
00564 chip),
00565 "Error during processing");
00566
00567 check( qclog[0] = cd_align_qclog(cd_align,
00568 raw_headers[0][raw_index],
00569 chip),
00570 "Could not compute QC");
00571
00572 product_header = uves_propertylist_new();
00573 product_filename = uves_cd_align_filename(chip);
00574 check( uves_frameset_insert(frames,
00575 cd_align,
00576 CPL_FRAME_GROUP_PRODUCT,
00577 CPL_FRAME_TYPE_TABLE,
00578 CPL_FRAME_LEVEL_FINAL,
00579 product_filename,
00580 UVES_CD_ALIGN_TABLE(blue),
00581 raw_headers[0][raw_index],
00582 product_header,
00583 NULL,
00584 parameters,
00585 make_str(UVES_CD_ALIGN_ID),
00586 PACKAGE "/" PACKAGE_VERSION,
00587 qclog,
00588 starttime, true,
00589 0),
00590 "Could not add CD align table %s to frameset", product_filename);
00591
00592 uves_msg("CD align table %s (%s) added to frameset",
00593 product_filename, UVES_CD_ALIGN_TABLE(blue));
00594
00595 cleanup:
00596 uves_free_image(&raw_images[0][0]);
00597 uves_free_image(&raw_images[0][1]);
00598 uves_free_image(&raw_images[1][0]);
00599 uves_free_image(&raw_images[1][1]);
00600 uves_free_propertylist(&raw_headers[0][0]);
00601 uves_free_propertylist(&raw_headers[0][1]);
00602 uves_free_propertylist(&raw_headers[1][0]);
00603 uves_free_propertylist(&raw_headers[1][1]);
00604 uves_free_propertylist(&rotated_headers[0][0]);
00605 uves_free_propertylist(&rotated_headers[0][1]);
00606 uves_free_propertylist(&rotated_headers[1][0]);
00607 uves_free_propertylist(&rotated_headers[1][1]);
00608
00609 uves_free_table(&qclog[0]);
00610 uves_free_string_const(&product_filename);
00611 uves_free_table(&cd_align);
00612 uves_free_propertylist(&product_header);
00613
00614 return;
00615 }
00616
00617