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);
1443 nx = cpl_image_get_size_x(spectra);
1444 ny = cpl_image_get_size_y(spectra);
1449 cpl_msg_info(recipe,
"Apply flat field correction...");
1450 if (cpl_image_divide(spectra, norm_flat) != CPL_ERROR_NONE) {
1451 cpl_msg_error(recipe,
1452 "Failure of flat field correction: %s",
1453 cpl_error_get_message());
1454 fors_pmos_science_exit(NULL, nscience);
1458 cpl_msg_error(recipe,
"Cannot load input %s for flat field " 1459 "correction", master_norm_flat_tag);
1460 fors_pmos_science_exit(NULL, nscience);
1470 if (polytraces == NULL)
1471 fors_pmos_science_exit(
"Cannot load spectral curvature table", nscience);
1479 fors_pmos_science_exit(
"Cannot load slits location table", nscience);
1481 cpl_msg_info(recipe,
"Processing scientific spectra...");
1488 coordinate = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1491 reference, startwavelength,
1492 endwavelength, dispersion,
1503 if (dispersion > 1.0)
1508 if (skyalign >= 0) {
1510 cpl_msg_info(recipe,
1511 "Align wavelength solution to reference skylines " 1512 "applying %d order residual fit...", skyalign);
1515 cpl_msg_info(recipe,
"Align wavelength solution to reference " 1516 "skylines applying median offset...");
1521 startwavelength, endwavelength,
1522 idscoeff, lines, highres,
1523 skyalign, rainbow, 4);
1526 cpl_msg_warning(recipe,
"Alignment of the wavelength " 1527 "solution to reference sky lines may " 1528 "be unreliable in this case!");
1531 skylines_offsets_tag, NULL,
1532 parlist, recipe, ref_sci_frame);
1533 if(cpl_error_get_code() != CPL_ERROR_NONE)
1534 fors_pmos_science_exit(NULL, nscience);
1537 cpl_msg_warning(recipe,
"Alignment of the wavelength " 1538 "solution to reference sky lines could " 1548 polytraces, reference,
1549 startwavelength, endwavelength,
1553 cpl_image_delete(rainbow); rainbow = NULL;
1554 cpl_image_delete(coordinate); coordinate = NULL;
1562 startwavelength, endwavelength,
1563 dispersion, idscoeff, flux);
1566 cpl_msg_indent_less();
1567 cpl_msg_info(recipe,
1568 "Check applied wavelength against skylines...");
1569 cpl_msg_indent_more();
1572 dispersion, 6, highres);
1575 cpl_msg_info(recipe,
"Mean residual: %f", mean_rms);
1577 mean_rms = cpl_table_get_column_mean(idscoeff,
"error");
1579 cpl_msg_info(recipe,
"Mean model accuracy: %f pixel (%f A)",
1580 mean_rms, mean_rms * dispersion);
1583 save_header = cpl_propertylist_duplicate(header);
1585 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
1586 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
1587 cpl_propertylist_update_double(header,
"CRVAL1",
1588 startwavelength + dispersion/2);
1589 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
1590 cpl_propertylist_update_double(header,
"CD1_1", dispersion);
1591 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
1592 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
1593 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
1594 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
1595 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
1597 if (time_normalise) {
1598 dummy = cpl_image_divide_scalar_create(mapped_sky, alltime);
1602 mapped_science_sky_tag,
1604 fors_pmos_science_exit(NULL, nscience);
1609 fors_pmos_science_exit(NULL, nscience);
1612 cpl_image_delete(dummy); dummy = NULL;
1618 mapped_science_sky_tag,
1620 fors_pmos_science_exit(NULL, nscience);
1625 mapped_science_sky_tag, header)) {
1626 fors_pmos_science_exit(NULL, nscience);
1631 if (skymedian == 0 && skylocal == 0) {
1632 cpl_image_delete(mapped_sky); mapped_sky = NULL;
1637 cpl_msg_indent_less();
1639 cpl_msg_info(recipe,
"Local sky determination...");
1640 cpl_msg_indent_more();
1642 startwavelength, endwavelength, dispersion);
1646 cpl_image_divide_scalar(skymap, alltime);
1652 fors_pmos_science_exit(NULL, nscience);
1658 fors_pmos_science_exit(NULL, nscience);
1661 cpl_image_delete(skymap); skymap = NULL;
1665 unmapped_science_tag,
1667 fors_pmos_science_exit(NULL, nscience);
1673 fors_pmos_science_exit(NULL, nscience);
1677 cpl_msg_info(recipe,
"Removing cosmic rays...");
1686 cpl_image_delete(smapped); smapped = NULL;
1689 reference, startwavelength,
1690 endwavelength, dispersion,
1694 cpl_msg_warning(recipe,
"Sky subtraction failure");
1696 cpl_msg_warning(recipe,
1697 "Cosmic rays removal not performed!");
1698 cosmics = skylocal = 0;
1702 cpl_image_delete(spectra); spectra = NULL;
1703 cpl_table_delete(polytraces); polytraces = NULL;
1705 if (skyalign >= 0) {
1710 wavelength_map_sky_tag,
1712 fors_pmos_science_exit(NULL, nscience);
1718 fors_pmos_science_exit(NULL, nscience);
1722 cpl_image_delete(wavemap); wavemap = NULL;
1725 startwavelength, endwavelength,
1726 dispersion, idscoeff, flux);
1728 cpl_image_delete(smapped); smapped = NULL;
1730 if (skyalign >= 0) {
1733 NULL, parlist, recipe, ref_sci_frame);
1734 if(cpl_error_get_code() != CPL_ERROR_NONE)
1735 fors_pmos_science_exit(NULL, nscience);
1740 cpl_msg_indent_less();
1741 cpl_msg_info(recipe,
"Local sky determination...");
1742 cpl_msg_indent_more();
1745 cpl_image_subtract(mapped, skylocalmap);
1746 cpl_image_delete(skylocalmap); skylocalmap = NULL;
1749 if (skymedian || skylocal) {
1751 skylocalmap = cpl_image_subtract_create(mapped_sky, mapped);
1753 cpl_image_delete(mapped_sky); mapped_sky = NULL;
1755 if (time_normalise) {
1756 dummy = cpl_image_divide_scalar_create(skylocalmap, alltime);
1762 fors_pmos_science_exit(NULL, nscience);
1768 fors_pmos_science_exit(NULL, nscience);
1771 cpl_image_delete(dummy); dummy = NULL;
1778 fors_pmos_science_exit(NULL, nscience);
1784 fors_pmos_science_exit(NULL, nscience);
1788 skylocalmaps[j] = skylocalmap;
1790 cpl_msg_indent_less();
1791 cpl_msg_info(recipe,
"Object detection...");
1792 cpl_msg_indent_more();
1795 origslits = cpl_table_duplicate(slits);
1796 nslits = cpl_table_get_nrow(slits);
1799 if (cosmics || nscience > 1) {
1801 ext_radius, cont_radius);
1804 mapped_cleaned = cpl_image_duplicate(mapped);
1807 ext_radius, cont_radius);
1809 cpl_image_delete(mapped_cleaned); mapped_cleaned = NULL;
1812 cpl_image_delete(dummy); dummy = NULL;
1817 mappeds[j] = mapped;
1819 cpl_msg_indent_less();
1821 cpl_propertylist_delete(header); header = NULL;
1822 cpl_propertylist_delete(save_header); save_header = NULL;
1825 cpl_table_delete(offsets); offsets = NULL;
1826 cpl_table_delete(idscoeff); idscoeff = NULL;
1828 cpl_image_delete(norm_flat); norm_flat = NULL;
1829 cpl_vector_delete(lines); lines = NULL;
1832 cpl_msg_indent_less();
1833 cpl_msg_info(recipe,
1834 "Check object detection in both beams for all angles...");
1835 cpl_msg_indent_more();
1843 if (error == CPL_ERROR_DATA_NOT_FOUND) {
1844 cpl_msg_warning(recipe,
"No objects found: no Stokes " 1845 "parameters to compute!");
1846 for (j = 0; j < nscience; j++)
1847 cpl_table_delete(slitss[j]);
1849 cpl_table_delete(origslits);
1852 fors_pmos_science_exit(
"Problem in polarimetric object selection", nscience);
1856 NULL, parlist, recipe, ref_sci_frame);
1857 if(cpl_error_get_code() != CPL_ERROR_NONE)
1858 fors_pmos_science_exit(NULL, nscience);
1865 for (j = 0; j < nscience; j++) {
1869 fors_pmos_science_exit(NULL, nscience);
1874 fors_pmos_science_exit(NULL, nscience);
1878 nobjs_per_slit = fors_get_nobjs_perslit(origslits);
1880 cpl_msg_indent_less();
1881 cpl_msg_info(recipe,
"Object extraction...");
1882 cpl_msg_indent_more();
1884 for (j = 0; j < nscience; j++) {
1889 for (k = 0; k < j; k ++) {
1890 cpl_propertylist_delete(header);
1894 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
1895 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
1896 cpl_propertylist_update_double(header,
"CRVAL1",
1897 startwavelength + (dispersion * group)/2);
1898 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
1899 cpl_propertylist_update_double(header,
"CD1_1", dispersion * group);
1900 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
1901 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
1902 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
1903 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
1904 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
1906 if (skymedian || skylocal) {
1908 cpl_msg_info(recipe,
"Extracting at angle %.2f (%d out of %d) ...",
1909 angles[j], j + 1, nscience);
1913 ext_mode, ron, gain, 1);
1915 cpl_image_delete(skylocalmaps[j]); skylocalmaps[j] = NULL;
1919 cpl_image_divide_scalar(images[0], alltime);
1921 mos_rebin_signal(images, group);
1925 reduced_science_tag,
1927 fors_pmos_science_exit(NULL, nscience);
1933 fors_pmos_science_exit(NULL, nscience);
1936 reduceds[j] = images[0];
1939 cpl_image_divide_scalar(images[1], alltime);
1941 mos_rebin_signal(images + 1, group);
1947 fors_pmos_science_exit(NULL, nscience);
1953 fors_pmos_science_exit(NULL, nscience);
1955 cpl_image_delete(images[1]);
1958 cpl_image_divide_scalar(images[2], alltime);
1960 mos_rebin_error(images + 2, group);
1966 fors_pmos_science_exit(NULL, nscience);
1972 fors_pmos_science_exit(NULL, nscience);
1975 rerrors[j] = images[2];
1980 cpl_msg_warning(recipe,
"No objects found: the products " 1981 "%s, %s, and %s are not created",
1982 reduced_science_tag, reduced_sky_tag,
1988 if (skymedian || skylocal) {
1990 cpl_image_divide_scalar(mappeds[j], alltime);
1996 fors_pmos_science_exit(NULL, nscience);
2002 fors_pmos_science_exit(NULL, nscience);
2006 cpl_image_delete(mappeds[j]); mappeds[j] = NULL;
2007 cpl_propertylist_delete(header); header = NULL;
2011 cpl_table_delete(origslits);
2015 nobjects = cpl_image_get_size_y(reduceds[0]) / 2;
2016 nx = cpl_image_get_size_x(reduceds[0]);
2018 header = cpl_propertylist_new();
2019 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
2020 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
2021 cpl_propertylist_update_double(header,
"CRVAL1",
2022 startwavelength + (dispersion * group)/2);
2023 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
2024 cpl_propertylist_update_double(header,
"CD1_1", dispersion * group);
2025 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
2026 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
2027 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
2028 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
2029 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
2033 cpl_image *pv_im = NULL;
2034 cpl_image *pi_im = NULL;
2035 cpl_image *pvnull_im = NULL;
2036 cpl_image *pierr_im = NULL;
2037 cpl_image *perr_im = NULL;
2041 double *p_vnull = NULL;
2042 double *perr = NULL;
2043 double *pierr = NULL;
2050 pv_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2051 perr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2052 pi_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2053 pierr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2055 p_v = cpl_image_get_data_double(pv_im);
2056 perr = cpl_image_get_data_double(perr_im);
2057 p_i = cpl_image_get_data_double(pi_im);
2058 pierr = cpl_image_get_data_double(pierr_im);
2060 if (nscience / 2 > 1) {
2061 pvnull_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2062 p_vnull = cpl_image_get_data_double(pvnull_im);
2065 for (j = 0; j < nobjects; j++) {
2072 double * ip_v, * ip_i, * ipierr,
2073 * ip_vnull, * iperr;
2076 float * iff, * ierr;
2078 ip_v = p_v + (nobjects - 1 - j) * nx;
2080 if (nscience / 2 > 1)
2081 ip_vnull = p_vnull + (nobjects - 1 - j) * nx;
2083 iperr = perr + (nobjects - 1 - j) * nx;
2085 ip_i = p_i + (nobjects - 1 - j) * nx;
2086 ipierr = pierr + (nobjects - 1 - j) * nx;
2089 for (i = 0; i < nslits; i += 2) {
2090 total += nobjs_per_slit[i];
2097 for (
int k = 0; k < nscience / 2; k++) {
2098 float *if_o, *if_e, *ifdelta_o, *ifdelta_e;
2099 float *if_o_err, *if_e_err, *ifdelta_o_err, *ifdelta_e_err;
2101 int pos = fors_find_angle_pos(angles, nscience, 180 * k - 45);
2102 int pos_d = fors_find_angle_pos(angles, nscience, 180 * k + 45);
2105 data = cpl_image_get_data_float(reduceds[pos]);
2107 if_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2108 + (total - j - 1)) * nx;
2110 if_e = data + (2 * (nobjects - total)
2111 + (total - j - 1)) * nx;
2113 data = cpl_image_get_data_float(reduceds[pos_d]);
2115 ifdelta_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2116 + (total - j - 1)) * nx;
2118 ifdelta_e = data + (2 * (nobjects - total)
2119 + (total - j - 1)) * nx;
2121 data = cpl_image_get_data_float(rerrors[pos]);
2124 + (2 * (nobjects - total) + nobjs_per_slit[p]
2125 + (total - j - 1)) * nx;
2127 if_e_err = data + (2 * (nobjects - total)
2128 + (total - j - 1)) * nx;
2130 data = cpl_image_get_data_float(rerrors[pos_d]);
2132 ifdelta_o_err = data
2133 + (2 * (nobjects - total) + nobjs_per_slit[p]
2134 + (total - j - 1)) * nx;
2136 ifdelta_e_err = data + (2 * (nobjects - total)
2137 + (total - j - 1)) * nx;
2141 char *signal_to_noise = getenv(
"SIGNAL_TO_NOISE" );
2143 char *min_s2n = getenv(
"MIN_S2N" );
2146 if (signal_to_noise)
2147 s2n = atof(signal_to_noise);
2150 ms2n = atoi(min_s2n);
2159 for (m = 0; m < nx; m++) {
2160 if (if_o_err[m] > 0.0) {
2161 if (if_o[m]/if_o_err[m] > s2n) {
2163 if (bright > ms2n) {
2171 if (bright > ms2n) {
2173 filename = cpl_sprintf(
"angle_%d_%d.dat",
2175 file = fopen(filename,
"w");
2177 fprintf(file,
"%d\n", p + 2);
2179 for (m = 0; m < nx; m++) {
2180 double lambda = startwavelength
2181 + dispersion * group * (0.5 + m);
2182 fprintf(file,
"%.3f %.9e %.9e %.9e %.9e\n",
2183 lambda, if_o[m], if_o_err[m],
2184 if_e[m], if_e_err[m]);
2190 filename = cpl_sprintf(
"angle_%d_%d.dat",
2192 file = fopen(filename,
"w");
2194 fprintf(file,
"%d\n", p + 2);
2196 for (m = 0; m < nx; m++) {
2197 double lambda = startwavelength
2198 + dispersion * group * (0.5 + m);
2199 fprintf(file,
"%.3f %.9e %.9e %.9e %.9e\n",
2200 lambda, ifdelta_o[m], ifdelta_o_err[m],
2201 ifdelta_e[m], ifdelta_e_err[m]);
2208 cpl_msg_info(recipe,
2209 "Extracted signal not written to " 2210 "ASCII (S/N > %.0f only in %d < %d " 2211 "bins)", s2n, bright, ms2n);
2215 for (m = 0; m < nx; m++) {
2217 double quantity = if_o[m] + if_e[m] == 0.0 ? 0.0 :
2218 (if_o[m] - if_e[m] ) /
2219 (if_o[m] + if_e[m] ) -
2220 (ifdelta_o[m] - ifdelta_e[m]) /
2221 (ifdelta_o[m] + ifdelta_e[m]);
2223 quantity = isfinite(quantity) ? quantity : 0.0;
2226 ip_v[m] += quantity * 0.5 / (nscience / 2);
2229 if (nscience / 2 > 1) {
2231 ip_vnull[m] += quantity * 0.5 / (nscience / 2);
2233 ip_vnull[m] -= quantity * 0.5 / (nscience / 2);
2237 ip_i[m] += (if_o[m] + if_e[m] +
2238 ifdelta_o[m] + ifdelta_e[m]) / nscience;
2241 ipierr[m] += (if_o_err[m] * if_o_err[m]
2242 + if_e_err[m] * if_e_err[m]
2243 + ifdelta_o_err[m] * ifdelta_o_err[m]
2244 + ifdelta_e_err[m] * ifdelta_e_err[m])
2245 / nscience / nscience;
2251 data = cpl_image_get_data_float(reduceds[0]);
2252 iff = data + (2 * (nobjects - total) + (total - j - 1)) * nx;
2254 data = cpl_image_get_data_float(rerrors[0]);
2255 ierr = data + (2 * (nobjects - total) + (total - j - 1)) * nx;
2257 for (m = 0; m < nx; m++)
2258 iperr[m] = iff[m] <= 0.0 ?
2259 0.0 : ierr[m] / iff[m] * 0.5 / sqrt (nscience / 2);
2261 if (nscience / 2 > 1) {
2263 float max, sum, sum2, imean;
2268 weights = cpl_malloc(
sizeof(
float) * nx);
2271 for (k = 0; k < nx; k++) {
2272 if (max < iff[k]) max = iff[k];
2275 for (k = 0; k < nx; k++) {
2276 weights[k] = iff[k] < 0.0 ?
2277 0.0 : iff[k] * iff[k] / (max * max);
2282 for (k = 0; k < nx; k++) {
2283 sum += weights[k] * ip_vnull[k];
2291 mean_vnull += (imean - mean_vnull) / (j + 1.0);
2296 parlist, recipe, ref_sci_frame);
2297 if(cpl_error_get_code() != CPL_ERROR_NONE)
2298 fors_pmos_science_exit(NULL, nscience);
2301 parlist, recipe, ref_sci_frame);
2302 if(cpl_error_get_code() != CPL_ERROR_NONE)
2303 fors_pmos_science_exit(NULL, nscience);
2305 if (nscience / 2 > 1) {
2308 cpl_propertylist *qheader;
2311 cpl_propertylist_update_double(qheader,
"CRPIX1", 1.0);
2312 cpl_propertylist_update_double(qheader,
"CRPIX2", 1.0);
2313 cpl_propertylist_update_double(qheader,
"CRVAL1",
2314 startwavelength + (dispersion * group)/2);
2315 cpl_propertylist_update_double(qheader,
"CRVAL2", 1.0);
2316 cpl_propertylist_update_double(qheader,
"CD1_1",
2317 dispersion * group);
2318 cpl_propertylist_update_double(qheader,
"CD1_2", 0.0);
2319 cpl_propertylist_update_double(qheader,
"CD2_1", 0.0);
2320 cpl_propertylist_update_double(qheader,
"CD2_2", 1.0);
2321 cpl_propertylist_update_string(qheader,
"CTYPE1",
"LINEAR");
2322 cpl_propertylist_update_string(qheader,
"CTYPE2",
"PIXEL");
2332 "Product category", instrume))
2333 fors_pmos_science_exit(
"Cannot write product category to " 2334 "QC log file", nscience);
2337 "DPR type", instrume))
2338 fors_pmos_science_exit(
"Missing keyword DPR TYPE in " 2339 "scientific frame header", nscience);
2342 "Template", instrume))
2343 fors_pmos_science_exit(
"Missing keyword TPL ID in " 2344 "scientific frame header", nscience);
2347 "Grism name", instrume))
2348 fors_pmos_science_exit(
"Missing keyword INS GRIS1 NAME in " 2349 "scientific frame header", nscience);
2352 "Grism identifier", instrume))
2353 fors_pmos_science_exit(
"Missing keyword INS GRIS1 ID in " 2354 "scientific frame header", nscience);
2356 if (cpl_propertylist_has(qheader,
"ESO INS FILT1 NAME"))
2358 "Filter name", instrume);
2361 "Collimator name", instrume))
2362 fors_pmos_science_exit(
"Missing keyword INS COLL NAME in " 2363 "scientific frame header", nscience);
2366 "Chip identifier", instrume))
2367 fors_pmos_science_exit(
"Missing keyword DET CHIP1 ID in " 2368 "scientific frame header", nscience);
2371 "Archive name of input data",
2373 fors_pmos_science_exit(
"Missing keyword ARCFILE in " 2374 "scientific frame header", nscience);
2376 pipefile = dfs_generate_filename(reduced_nul_v_tag);
2378 "Pipeline product name", instrume))
2379 fors_pmos_science_exit(
"Cannot write PIPEFILE to " 2380 "QC log file", nscience);
2381 cpl_free(pipefile); pipefile = NULL;
2388 keyname =
"QC.NULL.V.MEAN";
2392 "Mean V null parameter",
2394 fors_pmos_science_exit(
"Cannot write mean Q null " 2395 "parameter to QC log file.", nscience);
2398 keyname =
"QC.NANGLES";
2400 if (fors_qc_write_qc_int(qheader, nscience,
2402 "Number of processed plate angles",
2404 fors_pmos_science_exit(
"Cannot write number of processed " 2405 "plate angles.", nscience);
2412 parlist, recipe, ref_sci_frame);
2413 if(cpl_error_get_code() != CPL_ERROR_NONE)
2414 fors_pmos_science_exit(NULL, nscience);
2416 cpl_propertylist_delete(qheader);
2420 parlist, recipe, ref_sci_frame);
2421 if(cpl_error_get_code() != CPL_ERROR_NONE)
2422 fors_pmos_science_exit(NULL, nscience);
2424 cpl_image_power(pierr_im, 0.5);
2427 parlist, recipe, ref_sci_frame);
2428 if(cpl_error_get_code() != CPL_ERROR_NONE)
2429 fors_pmos_science_exit(NULL, nscience);
2431 cpl_image_delete(pv_im);
2432 cpl_image_delete(pvnull_im);
2433 cpl_image_delete(perr_im);
2434 cpl_image_delete(pi_im);
2435 cpl_image_delete(pierr_im);
2438 cpl_image *pq_im = NULL;
2439 cpl_image *pu_im = NULL;
2440 cpl_image *pl_im = NULL;
2441 cpl_image *pi_im = NULL;
2443 cpl_image *pqnull_im = NULL;
2444 cpl_image *punull_im = NULL;
2446 cpl_image *pqerr_im = NULL;
2447 cpl_image *puerr_im = NULL;
2448 cpl_image *plerr_im = NULL;
2449 cpl_image *pierr_im = NULL;
2451 cpl_image *pang_im = NULL;
2452 cpl_image *pangerr_im = NULL;
2459 double *p_qnull = NULL;
2460 double *p_unull = NULL;
2462 double *pqerr = NULL;
2463 double *puerr = NULL;
2464 double *plerr = NULL;
2465 double *pierr = NULL;
2467 double *pang = NULL;
2468 double *pangerr = NULL;
2472 cpl_image *correct_im = cpl_image_new(nx, 1, CPL_TYPE_DOUBLE);
2473 double *correct = cpl_image_get_data_double(correct_im);
2475 double mean_unull, mean_qnull;
2480 pq_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2481 pu_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2482 pl_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2483 pi_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2485 pqerr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2486 puerr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2487 plerr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2488 pierr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2490 pang_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2491 pangerr_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2493 p_q = cpl_image_get_data_double(pq_im);
2494 p_u = cpl_image_get_data_double(pu_im);
2495 p_l = cpl_image_get_data_double(pl_im);
2496 p_i = cpl_image_get_data_double(pi_im);
2498 if (nscience / 4 > 1) {
2499 pqnull_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2500 punull_im = cpl_image_new(nx, nobjects, CPL_TYPE_DOUBLE);
2502 p_qnull = cpl_image_get_data_double(pqnull_im);
2503 p_unull = cpl_image_get_data_double(punull_im);
2505 cpl_msg_warning(cpl_func,
2506 "Not enough pairs to compute null parameters");
2509 pqerr = cpl_image_get_data_double(pqerr_im);
2510 puerr = cpl_image_get_data_double(puerr_im);
2511 plerr = cpl_image_get_data_double(plerr_im);
2512 pierr = cpl_image_get_data_double(pierr_im);
2514 pang = cpl_image_get_data_double(pang_im);
2515 pangerr = cpl_image_get_data_double(pangerr_im);
2518 cpl_table * chrotbl =
2521 int nrow = cpl_table_get_nrow(chrotbl);
2522 float * lambda = cpl_table_get_data_float(chrotbl,
"lambda");
2523 float * theta = cpl_table_get_data_float(chrotbl,
"eps_theta");
2525 for (j = 0; j < nx; j++) {
2526 double c_wave = startwavelength
2527 + (dispersion * group) / 2
2528 + j * dispersion * group;
2533 for (k = 0; k < nrow - 1; k++) {
2534 if (lambda[k] <= c_wave && c_wave < lambda[k + 1]) {
2541 correct[j] = (theta [k + 1] - theta [k]) /
2542 (lambda[k + 1] - lambda[k]) *
2543 (c_wave - lambda[k]) + theta[k];
2544 correct[j] *= M_PI / 180;
2547 correct[j] = correct[j-1];
2552 cpl_table_delete(chrotbl);
2555 for (j = 0; j < nobjects; j++) {
2577 ip_q = p_q + (nobjects - 1 - j) * nx;
2578 ip_u = p_u + (nobjects - 1 - j) * nx;
2579 ip_l = p_l + (nobjects - 1 - j) * nx;
2580 ip_i = p_i + (nobjects - 1 - j) * nx;
2582 if (nscience / 4 > 1) {
2583 ip_qnull = p_qnull + (nobjects - 1 - j) * nx;
2584 ip_unull = p_unull + (nobjects - 1 - j) * nx;
2587 ipqerr = pqerr + (nobjects - 1 - j) * nx;
2588 ipuerr = puerr + (nobjects - 1 - j) * nx;
2589 iplerr = plerr + (nobjects - 1 - j) * nx;
2590 ipierr = pierr + (nobjects - 1 - j) * nx;
2592 ipang = pang + (nobjects - 1 - j) * nx;
2593 ipangerr = pangerr + (nobjects - 1 - j) * nx;
2596 for (i = 0; i < nslits; i += 2) {
2597 total += nobjs_per_slit[i];
2604 for (
int k = 0; k < nscience / 4; k++) {
2605 float * if_o, * if_e, * ifdelta_o, * ifdelta_e;
2606 float * if_o_err, * if_e_err, * ifdelta_o_err, * ifdelta_e_err;
2610 pos = fors_find_angle_pos(angles, nscience, 90 * k);
2611 pos_d = fors_find_angle_pos(angles, nscience, 90 * k + 45);
2613 data = cpl_image_get_data_float(reduceds[pos]);
2615 if_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2616 + (total - j - 1)) * nx;
2618 if_e = data + (2 * (nobjects - total)
2619 + (total - j - 1)) * nx;
2621 data = cpl_image_get_data_float(reduceds[pos_d]);
2623 ifdelta_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2624 + (total - j - 1)) * nx;
2626 ifdelta_e = data + (2 * (nobjects - total)
2627 + (total - j - 1)) * nx;
2629 data = cpl_image_get_data_float(rerrors[pos]);
2631 if_o_err = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2632 + (total - j - 1)) * nx;
2634 if_e_err = data + (2 * (nobjects - total)
2635 + (total - j - 1)) * nx;
2637 data = cpl_image_get_data_float(rerrors[pos_d]);
2639 ifdelta_o_err = data + (2 * (nobjects - total)
2640 + nobjs_per_slit[p] + (total - j - 1)) * nx;
2642 ifdelta_e_err = data + (2 * (nobjects - total)
2643 + (total - j - 1)) * nx;
2645 for (m = 0; m < nx; m++) {
2647 double quantity = fabs(if_o[m] + if_e[m]) < FLT_MIN ? 0.0 :
2648 (if_o[m] - if_e[m] ) /
2649 (if_o[m] + if_e[m] ) -
2650 (ifdelta_o[m] - ifdelta_e[m]) /
2651 (ifdelta_o[m] + ifdelta_e[m]);
2653 quantity = isfinite(quantity) ? quantity : 0.0;
2656 ip_q[m] += quantity * 0.5 / (nscience / 4);
2659 if (nscience / 4 > 1) {
2661 ip_qnull[m] += quantity * 0.5 / (nscience / 4);
2663 ip_qnull[m] -= quantity * 0.5 / (nscience / 4);
2667 ip_i[m] += (if_o[m] + if_e[m] +
2668 ifdelta_o[m] + ifdelta_e[m]) / nscience;
2671 ipierr[m] += (if_o_err[m] * if_o_err[m]
2672 + if_e_err[m] * if_e_err[m]
2673 + ifdelta_o_err[m] * ifdelta_o_err[m]
2674 + ifdelta_e_err[m] * ifdelta_e_err[m])
2675 / nscience / nscience;
2680 pos = fors_find_angle_pos(angles, nscience, 90 * k + 22.5);
2681 pos_d = fors_find_angle_pos(angles, nscience, 90 * k + 67.5);
2683 data = cpl_image_get_data_float(reduceds[pos]);
2685 if_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2686 + (total - j - 1)) * nx;
2688 if_e = data + (2 * (nobjects - total)
2689 + (total - j - 1)) * nx;
2691 data = cpl_image_get_data_float(reduceds[pos_d]);
2693 ifdelta_o = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2694 + (total - j - 1)) * nx;
2696 ifdelta_e = data + (2 * (nobjects - total)
2697 + (total - j - 1)) * nx;
2699 data = cpl_image_get_data_float(rerrors[pos]);
2701 if_o_err = data + (2 * (nobjects - total) + nobjs_per_slit[p]
2702 + (total - j - 1)) * nx;
2704 if_e_err = data + (2 * (nobjects - total)
2705 + (total - j - 1)) * nx;
2707 data = cpl_image_get_data_float(rerrors[pos_d]);
2709 ifdelta_o_err = data + (2 * (nobjects - total)
2710 + nobjs_per_slit[p] + (total - j - 1)) * nx;
2712 ifdelta_e_err = data + (2 * (nobjects - total)
2713 + (total - j - 1)) * nx;
2715 for (m = 0; m < nx; m++) {
2717 double quantity = fabs(if_o[m] + if_e[m]) < FLT_MIN ? 0.0 :
2718 (if_o[m] - if_e[m] ) /
2719 (if_o[m] + if_e[m] ) -
2720 (ifdelta_o[m] - ifdelta_e[m]) /
2721 (ifdelta_o[m] + ifdelta_e[m]);
2723 quantity = isfinite(quantity) ? quantity : 0.0;
2726 ip_u[m] += quantity * 0.5 / (nscience / 4);
2729 if (nscience / 4 > 1) {
2731 ip_unull[m] += quantity * 0.5 / (nscience / 4);
2733 ip_unull[m] -= quantity * 0.5 / (nscience / 4);
2737 ip_i[m] += (if_o[m] + if_e[m] +
2738 ifdelta_o[m] + ifdelta_e[m]) / nscience;
2741 ipierr[m] += (if_o_err[m] * if_o_err[m]
2742 + if_e_err[m] * if_e_err[m]
2743 + ifdelta_o_err[m] * ifdelta_o_err[m]
2744 + ifdelta_e_err[m] * ifdelta_e_err[m])
2745 / nscience / nscience;
2751 pos = fors_find_angle_pos(angles, nscience, 0.0);
2753 data = cpl_image_get_data_float(reduceds[pos]);
2754 iffq = data + (2 * (nobjects - total) + (total - j - 1)) * nx;
2756 data = cpl_image_get_data_float(rerrors[pos]);
2757 ierrq = data + (2 * (nobjects - total) + (total - j - 1)) * nx;
2759 pos = fors_find_angle_pos(angles, nscience, 22.5);
2761 data = cpl_image_get_data_float(reduceds[pos]);
2762 iffu = data + (2 * (nobjects - total) + (total - j - 1)) * nx;
2764 data = cpl_image_get_data_float(rerrors[pos]);
2765 ierru = data + (2 * (nobjects - total) + (total - j - 1)) * nx;
2767 for (m = 0; m < nx; m++) {
2771 ipqerr[m] = iffq[m] <= 0.0 ?
2772 0.0 : ierrq[m] / iffq[m] * 0.5 / sqrt (nscience / 4);
2774 ipuerr[m] = iffu[m] <= 0.0 ?
2775 0.0 : ierru[m] / iffu[m] * 0.5 / sqrt (nscience / 4);
2777 iplerr[m] = 0.5 * (ipqerr[m] + ipuerr[m]);
2780 ip_l[m] = sqrt(ip_u[m] * ip_u[m] + ip_q[m] * ip_q[m]);
2783 if (fabs(ip_q[m]) < 0.00001) {
2784 if (ip_u[m] > 0.0) {
2792 ipang[m] = 0.5 * atan(ip_u[m] / ip_q[m]) * 180 / M_PI;
2793 if (ip_q[m] > 0.0) {
2794 if (ip_u[m] < 0.0) {
2804 radicand = ip_q[m] * ip_q[m] * ipuerr[m] * ipuerr[m] +
2805 ip_u[m] * ip_u[m] * ipqerr[m] * ipqerr[m];
2807 ipangerr[m] = (ip_l[m] == 0.0 ? 0.0 :
2808 sqrt(radicand) * 0.5 / (ip_l[m] * ip_l[m]) * 180 / M_PI);
2817 if (instrume[4] ==
'2') {
2819 double w_rotation = - wollaston * M_PI / 2;
2821 ipang[m] -= w_rotation * 180 / M_PI;
2823 ip_q[m] = ip_q[m] * cos(2 * w_rotation)
2824 + ip_u[m] * sin(2 * w_rotation);
2826 ip_u[m] = ip_u[m] * cos(2 * w_rotation)
2827 - ip_q[m] * sin(2 * w_rotation);
2831 ipang[m] -= correct[m] * 180 / M_PI;
2833 ip_q[m] = ip_q[m] * cos(2 * correct[m])
2834 + ip_u[m] * sin(2 * correct[m]);
2836 ip_u[m] = ip_u[m] * cos(2 * correct[m])
2837 - ip_q[m] * sin(2 * correct[m]);
2842 else if (ipang[m] >= 180.0)
2846 if (nscience / 4 > 1) {
2848 float max, sum, sum2, imean;
2853 weights = cpl_malloc(
sizeof(
float) * nx);
2856 for (k = 0; k < nx; k++) {
2857 if (max < iffq[k]) max = iffq[k];
2860 for (k = 0; k < nx; k++) {
2861 weights[k] = iffq[k] < 0.0 ?
2862 0.0 : iffq[k] * iffq[k] / (max * max);
2867 for (k = 0; k < nx; k++) {
2868 sum += weights[k] * ip_qnull[k];
2876 mean_qnull += (imean - mean_qnull) / (j + 1.0);
2879 weights = cpl_malloc(
sizeof(
float) * nx);
2882 for (k = 0; k < nx; k++) {
2883 if (max < iffu[k]) max = iffu[k];
2886 for (k = 0; k < nx; k++) {
2887 weights[k] = iffu[k] < 0.0 ?
2888 0.0 : iffu[k] * iffu[k] / (max * max);
2893 for (k = 0; k < nx; k++) {
2894 sum += weights[k] * ip_unull[k];
2902 mean_unull += (imean - mean_unull) / (j + 1.0);
2906 cpl_image_delete(correct_im);
2909 parlist, recipe, ref_sci_frame);
2910 if(cpl_error_get_code() != CPL_ERROR_NONE)
2911 fors_pmos_science_exit(NULL, nscience);
2914 parlist, recipe, ref_sci_frame);
2915 if(cpl_error_get_code() != CPL_ERROR_NONE)
2916 fors_pmos_science_exit(NULL, nscience);
2918 if (qc && standard) {
2919 cpl_table *polsta =
dfs_load_table(frameset, std_pmos_table_tag, 1);
2922 cpl_propertylist_update_double(qheader,
"CRPIX1", 1.0);
2923 cpl_propertylist_update_double(qheader,
"CRPIX2", 1.0);
2924 cpl_propertylist_update_double(qheader,
"CRVAL1",
2925 startwavelength + (dispersion * group)/2);
2926 cpl_propertylist_update_double(qheader,
"CRVAL2", 1.0);
2927 cpl_propertylist_update_double(qheader,
"CD1_1",
2928 dispersion * group);
2929 cpl_propertylist_update_double(qheader,
"CD1_2", 0.0);
2930 cpl_propertylist_update_double(qheader,
"CD2_1", 0.0);
2931 cpl_propertylist_update_double(qheader,
"CD2_2", 1.0);
2932 cpl_propertylist_update_string(qheader,
"CTYPE1",
"LINEAR");
2933 cpl_propertylist_update_string(qheader,
"CTYPE2",
"PIXEL");
2936 startwavelength, dispersion, 1000.,
2937 polsta, ra, dec, &filter,
2940 &qc_angle, &qc_angle_err)) {
2941 cpl_msg_warning(cpl_func,
"No QC can be computed");
2947 char band[] = {
' ',
'\0'};
2956 "Product category", instrume))
2957 fors_pmos_science_exit(
"Cannot write product category to " 2958 "QC log file", nscience);
2961 "DPR type", instrume))
2962 fors_pmos_science_exit(
"Missing keyword DPR TYPE in " 2963 "scientific frame header", nscience);
2966 "Template", instrume))
2967 fors_pmos_science_exit(
"Missing keyword TPL ID in " 2968 "scientific frame header", nscience);
2971 "Grism name", instrume))
2972 fors_pmos_science_exit(
"Missing keyword INS GRIS1 NAME in " 2973 "scientific frame header", nscience);
2976 "Grism identifier", instrume))
2977 fors_pmos_science_exit(
"Missing keyword INS GRIS1 ID in " 2978 "scientific frame header", nscience);
2980 if (cpl_propertylist_has(qheader,
"ESO INS FILT1 NAME"))
2982 "Filter name", instrume);
2985 "Collimator name", instrume))
2986 fors_pmos_science_exit(
"Missing keyword INS COLL NAME in " 2987 "scientific frame header", nscience);
2990 "Chip identifier", instrume))
2991 fors_pmos_science_exit(
"Missing keyword DET CHIP1 ID in " 2992 "scientific frame header", nscience);
2995 "Archive name of input data",
2997 fors_pmos_science_exit(
"Missing keyword ARCFILE in " 2998 "scientific frame header", nscience);
3000 pipefile = dfs_generate_filename(reduced_nul_q_tag);
3002 "Pipeline product name", instrume))
3003 fors_pmos_science_exit(
"Cannot write PIPEFILE to " 3004 "QC log file", nscience);
3005 cpl_free(pipefile); pipefile = NULL;
3012 keyname =
"QC.PMOS.BAND";
3016 "Band where polarisation was " 3017 "measured", instrume)) {
3018 fors_pmos_science_exit(
"Cannot write QC.PMOS.BAND " 3019 "parameter to QC log file", nscience);
3022 keyname =
"QC.PMOS.POLARISED";
3024 if (fors_qc_write_qc_int(qheader, polarised, keyname, NULL,
3025 "Polarisation is expected (1 = yes, " 3026 "0 = no)", instrume)) {
3027 fors_pmos_science_exit(
"Cannot write QC.PMOS.POLARISED " 3028 "parameter to QC log file", nscience);
3031 keyname =
"QC.PMOS.L.OFFSET";
3034 text =
"Linear polarisation relative offset";
3036 text =
"Linear polarisation offset";
3040 fors_pmos_science_exit(
"Cannot write linear polarisation " 3041 "offset to QC log file", nscience);
3044 keyname =
"QC.PMOS.L.OFFSETERR";
3047 "Error on linear polarisation offset",
3049 fors_pmos_science_exit(
"Cannot write linear polarisation " 3050 "offset error to QC log file", nscience);
3054 keyname =
"QC.PMOS.ANGLE.OFFSET";
3057 "Polarisation angle offset",
3059 fors_pmos_science_exit(
"Cannot write polarisation " 3060 "angle offset to QC log file", nscience);
3063 keyname =
"QC.PMOS.ANGLE.OFFSETERR";
3066 NULL,
"Error on polarisation " 3067 "angle offset", instrume)) {
3068 fors_pmos_science_exit(
"Cannot write polarisation " 3069 "angle offset error to QC " 3070 "log file", nscience);
3078 parlist, recipe, ref_sci_frame);
3079 if(cpl_error_get_code() != CPL_ERROR_NONE)
3080 fors_pmos_science_exit(NULL, nscience);
3082 cpl_propertylist_delete(qheader);
3086 parlist, recipe, ref_sci_frame);
3087 if(cpl_error_get_code() != CPL_ERROR_NONE)
3088 fors_pmos_science_exit(NULL, nscience);
3091 if (nscience / 4 > 1) {
3097 cpl_propertylist_update_double(qheader,
"CRPIX1", 1.0);
3098 cpl_propertylist_update_double(qheader,
"CRPIX2", 1.0);
3099 cpl_propertylist_update_double(qheader,
"CRVAL1",
3100 startwavelength + (dispersion * group)/2);
3101 cpl_propertylist_update_double(qheader,
"CRVAL2", 1.0);
3102 cpl_propertylist_update_double(qheader,
"CD1_1",
3103 dispersion * group);
3104 cpl_propertylist_update_double(qheader,
"CD1_2", 0.0);
3105 cpl_propertylist_update_double(qheader,
"CD2_1", 0.0);
3106 cpl_propertylist_update_double(qheader,
"CD2_2", 1.0);
3107 cpl_propertylist_update_string(qheader,
"CTYPE1",
"LINEAR");
3108 cpl_propertylist_update_string(qheader,
"CTYPE2",
"PIXEL");
3118 "Product category", instrume))
3119 fors_pmos_science_exit(
"Cannot write product category to " 3120 "QC log file", nscience);
3123 "DPR type", instrume))
3124 fors_pmos_science_exit(
"Missing keyword DPR TYPE in " 3125 "scientific frame header", nscience);
3128 "Template", instrume))
3129 fors_pmos_science_exit(
"Missing keyword TPL ID in " 3130 "scientific frame header", nscience);
3133 "Grism name", instrume))
3134 fors_pmos_science_exit(
"Missing keyword INS GRIS1 NAME in " 3135 "scientific frame header", nscience);
3138 "Grism identifier", instrume))
3139 fors_pmos_science_exit(
"Missing keyword INS GRIS1 ID in " 3140 "scientific frame header", nscience);
3142 if (cpl_propertylist_has(qheader,
"ESO INS FILT1 NAME"))
3144 "Filter name", instrume);
3147 "Collimator name", instrume))
3148 fors_pmos_science_exit(
"Missing keyword INS COLL NAME in " 3149 "scientific frame header", nscience);
3152 "Chip identifier", instrume))
3153 fors_pmos_science_exit(
"Missing keyword DET CHIP1 ID in " 3154 "scientific frame header", nscience);
3157 "Archive name of input data",
3159 fors_pmos_science_exit(
"Missing keyword ARCFILE in " 3160 "scientific frame header", nscience);
3162 pipefile = dfs_generate_filename(reduced_nul_q_tag);
3164 "Pipeline product name", instrume))
3165 fors_pmos_science_exit(
"Cannot write PIPEFILE to " 3166 "QC log file", nscience);
3167 cpl_free(pipefile); pipefile = NULL;
3174 keyname =
"QC.NULL.Q.MEAN";
3178 "Mean Q null parameter",
3180 fors_pmos_science_exit(
"Cannot write mean Q null " 3181 "parameter to QC log file", nscience);
3184 keyname =
"QC.NANGLES";
3186 if (fors_qc_write_qc_int(qheader, nscience / 2,
3188 "Number of processed plate angles",
3190 fors_pmos_science_exit(
"Cannot write number of processed " 3191 "plate angles.", nscience);
3198 parlist, recipe, ref_sci_frame);
3199 if(cpl_error_get_code() != CPL_ERROR_NONE)
3200 fors_pmos_science_exit(NULL, nscience);
3202 cpl_propertylist_delete(qheader);
3206 cpl_propertylist_update_double(qheader,
"CRPIX1", 1.0);
3207 cpl_propertylist_update_double(qheader,
"CRPIX2", 1.0);
3208 cpl_propertylist_update_double(qheader,
"CRVAL1",
3209 startwavelength + (dispersion * group)/2);
3210 cpl_propertylist_update_double(qheader,
"CRVAL2", 1.0);
3211 cpl_propertylist_update_double(qheader,
"CD1_1",
3212 dispersion * group);
3213 cpl_propertylist_update_double(qheader,
"CD1_2", 0.0);
3214 cpl_propertylist_update_double(qheader,
"CD2_1", 0.0);
3215 cpl_propertylist_update_double(qheader,
"CD2_2", 1.0);
3216 cpl_propertylist_update_string(qheader,
"CTYPE1",
"LINEAR");
3217 cpl_propertylist_update_string(qheader,
"CTYPE2",
"PIXEL");
3227 "Product category", instrume))
3228 fors_pmos_science_exit(
"Cannot write product category to " 3229 "QC log file", nscience);
3232 "DPR type", instrume))
3233 fors_pmos_science_exit(
"Missing keyword DPR TYPE in " 3234 "scientific frame header", nscience);
3237 "Template", instrume))
3238 fors_pmos_science_exit(
"Missing keyword TPL ID in " 3239 "scientific frame header", nscience);
3242 "Grism name", instrume))
3243 fors_pmos_science_exit(
"Missing keyword INS GRIS1 NAME in " 3244 "scientific frame header", nscience);
3247 "Grism identifier", instrume))
3248 fors_pmos_science_exit(
"Missing keyword INS GRIS1 ID in " 3249 "scientific frame header", nscience);
3251 if (cpl_propertylist_has(qheader,
"ESO INS FILT1 NAME"))
3253 "Filter name", instrume);
3256 "Collimator name", instrume))
3257 fors_pmos_science_exit(
"Missing keyword INS COLL NAME in " 3258 "scientific frame header", nscience);
3261 "Chip identifier", instrume))
3262 fors_pmos_science_exit(
"Missing keyword DET CHIP1 ID in " 3263 "scientific frame header", nscience);
3266 "Archive name of input data",
3268 fors_pmos_science_exit(
"Missing keyword ARCFILE in " 3269 "scientific frame header", nscience);
3271 pipefile = dfs_generate_filename(reduced_nul_u_tag);
3273 "Pipeline product name", instrume))
3274 fors_pmos_science_exit(
"Cannot write PIPEFILE to " 3275 "QC log file", nscience);
3276 cpl_free(pipefile); pipefile = NULL;
3283 keyname =
"QC.NULL.U.MEAN";
3287 "Mean U null parameter",
3289 fors_pmos_science_exit(
"Cannot write mean U null " 3290 "parameter to QC log file", nscience);
3293 keyname =
"QC.NANGLES";
3295 if (fors_qc_write_qc_int(qheader, nscience / 2,
3297 "Number of processed plate angles",
3299 fors_pmos_science_exit(
"Cannot write number of processed " 3300 "plate angles.", nscience);
3307 parlist, recipe, ref_sci_frame);
3308 if(cpl_error_get_code() != CPL_ERROR_NONE)
3309 fors_pmos_science_exit(NULL, nscience);
3311 cpl_propertylist_delete(qheader);
3315 parlist, recipe, ref_sci_frame);
3316 if(cpl_error_get_code() != CPL_ERROR_NONE)
3317 fors_pmos_science_exit(NULL, nscience);
3320 parlist, recipe, ref_sci_frame);
3321 if(cpl_error_get_code() != CPL_ERROR_NONE)
3322 fors_pmos_science_exit(NULL, nscience);
3325 parlist, recipe, ref_sci_frame);
3326 if(cpl_error_get_code() != CPL_ERROR_NONE)
3327 fors_pmos_science_exit(NULL, nscience);
3330 parlist, recipe, ref_sci_frame);
3331 if(cpl_error_get_code() != CPL_ERROR_NONE)
3332 fors_pmos_science_exit(NULL, nscience);
3335 header, parlist, recipe, ref_sci_frame);
3336 if(cpl_error_get_code() != CPL_ERROR_NONE)
3337 fors_pmos_science_exit(NULL, nscience);
3340 header, parlist, recipe, ref_sci_frame);
3341 if(cpl_error_get_code() != CPL_ERROR_NONE)
3342 fors_pmos_science_exit(NULL, nscience);
3344 cpl_image_power(pierr_im, 0.5);
3347 header, parlist, recipe, ref_sci_frame);
3348 if(cpl_error_get_code() != CPL_ERROR_NONE)
3349 fors_pmos_science_exit(NULL, nscience);
3353 cpl_image_delete(pq_im);
3354 cpl_image_delete(pu_im);
3355 cpl_image_delete(pl_im);
3356 cpl_image_delete(pi_im);
3358 cpl_image_delete(pqnull_im);
3359 cpl_image_delete(punull_im);
3361 cpl_image_delete(pqerr_im);
3362 cpl_image_delete(puerr_im);
3363 cpl_image_delete(plerr_im);
3364 cpl_image_delete(pierr_im);
3365 cpl_image_delete(pang_im);
3366 cpl_image_delete(pangerr_im);
3369 cpl_propertylist_delete(header);
3373 for (j = 0; j < nscience; j++) {
3374 cpl_image_delete(reduceds[j]);
3375 cpl_image_delete(rerrors[j]);
3376 cpl_table_delete(slitss[j]);
3377 cpl_image_delete(mappeds[j]);
3385 cpl_free(instrume); instrume = NULL;
3387 cpl_free(skylocalmaps);
3389 cpl_free(nobjs_per_slit);
3391 if (cpl_error_get_code()) {
3392 cpl_msg_error(cpl_error_get_where(),
"%s", cpl_error_get_message());
3393 fors_pmos_science_exit(NULL, nscience);
3411 static float * fors_check_angles(cpl_frameset * frameset,
3412 int pmos,
const char *tag,
int * circ)
3414 float *angles = NULL;
3415 cpl_frame *c_frame = NULL;
3416 char *ret_id = NULL;
3420 angles = cpl_malloc(
sizeof(
float) * pmos);
3422 for (c_frame = cpl_frameset_find(frameset, tag);
3423 c_frame != NULL; c_frame = cpl_frameset_find(frameset, NULL)) {
3425 cpl_propertylist * header =
3426 cpl_propertylist_load(cpl_frame_get_filename(c_frame), 0);
3429 ret_id = cpl_strdup(cpl_propertylist_get_string(header,
3430 "ESO INS OPTI4 ID"));
3432 if (ret_id[1] !=
'5' && ret_id[1] !=
'4') {
3433 cpl_msg_error(cpl_func,
3434 "Unknown retarder plate id: %s", ret_id);
3438 char * c_ret_id = (
char *)
3439 cpl_propertylist_get_string(header,
"ESO INS OPTI4 ID");
3440 if (ret_id[1] != c_ret_id[1]) {
3441 cpl_msg_error(cpl_func,
"Input frames are not from the same " 3447 if (ret_id[1] ==
'5') {
3448 if (cpl_propertylist_has(header,
"ESO INS RETA2 ROT")) {
3449 angles[i] = (float)floor(2*cpl_propertylist_get_double(header,
3450 "ESO INS RETA2 ROT") + 0.5)/2;
3452 else if (cpl_propertylist_has(header,
"ESO INS RETA2 POSANG")) {
3453 if (cpl_propertylist_has(header,
"ESO ADA POSANG")) {
3454 double reta2pos = cpl_propertylist_get_double(header,
3455 "ESO INS RETA2 POSANG");
3456 double adapos = cpl_propertylist_get_double(header,
3458 angles[i] = (float)floor(2*(reta2pos - adapos) + 0.5)/2;
3461 cpl_msg_error(cpl_func,
3462 "ESO ADA POSANG not found in header");
3467 cpl_msg_error(cpl_func,
"Neither ESO INS RETA2 ROT nor " 3468 "ESO INS RETA2 POSANG found in header");
3473 if (cpl_propertylist_has(header,
"ESO INS RETA4 ROT")) {
3474 angles[i] = (float)floor(2*cpl_propertylist_get_double(header,
3475 "ESO INS RETA4 ROT") + 0.5)/2;
3478 angles[i] = angles[i] + 360;
3480 else if (cpl_propertylist_has(header,
"ESO INS RETA4 POSANG")) {
3481 if (cpl_propertylist_has(header,
"ESO ADA POSANG")) {
3482 double reta4pos = cpl_propertylist_get_double(header,
3483 "ESO INS RETA4 POSANG");
3484 double adapos = cpl_propertylist_get_double(header,
3486 angles[i] = (float)floor(2*(reta4pos - adapos) + 0.5/2);
3489 cpl_msg_error(cpl_func,
3490 "ESO ADA POSANG not found in header");
3495 cpl_msg_error(cpl_func,
"Neither ESO INS RETA4 ROT nor " 3496 "ESO INS RETA4 POSANG found in header");
3502 cpl_propertylist_delete(header);
3509 if (pmos != 2 && pmos != 4) {
3510 cpl_msg_error(cpl_func,
"Wrong angle configuration: %d angles " 3511 "found, but either 2 or 4 are required for " 3512 "circular polarization measurements!", pmos);
3516 if (pmos != 4 && pmos != 8 && pmos != 16) {
3517 cpl_msg_error(cpl_func,
"Wrong angle configuration: %d angles " 3518 "found, but either 4, 8, or 16 are required for " 3519 "linear polarization measurements!", pmos);
3527 for (i = 0; i < pmos; i++) {
3528 if (fors_find_angle_pos(angles, pmos, 90.0 * i - 45.0) < 0) {
3529 const char *cangles;
3531 case 2: cangles =
"-45.0, 45.0";
break;
3532 case 4: cangles =
"-45.0, 45.0, 135.0, 225.0";
break;
3536 cpl_msg_error(cpl_func,
"Wrong angle configuration: missing " 3537 "angle %.2f. All angles %s must be provided.",
3538 angles[i], cangles);
3544 for (i = 0; i < pmos; i++) {
3545 if (fors_find_angle_pos(angles, pmos, 22.5 * i) < 0) {
3546 const char *cangles;
3548 case 4: cangles =
"0.0, 22.5, 45.0, 67.5";
break;
3549 case 8: cangles =
"0.0, 22.5, 45.0, 67.5, " 3550 "90.0, 112.5, 135.0, 157.5";
break;
3551 case 16: cangles =
"0.0, 22.5, 45.0, 67.5, " 3552 "90.0, 112.5, 135.0, 157.5, " 3553 "180.0, 202.5, 225.0, 247.5, " 3554 "270.0, 292.5, 315.0, 337.5";
break;
3558 cpl_msg_error(cpl_func,
"Wrong angle configuration: missing " 3559 "angle %.2f. All angles %s must be provided.",
3560 angles[i], cangles);
3579 fors_find_angle_pos(
float * angles,
int nangles,
float angle)
3583 for (i = 0; i < nangles; i++) {
3584 if (fabs(angles[i] - angle) < 1.0 ||
3585 fabs(angles[i] - 360.0 - angle) < 1.0) {
3591 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.