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