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
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 #ifdef HAVE_CONFIG_H
00160 # include <config.h>
00161 #endif
00162
00163
00169
00173
00174
00175
00176
00177 #include <uves_merge.h>
00178
00179 #include <uves_pfits.h>
00180 #include <uves_utils.h>
00181 #include <uves_utils_wrappers.h>
00182 #include <uves_dump.h>
00183 #include <uves_dfs.h>
00184 #include <uves_error.h>
00185
00186 #include <cpl.h>
00187 #include <float.h>
00188 #include <string.h>
00189
00190
00191
00192
00193
00194
00195
00196
00197
00224
00225
00226 cpl_image *
00227 uves_merge_orders(const cpl_image *spectrum,
00228 const cpl_image *spectrum_noise,
00229 const uves_propertylist *spectrum_header,
00230 merge_method m_method,
00231 int n_traces,
00232 uves_propertylist **merged_header,
00233 const double delt1,
00234 const double delt2,
00235 enum uves_chip chip,
00236 cpl_image **merged_noise)
00237 {
00238 cpl_image *merged = NULL;
00239
00240 const double *spectrum_data_double = NULL;
00241 const float *spectrum_data_float = NULL;
00242 const cpl_mask *spectrum_badmap = NULL;
00243 const cpl_binary *spectrum_bad = NULL;
00244
00245 const double *noise_data_double = NULL;
00246 const float *noise_data_float = NULL;
00247 const cpl_mask *noise_badmap = NULL;
00248 const cpl_binary *noise_bad = NULL;
00249 cpl_type type;
00250
00251 int nbins, ny, norders;
00252 double wavestep;
00253 int bin_min = 0, bin_max = 0;
00254 int total_bins;
00255 int order, trace;
00256 int spectrum_sx=0;
00257 int spectrum_sy=0;
00258 double delt1_bin=0;
00259 double delt2_bin=0;
00260 char* filename=NULL;
00261
00262 cpl_vector* image_1d=NULL;
00263 uves_propertylist* hext=NULL;
00264
00265 passure( spectrum != NULL, " ");
00266 passure( spectrum_noise != NULL, " ");
00267 passure( spectrum_header != NULL, " ");
00268 passure( merged_header != NULL, " ");
00269 passure( merged_noise != NULL, " ");
00270
00271 assure( m_method == MERGE_OPTIMAL ||
00272 m_method == MERGE_SUM ||
00273 m_method == MERGE_NOAPPEND,
00274 CPL_ERROR_ILLEGAL_INPUT,
00275 "Unknown merge method: %d", m_method);
00276
00277 assure( cpl_image_get_type(spectrum) == CPL_TYPE_DOUBLE ||
00278 cpl_image_get_type(spectrum) == CPL_TYPE_FLOAT,
00279 CPL_ERROR_TYPE_MISMATCH,
00280 "Spectrum must have type double or float. It is '%s'",
00281 uves_tostring_cpl_type(cpl_image_get_type(spectrum)));
00282
00283 assure( cpl_image_get_type(spectrum_noise) == CPL_TYPE_DOUBLE ||
00284 cpl_image_get_type(spectrum_noise) == CPL_TYPE_FLOAT,
00285 CPL_ERROR_TYPE_MISMATCH,
00286 "Spectrum noise must have type double. It is '%s'",
00287 uves_tostring_cpl_type(cpl_image_get_type(spectrum_noise)));
00288
00289 assure( cpl_image_get_type(spectrum) ==
00290 cpl_image_get_type(spectrum_noise),
00291 CPL_ERROR_TYPE_MISMATCH,
00292 "Spectrum and spectrum noise must have same type. They are "
00293 "%s and %s, respectively",
00294 uves_tostring_cpl_type(cpl_image_get_type(spectrum)),
00295 uves_tostring_cpl_type(cpl_image_get_type(spectrum_noise)) );
00296
00297 type = cpl_image_get_type(spectrum);
00298
00299
00300 nbins = cpl_image_get_size_x(spectrum);
00301 ny = cpl_image_get_size_y(spectrum);
00302
00303 assure( cpl_image_get_size_x(spectrum_noise) == nbins &&
00304 cpl_image_get_size_y(spectrum_noise) == ny,
00305 CPL_ERROR_INCOMPATIBLE_INPUT,
00306 "Incompatible spectrum/noise image sizes: %dx%d vs. %dx%d",
00307 nbins, ny,
00308 cpl_image_get_size_x(spectrum_noise),
00309 cpl_image_get_size_y(spectrum_noise) );
00310
00311 assure( ny % n_traces == 0, CPL_ERROR_INCOMPATIBLE_INPUT,
00312 "Spectrum image height (%d) is not a multiple of "
00313 "the number of traces (%d). Confused, bailing out",
00314 ny, n_traces);
00315
00316 norders = ny / n_traces;
00317
00318 check( wavestep = uves_pfits_get_cdelt1(spectrum_header),
00319 "Error reading bin width");
00320
00321
00322
00323 if (type == CPL_TYPE_DOUBLE) {
00324 spectrum_data_double = cpl_image_get_data_double_const(spectrum);
00325 }
00326 else {
00327 spectrum_data_float = cpl_image_get_data_float_const(spectrum);
00328 }
00329
00330 spectrum_sx=cpl_image_get_size_x(spectrum);
00331 spectrum_sy=cpl_image_get_size_y(spectrum);
00332
00333 spectrum_badmap = cpl_image_get_bpm_const(spectrum);
00334 spectrum_bad = cpl_mask_get_data_const(spectrum_badmap);
00335
00336 if (type == CPL_TYPE_DOUBLE) {
00337 noise_data_double = cpl_image_get_data_double_const(spectrum_noise);
00338 }
00339 else {
00340 noise_data_float = cpl_image_get_data_float_const(spectrum_noise);
00341 }
00342 noise_badmap = cpl_image_get_bpm_const(spectrum_noise);
00343 noise_bad = cpl_mask_get_data_const(noise_badmap);
00344 uves_msg("delt1=%f delt2=%f",delt1,delt2);
00345
00346 for (order = 1; order <= norders; order++)
00347 {
00348 double wstart, wend;
00349 check( wstart = uves_pfits_get_wstart(spectrum_header, order),
00350 "Error reading start wavelength for order #%d", order);
00351
00352 check( wend = uves_pfits_get_wend(spectrum_header, order),
00353 "Error reading end wavelength for order #%d", order);
00354
00355 uves_msg_debug("Order #%d: wstart - wend = %f - %f wlu", order, wstart, wend);
00356
00357
00358
00359
00360 if (order == 1)
00361 {
00362 bin_min = uves_round_double(wstart/wavestep);
00363 bin_max = uves_round_double(wend /wavestep);
00364 }
00365
00366 bin_min = uves_min_int(bin_min, uves_round_double(wstart/wavestep));
00367 bin_max = uves_max_int(bin_max, uves_round_double(wend /wavestep));
00368 }
00369 total_bins = (bin_max - bin_min) + 1;
00370
00371 uves_msg_debug("Merging orders into %d bins covering wavelengths %.3f - %.3f wlu",
00372 total_bins, bin_min * wavestep, bin_max * wavestep);
00373
00374
00375 if(m_method == MERGE_NOAPPEND) {
00376 merged = cpl_image_new(total_bins, n_traces*norders, type);
00377 *merged_noise = cpl_image_new(total_bins, n_traces*norders, type);
00378 } else {
00379 merged = cpl_image_new(total_bins, n_traces, type);
00380 *merged_noise = cpl_image_new(total_bins, n_traces, type);
00381 }
00382 cpl_image_add_scalar(*merged_noise, -1.0);
00383
00384
00385
00386 for (order = 1; order <= norders; order++)
00387 {
00388 double wstart, wend;
00389 int wstart_bin, wend_bin;
00390
00391
00392
00393 check( wstart = uves_pfits_get_wstart(spectrum_header, order),
00394 "Error reading start wavelength for order #%d", order);
00395
00396 check( wend = uves_pfits_get_wend(spectrum_header, order),
00397 "Error reading end wavelength for order #%d", order);
00398
00399
00400
00401
00402 wstart_bin = uves_round_double(wstart/wavestep);
00403 wend_bin = uves_round_double(wend/wavestep);
00404 delt1_bin = uves_round_double(delt1/wavestep);
00405 delt2_bin = uves_round_double(delt2/wavestep);
00406
00407
00408 int bin_min_ord = uves_round_double(wstart/wavestep);
00409 int bin_max_ord = uves_round_double(wend /wavestep);
00410 int nbins_ord = (bin_max_ord - bin_min_ord) + 1;
00411 cpl_image* merged_ord=NULL;
00412 cpl_image * noise_ord=NULL;
00413
00414 if(m_method == MERGE_NOAPPEND) {
00415 merged_ord = cpl_image_new(nbins_ord, n_traces, type);
00416 noise_ord = cpl_image_new(nbins_ord, n_traces, type);
00417 }
00418
00419
00420
00421
00422
00423
00424
00425
00426 for (trace = 1; trace <= n_traces; trace++)
00427 {
00428 int merged_row = 0;
00429 int spectrum_row = (order - 1)*n_traces + trace;
00430 if(m_method == MERGE_NOAPPEND) {
00431 merged_row = (order - 1)*n_traces + trace;
00432 } else {
00433 merged_row = trace;
00434
00435 }
00436 int rel_bin;
00437
00438 for (rel_bin = 1+delt1_bin;
00439 (rel_bin <= wend_bin - wstart_bin + 1-delt2_bin) &&
00440 (rel_bin <(spectrum_sx*spectrum_sy+1-(spectrum_row-1)*nbins));
00441 rel_bin++)
00442 {
00443 double flux, noise;
00444 double current_flux, new_flux;
00445 double current_noise, new_noise;
00446 double weight;
00447 int pis_rejected, noise_rejected;
00448
00449
00450 int merged_bin = (wstart_bin - bin_min) + rel_bin;
00451 int merged_bin_ord = rel_bin;
00452
00453 passure(1 <= merged_bin && merged_bin <= total_bins,
00454 "%d %d %d", rel_bin, merged_bin, total_bins);
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464 if (type == CPL_TYPE_DOUBLE) {
00465 flux = spectrum_data_double[(rel_bin-1) + (spectrum_row-1) * nbins];
00466 noise = noise_data_double [(rel_bin-1) + (spectrum_row-1) * nbins];
00467
00468 }
00469 else {
00470 flux = spectrum_data_float[(rel_bin-1) + (spectrum_row-1) * nbins];
00471 noise = noise_data_float [(rel_bin-1) + (spectrum_row-1) * nbins];
00472 }
00473
00474 pis_rejected = spectrum_bad[(rel_bin-1) + (spectrum_row-1) * nbins];
00475 noise_rejected = noise_bad [(rel_bin-1) + (spectrum_row-1) * nbins];
00476
00477 if (!pis_rejected && !noise_rejected)
00478 {
00479
00480 if(m_method == MERGE_NOAPPEND) {
00481 check(( current_flux = cpl_image_get(merged,
00482 merged_bin,
00483 merged_row,
00484 &pis_rejected),
00485 current_noise = cpl_image_get(*merged_noise,
00486 merged_bin,
00487 merged_row,
00488 &pis_rejected)),
00489 "Error reading merged spetrum");
00490 } else {
00491 check(( current_flux = cpl_image_get(
00492 merged , merged_bin, trace, &pis_rejected),
00493 current_noise = cpl_image_get(
00494 *merged_noise, merged_bin, trace, &pis_rejected)),
00495 "Error reading merged spetrum");
00496 }
00497 weight = 1/(noise*noise);
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 if (current_noise > 0)
00519 {
00520 if (m_method == MERGE_OPTIMAL)
00521 {
00522 new_noise = 1/(current_noise*current_noise);
00523 new_noise += weight;
00524 new_noise = 1/sqrt(new_noise);
00525 }
00526 else if (m_method == MERGE_SUM)
00527 {
00528 new_noise = sqrt(current_noise*current_noise
00529 + noise*noise);
00530 }
00531 else if (m_method == MERGE_NOAPPEND)
00532 {
00533 new_noise = current_noise;
00534 }
00535 else
00536 {
00537
00538 passure( false, "%d", m_method);
00539 }
00540 }
00541 else
00542 {
00543
00544 new_noise = noise;
00545 }
00546
00547 if (current_noise > 0)
00548 {
00549 if (m_method == MERGE_OPTIMAL)
00550 {
00551 new_flux = (current_flux /
00552 (current_noise*current_noise)
00553 + flux * weight) *
00554 (new_noise*new_noise);
00555 }
00556 else if (m_method == MERGE_SUM)
00557 {
00558 new_flux = current_flux + flux;
00559 }
00560 else if (m_method == MERGE_NOAPPEND)
00561 {
00562 new_flux = flux;
00563 }
00564 else
00565 {
00566
00567 passure( false, "%d", m_method);
00568 }
00569 }
00570 else
00571 {
00572 new_flux = flux;
00573 }
00574
00575 if(m_method == MERGE_NOAPPEND) {
00576
00577
00578
00579
00580
00581
00582 check( cpl_image_set(
00583 merged,
00584 merged_bin,
00585 merged_row,
00586 new_flux),
00587 "Error updating merged spectrum");
00588
00589 check( cpl_image_set(
00590 *merged_noise,
00591 merged_bin,
00592 merged_row,
00593 new_noise),
00594 "Error updating weights");
00595
00596
00597 check( cpl_image_set(
00598 merged_ord,
00599 merged_bin_ord,
00600 trace,
00601 new_flux),
00602 "Error updating merged spectrum");
00603
00604 check( cpl_image_set(
00605 noise_ord,
00606 merged_bin_ord,
00607 trace,
00608 new_noise),
00609 "Error updating merged spectrum");
00610
00611
00612 } else {
00613 check( cpl_image_set(
00614 merged , merged_bin, trace, new_flux),
00615 "Error updating merged spectrum");
00616 check( cpl_image_set(
00617 *merged_noise, merged_bin, trace, new_noise),
00618 "Error updating weights");
00619 }
00620
00621
00622
00623
00624
00625 }
00626
00627 }
00628
00629 }
00630
00631
00632 if (merged_header == NULL)
00633 {
00634 uves_free_propertylist(merged_header);
00635 check( *merged_header = uves_initialize_image_header(
00636 "WAVELENGTH", (n_traces > 1) ? "PIXEL" : " ", "FLUX",
00637 bin_min_ord * wavestep, 1.0,
00638 1.0, 1.0,
00639 wavestep, 1.0),
00640 "Error initializing merged spectrum header");
00641 }
00642
00643 if(m_method == MERGE_NOAPPEND) {
00644 filename=uves_sprintf("merged_data_noappend_%s.fits",
00645 uves_chip_tostring_upper(chip));
00646 image_1d = cpl_vector_wrap(cpl_image_get_size_x(merged_ord),
00647 cpl_image_get_data_double(merged_ord));
00648 uves_free_propertylist(&hext);
00649 hext=uves_propertylist_new();
00650 uves_propertylist_append_double(hext,"CRVAL1",wstart-delt1);
00651 uves_propertylist_append_double(hext,"CDELT1",wavestep);
00652 uves_propertylist_append_double(hext,"CRPIX1",0);
00653
00654 if(order==1) {
00655 uves_vector_save(image_1d,filename,CPL_BPP_IEEE_FLOAT,hext,
00656 CPL_IO_DEFAULT);
00657 } else {
00658 uves_vector_save(image_1d,filename,CPL_BPP_IEEE_FLOAT,hext,
00659 CPL_IO_EXTEND);
00660 }
00661 cpl_vector_unwrap(image_1d);
00662
00663 image_1d = cpl_vector_wrap(cpl_image_get_size_x(noise_ord),
00664 cpl_image_get_data_double(noise_ord));
00665
00666 uves_free(filename);
00667
00668 filename=uves_sprintf("merged_sigma_noappend_%s.fits",
00669 uves_chip_tostring_upper(chip));
00670 if(order==1) {
00671 uves_vector_save(image_1d,filename,CPL_BPP_IEEE_FLOAT,hext,
00672 CPL_IO_DEFAULT);
00673 } else {
00674 uves_vector_save(image_1d,filename,CPL_BPP_IEEE_FLOAT,hext,
00675 CPL_IO_EXTEND);
00676 }
00677 cpl_vector_unwrap(image_1d);
00678
00679 uves_free(filename);
00680 uves_free_image(&merged_ord);
00681 uves_free_image(&noise_ord);
00682 uves_free_propertylist(&hext);
00683 uves_free_propertylist(merged_header);
00684 }
00685
00686 }
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728 check( cpl_image_threshold(*merged_noise,
00729 0, DBL_MAX,
00730 1, 1),
00731 "Error setting undefined noise");
00732
00733
00734 if (merged_header != NULL)
00735 {
00736 check( *merged_header = uves_initialize_image_header(
00737 "WAVELENGTH [Ang]", (n_traces > 1) ? "PIXEL" : " ", "ADU",
00738 bin_min * wavestep, 1.0,
00739 1.0, 1.0,
00740 wavestep, 1.0),
00741 "Error initializing merged spectrum header");
00742 }
00743
00744
00745 cleanup:
00746 return merged;
00747 }
00748
00749
00759
00760 merge_method
00761 uves_get_merge_method(const cpl_parameterlist *parameters,
00762 const char *context,
00763 const char *subcontext)
00764 {
00765 const char *mm = "";
00766 merge_method result = 0;
00767
00768 check( uves_get_parameter(parameters, context, subcontext, "merge", CPL_TYPE_STRING, &mm),
00769 "Could not read parameter");
00770
00771 if (strcmp(mm, "optimal") == 0) result = MERGE_OPTIMAL;
00772 else if (strcmp(mm, "sum" ) == 0) result = MERGE_SUM;
00773 else if (strcmp(mm, "noappend") == 0) result = MERGE_NOAPPEND;
00774 else
00775 {
00776 assure(false, CPL_ERROR_ILLEGAL_INPUT, "No such merging method: '%s'", mm);
00777 }
00778
00779 cleanup:
00780 return result;
00781 }
00782
00783