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