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, nscience) \ 114 if ((const char *)message != NULL) cpl_msg_error(recipe, message); \ 115 if(reduceds != NULL) { \ 116 for (j = 0; j < nscience; j++) \ 117 cpl_image_delete(reduceds[j]); \ 119 if(rerrors != NULL) { \ 120 for (j = 0; j < nscience; j++) \ 121 cpl_image_delete(rerrors[j]); \ 123 if(slitss != NULL) { \ 124 for (j = 0; j < nscience; j++) \ 125 cpl_table_delete(slitss[j]); \ 127 if(mappeds != NULL) { \ 128 for (j = 0; j < nscience; j++) \ 129 cpl_image_delete(mappeds[j]); \ 131 if(skylocalmaps != NULL) { \ 132 for (j = 0; j < nscience; j++) \ 133 cpl_image_delete(skylocalmaps[j]); \ 135 cpl_free(reduceds); \ 139 cpl_free(skylocalmaps); \ 140 cpl_free(instrume); \ 141 cpl_image_delete(dummy); \ 142 cpl_image_delete(mapped_sky); \ 143 cpl_image_delete(mapped_cleaned); \ 144 cpl_image_delete(skymap); \ 145 cpl_image_delete(smapped); \ 146 cpl_table_delete(offsets); \ 147 cpl_table_delete(sky); \ 148 cpl_image_delete(bias); \ 149 cpl_image_delete(spectra); \ 150 cpl_image_delete(coordinate); \ 151 cpl_image_delete(norm_flat); \ 152 cpl_image_delete(rainbow); \ 153 cpl_image_delete(rectified); \ 154 cpl_image_delete(wavemap); \ 155 cpl_propertylist_delete(header); \ 156 cpl_propertylist_delete(save_header); \ 157 cpl_table_delete(grism_table); \ 158 cpl_table_delete(idscoeff); \ 159 cpl_table_delete(maskslits); \ 160 cpl_table_delete(overscans); \ 161 cpl_table_delete(polytraces); \ 162 cpl_table_delete(wavelengths); \ 163 cpl_table_delete(mask_science); \ 164 cpl_table_delete(mask_arc); \ 165 cpl_table_delete(mask_flat); \ 166 cpl_vector_delete(lines); \ 167 cpl_msg_indent_less(); \ 172 #define fors_pmos_science_exit_memcheck(message) \ 174 if ((const char *)message != NULL) cpl_msg_info(recipe, message); \ 175 cpl_free(instrume); \ 176 cpl_image_delete(dummy); \ 177 cpl_image_delete(mapped_cleaned); \ 178 cpl_image_delete(mapped_sky); \ 179 cpl_image_delete(skymap); \ 180 cpl_image_delete(smapped); \ 181 cpl_table_delete(offsets); \ 182 cpl_table_delete(sky); \ 183 cpl_image_delete(bias); \ 184 cpl_image_delete(spectra); \ 185 cpl_image_delete(coordinate); \ 186 cpl_image_delete(norm_flat); \ 187 cpl_image_delete(rainbow); \ 188 cpl_image_delete(rectified); \ 189 cpl_image_delete(wavemap); \ 190 cpl_propertylist_delete(header); \ 191 cpl_propertylist_delete(save_header); \ 192 cpl_table_delete(grism_table); \ 193 cpl_table_delete(idscoeff); \ 194 cpl_table_delete(maskslits); \ 195 cpl_table_delete(overscans); \ 196 cpl_table_delete(polytraces); \ 197 cpl_table_delete(wavelengths); \ 198 cpl_table_delete(mask_science); \ 199 cpl_table_delete(mask_arc); \ 200 cpl_table_delete(mask_flat); \ 201 cpl_vector_delete(lines); \ 202 cpl_msg_indent_less(); \ 220 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe );
221 cpl_plugin *plugin = &recipe->interface;
223 cpl_plugin_init(plugin,
226 CPL_PLUGIN_TYPE_RECIPE,
228 "Extraction of scientific spectra",
229 fors_pmos_science_description,
232 "This file is currently part of the FORS Instrument Pipeline\n" 233 "Copyright (C) 2002-2010 European Southern Observatory\n\n" 234 "This program is free software; you can redistribute it and/or modify\n" 235 "it under the terms of the GNU General Public License as published by\n" 236 "the Free Software Foundation; either version 2 of the License, or\n" 237 "(at your option) any later version.\n\n" 238 "This program is distributed in the hope that it will be useful,\n" 239 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" 240 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" 241 "GNU General Public License for more details.\n\n" 242 "You should have received a copy of the GNU General Public License\n" 243 "along with this program; if not, write to the Free Software Foundation,\n" 244 "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n",
245 fors_pmos_science_create,
246 fors_pmos_science_exec,
247 fors_pmos_science_destroy);
249 cpl_pluginlist_append(plist, plugin);
265 static int fors_pmos_science_create(cpl_plugin *plugin)
275 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
276 recipe = (cpl_recipe *)plugin;
284 recipe->parameters = cpl_parameterlist_new();
291 p = cpl_parameter_new_value(
"fors.fors_pmos_science.dispersion",
293 "Expected spectral dispersion (Angstrom/pixel)",
294 "fors.fors_pmos_science",
296 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"dispersion");
297 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
298 cpl_parameterlist_append(recipe->parameters, p);
304 p = cpl_parameter_new_value(
"fors.fors_pmos_science.rebin",
307 "fors.fors_pmos_science",
309 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"rebin");
310 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
311 cpl_parameterlist_append(recipe->parameters, p);
317 p = cpl_parameter_new_value(
"fors.fors_pmos_science.skyalign",
319 "Polynomial order for sky lines alignment, " 320 "or -1 to avoid alignment",
321 "fors.fors_pmos_science",
323 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"skyalign");
324 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
325 cpl_parameterlist_append(recipe->parameters, p);
331 p = cpl_parameter_new_value(
"fors.fors_pmos_science.wcolumn",
333 "Name of sky line catalog table column " 335 "fors.fors_pmos_science",
337 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcolumn");
338 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
339 cpl_parameterlist_append(recipe->parameters, p);
345 p = cpl_parameter_new_value(
"fors.fors_pmos_science.startwavelength",
347 "Start wavelength in spectral extraction",
348 "fors.fors_pmos_science",
350 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"startwavelength");
351 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
352 cpl_parameterlist_append(recipe->parameters, p);
358 p = cpl_parameter_new_value(
"fors.fors_pmos_science.endwavelength",
360 "End wavelength in spectral extraction",
361 "fors.fors_pmos_science",
363 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"endwavelength");
364 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
365 cpl_parameterlist_append(recipe->parameters, p);
371 p = cpl_parameter_new_value(
"fors.fors_pmos_science.flux",
373 "Apply flux conservation",
374 "fors.fors_pmos_science",
376 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"flux");
377 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
378 cpl_parameterlist_append(recipe->parameters, p);
384 p = cpl_parameter_new_value(
"fors.fors_pmos_science.flatfield",
387 "fors.fors_pmos_science",
389 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"flatfield");
390 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
391 cpl_parameterlist_append(recipe->parameters, p);
397 p = cpl_parameter_new_value(
"fors.fors_pmos_science.skymedian",
399 "Sky subtraction from extracted slit spectra",
400 "fors.fors_pmos_science",
402 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"skymedian");
403 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
404 cpl_parameterlist_append(recipe->parameters, p);
410 p = cpl_parameter_new_value(
"fors.fors_pmos_science.skylocal",
412 "Sky subtraction from CCD slit spectra",
413 "fors.fors_pmos_science",
415 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"skylocal");
416 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
417 cpl_parameterlist_append(recipe->parameters, p);
423 p = cpl_parameter_new_value(
"fors.fors_pmos_science.cosmics",
425 "Eliminate cosmic rays hits (only if local " 426 "sky subtraction is also requested)",
427 "fors.fors_pmos_science",
429 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"cosmics");
430 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
431 cpl_parameterlist_append(recipe->parameters, p);
437 p = cpl_parameter_new_value(
"fors.fors_pmos_science.slit_margin",
439 "Number of pixels to exclude at each slit " 440 "in object detection and extraction",
441 "fors.fors_pmos_science",
443 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slit_margin");
444 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
445 cpl_parameterlist_append(recipe->parameters, p);
451 p = cpl_parameter_new_value(
"fors.fors_pmos_science.ext_radius",
453 "Maximum extraction radius for detected " 455 "fors.fors_pmos_science",
457 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ext_radius");
458 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
459 cpl_parameterlist_append(recipe->parameters, p);
465 p = cpl_parameter_new_value(
"fors.fors_pmos_science.cont_radius",
467 "Minimum distance at which two objects " 468 "of equal luminosity do not contaminate " 469 "each other (pixel)",
470 "fors.fors_pmos_science",
472 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"cont_radius");
473 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
474 cpl_parameterlist_append(recipe->parameters, p);
480 p = cpl_parameter_new_value(
"fors.fors_pmos_science.ext_mode",
482 "Object extraction method: 0 = aperture, " 483 "1 = Horne optimal extraction",
484 "fors.fors_pmos_science",
486 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ext_mode");
487 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
488 cpl_parameterlist_append(recipe->parameters, p);
494 p = cpl_parameter_new_value(
"fors.fors_pmos_science.match_tolerance",
496 "Tolerance for matching spectra from the " 497 "same object at different angles and beams " 499 "fors.fors_pmos_science",
501 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"match_tolerance");
502 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
503 cpl_parameterlist_append(recipe->parameters, p);
509 p = cpl_parameter_new_value(
"fors.fors_pmos_science.time_normalise",
511 "Normalise output spectra by the exposure time",
512 "fors.fors_pmos_science",
514 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"time_normalise");
515 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
516 cpl_parameterlist_append(recipe->parameters, p);
522 p = cpl_parameter_new_value(
"fors.fors_pmos_science.chromatism",
524 "Chromatism correction to polarization angles",
525 "fors.fors_pmos_science",
527 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"chromatism");
528 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
529 cpl_parameterlist_append(recipe->parameters, p);
535 p = cpl_parameter_new_value(
"fors.fors_pmos_science.wollaston",
537 "Wollaston mounting (FORS2 only): true = 0 degrees " 538 "(ord. beam on top, extr. beam on bottom), " 539 "false = 180 degrees (beams are reversed), for FORS1 " 541 "fors.fors_pmos_science",
543 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wollaston");
544 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
545 cpl_parameterlist_append(recipe->parameters, p);
551 p = cpl_parameter_new_value(
"fors.fors_pmos_science.qc",
553 "Compute QC1 parameters",
554 "fors.fors_pmos_science",
556 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"qc");
557 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
558 cpl_parameterlist_append(recipe->parameters, p);
572 static int fors_pmos_science_exec(cpl_plugin *plugin)
576 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
577 recipe = (cpl_recipe *)plugin;
581 return fors_pmos_science(recipe->parameters, recipe->frames);
593 static int fors_pmos_science_destroy(cpl_plugin *plugin)
597 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
598 recipe = (cpl_recipe *)plugin;
602 cpl_parameterlist_delete(recipe->parameters);
617 static int fors_pmos_science(cpl_parameterlist *parlist, cpl_frameset *frameset)
620 const char *recipe =
"fors_pmos_science";
631 double startwavelength;
632 double endwavelength;
654 cpl_image **reduceds = NULL;
655 cpl_image **rerrors = NULL;
656 cpl_table **slitss = NULL;
657 cpl_image **mappeds = NULL;
658 cpl_image **skylocalmaps = NULL;
662 cpl_image *bias = NULL;
663 cpl_image *norm_flat = NULL;
664 cpl_image *spectra = NULL;
665 cpl_image *rectified = NULL;
666 cpl_image *coordinate = NULL;
667 cpl_image *rainbow = NULL;
668 cpl_image *mapped = NULL;
669 cpl_image *mapped_sky = NULL;
670 cpl_image *mapped_cleaned = NULL;
671 cpl_image *smapped = NULL;
672 cpl_image *wavemap = NULL;
673 cpl_image *skymap = NULL;
674 cpl_image *skylocalmap = NULL;
675 cpl_image *dummy = NULL;
677 cpl_table *grism_table = NULL;
678 cpl_table *overscans = NULL;
679 cpl_table *wavelengths = NULL;
680 cpl_table *idscoeff = NULL;
681 cpl_table *slits = NULL;
682 cpl_table *origslits = NULL;
683 cpl_table *maskslits = NULL;
684 cpl_table *mask_science = NULL;
685 cpl_table *mask_arc = NULL;
686 cpl_table *mask_flat = NULL;
687 cpl_table *polytraces = NULL;
688 cpl_table *offsets = NULL;
689 cpl_table *sky = NULL;
691 cpl_vector *lines = NULL;
693 cpl_propertylist *header = NULL;
694 cpl_propertylist *save_header = NULL;
701 char *instrume = NULL;
702 const char *science_tag;
703 const char *master_norm_flat_tag;
704 const char *disp_coeff_tag;
705 const char *disp_coeff_sky_tag;
706 const char *wavelength_map_sky_tag;
707 const char *curv_coeff_tag;
708 const char *slit_location_tag;
709 const char *reduced_science_tag;
710 const char *reduced_sky_tag;
711 const char *reduced_error_tag;
712 const char *mapped_science_tag;
713 const char *unmapped_science_tag;
714 const char *mapped_science_sky_tag;
715 const char *mapped_sky_tag;
716 const char *unmapped_sky_tag;
717 const char *object_table_tag;
718 const char *object_table_pol_tag;
719 const char *skylines_offsets_tag;
720 const char *reduced_q_tag;
721 const char *reduced_u_tag;
722 const char *reduced_v_tag;
723 const char *reduced_l_tag;
724 const char *reduced_i_tag;
725 const char *reduced_error_q_tag;
726 const char *reduced_error_u_tag;
727 const char *reduced_error_v_tag;
728 const char *reduced_error_l_tag;
729 const char *reduced_error_i_tag;
730 const char *reduced_nul_q_tag;
731 const char *reduced_nul_u_tag;
732 const char *reduced_nul_v_tag;
733 const char *reduced_angle_tag;
734 const char *reduced_error_angle_tag;
735 const char *chrom_table_tag =
"RETARDER_WAVEPLATE_CHROMATISM";
736 const char *std_pmos_table_tag =
"STD_PMOS_TABLE";
737 const cpl_frame *ref_sci_frame = NULL;
738 float *angles = NULL;
769 int nslits_out_det = 0;
772 cpl_error_code error;
774 snprintf(version, 80,
"%s-%s", PACKAGE, PACKAGE_VERSION);
777 char *montecarlo = getenv(
"MONTECARLO");
780 doit = atoi(montecarlo);
784 cpl_msg_set_indentation(2);
793 cpl_msg_info(recipe,
"Recipe %s configuration parameters:", recipe);
794 cpl_msg_indent_more();
796 if (cpl_frameset_count_tags(frameset,
"GRISM_TABLE") > 1)
797 fors_pmos_science_exit(
"Too many in input: GRISM_TABLE", nscience);
802 "fors.fors_pmos_science.dispersion", grism_table);
804 if (dispersion <= 0.0)
805 fors_pmos_science_exit(
"Invalid spectral dispersion", nscience);
808 "fors.fors_pmos_science.rebin", NULL);
811 fors_pmos_science_exit(
"Invalid rebin factor", nscience);
814 "fors.fors_pmos_science.skyalign", NULL);
817 fors_pmos_science_exit(
"Max polynomial degree for sky alignment is 2", nscience);
820 "fors.fors_pmos_science.wcolumn", NULL);
823 "fors.fors_pmos_science.startwavelength", grism_table);
824 if (startwavelength < 3000.0 || startwavelength > 13000.0)
825 fors_pmos_science_exit(
"Invalid wavelength", nscience);
828 "fors.fors_pmos_science.endwavelength", grism_table);
829 if (endwavelength < 3000.0 || endwavelength > 13000.0)
830 fors_pmos_science_exit(
"Invalid wavelength", nscience);
832 if (endwavelength - startwavelength <= 0.0)
833 fors_pmos_science_exit(
"Invalid wavelength interval", nscience);
838 "fors.fors_pmos_science.flatfield",
842 "fors.fors_pmos_science.skylocal",
845 "fors.fors_pmos_science.skymedian",
849 "fors.fors_pmos_science.chromatism",
853 "fors.fors_pmos_science.wollaston",
856 wollaston = wollaston ? 0 : 1;
858 if (skylocal && skymedian)
859 fors_pmos_science_exit(
"Cannot apply sky subtraction both on " 860 "extracted and non-extracted spectra", nscience);
863 "fors.fors_pmos_science.cosmics", NULL);
867 fors_pmos_science_exit(
"Cosmic rays correction requires " 868 "skylocal=true", nscience);
871 "fors.fors_pmos_science.slit_margin",
874 fors_pmos_science_exit(
"Value must be zero or positive", nscience);
877 "fors.fors_pmos_science.ext_radius",
880 fors_pmos_science_exit(
"Value must be zero or positive", nscience);
883 "fors.fors_pmos_science.cont_radius",
886 fors_pmos_science_exit(
"Value must be zero or positive", nscience);
890 if (ext_mode < 0 || ext_mode > 1)
891 fors_pmos_science_exit(
"Invalid object extraction mode", nscience);
894 "fors.fors_pmos_science.match_tolerance", NULL);
895 if (tolerance <= 0.0)
896 fors_pmos_science_exit(
"Invalid object match tolerance", nscience);
899 "fors.fors_pmos_science.time_normalise", NULL);
903 cpl_table_delete(grism_table); grism_table = NULL;
905 if (cpl_error_get_code())
906 fors_pmos_science_exit(
"Failure getting the configuration parameters",nscience);
913 cpl_msg_indent_less();
914 cpl_msg_info(recipe,
"Check input set-of-frames:");
915 cpl_msg_indent_more();
918 cpl_frameset *subframeset = cpl_frameset_duplicate(frameset);
919 cpl_frameset_erase(subframeset,
"MASTER_BIAS");
922 cpl_msg_warning(cpl_func,
"Input frames are not from the same grism");
925 cpl_msg_warning(cpl_func,
"Input frames are not from the same filter");
928 cpl_msg_warning(cpl_func,
"Input frames are not from the same chip");
930 cpl_frameset_delete(subframeset);
934 pmos = cpl_frameset_count_tags(frameset,
"SCIENCE_PMOS");
937 pmos = cpl_frameset_count_tags(frameset,
"STANDARD_PMOS");
942 fors_pmos_science_exit(
"Missing input scientific frame", nscience);
944 angles = fors_check_angles(frameset, pmos,
945 standard ?
"STANDARD_PMOS" :
"SCIENCE_PMOS",
948 fors_pmos_science_exit(
"Polarization angles could not be read", nscience);
957 reduceds = (cpl_image **)cpl_malloc(
sizeof(cpl_image *) * nscience);
958 rerrors = (cpl_image **)cpl_malloc(
sizeof(cpl_image *) * nscience);
959 slitss = (cpl_table **)cpl_malloc(
sizeof(cpl_table *) * nscience);
960 mappeds = (cpl_image **)cpl_malloc(
sizeof(cpl_image *) * nscience);
961 skylocalmaps = (cpl_image **)cpl_malloc(
sizeof(cpl_image *) * nscience);
964 cpl_msg_info(recipe,
"PMOS data found");
966 science_tag =
"STANDARD_PMOS";
967 reduced_science_tag =
"REDUCED_STD_PMOS";
968 unmapped_science_tag =
"UNMAPPED_STD_PMOS";
969 mapped_science_tag =
"MAPPED_STD_PMOS";
970 mapped_science_sky_tag =
"MAPPED_ALL_STD_PMOS";
971 skylines_offsets_tag =
"SKY_SHIFTS_SLIT_STD_PMOS";
972 wavelength_map_sky_tag =
"WAVELENGTH_MAP_STD_PMOS";
973 disp_coeff_sky_tag =
"DISP_COEFF_STD_PMOS";
974 mapped_sky_tag =
"MAPPED_SKY_STD_PMOS";
975 unmapped_sky_tag =
"UNMAPPED_SKY_STD_PMOS";
976 object_table_tag =
"OBJECT_TABLE_STD_PMOS";
977 object_table_pol_tag =
"OBJECT_TABLE_POL_STD_PMOS";
978 reduced_sky_tag =
"REDUCED_SKY_STD_PMOS";
979 reduced_error_tag =
"REDUCED_ERROR_STD_PMOS";
980 reduced_q_tag =
"REDUCED_Q_STD_PMOS";
981 reduced_u_tag =
"REDUCED_U_STD_PMOS";
982 reduced_v_tag =
"REDUCED_V_STD_PMOS";
983 reduced_l_tag =
"REDUCED_L_STD_PMOS";
984 reduced_i_tag =
"REDUCED_I_STD_PMOS";
985 reduced_error_q_tag =
"REDUCED_ERROR_Q_STD_PMOS";
986 reduced_error_u_tag =
"REDUCED_ERROR_U_STD_PMOS";
987 reduced_error_v_tag =
"REDUCED_ERROR_V_STD_PMOS";
988 reduced_error_l_tag =
"REDUCED_ERROR_L_STD_PMOS";
989 reduced_error_i_tag =
"REDUCED_ERROR_I_STD_PMOS";
990 reduced_nul_q_tag =
"REDUCED_NUL_Q_STD_PMOS";
991 reduced_nul_u_tag =
"REDUCED_NUL_U_STD_PMOS";
992 reduced_nul_v_tag =
"REDUCED_NUL_V_STD_PMOS";
993 reduced_angle_tag =
"REDUCED_ANGLE_STD_PMOS";
994 reduced_error_angle_tag =
"REDUCED_ERROR_ANGLE_STD_PMOS";
997 science_tag =
"SCIENCE_PMOS";
998 reduced_science_tag =
"REDUCED_SCI_PMOS";
999 unmapped_science_tag =
"UNMAPPED_SCI_PMOS";
1000 mapped_science_tag =
"MAPPED_SCI_PMOS";
1001 mapped_science_sky_tag =
"MAPPED_ALL_SCI_PMOS";
1002 skylines_offsets_tag =
"SKY_SHIFTS_SLIT_SCI_PMOS";
1003 wavelength_map_sky_tag =
"WAVELENGTH_MAP_SCI_PMOS";
1004 disp_coeff_sky_tag =
"DISP_COEFF_SCI_PMOS";
1005 mapped_sky_tag =
"MAPPED_SKY_SCI_PMOS";
1006 unmapped_sky_tag =
"UNMAPPED_SKY_SCI_PMOS";
1007 object_table_tag =
"OBJECT_TABLE_SCI_PMOS";
1008 object_table_pol_tag =
"OBJECT_TABLE_POL_SCI_PMOS";
1009 reduced_sky_tag =
"REDUCED_SKY_SCI_PMOS";
1010 reduced_error_tag =
"REDUCED_ERROR_SCI_PMOS";
1011 reduced_q_tag =
"REDUCED_Q_SCI_PMOS";
1012 reduced_u_tag =
"REDUCED_U_SCI_PMOS";
1013 reduced_v_tag =
"REDUCED_V_SCI_PMOS";
1014 reduced_l_tag =
"REDUCED_L_SCI_PMOS";
1015 reduced_i_tag =
"REDUCED_I_SCI_PMOS";
1016 reduced_error_q_tag =
"REDUCED_ERROR_Q_SCI_PMOS";
1017 reduced_error_u_tag =
"REDUCED_ERROR_U_SCI_PMOS";
1018 reduced_error_v_tag =
"REDUCED_ERROR_V_SCI_PMOS";
1019 reduced_error_l_tag =
"REDUCED_ERROR_L_SCI_PMOS";
1020 reduced_error_i_tag =
"REDUCED_ERROR_I_SCI_PMOS";
1021 reduced_nul_q_tag =
"REDUCED_NUL_Q_SCI_PMOS";
1022 reduced_nul_u_tag =
"REDUCED_NUL_U_SCI_PMOS";
1023 reduced_nul_v_tag =
"REDUCED_NUL_V_SCI_PMOS";
1024 reduced_angle_tag =
"REDUCED_ANGLE_SCI_PMOS";
1025 reduced_error_angle_tag =
"REDUCED_ERROR_ANGLE_SCI_PMOS";
1028 master_norm_flat_tag =
"MASTER_NORM_FLAT_PMOS";
1029 disp_coeff_tag =
"DISP_COEFF_PMOS";
1030 curv_coeff_tag =
"CURV_COEFF_PMOS";
1031 slit_location_tag =
"SLIT_LOCATION_PMOS";
1033 if (!cpl_frameset_count_tags(frameset, master_norm_flat_tag)) {
1034 master_norm_flat_tag =
"MASTER_NORM_FLAT_LONG_PMOS";
1035 disp_coeff_tag =
"DISP_COEFF_LONG_PMOS";
1036 slit_location_tag =
"SLIT_LOCATION_LONG_PMOS";
1040 if (cpl_frameset_count_tags(frameset,
"MASTER_BIAS") == 0)
1041 fors_pmos_science_exit(
"Missing required input: MASTER_BIAS", nscience);
1043 if (cpl_frameset_count_tags(frameset,
"MASTER_BIAS") > 1)
1044 fors_pmos_science_exit(
"Too many in input: MASTER_BIAS", nscience);
1047 if (cpl_frameset_count_tags(frameset,
"MASTER_SKYLINECAT") > 1)
1048 fors_pmos_science_exit(
"Too many in input: MASTER_SKYLINECAT", nscience);
1050 if (cpl_frameset_count_tags(frameset, disp_coeff_tag) == 0) {
1051 cpl_msg_error(recipe,
"Missing required input: %s", disp_coeff_tag);
1052 fors_pmos_science_exit(NULL, nscience);
1055 if (cpl_frameset_count_tags(frameset, disp_coeff_tag) > 1) {
1056 cpl_msg_error(recipe,
"Too many in input: %s", disp_coeff_tag);
1057 fors_pmos_science_exit(NULL, nscience);
1060 if (cpl_frameset_count_tags(frameset, slit_location_tag) == 0) {
1061 cpl_msg_error(recipe,
"Missing required input: %s",
1063 fors_pmos_science_exit(NULL, nscience);
1066 if (cpl_frameset_count_tags(frameset, slit_location_tag) > 1) {
1067 cpl_msg_error(recipe,
"Too many in input: %s", slit_location_tag);
1068 fors_pmos_science_exit(NULL, nscience);
1072 if (cpl_frameset_count_tags(frameset, chrom_table_tag) == 0) {
1073 cpl_msg_error(recipe,
"Missing required input: %s",
1075 fors_pmos_science_exit(NULL, nscience);
1078 if (cpl_frameset_count_tags(frameset, chrom_table_tag) > 1) {
1079 cpl_msg_error(recipe,
"Too many in input: %s", chrom_table_tag);
1080 fors_pmos_science_exit(NULL, nscience);
1084 if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) > 1) {
1086 cpl_msg_error(recipe,
"Too many in input: %s",
1087 master_norm_flat_tag);
1088 fors_pmos_science_exit(NULL, nscience);
1091 cpl_msg_warning(recipe,
"%s in input are 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) == 1) {
1099 cpl_msg_warning(recipe,
"%s in input is ignored, " 1100 "since flat field correction was not requested",
1101 master_norm_flat_tag);
1105 if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) == 0) {
1107 cpl_msg_error(recipe,
"Flat field correction was requested, " 1108 "but no %s are found in input",
1109 master_norm_flat_tag);
1110 fors_pmos_science_exit(NULL, nscience);
1115 if (cpl_frameset_count_tags(frameset, std_pmos_table_tag) > 1) {
1116 cpl_msg_error(recipe,
"Too many in input: %s", std_pmos_table_tag);
1117 fors_pmos_science_exit(NULL, nscience);
1121 if (cpl_frameset_count_tags(frameset, std_pmos_table_tag) == 0) {
1122 cpl_msg_error(recipe,
"QC computation was requested, but no " 1123 "%s is found in input", std_pmos_table_tag);
1124 fors_pmos_science_exit(NULL, nscience);
1129 cpl_msg_indent_less();
1131 ref_sci_frame = cpl_frameset_find_const(frameset, science_tag);
1142 fors_pmos_science_exit(
"Cannot load scientific frame header", nscience);
1144 instrume = (
char *)cpl_propertylist_get_string(header,
"INSTRUME");
1145 if (instrume == NULL)
1146 fors_pmos_science_exit(
"Missing keyword INSTRUME in scientific header", nscience);
1147 instrume = cpl_strdup(instrume);
1149 if (instrume[4] ==
'1')
1150 snprintf(version, 80,
"%s/%s",
"fors1", VERSION);
1151 if (instrume[4] ==
'2')
1152 snprintf(version, 80,
"%s/%s",
"fors2", VERSION);
1154 reference = cpl_propertylist_get_double(header,
"ESO INS GRIS1 WLEN");
1156 if (cpl_error_get_code() != CPL_ERROR_NONE)
1157 fors_pmos_science_exit(
"Missing keyword ESO INS GRIS1 WLEN in scientific " 1158 "frame header", nscience);
1160 if (reference < 3000.0)
1163 if (reference < 3000.0 || reference > 13000.0) {
1164 cpl_msg_error(recipe,
"Invalid central wavelength %.2f read from " 1165 "keyword ESO INS GRIS1 WLEN in scientific frame header",
1167 fors_pmos_science_exit(NULL, nscience);
1170 cpl_msg_info(recipe,
"The central wavelength is: %.2f", reference);
1172 rebin = cpl_propertylist_get_int(header,
"ESO DET WIN1 BINX");
1174 if (cpl_error_get_code() != CPL_ERROR_NONE)
1175 fors_pmos_science_exit(
"Missing keyword ESO DET WIN1 BINX in " 1176 "scientific frame header", nscience);
1179 dispersion *= rebin;
1180 cpl_msg_warning(recipe,
"The rebin factor is %d, and therefore the " 1181 "spectral dispersion used is %f A/pixel", rebin,
1183 ext_radius /= rebin;
1184 cpl_msg_warning(recipe,
"The rebin factor is %d, and therefore the " 1185 "extraction radius used is %d pixel", rebin,
1189 gain = cpl_propertylist_get_double(header,
"ESO DET OUT1 CONAD");
1191 if (cpl_error_get_code() != CPL_ERROR_NONE)
1192 fors_pmos_science_exit(
"Missing keyword ESO DET OUT1 CONAD in " 1193 "scientific frame header", nscience);
1195 cpl_msg_info(recipe,
"The gain factor is: %.2f e-/ADU", gain);
1197 ron = cpl_propertylist_get_double(header,
"ESO DET OUT1 RON");
1199 if (cpl_error_get_code() != CPL_ERROR_NONE)
1200 fors_pmos_science_exit(
"Missing keyword ESO DET OUT1 RON in " 1201 "scientific frame header", nscience);
1205 cpl_msg_info(recipe,
"The read-out-noise is: %.2f ADU", ron);
1207 if (cpl_frameset_count_tags(frameset, curv_coeff_tag) == 0) {
1208 cpl_msg_error(recipe,
"Missing required input: %s", curv_coeff_tag);
1209 fors_pmos_science_exit(NULL, nscience);
1212 if (cpl_frameset_count_tags(frameset, curv_coeff_tag) > 1) {
1213 cpl_msg_error(recipe,
"Too many in input: %s", curv_coeff_tag);
1214 fors_pmos_science_exit(NULL, nscience);
1217 cpl_msg_info(recipe,
"Load normalised flat field (if present)...");
1218 cpl_msg_indent_more();
1222 CPL_TYPE_FLOAT, 0, 1);
1225 if (skyalign >= 0) {
1227 cpl_msg_indent_less();
1228 cpl_msg_info(recipe,
"Load input sky line catalog...");
1229 cpl_msg_indent_more();
1238 nlines = cpl_table_get_nrow(wavelengths);
1241 fors_pmos_science_exit(
"Empty input sky line catalog", nscience);
1243 if (cpl_table_has_column(wavelengths, wcolumn) != 1) {
1244 cpl_msg_error(recipe,
"Missing column %s in input line " 1245 "catalog table", wcolumn);
1246 fors_pmos_science_exit(NULL, nscience);
1249 line = cpl_malloc(nlines *
sizeof(
double));
1251 for (i = 0; i < nlines; i++)
1252 line[i] = cpl_table_get(wavelengths, wcolumn, i, NULL);
1254 cpl_table_delete(wavelengths); wavelengths = NULL;
1256 lines = cpl_vector_wrap(nlines, line);
1259 cpl_msg_info(recipe,
"No sky line catalog found in input - fine!");
1270 cpl_propertylist_delete(header); header = NULL;
1272 cpl_table_name_column(mask_science,
"xtop",
"science");
1280 if (idscoeff == NULL)
1281 fors_pmos_science_exit(
"Cannot load wavelength calibration table", nscience);
1292 cpl_propertylist_delete(header); header = NULL;
1294 if (cpl_table_move_column(mask_science,
"xtop", mask_arc)) {
1296 cpl_msg_warning(recipe,
1297 "Slit configuration of science and arc differs!");
1298 cpl_table_delete(mask_arc); mask_arc = NULL;
1301 cpl_table_name_column(mask_science,
"xtop",
"arc");
1302 cpl_table_delete(mask_arc); mask_arc = NULL;
1315 cpl_propertylist_delete(header); header = NULL;
1317 if (cpl_table_move_column(mask_science,
"xtop", mask_flat)) {
1319 cpl_msg_warning(recipe,
1320 "Slit configuration of science and flat differs!");
1321 cpl_table_delete(mask_flat); mask_flat = NULL;
1324 cpl_table_name_column(mask_science,
"xtop",
"flat");
1325 cpl_table_delete(mask_flat); mask_flat = NULL;
1328 cpl_table_duplicate_column(mask_science,
"diff", mask_science,
"science");
1329 cpl_table_subtract_columns(mask_science,
"diff",
"arc");
1330 cpl_table_abs_column(mask_science,
"diff");
1332 if (cpl_table_get_column_max(mask_science,
"diff") > 0.01) {
1333 cpl_msg_warning(recipe,
1334 "Slit configuration of science and arc differs!");
1339 cpl_table_erase_column(mask_science,
"diff");
1341 cpl_table_duplicate_column(mask_science,
"diff",
1342 mask_science,
"science");
1343 cpl_table_subtract_columns(mask_science,
"diff",
"flat");
1344 cpl_table_abs_column(mask_science,
"diff");
1346 if (cpl_table_get_column_max(mask_science,
"diff") > 0.01) {
1347 cpl_msg_warning(recipe,
1348 "Slit configuration of science and flat differs!");
1355 cpl_table_delete(mask_science); mask_science = NULL;
1357 for (j = 0; j < nscience; j++) {
1360 cpl_msg_indent_less();
1361 cpl_msg_info(recipe,
"Processing scientific exposure of angle %.2f " 1362 "(%d out of %d) ...",
1363 angles[j], j + 1, nscience);
1364 cpl_msg_indent_more();
1366 cpl_msg_info(recipe,
"Load scientific exposure...");
1367 cpl_msg_indent_more();
1378 for (k = 0; k < j; k ++) {
1379 cpl_propertylist_delete(header);
1383 spectra =
dfs_load_image(frameset, science_tag, CPL_TYPE_FLOAT, 0, 0);
1385 for (k = 0; k < j; k ++) {
1386 cpl_image_delete(spectra);
1390 if (spectra == NULL)
1391 fors_pmos_science_exit(
"Cannot load scientific frame", nscience);
1394 fors_pmos_science_exit(
"Cannot load scientific frame header", nscience);
1396 alltime = cpl_propertylist_get_double(header,
"EXPTIME");
1398 if (cpl_error_get_code() != CPL_ERROR_NONE)
1399 fors_pmos_science_exit(
"Missing keyword EXPTIME in scientific " 1400 "frame header", nscience);
1402 cpl_msg_info(recipe,
"Scientific frame exposure time: %.2f s",
1405 ra = cpl_propertylist_get_double(header,
"RA");
1406 dec = cpl_propertylist_get_double(header,
"DEC");
1408 if (cpl_error_get_code() != CPL_ERROR_NONE)
1409 fors_pmos_science_exit(
"Missing keywords RA and DEC in scientific " 1410 "frame header", nscience);
1414 cpl_msg_indent_less();
1420 cpl_msg_info(recipe,
"Remove the master bias...");
1422 bias =
dfs_load_image(frameset,
"MASTER_BIAS", CPL_TYPE_FLOAT, 0, 1);
1425 fors_pmos_science_exit(
"Cannot load master bias", nscience);
1429 blevel = cpl_image_get_mean(bias);
1433 overscans = mos_load_overscans_fors(header);
1436 cpl_image_delete(spectra); spectra = dummy; dummy = NULL;
1437 cpl_image_delete(bias); bias = NULL;
1438 cpl_table_delete(overscans); overscans = NULL;
1440 if (spectra == NULL)
1441 fors_pmos_science_exit(
"Cannot remove bias from scientific frame", nscience);
1446 cpl_msg_info(recipe,
"Apply flat field correction...");
1447 if (cpl_image_divide(spectra, norm_flat) != CPL_ERROR_NONE) {
1448 cpl_msg_error(recipe,
1449 "Failure of flat field correction: %s",
1450 cpl_error_get_message());
1451 fors_pmos_science_exit(NULL, nscience);
1455 cpl_msg_error(recipe,
"Cannot load input %s for flat field " 1456 "correction", master_norm_flat_tag);
1457 fors_pmos_science_exit(NULL, nscience);
1467 if (polytraces == NULL)
1468 fors_pmos_science_exit(
"Cannot load spectral curvature table", nscience);
1476 fors_pmos_science_exit(
"Cannot load slits location table", nscience);
1478 cpl_msg_info(recipe,
"Processing scientific spectra...");
1485 coordinate = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1488 reference, startwavelength,
1489 endwavelength, dispersion,
1500 if (dispersion > 1.0)
1505 if (skyalign >= 0) {
1507 cpl_msg_info(recipe,
1508 "Align wavelength solution to reference skylines " 1509 "applying %d order residual fit...", skyalign);
1512 cpl_msg_info(recipe,
"Align wavelength solution to reference " 1513 "skylines applying median offset...");
1518 startwavelength, endwavelength,
1519 idscoeff, lines, highres,
1520 skyalign, rainbow, 4);
1523 cpl_msg_warning(recipe,
"Alignment of the wavelength " 1524 "solution to reference sky lines may " 1525 "be unreliable in this case!");
1528 skylines_offsets_tag, NULL,
1529 parlist, recipe, ref_sci_frame);
1530 if(cpl_error_get_code() != CPL_ERROR_NONE)
1531 fors_pmos_science_exit(NULL, nscience);
1534 cpl_msg_warning(recipe,
"Alignment of the wavelength " 1535 "solution to reference sky lines could " 1545 polytraces, reference,
1546 startwavelength, endwavelength,
1550 cpl_image_delete(rainbow); rainbow = NULL;
1551 cpl_image_delete(coordinate); coordinate = NULL;
1559 startwavelength, endwavelength,
1560 dispersion, idscoeff, flux);
1563 cpl_msg_indent_less();
1564 cpl_msg_info(recipe,
1565 "Check applied wavelength against skylines...");
1566 cpl_msg_indent_more();
1569 dispersion, 6, highres);
1572 cpl_msg_info(recipe,
"Mean residual: %f", mean_rms);
1574 mean_rms = cpl_table_get_column_mean(idscoeff,
"error");
1576 cpl_msg_info(recipe,
"Mean model accuracy: %f pixel (%f A)",
1577 mean_rms, mean_rms * dispersion);
1580 save_header = cpl_propertylist_duplicate(header);
1582 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
1583 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
1584 cpl_propertylist_update_double(header,
"CRVAL1",
1585 startwavelength + dispersion/2);
1586 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
1587 cpl_propertylist_update_double(header,
"CD1_1", dispersion);
1588 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
1589 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
1590 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
1591 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
1592 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
1594 if (time_normalise) {
1595 dummy = cpl_image_divide_scalar_create(mapped_sky, alltime);
1599 mapped_science_sky_tag,
1601 fors_pmos_science_exit(NULL, nscience);
1606 fors_pmos_science_exit(NULL, nscience);
1609 cpl_image_delete(dummy); dummy = NULL;
1615 mapped_science_sky_tag,
1617 fors_pmos_science_exit(NULL, nscience);
1622 mapped_science_sky_tag, header)) {
1623 fors_pmos_science_exit(NULL, nscience);
1628 if (skymedian == 0 && skylocal == 0) {
1629 cpl_image_delete(mapped_sky); mapped_sky = NULL;
1634 cpl_msg_indent_less();
1636 cpl_msg_info(recipe,
"Local sky determination...");
1637 cpl_msg_indent_more();
1639 startwavelength, endwavelength, dispersion);
1643 cpl_image_divide_scalar(skymap, alltime);
1649 fors_pmos_science_exit(NULL, nscience);
1655 fors_pmos_science_exit(NULL, nscience);
1658 cpl_image_delete(skymap); skymap = NULL;
1662 unmapped_science_tag,
1664 fors_pmos_science_exit(NULL, nscience);
1670 fors_pmos_science_exit(NULL, nscience);
1674 cpl_msg_info(recipe,
"Removing cosmic rays...");
1683 cpl_image_delete(smapped); smapped = NULL;
1686 reference, startwavelength,
1687 endwavelength, dispersion,
1691 cpl_msg_warning(recipe,
"Sky subtraction failure");
1693 cpl_msg_warning(recipe,
1694 "Cosmic rays removal not performed!");
1695 cosmics = skylocal = 0;
1699 cpl_image_delete(spectra); spectra = NULL;
1700 cpl_table_delete(polytraces); polytraces = NULL;
1702 if (skyalign >= 0) {
1707 wavelength_map_sky_tag,
1709 fors_pmos_science_exit(NULL, nscience);
1715 fors_pmos_science_exit(NULL, nscience);
1719 cpl_image_delete(wavemap); wavemap = NULL;
1722 startwavelength, endwavelength,
1723 dispersion, idscoeff, flux);
1725 cpl_image_delete(smapped); smapped = NULL;
1727 if (skyalign >= 0) {
1730 NULL, parlist, recipe, ref_sci_frame);
1731 if(cpl_error_get_code() != CPL_ERROR_NONE)
1732 fors_pmos_science_exit(NULL, nscience);
1737 cpl_msg_indent_less();
1738 cpl_msg_info(recipe,
"Local sky determination...");
1739 cpl_msg_indent_more();
1742 cpl_image_subtract(mapped, skylocalmap);
1743 cpl_image_delete(skylocalmap); skylocalmap = NULL;
1746 if (skymedian || skylocal) {
1748 skylocalmap = cpl_image_subtract_create(mapped_sky, mapped);
1750 cpl_image_delete(mapped_sky); mapped_sky = NULL;
1752 if (time_normalise) {
1753 dummy = cpl_image_divide_scalar_create(skylocalmap, alltime);
1759 fors_pmos_science_exit(NULL, nscience);
1765 fors_pmos_science_exit(NULL, nscience);
1768 cpl_image_delete(dummy); dummy = NULL;
1775 fors_pmos_science_exit(NULL, nscience);
1781 fors_pmos_science_exit(NULL, nscience);
1785 skylocalmaps[j] = skylocalmap;
1787 cpl_msg_indent_less();
1788 cpl_msg_info(recipe,
"Object detection...");
1789 cpl_msg_indent_more();
1792 origslits = cpl_table_duplicate(slits);
1793 nslits = cpl_table_get_nrow(slits);
1796 if (cosmics || nscience > 1) {
1798 ext_radius, cont_radius);
1801 mapped_cleaned = cpl_image_duplicate(mapped);
1804 ext_radius, cont_radius);
1806 cpl_image_delete(mapped_cleaned); mapped_cleaned = NULL;
1809 cpl_image_delete(dummy); dummy = NULL;
1814 mappeds[j] = mapped;
1816 cpl_msg_indent_less();
1818 cpl_propertylist_delete(header); header = NULL;
1819 cpl_propertylist_delete(save_header); save_header = NULL;
1822 cpl_table_delete(offsets); offsets = NULL;
1823 cpl_table_delete(idscoeff); idscoeff = NULL;
1825 cpl_image_delete(norm_flat); norm_flat = NULL;
1826 cpl_vector_delete(lines); lines = NULL;
1829 cpl_msg_indent_less();
1830 cpl_msg_info(recipe,
1831 "Check object detection in both beams for all angles...");
1832 cpl_msg_indent_more();
1840 if (error == CPL_ERROR_DATA_NOT_FOUND) {
1841 cpl_msg_warning(recipe,
"No objects found: no Stokes " 1842 "parameters to compute!");
1843 for (j = 0; j < nscience; j++)
1844 cpl_table_delete(slitss[j]);
1846 cpl_table_delete(origslits);
1849 fors_pmos_science_exit(
"Problem in polarimetric object selection", nscience);
1853 NULL, parlist, recipe, ref_sci_frame);
1854 if(cpl_error_get_code() != CPL_ERROR_NONE)
1855 fors_pmos_science_exit(NULL, nscience);
1862 for (j = 0; j < nscience; j++) {
1866 fors_pmos_science_exit(NULL, nscience);
1871 fors_pmos_science_exit(NULL, nscience);
1875 nobjs_per_slit = fors_get_nobjs_perslit(origslits);
1877 cpl_msg_indent_less();
1878 cpl_msg_info(recipe,
"Object extraction...");
1879 cpl_msg_indent_more();
1881 for (j = 0; j < nscience; j++) {
1886 for (k = 0; k < j; k ++) {
1887 cpl_propertylist_delete(header);
1891 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
1892 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
1893 cpl_propertylist_update_double(header,
"CRVAL1",
1894 startwavelength + (dispersion * group)/2);
1895 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
1896 cpl_propertylist_update_double(header,
"CD1_1", dispersion * group);
1897 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
1898 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
1899 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
1900 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
1901 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
1903 if (skymedian || skylocal) {
1905 cpl_msg_info(recipe,
"Extracting at angle %.2f (%d out of %d) ...",
1906 angles[j], j + 1, nscience);
1910 ext_mode, ron, gain, 1);
1912 cpl_image_delete(skylocalmaps[j]); skylocalmaps[j] = NULL;
1916 cpl_image_divide_scalar(images[0], alltime);
1918 mos_rebin_signal(images, group);
1922 reduced_science_tag,
1924 fors_pmos_science_exit(NULL, nscience);
1930 fors_pmos_science_exit(NULL, nscience);
1933 reduceds[j] = images[0];
1936 cpl_image_divide_scalar(images[1], alltime);
1938 mos_rebin_signal(images + 1, group);
1944 fors_pmos_science_exit(NULL, nscience);
1950 fors_pmos_science_exit(NULL, nscience);
1952 cpl_image_delete(images[1]);
1955 cpl_image_divide_scalar(images[2], alltime);
1957 mos_rebin_error(images + 2, group);
1963 fors_pmos_science_exit(NULL, nscience);
1969 fors_pmos_science_exit(NULL, nscience);
1972 rerrors[j] = images[2];
1977 cpl_msg_warning(recipe,
"No objects found: the products " 1978 "%s, %s, and %s are not created",
1979 reduced_science_tag, reduced_sky_tag,
1985 if (skymedian || skylocal) {
1987 cpl_image_divide_scalar(mappeds[j], alltime);
1993 fors_pmos_science_exit(NULL, nscience);
1999 fors_pmos_science_exit(NULL, nscience);
2003 cpl_image_delete(mappeds[j]); mappeds[j] = NULL;
2004 cpl_propertylist_delete(header); header = NULL;
2008 cpl_table_delete(origslits);
2012 nobjects = cpl_image_get_size_y(reduceds[0]) / 2;
2013 nx = cpl_image_get_size_x(reduceds[0]);
2015 header = cpl_propertylist_new();
2016 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
2017 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
2018 cpl_propertylist_update_double(header,
"CRVAL1",
2019 startwavelength + (dispersion * group)/2);
2020 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
2021 cpl_propertylist_update_double(header,
"CD1_1", dispersion * group);
2022 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
2023 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
2024 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
2025 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
2026 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
2030 cpl_image *pv_im = NULL;
2031 cpl_image *pi_im = NULL;
2032 cpl_image *pvnull_im = NULL;
2033 cpl_image *pierr_im = NULL;
2034 cpl_image *perr_im = NULL;
2038 double *p_vnull = NULL;
2039 double *perr = NULL;
2040 double *pierr = NULL;
2047 pv_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2048 perr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2049 pi_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2050 pierr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2052 p_v = cpl_image_get_data_double(pv_im);
2053 perr = cpl_image_get_data_double(perr_im);
2054 p_i = cpl_image_get_data_double(pi_im);
2055 pierr = cpl_image_get_data_double(pierr_im);
2057 if (nscience / 2 > 1) {
2058 pvnull_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2059 p_vnull = cpl_image_get_data_double(pvnull_im);
2062 for (j = 0; j < nobjects; j++) {
2069 double * ip_v, * ip_i, * ipierr,
2070 * ip_vnull, * iperr;
2073 float * iff, * ierr;
2075 ip_v = p_v + (nobjects - 1 - j) * nx;
2077 if (nscience / 2 > 1)
2078 ip_vnull = p_vnull + (nobjects - 1 - j) * nx;
2080 iperr = perr + (nobjects - 1 - j) * nx;
2082 ip_i = p_i + (nobjects - 1 - j) * nx;
2083 ipierr = pierr + (nobjects - 1 - j) * nx;
2086 for (i = 0; i < nslits; i += 2) {
2087 total += nobjs_per_slit[i];
2094 for (
int k = 0; k < nscience / 2; k++) {
2095 float *if_o, *if_e, *ifdelta_o, *ifdelta_e;
2096 float *if_o_err, *if_e_err, *ifdelta_o_err, *ifdelta_e_err;
2098 int pos = fors_find_angle_pos(angles, nscience, 180 * k - 45);
2099 int pos_d = fors_find_angle_pos(angles, nscience, 180 * k + 45);
2102 data = cpl_image_get_data_float(reduceds[pos]);
2104 if_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2105 + (total - j - 1)) * nx;
2107 if_e = data + (2 * (nobjects - total)
2108 + (total - j - 1)) * nx;
2110 data = cpl_image_get_data_float(reduceds[pos_d]);
2112 ifdelta_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2113 + (total - j - 1)) * nx;
2115 ifdelta_e = data + (2 * (nobjects - total)
2116 + (total - j - 1)) * nx;
2118 data = cpl_image_get_data_float(rerrors[pos]);
2121 + (2 * (nobjects - total) + nobjs_per_slit[p]
2122 + (total - j - 1)) * nx;
2124 if_e_err = data + (2 * (nobjects - total)
2125 + (total - j - 1)) * nx;
2127 data = cpl_image_get_data_float(rerrors[pos_d]);
2129 ifdelta_o_err = data
2130 + (2 * (nobjects - total) + nobjs_per_slit[p]
2131 + (total - j - 1)) * nx;
2133 ifdelta_e_err = data + (2 * (nobjects - total)
2134 + (total - j - 1)) * nx;
2138 char *signal_to_noise = getenv(
"SIGNAL_TO_NOISE" );
2140 char *min_s2n = getenv(
"MIN_S2N" );
2143 if (signal_to_noise)
2144 s2n = atof(signal_to_noise);
2147 ms2n = atoi(min_s2n);
2156 for (m = 0; m < nx; m++) {
2157 if (if_o_err[m] > 0.0) {
2158 if (if_o[m]/if_o_err[m] > s2n) {
2160 if (bright > ms2n) {
2168 if (bright > ms2n) {
2170 filename = cpl_sprintf(
"angle_%d_%d.dat",
2172 file = fopen(filename,
"w");
2174 fprintf(file,
"%d\n", p + 2);
2176 for (m = 0; m < nx; m++) {
2177 double lambda = startwavelength
2178 + dispersion * group * (0.5 + m);
2179 fprintf(file,
"%.3f %.9e %.9e %.9e %.9e\n",
2180 lambda, if_o[m], if_o_err[m],
2181 if_e[m], if_e_err[m]);
2187 filename = cpl_sprintf(
"angle_%d_%d.dat",
2189 file = fopen(filename,
"w");
2191 fprintf(file,
"%d\n", p + 2);
2193 for (m = 0; m < nx; m++) {
2194 double lambda = startwavelength
2195 + dispersion * group * (0.5 + m);
2196 fprintf(file,
"%.3f %.9e %.9e %.9e %.9e\n",
2197 lambda, ifdelta_o[m], ifdelta_o_err[m],
2198 ifdelta_e[m], ifdelta_e_err[m]);
2205 cpl_msg_info(recipe,
2206 "Extracted signal not written to " 2207 "ASCII (S/N > %.0f only in %d < %d " 2208 "bins)", s2n, bright, ms2n);
2212 for (m = 0; m < nx; m++) {
2214 double quantity = if_o[m] + if_e[m] == 0.0 ? 0.0 :
2215 (if_o[m] - if_e[m] ) /
2216 (if_o[m] + if_e[m] ) -
2217 (ifdelta_o[m] - ifdelta_e[m]) /
2218 (ifdelta_o[m] + ifdelta_e[m]);
2220 quantity = isfinite(quantity) ? quantity : 0.0;
2223 ip_v[m] += quantity * 0.5 / (nscience / 2);
2226 if (nscience / 2 > 1) {
2228 ip_vnull[m] += quantity * 0.5 / (nscience / 2);
2230 ip_vnull[m] -= quantity * 0.5 / (nscience / 2);
2234 ip_i[m] += (if_o[m] + if_e[m] +
2235 ifdelta_o[m] + ifdelta_e[m]) / nscience;
2238 ipierr[m] += (if_o_err[m] * if_o_err[m]
2239 + if_e_err[m] * if_e_err[m]
2240 + ifdelta_o_err[m] * ifdelta_o_err[m]
2241 + ifdelta_e_err[m] * ifdelta_e_err[m])
2242 / nscience / nscience;
2248 data = cpl_image_get_data_float(reduceds[0]);
2249 iff = data + (2 * (nobjects - total) + (total - j - 1)) * nx;
2251 data = cpl_image_get_data_float(rerrors[0]);
2252 ierr = data + (2 * (nobjects - total) + (total - j - 1)) * nx;
2254 for (m = 0; m < nx; m++)
2255 iperr[m] = iff[m] <= 0.0 ?
2256 0.0 : ierr[m] / iff[m] * 0.5 / sqrt (nscience / 2);
2258 if (nscience / 2 > 1) {
2260 float max, sum, sum2, imean;
2265 weights = cpl_malloc(
sizeof(
float) * nx);
2268 for (k = 0; k < nx; k++) {
2269 if (max < iff[k]) max = iff[k];
2272 for (k = 0; k < nx; k++) {
2273 weights[k] = iff[k] < 0.0 ?
2274 0.0 : iff[k] * iff[k] / (max * max);
2279 for (k = 0; k < nx; k++) {
2280 sum += weights[k] * ip_vnull[k];
2288 mean_vnull += (imean - mean_vnull) / (j + 1.0);
2293 parlist, recipe, ref_sci_frame);
2294 if(cpl_error_get_code() != CPL_ERROR_NONE)
2295 fors_pmos_science_exit(NULL, nscience);
2298 parlist, recipe, ref_sci_frame);
2299 if(cpl_error_get_code() != CPL_ERROR_NONE)
2300 fors_pmos_science_exit(NULL, nscience);
2302 if (nscience / 2 > 1) {
2305 cpl_propertylist *qheader;
2308 cpl_propertylist_update_double(qheader,
"CRPIX1", 1.0);
2309 cpl_propertylist_update_double(qheader,
"CRPIX2", 1.0);
2310 cpl_propertylist_update_double(qheader,
"CRVAL1",
2311 startwavelength + (dispersion * group)/2);
2312 cpl_propertylist_update_double(qheader,
"CRVAL2", 1.0);
2313 cpl_propertylist_update_double(qheader,
"CD1_1",
2314 dispersion * group);
2315 cpl_propertylist_update_double(qheader,
"CD1_2", 0.0);
2316 cpl_propertylist_update_double(qheader,
"CD2_1", 0.0);
2317 cpl_propertylist_update_double(qheader,
"CD2_2", 1.0);
2318 cpl_propertylist_update_string(qheader,
"CTYPE1",
"LINEAR");
2319 cpl_propertylist_update_string(qheader,
"CTYPE2",
"PIXEL");
2329 "Product category", instrume))
2330 fors_pmos_science_exit(
"Cannot write product category to " 2331 "QC log file", nscience);
2334 "DPR type", instrume))
2335 fors_pmos_science_exit(
"Missing keyword DPR TYPE in " 2336 "scientific frame header", nscience);
2339 "Template", instrume))
2340 fors_pmos_science_exit(
"Missing keyword TPL ID in " 2341 "scientific frame header", nscience);
2344 "Grism name", instrume))
2345 fors_pmos_science_exit(
"Missing keyword INS GRIS1 NAME in " 2346 "scientific frame header", nscience);
2349 "Grism identifier", instrume))
2350 fors_pmos_science_exit(
"Missing keyword INS GRIS1 ID in " 2351 "scientific frame header", nscience);
2353 if (cpl_propertylist_has(qheader,
"ESO INS FILT1 NAME"))
2355 "Filter name", instrume);
2358 "Collimator name", instrume))
2359 fors_pmos_science_exit(
"Missing keyword INS COLL NAME in " 2360 "scientific frame header", nscience);
2363 "Chip identifier", instrume))
2364 fors_pmos_science_exit(
"Missing keyword DET CHIP1 ID in " 2365 "scientific frame header", nscience);
2368 "Archive name of input data",
2370 fors_pmos_science_exit(
"Missing keyword ARCFILE in " 2371 "scientific frame header", nscience);
2373 pipefile = dfs_generate_filename(reduced_nul_v_tag);
2375 "Pipeline product name", instrume))
2376 fors_pmos_science_exit(
"Cannot write PIPEFILE to " 2377 "QC log file", nscience);
2378 cpl_free(pipefile); pipefile = NULL;
2385 keyname =
"QC.NULL.V.MEAN";
2389 "Mean V null parameter",
2391 fors_pmos_science_exit(
"Cannot write mean Q null " 2392 "parameter to QC log file.", nscience);
2395 keyname =
"QC.NANGLES";
2397 if (fors_qc_write_qc_int(qheader, nscience,
2399 "Number of processed plate angles",
2401 fors_pmos_science_exit(
"Cannot write number of processed " 2402 "plate angles.", nscience);
2409 parlist, recipe, ref_sci_frame);
2410 if(cpl_error_get_code() != CPL_ERROR_NONE)
2411 fors_pmos_science_exit(NULL, nscience);
2413 cpl_propertylist_delete(qheader);
2417 parlist, recipe, ref_sci_frame);
2418 if(cpl_error_get_code() != CPL_ERROR_NONE)
2419 fors_pmos_science_exit(NULL, nscience);
2421 cpl_image_power(pierr_im, 0.5);
2424 parlist, recipe, ref_sci_frame);
2425 if(cpl_error_get_code() != CPL_ERROR_NONE)
2426 fors_pmos_science_exit(NULL, nscience);
2428 cpl_image_delete(pv_im);
2429 cpl_image_delete(pvnull_im);
2430 cpl_image_delete(perr_im);
2431 cpl_image_delete(pi_im);
2432 cpl_image_delete(pierr_im);
2435 cpl_image *pq_im = NULL;
2436 cpl_image *pu_im = NULL;
2437 cpl_image *pl_im = NULL;
2438 cpl_image *pi_im = NULL;
2440 cpl_image *pqnull_im = NULL;
2441 cpl_image *punull_im = NULL;
2443 cpl_image *pqerr_im = NULL;
2444 cpl_image *puerr_im = NULL;
2445 cpl_image *plerr_im = NULL;
2446 cpl_image *pierr_im = NULL;
2448 cpl_image *pang_im = NULL;
2449 cpl_image *pangerr_im = NULL;
2456 double *p_qnull = NULL;
2457 double *p_unull = NULL;
2459 double *pqerr = NULL;
2460 double *puerr = NULL;
2461 double *plerr = NULL;
2462 double *pierr = NULL;
2464 double *pang = NULL;
2465 double *pangerr = NULL;
2469 cpl_image *correct_im = cpl_image_new(nx, 1, CPL_TYPE_DOUBLE);
2470 double *correct = cpl_image_get_data_double(correct_im);
2472 double mean_unull, mean_qnull;
2477 pq_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2478 pu_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2479 pl_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2480 pi_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2482 pqerr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2483 puerr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2484 plerr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2485 pierr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2487 pang_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2488 pangerr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2490 p_q = cpl_image_get_data_double(pq_im);
2491 p_u = cpl_image_get_data_double(pu_im);
2492 p_l = cpl_image_get_data_double(pl_im);
2493 p_i = cpl_image_get_data_double(pi_im);
2495 if (nscience / 4 > 1) {
2496 pqnull_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2497 punull_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2499 p_qnull = cpl_image_get_data_double(pqnull_im);
2500 p_unull = cpl_image_get_data_double(punull_im);
2502 cpl_msg_warning(cpl_func,
2503 "Not enough pairs to compute null parameters");
2506 pqerr = cpl_image_get_data_double(pqerr_im);
2507 puerr = cpl_image_get_data_double(puerr_im);
2508 plerr = cpl_image_get_data_double(plerr_im);
2509 pierr = cpl_image_get_data_double(pierr_im);
2511 pang = cpl_image_get_data_double(pang_im);
2512 pangerr = cpl_image_get_data_double(pangerr_im);
2515 cpl_table * chrotbl =
2518 int nrow = cpl_table_get_nrow(chrotbl);
2519 float * lambda = cpl_table_get_data_float(chrotbl,
"lambda");
2520 float * theta = cpl_table_get_data_float(chrotbl,
"eps_theta");
2522 for (j = 0; j < nx; j++) {
2523 double c_wave = startwavelength
2524 + (dispersion * group) / 2
2525 + j * dispersion * group;
2530 for (k = 0; k < nrow - 1; k++) {
2531 if (lambda[k] <= c_wave && c_wave < lambda[k + 1]) {
2538 correct[j] = (theta [k + 1] - theta [k]) /
2539 (lambda[k + 1] - lambda[k]) *
2540 (c_wave - lambda[k]) + theta[k];
2541 correct[j] *= M_PI / 180;
2544 correct[j] = correct[j-1];
2549 cpl_table_delete(chrotbl);
2552 for (j = 0; j < nobjects; j++) {
2574 ip_q = p_q + (nobjects - 1 - j) * nx;
2575 ip_u = p_u + (nobjects - 1 - j) * nx;
2576 ip_l = p_l + (nobjects - 1 - j) * nx;
2577 ip_i = p_i + (nobjects - 1 - j) * nx;
2579 if (nscience / 4 > 1) {
2580 ip_qnull = p_qnull + (nobjects - 1 - j) * nx;
2581 ip_unull = p_unull + (nobjects - 1 - j) * nx;
2584 ipqerr = pqerr + (nobjects - 1 - j) * nx;
2585 ipuerr = puerr + (nobjects - 1 - j) * nx;
2586 iplerr = plerr + (nobjects - 1 - j) * nx;
2587 ipierr = pierr + (nobjects - 1 - j) * nx;
2589 ipang = pang + (nobjects - 1 - j) * nx;
2590 ipangerr = pangerr + (nobjects - 1 - j) * nx;
2593 for (i = 0; i < nslits; i += 2) {
2594 total += nobjs_per_slit[i];
2601 for (
int k = 0; k < nscience / 4; k++) {
2602 float * if_o, * if_e, * ifdelta_o, * ifdelta_e;
2603 float * if_o_err, * if_e_err, * ifdelta_o_err, * ifdelta_e_err;
2607 pos = fors_find_angle_pos(angles, nscience, 90 * k);
2608 pos_d = fors_find_angle_pos(angles, nscience, 90 * k + 45);
2610 data = cpl_image_get_data_float(reduceds[pos]);
2612 if_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2613 + (total - j - 1)) * nx;
2615 if_e = data + (2 * (nobjects - total)
2616 + (total - j - 1)) * nx;
2618 data = cpl_image_get_data_float(reduceds[pos_d]);
2620 ifdelta_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2621 + (total - j - 1)) * nx;
2623 ifdelta_e = data + (2 * (nobjects - total)
2624 + (total - j - 1)) * nx;
2626 data = cpl_image_get_data_float(rerrors[pos]);
2628 if_o_err = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2629 + (total - j - 1)) * nx;
2631 if_e_err = data + (2 * (nobjects - total)
2632 + (total - j - 1)) * nx;
2634 data = cpl_image_get_data_float(rerrors[pos_d]);
2636 ifdelta_o_err = data + (2 * (nobjects - total)
2637 + nobjs_per_slit[p] + (total - j - 1)) * nx;
2639 ifdelta_e_err = data + (2 * (nobjects - total)
2640 + (total - j - 1)) * nx;
2642 for (m = 0; m < nx; m++) {
2644 double quantity = fabs(if_o[m] + if_e[m]) < FLT_MIN ? 0.0 :
2645 (if_o[m] - if_e[m] ) /
2646 (if_o[m] + if_e[m] ) -
2647 (ifdelta_o[m] - ifdelta_e[m]) /
2648 (ifdelta_o[m] + ifdelta_e[m]);
2650 quantity = isfinite(quantity) ? quantity : 0.0;
2653 ip_q[m] += quantity * 0.5 / (nscience / 4);
2656 if (nscience / 4 > 1) {
2658 ip_qnull[m] += quantity * 0.5 / (nscience / 4);
2660 ip_qnull[m] -= quantity * 0.5 / (nscience / 4);
2664 ip_i[m] += (if_o[m] + if_e[m] +
2665 ifdelta_o[m] + ifdelta_e[m]) / nscience;
2668 ipierr[m] += (if_o_err[m] * if_o_err[m]
2669 + if_e_err[m] * if_e_err[m]
2670 + ifdelta_o_err[m] * ifdelta_o_err[m]
2671 + ifdelta_e_err[m] * ifdelta_e_err[m])
2672 / nscience / nscience;
2677 pos = fors_find_angle_pos(angles, nscience, 90 * k + 22.5);
2678 pos_d = fors_find_angle_pos(angles, nscience, 90 * k + 67.5);
2680 data = cpl_image_get_data_float(reduceds[pos]);
2682 if_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2683 + (total - j - 1)) * nx;
2685 if_e = data + (2 * (nobjects - total)
2686 + (total - j - 1)) * nx;
2688 data = cpl_image_get_data_float(reduceds[pos_d]);
2690 ifdelta_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2691 + (total - j - 1)) * nx;
2693 ifdelta_e = data + (2 * (nobjects - total)
2694 + (total - j - 1)) * nx;
2696 data = cpl_image_get_data_float(rerrors[pos]);
2698 if_o_err = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2699 + (total - j - 1)) * nx;
2701 if_e_err = data + (2 * (nobjects - total)
2702 + (total - j - 1)) * nx;
2704 data = cpl_image_get_data_float(rerrors[pos_d]);
2706 ifdelta_o_err = data + (2 * (nobjects - total)
2707 + nobjs_per_slit[p] + (total - j - 1)) * nx;
2709 ifdelta_e_err = data + (2 * (nobjects - total)
2710 + (total - j - 1)) * nx;
2712 for (m = 0; m < nx; m++) {
2714 double quantity = fabs(if_o[m] + if_e[m]) < FLT_MIN ? 0.0 :
2715 (if_o[m] - if_e[m] ) /
2716 (if_o[m] + if_e[m] ) -
2717 (ifdelta_o[m] - ifdelta_e[m]) /
2718 (ifdelta_o[m] + ifdelta_e[m]);
2720 quantity = isfinite(quantity) ? quantity : 0.0;
2723 ip_u[m] += quantity * 0.5 / (nscience / 4);
2726 if (nscience / 4 > 1) {
2728 ip_unull[m] += quantity * 0.5 / (nscience / 4);
2730 ip_unull[m] -= quantity * 0.5 / (nscience / 4);
2734 ip_i[m] += (if_o[m] + if_e[m] +
2735 ifdelta_o[m] + ifdelta_e[m]) / nscience;
2738 ipierr[m] += (if_o_err[m] * if_o_err[m]
2739 + if_e_err[m] * if_e_err[m]
2740 + ifdelta_o_err[m] * ifdelta_o_err[m]
2741 + ifdelta_e_err[m] * ifdelta_e_err[m])
2742 / nscience / nscience;
2748 pos = fors_find_angle_pos(angles, nscience, 0.0);
2750 data = cpl_image_get_data_float(reduceds[pos]);
2751 iffq = data + (2 * (nobjects - total) + (total - j - 1)) * nx;
2753 data = cpl_image_get_data_float(rerrors[pos]);
2754 ierrq = data + (2 * (nobjects - total) + (total - j - 1)) * nx;
2756 pos = fors_find_angle_pos(angles, nscience, 22.5);
2758 data = cpl_image_get_data_float(reduceds[pos]);
2759 iffu = data + (2 * (nobjects - total) + (total - j - 1)) * nx;
2761 data = cpl_image_get_data_float(rerrors[pos]);
2762 ierru = data + (2 * (nobjects - total) + (total - j - 1)) * nx;
2764 for (m = 0; m < nx; m++) {
2768 ipqerr[m] = iffq[m] <= 0.0 ?
2769 0.0 : ierrq[m] / iffq[m] * 0.5 / sqrt (nscience / 4);
2771 ipuerr[m] = iffu[m] <= 0.0 ?
2772 0.0 : ierru[m] / iffu[m] * 0.5 / sqrt (nscience / 4);
2774 iplerr[m] = 0.5 * (ipqerr[m] + ipuerr[m]);
2777 ip_l[m] = sqrt(ip_u[m] * ip_u[m] + ip_q[m] * ip_q[m]);
2780 if (fabs(ip_q[m]) < 0.00001) {
2781 if (ip_u[m] > 0.0) {
2789 ipang[m] = 0.5 * atan(ip_u[m] / ip_q[m]) * 180 / M_PI;
2790 if (ip_q[m] > 0.0) {
2791 if (ip_u[m] < 0.0) {
2801 radicand = ip_q[m] * ip_q[m] * ipuerr[m] * ipuerr[m] +
2802 ip_u[m] * ip_u[m] * ipqerr[m] * ipqerr[m];
2804 ipangerr[m] = (ip_l[m] == 0.0 ? 0.0 :
2805 sqrt(radicand) * 0.5 / (ip_l[m] * ip_l[m]) * 180 / M_PI);
2814 if (instrume[4] ==
'2') {
2816 double w_rotation = - wollaston * M_PI / 2;
2818 ipang[m] -= w_rotation * 180 / M_PI;
2820 ip_q[m] = ip_q[m] * cos(2 * w_rotation)
2821 + ip_u[m] * sin(2 * w_rotation);
2823 ip_u[m] = ip_u[m] * cos(2 * w_rotation)
2824 - ip_q[m] * sin(2 * w_rotation);
2828 ipang[m] -= correct[m] * 180 / M_PI;
2830 ip_q[m] = ip_q[m] * cos(2 * correct[m])
2831 + ip_u[m] * sin(2 * correct[m]);
2833 ip_u[m] = ip_u[m] * cos(2 * correct[m])
2834 - ip_q[m] * sin(2 * correct[m]);
2839 else if (ipang[m] >= 180.0)
2843 if (nscience / 4 > 1) {
2845 float max, sum, sum2, imean;
2850 weights = cpl_malloc(
sizeof(
float) * nx);
2853 for (k = 0; k < nx; k++) {
2854 if (max < iffq[k]) max = iffq[k];
2857 for (k = 0; k < nx; k++) {
2858 weights[k] = iffq[k] < 0.0 ?
2859 0.0 : iffq[k] * iffq[k] / (max * max);
2864 for (k = 0; k < nx; k++) {
2865 sum += weights[k] * ip_qnull[k];
2873 mean_qnull += (imean - mean_qnull) / (j + 1.0);
2876 weights = cpl_malloc(
sizeof(
float) * nx);
2879 for (k = 0; k < nx; k++) {
2880 if (max < iffu[k]) max = iffu[k];
2883 for (k = 0; k < nx; k++) {
2884 weights[k] = iffu[k] < 0.0 ?
2885 0.0 : iffu[k] * iffu[k] / (max * max);
2890 for (k = 0; k < nx; k++) {
2891 sum += weights[k] * ip_unull[k];
2899 mean_unull += (imean - mean_unull) / (j + 1.0);
2903 cpl_image_delete(correct_im);
2906 parlist, recipe, ref_sci_frame);
2907 if(cpl_error_get_code() != CPL_ERROR_NONE)
2908 fors_pmos_science_exit(NULL, nscience);
2911 parlist, recipe, ref_sci_frame);
2912 if(cpl_error_get_code() != CPL_ERROR_NONE)
2913 fors_pmos_science_exit(NULL, nscience);
2915 if (qc && standard) {
2916 cpl_table *polsta =
dfs_load_table(frameset, std_pmos_table_tag, 1);
2919 cpl_propertylist_update_double(qheader,
"CRPIX1", 1.0);
2920 cpl_propertylist_update_double(qheader,
"CRPIX2", 1.0);
2921 cpl_propertylist_update_double(qheader,
"CRVAL1",
2922 startwavelength + (dispersion * group)/2);
2923 cpl_propertylist_update_double(qheader,
"CRVAL2", 1.0);
2924 cpl_propertylist_update_double(qheader,
"CD1_1",
2925 dispersion * group);
2926 cpl_propertylist_update_double(qheader,
"CD1_2", 0.0);
2927 cpl_propertylist_update_double(qheader,
"CD2_1", 0.0);
2928 cpl_propertylist_update_double(qheader,
"CD2_2", 1.0);
2929 cpl_propertylist_update_string(qheader,
"CTYPE1",
"LINEAR");
2930 cpl_propertylist_update_string(qheader,
"CTYPE2",
"PIXEL");
2933 startwavelength, dispersion, 1000.,
2934 polsta, ra, dec, &filter,
2937 &qc_angle, &qc_angle_err)) {
2938 cpl_msg_warning(cpl_func,
"No QC can be computed");
2944 char band[] = {
' ',
'\0'};
2953 "Product category", instrume))
2954 fors_pmos_science_exit(
"Cannot write product category to " 2955 "QC log file", nscience);
2958 "DPR type", instrume))
2959 fors_pmos_science_exit(
"Missing keyword DPR TYPE in " 2960 "scientific frame header", nscience);
2963 "Template", instrume))
2964 fors_pmos_science_exit(
"Missing keyword TPL ID in " 2965 "scientific frame header", nscience);
2968 "Grism name", instrume))
2969 fors_pmos_science_exit(
"Missing keyword INS GRIS1 NAME in " 2970 "scientific frame header", nscience);
2973 "Grism identifier", instrume))
2974 fors_pmos_science_exit(
"Missing keyword INS GRIS1 ID in " 2975 "scientific frame header", nscience);
2977 if (cpl_propertylist_has(qheader,
"ESO INS FILT1 NAME"))
2979 "Filter name", instrume);
2982 "Collimator name", instrume))
2983 fors_pmos_science_exit(
"Missing keyword INS COLL NAME in " 2984 "scientific frame header", nscience);
2987 "Chip identifier", instrume))
2988 fors_pmos_science_exit(
"Missing keyword DET CHIP1 ID in " 2989 "scientific frame header", nscience);
2992 "Archive name of input data",
2994 fors_pmos_science_exit(
"Missing keyword ARCFILE in " 2995 "scientific frame header", nscience);
2997 pipefile = dfs_generate_filename(reduced_nul_q_tag);
2999 "Pipeline product name", instrume))
3000 fors_pmos_science_exit(
"Cannot write PIPEFILE to " 3001 "QC log file", nscience);
3002 cpl_free(pipefile); pipefile = NULL;
3009 keyname =
"QC.PMOS.BAND";
3013 "Band where polarisation was " 3014 "measured", instrume)) {
3015 fors_pmos_science_exit(
"Cannot write QC.PMOS.BAND " 3016 "parameter to QC log file", nscience);
3019 keyname =
"QC.PMOS.POLARISED";
3021 if (fors_qc_write_qc_int(qheader, polarised, keyname, NULL,
3022 "Polarisation is expected (1 = yes, " 3023 "0 = no)", instrume)) {
3024 fors_pmos_science_exit(
"Cannot write QC.PMOS.POLARISED " 3025 "parameter to QC log file", nscience);
3028 keyname =
"QC.PMOS.L.OFFSET";
3031 text =
"Linear polarisation relative offset";
3033 text =
"Linear polarisation offset";
3037 fors_pmos_science_exit(
"Cannot write linear polarisation " 3038 "offset to QC log file", nscience);
3041 keyname =
"QC.PMOS.L.OFFSETERR";
3044 "Error on linear polarisation offset",
3046 fors_pmos_science_exit(
"Cannot write linear polarisation " 3047 "offset error to QC log file", nscience);
3051 keyname =
"QC.PMOS.ANGLE.OFFSET";
3054 "Polarisation angle offset",
3056 fors_pmos_science_exit(
"Cannot write polarisation " 3057 "angle offset to QC log file", nscience);
3060 keyname =
"QC.PMOS.ANGLE.OFFSETERR";
3063 NULL,
"Error on polarisation " 3064 "angle offset", instrume)) {
3065 fors_pmos_science_exit(
"Cannot write polarisation " 3066 "angle offset error to QC " 3067 "log file", nscience);
3075 parlist, recipe, ref_sci_frame);
3076 if(cpl_error_get_code() != CPL_ERROR_NONE)
3077 fors_pmos_science_exit(NULL, nscience);
3079 cpl_propertylist_delete(qheader);
3083 parlist, recipe, ref_sci_frame);
3084 if(cpl_error_get_code() != CPL_ERROR_NONE)
3085 fors_pmos_science_exit(NULL, nscience);
3088 if (nscience / 4 > 1) {
3094 cpl_propertylist_update_double(qheader,
"CRPIX1", 1.0);
3095 cpl_propertylist_update_double(qheader,
"CRPIX2", 1.0);
3096 cpl_propertylist_update_double(qheader,
"CRVAL1",
3097 startwavelength + (dispersion * group)/2);
3098 cpl_propertylist_update_double(qheader,
"CRVAL2", 1.0);
3099 cpl_propertylist_update_double(qheader,
"CD1_1",
3100 dispersion * group);
3101 cpl_propertylist_update_double(qheader,
"CD1_2", 0.0);
3102 cpl_propertylist_update_double(qheader,
"CD2_1", 0.0);
3103 cpl_propertylist_update_double(qheader,
"CD2_2", 1.0);
3104 cpl_propertylist_update_string(qheader,
"CTYPE1",
"LINEAR");
3105 cpl_propertylist_update_string(qheader,
"CTYPE2",
"PIXEL");
3115 "Product category", instrume))
3116 fors_pmos_science_exit(
"Cannot write product category to " 3117 "QC log file", nscience);
3120 "DPR type", instrume))
3121 fors_pmos_science_exit(
"Missing keyword DPR TYPE in " 3122 "scientific frame header", nscience);
3125 "Template", instrume))
3126 fors_pmos_science_exit(
"Missing keyword TPL ID in " 3127 "scientific frame header", nscience);
3130 "Grism name", instrume))
3131 fors_pmos_science_exit(
"Missing keyword INS GRIS1 NAME in " 3132 "scientific frame header", nscience);
3135 "Grism identifier", instrume))
3136 fors_pmos_science_exit(
"Missing keyword INS GRIS1 ID in " 3137 "scientific frame header", nscience);
3139 if (cpl_propertylist_has(qheader,
"ESO INS FILT1 NAME"))
3141 "Filter name", instrume);
3144 "Collimator name", instrume))
3145 fors_pmos_science_exit(
"Missing keyword INS COLL NAME in " 3146 "scientific frame header", nscience);
3149 "Chip identifier", instrume))
3150 fors_pmos_science_exit(
"Missing keyword DET CHIP1 ID in " 3151 "scientific frame header", nscience);
3154 "Archive name of input data",
3156 fors_pmos_science_exit(
"Missing keyword ARCFILE in " 3157 "scientific frame header", nscience);
3159 pipefile = dfs_generate_filename(reduced_nul_q_tag);
3161 "Pipeline product name", instrume))
3162 fors_pmos_science_exit(
"Cannot write PIPEFILE to " 3163 "QC log file", nscience);
3164 cpl_free(pipefile); pipefile = NULL;
3171 keyname =
"QC.NULL.Q.MEAN";
3175 "Mean Q null parameter",
3177 fors_pmos_science_exit(
"Cannot write mean Q null " 3178 "parameter to QC log file", nscience);
3181 keyname =
"QC.NANGLES";
3183 if (fors_qc_write_qc_int(qheader, nscience / 2,
3185 "Number of processed plate angles",
3187 fors_pmos_science_exit(
"Cannot write number of processed " 3188 "plate angles.", nscience);
3195 parlist, recipe, ref_sci_frame);
3196 if(cpl_error_get_code() != CPL_ERROR_NONE)
3197 fors_pmos_science_exit(NULL, nscience);
3199 cpl_propertylist_delete(qheader);
3203 cpl_propertylist_update_double(qheader,
"CRPIX1", 1.0);
3204 cpl_propertylist_update_double(qheader,
"CRPIX2", 1.0);
3205 cpl_propertylist_update_double(qheader,
"CRVAL1",
3206 startwavelength + (dispersion * group)/2);
3207 cpl_propertylist_update_double(qheader,
"CRVAL2", 1.0);
3208 cpl_propertylist_update_double(qheader,
"CD1_1",
3209 dispersion * group);
3210 cpl_propertylist_update_double(qheader,
"CD1_2", 0.0);
3211 cpl_propertylist_update_double(qheader,
"CD2_1", 0.0);
3212 cpl_propertylist_update_double(qheader,
"CD2_2", 1.0);
3213 cpl_propertylist_update_string(qheader,
"CTYPE1",
"LINEAR");
3214 cpl_propertylist_update_string(qheader,
"CTYPE2",
"PIXEL");
3224 "Product category", instrume))
3225 fors_pmos_science_exit(
"Cannot write product category to " 3226 "QC log file", nscience);
3229 "DPR type", instrume))
3230 fors_pmos_science_exit(
"Missing keyword DPR TYPE in " 3231 "scientific frame header", nscience);
3234 "Template", instrume))
3235 fors_pmos_science_exit(
"Missing keyword TPL ID in " 3236 "scientific frame header", nscience);
3239 "Grism name", instrume))
3240 fors_pmos_science_exit(
"Missing keyword INS GRIS1 NAME in " 3241 "scientific frame header", nscience);
3244 "Grism identifier", instrume))
3245 fors_pmos_science_exit(
"Missing keyword INS GRIS1 ID in " 3246 "scientific frame header", nscience);
3248 if (cpl_propertylist_has(qheader,
"ESO INS FILT1 NAME"))
3250 "Filter name", instrume);
3253 "Collimator name", instrume))
3254 fors_pmos_science_exit(
"Missing keyword INS COLL NAME in " 3255 "scientific frame header", nscience);
3258 "Chip identifier", instrume))
3259 fors_pmos_science_exit(
"Missing keyword DET CHIP1 ID in " 3260 "scientific frame header", nscience);
3263 "Archive name of input data",
3265 fors_pmos_science_exit(
"Missing keyword ARCFILE in " 3266 "scientific frame header", nscience);
3268 pipefile = dfs_generate_filename(reduced_nul_u_tag);
3270 "Pipeline product name", instrume))
3271 fors_pmos_science_exit(
"Cannot write PIPEFILE to " 3272 "QC log file", nscience);
3273 cpl_free(pipefile); pipefile = NULL;
3280 keyname =
"QC.NULL.U.MEAN";
3284 "Mean U null parameter",
3286 fors_pmos_science_exit(
"Cannot write mean U null " 3287 "parameter to QC log file", nscience);
3290 keyname =
"QC.NANGLES";
3292 if (fors_qc_write_qc_int(qheader, nscience / 2,
3294 "Number of processed plate angles",
3296 fors_pmos_science_exit(
"Cannot write number of processed " 3297 "plate angles.", nscience);
3304 parlist, recipe, ref_sci_frame);
3305 if(cpl_error_get_code() != CPL_ERROR_NONE)
3306 fors_pmos_science_exit(NULL, nscience);
3308 cpl_propertylist_delete(qheader);
3312 parlist, recipe, ref_sci_frame);
3313 if(cpl_error_get_code() != CPL_ERROR_NONE)
3314 fors_pmos_science_exit(NULL, nscience);
3317 parlist, recipe, ref_sci_frame);
3318 if(cpl_error_get_code() != CPL_ERROR_NONE)
3319 fors_pmos_science_exit(NULL, nscience);
3322 parlist, recipe, ref_sci_frame);
3323 if(cpl_error_get_code() != CPL_ERROR_NONE)
3324 fors_pmos_science_exit(NULL, nscience);
3327 parlist, recipe, ref_sci_frame);
3328 if(cpl_error_get_code() != CPL_ERROR_NONE)
3329 fors_pmos_science_exit(NULL, nscience);
3332 header, parlist, recipe, ref_sci_frame);
3333 if(cpl_error_get_code() != CPL_ERROR_NONE)
3334 fors_pmos_science_exit(NULL, nscience);
3337 header, parlist, recipe, ref_sci_frame);
3338 if(cpl_error_get_code() != CPL_ERROR_NONE)
3339 fors_pmos_science_exit(NULL, nscience);
3341 cpl_image_power(pierr_im, 0.5);
3344 header, parlist, recipe, ref_sci_frame);
3345 if(cpl_error_get_code() != CPL_ERROR_NONE)
3346 fors_pmos_science_exit(NULL, nscience);
3350 cpl_image_delete(pq_im);
3351 cpl_image_delete(pu_im);
3352 cpl_image_delete(pl_im);
3353 cpl_image_delete(pi_im);
3355 cpl_image_delete(pqnull_im);
3356 cpl_image_delete(punull_im);
3358 cpl_image_delete(pqerr_im);
3359 cpl_image_delete(puerr_im);
3360 cpl_image_delete(plerr_im);
3361 cpl_image_delete(pierr_im);
3362 cpl_image_delete(pang_im);
3363 cpl_image_delete(pangerr_im);
3366 cpl_propertylist_delete(header);
3370 for (j = 0; j < nscience; j++) {
3371 cpl_image_delete(reduceds[j]);
3372 cpl_image_delete(rerrors[j]);
3373 cpl_table_delete(slitss[j]);
3374 cpl_image_delete(mappeds[j]);
3382 cpl_free(instrume); instrume = NULL;
3384 cpl_free(skylocalmaps);
3386 cpl_free(nobjs_per_slit);
3388 if (cpl_error_get_code()) {
3389 cpl_msg_error(cpl_error_get_where(),
"%s", cpl_error_get_message());
3390 fors_pmos_science_exit(NULL, nscience);
3408 static float * fors_check_angles(cpl_frameset * frameset,
3409 int pmos,
const char *tag,
int * circ)
3411 float *angles = NULL;
3412 cpl_frame *c_frame = NULL;
3413 char *ret_id = NULL;
3417 angles = cpl_malloc(
sizeof(
float) * pmos);
3419 for (c_frame = cpl_frameset_find(frameset, tag);
3420 c_frame != NULL; c_frame = cpl_frameset_find(frameset, NULL)) {
3422 cpl_propertylist * header =
3423 cpl_propertylist_load(cpl_frame_get_filename(c_frame), 0);
3426 ret_id = cpl_strdup(cpl_propertylist_get_string(header,
3427 "ESO INS OPTI4 ID"));
3429 if (ret_id[1] !=
'5' && ret_id[1] !=
'4') {
3430 cpl_msg_error(cpl_func,
3431 "Unknown retarder plate id: %s", ret_id);
3435 char * c_ret_id = (
char *)
3436 cpl_propertylist_get_string(header,
"ESO INS OPTI4 ID");
3437 if (ret_id[1] != c_ret_id[1]) {
3438 cpl_msg_error(cpl_func,
"Input frames are not from the same " 3444 if (ret_id[1] ==
'5') {
3445 if (cpl_propertylist_has(header,
"ESO INS RETA2 ROT")) {
3446 angles[i] = (float)floor(2*cpl_propertylist_get_double(header,
3447 "ESO INS RETA2 ROT") + 0.5)/2;
3449 else if (cpl_propertylist_has(header,
"ESO INS RETA2 POSANG")) {
3450 if (cpl_propertylist_has(header,
"ESO ADA POSANG")) {
3451 double reta2pos = cpl_propertylist_get_double(header,
3452 "ESO INS RETA2 POSANG");
3453 double adapos = cpl_propertylist_get_double(header,
3455 angles[i] = (float)floor(2*(reta2pos - 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 RETA2 ROT nor " 3465 "ESO INS RETA2 POSANG found in header");
3470 if (cpl_propertylist_has(header,
"ESO INS RETA4 ROT")) {
3471 angles[i] = (float)floor(2*cpl_propertylist_get_double(header,
3472 "ESO INS RETA4 ROT") + 0.5)/2;
3475 angles[i] = angles[i] + 360;
3477 else if (cpl_propertylist_has(header,
"ESO INS RETA4 POSANG")) {
3478 if (cpl_propertylist_has(header,
"ESO ADA POSANG")) {
3479 double reta4pos = cpl_propertylist_get_double(header,
3480 "ESO INS RETA4 POSANG");
3481 double adapos = cpl_propertylist_get_double(header,
3483 angles[i] = (float)floor(2*(reta4pos - adapos) + 0.5/2);
3486 cpl_msg_error(cpl_func,
3487 "ESO ADA POSANG not found in header");
3492 cpl_msg_error(cpl_func,
"Neither ESO INS RETA4 ROT nor " 3493 "ESO INS RETA4 POSANG found in header");
3499 cpl_propertylist_delete(header);
3506 if (pmos != 2 && pmos != 4) {
3507 cpl_msg_error(cpl_func,
"Wrong angle configuration: %d angles " 3508 "found, but either 2 or 4 are required for " 3509 "circular polarization measurements!", pmos);
3513 if (pmos != 4 && pmos != 8 && pmos != 16) {
3514 cpl_msg_error(cpl_func,
"Wrong angle configuration: %d angles " 3515 "found, but either 4, 8, or 16 are required for " 3516 "linear polarization measurements!", pmos);
3524 for (i = 0; i < pmos; i++) {
3525 if (fors_find_angle_pos(angles, pmos, 90.0 * i - 45.0) < 0) {
3526 const char *cangles;
3528 case 2: cangles =
"-45.0, 45.0";
break;
3529 case 4: cangles =
"-45.0, 45.0, 135.0, 225.0";
break;
3533 cpl_msg_error(cpl_func,
"Wrong angle configuration: missing " 3534 "angle %.2f. All angles %s must be provided.",
3535 angles[i], cangles);
3541 for (i = 0; i < pmos; i++) {
3542 if (fors_find_angle_pos(angles, pmos, 22.5 * i) < 0) {
3543 const char *cangles;
3545 case 4: cangles =
"0.0, 22.5, 45.0, 67.5";
break;
3546 case 8: cangles =
"0.0, 22.5, 45.0, 67.5, " 3547 "90.0, 112.5, 135.0, 157.5";
break;
3548 case 16: cangles =
"0.0, 22.5, 45.0, 67.5, " 3549 "90.0, 112.5, 135.0, 157.5, " 3550 "180.0, 202.5, 225.0, 247.5, " 3551 "270.0, 292.5, 315.0, 337.5";
break;
3555 cpl_msg_error(cpl_func,
"Wrong angle configuration: missing " 3556 "angle %.2f. All angles %s must be provided.",
3557 angles[i], cangles);
3576 fors_find_angle_pos(
float * angles,
int nangles,
float angle)
3580 for (i = 0; i < nangles; i++) {
3581 if (fabs(angles[i] - angle) < 1.0 ||
3582 fabs(angles[i] - 360.0 - angle) < 1.0) {
3588 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.
void fors_dfs_save_image(cpl_frameset *frameset, const cpl_image *image, const char *category, cpl_propertylist *header, const cpl_parameterlist *parlist, const char *recipename, const cpl_frame *inherit_frame)
Save DFS product (image)
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)
void fors_dfs_save_table(cpl_frameset *frameset, const cpl_table *table, const char *category, cpl_propertylist *header, const cpl_parameterlist *parlist, const char *recipename, const cpl_frame *inherit_frame)
Save DFS product (table)
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.
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.
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_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.