32 #include <vimos_science_impl.h>
37 #include <fors_tools.h>
41 #define vimos_science_exit(message) \
43 if (message) cpl_msg_error(recipe, message); \
45 cpl_image_delete(dummy); \
46 cpl_image_delete(mapped); \
47 cpl_image_delete(mapped_sky); \
48 cpl_image_delete(mapped_cleaned); \
49 cpl_image_delete(skylocalmap); \
50 cpl_image_delete(skymap); \
51 cpl_image_delete(smapped); \
52 cpl_table_delete(offsets); \
53 cpl_table_delete(sky); \
54 cpl_image_delete(bias); \
55 cpl_image_delete(spectra); \
56 cpl_image_delete(coordinate); \
57 cpl_image_delete(norm_flat); \
58 cpl_image_delete(rainbow); \
59 cpl_image_delete(rectified); \
60 cpl_image_delete(wavemap); \
61 cpl_propertylist_delete(header); \
62 cpl_propertylist_delete(save_header); \
63 cpl_table_delete(grism_table); \
64 cpl_table_delete(idscoeff); \
65 cpl_table_delete(maskslits); \
66 cpl_table_delete(overscans); \
67 cpl_table_delete(polytraces); \
68 cpl_table_delete(slits); \
69 cpl_table_delete(wavelengths); \
70 cpl_vector_delete(lines); \
71 cpl_msg_indent_less(); \
81 int vimos_science_impl(cpl_frameset *frameset, cpl_parameterlist *parlist)
83 const char *recipe =
"vimos_science";
93 double startwavelength;
115 cpl_imagelist *all_science;
118 cpl_image *bias = NULL;
119 cpl_image *norm_flat = NULL;
120 cpl_image *spectra = NULL;
121 cpl_image *rectified = NULL;
122 cpl_image *coordinate = NULL;
123 cpl_image *rainbow = NULL;
124 cpl_image *mapped = NULL;
125 cpl_image *mapped_sky = NULL;
126 cpl_image *mapped_cleaned = NULL;
127 cpl_image *smapped = NULL;
128 cpl_image *wavemap = NULL;
129 cpl_image *skymap = NULL;
130 cpl_image *skylocalmap = NULL;
131 cpl_image *dummy = NULL;
133 cpl_table *grism_table = NULL;
134 cpl_table *overscans = NULL;
135 cpl_table *wavelengths = NULL;
136 cpl_table *idscoeff = NULL;
137 cpl_table *slits = NULL;
138 cpl_table *maskslits = NULL;
139 cpl_table *polytraces = NULL;
140 cpl_table *offsets = NULL;
141 cpl_table *sky = NULL;
143 cpl_vector *lines = NULL;
145 cpl_propertylist *header = NULL;
146 cpl_propertylist *save_header = NULL;
147 cpl_propertylist *qclist = NULL;
154 char *instrume = NULL;
155 const char *science_tag;
156 const char *master_norm_flat_tag;
157 const char *disp_coeff_tag;
158 const char *disp_coeff_sky_tag;
159 const char *wavelength_map_tag;
160 const char *wavelength_map_sky_tag;
161 const char *curv_coeff_tag;
162 const char *slit_location_tag;
163 const char *reduced_science_tag;
164 const char *reduced_sky_tag;
165 const char *reduced_error_tag;
166 const char *mapped_science_tag;
167 const char *unmapped_science_tag;
168 const char *mapped_science_sky_tag;
169 const char *mapped_sky_tag;
170 const char *unmapped_sky_tag;
171 const char *global_sky_spectrum_tag;
172 const char *object_table_tag;
173 const char *skylines_offsets_tag;
174 const char *specphot_tag;
175 const char *key_gris_name;
176 const char *key_gris_id;
177 const char *key_filt_name;
178 const char *key_filt_id;
181 int treat_as_lss = 0;
186 double *exptime = NULL;
199 int rotate_back = -1;
206 snprintf(version, 80,
"%s-%s", PACKAGE, PACKAGE_VERSION);
208 cpl_msg_set_indentation(2);
215 cpl_msg_info(recipe,
"Recipe %s configuration parameters:", recipe);
216 cpl_msg_indent_more();
218 if (cpl_frameset_count_tags(frameset,
"GRISM_TABLE") > 1)
219 vimos_science_exit(
"Too many in input: GRISM_TABLE");
224 "fors.vimos_science.dispersion", grism_table);
226 if (dispersion <= 0.0)
227 vimos_science_exit(
"Invalid resampling step");
230 "fors.vimos_science.skyalign", NULL);
233 vimos_science_exit(
"Max polynomial degree for sky alignment is 2");
236 "fors.vimos_science.wcolumn", NULL);
239 "fors.vimos_science.startwavelength", grism_table);
240 if (startwavelength < 3000.0 || startwavelength > 13000.0)
241 vimos_science_exit(
"Invalid wavelength");
244 "fors.vimos_science.endwavelength", grism_table);
245 if (endwavelength < 3000.0 || endwavelength > 13000.0)
246 vimos_science_exit(
"Invalid wavelength");
248 if (endwavelength - startwavelength <= 0.0)
249 vimos_science_exit(
"Invalid wavelength interval");
252 "fors.vimos_science.reference", grism_table);
254 if (reference < startwavelength || reference > endwavelength)
255 vimos_science_exit(
"Invalid reference wavelength");
269 if (skylocal && skyglobal)
270 vimos_science_exit(
"Cannot do both local and global sky subtraction");
272 if (skylocal && skymedian)
273 vimos_science_exit(
"Cannot do sky subtraction both on extracted "
274 "and non-extracted spectra");
277 "fors.vimos_science.cosmics", NULL);
280 if (!(skyglobal || skylocal))
281 vimos_science_exit(
"Cosmic rays correction requires "
282 "either skylocal=true or skyglobal=true");
285 "fors.vimos_science.slit_margin",
288 vimos_science_exit(
"Value must be zero or positive");
291 "fors.vimos_science.ext_radius",
294 vimos_science_exit(
"Value must be zero or positive");
297 "fors.vimos_science.cont_radius",
300 vimos_science_exit(
"Value must be zero or positive");
304 if (ext_mode < 0 || ext_mode > 1)
305 vimos_science_exit(
"Invalid object extraction mode");
308 "fors.vimos_science.time_normalise", NULL);
312 if (res_order < 2 || res_order > 10)
313 vimos_science_exit(
"Invalid instrument response modeling polynomial");
320 cpl_table_delete(grism_table); grism_table = NULL;
322 if (cpl_error_get_code())
323 vimos_science_exit(
"Failure getting the configuration parameters");
330 cpl_msg_indent_less();
331 cpl_msg_info(recipe,
"Check input set-of-frames:");
332 cpl_msg_indent_more();
335 vimos_science_exit(
"Input frames are not from the same quadrant");
337 mos = cpl_frameset_count_tags(frameset,
"MOS_SCIENCE");
341 mos = cpl_frameset_count_tags(frameset,
"MOS_STANDARD");
346 vimos_science_exit(
"Missing input scientific frame");
351 science_tag =
"MOS_STANDARD";
352 reduced_science_tag =
"MOS_STANDARD_REDUCED";
353 unmapped_science_tag =
"MOS_UNMAPPED_STANDARD";
354 mapped_science_tag =
"MOS_STANDARD_EXTRACTED";
355 mapped_science_sky_tag =
"MOS_STANDARD_SKY_EXTRACTED";
356 mapped_sky_tag =
"MOS_STANDARD_SKY";
357 specphot_tag =
"MOS_SPECPHOT_TABLE";
361 science_tag =
"MOS_SCIENCE";
362 reduced_science_tag =
"MOS_SCIENCE_REDUCED";
363 unmapped_science_tag =
"MOS_UNMAPPED_SCIENCE";
364 mapped_science_tag =
"MOS_SCIENCE_EXTRACTED";
365 mapped_science_sky_tag =
"MOS_SCIENCE_SKY_EXTRACTED";
366 mapped_sky_tag =
"MOS_SCIENCE_SKY";
369 reduced_sky_tag =
"MOS_SKY_REDUCED";
370 reduced_error_tag =
"MOS_ERROR_REDUCED";
371 master_norm_flat_tag =
"MOS_MASTER_SCREEN_FLAT";
372 disp_coeff_sky_tag =
"MOS_DISP_COEFF_SKY";
373 wavelength_map_sky_tag =
"MOS_WAVELENGTH_MAP_SKY";
374 disp_coeff_tag =
"MOS_DISP_COEFF";
375 wavelength_map_tag =
"WAVELENGTH_MAP_MXU";
376 curv_coeff_tag =
"MOS_CURV_COEFF";
377 slit_location_tag =
"MOS_SLIT_LOCATION";
378 skylines_offsets_tag =
"MOS_SKYLINES_OFFSETS_SLIT";
379 unmapped_sky_tag =
"MOS_UNMAPPED_SKY";
380 global_sky_spectrum_tag =
"MOS_GLOBAL_SKY_SPECTRUM";
381 object_table_tag =
"OBJECT_TABLE";
383 if (cpl_frameset_count_tags(frameset,
"MASTER_BIAS") == 0)
384 vimos_science_exit(
"Missing required input: MASTER_BIAS");
386 if (cpl_frameset_count_tags(frameset,
"MASTER_BIAS") > 1)
387 vimos_science_exit(
"Too many in input: MASTER_BIAS");
390 if (cpl_frameset_count_tags(frameset,
"SKY_LINE_CATALOG") > 1)
391 vimos_science_exit(
"Too many in input: SKY_LINE_CATALOG");
393 if (cpl_frameset_count_tags(frameset, disp_coeff_tag) == 0) {
394 cpl_msg_error(recipe,
"Missing required input: %s", disp_coeff_tag);
395 vimos_science_exit(NULL);
398 if (cpl_frameset_count_tags(frameset, disp_coeff_tag) > 1) {
399 cpl_msg_error(recipe,
"Too many in input: %s", disp_coeff_tag);
400 vimos_science_exit(NULL);
403 if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) > 1) {
405 cpl_msg_error(recipe,
"Too many in input: %s",
406 master_norm_flat_tag);
407 vimos_science_exit(NULL);
410 cpl_msg_warning(recipe,
"%s in input are ignored, "
411 "since flat field correction was not requested",
412 master_norm_flat_tag);
416 if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) == 1) {
418 cpl_msg_warning(recipe,
"%s in input is ignored, "
419 "since flat field correction was not requested",
420 master_norm_flat_tag);
424 if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) == 0) {
426 cpl_msg_error(recipe,
"Flat field correction was requested, "
427 "but no %s are found in input",
428 master_norm_flat_tag);
429 vimos_science_exit(NULL);
435 if (cpl_frameset_count_tags(frameset,
"EXTINCT_TABLE") == 0) {
436 cpl_msg_warning(recipe,
"An EXTINCT_TABLE was not found in input: "
437 "instrument response curve will not be produced.");
441 if (cpl_frameset_count_tags(frameset,
"EXTINCT_TABLE") > 1)
442 vimos_science_exit(
"Too many in input: EXTINCT_TABLE");
444 if (cpl_frameset_count_tags(frameset,
"STD_FLUX_TABLE") == 0) {
445 cpl_msg_warning(recipe,
"A STD_FLUX_TABLE was not found in input: "
446 "instrument response curve will not be produced.");
450 if (cpl_frameset_count_tags(frameset,
"STD_FLUX_TABLE") > 1)
451 vimos_science_exit(
"Too many in input: STD_FLUX_TABLE");
454 cpl_msg_warning(recipe,
"The target name of observation does not "
455 "match the standard star catalog: "
456 "instrument response curve will not be produced.");
461 cpl_msg_indent_less();
468 exptime = cpl_calloc(nscience,
sizeof(
double));
472 cpl_msg_info(recipe,
"Load %d scientific frames and median them...",
474 cpl_msg_indent_more();
476 all_science = cpl_imagelist_new();
481 vimos_science_exit(
"Cannot load scientific frame header");
483 alltime = exptime[0] = cpl_propertylist_get_double(header,
"EXPTIME");
485 if (cpl_error_get_code() != CPL_ERROR_NONE)
486 vimos_science_exit(
"Missing keyword EXPTIME in scientific "
492 vimos_science_exit(
"Missing airmass information in "
493 "scientific frame header");
496 instrume = (
char *)cpl_propertylist_get_string(header,
"INSTRUME");
497 if (instrume == NULL)
498 vimos_science_exit(
"Missing keyword INSTRUME "
499 "in scientific frame header");
501 cpl_propertylist_delete(header); header = NULL;
503 cpl_msg_info(recipe,
"Scientific frame 1 exposure time: %.2f s",
506 for (i = 1; i < nscience; i++) {
511 vimos_science_exit(
"Cannot load scientific frame header");
513 exptime[i] = cpl_propertylist_get_double(header,
"EXPTIME");
515 alltime += exptime[i];
517 if (cpl_error_get_code() != CPL_ERROR_NONE)
518 vimos_science_exit(
"Missing keyword EXPTIME in scientific "
521 cpl_propertylist_delete(header); header = NULL;
523 cpl_msg_info(recipe,
"Scientific frame %d exposure time: %.2f s",
527 spectra =
dfs_load_image(frameset, science_tag, CPL_TYPE_FLOAT, 0, 0);
530 vimos_science_exit(
"Cannot load scientific frame");
532 cpl_image_divide_scalar(spectra, exptime[0]);
533 cpl_imagelist_set(all_science, spectra, 0);
535 for (i = 1; i < nscience; i++) {
540 cpl_image_divide_scalar(spectra, exptime[i]);
541 cpl_imagelist_set(all_science, spectra, i);
544 vimos_science_exit(
"Cannot load scientific frame");
548 spectra = cpl_imagelist_collapse_median_create(all_science);
549 cpl_image_multiply_scalar(spectra, alltime);
551 cpl_imagelist_delete(all_science);
554 cpl_msg_info(recipe,
"Load scientific exposure...");
555 cpl_msg_indent_more();
560 vimos_science_exit(
"Cannot load scientific frame header");
562 alltime = exptime[0] = cpl_propertylist_get_double(header,
"EXPTIME");
564 if (cpl_error_get_code() != CPL_ERROR_NONE)
565 vimos_science_exit(
"Missing keyword EXPTIME in scientific "
571 vimos_science_exit(
"Missing airmass information in "
572 "scientific frame header");
575 instrume = (
char *)cpl_propertylist_get_string(header,
"INSTRUME");
576 if (instrume == NULL)
577 vimos_science_exit(
"Missing keyword INSTRUME "
578 "in scientific frame header");
580 cpl_propertylist_delete(header); header = NULL;
582 cpl_msg_info(recipe,
"Scientific frame exposure time: %.2f s",
585 spectra =
dfs_load_image(frameset, science_tag, CPL_TYPE_FLOAT, 0, 0);
589 vimos_science_exit(
"Cannot load scientific frame");
591 cpl_free(exptime); exptime = NULL;
593 cpl_msg_indent_less();
603 vimos_science_exit(
"Cannot load scientific frame header");
605 quadrant = cpl_propertylist_get_int(header,
"ESO OCS CON QUAD");
609 key_gris_name =
"ESO INS GRIS1 NAME";
610 key_gris_id =
"ESO INS GRIS1 ID";
611 key_filt_name =
"ESO INS FILT1 NAME";
612 key_filt_id =
"ESO INS FILT1 ID";
615 key_gris_name =
"ESO INS GRIS2 NAME";
616 key_gris_id =
"ESO INS GRIS2 ID";
617 key_filt_name =
"ESO INS FILT2 NAME";
618 key_filt_id =
"ESO INS FILT2 ID";
621 key_gris_name =
"ESO INS GRIS3 NAME";
622 key_gris_id =
"ESO INS GRIS3 ID";
623 key_filt_name =
"ESO INS FILT3 NAME";
624 key_filt_id =
"ESO INS FILT3 ID";
627 key_gris_name =
"ESO INS GRIS4 NAME";
628 key_gris_id =
"ESO INS GRIS4 ID";
629 key_filt_name =
"ESO INS FILT4 NAME";
630 key_filt_id =
"ESO INS FILT4 ID";
651 nexp = cpl_propertylist_get_int(header,
"ESO TPL NEXP");
653 if (cpl_error_get_code() != CPL_ERROR_NONE)
654 vimos_science_exit(
"Missing keyword ESO TPL NEXP in "
655 "scientific frame header");
658 expno = cpl_propertylist_get_int(header,
"ESO TPL EXPNO");
660 if (cpl_error_get_code() != CPL_ERROR_NONE)
661 vimos_science_exit(
"Missing keyword ESO TPL EXPNO in "
662 "scientific frame header");
665 if (quadrant != expno) {
666 cpl_msg_warning(recipe,
"The MOS_STANDARD frame is not "
667 "expected to contain a standard star: "
668 "instrument response curve will not be "
669 "produced. Set --anyframe=true to skip "
684 gain = cpl_propertylist_get_double(header,
"ESO DET OUT1 CONAD");
686 if (cpl_error_get_code() != CPL_ERROR_NONE)
687 vimos_science_exit(
"Missing keyword ESO DET OUT1 CONAD in scientific "
690 cpl_msg_info(recipe,
"The gain factor is: %.2f e-/ADU", gain);
692 ron = cpl_propertylist_get_double(header,
"ESO DET OUT1 RON");
694 if (cpl_error_get_code() != CPL_ERROR_NONE)
695 vimos_science_exit(
"Missing keyword ESO DET OUT1 RON in scientific "
700 cpl_msg_info(recipe,
"The read-out-noise is: %.2f ADU", ron);
740 vimos_science_exit(
"Cosmic rays correction for long-slit-like "
741 "data requires --skyglobal=true");
742 skymedian = skylocal;
747 if (cpl_frameset_count_tags(frameset, curv_coeff_tag) == 0) {
748 cpl_msg_error(recipe,
"Missing required input: %s", curv_coeff_tag);
749 vimos_science_exit(NULL);
752 if (cpl_frameset_count_tags(frameset, curv_coeff_tag) > 1) {
753 cpl_msg_error(recipe,
"Too many in input: %s", curv_coeff_tag);
754 vimos_science_exit(NULL);
757 if (cpl_frameset_count_tags(frameset, slit_location_tag) == 0) {
758 cpl_msg_error(recipe,
"Missing required input: %s",
760 vimos_science_exit(NULL);
763 if (cpl_frameset_count_tags(frameset, slit_location_tag) > 1) {
764 cpl_msg_error(recipe,
"Too many in input: %s", slit_location_tag);
765 vimos_science_exit(NULL);
776 cpl_msg_info(recipe,
"Remove the master bias...");
778 bias =
dfs_load_image(frameset,
"MASTER_BIAS", CPL_TYPE_FLOAT, 0, 1);
781 vimos_science_exit(
"Cannot load master bias");
784 cpl_propertylist_delete(header); header = NULL;
786 cpl_image_delete(spectra); spectra = dummy; dummy = NULL;
787 cpl_image_delete(bias); bias = NULL;
788 cpl_table_delete(overscans); overscans = NULL;
791 vimos_science_exit(
"Cannot remove bias from scientific frame");
797 cpl_image_turn(spectra, rotate);
799 nx = cpl_image_get_size_x(spectra);
800 ny = cpl_image_get_size_y(spectra);
802 cpl_msg_indent_less();
803 cpl_msg_info(recipe,
"Load normalised flat field (if present)...");
804 cpl_msg_indent_more();
809 CPL_TYPE_FLOAT, 0, 1);
812 cpl_image_turn(norm_flat, rotate);
813 cpl_msg_info(recipe,
"Apply flat field correction...");
814 if (cpl_image_divide(spectra, norm_flat) != CPL_ERROR_NONE) {
815 cpl_msg_error(recipe,
"Failure of flat field correction: %s",
816 cpl_error_get_message());
817 vimos_science_exit(NULL);
819 cpl_image_delete(norm_flat); norm_flat = NULL;
822 cpl_msg_error(recipe,
"Cannot load input %s for flat field "
823 "correction", master_norm_flat_tag);
824 vimos_science_exit(NULL);
831 cpl_msg_indent_less();
832 cpl_msg_info(recipe,
"Load input sky line catalog...");
833 cpl_msg_indent_more();
843 nlines = cpl_table_get_nrow(wavelengths);
846 vimos_science_exit(
"Empty input sky line catalog");
848 if (cpl_table_has_column(wavelengths, wcolumn) != 1) {
849 cpl_msg_error(recipe,
"Missing column %s in input line "
850 "catalog table", wcolumn);
851 vimos_science_exit(NULL);
854 line = cpl_malloc(nlines *
sizeof(
double));
856 for (i = 0; i < nlines; i++)
857 line[i] = cpl_table_get(wavelengths, wcolumn, i, NULL);
859 cpl_table_delete(wavelengths); wavelengths = NULL;
861 lines = cpl_vector_wrap(nlines, line);
864 cpl_msg_info(recipe,
"No sky line catalog found in input - fine!");
876 if (polytraces == NULL)
877 vimos_science_exit(
"Cannot load spectral curvature table");
887 slits = cpl_table_new(1);
888 cpl_table_new_column(slits,
"slit_id", CPL_TYPE_INT);
889 cpl_table_set_int(slits,
"slit_id", 0, 1);
890 cpl_table_new_column(slits,
"position", CPL_TYPE_INT);
891 cpl_table_set_int(slits,
"position", 0, 0);
892 cpl_table_new_column(slits,
"length", CPL_TYPE_INT);
893 cpl_table_set_int(slits,
"length", 0, ny);
898 vimos_science_exit(
"Cannot load slits location table");
908 if (idscoeff == NULL)
909 vimos_science_exit(
"Cannot load wavelength calibration table");
911 cpl_msg_indent_less();
912 cpl_msg_info(recipe,
"Processing scientific spectra...");
913 cpl_msg_indent_more();
921 smapped = cpl_image_duplicate(spectra);
924 coordinate = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
927 startwavelength, endwavelength,
928 dispersion, flux, coordinate);
940 if (dispersion > 1.0)
947 cpl_msg_info(recipe,
"Align wavelength solution to reference "
948 "skylines applying %d order residual fit...", skyalign);
951 cpl_msg_info(recipe,
"Align wavelength solution to reference "
952 "skylines applying median offset...");
957 startwavelength, endwavelength,
958 idscoeff, lines, highres,
959 skyalign, rainbow, 4);
963 startwavelength, endwavelength,
964 idscoeff, lines, highres, skyalign,
968 cpl_vector_delete(lines); lines = NULL;
972 cpl_msg_warning(recipe,
"Alignment of the wavelength solution "
973 "to reference sky lines may be unreliable in "
977 parlist, recipe, version))
978 vimos_science_exit(NULL);
980 cpl_table_delete(offsets); offsets = NULL;
983 cpl_msg_warning(recipe,
"Alignment of the wavelength solution "
984 "to reference sky lines could not be done!");
996 polytraces, reference,
997 startwavelength, endwavelength,
1001 cpl_image_delete(rainbow); rainbow = NULL;
1002 cpl_image_delete(coordinate); coordinate = NULL;
1010 startwavelength, endwavelength,
1011 dispersion, idscoeff, flux);
1013 cpl_msg_indent_less();
1014 cpl_msg_info(recipe,
"Check applied wavelength against skylines...");
1015 cpl_msg_indent_more();
1018 dispersion, 6, highres);
1020 cpl_msg_info(recipe,
"Mean residual: %f", mean_rms);
1022 mean_rms = cpl_table_get_column_mean(idscoeff,
"error");
1024 cpl_msg_info(recipe,
"Mean model accuracy: %f pixel (%f A)",
1025 mean_rms, mean_rms * dispersion);
1027 header = cpl_propertylist_new();
1028 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
1029 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
1030 cpl_propertylist_update_double(header,
"CRVAL1",
1031 startwavelength + dispersion/2);
1032 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
1035 cpl_propertylist_update_double(header,
"CD1_1", dispersion);
1036 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
1037 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
1038 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
1039 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
1040 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
1042 if (time_normalise) {
1043 dummy = cpl_image_divide_scalar_create(mapped_sky, alltime);
1044 if (
dfs_save_image(frameset, dummy, mapped_science_sky_tag, header,
1045 parlist, recipe, version))
1046 vimos_science_exit(NULL);
1047 cpl_image_delete(dummy); dummy = NULL;
1051 header, parlist, recipe, version))
1052 vimos_science_exit(NULL);
1055 if (skyglobal == 0 && skymedian == 0 && skylocal == 0) {
1056 cpl_image_delete(mapped_sky); mapped_sky = NULL;
1059 if (skyglobal || skylocal) {
1061 cpl_msg_indent_less();
1064 cpl_msg_info(recipe,
"Global sky determination...");
1065 cpl_msg_indent_more();
1066 skymap = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1070 cpl_image_subtract(spectra, skymap);
1072 cpl_image_delete(skymap); skymap = NULL;
1075 cpl_msg_info(recipe,
"Local sky determination...");
1076 cpl_msg_indent_more();
1078 startwavelength, endwavelength, dispersion);
1084 cpl_table_divide_scalar(sky,
"sky", alltime);
1086 NULL, parlist, recipe, version))
1087 vimos_science_exit(NULL);
1089 cpl_table_delete(sky); sky = NULL;
1095 cpl_image_divide_scalar(skymap, alltime);
1096 cpl_image_turn(skymap, rotate_back);
1098 save_header, parlist, recipe, version))
1099 vimos_science_exit(NULL);
1101 cpl_image_delete(skymap); skymap = NULL;
1103 cpl_image_turn(spectra, rotate_back);
1106 cpl_msg_info(recipe,
"Removing cosmic rays...");
1111 save_header, parlist, recipe, version))
1112 vimos_science_exit(NULL);
1113 cpl_image_turn(spectra, rotate);
1115 cpl_propertylist_delete(save_header); save_header = NULL;
1122 cpl_image_delete(smapped); smapped = NULL;
1125 smapped = cpl_image_duplicate(spectra);
1129 reference, startwavelength,
1130 endwavelength, dispersion,
1135 cpl_msg_warning(recipe,
"Sky subtraction failure");
1137 cpl_msg_warning(recipe,
"Cosmic rays removal not performed!");
1138 cosmics = skylocal = skyglobal = 0;
1142 cpl_image_delete(spectra); spectra = NULL;
1143 cpl_table_delete(polytraces); polytraces = NULL;
1145 if (skyalign >= 0) {
1147 cpl_image_turn(wavemap, rotate_back);
1149 save_header, parlist, recipe, version))
1150 vimos_science_exit(NULL);
1151 cpl_propertylist_delete(save_header); save_header = NULL;
1154 cpl_image_delete(wavemap); wavemap = NULL;
1157 startwavelength, endwavelength,
1158 dispersion, idscoeff, flux);
1160 cpl_image_delete(smapped); smapped = NULL;
1163 cpl_msg_indent_less();
1164 cpl_msg_info(recipe,
"Local sky determination...");
1165 cpl_msg_indent_more();
1168 cpl_image_subtract(mapped, skylocalmap);
1169 cpl_image_delete(skylocalmap); skylocalmap = NULL;
1172 if (skyglobal || skymedian || skylocal) {
1174 skylocalmap = cpl_image_subtract_create(mapped_sky, mapped);
1176 cpl_image_delete(mapped_sky); mapped_sky = NULL;
1178 if (time_normalise) {
1179 dummy = cpl_image_divide_scalar_create(skylocalmap, alltime);
1181 parlist, recipe, version))
1182 vimos_science_exit(NULL);
1183 cpl_image_delete(dummy); dummy = NULL;
1186 if (
dfs_save_image(frameset, skylocalmap, mapped_sky_tag, header,
1187 parlist, recipe, version))
1188 vimos_science_exit(NULL);
1191 cpl_msg_indent_less();
1192 cpl_msg_info(recipe,
"Object detection...");
1193 cpl_msg_indent_more();
1195 if (cosmics || nscience > 1) {
1200 mapped_cleaned = cpl_image_duplicate(mapped);
1203 ext_radius, cont_radius);
1205 cpl_image_delete(mapped_cleaned); mapped_cleaned = NULL;
1208 cpl_image_delete(dummy); dummy = NULL;
1211 if (
dfs_save_table(frameset, slits, object_table_tag, NULL, parlist,
1213 vimos_science_exit(NULL);
1215 cpl_msg_indent_less();
1216 cpl_msg_info(recipe,
"Object extraction...");
1217 cpl_msg_indent_more();
1220 ext_mode, ron, gain, 1);
1222 cpl_image_delete(skylocalmap); skylocalmap = NULL;
1226 cpl_table *photcal = NULL;
1227 cpl_table *ext_table = NULL;
1228 cpl_table *flux_table = NULL;
1237 airmass, flux_table,
1240 cpl_table_delete(ext_table);
1241 cpl_table_delete(flux_table);
1248 char *pipefile = NULL;
1254 vimos_science_exit(
"Cannot reload scientific "
1265 "Product category", instrume))
1266 vimos_science_exit(
"Cannot write product category "
1270 "DPR type", instrume))
1271 vimos_science_exit(
"Missing keyword DPR TYPE in "
1272 "scientific frame header");
1275 "Template", instrume))
1276 vimos_science_exit(
"Missing keyword TPL ID in "
1277 "scientific frame header");
1280 key_gris_name, NULL,
1281 "Grism name", instrume)) {
1282 cpl_msg_error(recipe,
"Missing keyword %s in "
1283 "scientific frame header",
1285 vimos_science_exit(NULL);
1289 "ESO INS GRIS1 ID", NULL,
1292 cpl_msg_error(recipe,
"Missing keyword %s in "
1293 "scientific frame header",
1295 vimos_science_exit(NULL);
1298 if (cpl_propertylist_has(qclist, key_filt_name))
1300 "Filter name", instrume);
1303 "ESO DET CHIP1 ID", NULL,
1306 vimos_science_exit(
"Missing keyword DET CHIP1 ID "
1307 "in scientific frame header");
1310 "Archive name of input data",
1312 vimos_science_exit(
"Missing keyword ARCFILE in "
1313 "scientific frame header");
1315 pipefile = dfs_generate_filename_tfits(specphot_tag);
1318 "Pipeline product name",
1320 vimos_science_exit(
"Cannot write PIPEFILE to "
1333 dummy = cpl_image_new(wcount, 1, CPL_TYPE_FLOAT);
1334 data = cpl_image_get_data_float(dummy);
1335 map_table(dummy, wstart, wstep, photcal,
1336 "WAVE",
"EFFICIENCY");
1338 for (i = 0; i < wcount; i++) {
1339 sprintf(keyname,
"QC.MOS.EFFICIENCY%d.LAMBDA",
1343 keyname,
"Angstrom",
1345 "efficiency evaluation",
1347 vimos_science_exit(
"Cannot write wavelength of "
1348 "efficiency evaluation");
1351 sprintf(keyname,
"QC.MOS.EFFICIENCY%d", i + 1);
1354 keyname,
"e-/photon",
1357 vimos_science_exit(
"Cannot write wavelength of "
1358 "efficiency evaluation");
1362 cpl_image_delete(dummy); dummy = NULL;
1369 parlist, recipe, version)) {
1370 cpl_table_delete(photcal);
1371 vimos_science_exit(NULL);
1373 cpl_propertylist_delete(qclist); qclist = NULL;
1374 cpl_table_delete(photcal);
1379 cpl_image_divide_scalar(images[0], alltime);
1381 if (
dfs_save_image(frameset, images[0], reduced_science_tag, header,
1382 parlist, recipe, version))
1383 vimos_science_exit(NULL);
1385 cpl_image_delete(images[0]);
1388 cpl_image_divide_scalar(images[1], alltime);
1391 parlist, recipe, version))
1392 vimos_science_exit(NULL);
1394 cpl_image_delete(images[1]);
1397 cpl_image_divide_scalar(images[2], alltime);
1399 if (
dfs_save_image(frameset, images[2], reduced_error_tag, header,
1400 parlist, recipe, version))
1401 vimos_science_exit(NULL);
1403 cpl_image_delete(images[2]);
1408 cpl_msg_warning(recipe,
"No objects found: the products "
1409 "%s, %s, and %s are not created",
1410 reduced_science_tag, reduced_sky_tag,
1416 cpl_table_delete(slits); slits = NULL;
1418 if (skyalign >= 0) {
1420 parlist, recipe, version))
1421 vimos_science_exit(NULL);
1424 cpl_table_delete(idscoeff); idscoeff = NULL;
1426 if (skyglobal || skymedian || skylocal) {
1428 cpl_image_divide_scalar(mapped, alltime);
1430 parlist, recipe, version))
1431 vimos_science_exit(NULL);
1434 cpl_image_delete(mapped); mapped = NULL;
1435 cpl_propertylist_delete(header); header = NULL;
1437 if (cpl_error_get_code()) {
1438 cpl_msg_error(cpl_error_get_where(), cpl_error_get_message());
1439 vimos_science_exit(NULL);
cpl_image * mos_spatial_calibration(cpl_image *spectra, cpl_table *slits, cpl_table *polytraces, double reference, double blue, double red, double dispersion, int flux, cpl_image *calibration)
Spatial remapping of CCD spectra eliminating the spectral curvature.
cpl_table * mos_photometric_calibration(cpl_image *spectra, double startwave, double dispersion, double gain, double exptime, cpl_table *ext_table, double airmass, cpl_table *flux_table, int order)
Produce instrument response curve, with some ancillary information.
cpl_image * dfs_load_image(cpl_frameset *frameset, const char *category, cpl_type type, int ext, int calib)
Loading image data of given category.
const char * dfs_get_parameter_string(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe string parameter value.
double mos_distortions_rms(cpl_image *rectified, cpl_vector *lines, double wavestart, double dispersion, int radius, int highres)
Estimate the spectral distortion modeling goodness.
cpl_propertylist * dfs_load_header(cpl_frameset *frameset, const char *category, int ext)
Loading header associated to data of given category.
cpl_image ** mos_extract_objects(cpl_image *science, cpl_image *sky, cpl_table *objects, int extraction, double ron, double gain, int ncombined)
Extract detected objects from rectified scientific frame.
cpl_error_code fors_qc_write_qc_double(cpl_propertylist *header, double value, const char *name, const char *unit, const char *comment, const char *instrument)
Write an integer value to the active QC1 PAF object and to a header.
cpl_error_code mos_rotate_slits(cpl_table *slits, int rotation, int nx, int ny)
Rotate a slit location table.
cpl_image * mos_map_wavelengths(cpl_image *spatial, cpl_image *calibration, cpl_table *slits, cpl_table *polytraces, double reference, double blue, double red, double dispersion)
Remapping of spatially rectified wavelengths to original CCD pixels.
cpl_error_code fors_qc_keyword_to_paf(cpl_propertylist *header, const char *name, const char *unit, const char *comment, const char *instrument)
Copy a keyword value to the currently active QC1 PAF object.
cpl_image * mos_wavelength_calibration(cpl_image *image, double refwave, double firstLambda, double lastLambda, double dispersion, cpl_table *idscoeff, int flux)
Remap at constant wavelength step an image of rectified scientific spectra.
cpl_table * mos_sky_map_super(cpl_image *spectra, cpl_image *wavemap, double dispersion, double factor, int minpoints, cpl_image *skymap)
Create a CCD median sky map.
cpl_table * mos_wavelength_align(cpl_image *image, cpl_table *slits, double refwave, double firstLambda, double lastLambda, cpl_table *idscoeff, cpl_vector *skylines, int highres, int order, cpl_image *calibration, int sradius)
Modify the input wavelength solution to match reference sky lines.
cpl_error_code fors_qc_start_group(cpl_propertylist *header, const char *qcdic_version, const char *instrument)
Initiate a new QC1 group.
cpl_image * mos_remove_bias(cpl_image *image, cpl_image *bias, cpl_table *overscans)
Subtract the bias from a CCD exposure.
cpl_error_code fors_qc_write_string(const char *name, const char *value, const char *comment, const char *instrument)
Add string parameter to current QC1 group.
cpl_image * mos_detect_objects(cpl_image *image, cpl_table *slits, int margin, int maxradius, int conradius)
Detect objects in rectified scientific frame.
cpl_image * mos_sky_local_old(cpl_image *spectra, cpl_table *slits)
Local determination of sky.
int dfs_get_parameter_bool(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe boolean parameter value.
int dfs_equal_keyword(cpl_frameset *frameset, const char *keyword)
Saving table data of given category.
cpl_table * mos_wavelength_align_lss(cpl_image *image, double refwave, double firstLambda, double lastLambda, cpl_table *idscoeff, cpl_vector *skylines, int highres, int order, cpl_image *calibration, int sradius)
Modify the input wavelength solution to match reference sky lines (LSS).
cpl_image * mos_subtract_sky(cpl_image *science, cpl_table *slits, cpl_table *polytraces, double reference, double blue, double red, double dispersion)
Subtract the sky from the scientific CCD exposure.
cpl_image * mos_map_idscoeff(cpl_table *idscoeff, int xsize, double reference, double blue, double red)
Create a wavelengths map from an IDS coefficients table.
int dfs_save_image(cpl_frameset *frameset, const cpl_image *image, const char *category, cpl_propertylist *header, const cpl_parameterlist *parlist, const char *recipename, const char *version)
Saving image data of given category.
cpl_table * dfs_load_table(cpl_frameset *frameset, const char *category, int ext)
Loading table data of given category.
int dfs_get_parameter_int(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe integer parameter value.
int dfs_save_table(cpl_frameset *frameset, const cpl_table *table, const char *category, cpl_propertylist *header, const cpl_parameterlist *parlist, const char *recipename, const char *version)
Saving table data of given category.
cpl_error_code fors_qc_end_group(void)
Close current QC1 PAF file.
cpl_error_code mos_clean_cosmics(cpl_image *image, float gain, float threshold, float ratio)
Remove cosmic rays from sky-subtracted CCD spectral exposure.
double dfs_get_parameter_double(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe double parameter value.
cpl_table * mos_load_overscans_vimos(const cpl_propertylist *header, int check_consistency)
Get the overscan positions from FITS header of VIMOS data.