40 #include <fors_utils.h>
43 static int fors_pmos_science_create(cpl_plugin *);
44 static int fors_pmos_science_exec(cpl_plugin *);
45 static int fors_pmos_science_destroy(cpl_plugin *);
46 static int fors_pmos_science(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_science_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"
83 " MASTER_NORM_FLAT_PMOS Calib Normalised flat field .\n"
84 " DISP_COEFF_PMOS Calib Inverse dispersion Y\n"
85 " CURV_COEFF_PMOS Calib Spectral curvature Y\n"
86 " SLIT_LOCATION_PMOS Calib Slits positions table Y\n"
87 " RETARDER_WAVEPLATE_CHROMATISM Calib Chromatism correction .\n"
88 " STD_PMOS_TABLE Calib Linear pol. of std stars .\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_X_SCI_PMOS FITS image X Stokes parameter (and L)\n"
96 " REDUCED_ERROR_X_SCI_PMOS FITS image Error on X Stokes parameter\n"
97 " REDUCED_NUL_X_SCI_PMOS FITS image Null parameter for X\n"
98 " REDUCED_ANGLE_SCI_PMOS FITS image Direction of linear polarization\n"
99 " REDUCED_ERROR_ANGLE_SCI_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 " OBJECT_TABLE_SCI_PMOS FITS table Positions of detected objects\n"
106 " OBJECT_TABLE_POL_SCI_PMOS FITS table Positions of real objects\n"
108 " Only if the sky-alignment of the wavelength solution is requested:\n"
109 " DISP_COEFF_SCI_PMOS FITS table Upgraded dispersion coefficients\n"
110 " WAVELENGTH_MAP_SCI_PMOS FITS image Upgraded wavelength map\n\n";
112 #define fors_pmos_science_exit(message) \
114 if (message) cpl_msg_error(recipe, message); \
115 cpl_free(instrume); \
116 cpl_image_delete(dummy); \
117 cpl_image_delete(mapped_sky); \
118 cpl_image_delete(mapped_cleaned); \
119 cpl_image_delete(skymap); \
120 cpl_image_delete(smapped); \
121 cpl_table_delete(offsets); \
122 cpl_table_delete(sky); \
123 cpl_image_delete(bias); \
124 cpl_image_delete(spectra); \
125 cpl_image_delete(coordinate); \
126 cpl_image_delete(norm_flat); \
127 cpl_image_delete(rainbow); \
128 cpl_image_delete(rectified); \
129 cpl_image_delete(wavemap); \
130 cpl_propertylist_delete(header); \
131 cpl_propertylist_delete(save_header); \
132 cpl_table_delete(grism_table); \
133 cpl_table_delete(idscoeff); \
134 cpl_table_delete(maskslits); \
135 cpl_table_delete(overscans); \
136 cpl_table_delete(polytraces); \
137 cpl_table_delete(wavelengths); \
138 cpl_table_delete(mask_science); \
139 cpl_table_delete(mask_arc); \
140 cpl_table_delete(mask_flat); \
141 cpl_vector_delete(lines); \
142 cpl_msg_indent_less(); \
147 #define fors_pmos_science_exit_memcheck(message) \
149 if (message) cpl_msg_info(recipe, message); \
150 cpl_free(instrume); \
151 cpl_image_delete(dummy); \
152 cpl_image_delete(mapped_cleaned); \
153 cpl_image_delete(mapped_sky); \
154 cpl_image_delete(skymap); \
155 cpl_image_delete(smapped); \
156 cpl_table_delete(offsets); \
157 cpl_table_delete(sky); \
158 cpl_image_delete(bias); \
159 cpl_image_delete(spectra); \
160 cpl_image_delete(coordinate); \
161 cpl_image_delete(norm_flat); \
162 cpl_image_delete(rainbow); \
163 cpl_image_delete(rectified); \
164 cpl_image_delete(wavemap); \
165 cpl_propertylist_delete(header); \
166 cpl_propertylist_delete(save_header); \
167 cpl_table_delete(grism_table); \
168 cpl_table_delete(idscoeff); \
169 cpl_table_delete(maskslits); \
170 cpl_table_delete(overscans); \
171 cpl_table_delete(polytraces); \
172 cpl_table_delete(wavelengths); \
173 cpl_table_delete(mask_science); \
174 cpl_table_delete(mask_arc); \
175 cpl_table_delete(mask_flat); \
176 cpl_vector_delete(lines); \
177 cpl_msg_indent_less(); \
195 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe );
196 cpl_plugin *plugin = &recipe->interface;
198 cpl_plugin_init(plugin,
201 CPL_PLUGIN_TYPE_RECIPE,
203 "Extraction of scientific spectra",
204 fors_pmos_science_description,
207 "This file is currently part of the FORS Instrument Pipeline\n"
208 "Copyright (C) 2002-2010 European Southern Observatory\n\n"
209 "This program is free software; you can redistribute it and/or modify\n"
210 "it under the terms of the GNU General Public License as published by\n"
211 "the Free Software Foundation; either version 2 of the License, or\n"
212 "(at your option) any later version.\n\n"
213 "This program is distributed in the hope that it will be useful,\n"
214 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
215 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
216 "GNU General Public License for more details.\n\n"
217 "You should have received a copy of the GNU General Public License\n"
218 "along with this program; if not, write to the Free Software Foundation,\n"
219 "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n",
220 fors_pmos_science_create,
221 fors_pmos_science_exec,
222 fors_pmos_science_destroy);
224 cpl_pluginlist_append(list, plugin);
240 static int fors_pmos_science_create(cpl_plugin *plugin)
250 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
251 recipe = (cpl_recipe *)plugin;
259 recipe->parameters = cpl_parameterlist_new();
266 p = cpl_parameter_new_value(
"fors.fors_pmos_science.dispersion",
268 "Expected spectral dispersion (Angstrom/pixel)",
269 "fors.fors_pmos_science",
271 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"dispersion");
272 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
273 cpl_parameterlist_append(recipe->parameters, p);
279 p = cpl_parameter_new_value(
"fors.fors_pmos_science.rebin",
282 "fors.fors_pmos_science",
284 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"rebin");
285 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
286 cpl_parameterlist_append(recipe->parameters, p);
292 p = cpl_parameter_new_value(
"fors.fors_pmos_science.skyalign",
294 "Polynomial order for sky lines alignment, "
295 "or -1 to avoid alignment",
296 "fors.fors_pmos_science",
298 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"skyalign");
299 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
300 cpl_parameterlist_append(recipe->parameters, p);
306 p = cpl_parameter_new_value(
"fors.fors_pmos_science.wcolumn",
308 "Name of sky line catalog table column "
310 "fors.fors_pmos_science",
312 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcolumn");
313 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
314 cpl_parameterlist_append(recipe->parameters, p);
320 p = cpl_parameter_new_value(
"fors.fors_pmos_science.startwavelength",
322 "Start wavelength in spectral extraction",
323 "fors.fors_pmos_science",
325 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"startwavelength");
326 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
327 cpl_parameterlist_append(recipe->parameters, p);
333 p = cpl_parameter_new_value(
"fors.fors_pmos_science.endwavelength",
335 "End wavelength in spectral extraction",
336 "fors.fors_pmos_science",
338 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"endwavelength");
339 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
340 cpl_parameterlist_append(recipe->parameters, p);
346 p = cpl_parameter_new_value(
"fors.fors_pmos_science.flux",
348 "Apply flux conservation",
349 "fors.fors_pmos_science",
351 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"flux");
352 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
353 cpl_parameterlist_append(recipe->parameters, p);
359 p = cpl_parameter_new_value(
"fors.fors_pmos_science.flatfield",
362 "fors.fors_pmos_science",
364 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"flatfield");
365 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
366 cpl_parameterlist_append(recipe->parameters, p);
372 p = cpl_parameter_new_value(
"fors.fors_pmos_science.skymedian",
374 "Sky subtraction from extracted slit spectra",
375 "fors.fors_pmos_science",
377 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"skymedian");
378 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
379 cpl_parameterlist_append(recipe->parameters, p);
385 p = cpl_parameter_new_value(
"fors.fors_pmos_science.skylocal",
387 "Sky subtraction from CCD slit spectra",
388 "fors.fors_pmos_science",
390 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"skylocal");
391 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
392 cpl_parameterlist_append(recipe->parameters, p);
398 p = cpl_parameter_new_value(
"fors.fors_pmos_science.cosmics",
400 "Eliminate cosmic rays hits (only if local "
401 "sky subtraction is also requested)",
402 "fors.fors_pmos_science",
404 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"cosmics");
405 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
406 cpl_parameterlist_append(recipe->parameters, p);
412 p = cpl_parameter_new_value(
"fors.fors_pmos_science.slit_margin",
414 "Number of pixels to exclude at each slit "
415 "in object detection and extraction",
416 "fors.fors_pmos_science",
418 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slit_margin");
419 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
420 cpl_parameterlist_append(recipe->parameters, p);
426 p = cpl_parameter_new_value(
"fors.fors_pmos_science.ext_radius",
428 "Maximum extraction radius for detected "
430 "fors.fors_pmos_science",
432 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ext_radius");
433 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
434 cpl_parameterlist_append(recipe->parameters, p);
440 p = cpl_parameter_new_value(
"fors.fors_pmos_science.cont_radius",
442 "Minimum distance at which two objects "
443 "of equal luminosity do not contaminate "
444 "each other (pixel)",
445 "fors.fors_pmos_science",
447 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"cont_radius");
448 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
449 cpl_parameterlist_append(recipe->parameters, p);
455 p = cpl_parameter_new_value(
"fors.fors_pmos_science.ext_mode",
457 "Object extraction method: 0 = aperture, "
458 "1 = Horne optimal extraction",
459 "fors.fors_pmos_science",
461 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ext_mode");
462 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
463 cpl_parameterlist_append(recipe->parameters, p);
469 p = cpl_parameter_new_value(
"fors.fors_pmos_science.match_tolerance",
471 "Tolerance for matching spectra from the "
472 "same object at different angles and beams "
474 "fors.fors_pmos_science",
476 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"match_tolerance");
477 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
478 cpl_parameterlist_append(recipe->parameters, p);
484 p = cpl_parameter_new_value(
"fors.fors_pmos_science.time_normalise",
486 "Normalise output spectra by the exposure time",
487 "fors.fors_pmos_science",
489 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"time_normalise");
490 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
491 cpl_parameterlist_append(recipe->parameters, p);
497 p = cpl_parameter_new_value(
"fors.fors_pmos_science.chromatism",
499 "Chromatism correction to polarization angles",
500 "fors.fors_pmos_science",
502 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"chromatism");
503 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
504 cpl_parameterlist_append(recipe->parameters, p);
510 p = cpl_parameter_new_value(
"fors.fors_pmos_science.wollaston",
512 "Wollaston mounting (FORS2 only): true = 0 degrees "
513 "(ord. beam on top, extr. beam on bottom), "
514 "false = 180 degrees (beams are reversed), for FORS1 "
516 "fors.fors_pmos_science",
518 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wollaston");
519 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
520 cpl_parameterlist_append(recipe->parameters, p);
526 p = cpl_parameter_new_value(
"fors.fors_pmos_science.check",
528 "Create intermediate products",
529 "fors.fors_pmos_science",
531 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"check");
532 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
533 cpl_parameterlist_append(recipe->parameters, p);
539 p = cpl_parameter_new_value(
"fors.fors_pmos_science.qc",
541 "Compute QC1 parameters",
542 "fors.fors_pmos_science",
544 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"qc");
545 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
546 cpl_parameterlist_append(recipe->parameters, p);
560 static int fors_pmos_science_exec(cpl_plugin *plugin)
564 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
565 recipe = (cpl_recipe *)plugin;
569 return fors_pmos_science(recipe->parameters, recipe->frames);
581 static int fors_pmos_science_destroy(cpl_plugin *plugin)
585 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
586 recipe = (cpl_recipe *)plugin;
590 cpl_parameterlist_delete(recipe->parameters);
605 static int fors_pmos_science(cpl_parameterlist *parlist, cpl_frameset *frameset)
608 const char *recipe =
"fors_pmos_science";
619 double startwavelength;
620 double endwavelength;
643 cpl_image **reduceds = NULL;
644 cpl_image **rerrors = NULL;
645 cpl_table **slitss = NULL;
646 cpl_image **mappeds = NULL;
647 cpl_image **skylocalmaps = NULL;
651 cpl_image *bias = NULL;
652 cpl_image *norm_flat = NULL;
653 cpl_image *spectra = NULL;
654 cpl_image *rectified = NULL;
655 cpl_image *coordinate = NULL;
656 cpl_image *rainbow = NULL;
657 cpl_image *mapped = NULL;
658 cpl_image *mapped_sky = NULL;
659 cpl_image *mapped_cleaned = NULL;
660 cpl_image *smapped = NULL;
661 cpl_image *wavemap = NULL;
662 cpl_image *skymap = NULL;
663 cpl_image *skylocalmap = NULL;
664 cpl_image *dummy = NULL;
666 cpl_table *grism_table = NULL;
667 cpl_table *overscans = NULL;
668 cpl_table *wavelengths = NULL;
669 cpl_table *idscoeff = NULL;
670 cpl_table *slits = NULL;
671 cpl_table *origslits = NULL;
672 cpl_table *maskslits = NULL;
673 cpl_table *mask_science = NULL;
674 cpl_table *mask_arc = NULL;
675 cpl_table *mask_flat = NULL;
676 cpl_table *polytraces = NULL;
677 cpl_table *offsets = NULL;
678 cpl_table *sky = NULL;
680 cpl_vector *lines = NULL;
682 cpl_propertylist *header = NULL;
683 cpl_propertylist *save_header = NULL;
690 char *instrume = NULL;
691 const char *science_tag;
692 const char *master_norm_flat_tag;
693 const char *disp_coeff_tag;
694 const char *disp_coeff_sky_tag;
695 const char *wavelength_map_sky_tag;
696 const char *curv_coeff_tag;
697 const char *slit_location_tag;
698 const char *reduced_science_tag;
699 const char *reduced_sky_tag;
700 const char *reduced_error_tag;
701 const char *mapped_science_tag;
702 const char *unmapped_science_tag;
703 const char *mapped_science_sky_tag;
704 const char *mapped_sky_tag;
705 const char *unmapped_sky_tag;
706 const char *object_table_tag;
707 const char *object_table_pol_tag;
708 const char *skylines_offsets_tag;
709 const char *reduced_q_tag;
710 const char *reduced_u_tag;
711 const char *reduced_v_tag;
712 const char *reduced_l_tag;
713 const char *reduced_i_tag;
714 const char *reduced_error_q_tag;
715 const char *reduced_error_u_tag;
716 const char *reduced_error_v_tag;
717 const char *reduced_error_l_tag;
718 const char *reduced_error_i_tag;
719 const char *reduced_nul_q_tag;
720 const char *reduced_nul_u_tag;
721 const char *reduced_nul_v_tag;
722 const char *reduced_angle_tag;
723 const char *reduced_error_angle_tag;
724 const char *chrom_table_tag =
"RETARDER_WAVEPLATE_CHROMATISM";
725 const char *std_pmos_table_tag =
"STD_PMOS_TABLE";
726 float *angles = NULL;
735 int ccd_xsize, ccd_ysize;
758 int nslits_out_det = 0;
761 cpl_error_code error;
763 snprintf(version, 80,
"%s-%s", PACKAGE, PACKAGE_VERSION);
766 char *montecarlo = getenv(
"MONTECARLO");
769 doit = atoi(montecarlo);
773 cpl_msg_set_indentation(2);
782 cpl_msg_info(recipe,
"Recipe %s configuration parameters:", recipe);
783 cpl_msg_indent_more();
785 if (cpl_frameset_count_tags(frameset,
"GRISM_TABLE") > 1)
786 fors_pmos_science_exit(
"Too many in input: GRISM_TABLE");
791 "fors.fors_pmos_science.dispersion", grism_table);
793 if (dispersion <= 0.0)
794 fors_pmos_science_exit(
"Invalid spectral dispersion");
797 "fors.fors_pmos_science.rebin", NULL);
800 fors_pmos_science_exit(
"Invalid rebin factor");
803 "fors.fors_pmos_science.skyalign", NULL);
806 fors_pmos_science_exit(
"Max polynomial degree for sky alignment is 2");
809 "fors.fors_pmos_science.wcolumn", NULL);
812 "fors.fors_pmos_science.startwavelength", grism_table);
813 if (startwavelength < 3000.0 || startwavelength > 13000.0)
814 fors_pmos_science_exit(
"Invalid wavelength");
817 "fors.fors_pmos_science.endwavelength", grism_table);
818 if (endwavelength < 3000.0 || endwavelength > 13000.0)
819 fors_pmos_science_exit(
"Invalid wavelength");
821 if (endwavelength - startwavelength <= 0.0)
822 fors_pmos_science_exit(
"Invalid wavelength interval");
827 "fors.fors_pmos_science.flatfield",
831 "fors.fors_pmos_science.skylocal",
834 "fors.fors_pmos_science.skymedian",
838 "fors.fors_pmos_science.chromatism",
842 "fors.fors_pmos_science.wollaston",
845 wollaston = wollaston ? 0 : 1;
847 if (skylocal && skymedian)
848 fors_pmos_science_exit(
"Cannot apply sky subtraction both on "
849 "extracted and non-extracted spectra");
852 "fors.fors_pmos_science.cosmics", NULL);
856 fors_pmos_science_exit(
"Cosmic rays correction requires "
860 "fors.fors_pmos_science.slit_margin",
863 fors_pmos_science_exit(
"Value must be zero or positive");
866 "fors.fors_pmos_science.ext_radius",
869 fors_pmos_science_exit(
"Value must be zero or positive");
872 "fors.fors_pmos_science.cont_radius",
875 fors_pmos_science_exit(
"Value must be zero or positive");
879 if (ext_mode < 0 || ext_mode > 1)
880 fors_pmos_science_exit(
"Invalid object extraction mode");
883 "fors.fors_pmos_science.match_tolerance", NULL);
884 if (tolerance <= 0.0)
885 fors_pmos_science_exit(
"Invalid object match tolerance");
888 "fors.fors_pmos_science.time_normalise", NULL);
891 "fors.fors_pmos_science.check", NULL);
895 cpl_table_delete(grism_table); grism_table = NULL;
897 if (cpl_error_get_code())
898 fors_pmos_science_exit(
"Failure getting the configuration parameters");
905 cpl_msg_indent_less();
906 cpl_msg_info(recipe,
"Check input set-of-frames:");
907 cpl_msg_indent_more();
910 cpl_frameset *subframeset = cpl_frameset_duplicate(frameset);
911 cpl_frameset_erase(subframeset,
"MASTER_BIAS");
914 fors_pmos_science_exit(
"Input frames are not from the same grism");
917 fors_pmos_science_exit(
"Input frames are not from the same filter");
920 fors_pmos_science_exit(
"Input frames are not from the same chip");
922 cpl_frameset_delete(subframeset);
926 pmos = cpl_frameset_count_tags(frameset,
"SCIENCE_PMOS");
929 pmos = cpl_frameset_count_tags(frameset,
"STANDARD_PMOS");
934 fors_pmos_science_exit(
"Missing input scientific frame");
936 angles = fors_check_angles(frameset, pmos,
937 standard ?
"STANDARD_PMOS" :
"SCIENCE_PMOS",
940 fors_pmos_science_exit(
"Polarization angles could not be read");
949 reduceds = (cpl_image **)cpl_malloc(
sizeof(cpl_image *) * nscience);
950 rerrors = (cpl_image **)cpl_malloc(
sizeof(cpl_image *) * nscience);
951 slitss = (cpl_table **)cpl_malloc(
sizeof(cpl_table *) * nscience);
952 mappeds = (cpl_image **)cpl_malloc(
sizeof(cpl_image *) * nscience);
953 skylocalmaps = (cpl_image **)cpl_malloc(
sizeof(cpl_image *) * nscience);
956 cpl_msg_info(recipe,
"PMOS data found");
958 science_tag =
"STANDARD_PMOS";
959 reduced_science_tag =
"REDUCED_STD_PMOS";
960 unmapped_science_tag =
"UNMAPPED_STD_PMOS";
961 mapped_science_tag =
"MAPPED_STD_PMOS";
962 mapped_science_sky_tag =
"MAPPED_ALL_STD_PMOS";
963 skylines_offsets_tag =
"SKY_SHIFTS_SLIT_STD_PMOS";
964 wavelength_map_sky_tag =
"WAVELENGTH_MAP_STD_PMOS";
965 disp_coeff_sky_tag =
"DISP_COEFF_STD_PMOS";
966 mapped_sky_tag =
"MAPPED_SKY_STD_PMOS";
967 unmapped_sky_tag =
"UNMAPPED_SKY_STD_PMOS";
968 object_table_tag =
"OBJECT_TABLE_STD_PMOS";
969 object_table_pol_tag =
"OBJECT_TABLE_POL_STD_PMOS";
970 reduced_sky_tag =
"REDUCED_SKY_STD_PMOS";
971 reduced_error_tag =
"REDUCED_ERROR_STD_PMOS";
972 reduced_q_tag =
"REDUCED_Q_STD_PMOS";
973 reduced_u_tag =
"REDUCED_U_STD_PMOS";
974 reduced_v_tag =
"REDUCED_V_STD_PMOS";
975 reduced_l_tag =
"REDUCED_L_STD_PMOS";
976 reduced_i_tag =
"REDUCED_I_STD_PMOS";
977 reduced_error_q_tag =
"REDUCED_ERROR_Q_STD_PMOS";
978 reduced_error_u_tag =
"REDUCED_ERROR_U_STD_PMOS";
979 reduced_error_v_tag =
"REDUCED_ERROR_V_STD_PMOS";
980 reduced_error_l_tag =
"REDUCED_ERROR_L_STD_PMOS";
981 reduced_error_i_tag =
"REDUCED_ERROR_I_STD_PMOS";
982 reduced_nul_q_tag =
"REDUCED_NUL_Q_STD_PMOS";
983 reduced_nul_u_tag =
"REDUCED_NUL_U_STD_PMOS";
984 reduced_nul_v_tag =
"REDUCED_NUL_V_STD_PMOS";
985 reduced_angle_tag =
"REDUCED_ANGLE_STD_PMOS";
986 reduced_error_angle_tag =
"REDUCED_ERROR_ANGLE_STD_PMOS";
989 science_tag =
"SCIENCE_PMOS";
990 reduced_science_tag =
"REDUCED_SCI_PMOS";
991 unmapped_science_tag =
"UNMAPPED_SCI_PMOS";
992 mapped_science_tag =
"MAPPED_SCI_PMOS";
993 mapped_science_sky_tag =
"MAPPED_ALL_SCI_PMOS";
994 skylines_offsets_tag =
"SKY_SHIFTS_SLIT_SCI_PMOS";
995 wavelength_map_sky_tag =
"WAVELENGTH_MAP_SCI_PMOS";
996 disp_coeff_sky_tag =
"DISP_COEFF_SCI_PMOS";
997 mapped_sky_tag =
"MAPPED_SKY_SCI_PMOS";
998 unmapped_sky_tag =
"UNMAPPED_SKY_SCI_PMOS";
999 object_table_tag =
"OBJECT_TABLE_SCI_PMOS";
1000 object_table_pol_tag =
"OBJECT_TABLE_POL_SCI_PMOS";
1001 reduced_sky_tag =
"REDUCED_SKY_SCI_PMOS";
1002 reduced_error_tag =
"REDUCED_ERROR_SCI_PMOS";
1003 reduced_q_tag =
"REDUCED_Q_SCI_PMOS";
1004 reduced_u_tag =
"REDUCED_U_SCI_PMOS";
1005 reduced_v_tag =
"REDUCED_V_SCI_PMOS";
1006 reduced_l_tag =
"REDUCED_L_SCI_PMOS";
1007 reduced_i_tag =
"REDUCED_I_SCI_PMOS";
1008 reduced_error_q_tag =
"REDUCED_ERROR_Q_SCI_PMOS";
1009 reduced_error_u_tag =
"REDUCED_ERROR_U_SCI_PMOS";
1010 reduced_error_v_tag =
"REDUCED_ERROR_V_SCI_PMOS";
1011 reduced_error_l_tag =
"REDUCED_ERROR_L_SCI_PMOS";
1012 reduced_error_i_tag =
"REDUCED_ERROR_I_SCI_PMOS";
1013 reduced_nul_q_tag =
"REDUCED_NUL_Q_SCI_PMOS";
1014 reduced_nul_u_tag =
"REDUCED_NUL_U_SCI_PMOS";
1015 reduced_nul_v_tag =
"REDUCED_NUL_V_SCI_PMOS";
1016 reduced_angle_tag =
"REDUCED_ANGLE_SCI_PMOS";
1017 reduced_error_angle_tag =
"REDUCED_ERROR_ANGLE_SCI_PMOS";
1020 master_norm_flat_tag =
"MASTER_NORM_FLAT_PMOS";
1021 disp_coeff_tag =
"DISP_COEFF_PMOS";
1022 curv_coeff_tag =
"CURV_COEFF_PMOS";
1023 slit_location_tag =
"SLIT_LOCATION_PMOS";
1025 if (!cpl_frameset_count_tags(frameset, master_norm_flat_tag)) {
1026 master_norm_flat_tag =
"MASTER_NORM_FLAT_LONG_PMOS";
1027 disp_coeff_tag =
"DISP_COEFF_LONG_PMOS";
1028 slit_location_tag =
"SLIT_LOCATION_LONG_PMOS";
1032 if (cpl_frameset_count_tags(frameset,
"MASTER_BIAS") == 0)
1033 fors_pmos_science_exit(
"Missing required input: MASTER_BIAS");
1035 if (cpl_frameset_count_tags(frameset,
"MASTER_BIAS") > 1)
1036 fors_pmos_science_exit(
"Too many in input: MASTER_BIAS");
1039 if (cpl_frameset_count_tags(frameset,
"MASTER_SKYLINECAT") > 1)
1040 fors_pmos_science_exit(
"Too many in input: MASTER_SKYLINECAT");
1042 if (cpl_frameset_count_tags(frameset, disp_coeff_tag) == 0) {
1043 cpl_msg_error(recipe,
"Missing required input: %s", disp_coeff_tag);
1044 fors_pmos_science_exit(NULL);
1047 if (cpl_frameset_count_tags(frameset, disp_coeff_tag) > 1) {
1048 cpl_msg_error(recipe,
"Too many in input: %s", disp_coeff_tag);
1049 fors_pmos_science_exit(NULL);
1052 if (cpl_frameset_count_tags(frameset, slit_location_tag) == 0) {
1053 cpl_msg_error(recipe,
"Missing required input: %s",
1055 fors_pmos_science_exit(NULL);
1058 if (cpl_frameset_count_tags(frameset, slit_location_tag) > 1) {
1059 cpl_msg_error(recipe,
"Too many in input: %s", slit_location_tag);
1060 fors_pmos_science_exit(NULL);
1064 if (cpl_frameset_count_tags(frameset, chrom_table_tag) == 0) {
1065 cpl_msg_error(recipe,
"Missing required input: %s",
1067 fors_pmos_science_exit(NULL);
1070 if (cpl_frameset_count_tags(frameset, chrom_table_tag) > 1) {
1071 cpl_msg_error(recipe,
"Too many in input: %s", chrom_table_tag);
1072 fors_pmos_science_exit(NULL);
1076 if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) > 1) {
1078 cpl_msg_error(recipe,
"Too many in input: %s",
1079 master_norm_flat_tag);
1080 fors_pmos_science_exit(NULL);
1083 cpl_msg_warning(recipe,
"%s in input are ignored, "
1084 "since flat field correction was not requested",
1085 master_norm_flat_tag);
1089 if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) == 1) {
1091 cpl_msg_warning(recipe,
"%s in input is ignored, "
1092 "since flat field correction was not requested",
1093 master_norm_flat_tag);
1097 if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) == 0) {
1099 cpl_msg_error(recipe,
"Flat field correction was requested, "
1100 "but no %s are found in input",
1101 master_norm_flat_tag);
1102 fors_pmos_science_exit(NULL);
1107 if (cpl_frameset_count_tags(frameset, std_pmos_table_tag) > 1) {
1108 cpl_msg_error(recipe,
"Too many in input: %s", std_pmos_table_tag);
1109 fors_pmos_science_exit(NULL);
1113 if (cpl_frameset_count_tags(frameset, std_pmos_table_tag) == 0) {
1114 cpl_msg_error(recipe,
"QC computation was requested, but no "
1115 "%s is found in input", std_pmos_table_tag);
1116 fors_pmos_science_exit(NULL);
1121 cpl_msg_indent_less();
1132 fors_pmos_science_exit(
"Cannot load scientific frame header");
1134 instrume = (
char *)cpl_propertylist_get_string(header,
"INSTRUME");
1135 if (instrume == NULL)
1136 fors_pmos_science_exit(
"Missing keyword INSTRUME in scientific header");
1137 instrume = cpl_strdup(instrume);
1139 if (instrume[4] ==
'1')
1140 snprintf(version, 80,
"%s/%s",
"fors1", VERSION);
1141 if (instrume[4] ==
'2')
1142 snprintf(version, 80,
"%s/%s",
"fors2", VERSION);
1144 reference = cpl_propertylist_get_double(header,
"ESO INS GRIS1 WLEN");
1146 if (cpl_error_get_code() != CPL_ERROR_NONE)
1147 fors_pmos_science_exit(
"Missing keyword ESO INS GRIS1 WLEN in scientific "
1150 if (reference < 3000.0)
1153 if (reference < 3000.0 || reference > 13000.0) {
1154 cpl_msg_error(recipe,
"Invalid central wavelength %.2f read from "
1155 "keyword ESO INS GRIS1 WLEN in scientific frame header",
1157 fors_pmos_science_exit(NULL);
1160 cpl_msg_info(recipe,
"The central wavelength is: %.2f", reference);
1162 rebin = cpl_propertylist_get_int(header,
"ESO DET WIN1 BINX");
1164 if (cpl_error_get_code() != CPL_ERROR_NONE)
1165 fors_pmos_science_exit(
"Missing keyword ESO DET WIN1 BINX in "
1166 "scientific frame header");
1169 dispersion *= rebin;
1170 cpl_msg_warning(recipe,
"The rebin factor is %d, and therefore the "
1171 "spectral dispersion used is %f A/pixel", rebin,
1173 ext_radius /= rebin;
1174 cpl_msg_warning(recipe,
"The rebin factor is %d, and therefore the "
1175 "extraction radius used is %d pixel", rebin,
1179 gain = cpl_propertylist_get_double(header,
"ESO DET OUT1 CONAD");
1181 if (cpl_error_get_code() != CPL_ERROR_NONE)
1182 fors_pmos_science_exit(
"Missing keyword ESO DET OUT1 CONAD in "
1183 "scientific frame header");
1185 cpl_msg_info(recipe,
"The gain factor is: %.2f e-/ADU", gain);
1187 ron = cpl_propertylist_get_double(header,
"ESO DET OUT1 RON");
1189 if (cpl_error_get_code() != CPL_ERROR_NONE)
1190 fors_pmos_science_exit(
"Missing keyword ESO DET OUT1 RON in "
1191 "scientific frame header");
1195 cpl_msg_info(recipe,
"The read-out-noise is: %.2f ADU", ron);
1197 if (cpl_frameset_count_tags(frameset, curv_coeff_tag) == 0) {
1198 cpl_msg_error(recipe,
"Missing required input: %s", curv_coeff_tag);
1199 fors_pmos_science_exit(NULL);
1202 if (cpl_frameset_count_tags(frameset, curv_coeff_tag) > 1) {
1203 cpl_msg_error(recipe,
"Too many in input: %s", curv_coeff_tag);
1204 fors_pmos_science_exit(NULL);
1207 cpl_msg_info(recipe,
"Load normalised flat field (if present)...");
1208 cpl_msg_indent_more();
1212 CPL_TYPE_FLOAT, 0, 1);
1215 if (skyalign >= 0) {
1217 cpl_msg_indent_less();
1218 cpl_msg_info(recipe,
"Load input sky line catalog...");
1219 cpl_msg_indent_more();
1228 nlines = cpl_table_get_nrow(wavelengths);
1231 fors_pmos_science_exit(
"Empty input sky line catalog");
1233 if (cpl_table_has_column(wavelengths, wcolumn) != 1) {
1234 cpl_msg_error(recipe,
"Missing column %s in input line "
1235 "catalog table", wcolumn);
1236 fors_pmos_science_exit(NULL);
1239 line = cpl_malloc(nlines *
sizeof(
double));
1241 for (i = 0; i < nlines; i++)
1242 line[i] = cpl_table_get(wavelengths, wcolumn, i, NULL);
1244 cpl_table_delete(wavelengths); wavelengths = NULL;
1246 lines = cpl_vector_wrap(nlines, line);
1249 cpl_msg_info(recipe,
"No sky line catalog found in input - fine!");
1260 cpl_propertylist_delete(header); header = NULL;
1262 cpl_table_name_column(mask_science,
"xtop",
"science");
1270 if (idscoeff == NULL)
1271 fors_pmos_science_exit(
"Cannot load wavelength calibration table");
1282 cpl_propertylist_delete(header); header = NULL;
1284 if (cpl_table_move_column(mask_science,
"xtop", mask_arc)) {
1286 cpl_msg_warning(recipe,
1287 "Slit configuration of science and arc differs!");
1288 cpl_table_delete(mask_arc); mask_arc = NULL;
1291 cpl_table_name_column(mask_science,
"xtop",
"arc");
1292 cpl_table_delete(mask_arc); mask_arc = NULL;
1305 cpl_propertylist_delete(header); header = NULL;
1307 if (cpl_table_move_column(mask_science,
"xtop", mask_flat)) {
1309 cpl_msg_warning(recipe,
1310 "Slit configuration of science and flat differs!");
1311 cpl_table_delete(mask_flat); mask_flat = NULL;
1314 cpl_table_name_column(mask_science,
"xtop",
"flat");
1315 cpl_table_delete(mask_flat); mask_flat = NULL;
1318 cpl_table_duplicate_column(mask_science,
"diff", mask_science,
"science");
1319 cpl_table_subtract_columns(mask_science,
"diff",
"arc");
1320 cpl_table_abs_column(mask_science,
"diff");
1322 if (cpl_table_get_column_max(mask_science,
"diff") > 0.01) {
1323 cpl_msg_warning(recipe,
1324 "Slit configuration of science and arc differs!");
1329 cpl_table_erase_column(mask_science,
"diff");
1331 cpl_table_duplicate_column(mask_science,
"diff",
1332 mask_science,
"science");
1333 cpl_table_subtract_columns(mask_science,
"diff",
"flat");
1334 cpl_table_abs_column(mask_science,
"diff");
1336 if (cpl_table_get_column_max(mask_science,
"diff") > 0.01) {
1337 cpl_msg_warning(recipe,
1338 "Slit configuration of science and flat differs!");
1345 cpl_table_delete(mask_science); mask_science = NULL;
1347 for (j = 0; j < nscience; j++) {
1350 cpl_msg_indent_less();
1351 cpl_msg_info(recipe,
"Processing scientific exposure of angle %.2f "
1352 "(%d out of %d) ...",
1353 angles[j], j + 1, nscience);
1354 cpl_msg_indent_more();
1356 cpl_msg_info(recipe,
"Load scientific exposure...");
1357 cpl_msg_indent_more();
1368 for (k = 0; k < j; k ++) {
1369 cpl_propertylist_delete(header);
1373 spectra =
dfs_load_image(frameset, science_tag, CPL_TYPE_FLOAT, 0, 0);
1375 for (k = 0; k < j; k ++) {
1376 cpl_image_delete(spectra);
1380 if (spectra == NULL)
1381 fors_pmos_science_exit(
"Cannot load scientific frame");
1384 fors_pmos_science_exit(
"Cannot load scientific frame header");
1386 alltime = cpl_propertylist_get_double(header,
"EXPTIME");
1388 if (cpl_error_get_code() != CPL_ERROR_NONE)
1389 fors_pmos_science_exit(
"Missing keyword EXPTIME in scientific "
1392 cpl_msg_info(recipe,
"Scientific frame exposure time: %.2f s",
1395 ra = cpl_propertylist_get_double(header,
"RA");
1396 dec = cpl_propertylist_get_double(header,
"DEC");
1398 if (cpl_error_get_code() != CPL_ERROR_NONE)
1399 fors_pmos_science_exit(
"Missing keywords RA and DEC in scientific "
1404 cpl_msg_indent_less();
1410 cpl_msg_info(recipe,
"Remove the master bias...");
1412 bias =
dfs_load_image(frameset,
"MASTER_BIAS", CPL_TYPE_FLOAT, 0, 1);
1415 fors_pmos_science_exit(
"Cannot load master bias");
1419 blevel = cpl_image_get_mean(bias);
1423 overscans = mos_load_overscans_fors(header);
1426 cpl_image_delete(spectra); spectra = dummy; dummy = NULL;
1427 cpl_image_delete(bias); bias = NULL;
1428 cpl_table_delete(overscans); overscans = NULL;
1430 if (spectra == NULL)
1431 fors_pmos_science_exit(
"Cannot remove bias from scientific frame");
1433 ccd_xsize = nx = cpl_image_get_size_x(spectra);
1434 ccd_ysize = ny = cpl_image_get_size_y(spectra);
1439 cpl_msg_info(recipe,
"Apply flat field correction...");
1440 if (cpl_image_divide(spectra, norm_flat) != CPL_ERROR_NONE) {
1441 cpl_msg_error(recipe,
1442 "Failure of flat field correction: %s",
1443 cpl_error_get_message());
1444 fors_pmos_science_exit(NULL);
1448 cpl_msg_error(recipe,
"Cannot load input %s for flat field "
1449 "correction", master_norm_flat_tag);
1450 fors_pmos_science_exit(NULL);
1460 if (polytraces == NULL)
1461 fors_pmos_science_exit(
"Cannot load spectral curvature table");
1469 fors_pmos_science_exit(
"Cannot load slits location table");
1471 cpl_msg_info(recipe,
"Processing scientific spectra...");
1478 coordinate = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1481 reference, startwavelength,
1482 endwavelength, dispersion,
1493 if (dispersion > 1.0)
1498 if (skyalign >= 0) {
1500 cpl_msg_info(recipe,
1501 "Align wavelength solution to reference skylines "
1502 "applying %d order residual fit...", skyalign);
1505 cpl_msg_info(recipe,
"Align wavelength solution to reference "
1506 "skylines applying median offset...");
1511 startwavelength, endwavelength,
1512 idscoeff, lines, highres,
1513 skyalign, rainbow, 4);
1516 cpl_msg_warning(recipe,
"Alignment of the wavelength "
1517 "solution to reference sky lines may "
1518 "be unreliable in this case!");
1521 NULL, parlist, recipe, version)) {
1522 fors_pmos_science_exit(NULL);
1526 cpl_msg_warning(recipe,
"Alignment of the wavelength "
1527 "solution to reference sky lines could "
1537 polytraces, reference,
1538 startwavelength, endwavelength,
1542 cpl_image_delete(rainbow); rainbow = NULL;
1543 cpl_image_delete(coordinate); coordinate = NULL;
1551 startwavelength, endwavelength,
1552 dispersion, idscoeff, flux);
1555 cpl_msg_indent_less();
1556 cpl_msg_info(recipe,
1557 "Check applied wavelength against skylines...");
1558 cpl_msg_indent_more();
1561 dispersion, 6, highres);
1564 cpl_msg_info(recipe,
"Mean residual: %f", mean_rms);
1566 mean_rms = cpl_table_get_column_mean(idscoeff,
"error");
1568 cpl_msg_info(recipe,
"Mean model accuracy: %f pixel (%f A)",
1569 mean_rms, mean_rms * dispersion);
1572 save_header = cpl_propertylist_duplicate(header);
1574 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
1575 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
1576 cpl_propertylist_update_double(header,
"CRVAL1",
1577 startwavelength + dispersion/2);
1578 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
1579 cpl_propertylist_update_double(header,
"CD1_1", dispersion);
1580 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
1581 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
1582 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
1583 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
1584 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
1586 if (time_normalise) {
1587 dummy = cpl_image_divide_scalar_create(mapped_sky, alltime);
1591 mapped_science_sky_tag,
1593 fors_pmos_science_exit(NULL);
1598 fors_pmos_science_exit(NULL);
1601 cpl_image_delete(dummy); dummy = NULL;
1607 mapped_science_sky_tag,
1609 fors_pmos_science_exit(NULL);
1614 mapped_science_sky_tag, header)) {
1615 fors_pmos_science_exit(NULL);
1620 if (skymedian == 0 && skylocal == 0) {
1621 cpl_image_delete(mapped_sky); mapped_sky = NULL;
1626 cpl_msg_indent_less();
1628 cpl_msg_info(recipe,
"Local sky determination...");
1629 cpl_msg_indent_more();
1631 startwavelength, endwavelength, dispersion);
1635 cpl_image_divide_scalar(skymap, alltime);
1641 fors_pmos_science_exit(NULL);
1647 fors_pmos_science_exit(NULL);
1650 cpl_image_delete(skymap); skymap = NULL;
1654 unmapped_science_tag,
1656 fors_pmos_science_exit(NULL);
1662 fors_pmos_science_exit(NULL);
1666 cpl_msg_info(recipe,
"Removing cosmic rays...");
1675 cpl_image_delete(smapped); smapped = NULL;
1678 reference, startwavelength,
1679 endwavelength, dispersion,
1683 cpl_msg_warning(recipe,
"Sky subtraction failure");
1685 cpl_msg_warning(recipe,
1686 "Cosmic rays removal not performed!");
1687 cosmics = skylocal = 0;
1691 cpl_image_delete(spectra); spectra = NULL;
1692 cpl_table_delete(polytraces); polytraces = NULL;
1694 if (skyalign >= 0) {
1699 wavelength_map_sky_tag,
1701 fors_pmos_science_exit(NULL);
1707 fors_pmos_science_exit(NULL);
1711 cpl_image_delete(wavemap); wavemap = NULL;
1714 startwavelength, endwavelength,
1715 dispersion, idscoeff, flux);
1717 cpl_image_delete(smapped); smapped = NULL;
1719 if (skyalign >= 0) {
1722 NULL, parlist, recipe, version)) {
1723 fors_pmos_science_exit(NULL);
1729 cpl_msg_indent_less();
1730 cpl_msg_info(recipe,
"Local sky determination...");
1731 cpl_msg_indent_more();
1734 cpl_image_subtract(mapped, skylocalmap);
1735 cpl_image_delete(skylocalmap); skylocalmap = NULL;
1738 if (skymedian || skylocal) {
1740 skylocalmap = cpl_image_subtract_create(mapped_sky, mapped);
1742 cpl_image_delete(mapped_sky); mapped_sky = NULL;
1744 if (time_normalise) {
1745 dummy = cpl_image_divide_scalar_create(skylocalmap, alltime);
1751 fors_pmos_science_exit(NULL);
1757 fors_pmos_science_exit(NULL);
1760 cpl_image_delete(dummy); dummy = NULL;
1767 fors_pmos_science_exit(NULL);
1773 fors_pmos_science_exit(NULL);
1777 skylocalmaps[j] = skylocalmap;
1779 cpl_msg_indent_less();
1780 cpl_msg_info(recipe,
"Object detection...");
1781 cpl_msg_indent_more();
1784 origslits = cpl_table_duplicate(slits);
1785 nslits = cpl_table_get_nrow(slits);
1788 if (cosmics || nscience > 1) {
1790 ext_radius, cont_radius);
1793 mapped_cleaned = cpl_image_duplicate(mapped);
1796 ext_radius, cont_radius);
1798 cpl_image_delete(mapped_cleaned); mapped_cleaned = NULL;
1801 cpl_image_delete(dummy); dummy = NULL;
1806 mappeds[j] = mapped;
1808 cpl_msg_indent_less();
1810 cpl_propertylist_delete(header); header = NULL;
1811 cpl_propertylist_delete(save_header); save_header = NULL;
1814 cpl_table_delete(offsets); offsets = NULL;
1815 cpl_table_delete(idscoeff); idscoeff = NULL;
1817 cpl_image_delete(norm_flat); norm_flat = NULL;
1818 cpl_vector_delete(lines); lines = NULL;
1821 cpl_msg_indent_less();
1822 cpl_msg_info(recipe,
1823 "Check object detection in both beams for all angles...");
1824 cpl_msg_indent_more();
1832 if (error == CPL_ERROR_DATA_NOT_FOUND) {
1833 cpl_msg_warning(recipe,
"No objects found: no Stokes "
1834 "parameters to compute!");
1835 for (j = 0; j < nscience; j++)
1836 cpl_table_delete(slitss[j]);
1838 cpl_table_delete(origslits);
1841 fors_pmos_science_exit(
"Problem in polarimetric object selection");
1845 NULL, parlist, recipe, version)) {
1846 fors_pmos_science_exit(NULL);
1853 for (j = 0; j < nscience; j++) {
1857 fors_pmos_science_exit(NULL);
1862 fors_pmos_science_exit(NULL);
1866 nobjs_per_slit = fors_get_nobjs_perslit(origslits);
1868 cpl_msg_indent_less();
1869 cpl_msg_info(recipe,
"Object extraction...");
1870 cpl_msg_indent_more();
1872 for (j = 0; j < nscience; j++) {
1877 for (k = 0; k < j; k ++) {
1878 cpl_propertylist_delete(header);
1882 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
1883 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
1884 cpl_propertylist_update_double(header,
"CRVAL1",
1885 startwavelength + (dispersion * group)/2);
1886 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
1887 cpl_propertylist_update_double(header,
"CD1_1", dispersion * group);
1888 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
1889 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
1890 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
1891 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
1892 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
1894 if (skymedian || skylocal) {
1896 cpl_msg_info(recipe,
"Extracting at angle %.2f (%d out of %d) ...",
1897 angles[j], j + 1, nscience);
1901 ext_mode, ron, gain, 1);
1903 cpl_image_delete(skylocalmaps[j]); skylocalmaps[j] = NULL;
1907 cpl_image_divide_scalar(images[0], alltime);
1909 mos_rebin_signal(images, group);
1913 reduced_science_tag,
1915 fors_pmos_science_exit(NULL);
1921 fors_pmos_science_exit(NULL);
1924 reduceds[j] = images[0];
1927 cpl_image_divide_scalar(images[1], alltime);
1929 mos_rebin_signal(images + 1, group);
1935 fors_pmos_science_exit(NULL);
1941 fors_pmos_science_exit(NULL);
1943 cpl_image_delete(images[1]);
1946 cpl_image_divide_scalar(images[2], alltime);
1948 mos_rebin_error(images + 2, group);
1954 fors_pmos_science_exit(NULL);
1960 fors_pmos_science_exit(NULL);
1963 rerrors[j] = images[2];
1968 cpl_msg_warning(recipe,
"No objects found: the products "
1969 "%s, %s, and %s are not created",
1970 reduced_science_tag, reduced_sky_tag,
1976 if (skymedian || skylocal) {
1978 cpl_image_divide_scalar(mappeds[j], alltime);
1984 fors_pmos_science_exit(NULL);
1990 fors_pmos_science_exit(NULL);
1994 cpl_image_delete(mappeds[j]); mappeds[j] = NULL;
1995 cpl_propertylist_delete(header); header = NULL;
1999 cpl_table_delete(origslits);
2003 nobjects = cpl_image_get_size_y(reduceds[0]) / 2;
2004 nx = cpl_image_get_size_x(reduceds[0]);
2006 header = cpl_propertylist_new();
2007 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
2008 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
2009 cpl_propertylist_update_double(header,
"CRVAL1",
2010 startwavelength + (dispersion * group)/2);
2011 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
2012 cpl_propertylist_update_double(header,
"CD1_1", dispersion * group);
2013 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
2014 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
2015 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
2016 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
2017 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
2021 cpl_image *pv_im = NULL;
2022 cpl_image *pi_im = NULL;
2023 cpl_image *pvnull_im = NULL;
2024 cpl_image *pierr_im = NULL;
2025 cpl_image *perr_im = NULL;
2029 double *p_vnull = NULL;
2030 double *perr = NULL;
2031 double *pierr = NULL;
2038 pv_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2039 perr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2040 pi_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2041 pierr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2043 p_v = cpl_image_get_data_double(pv_im);
2044 perr = cpl_image_get_data_double(perr_im);
2045 p_i = cpl_image_get_data_double(pi_im);
2046 pierr = cpl_image_get_data_double(pierr_im);
2048 if (nscience / 2 > 1) {
2049 pvnull_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2050 p_vnull = cpl_image_get_data_double(pvnull_im);
2053 for (j = 0; j < nobjects; j++) {
2060 double * ip_v, * ip_i, * ipierr,
2061 * ip_vnull, * iperr;
2064 float * iff, * ierr;
2066 ip_v = p_v + (nobjects - 1 - j) * nx;
2068 if (nscience / 2 > 1)
2069 ip_vnull = p_vnull + (nobjects - 1 - j) * nx;
2071 iperr = perr + (nobjects - 1 - j) * nx;
2073 ip_i = p_i + (nobjects - 1 - j) * nx;
2074 ipierr = pierr + (nobjects - 1 - j) * nx;
2077 for (i = 0; i < nslits; i += 2) {
2078 total += nobjs_per_slit[i];
2085 for (k = 0; k < nscience / 2; k++) {
2086 float *if_o, *if_e, *ifdelta_o, *ifdelta_e;
2087 float *if_o_err, *if_e_err, *ifdelta_o_err, *ifdelta_e_err;
2089 int pos = fors_find_angle_pos(angles, nscience, 180 * k - 45);
2090 int pos_d = fors_find_angle_pos(angles, nscience, 180 * k + 45);
2093 data = cpl_image_get_data_float(reduceds[pos]);
2095 if_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2096 + (total - j - 1)) * nx;
2098 if_e = data + (2 * (nobjects - total)
2099 + (total - j - 1)) * nx;
2101 data = cpl_image_get_data_float(reduceds[pos_d]);
2103 ifdelta_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2104 + (total - j - 1)) * nx;
2106 ifdelta_e = data + (2 * (nobjects - total)
2107 + (total - j - 1)) * nx;
2109 data = cpl_image_get_data_float(rerrors[pos]);
2112 + (2 * (nobjects - total) + nobjs_per_slit[p]
2113 + (total - j - 1)) * nx;
2115 if_e_err = data + (2 * (nobjects - total)
2116 + (total - j - 1)) * nx;
2118 data = cpl_image_get_data_float(rerrors[pos_d]);
2120 ifdelta_o_err = data
2121 + (2 * (nobjects - total) + nobjs_per_slit[p]
2122 + (total - j - 1)) * nx;
2124 ifdelta_e_err = data + (2 * (nobjects - total)
2125 + (total - j - 1)) * nx;
2129 char *signal_to_noise = getenv(
"SIGNAL_TO_NOISE" );
2131 char *min_s2n = getenv(
"MIN_S2N" );
2134 if (signal_to_noise)
2135 s2n = atof(signal_to_noise);
2138 ms2n = atoi(min_s2n);
2147 for (m = 0; m < nx; m++) {
2148 if (if_o_err[m] > 0.0) {
2149 if (if_o[m]/if_o_err[m] > s2n) {
2151 if (bright > ms2n) {
2159 if (bright > ms2n) {
2161 filename = cpl_sprintf(
"angle_%d_%d.dat",
2163 file = fopen(filename,
"w");
2165 fprintf(file,
"%d\n", p + 2);
2167 for (m = 0; m < nx; m++) {
2168 double lambda = startwavelength
2169 + dispersion * group * (0.5 + m);
2170 fprintf(file,
"%.3f %.9e %.9e %.9e %.9e\n",
2171 lambda, if_o[m], if_o_err[m],
2172 if_e[m], if_e_err[m]);
2178 filename = cpl_sprintf(
"angle_%d_%d.dat",
2180 file = fopen(filename,
"w");
2182 fprintf(file,
"%d\n", p + 2);
2184 for (m = 0; m < nx; m++) {
2185 double lambda = startwavelength
2186 + dispersion * group * (0.5 + m);
2187 fprintf(file,
"%.3f %.9e %.9e %.9e %.9e\n",
2188 lambda, ifdelta_o[m], ifdelta_o_err[m],
2189 ifdelta_e[m], ifdelta_e_err[m]);
2196 cpl_msg_info(recipe,
2197 "Extracted signal not written to "
2198 "ASCII (S/N > %.0f only in %d < %d "
2199 "bins)", s2n, bright, ms2n);
2203 for (m = 0; m < nx; m++) {
2205 double quantity = if_o[m] + if_e[m] == 0.0 ? 0.0 :
2206 (if_o[m] - if_e[m] ) /
2207 (if_o[m] + if_e[m] ) -
2208 (ifdelta_o[m] - ifdelta_e[m]) /
2209 (ifdelta_o[m] + ifdelta_e[m]);
2211 quantity = isfinite(quantity) ? quantity : 0.0;
2214 ip_v[m] += quantity * 0.5 / (nscience / 2);
2217 if (nscience / 2 > 1) {
2219 ip_vnull[m] += quantity * 0.5 / (nscience / 2);
2221 ip_vnull[m] -= quantity * 0.5 / (nscience / 2);
2225 ip_i[m] += (if_o[m] + if_e[m] +
2226 ifdelta_o[m] + ifdelta_e[m]) / nscience;
2229 ipierr[m] += (if_o_err[m] * if_o_err[m]
2230 + if_e_err[m] * if_e_err[m]
2231 + ifdelta_o_err[m] * ifdelta_o_err[m]
2232 + ifdelta_e_err[m] * ifdelta_e_err[m])
2233 / nscience / nscience;
2239 data = cpl_image_get_data_float(reduceds[0]);
2240 iff = data + (2 * (nobjects - total) + (total - j - 1)) * nx;
2242 data = cpl_image_get_data_float(rerrors[0]);
2243 ierr = data + (2 * (nobjects - total) + (total - j - 1)) * nx;
2245 for (m = 0; m < nx; m++)
2246 iperr[m] = iff[m] <= 0.0 ?
2247 0.0 : ierr[m] / iff[m] * 0.5 / sqrt (nscience / 2);
2249 if (nscience / 2 > 1) {
2251 float max, sum, sum2, imean;
2256 weights = cpl_malloc(
sizeof(
float) * nx);
2259 for (k = 0; k < nx; k++) {
2260 if (max < iff[k]) max = iff[k];
2263 for (k = 0; k < nx; k++) {
2264 weights[k] = iff[k] < 0.0 ?
2265 0.0 : iff[k] * iff[k] / (max * max);
2270 for (k = 0; k < nx; k++) {
2271 sum += weights[k] * ip_vnull[k];
2279 mean_vnull += (imean - mean_vnull) / (j + 1.0);
2284 parlist, recipe, version))
2285 fors_pmos_science_exit(NULL);
2288 parlist, recipe, version))
2289 fors_pmos_science_exit(NULL);
2291 if (nscience / 2 > 1) {
2294 cpl_propertylist *qheader;
2297 cpl_propertylist_update_double(qheader,
"CRPIX1", 1.0);
2298 cpl_propertylist_update_double(qheader,
"CRPIX2", 1.0);
2299 cpl_propertylist_update_double(qheader,
"CRVAL1",
2300 startwavelength + (dispersion * group)/2);
2301 cpl_propertylist_update_double(qheader,
"CRVAL2", 1.0);
2302 cpl_propertylist_update_double(qheader,
"CD1_1",
2303 dispersion * group);
2304 cpl_propertylist_update_double(qheader,
"CD1_2", 0.0);
2305 cpl_propertylist_update_double(qheader,
"CD2_1", 0.0);
2306 cpl_propertylist_update_double(qheader,
"CD2_2", 1.0);
2307 cpl_propertylist_update_string(qheader,
"CTYPE1",
"LINEAR");
2308 cpl_propertylist_update_string(qheader,
"CTYPE2",
"PIXEL");
2318 "Product category", instrume))
2319 fors_pmos_science_exit(
"Cannot write product category to "
2323 "DPR type", instrume))
2324 fors_pmos_science_exit(
"Missing keyword DPR TYPE in "
2325 "scientific frame header");
2328 "Template", instrume))
2329 fors_pmos_science_exit(
"Missing keyword TPL ID in "
2330 "scientific frame header");
2333 "Grism name", instrume))
2334 fors_pmos_science_exit(
"Missing keyword INS GRIS1 NAME in "
2335 "scientific frame header");
2338 "Grism identifier", instrume))
2339 fors_pmos_science_exit(
"Missing keyword INS GRIS1 ID in "
2340 "scientific frame header");
2342 if (cpl_propertylist_has(qheader,
"ESO INS FILT1 NAME"))
2344 "Filter name", instrume);
2347 "Collimator name", instrume))
2348 fors_pmos_science_exit(
"Missing keyword INS COLL NAME in "
2349 "scientific frame header");
2352 "Chip identifier", instrume))
2353 fors_pmos_science_exit(
"Missing keyword DET CHIP1 ID in "
2354 "scientific frame header");
2357 "Archive name of input data",
2359 fors_pmos_science_exit(
"Missing keyword ARCFILE in "
2360 "scientific frame header");
2362 pipefile = dfs_generate_filename(reduced_nul_v_tag);
2364 "Pipeline product name", instrume))
2365 fors_pmos_science_exit(
"Cannot write PIPEFILE to "
2367 cpl_free(pipefile); pipefile = NULL;
2374 keyname =
"QC.NULL.V.MEAN";
2378 "Mean V null parameter",
2380 fors_pmos_science_exit(
"Cannot write mean Q null "
2381 "parameter to QC log file.");
2384 keyname =
"QC.NANGLES";
2386 if (fors_qc_write_qc_int(qheader, nscience,
2388 "Number of processed plate angles",
2390 fors_pmos_science_exit(
"Cannot write number of processed "
2397 if (
dfs_save_image(frameset, pvnull_im, reduced_nul_v_tag, qheader,
2398 parlist, recipe, version))
2399 fors_pmos_science_exit(NULL);
2401 cpl_propertylist_delete(qheader);
2404 if (
dfs_save_image(frameset, perr_im, reduced_error_v_tag, header,
2405 parlist, recipe, version))
2406 fors_pmos_science_exit(NULL);
2408 cpl_image_power(pierr_im, 0.5);
2410 if (
dfs_save_image(frameset, pierr_im, reduced_error_i_tag, header,
2411 parlist, recipe, version))
2412 fors_pmos_science_exit(NULL);
2414 cpl_image_delete(pv_im);
2415 cpl_image_delete(pvnull_im);
2416 cpl_image_delete(perr_im);
2417 cpl_image_delete(pi_im);
2418 cpl_image_delete(pierr_im);
2421 cpl_image *pq_im = NULL;
2422 cpl_image *pu_im = NULL;
2423 cpl_image *pl_im = NULL;
2424 cpl_image *pi_im = NULL;
2426 cpl_image *pqnull_im = NULL;
2427 cpl_image *punull_im = NULL;
2429 cpl_image *pqerr_im = NULL;
2430 cpl_image *puerr_im = NULL;
2431 cpl_image *plerr_im = NULL;
2432 cpl_image *pierr_im = NULL;
2434 cpl_image *pang_im = NULL;
2435 cpl_image *pangerr_im = NULL;
2442 double *p_qnull = NULL;
2443 double *p_unull = NULL;
2445 double *pqerr = NULL;
2446 double *puerr = NULL;
2447 double *plerr = NULL;
2448 double *pierr = NULL;
2450 double *pang = NULL;
2451 double *pangerr = NULL;
2455 cpl_image *correct_im = cpl_image_new(nx, 1, CPL_TYPE_DOUBLE);
2456 double *correct = cpl_image_get_data_double(correct_im);
2458 double mean_unull, mean_qnull;
2463 pq_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2464 pu_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2465 pl_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2466 pi_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2468 pqerr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2469 puerr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2470 plerr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2471 pierr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2473 pang_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2474 pangerr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2476 p_q = cpl_image_get_data_double(pq_im);
2477 p_u = cpl_image_get_data_double(pu_im);
2478 p_l = cpl_image_get_data_double(pl_im);
2479 p_i = cpl_image_get_data_double(pi_im);
2481 if (nscience / 4 > 1) {
2482 pqnull_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2483 punull_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2485 p_qnull = cpl_image_get_data_double(pqnull_im);
2486 p_unull = cpl_image_get_data_double(punull_im);
2488 cpl_msg_warning(cpl_func,
2489 "Not enough pairs to compute null parameters");
2492 pqerr = cpl_image_get_data_double(pqerr_im);
2493 puerr = cpl_image_get_data_double(puerr_im);
2494 plerr = cpl_image_get_data_double(plerr_im);
2495 pierr = cpl_image_get_data_double(pierr_im);
2497 pang = cpl_image_get_data_double(pang_im);
2498 pangerr = cpl_image_get_data_double(pangerr_im);
2501 cpl_table * chrotbl =
2504 int nrow = cpl_table_get_nrow(chrotbl);
2505 float * lambda = cpl_table_get_data_float(chrotbl,
"lambda");
2506 float * theta = cpl_table_get_data_float(chrotbl,
"eps_theta");
2508 for (j = 0; j < nx; j++) {
2509 double c_wave = startwavelength
2510 + (dispersion * group) / 2
2511 + j * dispersion * group;
2515 for (k = 0; k < nrow - 1; k++) {
2516 if (lambda[k] <= c_wave && c_wave < lambda[k + 1]) {
2523 correct[j] = (theta [k + 1] - theta [k]) /
2524 (lambda[k + 1] - lambda[k]) *
2525 (c_wave - lambda[k]) + theta[k];
2526 correct[j] *= M_PI / 180;
2529 correct[j] = correct[j-1];
2534 cpl_table_delete(chrotbl);
2537 for (j = 0; j < nobjects; j++) {
2559 ip_q = p_q + (nobjects - 1 - j) * nx;
2560 ip_u = p_u + (nobjects - 1 - j) * nx;
2561 ip_l = p_l + (nobjects - 1 - j) * nx;
2562 ip_i = p_i + (nobjects - 1 - j) * nx;
2564 if (nscience / 4 > 1) {
2565 ip_qnull = p_qnull + (nobjects - 1 - j) * nx;
2566 ip_unull = p_unull + (nobjects - 1 - j) * nx;
2569 ipqerr = pqerr + (nobjects - 1 - j) * nx;
2570 ipuerr = puerr + (nobjects - 1 - j) * nx;
2571 iplerr = plerr + (nobjects - 1 - j) * nx;
2572 ipierr = pierr + (nobjects - 1 - j) * nx;
2574 ipang = pang + (nobjects - 1 - j) * nx;
2575 ipangerr = pangerr + (nobjects - 1 - j) * nx;
2578 for (i = 0; i < nslits; i += 2) {
2579 total += nobjs_per_slit[i];
2586 for (k = 0; k < nscience / 4; k++) {
2587 float * if_o, * if_e, * ifdelta_o, * ifdelta_e;
2588 float * if_o_err, * if_e_err, * ifdelta_o_err, * ifdelta_e_err;
2592 pos = fors_find_angle_pos(angles, nscience, 90 * k);
2593 pos_d = fors_find_angle_pos(angles, nscience, 90 * k + 45);
2595 data = cpl_image_get_data_float(reduceds[pos]);
2597 if_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2598 + (total - j - 1)) * nx;
2600 if_e = data + (2 * (nobjects - total)
2601 + (total - j - 1)) * nx;
2603 data = cpl_image_get_data_float(reduceds[pos_d]);
2605 ifdelta_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2606 + (total - j - 1)) * nx;
2608 ifdelta_e = data + (2 * (nobjects - total)
2609 + (total - j - 1)) * nx;
2611 data = cpl_image_get_data_float(rerrors[pos]);
2613 if_o_err = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2614 + (total - j - 1)) * nx;
2616 if_e_err = data + (2 * (nobjects - total)
2617 + (total - j - 1)) * nx;
2619 data = cpl_image_get_data_float(rerrors[pos_d]);
2621 ifdelta_o_err = data + (2 * (nobjects - total)
2622 + nobjs_per_slit[p] + (total - j - 1)) * nx;
2624 ifdelta_e_err = data + (2 * (nobjects - total)
2625 + (total - j - 1)) * nx;
2627 for (m = 0; m < nx; m++) {
2629 double quantity = fabs(if_o[m] + if_e[m]) < FLT_MIN ? 0.0 :
2630 (if_o[m] - if_e[m] ) /
2631 (if_o[m] + if_e[m] ) -
2632 (ifdelta_o[m] - ifdelta_e[m]) /
2633 (ifdelta_o[m] + ifdelta_e[m]);
2635 quantity = isfinite(quantity) ? quantity : 0.0;
2638 ip_q[m] += quantity * 0.5 / (nscience / 4);
2641 if (nscience / 4 > 1) {
2643 ip_qnull[m] += quantity * 0.5 / (nscience / 4);
2645 ip_qnull[m] -= quantity * 0.5 / (nscience / 4);
2649 ip_i[m] += (if_o[m] + if_e[m] +
2650 ifdelta_o[m] + ifdelta_e[m]) / nscience;
2653 ipierr[m] += (if_o_err[m] * if_o_err[m]
2654 + if_e_err[m] * if_e_err[m]
2655 + ifdelta_o_err[m] * ifdelta_o_err[m]
2656 + ifdelta_e_err[m] * ifdelta_e_err[m])
2657 / nscience / nscience;
2662 pos = fors_find_angle_pos(angles, nscience, 90 * k + 22.5);
2663 pos_d = fors_find_angle_pos(angles, nscience, 90 * k + 67.5);
2665 data = cpl_image_get_data_float(reduceds[pos]);
2667 if_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2668 + (total - j - 1)) * nx;
2670 if_e = data + (2 * (nobjects - total)
2671 + (total - j - 1)) * nx;
2673 data = cpl_image_get_data_float(reduceds[pos_d]);
2675 ifdelta_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2676 + (total - j - 1)) * nx;
2678 ifdelta_e = data + (2 * (nobjects - total)
2679 + (total - j - 1)) * nx;
2681 data = cpl_image_get_data_float(rerrors[pos]);
2683 if_o_err = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2684 + (total - j - 1)) * nx;
2686 if_e_err = data + (2 * (nobjects - total)
2687 + (total - j - 1)) * nx;
2689 data = cpl_image_get_data_float(rerrors[pos_d]);
2691 ifdelta_o_err = data + (2 * (nobjects - total)
2692 + nobjs_per_slit[p] + (total - j - 1)) * nx;
2694 ifdelta_e_err = data + (2 * (nobjects - total)
2695 + (total - j - 1)) * nx;
2697 for (m = 0; m < nx; m++) {
2699 double quantity = fabs(if_o[m] + if_e[m]) < FLT_MIN ? 0.0 :
2700 (if_o[m] - if_e[m] ) /
2701 (if_o[m] + if_e[m] ) -
2702 (ifdelta_o[m] - ifdelta_e[m]) /
2703 (ifdelta_o[m] + ifdelta_e[m]);
2705 quantity = isfinite(quantity) ? quantity : 0.0;
2708 ip_u[m] += quantity * 0.5 / (nscience / 4);
2711 if (nscience / 4 > 1) {
2713 ip_unull[m] += quantity * 0.5 / (nscience / 4);
2715 ip_unull[m] -= quantity * 0.5 / (nscience / 4);
2719 ip_i[m] += (if_o[m] + if_e[m] +
2720 ifdelta_o[m] + ifdelta_e[m]) / nscience;
2723 ipierr[m] += (if_o_err[m] * if_o_err[m]
2724 + if_e_err[m] * if_e_err[m]
2725 + ifdelta_o_err[m] * ifdelta_o_err[m]
2726 + ifdelta_e_err[m] * ifdelta_e_err[m])
2727 / nscience / nscience;
2733 pos = fors_find_angle_pos(angles, nscience, 0.0);
2735 data = cpl_image_get_data_float(reduceds[pos]);
2736 iffq = data + (2 * (nobjects - total) + (total - j - 1)) * nx;
2738 data = cpl_image_get_data_float(rerrors[pos]);
2739 ierrq = data + (2 * (nobjects - total) + (total - j - 1)) * nx;
2741 pos = fors_find_angle_pos(angles, nscience, 22.5);
2743 data = cpl_image_get_data_float(reduceds[pos]);
2744 iffu = data + (2 * (nobjects - total) + (total - j - 1)) * nx;
2746 data = cpl_image_get_data_float(rerrors[pos]);
2747 ierru = data + (2 * (nobjects - total) + (total - j - 1)) * nx;
2749 for (m = 0; m < nx; m++) {
2753 ipqerr[m] = iffq[m] <= 0.0 ?
2754 0.0 : ierrq[m] / iffq[m] * 0.5 / sqrt (nscience / 4);
2756 ipuerr[m] = iffu[m] <= 0.0 ?
2757 0.0 : ierru[m] / iffu[m] * 0.5 / sqrt (nscience / 4);
2759 iplerr[m] = 0.5 * (ipqerr[m] + ipuerr[m]);
2762 ip_l[m] = sqrt(ip_u[m] * ip_u[m] + ip_q[m] * ip_q[m]);
2765 if (fabs(ip_q[m]) < 0.00001) {
2766 if (ip_u[m] > 0.0) {
2774 ipang[m] = 0.5 * atan(ip_u[m] / ip_q[m]) * 180 / M_PI;
2775 if (ip_q[m] > 0.0) {
2776 if (ip_u[m] < 0.0) {
2786 radicand = ip_q[m] * ip_q[m] * ipuerr[m] * ipuerr[m] +
2787 ip_u[m] * ip_u[m] * ipqerr[m] * ipqerr[m];
2789 ipangerr[m] = (ip_l[m] == 0.0 ? 0.0 :
2790 sqrt(radicand) * 0.5 / (ip_l[m] * ip_l[m]) * 180 / M_PI);
2799 if (instrume[4] ==
'2') {
2801 double w_rotation = - wollaston * M_PI / 2;
2803 ipang[m] -= w_rotation * 180 / M_PI;
2805 ip_q[m] = ip_q[m] * cos(2 * w_rotation)
2806 + ip_u[m] * sin(2 * w_rotation);
2808 ip_u[m] = ip_u[m] * cos(2 * w_rotation)
2809 - ip_q[m] * sin(2 * w_rotation);
2813 ipang[m] -= correct[m] * 180 / M_PI;
2815 ip_q[m] = ip_q[m] * cos(2 * correct[m])
2816 + ip_u[m] * sin(2 * correct[m]);
2818 ip_u[m] = ip_u[m] * cos(2 * correct[m])
2819 - ip_q[m] * sin(2 * correct[m]);
2824 else if (ipang[m] >= 180.0)
2828 if (nscience / 4 > 1) {
2830 float max, sum, sum2, imean;
2835 weights = cpl_malloc(
sizeof(
float) * nx);
2838 for (k = 0; k < nx; k++) {
2839 if (max < iffq[k]) max = iffq[k];
2842 for (k = 0; k < nx; k++) {
2843 weights[k] = iffq[k] < 0.0 ?
2844 0.0 : iffq[k] * iffq[k] / (max * max);
2849 for (k = 0; k < nx; k++) {
2850 sum += weights[k] * ip_qnull[k];
2858 mean_qnull += (imean - mean_qnull) / (j + 1.0);
2861 weights = cpl_malloc(
sizeof(
float) * nx);
2864 for (k = 0; k < nx; k++) {
2865 if (max < iffu[k]) max = iffu[k];
2868 for (k = 0; k < nx; k++) {
2869 weights[k] = iffu[k] < 0.0 ?
2870 0.0 : iffu[k] * iffu[k] / (max * max);
2875 for (k = 0; k < nx; k++) {
2876 sum += weights[k] * ip_unull[k];
2884 mean_unull += (imean - mean_unull) / (j + 1.0);
2888 cpl_image_delete(correct_im);
2891 parlist, recipe, version))
2892 fors_pmos_science_exit(NULL);
2895 parlist, recipe, version))
2896 fors_pmos_science_exit(NULL);
2898 if (qc && standard) {
2899 cpl_table *polsta =
dfs_load_table(frameset, std_pmos_table_tag, 1);
2902 cpl_propertylist_update_double(qheader,
"CRPIX1", 1.0);
2903 cpl_propertylist_update_double(qheader,
"CRPIX2", 1.0);
2904 cpl_propertylist_update_double(qheader,
"CRVAL1",
2905 startwavelength + (dispersion * group)/2);
2906 cpl_propertylist_update_double(qheader,
"CRVAL2", 1.0);
2907 cpl_propertylist_update_double(qheader,
"CD1_1",
2908 dispersion * group);
2909 cpl_propertylist_update_double(qheader,
"CD1_2", 0.0);
2910 cpl_propertylist_update_double(qheader,
"CD2_1", 0.0);
2911 cpl_propertylist_update_double(qheader,
"CD2_2", 1.0);
2912 cpl_propertylist_update_string(qheader,
"CTYPE1",
"LINEAR");
2913 cpl_propertylist_update_string(qheader,
"CTYPE2",
"PIXEL");
2916 startwavelength, dispersion, 1000.,
2917 polsta, ra, dec, &filter,
2920 &qc_angle, &qc_angle_err)) {
2921 cpl_msg_warning(cpl_func,
"No QC can be computed");
2927 char band[] = {
' ',
'\0'};
2936 "Product category", instrume))
2937 fors_pmos_science_exit(
"Cannot write product category to "
2941 "DPR type", instrume))
2942 fors_pmos_science_exit(
"Missing keyword DPR TYPE in "
2943 "scientific frame header");
2946 "Template", instrume))
2947 fors_pmos_science_exit(
"Missing keyword TPL ID in "
2948 "scientific frame header");
2951 "Grism name", instrume))
2952 fors_pmos_science_exit(
"Missing keyword INS GRIS1 NAME in "
2953 "scientific frame header");
2956 "Grism identifier", instrume))
2957 fors_pmos_science_exit(
"Missing keyword INS GRIS1 ID in "
2958 "scientific frame header");
2960 if (cpl_propertylist_has(qheader,
"ESO INS FILT1 NAME"))
2962 "Filter name", instrume);
2965 "Collimator name", instrume))
2966 fors_pmos_science_exit(
"Missing keyword INS COLL NAME in "
2967 "scientific frame header");
2970 "Chip identifier", instrume))
2971 fors_pmos_science_exit(
"Missing keyword DET CHIP1 ID in "
2972 "scientific frame header");
2975 "Archive name of input data",
2977 fors_pmos_science_exit(
"Missing keyword ARCFILE in "
2978 "scientific frame header");
2980 pipefile = dfs_generate_filename(reduced_nul_q_tag);
2982 "Pipeline product name", instrume))
2983 fors_pmos_science_exit(
"Cannot write PIPEFILE to "
2985 cpl_free(pipefile); pipefile = NULL;
2992 keyname =
"QC.PMOS.BAND";
2996 "Band where polarisation was "
2997 "measured", instrume)) {
2998 fors_pmos_science_exit(
"Cannot write QC.PMOS.BAND "
2999 "parameter to QC log file");
3002 keyname =
"QC.PMOS.POLARISED";
3004 if (fors_qc_write_qc_int(qheader, polarised, keyname, NULL,
3005 "Polarisation is expected (1 = yes, "
3006 "0 = no)", instrume)) {
3007 fors_pmos_science_exit(
"Cannot write QC.PMOS.POLARISED "
3008 "parameter to QC log file");
3011 keyname =
"QC.PMOS.L.OFFSET";
3014 text =
"Linear polarisation relative offset";
3016 text =
"Linear polarisation offset";
3020 fors_pmos_science_exit(
"Cannot write linear polarisation "
3021 "offset to QC log file");
3024 keyname =
"QC.PMOS.L.OFFSETERR";
3027 "Error on linear polarisation offset",
3029 fors_pmos_science_exit(
"Cannot write linear polarisation "
3030 "offset error to QC log file");
3034 keyname =
"QC.PMOS.ANGLE.OFFSET";
3037 "Polarisation angle offset",
3039 fors_pmos_science_exit(
"Cannot write polarisation "
3040 "angle offset to QC log file");
3043 keyname =
"QC.PMOS.ANGLE.OFFSETERR";
3046 NULL,
"Error on polarisation "
3047 "angle offset", instrume)) {
3048 fors_pmos_science_exit(
"Cannot write polarisation "
3049 "angle offset error to QC "
3058 parlist, recipe, version))
3059 fors_pmos_science_exit(NULL);
3061 cpl_propertylist_delete(qheader);
3065 parlist, recipe, version))
3066 fors_pmos_science_exit(NULL);
3069 if (nscience / 4 > 1) {
3075 cpl_propertylist_update_double(qheader,
"CRPIX1", 1.0);
3076 cpl_propertylist_update_double(qheader,
"CRPIX2", 1.0);
3077 cpl_propertylist_update_double(qheader,
"CRVAL1",
3078 startwavelength + (dispersion * group)/2);
3079 cpl_propertylist_update_double(qheader,
"CRVAL2", 1.0);
3080 cpl_propertylist_update_double(qheader,
"CD1_1",
3081 dispersion * group);
3082 cpl_propertylist_update_double(qheader,
"CD1_2", 0.0);
3083 cpl_propertylist_update_double(qheader,
"CD2_1", 0.0);
3084 cpl_propertylist_update_double(qheader,
"CD2_2", 1.0);
3085 cpl_propertylist_update_string(qheader,
"CTYPE1",
"LINEAR");
3086 cpl_propertylist_update_string(qheader,
"CTYPE2",
"PIXEL");
3096 "Product category", instrume))
3097 fors_pmos_science_exit(
"Cannot write product category to "
3101 "DPR type", instrume))
3102 fors_pmos_science_exit(
"Missing keyword DPR TYPE in "
3103 "scientific frame header");
3106 "Template", instrume))
3107 fors_pmos_science_exit(
"Missing keyword TPL ID in "
3108 "scientific frame header");
3111 "Grism name", instrume))
3112 fors_pmos_science_exit(
"Missing keyword INS GRIS1 NAME in "
3113 "scientific frame header");
3116 "Grism identifier", instrume))
3117 fors_pmos_science_exit(
"Missing keyword INS GRIS1 ID in "
3118 "scientific frame header");
3120 if (cpl_propertylist_has(qheader,
"ESO INS FILT1 NAME"))
3122 "Filter name", instrume);
3125 "Collimator name", instrume))
3126 fors_pmos_science_exit(
"Missing keyword INS COLL NAME in "
3127 "scientific frame header");
3130 "Chip identifier", instrume))
3131 fors_pmos_science_exit(
"Missing keyword DET CHIP1 ID in "
3132 "scientific frame header");
3135 "Archive name of input data",
3137 fors_pmos_science_exit(
"Missing keyword ARCFILE in "
3138 "scientific frame header");
3140 pipefile = dfs_generate_filename(reduced_nul_q_tag);
3142 "Pipeline product name", instrume))
3143 fors_pmos_science_exit(
"Cannot write PIPEFILE to "
3145 cpl_free(pipefile); pipefile = NULL;
3152 keyname =
"QC.NULL.Q.MEAN";
3156 "Mean Q null parameter",
3158 fors_pmos_science_exit(
"Cannot write mean Q null "
3159 "parameter to QC log file");
3162 keyname =
"QC.NANGLES";
3164 if (fors_qc_write_qc_int(qheader, nscience / 2,
3166 "Number of processed plate angles",
3168 fors_pmos_science_exit(
"Cannot write number of processed "
3175 if (
dfs_save_image(frameset, pqnull_im, reduced_nul_q_tag, qheader,
3176 parlist, recipe, version))
3177 fors_pmos_science_exit(NULL);
3179 cpl_propertylist_delete(qheader);
3183 cpl_propertylist_update_double(qheader,
"CRPIX1", 1.0);
3184 cpl_propertylist_update_double(qheader,
"CRPIX2", 1.0);
3185 cpl_propertylist_update_double(qheader,
"CRVAL1",
3186 startwavelength + (dispersion * group)/2);
3187 cpl_propertylist_update_double(qheader,
"CRVAL2", 1.0);
3188 cpl_propertylist_update_double(qheader,
"CD1_1",
3189 dispersion * group);
3190 cpl_propertylist_update_double(qheader,
"CD1_2", 0.0);
3191 cpl_propertylist_update_double(qheader,
"CD2_1", 0.0);
3192 cpl_propertylist_update_double(qheader,
"CD2_2", 1.0);
3193 cpl_propertylist_update_string(qheader,
"CTYPE1",
"LINEAR");
3194 cpl_propertylist_update_string(qheader,
"CTYPE2",
"PIXEL");
3204 "Product category", instrume))
3205 fors_pmos_science_exit(
"Cannot write product category to "
3209 "DPR type", instrume))
3210 fors_pmos_science_exit(
"Missing keyword DPR TYPE in "
3211 "scientific frame header");
3214 "Template", instrume))
3215 fors_pmos_science_exit(
"Missing keyword TPL ID in "
3216 "scientific frame header");
3219 "Grism name", instrume))
3220 fors_pmos_science_exit(
"Missing keyword INS GRIS1 NAME in "
3221 "scientific frame header");
3224 "Grism identifier", instrume))
3225 fors_pmos_science_exit(
"Missing keyword INS GRIS1 ID in "
3226 "scientific frame header");
3228 if (cpl_propertylist_has(qheader,
"ESO INS FILT1 NAME"))
3230 "Filter name", instrume);
3233 "Collimator name", instrume))
3234 fors_pmos_science_exit(
"Missing keyword INS COLL NAME in "
3235 "scientific frame header");
3238 "Chip identifier", instrume))
3239 fors_pmos_science_exit(
"Missing keyword DET CHIP1 ID in "
3240 "scientific frame header");
3243 "Archive name of input data",
3245 fors_pmos_science_exit(
"Missing keyword ARCFILE in "
3246 "scientific frame header");
3248 pipefile = dfs_generate_filename(reduced_nul_u_tag);
3250 "Pipeline product name", instrume))
3251 fors_pmos_science_exit(
"Cannot write PIPEFILE to "
3253 cpl_free(pipefile); pipefile = NULL;
3260 keyname =
"QC.NULL.U.MEAN";
3264 "Mean U null parameter",
3266 fors_pmos_science_exit(
"Cannot write mean U null "
3267 "parameter to QC log file");
3270 keyname =
"QC.NANGLES";
3272 if (fors_qc_write_qc_int(qheader, nscience / 2,
3274 "Number of processed plate angles",
3276 fors_pmos_science_exit(
"Cannot write number of processed "
3283 if (
dfs_save_image(frameset, punull_im, reduced_nul_u_tag, qheader,
3284 parlist, recipe, version))
3285 fors_pmos_science_exit(NULL);
3287 cpl_propertylist_delete(qheader);
3290 if (
dfs_save_image(frameset, pqerr_im, reduced_error_q_tag, header,
3291 parlist, recipe, version))
3292 fors_pmos_science_exit(NULL);
3294 if (
dfs_save_image(frameset, puerr_im, reduced_error_u_tag, header,
3295 parlist, recipe, version))
3296 fors_pmos_science_exit(NULL);
3298 if (
dfs_save_image(frameset, plerr_im, reduced_error_l_tag, header,
3299 parlist, recipe, version))
3300 fors_pmos_science_exit(NULL);
3303 parlist, recipe, version))
3304 fors_pmos_science_exit(NULL);
3306 if (
dfs_save_image(frameset, pangerr_im, reduced_error_angle_tag,
3307 header, parlist, recipe, version))
3308 fors_pmos_science_exit(NULL);
3311 header, parlist, recipe, version))
3312 fors_pmos_science_exit(NULL);
3314 cpl_image_power(pierr_im, 0.5);
3317 header, parlist, recipe, version))
3318 fors_pmos_science_exit(NULL);
3322 cpl_image_delete(pq_im);
3323 cpl_image_delete(pu_im);
3324 cpl_image_delete(pl_im);
3325 cpl_image_delete(pi_im);
3327 cpl_image_delete(pqnull_im);
3328 cpl_image_delete(punull_im);
3330 cpl_image_delete(pqerr_im);
3331 cpl_image_delete(puerr_im);
3332 cpl_image_delete(plerr_im);
3333 cpl_image_delete(pierr_im);
3334 cpl_image_delete(pang_im);
3335 cpl_image_delete(pangerr_im);
3338 cpl_propertylist_delete(header);
3342 for (j = 0; j < nscience; j++) {
3343 cpl_image_delete(reduceds[j]);
3344 cpl_image_delete(rerrors[j]);
3345 cpl_table_delete(slitss[j]);
3346 cpl_image_delete(mappeds[j]);
3354 cpl_free(instrume); instrume = NULL;
3356 cpl_free(skylocalmaps);
3358 cpl_free(nobjs_per_slit);
3360 if (cpl_error_get_code()) {
3361 cpl_msg_error(cpl_error_get_where(),
"%s", cpl_error_get_message());
3362 fors_pmos_science_exit(NULL);
3380 static float * fors_check_angles(cpl_frameset * frameset,
3381 int pmos,
const char *tag,
int * circ)
3383 float *angles = NULL;
3384 cpl_frame *c_frame = NULL;
3385 char *ret_id = NULL;
3389 angles = cpl_malloc(
sizeof(
float) * pmos);
3391 for (c_frame = cpl_frameset_find(frameset, tag);
3392 c_frame != NULL; c_frame = cpl_frameset_find(frameset, NULL)) {
3394 cpl_propertylist * header =
3395 cpl_propertylist_load(cpl_frame_get_filename(c_frame), 0);
3398 ret_id = cpl_strdup(cpl_propertylist_get_string(header,
3399 "ESO INS OPTI4 ID"));
3401 if (ret_id[1] !=
'5' && ret_id[1] !=
'4') {
3402 cpl_msg_error(cpl_func,
3403 "Unknown retarder plate id: %s", ret_id);
3407 char * c_ret_id = (
char *)
3408 cpl_propertylist_get_string(header,
"ESO INS OPTI4 ID");
3409 if (ret_id[1] != c_ret_id[1]) {
3410 cpl_msg_error(cpl_func,
"Input frames are not from the same "
3416 if (ret_id[1] ==
'5') {
3417 if (cpl_propertylist_has(header,
"ESO INS RETA2 ROT")) {
3418 angles[i] = (float)floor(2*cpl_propertylist_get_double(header,
3419 "ESO INS RETA2 ROT") + 0.5)/2;
3421 else if (cpl_propertylist_has(header,
"ESO INS RETA2 POSANG")) {
3422 if (cpl_propertylist_has(header,
"ESO ADA POSANG")) {
3423 double reta2pos = cpl_propertylist_get_double(header,
3424 "ESO INS RETA2 POSANG");
3425 double adapos = cpl_propertylist_get_double(header,
3427 angles[i] = (float)floor(2*(reta2pos - adapos) + 0.5)/2;
3430 cpl_msg_error(cpl_func,
3431 "ESO ADA POSANG not found in header");
3436 cpl_msg_error(cpl_func,
"Neither ESO INS RETA2 ROT nor "
3437 "ESO INS RETA2 POSANG found in header");
3442 if (cpl_propertylist_has(header,
"ESO INS RETA4 ROT")) {
3443 angles[i] = (float)floor(2*cpl_propertylist_get_double(header,
3444 "ESO INS RETA4 ROT") + 0.5)/2;
3447 angles[i] = angles[i] + 360;
3449 else if (cpl_propertylist_has(header,
"ESO INS RETA4 POSANG")) {
3450 if (cpl_propertylist_has(header,
"ESO ADA POSANG")) {
3451 double reta4pos = cpl_propertylist_get_double(header,
3452 "ESO INS RETA4 POSANG");
3453 double adapos = cpl_propertylist_get_double(header,
3455 angles[i] = (float)floor(2*(reta4pos - adapos) + 0.5/2);
3458 cpl_msg_error(cpl_func,
3459 "ESO ADA POSANG not found in header");
3464 cpl_msg_error(cpl_func,
"Neither ESO INS RETA4 ROT nor "
3465 "ESO INS RETA4 POSANG found in header");
3471 cpl_propertylist_delete(header);
3478 if (pmos != 2 && pmos != 4) {
3479 cpl_msg_error(cpl_func,
"Wrong angle configuration: %d angles "
3480 "found, but either 2 or 4 are required for "
3481 "circular polarization measurements!", pmos);
3485 if (pmos != 4 && pmos != 8 && pmos != 16) {
3486 cpl_msg_error(cpl_func,
"Wrong angle configuration: %d angles "
3487 "found, but either 4, 8, or 16 are required for "
3488 "linear polarization measurements!", pmos);
3496 for (i = 0; i < pmos; i++) {
3497 if (fors_find_angle_pos(angles, pmos, 90.0 * i - 45.0) < 0) {
3498 const char *cangles;
3500 case 2: cangles =
"-45.0, 45.0";
break;
3501 case 4: cangles =
"-45.0, 45.0, 135.0, 225.0";
break;
3505 cpl_msg_error(cpl_func,
"Wrong angle configuration: missing "
3506 "angle %.2f. All angles %s must be provided.",
3507 angles[i], cangles);
3513 for (i = 0; i < pmos; i++) {
3514 if (fors_find_angle_pos(angles, pmos, 22.5 * i) < 0) {
3515 const char *cangles;
3517 case 4: cangles =
"0.0, 22.5, 45.0, 67.5";
break;
3518 case 8: cangles =
"0.0, 22.5, 45.0, 67.5, "
3519 "90.0, 112.5, 135.0, 157.5";
break;
3520 case 16: cangles =
"0.0, 22.5, 45.0, 67.5, "
3521 "90.0, 112.5, 135.0, 157.5, "
3522 "180.0, 202.5, 225.0, 247.5, "
3523 "270.0, 292.5, 315.0, 337.5";
break;
3527 cpl_msg_error(cpl_func,
"Wrong angle configuration: missing "
3528 "angle %.2f. All angles %s must be provided.",
3529 angles[i], cangles);
3548 fors_find_angle_pos(
float * angles,
int nangles,
float angle)
3552 for (i = 0; i < nangles; i++) {
3553 if (fabs(angles[i] - angle) < 1.0 ||
3554 fabs(angles[i] - 360.0 - angle) < 1.0) {
3560 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_error_code fors_qc_write_qc_string(cpl_propertylist *header, const char *name, const char *value, const char *comment, const char *instrument)
Write a string value to the active QC1 PAF object and to a header.
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_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_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_load_slits_fors_mos(cpl_propertylist *header, int *nslits_out_det)
Create slit location table from FITS header of FORS1/2 MOS data.
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.
void fors_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset.
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.
int mos_check_polarisation(cpl_image *q_image, cpl_image *q_error, cpl_image *u_image, cpl_image *u_error, double startwave, double dispersion, double band, cpl_table *pol_sta, double ra, double dec, char *filter, int *polarisation, double *p_offset, double *p_error, double *a_offset, double *a_error)
Estimate linear polarisation parameters on spectral interval.
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_error_code mos_clean_cosmics(cpl_image *image, float gain, float threshold, float ratio)
Remove cosmic rays from sky-subtracted CCD spectral exposure.
cpl_error_code mos_randomise_image(cpl_image *image, double ron, double gain, double bias)
Randomise image.
double dfs_get_parameter_double(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe double parameter value.