194 #include <uves_rebin.h>
196 #include <uves_parameters.h>
198 #include <uves_pfits.h>
199 #include <uves_dump.h>
200 #include <uves_utils.h>
201 #include <uves_utils_wrappers.h>
202 #include <uves_wavecal_utils.h>
203 #include <uves_error.h>
212 const float *spectrum_data_float,
213 const int *spectrum_data_int,
214 const cpl_binary *spectrum_bad,
217 double x_min,
double x_max,
218 bool threshold_to_positive,
222 const float *spectrum_data_float,
223 const int *spectrum_data_int,
224 const cpl_binary *spectrum_bad,
227 double x_min,
double x_max,
228 bool threshold_to_positive,
247 const char *name =
"";
248 char *full_name = NULL;
249 cpl_parameter *p = NULL;
250 cpl_parameterlist *parameters = NULL;
252 parameters = cpl_parameterlist_new();
256 full_name = uves_sprintf(
"%s.%s", UVES_REBIN_ID, name);
257 uves_parameter_new_range(p, full_name,
259 "The bin size (in w.l.u.) in wavelength space. "
260 "If negative, a step size of "
261 "2/3 * ( average pixel size ) is used.",
264 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
265 cpl_parameterlist_append(parameters, p);
269 full_name = uves_sprintf(
"%s.%s", UVES_REBIN_ID, name);
270 uves_parameter_new_value(p, full_name,
272 "Whether or not to multiply by the factor "
273 "dx/dlambda (pixels per wavelength) "
274 "during the rebinning. This option is disabled "
275 "as default in concordance with the "
276 "method used in the MIDAS pipeline. This "
277 "option should be set to true "
278 "to convert the observed flux (in pixel-space) "
279 "to a flux per wavelength (in "
280 "wavelength-space).",
283 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
284 cpl_parameterlist_append(parameters, p);
288 if (cpl_error_get_code() != CPL_ERROR_NONE)
290 cpl_msg_error(__func__,
"Creation of rebinning parameters failed: '%s'",
291 cpl_error_get_where());
292 cpl_parameterlist_delete(parameters);
349 const cpl_parameterlist *parameters,
const char *context,
350 const cpl_table *linetable,
const polynomial *dispersion_relation,
351 int first_abs_order,
int last_abs_order,
353 bool threshold_to_positive,
359 cpl_image *spectrum_local = NULL;
360 cpl_image *rebinned = NULL;
361 double *rebinned_data_double = NULL;
362 float *rebinned_data_float = NULL;
363 int *rebinned_data_int = NULL;
364 cpl_mask *rebinned_badmap = NULL;
365 cpl_binary *rebinned_bad = NULL;
367 const double *spectrum_data_double = NULL;
368 const float *spectrum_data_float = NULL;
369 const int *spectrum_data_int = NULL;
371 const cpl_mask *spectrum_badmap = NULL;
372 const cpl_binary *spectrum_bad = NULL;
376 int nx, ny, nlambda, norders;
378 bool warning_shown =
false;
381 passure( spectrum != NULL,
" ");
382 passure( dispersion_relation != NULL,
" ");
383 passure( rebinned_header != NULL,
" ");
385 assure( cpl_image_get_type(spectrum) == CPL_TYPE_DOUBLE ||
386 cpl_image_get_type(spectrum) == CPL_TYPE_FLOAT ||
387 cpl_image_get_type(spectrum) == CPL_TYPE_INT,
388 CPL_ERROR_TYPE_MISMATCH,
389 "Spectrum must have type double, float or int. It is '%s'",
393 check( uves_get_parameter(parameters, context, UVES_REBIN_ID,
"wavestep",
394 CPL_TYPE_DOUBLE, &wavestep ),
395 "Could not read parameter");
396 check( uves_get_parameter(parameters, context, UVES_REBIN_ID,
"scale" ,
397 CPL_TYPE_BOOL, &scale ),
398 "Could not read parameter");
405 check( pixelsize = cpl_table_get_column_mean(linetable, LINETAB_PIXELSIZE),
406 "Error reading mean pixelsize");
409 wavestep = pixelsize*2.0/3;
412 assure( wavestep > 0 , CPL_ERROR_ILLEGAL_INPUT,
413 "Illegal step size: %e wlu", wavestep);
414 assure( n_traces >= 1, CPL_ERROR_ILLEGAL_INPUT,
415 "Illegal number of traces: %d", n_traces);
417 nx = cpl_image_get_size_x(spectrum);
418 ny = cpl_image_get_size_y(spectrum);
420 assure( ny % n_traces == 0, CPL_ERROR_INCOMPATIBLE_INPUT,
421 "Spectrum image height (%d) is not a multiple of "
422 "the number of traces (%d). Confused, bailing out",
425 norders = ny / n_traces;
427 spectrum_local=(cpl_image*) spectrum;
430 cpl_image_power(spectrum_local,2);
433 if (cpl_image_get_type(spectrum_local) == CPL_TYPE_DOUBLE) {
434 spectrum_data_double = cpl_image_get_data_double(spectrum_local);
436 else if (cpl_image_get_type(spectrum_local) == CPL_TYPE_FLOAT) {
437 spectrum_data_float = cpl_image_get_data_float(spectrum_local);
439 spectrum_data_int = cpl_image_get_data_int(spectrum_local);
441 check_nomsg(spectrum_badmap = cpl_image_get_bpm(spectrum_local));
442 check_nomsg(spectrum_bad = cpl_mask_get_data_const(spectrum_badmap));
444 assure( norders >= 1, CPL_ERROR_ILLEGAL_INPUT,
"Empty spectrum");
445 assure( uves_round_double(fabs(first_abs_order - last_abs_order)) + 1 == norders,
446 CPL_ERROR_INCOMPATIBLE_INPUT,
447 "Spectrum contains %d orders, but line table absolute "
448 "order numbering is %d - %d",
449 norders, first_abs_order, last_abs_order);
454 (n_traces > 1) ?
"PIXEL" :
"ORDER",
456 (n_traces > 1) ?
"PIXEL" : NULL,
457 (scale) ?
"FLUX PER WAVEL" :
"ADU",
462 "Error setting up rebinned image header");
472 for (order = 1; order <= norders; order++)
482 double lambda_min, lambda_max;
501 dispersion_relation, minx - 0.5, absorder)/absorder;
503 dispersion_relation, maxx + 0.5, absorder)/absorder;
506 uves_round_double(lambda_max / wavestep) -
507 uves_round_double(lambda_min / wavestep) + 1;
509 nlambda = uves_max_int(nlambda, nbins);
512 *rebinned_header, order,
513 wavestep * uves_round_double(lambda_min / wavestep)),
514 "Error writing adding WSTART keyword to header");
517 *rebinned_header, order,
518 wavestep * uves_round_double(lambda_max / wavestep)),
519 "Error writing adding WEND keyword to header");
522 "Range = %d - %d pix = %f - %f wlu, %d bins",
531 uves_msg_debug(
"Step size = %f wlu (%d orders x %d bins)", wavestep, norders, nlambda);
536 check_nomsg( rebinned = cpl_image_new(nlambda, norders*n_traces, cpl_image_get_type(spectrum_local)));
539 if (cpl_image_get_type(spectrum_local) == CPL_TYPE_DOUBLE) {
540 rebinned_data_double = cpl_image_get_data_double(rebinned);
542 else if (cpl_image_get_type(spectrum_local) == CPL_TYPE_FLOAT) {
543 rebinned_data_float = cpl_image_get_data_float(rebinned);
545 rebinned_data_int = cpl_image_get_data_int(rebinned);
547 rebinned_badmap = cpl_image_get_bpm(rebinned);
548 rebinned_bad = cpl_mask_get_data(rebinned_badmap);
552 uves_image_reject_all(rebinned);
554 for (order = 1; order <= norders; order++)
563 "Error reading product header");
570 "Error getting 1d dispersion relation for absolute order #%d", absorder);
574 for (trace = 1; trace <= n_traces; trace++)
576 int spectrum_row = (order - 1)*n_traces + trace;
583 for (bin = 1; bin <= nlambda && x_min <= nx+0.5; bin++)
585 double lambda = lambda_start + (bin-1) * wavestep;
587 int multiplicity = 1;
597 if (cpl_error_get_code() == CPL_ERROR_DIVISION_BY_ZERO) {
599 if (!warning_shown) {
601 "order = %d, x = %f. This might be caused "
602 "by fitting a too high degree polynomial to "
603 "too few lines. Decrease dispersion "
605 "or relax rejection parameters!",
607 warning_shown =
true;
612 assure( cpl_error_get_code() == CPL_ERROR_NONE,
613 cpl_error_get_code(),
614 "Could not invert dispersion relation");
621 (lambda - 0.5*wavestep) * absorder,
625 if (cpl_error_get_code() == CPL_ERROR_DIVISION_BY_ZERO) {
627 if (!warning_shown) {
629 "order = %d, x = %f. This might be caused "
630 "by fitting a too high degree polynomial to "
631 "too few lines. Decrease dispersion "
633 "or relax rejection parameters!",
635 warning_shown =
true;
640 assure( cpl_error_get_code() == CPL_ERROR_NONE,
641 cpl_error_get_code(),
642 "Could not invert dispersion relation");
648 (lambda + 0.5*wavestep) * absorder,
652 if (cpl_error_get_code() == CPL_ERROR_DIVISION_BY_ZERO) {
654 if (!warning_shown) {
656 "order = %d, x = %f. This might be caused "
657 "by fitting a too high degree polynomial to "
658 "too few lines. Decrease dispersion "
660 "or relax rejection parameters!",
662 warning_shown =
true;
667 assure( cpl_error_get_code() == CPL_ERROR_NONE,
668 cpl_error_get_code(),
669 "Could not invert dispersion relation");
673 if (uves_max_double(0.5, uves_min_double(nx+0.5, x_min)) <
674 uves_max_double(0.5, uves_min_double(nx+0.5, x_max)))
682 double p_min=uves_max_double(0.5, uves_min_double(nx+0.5, x_min));
683 double p_max=uves_max_double(0.5, uves_min_double(nx+0.5, x_max));
687 spectrum_data_double,
695 threshold_to_positive,
697 / (( p_max -p_min) * ( p_max -p_min));
701 spectrum_data_double,
709 threshold_to_positive,
726 dispersion_relation, x, absorder, 1)
741 if (cpl_image_get_type(spectrum_local) == CPL_TYPE_DOUBLE) {
742 rebinned_data_double[(bin-1) +
743 (spectrum_row-1)*nlambda] =
746 else if (cpl_image_get_type(spectrum_local) == CPL_TYPE_FLOAT) {
747 rebinned_data_float[(bin-1) +
748 (spectrum_row-1)*nlambda] =
751 rebinned_data_int[(bin-1) +
752 (spectrum_row-1)*nlambda] =
759 rebinned_bad[(bin-1) +
760 (spectrum_row-1)*nlambda] =
783 cpl_image_power(rebinned,0.5);
789 if (cpl_error_get_code() != CPL_ERROR_NONE)
791 uves_free_image(&rebinned);
792 uves_free_propertylist(rebinned_header);
826 const float *spectrum_data_float,
827 const int *spectrum_data_int,
828 const cpl_binary *spectrum_bad,
831 double x_min,
double x_max,
832 bool threshold_to_positive,
836 double sum_interval = 0;
843 for (x = uves_min_int(nx, uves_max_int(1, uves_round_double(x_min)));
846 x <= uves_min_int(nx, uves_max_int(1, uves_round_double(x_max)));
850 if (spectrum_bad[(x-1) + (spectrum_row-1)*nx] == CPL_BINARY_0)
854 double interval_length;
878 bool pis_rejected_prev = (x_prev < 1 ) ||
879 (spectrum_bad[(x_prev-1) + (spectrum_row-1)*nx] == CPL_BINARY_1);
880 bool pis_rejected_next = (nx < x_next) ||
881 (spectrum_bad[(x_next-1) + (spectrum_row-1)*nx] == CPL_BINARY_1);
883 if (spectrum_data_double != NULL) {
884 flux = spectrum_data_double[(x-1) + (spectrum_row-1)*nx];
886 else if (spectrum_data_float != NULL) {
887 flux = spectrum_data_float [(x-1) + (spectrum_row-1)*nx];
889 flux = spectrum_data_int [(x-1) + (spectrum_row-1)*nx];
892 if (!pis_rejected_prev && !pis_rejected_next)
898 double flux_minus, flux_plus;
899 if (spectrum_data_double != NULL) {
901 (flux + spectrum_data_double[(x_prev-1) + (spectrum_row-1)*nx])
904 (flux + spectrum_data_double[(x_next-1) + (spectrum_row-1)*nx])
907 else if (spectrum_data_float != NULL) {
909 (flux + spectrum_data_float[(x_prev-1) + (spectrum_row-1)*nx])
912 (flux + spectrum_data_float[(x_next-1) + (spectrum_row-1)*nx])
916 (flux + spectrum_data_int[(x_prev-1) + (spectrum_row-1)*nx])
919 (flux + spectrum_data_int[(x_next-1) + (spectrum_row-1)*nx])
931 double flux_center = 2*flux - (flux_minus + flux_plus) / 2.0;
935 double slope_minus = (flux_center - flux_minus )/ 0.5;
936 double slope_plus = (flux_plus - flux_center) / 0.5;
943 double lo1 = uves_max_double(x-0.5, uves_min_double(x, x_min));
944 double hi1 = uves_max_double(x-0.5, uves_min_double(x, x_max));
945 double dy1 = hi1-lo1;
949 double lo2 = uves_max_double(x, uves_min_double(x+0.5, x_min));
950 double hi2 = uves_max_double(x, uves_min_double(x+0.5, x_max));
951 double dy2 = hi2-lo2;
961 dy1 * (flux_center + slope_minus * ((lo1+hi1)/2.0 - x))
963 dy2 * (flux_center + slope_plus * ((lo2+hi2)/2.0 - x));
971 interval_length = dy1 + dy2;
978 uves_min_double(x_max, x+0.5) -
979 uves_max_double(x_min, x-0.5);
981 current_term = interval_length * flux;
993 sum_interval += interval_length;
997 if (sum_interval == 0)
1007 double result = sum*(x_max-x_min)/sum_interval;
1011 if (threshold_to_positive) {
1018 result = fabs(result);
1054 const float *spectrum_data_float,
1055 const int *spectrum_data_int,
1056 const cpl_binary *spectrum_bad,
1059 double x_min,
double x_max,
1060 bool threshold_to_positive,
1064 double sum_interval = 0;
1071 for (x = uves_min_int(nx, uves_max_int(1, uves_round_double(x_min)));
1074 x <= uves_min_int(nx, uves_max_int(1, uves_round_double(x_max)));
1078 if (spectrum_bad[(x-1) + (spectrum_row-1)*nx] == CPL_BINARY_0)
1082 double interval_length;
1083 double current_term;
1106 bool pis_rejected_prev = (x_prev < 1 ) ||
1107 (spectrum_bad[(x_prev-1) + (spectrum_row-1)*nx] == CPL_BINARY_1);
1108 bool pis_rejected_next = (nx < x_next) ||
1109 (spectrum_bad[(x_next-1) + (spectrum_row-1)*nx] == CPL_BINARY_1);
1111 if (spectrum_data_double != NULL) {
1112 flux = spectrum_data_double[(x-1) + (spectrum_row-1)*nx];
1114 else if (spectrum_data_float != NULL) {
1115 flux = spectrum_data_float [(x-1) + (spectrum_row-1)*nx];
1117 flux = spectrum_data_int [(x-1) + (spectrum_row-1)*nx];
1120 if (!pis_rejected_prev && !pis_rejected_next)
1126 double flux_minus, flux_plus;
1127 if (spectrum_data_double != NULL) {
1129 (flux + spectrum_data_double[(x_prev-1) + (spectrum_row-1)*nx])
1132 (flux + spectrum_data_double[(x_next-1) + (spectrum_row-1)*nx])
1135 else if (spectrum_data_float != NULL) {
1137 (flux + spectrum_data_float[(x_prev-1) + (spectrum_row-1)*nx])
1140 (flux + spectrum_data_float[(x_next-1) + (spectrum_row-1)*nx])
1144 (flux + spectrum_data_int[(x_prev-1) + (spectrum_row-1)*nx])
1147 (flux + spectrum_data_int[(x_next-1) + (spectrum_row-1)*nx])
1159 double flux_center = 4*flux - (flux_minus + flux_plus) / 4.0;
1163 double slope_minus = 4.0 * (flux_center + flux_minus );
1164 double slope_plus = 4.0 * (flux_plus + flux_center);
1171 double lo1 = uves_max_double(x-0.5, uves_min_double(x, x_min));
1172 double hi1 = uves_max_double(x-0.5, uves_min_double(x, x_max));
1173 double dy1 = hi1-lo1;
1177 double lo2 = uves_max_double(x, uves_min_double(x+0.5, x_min));
1178 double hi2 = uves_max_double(x, uves_min_double(x+0.5, x_max));
1179 double dy2 = hi2-lo2;
1189 dy1*dy1 * (flux_center + slope_minus *
1190 ((lo1+hi1)/2.0 - x) * ((lo1+hi1)/2.0 - x) )
1192 dy2*dy2 * (flux_center + slope_plus *
1193 ((lo2+hi2)/2.0 - x) * ((lo2+hi2)/2.0 - x) );
1201 interval_length = dy1 + dy2;
1208 uves_min_double(x_max, x+0.5) -
1209 uves_max_double(x_min, x-0.5);
1211 current_term = interval_length * interval_length * flux;
1222 sum += current_term;
1223 sum_interval += interval_length;
1227 if (sum_interval == 0)
1237 double result = sum*(x_max-x_min)/sum_interval*
1238 (x_max-x_min)/sum_interval;
1242 if (threshold_to_positive) {
1249 result = fabs(result);
cpl_error_code uves_pfits_set_wstart(uves_propertylist *plist, int order, double wstart)
Write the wstart keyword.
polynomial * uves_polynomial_collapse(const polynomial *p, int varno, double value)
Collapse a polynomial by fixing one variable to a constant.
void uves_polynomial_delete(polynomial **p)
Delete a polynomial.
#define uves_msg_warning(...)
Print an warning message.
int uves_absolute_order(int first_abs_order, int last_abs_order, int relative_order)
Get the absolute order number.
#define passure(BOOL,...)
double uves_pfits_get_wstart(const uves_propertylist *plist, int order)
Read the wstart keyword.
double uves_polynomial_derivative_2d(const polynomial *p, double x1, double x2, int varno)
Evaluate the partial derivative of a 2d polynomial.
uves_propertylist * uves_initialize_image_header(const char *ctype1, const char *ctype2, const char *cunit1, const char *cunit2, const char *bunit, const double bscale, double crval1, double crval2, double crpix1, double crpix2, double cdelt1, double cdelt2)
Initialize image header.
double uves_polynomial_evaluate_2d(const polynomial *p, double x1, double x2)
Evaluate a 2d polynomial.
cpl_image * uves_rebin(const cpl_image *spectrum, const cpl_parameterlist *parameters, const char *context, const cpl_table *linetable, const polynomial *dispersion_relation, int first_abs_order, int last_abs_order, int n_traces, bool threshold_to_positive, bool is_noise, uves_propertylist **rebinned_header)
Rebin a spectrum.
const char * uves_tostring_cpl_type(cpl_type t)
Convert a CPL type to a string.
#define uves_error_reset()
static double integrate_flux(const double *spectrum_data_double, const float *spectrum_data_float, const int *spectrum_data_int, const cpl_binary *spectrum_bad, int spectrum_row, int nx, double x_min, double x_max, bool threshold_to_positive, bool *is_bad)
Integrate flux.
#define uves_msg_debug(...)
Print a debug message.
cpl_parameterlist * uves_rebin_define_parameters(void)
Define recipe parameters used for rebinning.
cpl_error_code uves_pfits_set_wend(uves_propertylist *plist, int order, double wend)
Write the wend keyword.
static double integrate_noise(const double *spectrum_data_double, const float *spectrum_data_float, const int *spectrum_data_int, const cpl_binary *spectrum_bad, int spectrum_row, int nx, double x_min, double x_max, bool threshold_to_positive, bool *is_bad)
Integrate variance.
double uves_polynomial_solve_1d(const polynomial *p, double value, double guess, int multiplicity)
Solve p(x) = value.