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