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
00120
00121
00122 #ifdef HAVE_CONFIG_H
00123 # include <config.h>
00124 #endif
00125
00126
00132
00136
00137
00138
00139
00140 #include <uves_merge.h>
00141
00142 #include <uves_pfits.h>
00143 #include <uves_utils.h>
00144 #include <uves_utils_wrappers.h>
00145 #include <uves_dump.h>
00146 #include <uves_dfs.h>
00147 #include <uves_error.h>
00148
00149 #include <cpl.h>
00150 #include <float.h>
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00187
00188
00189 cpl_image *
00190 uves_merge_orders(const cpl_image *spectrum,
00191 const cpl_image *spectrum_noise,
00192 const uves_propertylist *spectrum_header,
00193 merge_method m_method,
00194 int n_traces,
00195 uves_propertylist **merged_header,
00196 cpl_image **merged_noise)
00197 {
00198 cpl_image *merged = NULL;
00199
00200 const double *spectrum_data_double = NULL;
00201 const float *spectrum_data_float = NULL;
00202 const cpl_mask *spectrum_badmap = NULL;
00203 const cpl_binary *spectrum_bad = NULL;
00204
00205 const double *noise_data_double = NULL;
00206 const float *noise_data_float = NULL;
00207 const cpl_mask *noise_badmap = NULL;
00208 const cpl_binary *noise_bad = NULL;
00209 cpl_type type;
00210
00211 int nbins, ny, norders;
00212 double wavestep;
00213 int bin_min = 0, bin_max = 0;
00214 int total_bins;
00215 int order, trace;
00216
00217 passure( spectrum != NULL, " ");
00218 passure( spectrum_noise != NULL, " ");
00219 passure( spectrum_header != NULL, " ");
00220 passure( merged_header != NULL, " ");
00221 passure( merged_noise != NULL, " ");
00222
00223 assure( m_method == MERGE_OPTIMAL ||
00224 m_method == MERGE_SUM ||
00225 m_method == MERGE_NOAPPEND,
00226 CPL_ERROR_ILLEGAL_INPUT,
00227 "Unknown merge method: %d", m_method);
00228
00229 assure( cpl_image_get_type(spectrum) == CPL_TYPE_DOUBLE ||
00230 cpl_image_get_type(spectrum) == CPL_TYPE_FLOAT,
00231 CPL_ERROR_TYPE_MISMATCH,
00232 "Spectrum must have type double or float. It is '%s'",
00233 uves_tostring_cpl_type(cpl_image_get_type(spectrum)));
00234
00235 assure( cpl_image_get_type(spectrum_noise) == CPL_TYPE_DOUBLE ||
00236 cpl_image_get_type(spectrum_noise) == CPL_TYPE_FLOAT,
00237 CPL_ERROR_TYPE_MISMATCH,
00238 "Spectrum noise must have type double. It is '%s'",
00239 uves_tostring_cpl_type(cpl_image_get_type(spectrum_noise)));
00240
00241 assure( cpl_image_get_type(spectrum) ==
00242 cpl_image_get_type(spectrum_noise),
00243 CPL_ERROR_TYPE_MISMATCH,
00244 "Spectrum and spectrum noise must have same type. They are "
00245 "%s and %s, respectively",
00246 uves_tostring_cpl_type(cpl_image_get_type(spectrum)),
00247 uves_tostring_cpl_type(cpl_image_get_type(spectrum_noise)) );
00248
00249 type = cpl_image_get_type(spectrum);
00250
00251
00252 nbins = cpl_image_get_size_x(spectrum);
00253 ny = cpl_image_get_size_y(spectrum);
00254
00255 assure( cpl_image_get_size_x(spectrum_noise) == nbins &&
00256 cpl_image_get_size_y(spectrum_noise) == ny,
00257 CPL_ERROR_INCOMPATIBLE_INPUT,
00258 "Incompatible spectrum/noise image sizes: %dx%d vs. %dx%d",
00259 nbins, ny,
00260 cpl_image_get_size_x(spectrum_noise),
00261 cpl_image_get_size_y(spectrum_noise) );
00262
00263 assure( ny % n_traces == 0, CPL_ERROR_INCOMPATIBLE_INPUT,
00264 "Spectrum image height (%d) is not a multiple of "
00265 "the number of traces (%d). Confused, bailing out",
00266 ny, n_traces);
00267
00268 norders = ny / n_traces;
00269
00270 check( wavestep = uves_pfits_get_cdelt1(spectrum_header),
00271 "Error reading bin width");
00272
00273
00274
00275 if (type == CPL_TYPE_DOUBLE) {
00276 spectrum_data_double = cpl_image_get_data_double_const(spectrum);
00277 }
00278 else {
00279 spectrum_data_float = cpl_image_get_data_float_const(spectrum);
00280 }
00281 spectrum_badmap = cpl_image_get_bpm_const(spectrum);
00282 spectrum_bad = cpl_mask_get_data_const(spectrum_badmap);
00283
00284 if (type == CPL_TYPE_DOUBLE) {
00285 noise_data_double = cpl_image_get_data_double_const(spectrum_noise);
00286 }
00287 else {
00288 noise_data_float = cpl_image_get_data_float_const(spectrum_noise);
00289 }
00290 noise_badmap = cpl_image_get_bpm_const(spectrum_noise);
00291 noise_bad = cpl_mask_get_data_const(noise_badmap);
00292
00293
00294 for (order = 1; order <= norders; order++)
00295 {
00296 double wstart, wend;
00297 check( wstart = uves_pfits_get_wstart(spectrum_header, order),
00298 "Error reading start wavelength for order #%d", order);
00299
00300 check( wend = uves_pfits_get_wend(spectrum_header, order),
00301 "Error reading end wavelength for order #%d", order);
00302
00303 uves_msg_debug("Order #%d: wstart - wend = %f - %f wlu", order, wstart, wend);
00304
00305 if (order == 1)
00306 {
00307 bin_min = uves_round_double(wstart/wavestep);
00308 bin_max = uves_round_double(wend /wavestep);
00309 }
00310
00311 bin_min = uves_min_int(bin_min, uves_round_double(wstart/wavestep));
00312 bin_max = uves_max_int(bin_max, uves_round_double(wend /wavestep));
00313 }
00314
00315 total_bins = (bin_max - bin_min) + 1;
00316
00317 uves_msg_debug("Merging orders into %d bins covering wavelengths %.3f - %.3f wlu",
00318 total_bins, bin_min * wavestep, bin_max * wavestep);
00319
00320
00321 if(m_method == MERGE_NOAPPEND) {
00322 merged = cpl_image_new(total_bins, n_traces*norders, type);
00323 *merged_noise = cpl_image_new(total_bins, n_traces*norders, type);
00324 } else {
00325 merged = cpl_image_new(total_bins, n_traces, type);
00326 *merged_noise = cpl_image_new(total_bins, n_traces, type);
00327 }
00328 cpl_image_add_scalar(*merged_noise, -1.0);
00329
00330
00331 for (order = 1; order <= norders; order++)
00332 {
00333 double wstart, wend;
00334 int wstart_bin, wend_bin;
00335
00336
00337 check( wstart = uves_pfits_get_wstart(spectrum_header, order),
00338 "Error reading start wavelength for order #%d", order);
00339
00340 check( wend = uves_pfits_get_wend(spectrum_header, order),
00341 "Error reading end wavelength for order #%d", order);
00342
00343 wstart_bin = uves_round_double(wstart/wavestep);
00344 wend_bin = uves_round_double(wend/wavestep);
00345
00346
00347 int bin_min_ord = uves_round_double(wstart/wavestep);
00348 int bin_max_ord = uves_round_double(wend /wavestep);
00349 int nbins_ord = (bin_max_ord - bin_min_ord) + 1;
00350 cpl_image* merged_ord=NULL;
00351 cpl_image * noise_ord=NULL;
00352
00353 if(m_method == MERGE_NOAPPEND) {
00354 merged_ord = cpl_image_new(nbins_ord, n_traces, type);
00355 noise_ord = cpl_image_new(nbins_ord, n_traces, type);
00356 }
00357
00358
00359
00360
00361 for (trace = 1; trace <= n_traces; trace++)
00362 {
00363 int merged_row = 0;
00364 int spectrum_row = (order - 1)*n_traces + trace;
00365 if(m_method == MERGE_NOAPPEND) {
00366 merged_row = (order - 1)*n_traces + trace;
00367 } else {
00368 merged_row = trace;
00369
00370 }
00371 int rel_bin;
00372
00373 for (rel_bin = 1; rel_bin <= wend_bin - wstart_bin + 1; rel_bin++)
00374 {
00375 double flux, noise;
00376 double current_flux, new_flux;
00377 double current_noise, new_noise;
00378 double weight;
00379 int pis_rejected, noise_rejected;
00380
00381
00382 int merged_bin = (wstart_bin - bin_min) + rel_bin;
00383 int merged_bin_ord = rel_bin;
00384
00385 passure(1 <= merged_bin && merged_bin <= total_bins,
00386 "%d %d %d", rel_bin, merged_bin, total_bins);
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396 if (type == CPL_TYPE_DOUBLE) {
00397 flux = spectrum_data_double[(rel_bin-1) + (spectrum_row-1) * nbins];
00398 noise = noise_data_double [(rel_bin-1) + (spectrum_row-1) * nbins];
00399
00400 }
00401 else {
00402 flux = spectrum_data_float[(rel_bin-1) + (spectrum_row-1) * nbins];
00403 noise = noise_data_float [(rel_bin-1) + (spectrum_row-1) * nbins];
00404 }
00405
00406 pis_rejected = spectrum_bad[(rel_bin-1) + (spectrum_row-1) * nbins];
00407 noise_rejected = noise_bad [(rel_bin-1) + (spectrum_row-1) * nbins];
00408
00409 if (!pis_rejected && !noise_rejected)
00410 {
00411
00412 if(m_method == MERGE_NOAPPEND) {
00413 check(( current_flux = cpl_image_get(merged,
00414 merged_bin,
00415 merged_row,
00416 &pis_rejected),
00417 current_noise = cpl_image_get(*merged_noise,
00418 merged_bin,
00419 merged_row,
00420 &pis_rejected)),
00421 "Error reading merged spetrum");
00422 } else {
00423 check(( current_flux = cpl_image_get(
00424 merged , merged_bin, trace, &pis_rejected),
00425 current_noise = cpl_image_get(
00426 *merged_noise, merged_bin, trace, &pis_rejected)),
00427 "Error reading merged spetrum");
00428 }
00429 weight = 1/(noise*noise);
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 if (current_noise > 0)
00451 {
00452 if (m_method == MERGE_OPTIMAL)
00453 {
00454 new_noise = 1/(current_noise*current_noise);
00455 new_noise += weight;
00456 new_noise = 1/sqrt(new_noise);
00457 }
00458 else if (m_method == MERGE_SUM)
00459 {
00460 new_noise = sqrt(current_noise*current_noise
00461 + noise*noise);
00462 }
00463 else if (m_method == MERGE_NOAPPEND)
00464 {
00465 new_noise = current_noise;
00466 }
00467 else
00468 {
00469
00470 passure( false, "%d", m_method);
00471 }
00472 }
00473 else
00474 {
00475
00476 new_noise = noise;
00477 }
00478
00479 if (current_noise > 0)
00480 {
00481 if (m_method == MERGE_OPTIMAL)
00482 {
00483 new_flux = (current_flux /
00484 (current_noise*current_noise)
00485 + flux * weight) *
00486 (new_noise*new_noise);
00487 }
00488 else if (m_method == MERGE_SUM)
00489 {
00490 new_flux = current_flux + flux;
00491 }
00492 else if (m_method == MERGE_NOAPPEND)
00493 {
00494 new_flux = flux;
00495 }
00496 else
00497 {
00498
00499 passure( false, "%d", m_method);
00500 }
00501 }
00502 else
00503 {
00504 new_flux = flux;
00505 }
00506
00507 if(m_method == MERGE_NOAPPEND) {
00508
00509
00510
00511
00512
00513
00514 check( cpl_image_set(
00515 merged,
00516 merged_bin,
00517 merged_row,
00518 new_flux),
00519 "Error updating merged spectrum");
00520
00521 check( cpl_image_set(
00522 *merged_noise,
00523 merged_bin,
00524 merged_row,
00525 new_noise),
00526 "Error updating weights");
00527
00528
00529 check( cpl_image_set(
00530 merged_ord,
00531 merged_bin_ord,
00532 trace,
00533 new_flux),
00534 "Error updating merged spectrum");
00535
00536 check( cpl_image_set(
00537 merged_ord,
00538 merged_bin_ord,
00539 trace,
00540 new_noise),
00541 "Error updating merged spectrum");
00542
00543
00544 } else {
00545 check( cpl_image_set(
00546 merged , merged_bin, trace, new_flux),
00547 "Error updating merged spectrum");
00548 check( cpl_image_set(
00549 *merged_noise, merged_bin, trace, new_noise),
00550 "Error updating weights");
00551 }
00552
00553
00554
00555
00556
00557 }
00558
00559 }
00560
00561 }
00562
00563
00564 if (merged_header != NULL)
00565 {
00566 check( *merged_header = uves_initialize_image_header(
00567 "WAVELENGTH", (n_traces > 1) ? "PIXEL" : " ", "FLUX",
00568 bin_min_ord * wavestep, 1.0,
00569 1.0, 1.0,
00570 wavestep, 1.0),
00571 "Error initializing merged spectrum header");
00572 }
00573 if(m_method == MERGE_NOAPPEND) {
00574
00575 uves_save_image(merged_ord,uves_sprintf("mer_%4.4d.fits",order),
00576 *merged_header,true, true);
00577 uves_save_image(merged_ord,uves_sprintf("sig_%4.4d.fits",order),
00578 *merged_header,true, true);
00579 uves_free_image(&merged_ord);
00580 uves_free_image(&noise_ord);
00581 uves_free_propertylist(merged_header);
00582 }
00583
00584 }
00585
00586
00587
00588
00589
00590 check( cpl_image_threshold(*merged_noise,
00591 0, DBL_MAX,
00592 1, 1),
00593 "Error setting undefined noise");
00594
00595
00596 if (merged_header != NULL)
00597 {
00598 check( *merged_header = uves_initialize_image_header(
00599 "WAVELENGTH", (n_traces > 1) ? "PIXEL" : " ", "FLUX",
00600 bin_min * wavestep, 1.0,
00601 1.0, 1.0,
00602 wavestep, 1.0),
00603 "Error initializing merged spectrum header");
00604 }
00605
00606
00607 cleanup:
00608 return merged;
00609 }
00610
00611
00621
00622 merge_method
00623 uves_get_merge_method(const cpl_parameterlist *parameters,
00624 const char *context,
00625 const char *subcontext)
00626 {
00627 const char *mm = "";
00628 merge_method result = 0;
00629
00630 check( uves_get_parameter(parameters, context, subcontext, "merge", CPL_TYPE_STRING, &mm),
00631 "Could not read parameter");
00632
00633 if (strcmp(mm, "optimal") == 0) result = MERGE_OPTIMAL;
00634 else if (strcmp(mm, "sum" ) == 0) result = MERGE_SUM;
00635 else if (strcmp(mm, "noappend") == 0) result = MERGE_NOAPPEND;
00636 else
00637 {
00638 assure(false, CPL_ERROR_ILLEGAL_INPUT, "No such merging method: '%s'", mm);
00639 }
00640
00641 cleanup:
00642 return result;
00643 }
00644
00645