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