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