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