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
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00117
00118
00119 #ifdef HAVE_CONFIG_H
00120 # include <config.h>
00121 #endif
00122
00123
00124
00125
00126
00127 #include <uves_response_efficiency.h>
00128 #include <uves_response_utils.h>
00129 #include <uves_reduce.h>
00130 #include <uves_reduce_utils.h>
00131 #include <uves_dfs.h>
00132 #include <uves_pfits.h>
00133 #include <uves_wavecal_utils.h>
00134 #include <uves_utils_polynomial.h>
00135 #include <uves_utils.h>
00136 #include <uves_utils_wrappers.h>
00137 #include <uves_utils_cpl.h>
00138 #include <uves.h>
00139 #include <uves_error.h>
00140 #include <uves_msg.h>
00141
00142 #include <irplib_access.h>
00143 #include <cpl.h>
00144
00145 #include <stdbool.h>
00146
00147
00148
00149
00150 #define H_BAR 6.626068e-34
00151 #define PRIMARY_DIA 818
00152 #define OBSTR_DIA 140
00153 #define TELESCOPE_EFFECTIVE_AREA \
00154 (M_PI * (PRIMARY_DIA * PRIMARY_DIA - OBSTR_DIA * OBSTR_DIA) / 4.0)
00155
00184
00185 cpl_error_code
00186 uves_response_efficiency(const cpl_image *raw_image,
00187 const uves_propertylist *raw_header,
00188 const uves_propertylist *rotated_header,
00189 const cpl_image *master_bias,
00190 const cpl_image *master_dark,
00191 const uves_propertylist *mdark_header,
00192 const cpl_table *ordertable,
00193 const polynomial *order_locations,
00194 const cpl_table *linetable[3],
00195 const uves_propertylist *linetable_header[3],
00196 const polynomial *dispersion_relation[3],
00197 const cpl_table *flux_table,
00198 const cpl_table *atm_extinction,
00199 enum uves_chip chip,
00200 bool DEBUG,
00201 const cpl_parameterlist *parameters,
00202
00203 double PACCURACY,
00204
00205 cpl_table **efficiency,
00206 cpl_table **blaze_efficiency)
00207 {
00208 cpl_image *background = NULL;
00209 cpl_image *rebinned_spectrum = NULL;
00210 cpl_image *rebinned_noise = NULL;
00211 cpl_image *merged_sky = NULL;
00212 cpl_image *merged_spectrum = NULL;
00213 cpl_image *merged_noise = NULL;
00214 cpl_image *reduced_spectrum = NULL;
00215 cpl_image *reduced_noise = NULL;
00216 cpl_image *reduced_rebinned = NULL;
00217 cpl_image *reduced_rebinned_noise = NULL;
00218 uves_propertylist *rebinned_header = NULL;
00219 uves_propertylist *reduced_header = NULL;
00220 polynomial *disprel_1d = NULL;
00221
00222 cpl_image *response_orders = NULL;
00223 cpl_image *efficiency_spectrum = NULL;
00224 cpl_table *central_efficiency = NULL;
00225
00226 cpl_table *info_tbl = NULL;
00227
00228
00229
00230
00231 char *ref_obj_id = NULL;
00232
00233 double wavestep;
00234 double extraction_slit;
00235
00236
00237
00238
00239
00240
00241 {
00242 double smooth_step;
00243
00244
00245 check( uves_get_parameter(parameters, NULL,
00246 make_str(UVES_RESPONSE_ID) ".efficiency", "reduce.rebin.wavestep",
00247 CPL_TYPE_DOUBLE, &wavestep),
00248 "Error getting resampling step size");
00249
00250 check( smooth_step = cpl_table_get_column_mean(linetable[1], LINETAB_PIXELSIZE),
00251 "Error reading mean pixelsize");
00252
00253 smooth_step = 10*2*smooth_step/3;
00254
00255
00256
00257
00258
00259 check( uves_set_parameter((cpl_parameterlist *) parameters,
00260 make_str(UVES_RESPONSE_ID) ".efficiency", "reduce.rebin.wavestep",
00261 CPL_TYPE_DOUBLE, &smooth_step),
00262 "Error setting resampling step size");
00263 }
00264
00265 check( uves_reduce(raw_image,
00266 raw_header,
00267 rotated_header,
00268 master_bias,
00269 master_dark,
00270 mdark_header,
00271 NULL,
00272 NULL,
00273 ordertable,
00274 order_locations,
00275 linetable,
00276 linetable_header,
00277 dispersion_relation,
00278 chip,
00279 DEBUG,
00280 parameters,
00281 make_str(UVES_RESPONSE_ID) ".efficiency",
00282
00283 NULL,
00284 NULL,
00285 NULL,
00286 NULL,
00287 &background,
00288 NULL,
00289 NULL,
00290 NULL,
00291 NULL,
00292
00293 &merged_sky,
00294 &rebinned_spectrum,
00295 &rebinned_noise,
00296 &rebinned_header,
00297 &merged_spectrum,
00298 &merged_noise,
00299 &reduced_header,
00300 &reduced_rebinned,
00301 &reduced_rebinned_noise,
00302 &reduced_spectrum,
00303 &reduced_noise,
00304 &info_tbl,
00305 &extraction_slit,
00306 NULL),
00307 "Could not reduce frame");
00308
00309
00310 {
00311 uves_msg_debug("Resetting parameter wavestep = %e", wavestep);
00312
00313
00314 check( uves_set_parameter((cpl_parameterlist *) parameters,
00315 make_str(UVES_RESPONSE_ID) ".efficiency", "reduce.rebin.wavestep",
00316 CPL_TYPE_DOUBLE, &wavestep),
00317 "Error resetting resampling step size");
00318 }
00319
00320
00321
00322 if (DEBUG)
00323 {
00324
00325 check( uves_save_image_local("Reduced spectrum (2d)", "reduced",
00326 reduced_rebinned, chip, -1, -1, rebinned_header),
00327 "Error saving reduced spectrum (2d)");
00328
00329 check( uves_save_image_local("Reduced spectrum (2d) noise", "errreduced",
00330 reduced_rebinned_noise, chip, -1, -1, rebinned_header),
00331 "Error saving reduced spectrum (2d) noise");
00332
00333 check( uves_save_image_local("Reduced spectrum", "merged",
00334 reduced_spectrum, chip, -1, -1, reduced_header),
00335 "Error saving reduced spectrum");
00336
00337 check( uves_save_image_local("Reduced spectrum noise", "errmerged",
00338 reduced_noise, chip, -1, -1, reduced_header),
00339 "Error saving reduced spectrum noise");
00340 }
00341
00342 uves_msg("Dividing by catalogue flux");
00343
00344
00345
00346 check( response_orders = uves_calculate_response(reduced_rebinned, rebinned_header,
00347 flux_table,
00348 raw_header, PACCURACY,
00349 false,
00350 &ref_obj_id),
00351 "Could not calculate response curve");
00352
00353 if (DEBUG)
00354 {
00355 check( uves_save_image_local("2d response curve", "resp",
00356 response_orders, chip, -1, -1, rebinned_header),
00357 "Error saving 2d response curve");
00358 }
00359
00360
00361
00362
00363 {
00364 int n_traces = cpl_image_get_size_y(merged_spectrum);
00365
00366 assure( n_traces == 1, CPL_ERROR_ILLEGAL_INPUT,
00367 "2d extraction/reduction not supported");
00368
00369 check( efficiency_spectrum = uves_normalize_spectrum(response_orders, NULL,
00370
00371 rebinned_header,
00372 raw_header,
00373 n_traces,
00374 chip,
00375 atm_extinction,
00376 false,
00377 NULL),
00378 "Could not normalize spectrum");
00379 }
00380
00381
00382
00383
00384 uves_msg("Applying 7x1 median filter");
00385 check( uves_filter_image_median(&efficiency_spectrum, 3, 0, false),
00386 "Error applying median filter");
00387
00388
00389 uves_msg("Calculating quantum detection efficiency");
00390
00391 {
00392 int nx, nbins, norders, order;
00393 int first_abs_order, last_abs_order, abs_order;
00394 double dlambda;
00395 double average_noise;
00396 int row = 0;
00397
00398 double *efficiency_data;
00399 double *reduced_noise_data;
00400
00401 efficiency_data = irplib_image_get_data_double(efficiency_spectrum);
00402 reduced_noise_data = irplib_image_get_data_double(reduced_rebinned_noise);
00403
00404 nx = cpl_image_get_size_x(raw_image);
00405 nbins = cpl_image_get_size_x(efficiency_spectrum);
00406 norders = cpl_image_get_size_y(efficiency_spectrum);
00407
00408 *efficiency = cpl_table_new(nbins * norders);
00409 cpl_table_new_column(*efficiency, "Wave", CPL_TYPE_DOUBLE);
00410 cpl_table_new_column(*efficiency, "Eff", CPL_TYPE_DOUBLE);
00411 cpl_table_new_column(*efficiency, "Binsize", CPL_TYPE_DOUBLE);
00412 cpl_table_new_column(*efficiency, "Order", CPL_TYPE_INT);
00413 row = 0;
00414
00415 check( first_abs_order = uves_pfits_get_firstabsorder(linetable_header[1]),
00416 "Could not read order numbers from line table header");
00417 check( last_abs_order = uves_pfits_get_lastabsorder (linetable_header[1]),
00418 "Could not read order numbers from line table header");
00419
00420 check( dlambda = uves_pfits_get_cdelt1(rebinned_header),
00421 "Error reading bin width from header");
00422
00423 check( average_noise = cpl_image_get_median(reduced_rebinned_noise),
00424 "Error reading median noise level");
00425
00426 for (order = 1; order <= norders; order++)
00427 {
00428 double lambda_start, lambda, lambda_end;
00429 double x;
00430 int bin;
00431
00432 abs_order = uves_absolute_order(first_abs_order, last_abs_order, order);
00433
00434 check( lambda_start = uves_pfits_get_wstart(rebinned_header, order),
00435 "Error reading start wavelength from header");
00436
00437 check( lambda_end = uves_pfits_get_wend(rebinned_header, order),
00438 "Error reading end wavelength from header");
00439
00440
00441
00442
00443
00444
00445
00446 uves_polynomial_delete(&disprel_1d);
00447 check( disprel_1d = uves_polynomial_collapse(dispersion_relation[1],
00448 2,
00449 abs_order),
00450 "Error getting 1d dispersion relation for absolute order #%d", abs_order);
00451
00452 x = 1;
00453 for (lambda = lambda_start, bin = 1;
00454 lambda < lambda_end + 0.5 * dlambda && bin <= nbins;
00455 bin++, lambda += dlambda)
00456 {
00457 double flux;
00458 double dldx;
00459 double noise;
00460
00461
00462
00463
00464
00465
00466 flux = efficiency_data [(bin-1) + (order-1) * nbins];
00467 noise = reduced_noise_data[(bin-1) + (order-1) * nbins];
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485 check( x = uves_polynomial_solve_1d(
00486 disprel_1d,
00487 abs_order * lambda,
00488 x,
00489 1),
00490 "Could not solve dispersion relation for x "
00491 "at (m, lambda) = (%d, %f)", abs_order, lambda);
00492
00493
00494
00495
00496
00497
00498 check( dldx = fabs(uves_polynomial_derivative_2d(
00499 dispersion_relation[1],
00500 x,
00501 abs_order, 1) / abs_order),
00502 "Could not evaluate dispersion relation");
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 flux = flux * 1e16 * 1e17 * H_BAR * SPEED_OF_LIGHT /
00519 (dldx * lambda * TELESCOPE_EFFECTIVE_AREA);
00520
00521
00522
00523
00524
00525
00526 if (noise < 3*average_noise)
00527 {
00528 check(( cpl_table_set_double(*efficiency, "Wave", row, lambda),
00529 cpl_table_set_double(*efficiency, "Eff", row, flux),
00530 cpl_table_set_double(*efficiency, "Binsize", row, dldx),
00531 cpl_table_set_int (*efficiency, "Order", row, order),
00532 row++),
00533 "Error updating efficiency table row %d", row);
00534 }
00535 }
00536 }
00537
00538
00539 check( cpl_table_set_size(*efficiency, row),
00540 "Error setting size of efficiency table to %d rows", row);
00541
00542
00543
00544 *blaze_efficiency = cpl_table_new(norders);
00545 cpl_table_new_column(*blaze_efficiency, "Order", CPL_TYPE_INT);
00546 cpl_table_new_column(*blaze_efficiency, "Wave" , CPL_TYPE_DOUBLE);
00547 cpl_table_new_column(*blaze_efficiency, "Eff" , CPL_TYPE_DOUBLE);
00548 row = 0;
00549
00550 for (order = 1; order <= norders; order++)
00551 {
00552 double lambda_min;
00553 double lambda_central_min;
00554 double lambda_central;
00555 double lambda_central_max;
00556 double lambda_max;
00557 double top_efficiency;
00558
00559 abs_order = uves_absolute_order(first_abs_order, last_abs_order, order);
00560
00561
00562 check( lambda_min = uves_pfits_get_wstart(rebinned_header, order),
00563 "Error reading bin width from header");
00564
00565 check( lambda_max = uves_pfits_get_wend(rebinned_header, order),
00566 "Error reading bin width from header");
00567
00568 lambda_central_min = lambda_min + 0.4 * (lambda_max - lambda_min);
00569 lambda_central = lambda_min + 0.5 * (lambda_max - lambda_min);
00570 lambda_central_max = lambda_min + 0.6 * (lambda_max - lambda_min);
00571
00572
00573
00574 cpl_table_select_all(*efficiency);
00575 cpl_table_and_selected_int (*efficiency, "Order",
00576 CPL_EQUAL_TO , order);
00577 cpl_table_and_selected_double(*efficiency, "Wave" ,
00578 CPL_GREATER_THAN, lambda_central_min);
00579 cpl_table_and_selected_double(*efficiency, "Wave" ,
00580 CPL_LESS_THAN , lambda_central_max);
00581
00582 uves_msg_debug("%d bins in central 20 %% range of order #%d",
00583 cpl_table_count_selected(*efficiency), order);
00584
00585 if ( cpl_table_count_selected(*efficiency) > 0)
00586 {
00587 uves_free_table(¢ral_efficiency);
00588 central_efficiency = cpl_table_extract_selected(*efficiency);
00589
00590
00591 uves_sort_table_1(central_efficiency, "Eff", false);
00592
00593 top_efficiency = cpl_table_get_double(
00594 central_efficiency, "Eff",
00595 (int) (0.9 * cpl_table_get_nrow(central_efficiency)), NULL);
00596 }
00597 else
00598 {
00599 uves_msg_debug("No wavelength bins in central 20%% range of order #%d",
00600 order);
00601 top_efficiency = 0;
00602 }
00603
00604 uves_msg("Efficiency(lambda = %.2f A) = %.2f%%",
00605 lambda_central, top_efficiency*100);
00606
00607 check(( cpl_table_set_int (*blaze_efficiency, "Order", row, order),
00608 cpl_table_set_double(*blaze_efficiency, "Wave" , row, lambda_central),
00609 cpl_table_set_double(*blaze_efficiency, "Eff" , row, top_efficiency),
00610 row++),
00611 "Error updating blaze efficiency table");
00612 }
00613 }
00614
00615 cleanup:
00616 uves_free_image(&background);
00617 uves_free_image(&rebinned_spectrum);
00618 uves_free_image(&rebinned_noise);
00619 uves_free_image(&merged_sky);
00620 uves_free_image(&merged_spectrum);
00621 uves_free_image(&merged_noise);
00622 uves_free_image(&reduced_spectrum);
00623 uves_free_image(&reduced_noise);
00624 uves_free_image(&reduced_rebinned);
00625 uves_free_image(&reduced_rebinned_noise);
00626 uves_free_propertylist(&reduced_header);
00627 uves_free_propertylist(&rebinned_header);
00628 uves_polynomial_delete(&disprel_1d);
00629
00630 uves_free_image(&response_orders);
00631 uves_free_image(&efficiency_spectrum);
00632 uves_free_table(¢ral_efficiency);
00633 uves_free_table(&info_tbl);
00634
00635 cpl_free(ref_obj_id);
00636
00637 if (cpl_error_get_code() != CPL_ERROR_NONE)
00638 {
00639 uves_free_table(efficiency);
00640 uves_free_table(blaze_efficiency);
00641 }
00642
00643 return cpl_error_get_code();
00644 }