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 #ifdef HAVE_CONFIG_H
00117 # include <config.h>
00118 #endif
00119
00120
00126
00130
00131
00132
00133
00134 #include <uves_merge.h>
00135
00136 #include <uves_pfits.h>
00137 #include <uves_utils.h>
00138 #include <uves_utils_wrappers.h>
00139 #include <uves_dump.h>
00140 #include <uves_error.h>
00141
00142 #include <cpl.h>
00143 #include <float.h>
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00180
00181
00182 cpl_image *
00183 uves_merge_orders(const cpl_image *spectrum, const cpl_image *spectrum_noise,
00184 const uves_propertylist *spectrum_header,
00185 merge_method m_method,
00186 int n_traces,
00187 uves_propertylist **merged_header,
00188 cpl_image **merged_noise)
00189 {
00190 cpl_image *merged = NULL;
00191
00192 const double *spectrum_data_double = NULL;
00193 const float *spectrum_data_float = NULL;
00194 const cpl_mask *spectrum_badmap = NULL;
00195 const cpl_binary *spectrum_bad = NULL;
00196
00197 const double *noise_data_double = NULL;
00198 const float *noise_data_float = NULL;
00199 const cpl_mask *noise_badmap = NULL;
00200 const cpl_binary *noise_bad = NULL;
00201 cpl_type type;
00202
00203 int nbins, ny, norders;
00204 double wavestep;
00205 int bin_min = 0, bin_max = 0;
00206 int total_bins;
00207 int order, trace;
00208
00209 passure( spectrum != NULL, " ");
00210 passure( spectrum_noise != NULL, " ");
00211 passure( spectrum_header != NULL, " ");
00212 passure( merged_header != NULL, " ");
00213 passure( merged_noise != NULL, " ");
00214
00215 assure( m_method == MERGE_OPTIMAL || m_method == MERGE_SUM, CPL_ERROR_ILLEGAL_INPUT,
00216 "Unknown merge method: %d", m_method);
00217
00218 assure( cpl_image_get_type(spectrum) == CPL_TYPE_DOUBLE ||
00219 cpl_image_get_type(spectrum) == CPL_TYPE_FLOAT,
00220 CPL_ERROR_TYPE_MISMATCH,
00221 "Spectrum must have type double or float. It is '%s'",
00222 uves_tostring_cpl_type(cpl_image_get_type(spectrum)));
00223
00224 assure( cpl_image_get_type(spectrum_noise) == CPL_TYPE_DOUBLE ||
00225 cpl_image_get_type(spectrum_noise) == CPL_TYPE_FLOAT,
00226 CPL_ERROR_TYPE_MISMATCH,
00227 "Spectrum noise must have type double. It is '%s'",
00228 uves_tostring_cpl_type(cpl_image_get_type(spectrum_noise)));
00229
00230 assure( cpl_image_get_type(spectrum) ==
00231 cpl_image_get_type(spectrum_noise),
00232 CPL_ERROR_TYPE_MISMATCH,
00233 "Spectrum and spectrum noise must have same type. They are "
00234 "%s and %s, respectively",
00235 uves_tostring_cpl_type(cpl_image_get_type(spectrum)),
00236 uves_tostring_cpl_type(cpl_image_get_type(spectrum_noise)) );
00237
00238 type = cpl_image_get_type(spectrum);
00239
00240
00241 nbins = cpl_image_get_size_x(spectrum);
00242 ny = cpl_image_get_size_y(spectrum);
00243
00244 assure( cpl_image_get_size_x(spectrum_noise) == nbins &&
00245 cpl_image_get_size_y(spectrum_noise) == ny,
00246 CPL_ERROR_INCOMPATIBLE_INPUT,
00247 "Incompatible spectrum/noise image sizes: %dx%d vs. %dx%d",
00248 nbins, ny,
00249 cpl_image_get_size_x(spectrum_noise),
00250 cpl_image_get_size_y(spectrum_noise) );
00251
00252 assure( ny % n_traces == 0, CPL_ERROR_INCOMPATIBLE_INPUT,
00253 "Spectrum image height (%d) is not a multiple of "
00254 "the number of traces (%d). Confused, bailing out",
00255 ny, n_traces);
00256
00257 norders = ny / n_traces;
00258
00259 check( wavestep = uves_pfits_get_cdelt1(spectrum_header),
00260 "Error reading bin width");
00261
00262
00263
00264 if (type == CPL_TYPE_DOUBLE) {
00265 spectrum_data_double = cpl_image_get_data_double_const(spectrum);
00266 }
00267 else {
00268 spectrum_data_float = cpl_image_get_data_float_const(spectrum);
00269 }
00270 spectrum_badmap = cpl_image_get_bpm_const(spectrum);
00271 spectrum_bad = cpl_mask_get_data_const(spectrum_badmap);
00272
00273 if (type == CPL_TYPE_DOUBLE) {
00274 noise_data_double = cpl_image_get_data_double_const(spectrum_noise);
00275 }
00276 else {
00277 noise_data_float = cpl_image_get_data_float_const(spectrum_noise);
00278 }
00279 noise_badmap = cpl_image_get_bpm_const(spectrum_noise);
00280 noise_bad = cpl_mask_get_data_const(noise_badmap);
00281
00282
00283 for (order = 1; order <= norders; order++)
00284 {
00285 double wstart, wend;
00286 check( wstart = uves_pfits_get_wstart(spectrum_header, order),
00287 "Error reading start wavelength for order #%d", order);
00288
00289 check( wend = uves_pfits_get_wend(spectrum_header, order),
00290 "Error reading end wavelength for order #%d", order);
00291
00292 uves_msg_debug("Order #%d: wstart - wend = %f - %f wlu", order, wstart, wend);
00293
00294 if (order == 1)
00295 {
00296 bin_min = uves_round_double(wstart/wavestep);
00297 bin_max = uves_round_double(wend /wavestep);
00298 }
00299
00300 bin_min = uves_min_int(bin_min, uves_round_double(wstart/wavestep));
00301 bin_max = uves_max_int(bin_max, uves_round_double(wend /wavestep));
00302 }
00303
00304 total_bins = (bin_max - bin_min) + 1;
00305
00306 uves_msg_debug("Merging orders into %d bins covering wavelengths %.3f - %.3f wlu",
00307 total_bins, bin_min * wavestep, bin_max * wavestep);
00308
00309
00310 merged = cpl_image_new(total_bins, n_traces, type);
00311 *merged_noise = cpl_image_new(total_bins, n_traces, type);
00312 cpl_image_add_scalar(*merged_noise, -1.0);
00313
00314
00315 for (order = 1; order <= norders; order++)
00316 {
00317 double wstart, wend;
00318 int wstart_bin, wend_bin;
00319
00320 check( wstart = uves_pfits_get_wstart(spectrum_header, order),
00321 "Error reading start wavelength for order #%d", order);
00322
00323 check( wend = uves_pfits_get_wend(spectrum_header, order),
00324 "Error reading end wavelength for order #%d", order);
00325
00326 wstart_bin = uves_round_double(wstart/wavestep);
00327 wend_bin = uves_round_double(wend/wavestep);
00328
00329
00330 for (trace = 1; trace <= n_traces; trace++)
00331 {
00332 int spectrum_row = (order - 1)*n_traces + trace;
00333 int rel_bin;
00334
00335 for (rel_bin = 1; rel_bin <= wend_bin - wstart_bin + 1; rel_bin++)
00336 {
00337 double flux, noise;
00338 double current_flux, new_flux;
00339 double current_noise, new_noise;
00340 double weight;
00341 int pis_rejected, noise_rejected;
00342
00343
00344 int merged_bin = (wstart_bin - bin_min) + rel_bin;
00345
00346 passure(1 <= merged_bin && merged_bin <= total_bins,
00347 "%d %d %d", rel_bin, merged_bin, total_bins);
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 if (type == CPL_TYPE_DOUBLE) {
00358 flux = spectrum_data_double[(rel_bin-1) + (spectrum_row-1) * nbins];
00359 noise = noise_data_double [(rel_bin-1) + (spectrum_row-1) * nbins];
00360
00361 }
00362 else {
00363 flux = spectrum_data_float[(rel_bin-1) + (spectrum_row-1) * nbins];
00364 noise = noise_data_float [(rel_bin-1) + (spectrum_row-1) * nbins];
00365 }
00366
00367 pis_rejected = spectrum_bad[(rel_bin-1) + (spectrum_row-1) * nbins];
00368 noise_rejected = noise_bad [(rel_bin-1) + (spectrum_row-1) * nbins];
00369
00370 if (!pis_rejected && !noise_rejected)
00371 {
00372 check(( current_flux = cpl_image_get(
00373 merged , merged_bin, trace, &pis_rejected),
00374 current_noise = cpl_image_get(
00375 *merged_noise, merged_bin, trace, &pis_rejected)),
00376 "Error reading merged spetrum");
00377
00378 weight = 1/(noise*noise);
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 if (current_noise > 0)
00400 {
00401 if (m_method == MERGE_OPTIMAL)
00402 {
00403 new_noise = 1/(current_noise*current_noise);
00404 new_noise += weight;
00405 new_noise = 1/sqrt(new_noise);
00406 }
00407 else if (m_method == MERGE_SUM)
00408 {
00409 new_noise = sqrt(current_noise*current_noise
00410 + noise*noise);
00411 }
00412 else
00413 {
00414
00415 passure( false, "%d", m_method);
00416 }
00417 }
00418 else
00419 {
00420
00421 new_noise = noise;
00422 }
00423
00424 if (current_noise > 0)
00425 {
00426 if (m_method == MERGE_OPTIMAL)
00427 {
00428 new_flux = (current_flux /
00429 (current_noise*current_noise)
00430 + flux * weight) *
00431 (new_noise*new_noise);
00432 }
00433 else if (m_method == MERGE_SUM)
00434 {
00435 new_flux = current_flux + flux;
00436 }
00437 else
00438 {
00439
00440 passure( false, "%d", m_method);
00441 }
00442 }
00443 else
00444 {
00445 new_flux = flux;
00446 }
00447
00448 check( cpl_image_set(
00449 merged , merged_bin, trace, new_flux),
00450 "Error updating merged spectrum");
00451 check( cpl_image_set(
00452 *merged_noise, merged_bin, trace, new_noise),
00453 "Error updating weights");
00454
00455
00456
00457
00458
00459
00460 }
00461
00462 }
00463
00464 }
00465
00466 }
00467
00468
00469
00470
00471 check( cpl_image_threshold(*merged_noise,
00472 0, DBL_MAX,
00473 1, 1),
00474 "Error setting undefined noise");
00475
00476 if (merged_header != NULL)
00477 {
00478 check( *merged_header = uves_initialize_image_header(
00479 "WAVELENGTH", (n_traces > 1) ? "PIXEL" : " ", "FLUX",
00480 bin_min * wavestep, 1.0,
00481 1.0, 1.0,
00482 wavestep, 1.0),
00483 "Error initializing merged spectrum header");
00484 }
00485
00486 cleanup:
00487 return merged;
00488 }
00489
00490
00500
00501 merge_method
00502 uves_get_merge_method(const cpl_parameterlist *parameters, const char *context,
00503 const char *subcontext)
00504 {
00505 const char *mm = "";
00506 merge_method result = 0;
00507
00508 check( uves_get_parameter(parameters, context, subcontext, "merge", CPL_TYPE_STRING, &mm),
00509 "Could not read parameter");
00510
00511 if (strcmp(mm, "optimal") == 0) result = MERGE_OPTIMAL;
00512 else if (strcmp(mm, "sum" ) == 0) result = MERGE_SUM;
00513 else
00514 {
00515 assure(false, CPL_ERROR_ILLEGAL_INPUT, "No such merging method: '%s'", mm);
00516 }
00517
00518 cleanup:
00519 return result;
00520 }
00521
00522