40 #include <fors_utils.h>
43 static int fors_pmos_extract_create(cpl_plugin *);
44 static int fors_pmos_extract_exec(cpl_plugin *);
45 static int fors_pmos_extract_destroy(cpl_plugin *);
46 static int fors_pmos_extract(cpl_parameterlist *, cpl_frameset *);
48 static float * fors_check_angles(cpl_frameset *,
int,
const char *,
int *);
50 fors_find_angle_pos(
float * angles,
int nangles,
float angle);
52 static char fors_pmos_extract_description[] =
53 "This recipe is used to reduce scientific spectra using the extraction\n"
54 "mask and the products created by the recipe fors_mpol_calib. The spectra\n"
55 "are bias subtracted, flat fielded (if a normalised flat field is specified)\n"
56 "and remapped eliminating the optical distortions. The wavelength calibration\n"
57 "can be optionally upgraded using a number of sky lines: if no sky lines\n"
58 "catalog of wavelengths is specified, an internal one is used instead.\n"
59 "If the alignment to the sky lines is performed, the input dispersion\n"
60 "coefficients table is upgraded and saved to disk, and a new CCD wavelengths\n"
62 "This recipe accepts both FORS1 and FORS2 frames. A grism table (typically\n"
63 "depending on the instrument mode, and in particular on the grism used)\n"
64 "may also be specified: this table contains a default recipe parameter\n"
65 "setting to control the way spectra are extracted for a specific instrument\n"
66 "mode, as it is used for automatic run of the pipeline on Paranal and in\n"
67 "Garching. If this table is specified, it will modify the default recipe\n"
68 "parameter setting, with the exception of those parameters which have been\n"
69 "explicitly modifyed on the command line. If a grism table is not specified,\n"
70 "the input recipe parameters values will always be read from the command\n"
71 "line, or from an esorex configuration file if present, or from their\n"
72 "generic default values (that are rarely meaningful).\n"
73 "Either a scientific or a standard star exposure can be specified in input.\n"
74 "The acronym SCI on products should be read STD in case of standard stars\n"
77 " DO category: Type: Explanation: Required:\n"
78 " SCIENCE_PMOS Raw Scientific exposure Y\n"
79 " or STANDARD_PMOS Raw Standard star exposure Y\n"
80 " MASTER_BIAS Calib Master bias Y\n"
81 " GRISM_TABLE Calib Grism table .\n"
82 " MASTER_SKYLINECAT Calib Sky lines catalog .\n"
84 " MASTER_NORM_FLAT_PMOS Calib Normalised flat field .\n"
85 " DISP_COEFF_PMOS Calib Inverse dispersion Y\n"
86 " CURV_COEFF_PMOS Calib Spectral curvature Y\n"
87 " SLIT_LOCATION_PMOS Calib Slits positions table Y\n"
88 " RETARDER_WAVEPLATE_CHROMATISM Calib Chromatism correction .\n"
91 " DO category: Data type: Explanation:\n"
92 " REDUCED_SCI_PMOS FITS image Extracted scientific spectra\n"
93 " REDUCED_SKY_SCI_PMOS FITS image Extracted sky spectra\n"
94 " REDUCED_ERROR_SCI_PMOS FITS image Errors on extracted spectra\n"
95 " REDUCED_SCI_X_PMOS FITS image X Stokes parameter (and L)\n"
96 " REDUCED_ERROR_X_PMOS FITS image Error on X Stokes parameter\n"
97 " REDUCED_NUL_X_PMOS FITS image Null parameter for X\n"
98 " REDUCED_POL_ANGLE_PMOS FITS image Direction of linear polarization\n"
99 " REDUCED_POL_ANGLE_ERROR_PMOS FITS image Error on polarization direction\n"
100 " UNMAPPED_SCI_PMOS FITS image Sky subtracted scientific spectra\n"
101 " MAPPED_SCI_PMOS FITS image Rectified scientific spectra\n"
102 " MAPPED_ALL_SCI_PMOS FITS image Rectified science spectra with sky\n"
103 " MAPPED_SKY_SCI_PMOS FITS image Rectified sky spectra\n"
104 " UNMAPPED_SKY_SCI_PMOS FITS image Sky on CCD\n"
105 " GLOBAL_SKY_SPECTRUM_PMOS FITS table Global sky spectrum\n"
106 " OBJECT_TABLE_SCI_PMOS FITS table Positions of detected objects\n"
107 " OBJECT_TABLE_POL_SCI_PMOS FITS table Positions of real objects\n"
109 " Only if the sky-alignment of the wavelength solution is requested:\n"
110 " DISP_COEFF_SCI_PMOS FITS table Upgraded dispersion coefficients\n"
111 " WAVELENGTH_MAP_SCI_PMOS FITS image Upgraded wavelength map\n\n";
113 #define fors_pmos_extract_exit(message) \
115 if ((const char *)message != NULL) cpl_msg_error(recipe, message); \
116 cpl_free(instrume); \
117 cpl_image_delete(dummy); \
118 cpl_image_delete(mapped_sky); \
119 cpl_image_delete(mapped_cleaned); \
120 cpl_image_delete(skymap); \
121 cpl_image_delete(smapped); \
122 cpl_table_delete(offsets); \
123 cpl_table_delete(sky); \
124 cpl_image_delete(bias); \
125 cpl_image_delete(spectra); \
126 cpl_image_delete(coordinate); \
127 cpl_image_delete(norm_flat); \
128 cpl_image_delete(rainbow); \
129 cpl_image_delete(rectified); \
130 cpl_image_delete(wavemap); \
131 cpl_propertylist_delete(header); \
132 cpl_propertylist_delete(save_header); \
133 cpl_table_delete(grism_table); \
134 cpl_table_delete(idscoeff); \
135 cpl_table_delete(maskslits); \
136 cpl_table_delete(overscans); \
137 cpl_table_delete(polytraces); \
138 cpl_table_delete(wavelengths); \
139 cpl_vector_delete(lines); \
140 cpl_msg_indent_less(); \
145 #define fors_pmos_extract_exit_memcheck(message) \
147 if ((const char *)message != NULL) cpl_msg_info(recipe, message); \
148 cpl_free(instrume); \
149 cpl_image_delete(dummy); \
150 cpl_image_delete(mapped_cleaned); \
151 cpl_image_delete(mapped_sky); \
152 cpl_image_delete(skymap); \
153 cpl_image_delete(smapped); \
154 cpl_table_delete(offsets); \
155 cpl_table_delete(sky); \
156 cpl_image_delete(bias); \
157 cpl_image_delete(spectra); \
158 cpl_image_delete(coordinate); \
159 cpl_image_delete(norm_flat); \
160 cpl_image_delete(rainbow); \
161 cpl_image_delete(rectified); \
162 cpl_image_delete(wavemap); \
163 cpl_propertylist_delete(header); \
164 cpl_propertylist_delete(save_header); \
165 cpl_table_delete(grism_table); \
166 cpl_table_delete(idscoeff); \
167 cpl_table_delete(maskslits); \
168 cpl_table_delete(overscans); \
169 cpl_table_delete(polytraces); \
170 cpl_table_delete(wavelengths); \
171 cpl_vector_delete(lines); \
172 cpl_msg_indent_less(); \
190 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe );
191 cpl_plugin *plugin = &recipe->interface;
193 cpl_plugin_init(plugin,
196 CPL_PLUGIN_TYPE_RECIPE,
198 "Extraction of scientific spectra",
199 fors_pmos_extract_description,
202 "This file is currently part of the FORS Instrument Pipeline\n"
203 "Copyright (C) 2002-2010 European Southern Observatory\n\n"
204 "This program is free software; you can redistribute it and/or modify\n"
205 "it under the terms of the GNU General Public License as published by\n"
206 "the Free Software Foundation; either version 2 of the License, or\n"
207 "(at your option) any later version.\n\n"
208 "This program is distributed in the hope that it will be useful,\n"
209 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
210 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
211 "GNU General Public License for more details.\n\n"
212 "You should have received a copy of the GNU General Public License\n"
213 "along with this program; if not, write to the Free Software Foundation,\n"
214 "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n",
215 fors_pmos_extract_create,
216 fors_pmos_extract_exec,
217 fors_pmos_extract_destroy);
219 cpl_pluginlist_append(list, plugin);
235 static int fors_pmos_extract_create(cpl_plugin *plugin)
245 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
246 recipe = (cpl_recipe *)plugin;
254 recipe->parameters = cpl_parameterlist_new();
261 p = cpl_parameter_new_value(
"fors.fors_pmos_extract.dispersion",
263 "Resampling step (Angstrom/pixel)",
264 "fors.fors_pmos_extract",
266 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"dispersion");
267 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
268 cpl_parameterlist_append(recipe->parameters, p);
274 p = cpl_parameter_new_value(
"fors.fors_pmos_extract.skyalign",
276 "Polynomial order for sky lines alignment, "
277 "or -1 to avoid alignment",
278 "fors.fors_pmos_extract",
280 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"skyalign");
281 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
282 cpl_parameterlist_append(recipe->parameters, p);
288 p = cpl_parameter_new_value(
"fors.fors_pmos_extract.wcolumn",
290 "Name of sky line catalog table column "
292 "fors.fors_pmos_extract",
294 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcolumn");
295 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
296 cpl_parameterlist_append(recipe->parameters, p);
302 p = cpl_parameter_new_value(
"fors.fors_pmos_extract.startwavelength",
304 "Start wavelength in spectral extraction",
305 "fors.fors_pmos_extract",
307 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"startwavelength");
308 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
309 cpl_parameterlist_append(recipe->parameters, p);
315 p = cpl_parameter_new_value(
"fors.fors_pmos_extract.endwavelength",
317 "End wavelength in spectral extraction",
318 "fors.fors_pmos_extract",
320 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"endwavelength");
321 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
322 cpl_parameterlist_append(recipe->parameters, p);
328 p = cpl_parameter_new_value(
"fors.fors_pmos_extract.flux",
330 "Apply flux conservation",
331 "fors.fors_pmos_extract",
333 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"flux");
334 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
335 cpl_parameterlist_append(recipe->parameters, p);
341 p = cpl_parameter_new_value(
"fors.fors_pmos_extract.flatfield",
344 "fors.fors_pmos_extract",
346 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"flatfield");
347 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
348 cpl_parameterlist_append(recipe->parameters, p);
354 p = cpl_parameter_new_value(
"fors.fors_pmos_extract.skyglobal",
356 "Subtract global sky spectrum from CCD",
357 "fors.fors_pmos_extract",
359 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"skyglobal");
360 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
361 cpl_parameterlist_append(recipe->parameters, p);
363 p = cpl_parameter_new_value(
"fors.fors_pmos_extract.skymedian",
365 "Sky subtraction from extracted slit spectra",
366 "fors.fors_pmos_extract",
368 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"skymedian");
369 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
370 cpl_parameterlist_append(recipe->parameters, p);
376 p = cpl_parameter_new_value(
"fors.fors_pmos_extract.skylocal",
378 "Sky subtraction from CCD slit spectra",
379 "fors.fors_pmos_extract",
381 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"skylocal");
382 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
383 cpl_parameterlist_append(recipe->parameters, p);
389 p = cpl_parameter_new_value(
"fors.fors_pmos_extract.cosmics",
391 "Eliminate cosmic rays hits (only if global "
392 "sky subtraction is also requested)",
393 "fors.fors_pmos_extract",
395 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"cosmics");
396 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
397 cpl_parameterlist_append(recipe->parameters, p);
403 p = cpl_parameter_new_value(
"fors.fors_pmos_extract.slit_margin",
405 "Number of pixels to exclude at each slit "
406 "in object detection and extraction",
407 "fors.fors_pmos_extract",
409 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slit_margin");
410 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
411 cpl_parameterlist_append(recipe->parameters, p);
417 p = cpl_parameter_new_value(
"fors.fors_pmos_extract.ext_radius",
419 "Maximum extraction radius for detected "
421 "fors.fors_pmos_extract",
423 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ext_radius");
424 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
425 cpl_parameterlist_append(recipe->parameters, p);
431 p = cpl_parameter_new_value(
"fors.fors_pmos_extract.cont_radius",
433 "Minimum distance at which two objects "
434 "of equal luminosity do not contaminate "
435 "each other (pixel)",
436 "fors.fors_pmos_extract",
438 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"cont_radius");
439 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
440 cpl_parameterlist_append(recipe->parameters, p);
446 p = cpl_parameter_new_value(
"fors.fors_pmos_extract.ext_mode",
448 "Object extraction method: 0 = aperture, "
449 "1 = Horne optimal extraction",
450 "fors.fors_pmos_extract",
452 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ext_mode");
453 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
454 cpl_parameterlist_append(recipe->parameters, p);
460 p = cpl_parameter_new_value(
"fors.fors_pmos_extract.time_normalise",
462 "Normalise output spectra by the exposure time",
463 "fors.fors_pmos_extract",
465 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"time_normalise");
466 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
467 cpl_parameterlist_append(recipe->parameters, p);
473 p = cpl_parameter_new_value(
"fors.fors_pmos_extract.chromatism",
475 "Chromatism correction to polarization angles",
476 "fors.fors_pmos_extract",
478 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"chromatism");
479 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
480 cpl_parameterlist_append(recipe->parameters, p);
486 p = cpl_parameter_new_value(
"fors.fors_pmos_extract.check",
488 "Create intermediate products",
489 "fors.fors_pmos_extract",
491 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"check");
492 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
493 cpl_parameterlist_append(recipe->parameters, p);
507 static int fors_pmos_extract_exec(cpl_plugin *plugin)
511 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
512 recipe = (cpl_recipe *)plugin;
516 return fors_pmos_extract(recipe->parameters, recipe->frames);
528 static int fors_pmos_extract_destroy(cpl_plugin *plugin)
532 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
533 recipe = (cpl_recipe *)plugin;
537 cpl_parameterlist_delete(recipe->parameters);
552 static int fors_pmos_extract(cpl_parameterlist *parlist, cpl_frameset *frameset)
555 const char *recipe =
"fors_pmos_extract";
565 double startwavelength;
566 double endwavelength;
587 cpl_image **reduceds = NULL;
588 cpl_image **rerrors = NULL;
589 cpl_table **slitss = NULL;
590 cpl_image **mappeds = NULL;
591 cpl_image **skylocalmaps = NULL;
595 cpl_image *bias = NULL;
596 cpl_image *norm_flat = NULL;
597 cpl_image *spectra = NULL;
598 cpl_image *rectified = NULL;
599 cpl_image *coordinate = NULL;
600 cpl_image *rainbow = NULL;
601 cpl_image *mapped = NULL;
602 cpl_image *mapped_sky = NULL;
603 cpl_image *mapped_cleaned = NULL;
604 cpl_image *smapped = NULL;
605 cpl_image *wavemap = NULL;
606 cpl_image *skymap = NULL;
607 cpl_image *skylocalmap = NULL;
608 cpl_image *dummy = NULL;
610 cpl_table *grism_table = NULL;
611 cpl_table *overscans = NULL;
612 cpl_table *wavelengths = NULL;
613 cpl_table *idscoeff = NULL;
614 cpl_table *slits = NULL;
615 cpl_table *origslits = NULL;
616 cpl_table *maskslits = NULL;
617 cpl_table *polytraces = NULL;
618 cpl_table *offsets = NULL;
619 cpl_table *sky = NULL;
621 cpl_vector *lines = NULL;
623 cpl_propertylist *header = NULL;
624 cpl_propertylist *save_header = NULL;
626 cpl_table *global = NULL;
632 char *instrume = NULL;
633 const char *science_tag;
634 const char *master_norm_flat_tag;
635 const char *disp_coeff_sky_tag;
636 const char *wavelength_map_sky_tag;
637 const char *reduced_science_tag;
638 const char *reduced_sky_tag;
639 const char *reduced_error_tag;
640 const char *mapped_science_tag;
641 const char *unmapped_science_tag;
642 const char *mapped_science_sky_tag;
643 const char *mapped_sky_tag;
644 const char *unmapped_sky_tag;
645 const char *global_sky_spectrum_tag;
646 const char *object_table_tag;
647 const char *object_table_pol_tag;
648 const char *skylines_offsets_tag;
649 const char *reduced_q_tag;
650 const char *reduced_u_tag;
651 const char *reduced_v_tag;
652 const char *reduced_l_tag;
653 const char *reduced_error_q_tag;
654 const char *reduced_error_u_tag;
655 const char *reduced_error_v_tag;
656 const char *reduced_error_l_tag;
657 const char *reduced_nul_q_tag;
658 const char *reduced_nul_u_tag;
659 const char *reduced_nul_v_tag;
660 const char *reduced_angle_tag;
661 const char *reduced_error_angle_tag;
662 const char *master_distortion_tag =
"MASTER_DISTORTION_TABLE";
663 const char *chrom_table_tag =
"RETARDER_WAVEPLATE_CHROMATISM";
664 float *angles = NULL;
680 cpl_error_code error;
682 int * nobjs_per_slit;
683 int nslits_out_det = 0;
686 snprintf(version, 80,
"%s-%s", PACKAGE, PACKAGE_VERSION);
688 cpl_msg_set_indentation(2);
694 cpl_msg_info(recipe,
"Recipe %s configuration parameters:", recipe);
695 cpl_msg_indent_more();
697 if (cpl_frameset_count_tags(frameset,
"GRISM_TABLE") > 1)
698 fors_pmos_extract_exit(
"Too many in input: GRISM_TABLE");
703 "fors.fors_pmos_extract.dispersion", grism_table);
705 if (dispersion <= 0.0)
706 fors_pmos_extract_exit(
"Invalid resampling step");
709 "fors.fors_pmos_extract.skyalign", NULL);
712 fors_pmos_extract_exit(
"Max polynomial degree for sky alignment is 2");
715 "fors.fors_pmos_extract.wcolumn", NULL);
718 "fors.fors_pmos_extract.startwavelength", grism_table);
719 if (startwavelength < 3000.0 || startwavelength > 13000.0)
720 fors_pmos_extract_exit(
"Invalid wavelength");
723 "fors.fors_pmos_extract.endwavelength", grism_table);
724 if (endwavelength < 3000.0 || endwavelength > 13000.0)
725 fors_pmos_extract_exit(
"Invalid wavelength");
727 if (endwavelength - startwavelength <= 0.0)
728 fors_pmos_extract_exit(
"Invalid wavelength interval");
750 if (skylocal && skyglobal)
751 fors_pmos_extract_exit(
"Cannot apply both local and global sky subtraction");
753 if (skylocal && skymedian)
754 fors_pmos_extract_exit(
"Cannot apply sky subtraction both on extracted "
755 "and non-extracted spectra");
758 "fors.fors_pmos_extract.cosmics", NULL);
761 if (!(skyglobal || skylocal))
762 fors_pmos_extract_exit(
"Cosmic rays correction requires "
763 "either skylocal=true or skyglobal=true");
766 "fors.fors_pmos_extract.slit_margin",
769 fors_pmos_extract_exit(
"Value must be zero or positive");
774 fors_pmos_extract_exit(
"Value must be zero or positive");
777 "fors.fors_pmos_extract.cont_radius",
780 fors_pmos_extract_exit(
"Value must be zero or positive");
784 if (ext_mode < 0 || ext_mode > 1)
785 fors_pmos_extract_exit(
"Invalid object extraction mode");
788 "fors.fors_pmos_extract.time_normalise", NULL);
791 cpl_table_delete(grism_table); grism_table = NULL;
793 if (cpl_error_get_code())
794 fors_pmos_extract_exit(
"Failure getting the configuration parameters");
801 cpl_msg_indent_less();
802 cpl_msg_info(recipe,
"Check input set-of-frames:");
803 cpl_msg_indent_more();
806 cpl_msg_warning(cpl_func,
"Input frames are not from the same grism");
809 cpl_msg_warning(cpl_func,
"Input frames are not from the same filter");
812 cpl_msg_warning(cpl_func,
"Input frames are not from the same chip");
815 pmos = cpl_frameset_count_tags(frameset,
"SCIENCE_PMOS");
818 pmos = cpl_frameset_count_tags(frameset,
"STANDARD_PMOS");
823 fors_pmos_extract_exit(
"Missing input scientific frame");
825 angles = fors_check_angles(frameset, pmos,
826 standard ?
"STANDARD_PMOS" :
"SCIENCE_PMOS",
829 fors_pmos_extract_exit(
"Polarization angles could not be read");
838 reduceds = (cpl_image **)cpl_malloc(
sizeof(cpl_image *) * nscience);
839 rerrors = (cpl_image **)cpl_malloc(
sizeof(cpl_image *) * nscience);
840 slitss = (cpl_table **)cpl_malloc(
sizeof(cpl_table *) * nscience);
841 mappeds = (cpl_image **)cpl_malloc(
sizeof(cpl_image *) * nscience);
842 skylocalmaps = (cpl_image **)cpl_malloc(
sizeof(cpl_image *) * nscience);
845 cpl_msg_info(recipe,
"PMOS data found");
847 science_tag =
"STANDARD_PMOS";
848 reduced_science_tag =
"REDUCED_STD_PMOS";
849 unmapped_science_tag =
"UNMAPPED_STD_PMOS";
850 mapped_science_tag =
"MAPPED_STD_PMOS";
851 mapped_science_sky_tag =
"MAPPED_ALL_STD_PMOS";
852 skylines_offsets_tag =
"SKY_SHIFTS_SLIT_STD_PMOS";
853 wavelength_map_sky_tag =
"WAVELENGTH_MAP_STD_PMOS";
854 disp_coeff_sky_tag =
"DISP_COEFF_STD_PMOS";
855 mapped_sky_tag =
"MAPPED_SKY_STD_PMOS";
856 unmapped_sky_tag =
"UNMAPPED_SKY_STD_PMOS";
857 object_table_tag =
"OBJECT_TABLE_STD_PMOS";
858 object_table_pol_tag =
"OBJECT_TABLE_POL_STD_PMOS";
859 reduced_sky_tag =
"REDUCED_SKY_STD_PMOS";
860 reduced_error_tag =
"REDUCED_ERROR_STD_PMOS";
861 reduced_q_tag =
"REDUCED_Q_STD_PMOS";
862 reduced_u_tag =
"REDUCED_U_STD_PMOS";
863 reduced_v_tag =
"REDUCED_V_STD_PMOS";
864 reduced_l_tag =
"REDUCED_L_STD_PMOS";
865 reduced_error_q_tag =
"REDUCED_ERROR_Q_STD_PMOS";
866 reduced_error_u_tag =
"REDUCED_ERROR_U_STD_PMOS";
867 reduced_error_v_tag =
"REDUCED_ERROR_V_STD_PMOS";
868 reduced_error_l_tag =
"REDUCED_ERROR_L_STD_PMOS";
869 reduced_nul_q_tag =
"REDUCED_NUL_Q_STD_PMOS";
870 reduced_nul_u_tag =
"REDUCED_NUL_U_STD_PMOS";
871 reduced_nul_v_tag =
"REDUCED_NUL_V_STD_PMOS";
872 reduced_angle_tag =
"REDUCED_ANGLE_STD_PMOS";
873 reduced_error_angle_tag =
"REDUCED_ERROR_ANGLE_STD_PMOS";
876 science_tag =
"SCIENCE_PMOS";
877 reduced_science_tag =
"REDUCED_SCI_PMOS";
878 unmapped_science_tag =
"UNMAPPED_SCI_PMOS";
879 mapped_science_tag =
"MAPPED_SCI_PMOS";
880 mapped_science_sky_tag =
"MAPPED_ALL_SCI_PMOS";
881 skylines_offsets_tag =
"SKY_SHIFTS_SLIT_SCI_PMOS";
882 wavelength_map_sky_tag =
"WAVELENGTH_MAP_SCI_PMOS";
883 disp_coeff_sky_tag =
"DISP_COEFF_SCI_PMOS";
884 mapped_sky_tag =
"MAPPED_SKY_SCI_PMOS";
885 unmapped_sky_tag =
"UNMAPPED_SKY_SCI_PMOS";
886 object_table_tag =
"OBJECT_TABLE_SCI_PMOS";
887 object_table_pol_tag =
"OBJECT_TABLE_POL_SCI_PMOS";
888 reduced_sky_tag =
"REDUCED_SKY_SCI_PMOS";
889 reduced_error_tag =
"REDUCED_ERROR_SCI_PMOS";
890 reduced_q_tag =
"REDUCED_Q_SCI_PMOS";
891 reduced_u_tag =
"REDUCED_U_SCI_PMOS";
892 reduced_v_tag =
"REDUCED_V_SCI_PMOS";
893 reduced_l_tag =
"REDUCED_L_SCI_PMOS";
894 reduced_error_q_tag =
"REDUCED_ERROR_Q_SCI_PMOS";
895 reduced_error_u_tag =
"REDUCED_ERROR_U_SCI_PMOS";
896 reduced_error_v_tag =
"REDUCED_ERROR_V_SCI_PMOS";
897 reduced_error_l_tag =
"REDUCED_ERROR_L_SCI_PMOS";
898 reduced_nul_q_tag =
"REDUCED_NUL_Q_SCI_PMOS";
899 reduced_nul_u_tag =
"REDUCED_NUL_U_SCI_PMOS";
900 reduced_nul_v_tag =
"REDUCED_NUL_V_SCI_PMOS";
901 reduced_angle_tag =
"REDUCED_ANGLE_SCI_PMOS";
902 reduced_error_angle_tag =
"REDUCED_ERROR_ANGLE_SCI_PMOS";
905 master_norm_flat_tag =
"MASTER_NORM_FLAT_PMOS";
906 global_sky_spectrum_tag =
"GLOBAL_SKY_SPECTRUM_PMOS";
908 if (!cpl_frameset_count_tags(frameset, master_norm_flat_tag)) {
909 master_norm_flat_tag =
"MASTER_NORM_FLAT_LONG_PMOS";
913 if (cpl_frameset_count_tags(frameset,
"MASTER_BIAS") == 0)
914 fors_pmos_extract_exit(
"Missing required input: MASTER_BIAS");
916 if (cpl_frameset_count_tags(frameset,
"MASTER_BIAS") > 1)
917 fors_pmos_extract_exit(
"Too many in input: MASTER_BIAS");
920 if (cpl_frameset_count_tags(frameset,
"MASTER_SKYLINECAT") > 1)
921 fors_pmos_extract_exit(
"Too many in input: MASTER_SKYLINECAT");
924 if (cpl_frameset_count_tags(frameset, chrom_table_tag) == 0) {
925 cpl_msg_error(recipe,
"Missing required input: %s",
927 fors_pmos_extract_exit(NULL);
930 if (cpl_frameset_count_tags(frameset, chrom_table_tag) > 1) {
931 cpl_msg_error(recipe,
"Too many in input: %s", chrom_table_tag);
932 fors_pmos_extract_exit(NULL);
936 if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) > 1) {
938 cpl_msg_error(recipe,
"Too many in input: %s",
939 master_norm_flat_tag);
940 fors_pmos_extract_exit(NULL);
943 cpl_msg_warning(recipe,
"%s in input are ignored, "
944 "since flat field correction was not requested",
945 master_norm_flat_tag);
949 if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) == 1) {
951 cpl_msg_warning(recipe,
"%s in input is ignored, "
952 "since flat field correction was not requested",
953 master_norm_flat_tag);
957 if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) == 0) {
959 cpl_msg_error(recipe,
"Flat field correction was requested, "
960 "but no %s are found in input",
961 master_norm_flat_tag);
962 fors_pmos_extract_exit(NULL);
966 if (cpl_frameset_count_tags(frameset, master_distortion_tag) == 0)
967 fors_pmos_extract_exit(
"Missing required input: MASTER_DISTORTION_TABLE");
969 if (cpl_frameset_count_tags(frameset, master_distortion_tag) > 1)
970 fors_pmos_extract_exit(
"Too many in input: MASTER_DISTORTION_TABLE");
974 fors_pmos_extract_exit(
"Cannot load master distortion table");
976 cpl_msg_indent_less();
986 fors_pmos_extract_exit(
"Cannot load scientific frame header");
988 instrume = (
char *)cpl_propertylist_get_string(header,
"INSTRUME");
989 if (instrume == NULL)
990 fors_pmos_extract_exit(
"Missing keyword INSTRUME in scientific header");
991 instrume = cpl_strdup(instrume);
993 if (instrume[4] ==
'1')
994 snprintf(version, 80,
"%s/%s",
"fors1", VERSION);
995 if (instrume[4] ==
'2')
996 snprintf(version, 80,
"%s/%s",
"fors2", VERSION);
998 reference = cpl_propertylist_get_double(header,
"ESO INS GRIS1 WLEN");
1000 if (cpl_error_get_code() != CPL_ERROR_NONE)
1001 fors_pmos_extract_exit(
"Missing keyword ESO INS GRIS1 WLEN in scientific "
1004 if (reference < 3000.0)
1007 if (reference < 3000.0 || reference > 13000.0) {
1008 cpl_msg_error(recipe,
"Invalid central wavelength %.2f read from "
1009 "keyword ESO INS GRIS1 WLEN in scientific frame header",
1011 fors_pmos_extract_exit(NULL);
1014 cpl_msg_info(recipe,
"The central wavelength is: %.2f", reference);
1016 rebin = cpl_propertylist_get_int(header,
"ESO DET WIN1 BINX");
1018 if (cpl_error_get_code() != CPL_ERROR_NONE)
1019 fors_pmos_extract_exit(
"Missing keyword ESO DET WIN1 BINX in scientific "
1023 dispersion *= rebin;
1024 cpl_msg_warning(recipe,
"The rebin factor is %d, and therefore the "
1025 "resampling step used is %f A/pixel", rebin,
1029 gain = cpl_propertylist_get_double(header,
"ESO DET OUT1 CONAD");
1031 if (cpl_error_get_code() != CPL_ERROR_NONE)
1032 fors_pmos_extract_exit(
"Missing keyword ESO DET OUT1 CONAD in scientific "
1035 cpl_msg_info(recipe,
"The gain factor is: %.2f e-/ADU", gain);
1037 ron = cpl_propertylist_get_double(header,
"ESO DET OUT1 RON");
1039 if (cpl_error_get_code() != CPL_ERROR_NONE)
1040 fors_pmos_extract_exit(
"Missing keyword ESO DET OUT1 RON in scientific "
1045 cpl_msg_info(recipe,
"The read-out-noise is: %.2f ADU", ron);
1047 cpl_msg_info(recipe,
"Load normalised flat field (if present)...");
1048 cpl_msg_indent_more();
1052 CPL_TYPE_FLOAT, 0, 1);
1055 cpl_msg_info(recipe,
"Produce mask slit position table...");
1059 if (skyalign >= 0) {
1061 cpl_msg_indent_less();
1062 cpl_msg_info(recipe,
"Load input sky line catalog...");
1063 cpl_msg_indent_more();
1072 nlines = cpl_table_get_nrow(wavelengths);
1075 fors_pmos_extract_exit(
"Empty input sky line catalog");
1077 if (cpl_table_has_column(wavelengths, wcolumn) != 1) {
1078 cpl_msg_error(recipe,
"Missing column %s in input line "
1079 "catalog table", wcolumn);
1080 fors_pmos_extract_exit(NULL);
1083 line = cpl_malloc(nlines *
sizeof(
double));
1085 for (i = 0; i < nlines; i++)
1086 line[i] = cpl_table_get(wavelengths, wcolumn, i, NULL);
1088 cpl_table_delete(wavelengths); wavelengths = NULL;
1090 lines = cpl_vector_wrap(nlines, line);
1093 cpl_msg_info(recipe,
"No sky line catalog found in input - fine!");
1098 cpl_propertylist_delete(header); header = NULL;
1104 for (j = 0; j < nscience; j++) {
1107 cpl_msg_indent_less();
1108 cpl_msg_info(recipe,
"Processing scientific exposure of angle %.2f "
1109 "(%d out of %d) ...",
1110 angles[j], j + 1, nscience);
1111 cpl_msg_indent_more();
1113 cpl_msg_info(recipe,
"Load scientific exposure...");
1114 cpl_msg_indent_more();
1124 for (k = 0; k < j; k ++) {
1125 cpl_propertylist_delete(header);
1129 spectra =
dfs_load_image(frameset, science_tag, CPL_TYPE_FLOAT, 0, 0);
1131 for (k = 0; k < j; k ++) {
1132 cpl_image_delete(spectra);
1136 if (spectra == NULL)
1137 fors_pmos_extract_exit(
"Cannot load scientific frame");
1140 fors_pmos_extract_exit(
"Cannot load scientific frame header");
1142 alltime = cpl_propertylist_get_double(header,
"EXPTIME");
1144 if (cpl_error_get_code() != CPL_ERROR_NONE)
1145 fors_pmos_extract_exit(
"Missing keyword EXPTIME in scientific "
1151 cpl_msg_info(recipe,
"Scientific frame exposure time: %.2f s",
1154 cpl_msg_indent_less();
1160 cpl_msg_info(recipe,
"Remove the master bias...");
1162 bias =
dfs_load_image(frameset,
"MASTER_BIAS", CPL_TYPE_FLOAT, 0, 1);
1165 fors_pmos_extract_exit(
"Cannot load master bias");
1170 cpl_image_delete(spectra); spectra = dummy; dummy = NULL;
1171 cpl_image_delete(bias); bias = NULL;
1172 cpl_table_delete(overscans); overscans = NULL;
1174 if (spectra == NULL)
1175 fors_pmos_extract_exit(
"Cannot remove bias from scientific frame");
1177 ccd_xsize = nx = cpl_image_get_size_x(spectra);
1178 ny = cpl_image_get_size_y(spectra);
1183 cpl_msg_info(recipe,
"Apply flat field correction...");
1184 if (cpl_image_divide(spectra, norm_flat) != CPL_ERROR_NONE) {
1185 cpl_msg_error(recipe,
"Failure of flat field correction: %s",
1186 cpl_error_get_message());
1187 fors_pmos_extract_exit(NULL);
1191 cpl_msg_error(recipe,
"Cannot load input %s for flat field "
1192 "correction", master_norm_flat_tag);
1193 fors_pmos_extract_exit(NULL);
1204 if (slits == NULL) {
1205 fors_pmos_extract_exit(
"Cannot load slits location table");
1207 cpl_table_new_column(slits,
"pair_id", CPL_TYPE_INT);
1209 int m, null, size = cpl_table_get_nrow(slits);
1211 for (m = 0; m < size; m++) {
1212 int slit_id = cpl_table_get(slits,
"slit_id", m, &null);
1214 int pair_id = slit_id % 2 ? slit_id + 1 : slit_id;
1216 cpl_table_set(slits,
"pair_id", m, pair_id);
1220 cpl_msg_info(recipe,
"Processing scientific spectra...");
1227 if (polytraces == NULL)
1228 fors_pmos_extract_exit(
"Cannot create spectral curvature table");
1235 coordinate = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1238 startwavelength, endwavelength,
1239 dispersion, flux, coordinate);
1251 if (idscoeff == NULL)
1252 fors_pmos_extract_exit(
"Cannot create wavelength calibration table");
1257 if (dispersion > 1.0)
1262 if (skyalign >= 0) {
1264 cpl_msg_info(recipe,
"Align wavelength solution to reference "
1265 "skylines applying %d order residual fit...", skyalign);
1268 cpl_msg_info(recipe,
"Align wavelength solution to reference "
1269 "skylines applying median offset...");
1274 startwavelength, endwavelength,
1275 idscoeff, lines, highres,
1276 skyalign, rainbow, 4);
1280 cpl_msg_warning(recipe,
"Alignment of the wavelength solution "
1281 "to reference sky lines may be unreliable in "
1285 NULL, parlist, recipe, version)) {
1286 fors_pmos_extract_exit(NULL);
1290 cpl_msg_warning(recipe,
"Alignment of the wavelength solution "
1291 "to reference sky lines could not be done!");
1300 polytraces, reference,
1301 startwavelength, endwavelength,
1305 cpl_image_delete(rainbow); rainbow = NULL;
1306 cpl_image_delete(coordinate); coordinate = NULL;
1314 startwavelength, endwavelength,
1315 dispersion, idscoeff, flux);
1318 cpl_msg_indent_less();
1319 cpl_msg_info(recipe,
"Check applied wavelength against skylines...");
1320 cpl_msg_indent_more();
1323 dispersion, 6, highres);
1326 cpl_msg_info(recipe,
"Mean residual: %f", mean_rms);
1328 mean_rms = cpl_table_get_column_mean(idscoeff,
"error");
1330 cpl_msg_info(recipe,
"Mean model accuracy: %f pixel (%f A)",
1331 mean_rms, mean_rms * dispersion);
1334 save_header = cpl_propertylist_duplicate(header);
1336 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
1337 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
1338 cpl_propertylist_update_double(header,
"CRVAL1",
1339 startwavelength + dispersion/2);
1340 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
1343 cpl_propertylist_update_double(header,
"CD1_1", dispersion);
1344 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
1345 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
1346 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
1347 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
1348 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
1350 if (time_normalise) {
1351 dummy = cpl_image_divide_scalar_create(mapped_sky, alltime);
1354 mapped_science_sky_tag,
1356 fors_pmos_extract_exit(NULL);
1360 fors_pmos_extract_exit(NULL);
1362 cpl_image_delete(dummy); dummy = NULL;
1368 mapped_science_sky_tag,
1370 fors_pmos_extract_exit(NULL);
1375 mapped_science_sky_tag, header)) {
1376 fors_pmos_extract_exit(NULL);
1382 if (skyglobal == 0 && skymedian == 0 && skylocal == 0) {
1383 cpl_image_delete(mapped_sky); mapped_sky = NULL;
1386 if (skyglobal || skylocal) {
1388 cpl_msg_indent_less();
1391 cpl_msg_info(recipe,
"Global sky determination...");
1392 cpl_msg_indent_more();
1393 skymap = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1399 cpl_image_subtract(spectra, skymap);
1402 cpl_image_delete(skymap); skymap = NULL;
1406 cpl_msg_info(recipe,
"Local sky determination...");
1407 cpl_msg_indent_more();
1409 startwavelength, endwavelength, dispersion);
1415 cpl_table_divide_scalar(sky,
"sky", alltime);
1436 global_sky_spectrum_tag,
1438 fors_pmos_extract_exit(NULL);
1444 fors_pmos_extract_exit(NULL);
1448 cpl_table_delete(sky); sky = NULL;
1454 cpl_image_divide_scalar(skymap, alltime);
1460 fors_pmos_extract_exit(NULL);
1466 fors_pmos_extract_exit(NULL);
1469 cpl_image_delete(skymap); skymap = NULL;
1473 unmapped_science_tag,
1475 fors_pmos_extract_exit(NULL);
1481 fors_pmos_extract_exit(NULL);
1487 cpl_msg_info(recipe,
"Removing cosmic rays...");
1496 cpl_image_delete(smapped); smapped = NULL;
1499 reference, startwavelength,
1500 endwavelength, dispersion,
1504 cpl_msg_warning(recipe,
"Sky subtraction failure");
1506 cpl_msg_warning(recipe,
"Cosmic rays removal not performed!");
1507 cosmics = skylocal = skyglobal = 0;
1511 cpl_image_delete(spectra); spectra = NULL;
1512 cpl_table_delete(polytraces); polytraces = NULL;
1514 if (skyalign >= 0) {
1519 wavelength_map_sky_tag,
1521 fors_pmos_extract_exit(NULL);
1527 fors_pmos_extract_exit(NULL);
1533 cpl_image_delete(wavemap); wavemap = NULL;
1536 startwavelength, endwavelength,
1537 dispersion, idscoeff, flux);
1539 cpl_image_delete(smapped); smapped = NULL;
1541 if (skyalign >= 0) {
1544 NULL, parlist, recipe, version)) {
1545 fors_pmos_extract_exit(NULL);
1552 cpl_msg_indent_less();
1553 cpl_msg_info(recipe,
"Local sky determination...");
1554 cpl_msg_indent_more();
1559 cpl_image_subtract(mapped, skylocalmap);
1565 cpl_image_delete(skylocalmap); skylocalmap = NULL;
1569 if (skyglobal || skymedian || skylocal) {
1571 skylocalmap = cpl_image_subtract_create(mapped_sky, mapped);
1573 cpl_image_delete(mapped_sky); mapped_sky = NULL;
1575 if (time_normalise) {
1576 dummy = cpl_image_divide_scalar_create(skylocalmap, alltime);
1582 fors_pmos_extract_exit(NULL);
1588 fors_pmos_extract_exit(NULL);
1591 cpl_image_delete(dummy); dummy = NULL;
1598 fors_pmos_extract_exit(NULL);
1604 fors_pmos_extract_exit(NULL);
1608 skylocalmaps[j] = skylocalmap;
1610 cpl_msg_indent_less();
1611 cpl_msg_info(recipe,
"Object detection...");
1612 cpl_msg_indent_more();
1615 origslits = cpl_table_duplicate(slits);
1617 if (cosmics || nscience > 1) {
1622 mapped_cleaned = cpl_image_duplicate(mapped);
1625 ext_radius, cont_radius);
1627 cpl_image_delete(mapped_cleaned); mapped_cleaned = NULL;
1630 cpl_image_delete(dummy); dummy = NULL;
1653 fors_pmos_extract_exit(NULL);
1658 fors_pmos_extract_exit(NULL);
1664 mappeds[j] = mapped;
1666 cpl_msg_indent_less();
1668 cpl_propertylist_delete(header); header = NULL;
1669 cpl_propertylist_delete(save_header); save_header = NULL;
1671 cpl_table_delete(idscoeff); idscoeff = NULL;
1674 cpl_table_delete(offsets); offsets = NULL;
1676 cpl_image_delete(norm_flat); norm_flat = NULL;
1677 cpl_vector_delete(lines); lines = NULL;
1679 cpl_table_delete(maskslits); maskslits = NULL;
1682 cpl_msg_indent_less();
1683 cpl_msg_info(recipe,
1684 "Check object detection in both beams for all angles...");
1685 cpl_msg_indent_more();
1690 if (error == CPL_ERROR_DATA_NOT_FOUND) {
1691 cpl_msg_warning(recipe,
"No objects found: no Stokes "
1692 "parameters to compute!");
1693 for (j = 0; j < nscience; j++)
1694 cpl_table_delete(slitss[j]);
1696 cpl_table_delete(origslits);
1699 fors_pmos_extract_exit(
"Problem in polarimetric object selection");
1703 NULL, parlist, recipe, version)) {
1704 fors_pmos_extract_exit(NULL);
1707 nobjs_per_slit = fors_get_nobjs_perslit(origslits);
1709 cpl_msg_indent_less();
1710 cpl_msg_info(recipe,
"Object extraction...");
1711 cpl_msg_indent_more();
1713 for (j = 0; j < nscience; j++) {
1718 for (k = 0; k < j; k ++) {
1719 cpl_propertylist_delete(header);
1723 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
1724 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
1725 cpl_propertylist_update_double(header,
"CRVAL1",
1726 startwavelength + dispersion/2);
1727 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
1730 cpl_propertylist_update_double(header,
"CD1_1", dispersion);
1731 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
1732 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
1733 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
1734 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
1735 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
1737 if (skyglobal || skymedian || skylocal) {
1739 cpl_msg_info(recipe,
"Extracting at angle %.2f (%d out of %d) ...",
1740 angles[j], j + 1, nscience);
1744 ext_mode, ron, gain, 1);
1746 cpl_image_delete(skylocalmaps[j]); skylocalmaps[j] = NULL;
1750 cpl_image_divide_scalar(images[0], alltime);
1754 reduced_science_tag,
1756 fors_pmos_extract_exit(NULL);
1762 fors_pmos_extract_exit(NULL);
1765 reduceds[j] = images[0];
1769 cpl_image_divide_scalar(images[1], alltime);
1775 fors_pmos_extract_exit(NULL);
1781 fors_pmos_extract_exit(NULL);
1783 cpl_image_delete(images[1]);
1786 cpl_image_divide_scalar(images[2], alltime);
1792 fors_pmos_extract_exit(NULL);
1798 fors_pmos_extract_exit(NULL);
1801 rerrors[j] = images[2];
1807 cpl_msg_warning(recipe,
"No objects found: the products "
1808 "%s, %s, and %s are not created",
1809 reduced_science_tag, reduced_sky_tag,
1820 if (skyglobal || skymedian || skylocal) {
1822 cpl_image_divide_scalar(mappeds[j], alltime);
1828 fors_pmos_extract_exit(NULL);
1834 fors_pmos_extract_exit(NULL);
1838 cpl_image_delete(mappeds[j]); mappeds[j] = NULL;
1839 cpl_propertylist_delete(header); header = NULL;
1843 cpl_table_delete(origslits);
1847 nobjects = cpl_image_get_size_y(reduceds[0]) / 2;
1848 nx = cpl_image_get_size_x(reduceds[0]);
1850 header = cpl_propertylist_new();
1851 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
1852 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
1853 cpl_propertylist_update_double(header,
"CRVAL1",
1854 startwavelength + dispersion/2);
1855 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
1858 cpl_propertylist_update_double(header,
"CD1_1", dispersion);
1859 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
1860 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
1861 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
1862 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
1863 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
1867 cpl_image *pv_im = NULL;
1868 cpl_image *pvnull_im = NULL;
1869 cpl_image *perr_im = NULL;
1872 double *p_vnull = NULL;
1873 double *perr = NULL;
1880 pv_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
1881 perr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
1883 p_v = cpl_image_get_data_double(pv_im);
1884 perr = cpl_image_get_data_double(perr_im);
1886 if (nscience / 2 > 1) {
1887 pvnull_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
1888 p_vnull = cpl_image_get_data_double(pvnull_im);
1891 for (j = 0; j < nobjects; j++) {
1895 * ip_vnull, * iperr;
1898 float * iff, * ierr;
1900 ip_v = p_v + (nobjects - 1 - j) * nx;
1902 if (nscience / 2 > 1)
1903 ip_vnull = p_vnull + (nobjects - 1 - j) * nx;
1905 iperr = perr + (nobjects - 1 - j) * nx;
1907 while (total < j + 1) {
1909 total += nobjs_per_slit[p];
1912 for (k = 0; k < nscience / 2; k++) {
1913 float * if_o, * if_e, * ifdelta_o, * ifdelta_e;
1915 int pos = fors_find_angle_pos(angles, nscience, 180 * k - 45);
1916 int pos_d = fors_find_angle_pos(angles, nscience, 180 * k + 45);
1918 data = cpl_image_get_data_float(reduceds[pos]);
1920 if_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
1921 + (total - j - 1)) * nx;
1923 if_e = data + (2 * (nobjects - total)
1924 + (total - j - 1)) * nx;
1929 data = cpl_image_get_data_float(reduceds[pos_d]);
1931 ifdelta_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
1932 + (total - j - 1)) * nx;
1934 ifdelta_e = data + (2 * (nobjects - total)
1935 + (total - j - 1)) * nx;
1940 for (m = 0; m < nx; m++) {
1942 double quantity = if_o[m] + if_e[m] == 0.0 ? 0.0 :
1943 (if_o[m] - if_e[m] ) /
1944 (if_o[m] + if_e[m] ) -
1945 (ifdelta_o[m] - ifdelta_e[m]) /
1946 (ifdelta_o[m] + ifdelta_e[m]);
1948 quantity = isfinite(quantity) ? quantity : 0.0;
1951 ip_v[m] += quantity * 0.5 / (nscience / 2);
1954 if (nscience / 2 > 1) {
1956 ip_vnull[m] += quantity * 0.5 / (nscience / 2);
1958 ip_vnull[m] -= quantity * 0.5 / (nscience / 2);
1964 data = cpl_image_get_data_float(reduceds[0]);
1965 iff = data + 2 * (nobjects - 1 - j) * nx;
1967 data = cpl_image_get_data_float(rerrors[0]);
1968 ierr = data + 2 * (nobjects - 1 - j) * nx;
1970 for (m = 0; m < nx; m++)
1971 iperr[m] = iff[m] <= 0.0 ?
1972 0.0 : ierr[m] / iff[m] * 0.5 / sqrt (nscience / 2);
1974 if (nscience / 2 > 1) {
1976 float max, sum, sum2, imean;
1981 weights = cpl_malloc(
sizeof(
float) * nx);
1984 for (k = 0; k < nx; k++) {
1985 if (max < iff[k]) max = iff[k];
1988 for (k = 0; k < nx; k++) {
1989 weights[k] = iff[k] < 0.0 ?
1990 0.0 : iff[k] * iff[k] / (max * max);
1995 for (k = 0; k < nx; k++) {
1996 sum += weights[k] * ip_vnull[k];
2004 mean_vnull += (imean - mean_vnull) / (j + 1.0);
2009 parlist, recipe, version))
2010 fors_pmos_extract_exit(NULL);
2012 if (nscience / 2 > 1) {
2013 char * pipefile, * keyname;
2014 cpl_propertylist * qheader =
dfs_load_header(frameset, science_tag, 0);
2016 cpl_propertylist_update_double(qheader,
"CRPIX1", 1.0);
2017 cpl_propertylist_update_double(qheader,
"CRPIX2", 1.0);
2018 cpl_propertylist_update_double(qheader,
"CRVAL1",
2019 startwavelength + dispersion/2);
2020 cpl_propertylist_update_double(qheader,
"CRVAL2", 1.0);
2023 cpl_propertylist_update_double(qheader,
"CD1_1", dispersion);
2024 cpl_propertylist_update_double(qheader,
"CD1_2", 0.0);
2025 cpl_propertylist_update_double(qheader,
"CD2_1", 0.0);
2026 cpl_propertylist_update_double(qheader,
"CD2_2", 1.0);
2027 cpl_propertylist_update_string(qheader,
"CTYPE1",
"LINEAR");
2028 cpl_propertylist_update_string(qheader,
"CTYPE2",
"PIXEL");
2037 "Product category", instrume))
2038 fors_pmos_extract_exit(
"Cannot write product category to "
2042 "DPR type", instrume))
2043 fors_pmos_extract_exit(
"Missing keyword DPR TYPE in arc "
2047 "Template", instrume))
2048 fors_pmos_extract_exit(
"Missing keyword TPL ID in arc "
2052 "Grism name", instrume))
2053 fors_pmos_extract_exit(
"Missing keyword INS GRIS1 NAME in arc "
2057 "Grism identifier", instrume))
2058 fors_pmos_extract_exit(
"Missing keyword INS GRIS1 ID in arc "
2061 if (cpl_propertylist_has(qheader,
"ESO INS FILT1 NAME"))
2063 "Filter name", instrume);
2066 "Collimator name", instrume))
2067 fors_pmos_extract_exit(
"Missing keyword INS COLL NAME in arc "
2071 "Chip identifier", instrume))
2072 fors_pmos_extract_exit(
"Missing keyword DET CHIP1 ID in arc "
2076 "Archive name of input data",
2078 fors_pmos_extract_exit(
"Missing keyword ARCFILE in arc "
2081 pipefile = dfs_generate_filename(reduced_nul_v_tag);
2083 "Pipeline product name", instrume))
2084 fors_pmos_extract_exit(
"Cannot write PIPEFILE to QC log file");
2085 cpl_free(pipefile); pipefile = NULL;
2092 keyname =
"QC.NULL.V.MEAN";
2096 "Mean V null parameter",
2098 fors_pmos_extract_exit(
"Cannot write mean Q null parameter "
2104 if (
dfs_save_image(frameset, pvnull_im, reduced_nul_v_tag, qheader,
2105 parlist, recipe, version))
2106 fors_pmos_extract_exit(NULL);
2108 cpl_propertylist_delete(qheader);
2111 if (
dfs_save_image(frameset, perr_im, reduced_error_v_tag, header,
2112 parlist, recipe, version))
2113 fors_pmos_extract_exit(NULL);
2115 cpl_image_delete(pv_im);
2116 cpl_image_delete(pvnull_im);
2117 cpl_image_delete(perr_im);
2119 cpl_image *pq_im = NULL;
2120 cpl_image *pu_im = NULL;
2121 cpl_image *pl_im = NULL;
2123 cpl_image *pqnull_im = NULL;
2124 cpl_image *punull_im = NULL;
2126 cpl_image *pqerr_im = NULL;
2127 cpl_image *puerr_im = NULL;
2128 cpl_image *plerr_im = NULL;
2130 cpl_image *pang_im = NULL;
2131 cpl_image *pangerr_im = NULL;
2137 double *p_qnull = NULL;
2138 double *p_unull = NULL;
2140 double *pqerr = NULL;
2141 double *puerr = NULL;
2142 double *plerr = NULL;
2144 double *pang = NULL;
2145 double *pangerr = NULL;
2149 cpl_image * correct_im = cpl_image_new(nx, 1, CPL_TYPE_DOUBLE);
2150 double * correct = cpl_image_get_data_double(correct_im);
2152 double mean_unull, mean_qnull;
2157 pq_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2158 pu_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2159 pl_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2161 pqerr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2162 puerr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2163 plerr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2165 pang_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2166 pangerr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2168 p_q = cpl_image_get_data_double(pq_im);
2169 p_u = cpl_image_get_data_double(pu_im);
2170 p_l = cpl_image_get_data_double(pl_im);
2172 if (nscience / 4 > 1) {
2173 pqnull_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2174 punull_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2176 p_qnull = cpl_image_get_data_double(pqnull_im);
2177 p_unull = cpl_image_get_data_double(punull_im);
2179 cpl_msg_warning(cpl_func,
2180 "Not enough pairs to compute null parameters");
2183 pqerr = cpl_image_get_data_double(pqerr_im);
2184 puerr = cpl_image_get_data_double(puerr_im);
2185 plerr = cpl_image_get_data_double(plerr_im);
2187 pang = cpl_image_get_data_double(pang_im);
2188 pangerr = cpl_image_get_data_double(pangerr_im);
2191 cpl_table * chrotbl =
2194 int nrow = cpl_table_get_nrow(chrotbl);
2195 float * lambda = cpl_table_get_data_float(chrotbl,
"lambda");
2196 float * theta = cpl_table_get_data_float(chrotbl,
"eps_theta");
2198 for (j = 0; j < nx; j++) {
2200 startwavelength + dispersion / 2 + j * dispersion;
2204 for (k = 0; k < nrow - 1; k++) {
2205 if (lambda[k] <= c_wave && c_wave < lambda[k + 1]) {
2212 correct[j] = (theta [k + 1] - theta [k]) /
2213 (lambda[k + 1] - lambda[k]) *
2214 (c_wave - lambda[k]) + theta[k];
2215 correct[j] *= M_PI / 180;
2218 correct[j] = correct[j-1];
2224 cpl_table_delete(chrotbl);
2227 for (j = 0; j < nobjects; j++) {
2228 double * ip_q, * ip_u, * ip_l,
2229 * ip_qnull, * ip_unull, * ipqerr, * ipuerr, * iplerr,
2230 * ipang, * ipangerr;
2233 float * iffq, * ierrq, * iffu, * ierru;
2237 ip_q = p_q + (nobjects - 1 - j) * nx;
2238 ip_u = p_u + (nobjects - 1 - j) * nx;
2239 ip_l = p_l + (nobjects - 1 - j) * nx;
2241 if (nscience / 4 > 1) {
2242 ip_qnull = p_qnull + (nobjects - 1 - j) * nx;
2243 ip_unull = p_unull + (nobjects - 1 - j) * nx;
2246 ipqerr = pqerr + (nobjects - 1 - j) * nx;
2247 ipuerr = puerr + (nobjects - 1 - j) * nx;
2248 iplerr = plerr + (nobjects - 1 - j) * nx;
2250 ipang = pang + (nobjects - 1 - j) * nx;
2251 ipangerr = pangerr + (nobjects - 1 - j) * nx;
2253 while (total < j + 1) {
2255 total += nobjs_per_slit[p];
2258 for (k = 0; k < nscience / 4; k++) {
2259 float * if_o, * if_e, * ifdelta_o, * ifdelta_e;
2263 pos = fors_find_angle_pos(angles, nscience, 90 * k);
2264 pos_d = fors_find_angle_pos(angles, nscience, 90 * k + 45);
2266 data = cpl_image_get_data_float(reduceds[pos]);
2268 if_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2269 + (total - j - 1)) * nx;
2271 if_e = data + (2 * (nobjects - total)
2272 + (total - j - 1)) * nx;
2277 data = cpl_image_get_data_float(reduceds[pos_d]);
2279 ifdelta_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2280 + (total - j - 1)) * nx;
2282 ifdelta_e = data + (2 * (nobjects - total)
2283 + (total - j - 1)) * nx;
2288 for (m = 0; m < nx; m++) {
2290 double quantity = fabs(if_o[m] + if_e[m]) < FLT_MIN ? 0.0 :
2291 (if_o[m] - if_e[m] ) /
2292 (if_o[m] + if_e[m] ) -
2293 (ifdelta_o[m] - ifdelta_e[m]) /
2294 (ifdelta_o[m] + ifdelta_e[m]);
2296 quantity = isfinite(quantity) ? quantity : 0.0;
2299 ip_q[m] += quantity * 0.5 / (nscience / 4);
2302 if (nscience / 4 > 1) {
2304 ip_qnull[m] += quantity * 0.5 / (nscience / 4);
2306 ip_qnull[m] -= quantity * 0.5 / (nscience / 4);
2312 pos = fors_find_angle_pos(angles, nscience, 90 * k + 22.5);
2313 pos_d = fors_find_angle_pos(angles, nscience, 90 * k + 67.5);
2315 data = cpl_image_get_data_float(reduceds[pos]);
2317 if_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2318 + (total - j - 1)) * nx;
2320 if_e = data + (2 * (nobjects - total)
2321 + (total - j - 1)) * nx;
2326 data = cpl_image_get_data_float(reduceds[pos_d]);
2328 ifdelta_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2329 + (total - j - 1)) * nx;
2331 ifdelta_e = data + (2 * (nobjects - total)
2332 + (total - j - 1)) * nx;
2337 for (m = 0; m < nx; m++) {
2339 double quantity = fabs(if_o[m] + if_e[m]) < FLT_MIN ? 0.0 :
2340 (if_o[m] - if_e[m] ) /
2341 (if_o[m] + if_e[m] ) -
2342 (ifdelta_o[m] - ifdelta_e[m]) /
2343 (ifdelta_o[m] + ifdelta_e[m]);
2345 quantity = isfinite(quantity) ? quantity : 0.0;
2348 ip_u[m] += quantity * 0.5 / (nscience / 4);
2351 if (nscience / 4 > 1) {
2353 ip_unull[m] += quantity * 0.5 / (nscience / 4);
2355 ip_unull[m] -= quantity * 0.5 / (nscience / 4);
2362 pos = fors_find_angle_pos(angles, nscience, 0.0);
2364 data = cpl_image_get_data_float(reduceds[pos]);
2365 iffq = data + 2 * (nobjects - 1 - j) * nx;
2367 data = cpl_image_get_data_float(rerrors[pos]);
2368 ierrq = data + 2 * (nobjects - 1 - j) * nx;
2370 pos = fors_find_angle_pos(angles, nscience, 22.5);
2372 data = cpl_image_get_data_float(reduceds[pos]);
2373 iffu = data + 2 * (nobjects - 1 - j) * nx;
2375 data = cpl_image_get_data_float(rerrors[pos]);
2376 ierru = data + 2 * (nobjects - 1 - j) * nx;
2378 for (m = 0; m < nx; m++) {
2382 ipqerr[m] = iffq[m] <= 0.0 ?
2383 0.0 : ierrq[m] / iffq[m] * 0.5 / sqrt (nscience / 4);
2385 ipuerr[m] = iffu[m] <= 0.0 ?
2386 0.0 : ierru[m] / iffu[m] * 0.5 / sqrt (nscience / 4);
2388 iplerr[m] = CPL_MATH_SQRT1_2 * 0.5 * (ipqerr[m] + ipuerr[m]);
2392 ip_q[m] = ip_q[m] * cos(2 * correct[m]) -
2393 ip_u[m] * sin(2 * correct[m]);
2395 ip_u[m] = ip_q[m] * sin(2 * correct[m]) +
2396 ip_u[m] * cos(2 * correct[m]);
2401 ip_l[m] = sqrt(ip_u[m] * ip_u[m] + ip_q[m] * ip_q[m]);
2404 ipang[m] = (ip_q[m] == 0.0 ?
2405 (ip_u[m] > 0.0 ? 45.0 : 135.0)
2406 : 0.5 * (atan2(ip_u[m], ip_q[m]) * 180 / M_PI +
2407 ((atan2(ip_u[m], ip_q[m]) > 0.0 ? 0.0 : 360.0))));
2410 radicand = ip_q[m] * ip_q[m] * ipuerr[m] * ipuerr[m] +
2411 ip_u[m] * ip_u[m] * ipqerr[m] * ipqerr[m];
2413 ipangerr[m] = ip_l[m] == 0.0 ? 0.0 :
2414 sqrt(radicand) * 0.5 / (ip_l[m] * ip_l[m]) * 180 / M_PI;
2435 if (nscience / 4 > 1) {
2437 float max, sum, sum2, imean;
2442 weights = cpl_malloc(
sizeof(
float) * nx);
2445 for (k = 0; k < nx; k++) {
2446 if (max < iffq[k]) max = iffq[k];
2449 for (k = 0; k < nx; k++) {
2450 weights[k] = iffq[k] < 0.0 ?
2451 0.0 : iffq[k] * iffq[k] / (max * max);
2456 for (k = 0; k < nx; k++) {
2457 sum += weights[k] * ip_qnull[k];
2465 mean_qnull += (imean - mean_qnull) / (j + 1.0);
2468 weights = cpl_malloc(
sizeof(
float) * nx);
2471 for (k = 0; k < nx; k++) {
2472 if (max < iffu[k]) max = iffu[k];
2475 for (k = 0; k < nx; k++) {
2476 weights[k] = iffu[k] < 0.0 ?
2477 0.0 : iffu[k] * iffu[k] / (max * max);
2482 for (k = 0; k < nx; k++) {
2483 sum += weights[k] * ip_unull[k];
2491 mean_unull += (imean - mean_unull) / (j + 1.0);
2495 cpl_image_delete(correct_im);
2498 parlist, recipe, version))
2499 fors_pmos_extract_exit(NULL);
2502 parlist, recipe, version))
2503 fors_pmos_extract_exit(NULL);
2506 parlist, recipe, version))
2507 fors_pmos_extract_exit(NULL);
2509 if (nscience / 4 > 1) {
2515 cpl_propertylist_update_double(qheader,
"CRPIX1", 1.0);
2516 cpl_propertylist_update_double(qheader,
"CRPIX2", 1.0);
2517 cpl_propertylist_update_double(qheader,
"CRVAL1",
2518 startwavelength + dispersion/2);
2519 cpl_propertylist_update_double(qheader,
"CRVAL2", 1.0);
2522 cpl_propertylist_update_double(qheader,
"CD1_1", dispersion);
2523 cpl_propertylist_update_double(qheader,
"CD1_2", 0.0);
2524 cpl_propertylist_update_double(qheader,
"CD2_1", 0.0);
2525 cpl_propertylist_update_double(qheader,
"CD2_2", 1.0);
2526 cpl_propertylist_update_string(qheader,
"CTYPE1",
"LINEAR");
2527 cpl_propertylist_update_string(qheader,
"CTYPE2",
"PIXEL");
2536 "Product category", instrume))
2537 fors_pmos_extract_exit(
"Cannot write product category to "
2541 "DPR type", instrume))
2542 fors_pmos_extract_exit(
"Missing keyword DPR TYPE in arc "
2546 "Template", instrume))
2547 fors_pmos_extract_exit(
"Missing keyword TPL ID in arc "
2551 "Grism name", instrume))
2552 fors_pmos_extract_exit(
"Missing keyword INS GRIS1 NAME in arc "
2556 "Grism identifier", instrume))
2557 fors_pmos_extract_exit(
"Missing keyword INS GRIS1 ID in arc "
2560 if (cpl_propertylist_has(qheader,
"ESO INS FILT1 NAME"))
2562 "Filter name", instrume);
2565 "Collimator name", instrume))
2566 fors_pmos_extract_exit(
"Missing keyword INS COLL NAME in arc "
2570 "Chip identifier", instrume))
2571 fors_pmos_extract_exit(
"Missing keyword DET CHIP1 ID in arc "
2575 "Archive name of input data",
2577 fors_pmos_extract_exit(
"Missing keyword ARCFILE in arc "
2580 pipefile = dfs_generate_filename(reduced_nul_q_tag);
2582 "Pipeline product name", instrume))
2583 fors_pmos_extract_exit(
"Cannot write PIPEFILE to QC log file");
2584 cpl_free(pipefile); pipefile = NULL;
2591 keyname =
"QC.NULL.Q.MEAN";
2595 "Mean Q null parameter",
2597 fors_pmos_extract_exit(
"Cannot write mean Q null parameter "
2603 if (
dfs_save_image(frameset, pqnull_im, reduced_nul_q_tag, qheader,
2604 parlist, recipe, version))
2605 fors_pmos_extract_exit(NULL);
2607 cpl_propertylist_delete(qheader);
2611 cpl_propertylist_update_double(qheader,
"CRPIX1", 1.0);
2612 cpl_propertylist_update_double(qheader,
"CRPIX2", 1.0);
2613 cpl_propertylist_update_double(qheader,
"CRVAL1",
2614 startwavelength + dispersion/2);
2615 cpl_propertylist_update_double(qheader,
"CRVAL2", 1.0);
2618 cpl_propertylist_update_double(qheader,
"CD1_1", dispersion);
2619 cpl_propertylist_update_double(qheader,
"CD1_2", 0.0);
2620 cpl_propertylist_update_double(qheader,
"CD2_1", 0.0);
2621 cpl_propertylist_update_double(qheader,
"CD2_2", 1.0);
2622 cpl_propertylist_update_string(qheader,
"CTYPE1",
"LINEAR");
2623 cpl_propertylist_update_string(qheader,
"CTYPE2",
"PIXEL");
2632 "Product category", instrume))
2633 fors_pmos_extract_exit(
"Cannot write product category to "
2637 "DPR type", instrume))
2638 fors_pmos_extract_exit(
"Missing keyword DPR TYPE in arc "
2642 "Template", instrume))
2643 fors_pmos_extract_exit(
"Missing keyword TPL ID in arc "
2647 "Grism name", instrume))
2648 fors_pmos_extract_exit(
"Missing keyword INS GRIS1 NAME in arc "
2652 "Grism identifier", instrume))
2653 fors_pmos_extract_exit(
"Missing keyword INS GRIS1 ID in arc "
2656 if (cpl_propertylist_has(qheader,
"ESO INS FILT1 NAME"))
2658 "Filter name", instrume);
2661 "Collimator name", instrume))
2662 fors_pmos_extract_exit(
"Missing keyword INS COLL NAME in arc "
2666 "Chip identifier", instrume))
2667 fors_pmos_extract_exit(
"Missing keyword DET CHIP1 ID in arc "
2671 "Archive name of input data",
2673 fors_pmos_extract_exit(
"Missing keyword ARCFILE in arc "
2676 pipefile = dfs_generate_filename(reduced_nul_u_tag);
2678 "Pipeline product name", instrume))
2679 fors_pmos_extract_exit(
"Cannot write PIPEFILE to QC log file");
2680 cpl_free(pipefile); pipefile = NULL;
2687 keyname =
"QC.NULL.U.MEAN";
2691 "Mean U null parameter",
2693 fors_pmos_extract_exit(
"Cannot write mean U null parameter "
2699 if (
dfs_save_image(frameset, punull_im, reduced_nul_u_tag, qheader,
2700 parlist, recipe, version))
2701 fors_pmos_extract_exit(NULL);
2703 cpl_propertylist_delete(qheader);
2706 if (
dfs_save_image(frameset, pqerr_im, reduced_error_q_tag, header,
2707 parlist, recipe, version))
2708 fors_pmos_extract_exit(NULL);
2710 if (
dfs_save_image(frameset, puerr_im, reduced_error_u_tag, header,
2711 parlist, recipe, version))
2712 fors_pmos_extract_exit(NULL);
2714 if (
dfs_save_image(frameset, plerr_im, reduced_error_l_tag, header,
2715 parlist, recipe, version))
2716 fors_pmos_extract_exit(NULL);
2719 parlist, recipe, version))
2720 fors_pmos_extract_exit(NULL);
2722 if (
dfs_save_image(frameset, pangerr_im, reduced_error_angle_tag,
2723 header, parlist, recipe, version))
2724 fors_pmos_extract_exit(NULL);
2726 cpl_image_delete(pq_im);
2727 cpl_image_delete(pu_im);
2728 cpl_image_delete(pl_im);
2730 cpl_image_delete(pqnull_im);
2731 cpl_image_delete(punull_im);
2733 cpl_image_delete(pqerr_im);
2734 cpl_image_delete(puerr_im);
2735 cpl_image_delete(plerr_im);
2736 cpl_image_delete(pang_im);
2737 cpl_image_delete(pangerr_im);
2740 cpl_propertylist_delete(header);
2744 for (j = 0; j < nscience; j++) {
2745 cpl_image_delete(reduceds[j]);
2746 cpl_image_delete(rerrors[j]);
2747 cpl_table_delete(slitss[j]);
2748 cpl_image_delete(mappeds[j]);
2756 cpl_free(instrume); instrume = NULL;
2758 cpl_free(skylocalmaps);
2759 cpl_free(nobjs_per_slit);
2761 if (cpl_error_get_code()) {
2762 cpl_msg_error(cpl_error_get_where(),
"%s", cpl_error_get_message());
2763 fors_pmos_extract_exit(NULL);
2781 static float * fors_check_angles(cpl_frameset * frameset,
2782 int pmos,
const char *tag,
int * circ)
2784 float *angles = NULL;
2785 cpl_frame *c_frame = NULL;
2786 char *ret_id = NULL;
2790 angles = cpl_malloc(
sizeof(
float) * pmos);
2792 for (c_frame = cpl_frameset_find(frameset, tag);
2793 c_frame != NULL; c_frame = cpl_frameset_find(frameset, NULL)) {
2795 cpl_propertylist * header =
2796 cpl_propertylist_load(cpl_frame_get_filename(c_frame), 0);
2799 ret_id = cpl_strdup(cpl_propertylist_get_string(header,
2800 "ESO INS OPTI4 ID"));
2802 if (ret_id[1] !=
'5' && ret_id[1] !=
'4') {
2803 cpl_msg_error(cpl_func,
2804 "Unknown retarder plate id: %s", ret_id);
2808 char * c_ret_id = (
char *)
2809 cpl_propertylist_get_string(header,
"ESO INS OPTI4 ID");
2810 if (ret_id[1] != c_ret_id[1]) {
2811 cpl_msg_error(cpl_func,
"Input frames are not from the same "
2817 if (ret_id[1] ==
'5') {
2819 cpl_propertylist_get_double(header,
"ESO INS RETA2 ROT");
2823 cpl_propertylist_get_double(header,
"ESO INS RETA4 ROT");
2827 cpl_propertylist_delete(header);
2834 if (pmos != 2 && pmos != 4) {
2835 cpl_msg_error(cpl_func,
"Wrong angle configuration: %d angles "
2836 "found, but either 2 or 4 are required for "
2837 "circular polarization measurements!", pmos);
2841 if (pmos != 4 && pmos != 8 && pmos != 16) {
2842 cpl_msg_error(cpl_func,
"Wrong angle configuration: %d angles "
2843 "found, but either 4, 8, or 16 are required for "
2844 "linear polarization measurements!", pmos);
2852 for (i = 0; i < pmos; i++) {
2853 if (fors_find_angle_pos(angles, pmos, 90.0 * i - 45.0) < 0) {
2854 const char *cangles;
2856 case 2: cangles =
"-45.0, 45.0";
break;
2857 case 4: cangles =
"-45.0, 45.0, 135.0, 225.0";
break;
2861 cpl_msg_error(cpl_func,
"Wrong angle configuration: missing "
2862 "angle %.2f. All angles %s must be provided.",
2863 angles[i], cangles);
2869 for (i = 0; i < pmos; i++) {
2870 if (fors_find_angle_pos(angles, pmos, 22.5 * i) < 0) {
2871 const char *cangles;
2873 case 4: cangles =
"0.0, 22.5, 45.0, 67.5";
break;
2874 case 8: cangles =
"0.0, 22.5, 45.0, 67.5, "
2875 "90.0, 112.5, 135.0, 157.5";
break;
2876 case 16: cangles =
"0.0, 22.5, 45.0, 67.5, "
2877 "90.0, 112.5, 135.0, 157.5, "
2878 "180.0, 202.5, 225.0, 247.5, "
2879 "270.0, 292.5, 315.0, 337.5";
break;
2883 cpl_msg_error(cpl_func,
"Wrong angle configuration: missing "
2884 "angle %.2f. All angles %s must be provided.",
2885 angles[i], cangles);
2904 fors_find_angle_pos(
float * angles,
int nangles,
float angle)
2908 for (i = 0; i < nangles; i++) {
2909 if (fabs(angles[i] - angle) < 1.0 ||
2910 fabs(angles[i] - 360.0 - angle) < 1.0) {
2916 return match ? i : -1;
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_build_disp_coeff(cpl_table *global, cpl_table *slits)
Build the IDS coefficients table from a global distortions table.
int cpl_plugin_get_info(cpl_pluginlist *list)
Build the list of available plugins, for this module.
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_error_code dfs_save_image_null(cpl_frameset *frameset, cpl_parameterlist *parlist, const char *tag, const char *recipename, const char *version)
Save a product with an empty primary extension.
cpl_error_code dfs_save_image_ext(cpl_image *image, const char *tag, cpl_propertylist *extheader)
Save an image in a extension.
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_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_error_code dfs_save_table_ext(cpl_table *table, const char *tag, cpl_propertylist *extheader)
Save a table in a extension (different from the first one)
cpl_error_code mos_object_intersect(cpl_table **slitss, cpl_table *origslits, int nscience, float tolerance)
Intersect a number of slit tables.
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_image ** mos_extract_objects(cpl_image *science, cpl_image *science_var, cpl_image *sky, cpl_table *objects, int extraction, double ron, double gain, int ncombined)
Extract detected objects from rectified scientific frame.
cpl_error_code mos_clean_cosmics(cpl_image *image, float gain, float threshold, float ratio)
Remove cosmic rays from sky-subtracted CCD spectral exposure.
cpl_table * mos_load_slits_fors_pmos(cpl_propertylist *header, int *nslits_out_det)
Create PMOS slit location table from FITS header of FORS1/2 MOS data.
cpl_table * mos_build_curv_coeff(cpl_table *global, cpl_table *maskslits, cpl_table *slits)
Build the curvature coefficients table from a global distortions table.
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.
cpl_table * mos_build_slit_location(cpl_table *global, cpl_table *maskslits, int ysize)
Build the slit location table from a global distortions table.