46 #include "uves_reduce.h"
49 #include <uves_extract.h>
50 #include <uves_backsub.h>
51 #include <uves_parameters.h>
52 #include <uves_flatfield.h>
53 #include <uves_rebin.h>
54 #include <uves_merge.h>
55 #include <uves_utils_cpl.h>
56 #include <uves_utils_wrappers.h>
57 #include <uves_pfits.h>
59 #include <uves_dump.h>
60 #include <uves_qclog.h>
61 #include <uves_plot.h>
62 #include <uves_error.h>
70 #define UVES_MIN_LINE_ROWS_TO_MAKE_FIT 5
71 #define UVES_BLAZE_DUMMY_VAL 999.
74 cpl_image *backsubbed_noise,
76 const cpl_image *master_flat,
77 cpl_image *mflat_noise,
78 const cpl_table *ordertable,
80 const cpl_table *linetable,
90 const cpl_parameterlist *parameters,
93 flatfielding_method ff_method,
94 extract_method ee_method,
95 merge_method m_method,
100 cpl_table **cosmic_mask,
101 cpl_image **wave_map,
102 cpl_image **flatfielded_variance,
104 cpl_image **resampled_spectrum,
105 cpl_image **resampled_mf,
106 cpl_image **merged_sky,
107 cpl_image **rebinned_spectrum,
108 cpl_image **rebinned_noise,
110 cpl_image **merged_spectrum,
111 cpl_image **merged_noise,
113 cpl_table** info_tbl,
114 cpl_table **order_trace);
118 cpl_image *rebinned_obj_noise,
120 const cpl_image *rebinned_sky1,
121 const cpl_image *rebinned_sky1_noise,
123 const cpl_image *rebinned_sky2,
124 const cpl_image *rebinned_sky2_noise,
126 cpl_image **merged_obj,
127 cpl_image **merged_obj_noise,
129 const cpl_image *merged_sky1,
130 const cpl_image *merged_sky1_noise,
132 const cpl_image *merged_sky2,
133 const cpl_image *merged_sky2_noise,
142 cpl_image *obj_noise,
146 const cpl_image *sky1,
147 const cpl_image *sky1_noise,
151 const cpl_image *sky2,
152 const cpl_image *sky2_noise,
158 double *common_start,
161 static double get_offset(
const cpl_image *back_subbed,
162 const cpl_table *ordertable,
170 const cpl_image *spectrum_noise);
190 const char *name =
"";
191 char *full_name = NULL;
192 cpl_parameterlist *parameters = NULL;
193 cpl_parameter *p = NULL;
195 parameters = cpl_parameterlist_new();
200 if (cpl_error_get_code() == CPL_ERROR_NONE)
202 uves_propagate_parameters_step(UVES_BACKSUB_ID, parameters,
203 UVES_REDUCE_ID, NULL);
210 if (cpl_error_get_code() == CPL_ERROR_NONE)
212 uves_propagate_parameters_step(UVES_EXTRACT_ID, parameters,
213 UVES_REDUCE_ID, NULL);
220 if (cpl_error_get_code() == CPL_ERROR_NONE)
223 full_name = uves_sprintf(
"%s.%s", UVES_REDUCE_ID, name);
225 uves_parameter_new_range(p, full_name,
227 "Extraction slit length (in pixels). "
228 "If negative, the value "
229 "inferred from the raw frame header is used",
234 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
235 cpl_parameterlist_append(parameters, p);
239 if (cpl_error_get_code() == CPL_ERROR_NONE)
242 full_name = uves_sprintf(
"%s.%s", UVES_REDUCE_ID, name);
244 uves_parameter_new_value(p, full_name,
246 "Do sky-subtraction (only applicable to linear "
247 "and average extractions)?",
251 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
252 cpl_parameterlist_append(parameters, p);
256 if (cpl_error_get_code() == CPL_ERROR_NONE)
259 full_name = uves_sprintf(
"%s.%s", UVES_REDUCE_ID, name);
261 uves_parameter_new_value(p, full_name,
263 "Offset (in pixels) of extraction slit "
264 "with respect to center of order. "
265 "This parameter applies to linear/average/"
266 "optimal extraction. "
267 "For linear/average extraction, if the related "
268 "parameter objslit is negative, the offset is "
269 "automatically determined by measuring the "
270 "actual object position. ",
274 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
275 cpl_parameterlist_append(parameters, p);
279 if (cpl_error_get_code() == CPL_ERROR_NONE)
282 full_name = uves_sprintf(
"%s.%s", UVES_REDUCE_ID, name);
284 uves_parameter_new_range(p, full_name,
286 "Object window size (in pixels). This must "
287 "be less than the total slit length. If "
288 "negative, the default value (half of full "
289 "slit length) is used. The upper and lower "
290 "sky windows are defined as the part of the "
291 "full slit (if any) outside the object "
292 "window. The center of the object window "
293 "is determined by the offset parameter. "
294 "This parameter does not apply to optimal "
300 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
301 cpl_parameterlist_append(parameters, p);
305 if (cpl_error_get_code() == CPL_ERROR_NONE)
308 full_name = uves_sprintf(
"%s.%s", UVES_REDUCE_ID, name);
310 uves_parameter_new_value(p, full_name,
312 "If enabled (recommended), the provided "
313 "dispersion solutions "
314 "obtained at different slit positions are "
315 "interpolated linearly at the actually "
316 "measured position of the object/sky. "
317 "Line tilt correction is currently not supported "
318 "for 2d extraction, in which case the "
319 "dispersion solution obtained at the middle of "
320 "the slit is always used.",
324 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
325 cpl_parameterlist_append(parameters, p);
335 if (cpl_error_get_code() == CPL_ERROR_NONE)
338 full_name = uves_sprintf(
"%s.%s", UVES_REDUCE_ID, name);
340 uves_parameter_new_enum(p, full_name,
342 "Flat-fielding method. If set to 'pixel', "
343 "flat-fielding is done in pixel-pixel space "
344 "(before extraction); if set to 'extract', "
345 "flat-fielding is performed in pixel-order "
346 "space (i.e. after extraction). If set to "
347 "'no', no flat-field correction is done",
352 "pixel",
"extract",
"no");
354 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
355 cpl_parameterlist_append(parameters, p);
363 if (cpl_error_get_code() == CPL_ERROR_NONE)
388 if (cpl_error_get_code() == CPL_ERROR_NONE)
390 uves_propagate_parameters_step(UVES_REBIN_ID, parameters,
391 UVES_REDUCE_ID, NULL);
398 if (cpl_error_get_code() == CPL_ERROR_NONE)
401 full_name = uves_sprintf(
"%s.%s", UVES_REDUCE_ID, name);
403 uves_parameter_new_enum(p, full_name,
405 "Order merging method. If 'optimal', the "
406 "flux in the overlapping region is set "
407 "to the (optimally computed, using the "
408 "uncertainties) average of single order "
409 "spectra. If 'sum', the flux in the "
410 "overlapping region is computed as the "
411 "sum of the single order spectra. If 'noappend' "
412 "the spectrum is simply rebinned but not merged."
413 "If flat-fielding is done, method 'optimal' "
414 "is recommended, otherwise 'sum'.",
418 "optimal",
"sum",
"noappend");
420 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
421 cpl_parameterlist_append(parameters, p);
425 name =
"merge_delt1";
426 full_name = uves_sprintf(
"%s.%s", UVES_REDUCE_ID, name);
428 uves_parameter_new_range(p, full_name,
430 "Order merging left hand (short wavelength) "
431 "cut. To reduce the amount of order "
432 "overlapping regions we allow to cut short and "
433 "long wavelength ranges. "
434 "This may reduce the ripple possibly "
435 "introduced by the order merging. "
436 "Suggested values are: "
437 "10 (W<=390), 12 (390<W<=437, 520<W<=564), "
438 "14 (437<W<=520, 564<W) ",
442 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
443 cpl_parameterlist_append(parameters, p);
447 name =
"merge_delt2";
448 full_name = uves_sprintf(
"%s.%s", UVES_REDUCE_ID, name);
450 uves_parameter_new_range(p, full_name,
452 "Order merging right hand (long wavelength) "
453 "cut. To reduce the amount of order "
454 "overlapping regions we allow to cut short and "
455 "long wavelength ranges. "
456 "This may reduce the ripple possibly "
457 "introduced by the order merging. "
458 "Suggested values is 4",
462 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name);
463 cpl_parameterlist_append(parameters, p);
470 if (cpl_error_get_code() != CPL_ERROR_NONE)
472 cpl_msg_error(__func__,
"Creation of reduction parameters failed: '%s'",
473 cpl_error_get_where());
474 cpl_parameterlist_delete(parameters);
578 const cpl_image *master_bias,
580 const cpl_image *master_dark,
582 const cpl_image *master_flat,
584 const cpl_table *ordertable,
586 const cpl_table *linetable[3],
596 const cpl_parameterlist *parameters,
602 cpl_table **cosmic_mask,
603 cpl_image **wave_map,
604 cpl_image **background,
605 cpl_image **flatfielded_variance,
607 cpl_image **resampled_spectrum,
608 cpl_image **resampled_mf,
609 cpl_image **merged_sky,
611 cpl_image **rebinned_spectrum,
612 cpl_image **rebinned_noise,
614 cpl_image **merged_spectrum ,
615 cpl_image **merged_noise,
618 cpl_image **reduced_rebinned_spectrum,
619 cpl_image **reduced_rebinned_noise,
620 cpl_image **reduced_spectrum ,
621 cpl_image **reduced_noise,
622 cpl_table **info_tbl,
623 double *extraction_slit,
624 cpl_table **order_trace)
628 flatfielding_method ff_method;
629 merge_method m_method;
630 extract_method ex_method;
631 bool blaze_corr=
false;
638 cpl_image *back_subbed = NULL;
639 cpl_image *backsubbed_noise = NULL;
641 cpl_image *mflat_noise = NULL;
643 cpl_image *simple_extracted = NULL;
644 cpl_image *simple_extracted_mf = NULL;
646 cpl_image *sky_lo = NULL;
647 cpl_image *sky_lo_noise = NULL;
648 cpl_image *sky_hi = NULL;
649 cpl_image *sky_hi_noise = NULL;
653 cpl_image *sky_lo_rebinned = NULL;
654 cpl_image *sky_lo_rebinned_noise = NULL;
655 cpl_image *sky_hi_rebinned = NULL;
656 cpl_image *sky_hi_rebinned_noise = NULL;
660 char *subcontext = NULL;
661 double header_full_slit;
663 char *ex_method_string = NULL;
666 bool has_fnoise=
false;
670 passure( background != NULL,
" "); *background = NULL;
672 passure( rebinned_spectrum != NULL,
" "); *rebinned_spectrum = NULL;
673 passure( rebinned_noise != NULL,
" "); *rebinned_noise = NULL;
674 passure( rebinned_header != NULL,
" "); *rebinned_header = NULL;
675 passure( merged_spectrum != NULL,
" "); *merged_spectrum = NULL;
676 passure( merged_sky != NULL,
" "); *merged_sky = NULL;
677 passure( merged_noise != NULL,
" "); *merged_noise = NULL;
678 passure( merged_header != NULL,
" "); *merged_header = NULL;
679 passure( reduced_rebinned_spectrum != NULL,
" "); *reduced_rebinned_spectrum = NULL;
680 passure( reduced_rebinned_noise != NULL,
" "); *reduced_rebinned_noise = NULL;
681 passure( reduced_spectrum != NULL,
" "); *reduced_spectrum = NULL;
682 passure( reduced_noise != NULL,
" "); *reduced_noise = NULL;
684 passure( (flatfielded_variance == NULL) == (flatfielded_variance_header == NULL),
685 "%d %d", flatfielded_variance == NULL, flatfielded_variance_header == NULL);
687 assure_nomsg( extraction_slit != NULL, CPL_ERROR_NULL_INPUT );
692 if(strcmp(mode,
".efficiency")==0) {
693 sprintf(context,
"%s%s",rec_id,mode);
695 sprintf(context,
"%s",rec_id);
698 "Could not read flat-fielding method");
700 assure( ff_method == FF_NO || master_flat != NULL, CPL_ERROR_NULL_INPUT,
701 "Flat-fielding requested, but no flat field provided");
705 UVES_REDUCE_ID
"." UVES_EXTRACT_ID),
706 "Could not get extraction method");
708 assure( ex_method != EXTRACT_WEIGHTED, CPL_ERROR_ILLEGAL_INPUT,
709 "Weighted extraction is used only internally, "
710 "as a part of optimal extraction");
713 "Could not get merging method");
722 check( uves_get_parameter(parameters, rec_id, UVES_REDUCE_ID,
723 "skysub", CPL_TYPE_BOOL, &sky_sub),
724 "Could not read parameter");
726 check( uves_get_parameter(parameters, rec_id, UVES_REDUCE_ID,
727 "tiltcorr", CPL_TYPE_BOOL, &tilt_corr),
728 "Could not read parameter");
730 assure( !blaze_corr || ff_method != FF_NO, CPL_ERROR_INCOMPATIBLE_INPUT,
731 "Sorry, cannot apply blaze function "
732 "correction when no flatfielding is done");
734 if (blaze_corr && ex_method == EXTRACT_2D)
737 "for 2d extraction");
740 if (ff_method == FF_NO && m_method == MERGE_OPTIMAL)
743 "Is this really what you want?");
745 if (ff_method != FF_NO && m_method == MERGE_SUM)
748 "Is this really what you want?");
751 check( uves_get_parameter(parameters, rec_id, UVES_REDUCE_ID,
"slitlength",
752 CPL_TYPE_DOUBLE, &full_slit),
"Could not read parameter");
754 check( uves_get_parameter(parameters, rec_id, UVES_REDUCE_ID,
"objoffset",
755 CPL_TYPE_DOUBLE, &obj_offset),
756 "Could not read parameter");
757 check( uves_get_parameter(parameters, rec_id, UVES_REDUCE_ID,
"objslit",
758 CPL_TYPE_DOUBLE, &obj_slit),
759 "Could not read parameter");
763 subcontext = uves_sprintf(
"%s.%s", rec_id, UVES_REDUCE_ID);
766 check( back_subbed = cpl_image_duplicate(raw_image),
767 "Error copying raw image");
770 if (master_bias != NULL)
772 uves_msg(
"Subtracting master bias");
774 "Error subtracting master bias");
777 int pn = PORT_ID(chip);
779 sprintf(key_name,
"ESO QC OUT%d RON MASTER", pn);
784 uves_msg(
"key %s not found, compute it on the fly",key_name);
793 for(
int i=0;i<niter;i++){
794 bmin=cpl_image_get_min(master_bias);
795 bmax=cpl_image_get_max(master_bias);
796 bavg=cpl_image_get_mean(master_bias);
797 brms=cpl_image_get_stdev(master_bias);
798 msk=cpl_mask_threshold_image_create(master_bias,bavg-kappa*brms,bavg+kappa*brms);
800 cpl_image_reject_from_mask(master_bias, msk);
801 cpl_mask_delete(msk);
804 bnoise=cpl_image_get_stdev(master_bias);
809 "Master bias RMS on frame");
817 uves_msg(
"Skipping bias subtraction");
821 if (master_dark != NULL)
823 uves_msg(
"Subtracting master dark");
825 master_dark, mdark_header),
826 "Error subtracting master dark");
836 for(
int i=0;i<niter;i++){
837 dmin=cpl_image_get_min(master_dark);
838 dmax=cpl_image_get_max(master_dark);
839 davg=cpl_image_get_mean(master_dark);
840 drms=cpl_image_get_stdev(master_dark);
841 msk=cpl_mask_threshold_image_create(master_dark,davg-kappa*drms,davg+kappa*drms);
843 cpl_image_reject_from_mask(master_dark, msk);
844 cpl_mask_delete(msk);
848 dnoise=cpl_image_get_stdev(master_dark);
854 "Master dark RMS on frame");
856 "Master dark RMS on frame");
860 uves_msg(
"Skipping dark subtraction");
863 if (master_flat != NULL)
870 if (debug_mode)
check( uves_save_image_local(
"Bias/dark subtracted raw image",
"pre",
871 back_subbed, chip, -1, -1, rotated_header,
true),
872 "Error saving image");
879 "Could not calculate noise image");
882 if (debug_mode)
check( uves_save_image_local(
"Background subtracted raw image noise",
883 "errb", backsubbed_noise,
884 chip, -1, -1, rotated_header,
true),
885 "Error saving image");
888 uves_msg(
"Subtracting inter-order background");
890 check( uves_backsub_spline(back_subbed, raw_header,
891 ordertable, order_locations,
892 parameters, subcontext,
896 "Error subtracting background");
899 if (debug_mode)
check( uves_save_image_local(
"Background subtracted raw image",
"b",
900 back_subbed, chip, -1, -1, rotated_header,
true),
901 "Error saving image");
907 if (ff_method == FF_NO)
909 uves_msg(
"Skipping flat-field correction");
912 if (ff_method != FF_NO || resampled_mf != NULL)
919 check( uves_save_image_local(
"Master flat image",
"mf",
921 chip, -1, -1, rotated_header,
true),
922 "Error saving master flat image");
928 "Error reading number of raw flat field frames "
929 "used for master flat image");
931 uves_msg(
"Creating master flat noise image");
934 mflat_datancom,chip),
935 "Could not define master flat noise");
941 check( uves_save_image_local(
"Master flat noise",
"errmf", mflat_noise,
942 chip, -1, -1, rotated_header,
true),
943 "Error saving master flat image");
952 "Could not read slit length");
960 full_slit = uves_max_double(1.0, header_full_slit - 2);
965 if (full_slit > header_full_slit)
968 "is larger than input header slit "
969 "length (%e pixels)",
970 full_slit, header_full_slit);
974 uves_msg(
"Slit length = %.2f pixels", full_slit);
975 *extraction_slit = full_slit;
977 if (ff_method == FF_PIXEL)
979 uves_msg(
"Dividing by normalized master flat-field (method = pixel)");
982 master_flat, mflat_noise),
983 "Could not perform flat-fielding");
988 check( uves_save_image_local(
"Flat-fielded image",
"fb",
989 back_subbed, chip, -1, -1,
990 rotated_header,
true),
991 "Error saving flat-fielded image");
993 check( uves_save_image_local(
"Flat-fielded image noise",
"errfb",
994 backsubbed_noise, chip, -1, -1,
995 rotated_header,
true),
996 "Error saving noise of flat-fielded image");
1003 case EXTRACT_OPTIMAL:
1005 int window_number = 2;
1014 linetable[window_number-1],
1016 dispersion_relation,
1035 flatfielded_variance,
1036 flatfielded_variance_header,
1050 "Error during reduction");
1055 check(( *reduced_spectrum = cpl_image_duplicate(*merged_spectrum),
1056 *reduced_noise = cpl_image_duplicate(*merged_noise),
1057 *reduced_rebinned_spectrum = cpl_image_duplicate(*rebinned_spectrum),
1058 *reduced_rebinned_noise = cpl_image_duplicate(*rebinned_noise)),
1059 "Error creating sky-subtracted spectra");
1062 case EXTRACT_LINEAR:
1063 case EXTRACT_AVERAGE:
1070 const char *slicer_name;
1072 double obj_hi, obj_lo;
1073 double sky_lo_slit, sky_hi_slit;
1082 "Could not read slicer id");
1084 uves_msg(
"Slicer name = '%s'%s", slicer_name,
1085 (strcmp(slicer_name,
"FREE") == 0) ?
" (no slicer)" :
"");
1087 if ( strncmp(slicer_name,
"SLIC", 4) == 0)
1093 obj_hi = uves_min_double(+full_slit/2, obj_offset + full_slit/2);
1094 obj_lo = uves_max_double(-full_slit/2, obj_offset - full_slit/2);
1096 obj_slit = obj_hi - obj_lo;
1101 uves_msg(
"Extraction slits (full slit = %.2f pixels)", full_slit);
1102 uves_msg(
"|* Sky 1 *|******** Obj ********|* Sky 2 *|");
1103 uves_msg(
"|* %-5.1f *|******* %-5.1f *******|* %-5.1f *|",
1104 0.0, obj_slit, 0.0);
1109 assure( strncmp(slicer_name,
"FREE", 4) == 0, CPL_ERROR_UNSUPPORTED_MODE,
1110 "Unrecognized slicer name: '%s'. "
1111 "Recognized names include 'FREE', 'SLIC#1', 'SLIC#2', 'SLIC#3'.",
1119 ordertable, order_locations,
1123 "Could not find object offset");
1125 uves_msg(
"Measured object position = %.2f +- %.2f pixels",
1126 obj_offset, doffset);
1132 obj_hi = uves_min_double(+full_slit/2,
1133 obj_offset + full_slit/4.0);
1134 obj_lo = uves_max_double(-full_slit/2,
1135 obj_offset - full_slit/4.0);
1140 obj_hi = uves_min_double(+full_slit/2,
1141 obj_offset + full_slit/2.0);
1142 obj_lo = uves_max_double(-full_slit/2,
1143 obj_offset - full_slit/2.0);
1145 obj_slit = obj_hi - obj_lo;
1150 uves_msg(
"Object offset = %.2f pixels", obj_offset);
1152 obj_hi = obj_offset + obj_slit / 2;
1153 obj_lo = obj_offset - obj_slit / 2;
1156 uves_msg(
"Object slit = %.2f pixels", obj_slit);
1158 assure( -full_slit / 2 < obj_offset && obj_offset < full_slit / 2,
1159 CPL_ERROR_ILLEGAL_INPUT,
1160 "Object is outside slit! Offset = %f, Slit length = %f",
1161 obj_offset, full_slit);
1166 sky_lo_slit = obj_lo - (-full_slit/2);
1167 sky_hi_slit = full_slit/2 - obj_hi;
1169 assure( sky_lo_slit > 0 || sky_hi_slit > 0, CPL_ERROR_ILLEGAL_INPUT,
1170 "At least one sky slit length must be positive. "
1171 "They are %f and %f pixels", sky_lo_slit, sky_hi_slit);
1179 uves_msg(
"Extraction slits (full slit = %.2f pixels)", full_slit);
1180 uves_msg(
"|*** Sky 1 **%s|**** Obj ****|%s** Sky 2 ***|",
1181 (obj_lo > -obj_hi) ?
"*" :
"",
1182 (obj_lo > -obj_hi) ?
"" :
"*");
1183 uves_msg(
"|*** %-5.1f **%s|*** %-5.1f ***|%s** %-5.1f ***|",
1184 sky_lo_slit, (obj_lo > -obj_hi) ?
"*" :
"",
1185 obj_slit , (obj_lo > -obj_hi) ?
"" :
"*",
1202 if ( sky_lo_slit > 0 )
1204 uves_msg(
"Processing sky 1 window");
1214 dispersion_relation,
1216 -full_slit/2 + sky_lo_slit/2,
1240 &sky_lo_rebinned_noise,
1241 &sky_lo_rebinned_header,
1247 "Error processing lower sky window");
1252 sky_lo_rebinned = NULL;
1258 if ( sky_hi_slit > 0 )
1260 uves_msg(
"Processing sky 2 window");
1262 uves_free_propertylist(rebinned_header);
1272 dispersion_relation,
1274 full_slit/2 - sky_hi_slit/2,
1298 &sky_hi_rebinned_noise,
1299 &sky_hi_rebinned_header,
1305 "Error processing upper sky window");
1310 sky_hi_rebinned = NULL;
1316 uves_msg(
"Processing object window");
1317 uves_free_propertylist(rebinned_header);
1319 master_flat, mflat_noise,
1320 ordertable, order_locations,
1321 linetable[window_number-1],
1323 dispersion_relation,
1343 flatfielded_variance,
1344 flatfielded_variance_header,
1356 "Error processing object window");
1358 if (info_tbl != NULL && *info_tbl != NULL)
1363 for (i = 0; i < cpl_table_get_nrow(*info_tbl); i++)
1365 cpl_table_set_double(*info_tbl,
"ObjPosOnSlit", i,
1366 cpl_table_get_double(*info_tbl,
"ObjPosOnSlit", i, NULL)
1368 ((sky_lo_slit >= 0) ? sky_lo_slit : 0));
1379 check(( *reduced_spectrum = cpl_image_duplicate(*merged_spectrum),
1380 *reduced_noise = cpl_image_duplicate(*merged_noise)),
1381 "Error allocating sky-subtracted spectra");
1384 check(( *reduced_rebinned_spectrum =
1385 cpl_image_duplicate(*rebinned_spectrum),
1386 *reduced_rebinned_noise =
1387 cpl_image_duplicate(*rebinned_noise)),
1388 "Error allocating sky-subtracted spectra");
1390 if (sky_lo != NULL || sky_hi != NULL)
1394 check( *merged_sky =
1396 *reduced_rebinned_noise, *rebinned_header,
1397 sky_lo_rebinned, sky_lo_rebinned_noise,
1398 sky_lo_rebinned_header,
1399 sky_hi_rebinned, sky_hi_rebinned_noise,
1400 sky_hi_rebinned_header,
1401 reduced_spectrum, reduced_noise, *merged_header,
1402 sky_lo, sky_lo_noise, sky_lo_header,
1403 sky_hi, sky_hi_noise, sky_hi_header,
1404 (ex_method == EXTRACT_AVERAGE) ? 1.0 : obj_slit,
1405 (ex_method == EXTRACT_AVERAGE) ? 1.0 : sky_lo_slit,
1406 (ex_method == EXTRACT_AVERAGE) ? 1.0 : sky_hi_slit),
1407 "Could not subtract sky");
1409 if (*merged_sky == NULL)
1425 int window_number = 2;
1428 int half_slit_length;
1433 uves_max_int(1, uves_round_double(header_full_slit/2) - 1);
1442 linetable[window_number-1],
1444 dispersion_relation,
1477 "Error during reduction");
1479 if (x_header != NULL)
1482 uves_round_double(2*half_slit_length));
1484 if (rebinned_header != NULL)
1487 uves_round_double(2*half_slit_length));
1489 if (merged_header != NULL)
1492 uves_round_double(2*half_slit_length));
1499 check(( *reduced_spectrum = cpl_image_duplicate(*merged_spectrum),
1500 *reduced_noise = cpl_image_duplicate(*merged_noise),
1501 *reduced_rebinned_spectrum = cpl_image_duplicate(*rebinned_spectrum),
1502 *reduced_rebinned_noise = cpl_image_duplicate(*rebinned_noise)),
1503 "Error allocating reduced spectra");
1507 assure(
false, CPL_ERROR_ILLEGAL_INPUT,
1508 "Unknown extraction method: %d", ex_method);
1513 uves_free_image(&back_subbed);
1514 uves_free_image(&backsubbed_noise);
1515 uves_free_image(&mflat_noise);
1516 uves_free_image(&simple_extracted);
1517 uves_free_image(&simple_extracted_mf);
1518 uves_free_image(&sky_lo);
1519 uves_free_image(&sky_lo_noise);
1520 uves_free_image(&sky_hi);
1521 uves_free_image(&sky_hi_noise);
1522 uves_free_image(&sky_lo_rebinned);
1523 uves_free_image(&sky_lo_rebinned_noise);
1524 uves_free_image(&sky_hi_rebinned);
1525 uves_free_image(&sky_hi_rebinned_noise);
1526 uves_free_propertylist(&sky_lo_header);
1527 uves_free_propertylist(&sky_hi_header);
1528 uves_free_propertylist(&sky_lo_rebinned_header);
1529 uves_free_propertylist(&sky_hi_rebinned_header);
1531 cpl_free(subcontext);
1532 cpl_free(ex_method_string);
1534 if (cpl_error_get_code() != CPL_ERROR_NONE)
1536 uves_free_image(background);
1537 uves_free_image(flatfielded_variance);
1538 uves_free_propertylist(flatfielded_variance_header);
1539 uves_free_image(resampled_spectrum);
1540 uves_free_image(resampled_mf);
1541 uves_free_image(merged_sky);
1542 uves_free_image(rebinned_spectrum);
1543 uves_free_image(rebinned_noise);
1544 uves_free_propertylist(rebinned_header);
1546 uves_free_image(merged_noise);
1547 uves_free_image(merged_spectrum);
1548 uves_free_propertylist(merged_header);
1551 return cpl_error_get_code();
1574 cpl_table *offset = cpl_table_new(3);
1576 double offset1, offset2;
1579 cpl_table_new_column(offset,
"Index", CPL_TYPE_INT);
1580 cpl_table_new_column(offset,
"Offset", CPL_TYPE_DOUBLE);
1585 for (i = 0; i < 3; i++) {
1586 cpl_table_set_int(offset,
"Index", i, i);
1587 cpl_table_set_double(offset,
"Offset", i,
1591 cpl_table_get_double(offset,
"Offset", i, NULL));
1595 uves_sort_table_1(offset,
"Offset", reverse);
1599 if (objoffset <= cpl_table_get_double(offset,
"Offset", 1, NULL))
1601 ilow = cpl_table_get_int(offset,
"Index", 0, NULL);
1602 ihigh = cpl_table_get_int(offset,
"Index", 1, NULL);
1603 offset1 = cpl_table_get_double(offset,
"Offset", 0, NULL);
1604 offset2 = cpl_table_get_double(offset,
"Offset", 1, NULL);
1608 ilow = cpl_table_get_int(offset,
"Index", 1, NULL);
1609 ihigh = cpl_table_get_int(offset,
"Index", 2, NULL);
1610 offset1 = cpl_table_get_double(offset,
"Offset", 1, NULL);
1611 offset2 = cpl_table_get_double(offset,
"Offset", 2, NULL);
1614 uves_msg(
"Interpolating dispersion relation at offset = %.2f",
1617 uves_msg_debug(
"Using previous solutions at %.2f and %.2f pixels",
1622 assure( offset1 < offset2,
1623 CPL_ERROR_DIVISION_BY_ZERO,
1624 "Dispersion solution %d offset = %.2f pixels; "
1625 "dispersion solution %d offset = %.2f pixels; cannot extrapolate",
1641 double a = (offset2 - objoffset) / (offset2 - offset1);
1642 double b = (offset1 - objoffset) / (offset1 - offset2);
1656 uves_free_table(&offset);
1744 static cpl_error_code
1746 cpl_image *backsubbed_noise,
1748 const cpl_image *master_flat,
1749 cpl_image *mflat_noise,
1750 const cpl_table *ordertable,
1752 const cpl_table *linetable,
1758 enum uves_chip chip,
1762 const cpl_parameterlist *parameters,
1763 const char *context,
1765 flatfielding_method ff_method,
1766 extract_method ex_method,
1767 merge_method m_method,
1771 cpl_table **cosmic_mask,
1772 cpl_image **wave_map,
1773 cpl_image **flatfielded_variance,
1775 cpl_image **resampled_spectrum,
1776 cpl_image **resampled_mf,
1777 cpl_image **merged_sky,
1778 cpl_image **rebinned_spectrum,
1779 cpl_image **rebinned_noise,
1781 cpl_image **merged_spectrum,
1782 cpl_image **merged_noise,
1784 cpl_table **info_tbl,
1785 cpl_table **order_trace)
1787 cpl_image *extracted = NULL;
1788 cpl_image *extracted_noff = NULL;
1789 cpl_image *extracted_noise = NULL;
1790 cpl_image *extracted_sky = NULL;
1791 cpl_image *extracted_sky_noise = NULL;
1792 cpl_image *blaze_ratio = NULL;
1795 cpl_image *cosmic_image = NULL;
1796 cpl_image *weights = NULL;
1797 cpl_table *profile_table = NULL;
1800 cpl_image *extracted_mf = NULL;
1801 cpl_image *extracted_mf_noise = NULL;
1803 cpl_image *rebinned_sky = NULL;
1804 cpl_image *rebinned_sky_noise = NULL;
1805 cpl_image *merged_sky_noise = NULL;
1812 cpl_table *poly_table = NULL;
1813 cpl_image *temp_image = NULL;
1817 int first_abs_order, last_abs_order;
1818 int filename_window;
1827 passure((ff_method != FF_EXTRACT && resampled_mf == NULL)
1829 master_flat != NULL,
" ");
1833 passure( !blaze_correct || ff_method != FF_NO,
" ");
1835 passure( ex_method != EXTRACT_OPTIMAL || merged_sky != NULL,
" ");
1836 passure( ex_method != EXTRACT_OPTIMAL || cosmic_mask != NULL,
" ");
1838 passure(1 <= window && window <= 3,
"Illegal window: %d", window);
1840 passure( (x == NULL) == (x_header == NULL) &&
1841 (x == NULL) == (fx == NULL),
" ");
1847 check( uves_get_parameter(parameters, NULL,
1848 context,
"merge_delt1",
1849 CPL_TYPE_DOUBLE, &delt1),
1850 "Could not read parameter delt1");
1852 check( uves_get_parameter(parameters, NULL,
1853 context,
"merge_delt2",
1854 CPL_TYPE_DOUBLE, &delt2),
1855 "Could not read parameter delt2");
1862 if (ex_method == EXTRACT_OPTIMAL || ex_method == EXTRACT_2D)
1870 filename_window = -1;
1875 filename_window = window;
1878 n_traces = (ex_method == EXTRACT_2D) ? uves_round_double(slit_length) : 1;
1881 "Could not read order numbers from line table header");
1883 "Could not read order numbers from line table header");
1889 if( ff_method == FF_EXTRACT ) {
1891 backsubbed_header));
1912 &extracted_sky_noise,
1916 &profile_table : NULL,
1921 "Error extracting spectrum");
1924 *x = cpl_image_duplicate(extracted);
1928 if (ex_method == EXTRACT_OPTIMAL) {
1929 uves_msg_low(
"%" CPL_SIZE_FORMAT
" hot pixels were detected during optimal extraction",
1930 cpl_table_get_nrow(*cosmic_mask));
1932 if (cpl_table_get_nrow(*cosmic_mask) > 0) {
1933 check( uves_plot_table(*cosmic_mask,
"X",
"Y",
1934 "%" CPL_SIZE_FORMAT
"hot/cold pixels",
1935 cpl_table_get_nrow(*cosmic_mask)),
1952 "^ESO ",0),
"error copying hierarch keys");
1955 check( uves_save_image_local((ff_method == FF_PIXEL) ?
1956 "Extracted, flatfielded spectrum" :
1957 "Extracted spectrum",
1958 (ff_method == FF_PIXEL) ?
1960 extracted, chip, -1,
1961 filename_window, extracted_header,
true),
1962 "Error saving extracted%s spectrum",
1963 (ff_method == FF_PIXEL) ?
", flatfielded" :
"");
1965 check( uves_save_image_local((ff_method == FF_PIXEL) ?
1966 "Extracted, flatfielded spectrum noise" :
1967 "Extracted spectrum noise",
1968 (ff_method == FF_PIXEL) ?
1970 extracted_noise, chip, -1,
1971 filename_window, extracted_header,
true),
1972 "Error saving noise of extracted%s spectrum",
1973 (ff_method == FF_PIXEL) ?
", flatfielded" :
"");
1975 if (extracted_sky != NULL)
1977 check( uves_save_image_local((ff_method == FF_PIXEL) ?
1978 "Extracted, flatfielded sky" :
1980 (ff_method == FF_PIXEL) ?
1982 extracted_sky, chip, -1,
1983 filename_window, extracted_header,
true),
1984 "Error saving extracted%s sky",
1985 (ff_method == FF_PIXEL) ?
", flatfielded" :
"");
1987 check( uves_save_image_local((ff_method == FF_PIXEL) ?
1988 "Noise of extracted, flatfielded sky" :
1989 "Noise of extracted sky",
1990 (ff_method == FF_PIXEL) ?
1991 "errxfsky" :
"errxsky",
1992 extracted_sky_noise, chip, -1,
1993 filename_window, extracted_header,
true),
1994 "Error saving extracted%s sky noise",
1995 (ff_method == FF_PIXEL) ?
", flatfielded" :
"");
1998 if (ex_method == EXTRACT_OPTIMAL)
2000 check( uves_save_image_local(
"Optimal extraction weights",
2004 backsubbed_header,
true),
2005 "Error saving weights map");
2007 check( uves_save_table_local(
"Cosmic ray table",
"crmask",
2008 *cosmic_mask, chip, -1,
2010 backsubbed_header, NULL),
2011 "Error saving cosmic ray mask");
2013 check( uves_save_image_local(
"Cosmic ray image",
"crimage",
2014 cosmic_image, chip, -1,
2016 backsubbed_header,
true),
2017 "Error saving cosmic ray mask");
2019 if (profile_table != NULL)
2021 check( uves_save_table_local(
"Profile table",
"profile",
2022 profile_table, chip, -1,
2024 backsubbed_header, NULL),
2025 "Error saving profile table");
2031 if (master_flat != NULL && (ff_method == FF_EXTRACT || resampled_mf != NULL))
2033 uves_msg(
"Extracting master flat field");
2039 if (ex_method == EXTRACT_OPTIMAL)
2041 const char *temp_method =
"weighted";
2048 check( uves_set_parameter((cpl_parameterlist *) parameters,
2049 context, UVES_EXTRACT_ID
".method",
2050 CPL_TYPE_STRING, &temp_method),
2051 "Error setting extraction method to '%s'", temp_method);
2054 check( extracted_mf =
2065 parameters, context,
2072 &extracted_mf_noise,
2082 "Error extracting master flat spectrum");
2086 if (ex_method == EXTRACT_OPTIMAL) {
2087 const char *method =
"optimal";
2091 check( uves_set_parameter((cpl_parameterlist *) parameters,
2092 context, UVES_EXTRACT_ID
".method",
2093 CPL_TYPE_STRING, &method),
2094 "Error resetting extraction method to '%s'", method);
2101 uves_free_image(&temp_image);
2103 ff_mean = cpl_image_get_mean(extracted_mf);
2106 cpl_image_divide_scalar_create(extracted_mf, ff_mean),
2107 "Could not normalize master flat spectrum");
2109 check( uves_save_image_local(
"Normalized master flat spectrum",
2111 temp_image, chip, -1,
2112 filename_window, extracted_header,
true),
2113 "Error saving image");
2116 uves_free_image(&temp_image);
2118 cpl_image_divide_scalar_create(extracted_mf_noise,
2120 "Could not rescale master flat noise spectrum");
2122 check( uves_save_image_local(
"Noise of normalized "
2123 "master flat spectrum",
"errxmf",
2124 temp_image, chip, -1,
2125 filename_window, extracted_header,
true),
2126 "Error saving image");
2128 uves_free_image(&temp_image);
2132 if (resampled_mf != NULL) {
2133 uves_msg(
"Rebinning master flat spectrum");
2142 parameters, context,
2144 dispersion_relation[1],
2151 "Error resampling master flat");
2160 dispersion_relation[1],
2164 "Error generating wave map");
2166 check( uves_save_image_local(
"Wave map",
2168 *wave_map, chip, -1,
2170 extracted_header,
true),
2171 "Error saving wavemap image");
2179 "^ESO ", 0),
"error copying hierarch keys");
2182 check( uves_save_image_local(
"Resampled master flat spectrum",
2183 "wxmf", *resampled_mf, chip, -1,
2184 filename_window, *rebinned_header,
true),
2185 "Error saving image");
2191 if (ff_method == FF_EXTRACT)
2194 uves_msg(
"Dividing by normalized master flat-field (method = extract)");
2197 extracted_noff = cpl_image_duplicate(extracted);
2200 extracted_mf, extracted_mf_noise),
2201 "Could not perform flat-fielding");
2203 if (extracted_sky != NULL)
2206 extracted_mf, extracted_mf_noise),
2207 "Could not perform flat-fielding");
2213 check( uves_save_image_local(
"Flat-fielded spectrum",
"fxb",
2214 extracted, chip, -1, filename_window,
2215 extracted_header,
true),
2216 "Error saving image");
2218 check( uves_save_image_local(
"Flat-fielded spectrum noise",
2219 "errfxb", extracted_noise, chip,
2220 -1, filename_window, extracted_header,
true),
2221 "Error saving noise of flat-fielded image");
2224 if (debug_mode && extracted_sky != NULL)
2226 check( uves_save_image_local(
"Flat-fielded sky",
"fxsky",
2227 extracted_sky, chip, -1,
2228 filename_window, extracted_header,
true),
2229 "Error saving image");
2231 check( uves_save_image_local(
"Flat-fielded sky noise",
"errfxsky",
2232 extracted_sky_noise, chip, -1,
2233 filename_window, extracted_header,
true),
2234 "Error saving noise of flat-fielded image");
2240 *fx = cpl_image_duplicate(extracted);
2245 if (flatfielded_variance != NULL)
2248 check( *flatfielded_variance =
2249 cpl_image_multiply_create(extracted_noise,
2251 "Error creating variance of flatfielded spectrum");
2253 passure(flatfielded_variance_header != NULL,
" ");
2254 check( *flatfielded_variance_header =
2256 "Could not copy extracted spectrum header");
2261 if (ex_method == EXTRACT_2D)
2264 uves_msg_low(
"Skipping blaze function correction for 2d extraction mode");
2268 uves_msg(
"Calculating blaze function correction");
2271 "Error calculating blaze function correction");
2273 uves_msg(
"Applying blaze function correction");
2275 check(( cpl_image_divide(extracted , blaze_ratio),
2276 cpl_image_divide(extracted_noise, blaze_ratio)),
2277 "Error applying blaze function correction");
2279 if (extracted_sky != NULL)
2281 check(( cpl_image_multiply(extracted_sky, blaze_ratio),
2282 cpl_image_multiply(extracted_sky_noise, blaze_ratio)),
2283 "Error applying blaze function correction");
2290 if (ex_method == EXTRACT_2D) {
2293 "of 2d spectra is unsupported");
2297 else if (tilt_corr) {
2300 if (info_tbl != NULL) {
2301 objoffset = cpl_table_get_column_median(*info_tbl,
"ObjPosOnSlit");
2307 uves_msg_debug(
"Object position (from bottom of extraction window) = %.2f pixels",
2310 objoffset -= slit_length / 2;
2313 objoffset += slit_offset;
2316 uves_msg_debug(
"Object position (from slit center) = %.2f pixels",
2322 "using %.2f pixels", slit_offset);
2323 objoffset = slit_offset;
2329 "Could not interpolate dispersion solutions");
2333 "Error converting polynomial to table");
2335 check( uves_save_table_local(
"Interpolated dispersion relation",
2337 poly_table, chip, -1,
2338 filename_window, backsubbed_header, NULL),
2339 "Error saving interpolated dispersion solution");
2346 uves_free_propertylist(rebinned_header);
2348 parameters, context,
2349 linetable, dispersion_int,
2356 "Could not rebin spectrum");
2358 uves_msg(
"Rebinning spectrum noise");
2368 bool threshold_to_positive =
true;
2370 uves_free_propertylist(rebinned_header);
2372 parameters, context,
2373 linetable, dispersion_int,
2377 threshold_to_positive,
2380 "Could not rebin spectrum noise");
2383 if (extracted_sky != NULL) {
2384 uves_msg(
"Rebinning sky spectrum");
2397 "Could not interpolate dispersion solutions");
2405 uves_free_propertylist(rebinned_header);
2407 parameters, context,
2408 linetable, dispersion_int_sky,
2415 "Could not rebin sky noise");
2417 uves_msg(
"Rebinning sky spectrum noise");
2419 uves_free_propertylist(rebinned_header);
2421 parameters, context,
2422 linetable, dispersion_int_sky,
2429 "Could not rebin sky noise");
2435 const char *filename =
"";
2436 const char *filename_err =
"";
2437 const char *filename_sky =
"";
2438 const char *filename_sky_err =
"";
2439 if (ff_method == FF_PIXEL)
2442 filename_err =
"errwxfb";
2443 filename_sky =
"wxfsky";
2444 filename_sky_err =
"errwxfsky";
2446 else if (ff_method == FF_EXTRACT)
2449 filename_err =
"errwfxb";
2450 filename_sky =
"wfxsky";
2451 filename_sky_err =
"errwfxsky";
2453 else if (ff_method == FF_NO)
2456 filename_err =
"errwxb";
2457 filename_sky =
"wxsky";
2458 filename_sky_err =
"errwxsky";
2462 passure(
false,
"Unknown ff_method: %d", ff_method);
2467 "^ESO ", 1),
"error copying hierarch keys");
2470 check( uves_save_image_local(
"Rebinned spectrum",
2471 filename, *rebinned_spectrum,
2472 chip, -1, filename_window, *rebinned_header,
true),
2473 "Error saving image");
2475 check( uves_save_image_local(
"Noise of rebinned spectrum", filename_err,
2476 *rebinned_noise, chip, -1, filename_window,
2477 *rebinned_header,
true),
2478 "Error saving image");
2480 if (extracted_sky != NULL)
2482 check( uves_save_image_local(
"Rebinned sky", filename_sky,
2483 rebinned_sky, chip, -1,
2484 filename_window, *rebinned_header,
true),
2485 "Error saving image");
2487 check( uves_save_image_local(
"Noise of rebinned sky",
2489 rebinned_sky_noise, chip, -1,
2490 filename_window, *rebinned_header,
true),
2491 "Error saving image");
2500 if (resampled_spectrum != NULL)
2502 if (ff_method == FF_EXTRACT)
2505 uves_msg(
"Rebinning pre-flatfielded spectrum");
2507 uves_free_propertylist(rebinned_header);
2508 check( *resampled_spectrum =
2510 parameters, context,
2511 linetable, dispersion_int,
2518 "Could not rebin spectrum");
2522 check( uves_save_image_local(
"Rebinned, extracted spectrum",
2523 "wx", *resampled_spectrum,
2524 chip, -1, filename_window,
2525 *rebinned_header,
true),
2526 "Error saving image");
2532 check( *resampled_spectrum = cpl_image_duplicate(*rebinned_spectrum),
2533 "Error copying rebinned spectrum");
2538 if (extracted_sky != NULL)
2549 "Error merging sky");
2553 uves_free_propertylist(merged_header);
2562 "Error merging orders");
2566 "^ESO ", 0),
"error copying hierarch keys");
2570 check( uves_save_image_local(
"Merged spectrum",
"m", *merged_spectrum,
2571 chip, -1, filename_window, *merged_header,
true),
2572 "Error saving image");
2574 check( uves_save_image_local(
"Noise of merged spectrum",
"errm",
2575 *merged_noise, chip, -1,
2576 filename_window, *merged_header,
true),
2577 "Error saving image");
2580 if (debug_mode && extracted_sky != NULL)
2582 check( uves_save_image_local(
"Merged sky",
"msky", *merged_sky,
2584 filename_window, *merged_header,
true),
2585 "Error saving image");
2587 check( uves_save_image_local(
"Noise of merged sky",
"errmsky",
2588 merged_sky_noise, chip, -1,
2589 filename_window, *merged_header,
true),
2590 "Error saving image");
2594 uves_free_image(&extracted);
2595 uves_free_image(&extracted_noff);
2596 uves_free_image(&extracted_noise);
2597 uves_free_image(&extracted_sky);
2598 uves_free_image(&extracted_sky_noise);
2599 uves_free_image(&cosmic_image);
2600 uves_free_image(&blaze_ratio);
2601 uves_free_image(&weights);
2604 uves_free_table(&poly_table);
2605 uves_free_propertylist(&extracted_header);
2606 uves_free_table(&profile_table);
2607 uves_free_image(&extracted_mf);
2608 uves_free_image(&extracted_mf_noise);
2609 uves_free_image(&rebinned_sky);
2610 uves_free_image(&rebinned_sky_noise);
2611 uves_free_image(&merged_sky_noise);
2613 uves_free_image(&temp_image);
2615 return cpl_error_get_code();
2660 const cpl_image *rebinned_sky1,
const cpl_image *rebinned_sky1_noise,
2662 const cpl_image *rebinned_sky2,
const cpl_image *rebinned_sky2_noise,
2664 cpl_image **merged_obj, cpl_image **merged_obj_noise,
2666 const cpl_image *merged_sky1,
const cpl_image *merged_sky1_noise,
2668 const cpl_image *merged_sky2,
const cpl_image *merged_sky2_noise,
2670 double obj_slit,
double sky1_slit,
double sky2_slit)
2675 cpl_image *merged_sky = NULL;
2677 passure( rebinned_obj != NULL,
" ");
2678 passure( rebinned_obj_noise != NULL,
" ");
2679 passure( rebinned_obj_header != NULL,
" ");
2680 passure( merged_obj != NULL,
" ");
2681 passure( merged_obj_noise != NULL,
" ");
2682 passure( merged_obj_header != NULL,
" ");
2683 passure( *merged_obj != NULL,
" ");
2684 passure( *merged_obj_noise != NULL,
" ");
2688 "Error reading wavelength step");
2689 norders = cpl_image_get_size_y(rebinned_obj);
2693 assure((rebinned_sky1 == NULL || norders == cpl_image_get_size_y(rebinned_sky1)) &&
2694 (rebinned_sky2 == NULL || norders == cpl_image_get_size_y(rebinned_sky2)),
2695 CPL_ERROR_ILLEGAL_INPUT,
2696 "Different number of orders in object/sky spectra: obj = %d, "
2697 "sky1 = %" CPL_SIZE_FORMAT
", sky3 = %" CPL_SIZE_FORMAT
"",
2699 cpl_image_get_size_y(rebinned_sky1),
2700 cpl_image_get_size_y(rebinned_sky2));
2702 if (rebinned_sky1 != NULL)
2706 "Error reading wavelength step");
2707 assure( fabs(wavestep1 - wavestep) / wavestep < 0.01,
2708 CPL_ERROR_ILLEGAL_INPUT,
2709 "Different bin widths: sky1 = %f ; obj = %f",
2710 wavestep1, wavestep);
2712 if (rebinned_sky2 != NULL)
2716 "Error reading wavelength step");
2717 assure( fabs(wavestep2 - wavestep) / wavestep < 0.01,
2718 CPL_ERROR_ILLEGAL_INPUT,
2719 "Different bin widths: sky3 = %f ; obj = %f",
2720 wavestep2, wavestep);
2726 for (order = 1; order <= norders; order++)
2728 double obj_start , obj_end;
2729 double sky1_start , sky1_end;
2730 double sky2_start , sky2_end;
2731 double common_start, common_end;
2734 "Error reading start wavelength for order #%d", order);
2736 "Error reading end wavelength for order #%d", order);
2738 if (rebinned_sky1 != NULL)
2742 "Error reading start wavelength for order #%d", order);
2745 "Error reading end wavelength for order #%d", order);
2749 sky1_start = obj_start;
2753 if (rebinned_sky2 != NULL)
2757 "Error reading start wavelength for order #%d", order);
2760 "Error reading end wavelength for order #%d", order);
2764 sky2_start = obj_start;
2770 obj_start , obj_end, obj_slit,
2771 rebinned_sky1, rebinned_sky1_noise,
2772 sky1_start, sky1_end, sky1_slit,
2773 rebinned_sky2, rebinned_sky2_noise,
2774 sky2_start, sky2_end, sky2_slit,
2775 order, wavestep, &common_start,
2777 "Could not subtract sky for rebinned spectrum order #%d", order);
2778 uves_free_image(&merged_sky);
2781 "Error updating start wavelength for order #%d", order);
2783 "Error updating start wavelength for order #%d", order);
2789 double obj_start , obj_end;
2790 double sky1_start , sky1_end;
2791 double sky2_start , sky2_end;
2792 double common_start, common_end;
2795 obj_end = obj_start + wavestep * (cpl_image_get_size_x(*merged_obj) - 1);
2797 if (merged_sky1 != NULL)
2800 sky1_end = sky1_start +
2801 wavestep * (cpl_image_get_size_x(merged_sky1) - 1);
2805 sky1_start = obj_start;
2809 if (merged_sky2 != NULL)
2812 sky2_end = sky2_start +
2813 wavestep * (cpl_image_get_size_x(merged_sky2) - 1);
2817 sky2_start = obj_start;
2823 obj_start , obj_end, obj_slit,
2824 merged_sky1, merged_sky1_noise,
2825 sky1_start, sky1_end, sky1_slit,
2826 merged_sky2, merged_sky2_noise,
2827 sky2_start, sky2_end, sky2_slit,
2828 1, wavestep, &common_start,
2830 "Error subtracting sky of merged spectrum");
2833 "Could not update start wavelength");
2836 check( uves_crop_image(merged_obj,
2838 1 + uves_round_double((common_end -
2839 common_start)/wavestep),
2841 "Error cropping merged spectrum");
2843 check( uves_crop_image(merged_obj_noise,
2845 1 + uves_round_double((common_end -
2846 common_start)/wavestep),
2848 "Error cropping merged spectrum noise");
2850 if (merged_sky != NULL)
2853 assure( cpl_image_get_size_x(merged_sky) ==
2854 cpl_image_get_size_x(*merged_obj), CPL_ERROR_ILLEGAL_OUTPUT,
2855 "Sky and object spectrum sizes differ, "
2856 "sky = %" CPL_SIZE_FORMAT
" bins, obj = %" CPL_SIZE_FORMAT
" bins",
2857 cpl_image_get_size_x(merged_sky),
2858 cpl_image_get_size_x(*merged_obj));
2863 if (cpl_error_get_code() != CPL_ERROR_NONE)
2865 uves_free_image(&merged_sky);
2906 double obj_start,
double obj_end,
double obj_slit,
2907 const cpl_image *sky1,
const cpl_image *sky1_noise,
2908 double sky1_start,
double sky1_end,
double sky1_slit,
2909 const cpl_image *sky2,
const cpl_image *sky2_noise,
2910 double sky2_start,
double sky2_end,
double sky2_slit,
2911 int row,
double wavestep,
2912 double *common_start,
double *common_end)
2918 cpl_image *common_obj = NULL;
2919 cpl_image *common_sky1 = NULL;
2920 cpl_image *common_sky2 = NULL;
2921 cpl_image *common_obj_noise = NULL;
2922 cpl_image *common_sky1_noise = NULL;
2923 cpl_image *common_sky2_noise = NULL;
2924 bool is_good1, is_good2;
2926 cpl_image *common_sky = NULL;
2928 cpl_image *common_sky_noise = NULL;
2930 cpl_image *temp = NULL;
2932 *common_start = uves_max_double(obj_start, uves_max_double(sky1_start, sky2_start));
2933 *common_end = uves_min_double(obj_end , uves_min_double(sky1_end , sky2_end ));
2935 if (*common_start <= *common_end)
2937 nbins = 1 + uves_round_double((*common_end - *common_start) / wavestep);
2939 uves_msg_debug(
"Lower sky range: %f - %f w.l.u.", sky1_start, sky1_end);
2940 uves_msg_debug(
"Upper sky range: %f - %f w.l.u.", sky2_start, sky2_end);
2941 uves_msg_debug(
"Object sky range: %f - %f w.l.u.", obj_start, obj_end);
2942 uves_msg_debug(
"Sky/object common wavelength range in order %d: "
2943 "%f - %f w.l.u. (%d bins)",
2944 row, *common_start, *common_end, nbins);
2946 first_bin_obj = 1 + uves_round_double((*common_start - obj_start )/wavestep);
2947 first_bin_sky1 = 1 + uves_round_double((*common_start - sky1_start)/wavestep);
2948 first_bin_sky2 = 1 + uves_round_double((*common_start - sky2_start)/wavestep);
2951 check( common_obj = cpl_image_extract(obj,
2953 first_bin_obj + nbins-1, row),
2954 "Error extracting common rows (object)");
2956 check( common_obj_noise = cpl_image_extract(obj_noise,
2958 first_bin_obj + nbins-1, row),
2959 "Error extracting common rows (object noise)");
2963 check( common_sky1 =
2964 cpl_image_extract(sky1,
2965 first_bin_sky1, row,
2966 first_bin_sky1 + nbins-1, row),
2967 "Error extracting common rows (lower sky)");
2969 check( common_sky1_noise =
2970 cpl_image_extract(sky1_noise,
2971 first_bin_sky1, row,
2972 first_bin_sky1 + nbins-1, row),
2973 "Error extracting common rows (lower sky noise)");
2975 check(( cpl_image_multiply_scalar(common_sky1 , obj_slit / sky1_slit),
2976 cpl_image_multiply_scalar(common_sky1_noise, obj_slit / sky1_slit)),
2977 "Error normalizing sky flux");
2980 cpl_image_count_rejected(common_sky1) <
2981 cpl_image_get_size_x(common_sky1)*
2982 cpl_image_get_size_y(common_sky1) &&
2985 cpl_image_get_min(common_sky1_noise) > 0;
2993 check( common_sky2 = cpl_image_extract(sky2,
2994 first_bin_sky2, row,
2995 first_bin_sky2 + nbins-1, row),
2996 "Error extracting common rows (upper sky)");
2998 check( common_sky2_noise = cpl_image_extract(sky2_noise,
2999 first_bin_sky2, row,
3000 first_bin_sky2 + nbins-1, row),
3001 "Error extracting common rows (upper sky noise)");
3003 check(( cpl_image_multiply_scalar(common_sky2 , obj_slit / sky2_slit),
3004 cpl_image_multiply_scalar(common_sky2_noise, obj_slit / sky2_slit)),
3005 "Error normalizing sky flux");
3008 cpl_image_count_rejected(common_sky2) <
3009 cpl_image_get_size_x(common_sky2)*
3010 cpl_image_get_size_y(common_sky2) &&
3011 cpl_image_get_min(common_sky2_noise) > 0;
3021 if (is_good1 && is_good2)
3025 common_sky2, common_sky2_noise,
3027 "Error combining sky windows");
3029 else if (is_good1 && !is_good2)
3031 common_sky = cpl_image_duplicate(common_sky1);
3032 common_sky_noise = cpl_image_duplicate(common_sky1_noise);
3034 else if (!is_good1 && is_good2)
3036 common_sky = cpl_image_duplicate(common_sky2);
3037 common_sky_noise = cpl_image_duplicate(common_sky2_noise);
3044 if (common_sky != NULL)
3054 check(( cpl_image_subtract (common_obj, common_sky)),
3055 "Error subtracting combined sky");
3059 check(( cpl_image_power(common_obj_noise, 2),
3060 cpl_image_power(common_sky_noise, 2),
3061 cpl_image_add (common_obj_noise, common_sky_noise),
3062 cpl_image_power(common_obj_noise, 0.5)),
3063 "Error propagating noise during sky subtration");
3066 check(( cpl_image_copy(obj,
3069 cpl_image_copy(obj_noise,
3072 "Error writing subtracted flux to row %d of spectrum", row);
3080 uves_msg_low(
"Extracted object and sky spectra have no overlap in order #%d. "
3081 "Order marked as bad", row);
3083 for (x = 1; x <= cpl_image_get_size_x(obj); x++)
3085 check(( cpl_image_reject(obj , x, row),
3086 cpl_image_reject(obj_noise, x, row)),
3087 "Error rejecting sky-subtracted spectrum "
3088 "at (x, row) = (%d, %d)", x, row);
3093 uves_free_image(&common_obj);
3094 uves_free_image(&common_sky1);
3095 uves_free_image(&common_sky2);
3096 uves_free_image(&common_obj_noise);
3097 uves_free_image(&common_sky_noise);
3098 uves_free_image(&common_sky1_noise);
3099 uves_free_image(&common_sky2_noise);
3100 uves_free_image(&temp);
3101 if (cpl_error_get_code() != CPL_ERROR_NONE)
3103 uves_free_image(&common_sky);
3128 const cpl_table *ordertable,
3130 double search_range,
int nsamples,
double *doffset)
3132 cpl_image *chunk = NULL;
3133 cpl_image *chunk_col = NULL;
3135 int minorder, maxorder;
3136 int order, x, nx, ny;
3137 double sum = 0, sum_o = 0, sum_oo = 0;
3139 int s_r_int = uves_round_double(search_range);
3141 passure( back_subbed != NULL,
" ");
3142 passure( ordertable != NULL,
" ");
3143 passure( order_locations != NULL,
" ");
3145 assure( nsamples >= 1, CPL_ERROR_ILLEGAL_INPUT,
3146 "Illegal number of sample points per order: %d", nsamples);
3148 minorder = cpl_table_get_column_min(ordertable,
"Order");
3149 maxorder = cpl_table_get_column_max(ordertable,
"Order");
3150 nx = cpl_image_get_size_x(back_subbed);
3151 ny = cpl_image_get_size_y(back_subbed);
3156 for (order = minorder; order <= maxorder; order++)
3158 int stepx = nx / nsamples;
3160 for (x = stepx/2; x <= nx; x += stepx)
3162 int y = uves_round_double(
3165 if (1 <= y - s_r_int && y + s_r_int <= ny)
3172 cpl_image_extract(back_subbed,
3173 uves_max_int(1 , x - stepx/2),
3175 uves_min_int(nx, x + stepx/2),
3180 cpl_image_collapse_median_create(chunk,
3187 offset = (y - s_r_int - 1) +
3188 cpl_image_get_centroid_y_window(chunk_col,
3191 cpl_image_get_size_y(chunk_col));
3196 uves_free_image(&chunk);
3197 uves_free_image(&chunk_col);
3201 sum_oo += offset*offset;
3208 assure( sum > 0, CPL_ERROR_ILLEGAL_OUTPUT,
3209 "No evaluation points inside image!");
3211 if (doffset != NULL)
3213 *doffset = sqrt(sum_oo/(1.0*sum) -
3214 (sum_o*sum_o) / (sum*1.0*sum));
3218 uves_free_image(&chunk);
3219 uves_free_image(&chunk_col);
3221 return (1.0*sum_o) / sum;
3250 const cpl_image *spectrum_noise)
3253 int smooth_x, smooth_y;
3255 cpl_image *blaze_ratio = NULL;
3256 cpl_image *blaze_ratio_noise = NULL;
3258 cpl_table *values = NULL;
3261 passure( spectrum != NULL,
" ");
3262 passure( spectrum_noise != NULL,
" ");
3264 nx = cpl_image_get_size_x(spectrum);
3265 ny = cpl_image_get_size_y(spectrum);
3267 blaze_ratio = cpl_image_duplicate(spectrum);
3268 blaze_ratio_noise = cpl_image_duplicate(spectrum_noise);
3280 for (y = 1; y <= ny; y++)
3282 double median = cpl_image_get_median_window(blaze_ratio,
3294 double max_noise = cpl_image_get_max(blaze_ratio_noise);
3296 for (x = 1; x <= nx; x++)
3298 cpl_image_set(blaze_ratio , x, y, 1);
3301 cpl_image_set(blaze_ratio_noise, x, y, max_noise);
3310 for (x = 1; x <= nx; x++)
3312 int pis_rejected1, pis_rejected2;
3315 val1 = cpl_image_get(blaze_ratio ,
3316 x, y, &pis_rejected1);
3317 val2 = cpl_image_get(blaze_ratio_noise,
3318 x, y, &pis_rejected2);
3320 if (!pis_rejected1 && !pis_rejected2 &&
3321 val1/median < exclude && val1/median > 1/exclude)
3323 cpl_image_set(blaze_ratio ,
3324 x, y, val1 / median);
3325 cpl_image_set(blaze_ratio_noise,
3326 x, y, val2 / median);
3332 cpl_image_set (blaze_ratio , x, y, 1);
3334 cpl_image_reject(blaze_ratio , x, y);
3335 cpl_image_reject(blaze_ratio_noise, x, y);
3341 uves_plot_image_rows(blaze_ratio, 1, ny, ny/10,
3342 "x",
"y",
"ratio (normalized to 1)");
3345 smooth_x = nx / 20 + 1;
3346 smooth_y = ny / 20 + 1;
3350 "Error creating smoothed ratio");
3352 uves_plot_image_rows(blaze_ratio, 1, ny, ny/10,
"x",
"y",
"ratio (smoothed)");
3362 double interpolated=0;
3363 for (x = 1; x <= nx; x++)
3370 uves_free_table(&values);
3371 values = cpl_table_new(ny);
3372 cpl_table_new_column(values,
"Y", CPL_TYPE_INT);
3373 cpl_table_new_column(values,
"Ratio", CPL_TYPE_DOUBLE);
3374 cpl_table_new_column(values,
"dRatio", CPL_TYPE_DOUBLE);
3379 for (y = 1; y <= ny; y++)
3381 double ratio=0., dratio=0.;
3382 int pis_rejected1=0, pis_rejected2=0;
3384 ratio = cpl_image_get(blaze_ratio ,
3385 x, y, &pis_rejected1);
3386 check_nomsg(dratio = cpl_image_get(blaze_ratio_noise,
3387 x, y, &pis_rejected2));
3392 if (!pis_rejected1 && !pis_rejected2)
3394 cpl_table_set_int (values,
"Y" ,
3396 cpl_table_set_double(values,
"Ratio" ,
3397 current_row, ratio);
3398 cpl_table_set_double(values,
"dRatio",
3399 current_row, dratio);
3408 cpl_table_set_size(values, current_row);
3409 if(current_row>UVES_MIN_LINE_ROWS_TO_MAKE_FIT)
3416 "Y",
"Ratio",
"dRatio",
3424 if (cpl_error_get_code() == CPL_ERROR_ILLEGAL_INPUT ||
3425 cpl_error_get_code() == CPL_ERROR_ILLEGAL_OUTPUT)
3439 uves_free_table(&values);
3440 values = cpl_table_new(2);
3441 cpl_table_new_column(values,
"Y", CPL_TYPE_INT);
3442 cpl_table_new_column(values,
"Ratio", CPL_TYPE_DOUBLE);
3443 cpl_table_set_int (values,
"Y" , 0, 1);
3444 cpl_table_set_double(values,
"Ratio" , 0, 1);
3445 cpl_table_set_int (values,
"Y" , 1, 2);
3446 cpl_table_set_double(values,
"Ratio" , 1, 1);
3458 assure( cpl_error_get_code() == CPL_ERROR_NONE, cpl_error_get_code(),
3459 "Could not fit %d. degree polynomial to column %d", degree, x);
3462 interpolated=UVES_BLAZE_DUMMY_VAL;
3465 for (y = 1; y <= ny; y++)
3467 if(current_row>UVES_MIN_LINE_ROWS_TO_MAKE_FIT) {
3470 cpl_image_set(blaze_ratio, x, y, fabs(interpolated));
3477 2*smooth_x, 2*smooth_y,
3479 "Error creating smoothed ratio");
3481 uves_plot_image_rows(blaze_ratio, 1, ny, ny/10,
"x",
"y",
"ratio (poly. fit)");
3499 uves_free_table(&values);
3501 uves_free_image(&blaze_ratio_noise);
3503 if (cpl_error_get_code() != CPL_ERROR_NONE)
3505 uves_free_image(&blaze_ratio);