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
00169
00170
00171
00172
00173
00174
00175
00176 #ifdef HAVE_CONFIG_H
00177 # include <config.h>
00178 #endif
00179
00180
00187
00190
00191
00192
00193
00194 #include <uves_rebin.h>
00195
00196 #include <uves_parameters.h>
00197 #include <uves.h>
00198 #include <uves_pfits.h>
00199 #include <uves_dump.h>
00200 #include <uves_utils.h>
00201 #include <uves_utils_wrappers.h>
00202 #include <uves_wavecal_utils.h>
00203 #include <uves_error.h>
00204
00205 #include <cpl.h>
00206
00207
00208
00209
00210 static double
00211 integrate_flux(const double *spectrum_data_double,
00212 const float *spectrum_data_float,
00213 const int *spectrum_data_int,
00214 const cpl_binary *spectrum_bad,
00215 int spectrum_row,
00216 int nx,
00217 double x_min, double x_max,
00218 bool threshold_to_positive,
00219 bool *is_bad);
00220 static double
00221 integrate_noise(const double *spectrum_data_double,
00222 const float *spectrum_data_float,
00223 const int *spectrum_data_int,
00224 const cpl_binary *spectrum_bad,
00225 int spectrum_row,
00226 int nx,
00227 double x_min, double x_max,
00228 bool threshold_to_positive,
00229 bool *is_bad);
00230
00231
00232
00233
00234
00235
00243
00244 cpl_parameterlist *
00245 uves_rebin_define_parameters(void)
00246 {
00247 const char *name = "";
00248 char *full_name = NULL;
00249 cpl_parameter *p = NULL;
00250 cpl_parameterlist *parameters = NULL;
00251
00252 parameters = cpl_parameterlist_new();
00253
00254 {
00255 name = "wavestep";
00256 full_name = uves_sprintf("%s.%s", UVES_REBIN_ID, name);
00257 uves_parameter_new_range(p, full_name,
00258 CPL_TYPE_DOUBLE,
00259 "The bin size (in w.l.u.) in wavelength space. "
00260 "If negative, a step size of "
00261 "2/3 * ( average pixel size ) is used.",
00262 UVES_REBIN_ID,
00263 -1.0,-1.0,DBL_MAX);
00264 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00265 cpl_parameterlist_append(parameters, p);
00266 cpl_free(full_name);
00267
00268 name = "scale";
00269 full_name = uves_sprintf("%s.%s", UVES_REBIN_ID, name);
00270 uves_parameter_new_value(p, full_name,
00271 CPL_TYPE_BOOL,
00272 "Whether or not to multiply by the factor "
00273 "dx/dlambda (pixels per wavelength) "
00274 "during the rebinning. This option is disabled "
00275 "as default in concordance with the "
00276 "method used in the MIDAS pipeline. This "
00277 "option should be set to true "
00278 "to convert the observed flux (in pixel-space) "
00279 "to a flux per wavelength (in "
00280 "wavelength-space).",
00281 UVES_REBIN_ID,
00282 false);
00283 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
00284 cpl_parameterlist_append(parameters, p);
00285 cpl_free(full_name);
00286 }
00287
00288 if (cpl_error_get_code() != CPL_ERROR_NONE)
00289 {
00290 cpl_msg_error(__func__, "Creation of rebinning parameters failed: '%s'",
00291 cpl_error_get_where());
00292 cpl_parameterlist_delete(parameters);
00293 return NULL;
00294 }
00295 else
00296 {
00297 return parameters;
00298 }
00299 }
00300
00301
00346
00347 cpl_image *
00348 uves_rebin(const cpl_image *spectrum,
00349 const cpl_parameterlist *parameters, const char *context,
00350 const cpl_table *linetable, const polynomial *dispersion_relation,
00351 int first_abs_order, int last_abs_order,
00352 int n_traces,
00353 bool threshold_to_positive,
00354 bool is_noise,
00355 uves_propertylist **rebinned_header)
00356 {
00357 double wavestep;
00358 bool scale;
00359 cpl_image *spectrum_local = NULL;
00360 cpl_image *rebinned = NULL;
00361 double *rebinned_data_double = NULL;
00362 float *rebinned_data_float = NULL;
00363 int *rebinned_data_int = NULL;
00364 cpl_mask *rebinned_badmap = NULL;
00365 cpl_binary *rebinned_bad = NULL;
00366
00367 const double *spectrum_data_double = NULL;
00368 const float *spectrum_data_float = NULL;
00369 const int *spectrum_data_int = NULL;
00370
00371 const cpl_mask *spectrum_badmap = NULL;
00372 const cpl_binary *spectrum_bad = NULL;
00373
00374 polynomial *disprel_1d = NULL;
00375
00376 int nx, ny, nlambda, norders;
00377 int order;
00378 bool warning_shown = false;
00379
00380
00381 passure( spectrum != NULL, " ");
00382 passure( dispersion_relation != NULL, " ");
00383 passure( rebinned_header != NULL, " ");
00384
00385 assure( cpl_image_get_type(spectrum) == CPL_TYPE_DOUBLE ||
00386 cpl_image_get_type(spectrum) == CPL_TYPE_FLOAT ||
00387 cpl_image_get_type(spectrum) == CPL_TYPE_INT,
00388 CPL_ERROR_TYPE_MISMATCH,
00389 "Spectrum must have type double, float or int. It is '%s'",
00390 uves_tostring_cpl_type(cpl_image_get_type(spectrum)));
00391
00392
00393 check( uves_get_parameter(parameters, context, UVES_REBIN_ID, "wavestep",
00394 CPL_TYPE_DOUBLE, &wavestep ),
00395 "Could not read parameter");
00396 check( uves_get_parameter(parameters, context, UVES_REBIN_ID, "scale" ,
00397 CPL_TYPE_BOOL, &scale ),
00398 "Could not read parameter");
00399
00400
00401
00402 if (wavestep < 0)
00403 {
00404 double pixelsize;
00405 check( pixelsize = cpl_table_get_column_mean(linetable, LINETAB_PIXELSIZE),
00406 "Error reading mean pixelsize");
00407 uves_msg_debug("Average pixelsize = %f w.l.u.", pixelsize);
00408
00409 wavestep = pixelsize*2.0/3;
00410 }
00411
00412 assure( wavestep > 0 , CPL_ERROR_ILLEGAL_INPUT,
00413 "Illegal step size: %e wlu", wavestep);
00414 assure( n_traces >= 1, CPL_ERROR_ILLEGAL_INPUT,
00415 "Illegal number of traces: %d", n_traces);
00416
00417 nx = cpl_image_get_size_x(spectrum);
00418 ny = cpl_image_get_size_y(spectrum);
00419
00420 assure( ny % n_traces == 0, CPL_ERROR_INCOMPATIBLE_INPUT,
00421 "Spectrum image height (%d) is not a multiple of "
00422 "the number of traces (%d). Confused, bailing out",
00423 ny, n_traces);
00424
00425 norders = ny / n_traces;
00426
00427 spectrum_local=(cpl_image*) spectrum;
00428
00429 if(is_noise) {
00430 cpl_image_power(spectrum_local,2);
00431 }
00432
00433 if (cpl_image_get_type(spectrum_local) == CPL_TYPE_DOUBLE) {
00434 spectrum_data_double = cpl_image_get_data_double(spectrum_local);
00435 }
00436 else if (cpl_image_get_type(spectrum_local) == CPL_TYPE_FLOAT) {
00437 spectrum_data_float = cpl_image_get_data_float(spectrum_local);
00438 } else {
00439 spectrum_data_int = cpl_image_get_data_int(spectrum_local);
00440 }
00441 check_nomsg(spectrum_badmap = cpl_image_get_bpm(spectrum_local));
00442 check_nomsg(spectrum_bad = cpl_mask_get_data_const(spectrum_badmap));
00443
00444 assure( norders >= 1, CPL_ERROR_ILLEGAL_INPUT, "Empty spectrum");
00445 assure( uves_round_double(fabs(first_abs_order - last_abs_order)) + 1 == norders,
00446 CPL_ERROR_INCOMPATIBLE_INPUT,
00447 "Spectrum contains %d orders, but line table absolute "
00448 "order numbering is %d - %d",
00449 norders, first_abs_order, last_abs_order);
00450
00451
00452 check( *rebinned_header = uves_initialize_image_header(
00453 "Ang",
00454 (n_traces > 1) ? "PIXEL" : "ORDER",
00455 (scale) ? "FLUX PER WAVEL" : "FLUX",
00456 0.0, 1.0,
00457 1.0, 1.0,
00458 wavestep, 1.0),
00459 "Error setting up rebinned image header");
00460
00461
00462
00463
00464
00465
00466
00467 nlambda = -1;
00468
00469 for (order = 1; order <= norders; order++)
00470 {
00471
00472
00473
00474
00475
00476
00477
00478 int absorder = uves_absolute_order(first_abs_order, last_abs_order, order);
00479 double lambda_min, lambda_max;
00480 int nbins;
00481
00482 int minx, maxx;
00483
00484 minx = 1;
00485
00486
00487
00488
00489 maxx = nx;
00490
00491 if ( minx > nx )
00492 {
00493 uves_msg_debug("Nothing extracted in order #%d", order);
00494 minx = maxx = nx/2;
00495 }
00496
00497 lambda_min = uves_polynomial_evaluate_2d(
00498 dispersion_relation, minx - 0.5, absorder)/absorder;
00499 lambda_max = uves_polynomial_evaluate_2d(
00500 dispersion_relation, maxx + 0.5, absorder)/absorder;
00501
00502 nbins =
00503 uves_round_double(lambda_max / wavestep) -
00504 uves_round_double(lambda_min / wavestep) + 1;
00505
00506 nlambda = uves_max_int(nlambda, nbins);
00507
00508 check( uves_pfits_set_wstart(
00509 *rebinned_header, order,
00510 wavestep * uves_round_double(lambda_min / wavestep)),
00511 "Error writing adding WSTART keyword to header");
00512
00513 check( uves_pfits_set_wend(
00514 *rebinned_header, order,
00515 wavestep * uves_round_double(lambda_max / wavestep)),
00516 "Error writing adding WEND keyword to header");
00517
00518 uves_msg_debug("Rebinning abs. order #%d. "
00519 "Range = %d - %d pix = %f - %f wlu, %d bins",
00520 absorder,
00521 minx, maxx,
00522 lambda_min,
00523 lambda_max,
00524 nbins);
00525 }
00526
00527
00528 uves_msg_debug("Step size = %f wlu (%d orders x %d bins)", wavestep, norders, nlambda);
00529
00530
00531
00532
00533 check_nomsg( rebinned = cpl_image_new(nlambda, norders*n_traces, cpl_image_get_type(spectrum_local)));
00534 assure_mem( rebinned );
00535
00536 if (cpl_image_get_type(spectrum_local) == CPL_TYPE_DOUBLE) {
00537 rebinned_data_double = cpl_image_get_data_double(rebinned);
00538 }
00539 else if (cpl_image_get_type(spectrum_local) == CPL_TYPE_FLOAT) {
00540 rebinned_data_float = cpl_image_get_data_float(rebinned);
00541 } else {
00542 rebinned_data_int = cpl_image_get_data_int(rebinned);
00543 }
00544 rebinned_badmap = cpl_image_get_bpm(rebinned);
00545 rebinned_bad = cpl_mask_get_data(rebinned_badmap);
00546
00547
00548
00549 uves_image_reject_all(rebinned);
00550
00551 for (order = 1; order <= norders; order++)
00552 {
00553 int absorder = uves_absolute_order(first_abs_order, last_abs_order, order);
00554 double lambda_start;
00555 int trace;
00556
00557
00558
00559 check( lambda_start = uves_pfits_get_wstart(*rebinned_header, order),
00560 "Error reading product header");
00561
00562
00563 uves_polynomial_delete(&disprel_1d);
00564 check( disprel_1d = uves_polynomial_collapse(dispersion_relation,
00565 2,
00566 absorder),
00567 "Error getting 1d dispersion relation for absolute order #%d", absorder);
00568
00569
00570
00571 for (trace = 1; trace <= n_traces; trace++)
00572 {
00573 int spectrum_row = (order - 1)*n_traces + trace;
00574 int bin;
00575
00576 double x = 1;
00577 double x_min = 1;
00578 double x_max = 1;
00579
00580 for (bin = 1; bin <= nlambda && x_min <= nx+0.5; bin++)
00581 {
00582 double lambda = lambda_start + (bin-1) * wavestep;
00583
00584 int multiplicity = 1;
00585 double x_guess = x;
00586
00587
00588
00589 x = uves_polynomial_solve_1d(disprel_1d,
00590 lambda * absorder,
00591 x_guess,
00592 multiplicity);
00593
00594 if (cpl_error_get_code() == CPL_ERROR_DIVISION_BY_ZERO) {
00595 uves_error_reset();
00596 if (!warning_shown) {
00597 uves_msg_warning("Could not invert dispersion relation at "
00598 "order = %d, x = %f. This might be caused "
00599 "by fitting a too high degree polynomial to "
00600 "too few lines. Decrease dispersion "
00601 "polynomial degree "
00602 "or relax rejection parameters!",
00603 absorder, x_guess);
00604 warning_shown = true;
00605 }
00606 x = x_guess;
00607 }
00608 else {
00609 assure( cpl_error_get_code() == CPL_ERROR_NONE,
00610 cpl_error_get_code(),
00611 "Could not invert dispersion relation");
00612 }
00613
00614
00615 x_guess = x;
00616 x_min = uves_polynomial_solve_1d(
00617 disprel_1d,
00618 (lambda - 0.5*wavestep) * absorder,
00619 x_guess,
00620 multiplicity);
00621
00622 if (cpl_error_get_code() == CPL_ERROR_DIVISION_BY_ZERO) {
00623 uves_error_reset();
00624 if (!warning_shown) {
00625 uves_msg_warning("Could not invert dispersion relation at "
00626 "order = %d, x = %f. This might be caused "
00627 "by fitting a too high degree polynomial to "
00628 "too few lines. Decrease dispersion "
00629 "polynomial degree "
00630 "or relax rejection parameters!",
00631 absorder, x_guess);
00632 warning_shown = true;
00633 }
00634 x_min = x_guess;
00635 }
00636 else {
00637 assure( cpl_error_get_code() == CPL_ERROR_NONE,
00638 cpl_error_get_code(),
00639 "Could not invert dispersion relation");
00640 }
00641
00642
00643 x_max = uves_polynomial_solve_1d(
00644 disprel_1d,
00645 (lambda + 0.5*wavestep) * absorder,
00646 x_guess,
00647 multiplicity);
00648
00649 if (cpl_error_get_code() == CPL_ERROR_DIVISION_BY_ZERO) {
00650 uves_error_reset();
00651 if (!warning_shown) {
00652 uves_msg_warning("Could not invert dispersion relation at "
00653 "order = %d, x = %f. This might be caused "
00654 "by fitting a too high degree polynomial to "
00655 "too few lines. Decrease dispersion "
00656 "polynomial degree "
00657 "or relax rejection parameters!",
00658 absorder, x_guess);
00659 warning_shown = true;
00660 }
00661 x_max = x_guess;
00662 }
00663 else {
00664 assure( cpl_error_get_code() == CPL_ERROR_NONE,
00665 cpl_error_get_code(),
00666 "Could not invert dispersion relation");
00667 }
00668
00669
00670 if (uves_max_double(0.5, uves_min_double(nx+0.5, x_min)) <
00671 uves_max_double(0.5, uves_min_double(nx+0.5, x_max)))
00672 {
00673
00674
00675
00676
00677
00678 bool pis_rejected;
00679 double p_min=uves_max_double(0.5, uves_min_double(nx+0.5, x_min));
00680 double p_max=uves_max_double(0.5, uves_min_double(nx+0.5, x_max));
00681 double flux_x =0;
00682 if(is_noise) {
00683 flux_x = integrate_noise(
00684 spectrum_data_double,
00685 spectrum_data_float,
00686 spectrum_data_int,
00687 spectrum_bad,
00688 spectrum_row,
00689 nx,
00690 p_min,
00691 p_max,
00692 threshold_to_positive,
00693 &pis_rejected)
00694 / (( p_max -p_min) * ( p_max -p_min));
00695
00696 } else {
00697 flux_x = integrate_flux(
00698 spectrum_data_double,
00699 spectrum_data_float,
00700 spectrum_data_int,
00701 spectrum_bad,
00702 spectrum_row,
00703 nx,
00704 p_min,
00705 p_max,
00706 threshold_to_positive,
00707 &pis_rejected)
00708 / ( p_max - p_min );
00709 }
00710 if (!pis_rejected)
00711 {
00712
00713
00714 double dldx;
00715
00716
00717 if (scale)
00718 {
00719
00720
00721
00722 dldx = uves_polynomial_derivative_2d(
00723 dispersion_relation, x, absorder, 1)
00724 / absorder;
00725
00726 if(is_noise) {
00727 dldx *= dldx;
00728 }
00729 }
00730 else
00731 {
00732 dldx = 1;
00733 }
00734
00735
00736
00737
00738 if (cpl_image_get_type(spectrum_local) == CPL_TYPE_DOUBLE) {
00739 rebinned_data_double[(bin-1) +
00740 (spectrum_row-1)*nlambda] =
00741 flux_x / fabs(dldx);
00742 }
00743 else if (cpl_image_get_type(spectrum_local) == CPL_TYPE_FLOAT) {
00744 rebinned_data_float[(bin-1) +
00745 (spectrum_row-1)*nlambda] =
00746 flux_x / fabs(dldx);
00747 } else {
00748 rebinned_data_int[(bin-1) +
00749 (spectrum_row-1)*nlambda] =
00750 flux_x / fabs(dldx);
00751
00752
00753 }
00754
00755
00756 rebinned_bad[(bin-1) +
00757 (spectrum_row-1)*nlambda] =
00758 CPL_BINARY_0;
00759 }
00760 else
00761 {
00762
00763
00764 }
00765
00766 }
00767 else
00768 {
00769
00770
00771 }
00772
00773
00774 }
00775 }
00776
00777 }
00778
00779 if(is_noise) {
00780 cpl_image_power(rebinned,0.5);
00781 }
00782
00783
00784 cleanup:
00785 uves_polynomial_delete(&disprel_1d);
00786 if (cpl_error_get_code() != CPL_ERROR_NONE)
00787 {
00788 uves_free_image(&rebinned);
00789 uves_free_propertylist(rebinned_header);
00790 }
00791
00792 return rebinned;
00793 }
00794
00795
00820
00821 static double
00822 integrate_flux(const double *spectrum_data_double,
00823 const float *spectrum_data_float,
00824 const int *spectrum_data_int,
00825 const cpl_binary *spectrum_bad,
00826 int spectrum_row,
00827 int nx,
00828 double x_min, double x_max,
00829 bool threshold_to_positive,
00830 bool *is_bad)
00831 {
00832 double sum = 0;
00833 double sum_interval = 0;
00834
00835 int x;
00836 int first_good = 0;
00837
00838 *is_bad = true;
00839
00840 for (x = uves_min_int(nx, uves_max_int(1, uves_round_double(x_min)));
00841
00842
00843 x <= uves_min_int(nx, uves_max_int(1, uves_round_double(x_max)));
00844 x++)
00845 {
00846
00847 if (spectrum_bad[(x-1) + (spectrum_row-1)*nx] == CPL_BINARY_0)
00848
00849 {
00850 double flux;
00851 double interval_length;
00852 double current_term;
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873 int x_prev = x-1;
00874 int x_next = x+1;
00875 bool pis_rejected_prev = (x_prev < 1 ) ||
00876 (spectrum_bad[(x_prev-1) + (spectrum_row-1)*nx] == CPL_BINARY_1);
00877 bool pis_rejected_next = (nx < x_next) ||
00878 (spectrum_bad[(x_next-1) + (spectrum_row-1)*nx] == CPL_BINARY_1);
00879
00880 if (spectrum_data_double != NULL) {
00881 flux = spectrum_data_double[(x-1) + (spectrum_row-1)*nx];
00882 }
00883 else if (spectrum_data_float != NULL) {
00884 flux = spectrum_data_float [(x-1) + (spectrum_row-1)*nx];
00885 } else {
00886 flux = spectrum_data_int [(x-1) + (spectrum_row-1)*nx];
00887 }
00888
00889 if (!pis_rejected_prev && !pis_rejected_next)
00890 {
00891
00892
00893
00894
00895 double flux_minus, flux_plus;
00896 if (spectrum_data_double != NULL) {
00897 flux_minus =
00898 (flux + spectrum_data_double[(x_prev-1) + (spectrum_row-1)*nx])
00899 / 2.0;
00900 flux_plus =
00901 (flux + spectrum_data_double[(x_next-1) + (spectrum_row-1)*nx])
00902 / 2.0;
00903 }
00904 else if (spectrum_data_float != NULL) {
00905 flux_minus =
00906 (flux + spectrum_data_float[(x_prev-1) + (spectrum_row-1)*nx])
00907 / 2.0;
00908 flux_plus =
00909 (flux + spectrum_data_float[(x_next-1) + (spectrum_row-1)*nx])
00910 / 2.0;
00911 } else {
00912 flux_minus =
00913 (flux + spectrum_data_int[(x_prev-1) + (spectrum_row-1)*nx])
00914 / 2.0;
00915 flux_plus =
00916 (flux + spectrum_data_int[(x_next-1) + (spectrum_row-1)*nx])
00917 / 2.0;
00918 }
00919
00920
00921
00922
00923
00924
00925
00926
00927 {
00928 double flux_center = 2*flux - (flux_minus + flux_plus) / 2.0;
00929
00930
00931
00932 double slope_minus = (flux_center - flux_minus )/ 0.5;
00933 double slope_plus = (flux_plus - flux_center) / 0.5;
00934
00935
00936
00937
00938
00939
00940 double lo1 = uves_max_double(x-0.5, uves_min_double(x, x_min));
00941 double hi1 = uves_max_double(x-0.5, uves_min_double(x, x_max));
00942 double dy1 = hi1-lo1;
00943
00944
00945
00946 double lo2 = uves_max_double(x, uves_min_double(x+0.5, x_min));
00947 double hi2 = uves_max_double(x, uves_min_double(x+0.5, x_max));
00948 double dy2 = hi2-lo2;
00949
00950
00951
00952
00953
00954
00955
00956
00957 current_term =
00958 dy1 * (flux_center + slope_minus * ((lo1+hi1)/2.0 - x))
00959 +
00960 dy2 * (flux_center + slope_plus * ((lo2+hi2)/2.0 - x));
00961
00962
00963
00964
00965
00966
00967
00968 interval_length = dy1 + dy2;
00969 }
00970
00971 }
00972 else
00973 {
00974 interval_length =
00975 uves_min_double(x_max, x+0.5) -
00976 uves_max_double(x_min, x-0.5);
00977
00978 current_term = interval_length * flux;
00979
00980
00981
00982 }
00983
00984 if (*is_bad) {
00985 first_good = x;
00986 }
00987 *is_bad = false;
00988
00989 sum += current_term;
00990 sum_interval += interval_length;
00991 }
00992 }
00993
00994 if (sum_interval == 0)
00995 {
00996 *is_bad = true;
00997 return -1;
00998 }
00999 else
01000 {
01001
01002
01003
01004 double result = sum*(x_max-x_min)/sum_interval;
01005
01006
01007
01008 if (threshold_to_positive) {
01009 if (result == 0) {
01010
01011 *is_bad = true;
01012 return -1;
01013 }
01014 else {
01015 result = fabs(result);
01016 }
01017 }
01018 return result;
01019 }
01020 }
01021
01022
01023
01048
01049 static double
01050 integrate_noise(const double *spectrum_data_double,
01051 const float *spectrum_data_float,
01052 const int *spectrum_data_int,
01053 const cpl_binary *spectrum_bad,
01054 int spectrum_row,
01055 int nx,
01056 double x_min, double x_max,
01057 bool threshold_to_positive,
01058 bool *is_bad)
01059 {
01060 double sum = 0;
01061 double sum_interval = 0;
01062
01063 int x;
01064 int first_good = 0;
01065
01066 *is_bad = true;
01067
01068 for (x = uves_min_int(nx, uves_max_int(1, uves_round_double(x_min)));
01069
01070
01071 x <= uves_min_int(nx, uves_max_int(1, uves_round_double(x_max)));
01072 x++)
01073 {
01074
01075 if (spectrum_bad[(x-1) + (spectrum_row-1)*nx] == CPL_BINARY_0)
01076
01077 {
01078 double flux;
01079 double interval_length;
01080 double current_term;
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101 int x_prev = x-1;
01102 int x_next = x+1;
01103 bool pis_rejected_prev = (x_prev < 1 ) ||
01104 (spectrum_bad[(x_prev-1) + (spectrum_row-1)*nx] == CPL_BINARY_1);
01105 bool pis_rejected_next = (nx < x_next) ||
01106 (spectrum_bad[(x_next-1) + (spectrum_row-1)*nx] == CPL_BINARY_1);
01107
01108 if (spectrum_data_double != NULL) {
01109 flux = spectrum_data_double[(x-1) + (spectrum_row-1)*nx];
01110 }
01111 else if (spectrum_data_float != NULL) {
01112 flux = spectrum_data_float [(x-1) + (spectrum_row-1)*nx];
01113 } else {
01114 flux = spectrum_data_int [(x-1) + (spectrum_row-1)*nx];
01115 }
01116
01117 if (!pis_rejected_prev && !pis_rejected_next)
01118 {
01119
01120
01121
01122
01123 double flux_minus, flux_plus;
01124 if (spectrum_data_double != NULL) {
01125 flux_minus =
01126 (flux + spectrum_data_double[(x_prev-1) + (spectrum_row-1)*nx])
01127 / 4.0;
01128 flux_plus =
01129 (flux + spectrum_data_double[(x_next-1) + (spectrum_row-1)*nx])
01130 / 4.0;
01131 }
01132 else if (spectrum_data_float != NULL) {
01133 flux_minus =
01134 (flux + spectrum_data_float[(x_prev-1) + (spectrum_row-1)*nx])
01135 / 4.0;
01136 flux_plus =
01137 (flux + spectrum_data_float[(x_next-1) + (spectrum_row-1)*nx])
01138 / 4.0;
01139 } else {
01140 flux_minus =
01141 (flux + spectrum_data_int[(x_prev-1) + (spectrum_row-1)*nx])
01142 / 4.0;
01143 flux_plus =
01144 (flux + spectrum_data_int[(x_next-1) + (spectrum_row-1)*nx])
01145 / 4.0;
01146 }
01147
01148
01149
01150
01151
01152
01153
01154
01155 {
01156 double flux_center = 4*flux - (flux_minus + flux_plus) / 4.0;
01157
01158
01159
01160 double slope_minus = 4.0 * (flux_center + flux_minus );
01161 double slope_plus = 4.0 * (flux_plus + flux_center);
01162
01163
01164
01165
01166
01167
01168 double lo1 = uves_max_double(x-0.5, uves_min_double(x, x_min));
01169 double hi1 = uves_max_double(x-0.5, uves_min_double(x, x_max));
01170 double dy1 = hi1-lo1;
01171
01172
01173
01174 double lo2 = uves_max_double(x, uves_min_double(x+0.5, x_min));
01175 double hi2 = uves_max_double(x, uves_min_double(x+0.5, x_max));
01176 double dy2 = hi2-lo2;
01177
01178
01179
01180
01181
01182
01183
01184
01185 current_term =
01186 dy1*dy1 * (flux_center + slope_minus *
01187 ((lo1+hi1)/2.0 - x) * ((lo1+hi1)/2.0 - x) )
01188 +
01189 dy2*dy2 * (flux_center + slope_plus *
01190 ((lo2+hi2)/2.0 - x) * ((lo2+hi2)/2.0 - x) );
01191
01192
01193
01194
01195
01196
01197
01198 interval_length = dy1 + dy2;
01199 }
01200
01201 }
01202 else
01203 {
01204 interval_length =
01205 uves_min_double(x_max, x+0.5) -
01206 uves_max_double(x_min, x-0.5);
01207
01208 current_term = interval_length * interval_length * flux;
01209
01210
01211
01212 }
01213
01214 if (*is_bad) {
01215 first_good = x;
01216 }
01217 *is_bad = false;
01218
01219 sum += current_term;
01220 sum_interval += interval_length;
01221 }
01222 }
01223
01224 if (sum_interval == 0)
01225 {
01226 *is_bad = true;
01227 return -1;
01228 }
01229 else
01230 {
01231
01232
01233
01234 double result = sum*(x_max-x_min)/sum_interval*
01235 (x_max-x_min)/sum_interval;
01236
01237
01238
01239 if (threshold_to_positive) {
01240 if (result == 0) {
01241
01242 *is_bad = true;
01243 return -1;
01244 }
01245 else {
01246 result = fabs(result);
01247 }
01248 }
01249 return result;
01250 }
01251 }
01252
01253
01254