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