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