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