37 #include <fors_stack.h>
39 #include <fors_header.h>
44 static int fors_pmos_calib_create(cpl_plugin *);
45 static int fors_pmos_calib_exec(cpl_plugin *);
46 static int fors_pmos_calib_destroy(cpl_plugin *);
47 static int fors_pmos_calib(cpl_parameterlist *, cpl_frameset *);
49 static char fors_pmos_calib_description[] =
50 "This recipe is used to identify reference lines on PMOS arc lamp\n"
51 "exposures, and trace the spectral edges on the corresponding flat field\n"
52 "exposures. This information is used to determine the spectral extraction\n"
53 "mask to be applied in the scientific data reduction, performed with the\n"
54 "recipe fors_science.\n"
55 "This recipe accepts both FORS1 and FORS2 frames. The input arc lamps and\n"
56 "flat field exposures are assumed to be obtained quasi-simultaneously, so\n"
57 "that they would be described by exactly the same instrument distortions.\n"
58 "A line catalog must be specified, containing the wavelengths of the\n"
59 "reference arc lamp lines used for the wavelength calibration. A grism\n"
60 "table (typically depending on the instrument mode, and in particular on\n"
61 "the grism used) may also be specified: this table contains a default\n"
62 "recipe parameter setting to control the way spectra are extracted for\n"
63 "a specific instrument mode, as it is used for automatic run of the\n"
64 "pipeline on Paranal and in Garching. If this table is specified, it\n"
65 "will modify the default recipe parameter setting, with the exception of\n"
66 "those parameters which have been explicitly modifyed on the command line.\n"
67 "If a grism table is not specified, the input recipe parameters values\n"
68 "will always be read from the command line, or from an esorex configuration\n"
69 "file if present, or from their generic default values (that are rarely\n"
70 "meaningful). Finally a master bias frame must be input to this recipe.\n"
71 "The products SPECTRA_DETECTION_PMOS, SLIT_MAP_PMOS, and DISP_RESIDUALS_PMOS,\n"
72 "are just created if the --check parameter is set to true.\n"
73 "The MASTER_DISTORTION_TABLE is marked as required, but it is not so if all\n"
74 "slits have different offsets, and in the case of FORS1 observations made\n"
75 "with the old TK2048EB4-1 1604 chip read in windowed mode (2048x400)\n\n"
77 " DO category: Type: Explanation: Required:\n"
78 " SCREEN_FLAT_PMOS Raw Flat field exposures Y\n"
79 " LAMP_PMOS Raw Arc lamp exposure Y\n"
80 " MASTER_BIAS or BIAS Calib Bias frame Y\n"
81 " MASTER_LINECAT Calib Line catalog Y\n"
82 " GRISM_TABLE Calib Grism table .\n"
83 " MASTER_DISTORTION_TABLE Calib Master distortions table Y\n\n"
85 " DO category: Data type: Explanation:\n"
86 " MASTER_SCREEN_FLAT_PMOS FITS image Combined (sum) flat field\n"
87 " MASTER_NORM_FLAT_PMOS FITS image Normalised flat field\n"
88 " MAPPED_SCREEN_FLAT_PMOS FITS image Wavelength calibrated flat field\n"
89 " MAPPED_NORM_FLAT_PMOS FITS image Wavelength calibrated normalised flat\n"
90 " REDUCED_LAMP_PMOS FITS image Wavelength calibrated arc spectrum\n"
91 " DISP_COEFF_PMOS FITS table Inverse dispersion coefficients\n"
92 " DISP_RESIDUALS_PMOS FITS image Residuals in wavelength calibration\n"
93 " DISP_RESIDUALS_TABLE_PMOS FITS table Residuals in wavelength calibration\n"
94 " DELTA_IMAGE_PMOS FITS image Offset vs linear wavelength calib\n"
95 " WAVELENGTH_MAP_PMOS FITS image Wavelength for each pixel on CCD\n"
96 " SPECTRA_DETECTION_PMOS FITS image Check for preliminary detection\n"
97 " SLIT_MAP_PMOS FITS image Map of central wavelength on CCD\n"
98 " CURV_TRACES_PMOS FITS table Spectral curvature traces\n"
99 " CURV_COEFF_PMOS FITS table Spectral curvature coefficients\n"
100 " SPATIAL_MAP_PMOS FITS image Spatial position along slit on CCD\n"
101 " SPECTRAL_RESOLUTION_PMOS FITS table Resolution at reference arc lines\n"
102 " SLIT_LOCATION_PMOS FITS table Slits on product frames and CCD\n\n";
104 #define fors_pmos_calib_exit(message) \
106 if ((const char *)message != NULL) cpl_msg_error(recipe, message); \
107 cpl_free(instrume); \
108 cpl_free(fiterror); \
109 cpl_free(fitlines); \
110 cpl_image_delete(bias); \
111 cpl_image_delete(master_bias); \
112 cpl_image_delete(coordinate); \
113 cpl_image_delete(checkwave); \
114 cpl_image_delete(flat); \
115 cpl_image_delete(master_flat); \
116 cpl_image_delete(added_flat); \
117 cpl_image_delete(norm_flat); \
118 cpl_image_delete(mapped_flat); \
119 cpl_image_delete(mapped_nflat); \
120 cpl_image_delete(rainbow); \
121 cpl_image_delete(rectified); \
122 cpl_image_delete(residual); \
123 cpl_image_delete(smo_flat); \
124 cpl_image_delete(spatial); \
125 cpl_image_delete(spectra); \
126 cpl_image_delete(wavemap); \
127 cpl_image_delete(delta); \
128 cpl_image_delete(rect_flat); \
129 cpl_image_delete(rect_nflat); \
130 cpl_mask_delete(refmask); \
131 cpl_propertylist_delete(header); \
132 cpl_propertylist_delete(save_header); \
133 cpl_propertylist_delete(qclist); \
134 cpl_table_delete(grism_table); \
135 cpl_table_delete(idscoeff); \
136 cpl_table_delete(idscoeff_all); \
137 cpl_table_delete(restable); \
138 cpl_table_delete(maskslits); \
139 cpl_table_delete(overscans); \
140 cpl_table_delete(traces); \
141 cpl_table_delete(polytraces); \
142 cpl_table_delete(slits); \
143 cpl_table_delete(restab); \
144 cpl_table_delete(global); \
145 cpl_table_delete(wavelengths); \
146 cpl_vector_delete(lines); \
147 cpl_msg_indent_less(); \
151 #define fors_pmos_calib_exit_memcheck(message) \
153 if ((const char *)message != NULL) cpl_msg_info(recipe, message); \
154 printf("free instrume (%p)\n", instrume); \
155 cpl_free(instrume); \
156 printf("free pipefile (%p)\n", pipefile); \
157 cpl_free(pipefile); \
158 printf("free fiterror (%p)\n", fiterror); \
159 cpl_free(fiterror); \
160 printf("free fitlines (%p)\n", fitlines); \
161 cpl_free(fitlines); \
162 printf("free bias (%p)\n", bias); \
163 cpl_image_delete(bias); \
164 printf("free master_bias (%p)\n", master_bias); \
165 cpl_image_delete(master_bias); \
166 printf("free coordinate (%p)\n", coordinate); \
167 cpl_image_delete(coordinate); \
168 printf("free checkwave (%p)\n", checkwave); \
169 cpl_image_delete(checkwave); \
170 printf("free flat (%p)\n", flat); \
171 cpl_image_delete(flat); \
172 printf("free master_flat (%p)\n", master_flat); \
173 cpl_image_delete(master_flat); \
174 printf("free norm_flat (%p)\n", norm_flat); \
175 cpl_image_delete(norm_flat); \
176 printf("free mapped_flat (%p)\n", mapped_flat); \
177 cpl_image_delete(mapped_flat); \
178 printf("free mapped_nflat (%p)\n", mapped_nflat); \
179 cpl_image_delete(mapped_nflat); \
180 printf("free rainbow (%p)\n", rainbow); \
181 cpl_image_delete(rainbow); \
182 printf("free rectified (%p)\n", rectified); \
183 cpl_image_delete(rectified); \
184 printf("free residual (%p)\n", residual); \
185 cpl_image_delete(residual); \
186 printf("free smo_flat (%p)\n", smo_flat); \
187 cpl_image_delete(smo_flat); \
188 printf("free spatial (%p)\n", spatial); \
189 cpl_image_delete(spatial); \
190 printf("free spectra (%p)\n", spectra); \
191 cpl_image_delete(spectra); \
192 printf("free wavemap (%p)\n", wavemap); \
193 cpl_image_delete(wavemap); \
194 printf("free delta (%p)\n", delta); \
195 cpl_image_delete(delta); \
196 printf("free rect_flat (%p)\n", rect_flat); \
197 cpl_image_delete(rect_flat); \
198 printf("free rect_nflat (%p)\n", rect_nflat); \
199 cpl_image_delete(rect_nflat); \
200 printf("free refmask (%p)\n", refmask); \
201 cpl_mask_delete(refmask); \
202 printf("free header (%p)\n", header); \
203 cpl_propertylist_delete(header); \
204 printf("free save_header (%p)\n", save_header); \
205 cpl_propertylist_delete(save_header); \
206 printf("free qclist (%p)\n", qclist); \
207 cpl_propertylist_delete(qclist); \
208 printf("free grism_table (%p)\n", grism_table); \
209 cpl_table_delete(grism_table); \
210 printf("free idscoeff (%p)\n", idscoeff); \
211 cpl_table_delete(idscoeff); \
212 printf("free idscoeff_all (%p)\n", idscoeff_all); \
213 cpl_table_delete(idscoeff_all); \
214 printf("free restable (%p)\n", restable); \
215 cpl_table_delete(restable); \
216 printf("free maskslits (%p)\n", maskslits); \
217 cpl_table_delete(maskslits); \
218 printf("free overscans (%p)\n", overscans); \
219 cpl_table_delete(overscans); \
220 printf("free traces (%p)\n", traces); \
221 cpl_table_delete(traces); \
222 printf("free polytraces (%p)\n", polytraces); \
223 cpl_table_delete(polytraces); \
224 printf("free slits (%p)\n", slits); \
225 cpl_table_delete(slits); \
226 printf("free restab (%p)\n", restab); \
227 cpl_table_delete(restab); \
228 printf("free global (%p)\n", global); \
229 cpl_table_delete(global); \
230 printf("free wavelengths (%p)\n", wavelengths); \
231 cpl_table_delete(wavelengths); \
232 printf("free lines (%p)\n", lines); \
233 cpl_vector_delete(lines); \
234 cpl_msg_indent_less(); \
252 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe );
253 cpl_plugin *plugin = &recipe->interface;
255 cpl_plugin_init(plugin,
258 CPL_PLUGIN_TYPE_RECIPE,
260 "Determination of the extraction mask",
261 fors_pmos_calib_description,
264 "This file is currently part of the FORS Instrument Pipeline\n"
265 "Copyright (C) 2002-2010 European Southern Observatory\n\n"
266 "This program is free software; you can redistribute it and/or modify\n"
267 "it under the terms of the GNU General Public License as published by\n"
268 "the Free Software Foundation; either version 2 of the License, or\n"
269 "(at your option) any later version.\n\n"
270 "This program is distributed in the hope that it will be useful,\n"
271 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
272 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
273 "GNU General Public License for more details.\n\n"
274 "You should have received a copy of the GNU General Public License\n"
275 "along with this program; if not, write to the Free Software Foundation,\n"
276 "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n",
277 fors_pmos_calib_create,
278 fors_pmos_calib_exec,
279 fors_pmos_calib_destroy);
281 cpl_pluginlist_append(list, plugin);
297 static int fors_pmos_calib_create(cpl_plugin *plugin)
307 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
308 recipe = (cpl_recipe *)plugin;
316 recipe->parameters = cpl_parameterlist_new();
323 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.dispersion",
325 "Expected spectral dispersion (Angstrom/pixel)",
326 "fors.fors_pmos_calib",
328 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"dispersion");
329 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
330 cpl_parameterlist_append(recipe->parameters, p);
336 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.peakdetection",
338 "Initial peak detection threshold (ADU)",
339 "fors.fors_pmos_calib",
341 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"peakdetection");
342 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
343 cpl_parameterlist_append(recipe->parameters, p);
349 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.wdegree",
351 "Degree of wavelength calibration polynomial",
352 "fors.fors_pmos_calib",
354 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wdegree");
355 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
356 cpl_parameterlist_append(recipe->parameters, p);
362 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.wradius",
364 "Search radius if iterating pattern-matching "
365 "with first-guess method",
366 "fors.fors_pmos_calib",
368 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wradius");
369 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
370 cpl_parameterlist_append(recipe->parameters, p);
376 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.wreject",
378 "Rejection threshold in dispersion "
379 "relation fit (pixel)",
380 "fors.fors_pmos_calib",
382 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wreject");
383 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
384 cpl_parameterlist_append(recipe->parameters, p);
390 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.wcolumn",
392 "Name of line catalog table column "
394 "fors.fors_pmos_calib",
396 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcolumn");
397 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
398 cpl_parameterlist_append(recipe->parameters, p);
404 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.cdegree",
406 "Degree of spectral curvature polynomial",
407 "fors.fors_pmos_calib",
409 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"cdegree");
410 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
411 cpl_parameterlist_append(recipe->parameters, p);
417 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.cmode",
419 "Interpolation mode of curvature solution "
421 "interpolation, 1 = fill gaps, 2 = global "
423 "fors.fors_pmos_calib",
425 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"cmode");
426 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
427 cpl_parameterlist_append(recipe->parameters, p);
433 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.startwavelength",
435 "Start wavelength in spectral extraction",
436 "fors.fors_pmos_calib",
438 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"startwavelength");
439 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
440 cpl_parameterlist_append(recipe->parameters, p);
446 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.endwavelength",
448 "End wavelength in spectral extraction",
449 "fors.fors_pmos_calib",
451 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"endwavelength");
452 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
453 cpl_parameterlist_append(recipe->parameters, p);
466 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.ddegree",
468 "Degree of flat field fitting polynomial "
469 "along dispersion direction",
470 "fors.fors_pmos_calib",
472 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ddegree");
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_calib.dradius",
482 "Smooth box radius for flat field along "
483 "dispersion direction",
484 "fors.fors_pmos_calib",
486 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"dradius");
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_calib.qc",
496 "Compute QC1 parameters",
497 "fors.fors_pmos_calib",
499 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"qc");
500 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
501 cpl_parameterlist_append(recipe->parameters, p);
507 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.check",
509 "Create intermediate products",
510 "fors.fors_pmos_calib",
512 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"check");
513 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
514 cpl_parameterlist_append(recipe->parameters, p);
528 static int fors_pmos_calib_exec(cpl_plugin *plugin)
532 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
533 recipe = (cpl_recipe *)plugin;
537 return fors_pmos_calib(recipe->parameters, recipe->frames);
549 static int fors_pmos_calib_destroy(cpl_plugin *plugin)
553 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
554 recipe = (cpl_recipe *)plugin;
558 cpl_parameterlist_delete(recipe->parameters);
573 static int fors_pmos_calib(cpl_parameterlist *parlist, cpl_frameset *frameset)
576 const char *recipe =
"fors_pmos_calib";
584 double peakdetection;
591 double startwavelength;
592 double endwavelength;
597 const char *stack_method;
609 cpl_imagelist *biases = NULL;
610 cpl_image *bias = NULL;
611 cpl_image *master_bias = NULL;
612 cpl_image *multi_bias = NULL;
613 cpl_image *flat = NULL;
614 cpl_image *master_flat = NULL;
615 cpl_image *added_flat = NULL;
616 cpl_image *trace_flat = NULL;
617 cpl_image *smo_flat = NULL;
618 cpl_image *norm_flat = NULL;
619 cpl_image *spectra = NULL;
620 cpl_image *wavemap = NULL;
621 cpl_image *delta = NULL;
622 cpl_image *residual = NULL;
623 cpl_image *checkwave = NULL;
624 cpl_image *rectified = NULL;
625 cpl_image *dummy = NULL;
626 cpl_image *add_dummy = NULL;
627 cpl_image *refimage = NULL;
628 cpl_image *coordinate = NULL;
629 cpl_image *rainbow = NULL;
630 cpl_image *spatial = NULL;
631 cpl_image *rect_flat = NULL;
632 cpl_image *rect_nflat = NULL;
633 cpl_image *mapped_flat = NULL;
634 cpl_image *mapped_nflat = NULL;
636 cpl_mask *refmask = NULL;
638 cpl_table *grism_table = NULL;
639 cpl_table *overscans = NULL;
640 cpl_table *wavelengths = NULL;
641 cpl_table *idscoeff = NULL;
642 cpl_table *idscoeff_all = NULL;
643 cpl_table *restable = NULL;
644 cpl_table *slits = NULL;
645 cpl_table *positions = NULL;
646 cpl_table *maskslits = NULL;
647 cpl_table *traces = NULL;
648 cpl_table *polytraces = NULL;
649 cpl_table *restab = NULL;
650 cpl_table *global = NULL;
652 cpl_vector *lines = NULL;
654 cpl_propertylist *header_dist = NULL;
655 cpl_propertylist *header = NULL;
656 cpl_propertylist *save_header = NULL;
657 cpl_propertylist *qclist = NULL;
665 const char *flat_tag;
666 const char *master_screen_flat_tag;
667 const char *master_norm_flat_tag;
668 const char *reduced_lamp_tag;
669 const char *disp_residuals_tag;
670 const char *disp_coeff_tag;
671 const char *wavelength_map_tag;
672 const char *spectra_detection_tag;
673 const char *spectral_resolution_tag;
674 const char *slit_map_tag;
675 const char *curv_traces_tag;
676 const char *curv_coeff_tag;
677 const char *spatial_map_tag;
678 const char *slit_location_tag;
679 const char *master_distortion_tag =
"MASTER_DISTORTION_TABLE";
680 const char *disp_residuals_table_tag;
681 const char *delta_image_tag;
682 const char *mapped_screen_flat_tag;
683 const char *mapped_norm_flat_tag;
697 int rebin, rebin_dist;
699 double *fiterror = NULL;
700 int *fitlines = NULL;
707 char *instrume = NULL;
718 snprintf(version, 80,
"%s-%s", PACKAGE, PACKAGE_VERSION);
720 cpl_msg_set_indentation(2);
728 cpl_msg_info(recipe,
"Recipe %s configuration parameters:", recipe);
729 cpl_msg_indent_more();
731 if (cpl_frameset_count_tags(frameset,
"GRISM_TABLE") > 1)
732 fors_pmos_calib_exit(
"Too many in input: GRISM_TABLE");
737 "fors.fors_pmos_calib.dispersion", grism_table);
739 if (dispersion <= 0.0)
740 fors_pmos_calib_exit(
"Invalid spectral dispersion value");
743 "fors.fors_pmos_calib.peakdetection", grism_table);
744 if (peakdetection <= 0.0)
745 fors_pmos_calib_exit(
"Invalid peak detection level");
748 "fors.fors_pmos_calib.wdegree", grism_table);
751 fors_pmos_calib_exit(
"Invalid polynomial degree");
754 fors_pmos_calib_exit(
"Max allowed polynomial degree is 5");
757 "fors.fors_pmos_calib.wradius", NULL);
760 fors_pmos_calib_exit(
"Invalid search radius");
763 "fors.fors_pmos_calib.wreject", NULL);
766 fors_pmos_calib_exit(
"Invalid rejection threshold");
769 "fors.fors_pmos_calib.wcolumn", NULL);
772 "fors.fors_pmos_calib.cdegree", grism_table);
775 fors_pmos_calib_exit(
"Invalid polynomial degree");
778 fors_pmos_calib_exit(
"Max allowed polynomial degree is 5");
782 if (cmode < 0 || cmode > 2)
783 fors_pmos_calib_exit(
"Invalid curvature solution interpolation mode");
786 "fors.fors_pmos_calib.startwavelength", grism_table);
787 if (startwavelength > 1.0)
788 if (startwavelength < 3000.0 || startwavelength > 13000.0)
789 fors_pmos_calib_exit(
"Invalid wavelength");
792 "fors.fors_pmos_calib.endwavelength", grism_table);
793 if (endwavelength > 1.0) {
794 if (endwavelength < 3000.0 || endwavelength > 13000.0)
795 fors_pmos_calib_exit(
"Invalid wavelength");
796 if (startwavelength < 1.0)
797 fors_pmos_calib_exit(
"Invalid wavelength interval");
800 if (startwavelength > 1.0)
801 if (endwavelength - startwavelength <= 0.0)
802 fors_pmos_calib_exit(
"Invalid wavelength interval");
805 "fors.fors_pmos_calib.stack_method",
808 if (strcmp(stack_method,
"minmax") == 0) {
810 "fors.fors_pmos_calib.minrejection", NULL);
812 fors_pmos_calib_exit(
"Invalid number of lower rejections");
815 "fors.fors_pmos_calib.maxrejection", NULL);
817 fors_pmos_calib_exit(
"Invalid number of upper rejections");
820 if (strcmp(stack_method,
"ksigma") == 0) {
822 "fors.fors_pmos_calib.klow", NULL);
824 fors_pmos_calib_exit(
"Invalid lower K-sigma");
827 "fors.fors_pmos_calib.khigh", NULL);
829 fors_pmos_calib_exit(
"Invalid lower K-sigma");
832 "fors.fors_pmos_calib.kiter", NULL);
834 fors_pmos_calib_exit(
"Invalid number of iterations");
838 "fors.fors_pmos_calib.ddegree", NULL);
840 "fors.fors_pmos_calib.dradius", NULL);
843 fors_pmos_calib_exit(
"Invalid smoothing box radius");
849 cpl_table_delete(grism_table); grism_table = NULL;
851 if (cpl_error_get_code())
852 fors_pmos_calib_exit(
"Failure getting the configuration parameters");
859 cpl_msg_indent_less();
860 cpl_msg_info(recipe,
"Check input set-of-frames:");
861 cpl_msg_indent_more();
864 cpl_frameset *subframeset = cpl_frameset_duplicate(frameset);
865 cpl_frameset_erase(subframeset,
"BIAS");
866 cpl_frameset_erase(subframeset,
"MASTER_BIAS");
869 cpl_msg_warning(cpl_func,
"Input frames are not from the same grism");
872 cpl_msg_warning(cpl_func,
"Input frames are not from the same filter");
875 cpl_msg_warning(cpl_func,
"Input frames are not from the same chip");
877 cpl_frameset_delete(subframeset);
880 pmos = cpl_frameset_count_tags(frameset,
"LAMP_PMOS");
883 fors_pmos_calib_exit(
"Missing input arc lamp frame");
886 cpl_msg_info(recipe,
"PMOS data found");
887 arc_tag =
"LAMP_PMOS";
888 flat_tag =
"SCREEN_FLAT_PMOS";
889 master_screen_flat_tag =
"MASTER_SCREEN_FLAT_PMOS";
890 master_norm_flat_tag =
"MASTER_NORM_FLAT_PMOS";
891 reduced_lamp_tag =
"REDUCED_LAMP_PMOS";
892 disp_residuals_tag =
"DISP_RESIDUALS_PMOS";
893 disp_coeff_tag =
"DISP_COEFF_PMOS";
894 wavelength_map_tag =
"WAVELENGTH_MAP_PMOS";
895 spectra_detection_tag =
"SPECTRA_DETECTION_PMOS";
896 spectral_resolution_tag =
"SPECTRAL_RESOLUTION_PMOS";
897 slit_map_tag =
"SLIT_MAP_PMOS";
898 curv_traces_tag =
"CURV_TRACES_PMOS";
899 curv_coeff_tag =
"CURV_COEFF_PMOS";
900 spatial_map_tag =
"SPATIAL_MAP_PMOS";
901 slit_location_tag =
"SLIT_LOCATION_PMOS";
902 disp_residuals_table_tag =
"DISP_RESIDUALS_TABLE_PMOS";
903 delta_image_tag =
"DELTA_IMAGE_PMOS";
904 mapped_screen_flat_tag =
"MAPPED_SCREEN_FLAT_PMOS";
905 mapped_norm_flat_tag =
"MAPPED_NORM_FLAT_PMOS";
909 if (cpl_frameset_count_tags(frameset,
"MASTER_BIAS") == 0) {
910 if (cpl_frameset_count_tags(frameset,
"BIAS") == 0)
911 fors_pmos_calib_exit(
"Missing required input: MASTER_BIAS or BIAS");
912 nbias = cpl_frameset_count_tags(frameset,
"BIAS");
915 if (cpl_frameset_count_tags(frameset,
"MASTER_BIAS") > 1)
916 fors_pmos_calib_exit(
"Too many in input: MASTER_BIAS");
918 if (cpl_frameset_count_tags(frameset,
"MASTER_LINECAT") == 0)
919 fors_pmos_calib_exit(
"Missing required input: MASTER_LINECAT");
921 if (cpl_frameset_count_tags(frameset,
"MASTER_LINECAT") > 1)
922 fors_pmos_calib_exit(
"Too many in input: MASTER_LINECAT");
924 if (cpl_frameset_count_tags(frameset,
"MASTER_LINECAT") == 0)
925 fors_pmos_calib_exit(
"Missing required input: MASTER_LINECAT");
927 if (cpl_frameset_count_tags(frameset,
"MASTER_LINECAT") > 1)
928 fors_pmos_calib_exit(
"Too many in input: MASTER_LINECAT");
935 if (cpl_frameset_count_tags(frameset, master_distortion_tag) > 1)
936 fors_pmos_calib_exit(
"Too many in input: MASTER_DISTORTION_TABLE");
938 nflats = cpl_frameset_count_tags(frameset, flat_tag);
941 cpl_msg_error(recipe,
"Missing required input: %s", flat_tag);
942 fors_pmos_calib_exit(NULL);
945 cpl_msg_indent_less();
948 cpl_msg_info(recipe,
"Load %d flat field frames and stack them "
949 "with method \"%s\"", nflats, stack_method);
951 cpl_msg_info(recipe,
"Load flat field exposure...");
953 cpl_msg_indent_more();
958 fors_pmos_calib_exit(
"Cannot load flat field frame header");
960 alltime = cpl_propertylist_get_double(header,
"EXPTIME");
962 if (cpl_error_get_code() != CPL_ERROR_NONE)
963 fors_pmos_calib_exit(
"Missing keyword EXPTIME in flat field "
966 cpl_propertylist_delete(header);
968 for (i = 1; i < nflats; i++) {
973 fors_pmos_calib_exit(
"Cannot load flat field frame header");
975 alltime += cpl_propertylist_get_double(header,
"EXPTIME");
977 if (cpl_error_get_code() != CPL_ERROR_NONE)
978 fors_pmos_calib_exit(
"Missing keyword EXPTIME in flat field "
981 cpl_propertylist_delete(header);
986 char *montecarlo = getenv(
"MONTECARLO");
989 doit = atoi(montecarlo);
993 CPL_TYPE_FLOAT, 0, 1);
994 if (master_bias == NULL)
995 fors_pmos_calib_exit(
"Cannot load master bias");
997 blevel = cpl_image_get_mean(master_bias);
999 cpl_image_delete(master_bias);
1003 master_flat =
dfs_load_image(frameset, flat_tag, CPL_TYPE_FLOAT, 0, 0);
1005 if (master_flat == NULL)
1006 fors_pmos_calib_exit(
"Cannot load flat field");
1011 gain = cpl_propertylist_get_double(header,
"ESO DET OUT1 CONAD");
1013 if (cpl_error_get_code() != CPL_ERROR_NONE)
1014 fors_pmos_calib_exit(
"Missing keyword ESO DET OUT1 CONAD "
1015 "in flat field frame header");
1017 ron = cpl_propertylist_get_double(header,
"ESO DET OUT1 RON");
1019 if (cpl_error_get_code() != CPL_ERROR_NONE)
1020 fors_pmos_calib_exit(
"Missing keyword ESO DET OUT1 RON "
1021 "in flat field frame header");
1023 cpl_propertylist_delete(header);
1030 ny = cpl_image_get_size_y(master_flat);
1033 if (strcmp(stack_method,
"average") == 0) {
1034 for (i = 1; i < nflats; i++) {
1040 cpl_image_add(master_flat, flat);
1041 cpl_image_delete(flat); flat = NULL;
1044 fors_pmos_calib_exit(
"Cannot load flat field");
1054 cpl_imagelist *flatlist = NULL;
1057 added_flat = cpl_image_duplicate(master_flat);
1059 flatlist = cpl_imagelist_new();
1060 cpl_imagelist_set(flatlist, master_flat,
1061 cpl_imagelist_get_size(flatlist));
1072 rflux = cpl_image_get_mean(master_flat);
1074 for (i = 1; i < nflats; i++) {
1080 cpl_image_add(added_flat, flat);
1081 flux = cpl_image_get_mean(flat);
1082 cpl_image_multiply_scalar(flat, rflux / flux);
1083 cpl_imagelist_set(flatlist, flat,
1084 cpl_imagelist_get_size(flatlist));
1087 fors_pmos_calib_exit(
"Cannot load flat field");
1091 if (strcmp(stack_method,
"median") == 0) {
1092 master_flat = cpl_imagelist_collapse_median_create(flatlist);
1095 if (strcmp(stack_method,
"minmax") == 0) {
1096 master_flat = cpl_imagelist_collapse_minmax_create(flatlist,
1101 if (strcmp(stack_method,
"ksigma") == 0) {
1103 klow, khigh, kiter, NULL);
1117 fors_pmos_calib_exit(
"Cannot load arc lamp header");
1119 instrume = (
char *)cpl_propertylist_get_string(header,
"INSTRUME");
1120 if (instrume == NULL)
1121 fors_pmos_calib_exit(
"Missing keyword INSTRUME in arc lamp header");
1123 instrume = cpl_strdup(instrume);
1125 if (instrume[4] ==
'1')
1126 snprintf(version, 80,
"%s/%s",
"fors1", VERSION);
1127 if (instrume[4] ==
'2')
1128 snprintf(version, 80,
"%s/%s",
"fors2", VERSION);
1130 reference = cpl_propertylist_get_double(header,
"ESO INS GRIS1 WLEN");
1132 if (cpl_error_get_code() != CPL_ERROR_NONE)
1133 fors_pmos_calib_exit(
"Missing keyword ESO INS GRIS1 WLEN in arc lamp "
1136 if (reference < 3000.0)
1139 if (reference < 3000.0 || reference > 13000.0) {
1140 cpl_msg_error(recipe,
"Invalid central wavelength %.2f read from "
1141 "keyword ESO INS GRIS1 WLEN in arc lamp frame header",
1143 fors_pmos_calib_exit(NULL);
1146 cpl_msg_info(recipe,
"The central wavelength is: %.2f", reference);
1148 rebin = cpl_propertylist_get_int(header,
"ESO DET WIN1 BINX");
1150 if (cpl_error_get_code() != CPL_ERROR_NONE)
1151 fors_pmos_calib_exit(
"Missing keyword ESO DET WIN1 BINX in arc lamp "
1155 dispersion *= rebin;
1156 cpl_msg_warning(recipe,
"The rebin factor is %d, and therefore the "
1157 "working dispersion used is %f A/pixel", rebin,
1161 gain = cpl_propertylist_get_double(header,
"ESO DET OUT1 CONAD");
1163 if (cpl_error_get_code() != CPL_ERROR_NONE)
1164 fors_pmos_calib_exit(
"Missing keyword ESO DET OUT1 CONAD in arc lamp "
1167 cpl_msg_info(recipe,
"The gain factor is: %.2f e-/ADU", gain);
1171 cpl_msg_info(recipe,
"Produce mask slit position table...");
1180 mxpos = cpl_table_get_column_median(maskslits,
"xtop");
1181 xpos = cpl_table_get_data_double(maskslits,
"xtop");
1182 nslits = cpl_table_get_nrow(maskslits);
1185 for (i = 0; i < nslits; i++) {
1186 if (fabs(mxpos-xpos[i]) > 0.01) {
1193 if(nslits_out_det != 0)
1197 cpl_msg_info(recipe,
"All slits have same offset: %.2f", mxpos);
1200 cpl_msg_info(recipe,
"All slits have different offsets");
1203 if (ny != 400 && ny != 500) {
1204 if (cpl_frameset_count_tags(frameset,
1205 master_distortion_tag) == 0)
1206 fors_pmos_calib_exit(
1207 "Missing required input: MASTER_DISTORTION_TABLE");
1210 master_distortion_tag, 0);
1211 rebin_dist = cpl_propertylist_get_int(header_dist,
1212 "ESO DET WIN1 BINX");
1213 cpl_propertylist_delete(header_dist);
1230 cpl_msg_info(recipe,
"Generate the master from input raw biases...");
1234 biases = cpl_imagelist_new();
1239 fors_pmos_calib_exit(
"Cannot load bias frame");
1241 cpl_imagelist_set(biases, bias, 0);
1243 for (i = 1; i < nbias; i++) {
1246 cpl_imagelist_set(biases, bias, i);
1248 fors_pmos_calib_exit(
"Cannot load bias frame");
1251 master_bias = cpl_imagelist_collapse_median_create(biases);
1253 cpl_imagelist_delete(biases);
1257 CPL_TYPE_FLOAT, 0, 1);
1258 if (master_bias == NULL)
1259 fors_pmos_calib_exit(
"Cannot load bias");
1265 CPL_TYPE_FLOAT, 0, 1);
1266 if (master_bias == NULL)
1267 fors_pmos_calib_exit(
"Cannot load master bias");
1270 cpl_msg_info(recipe,
"Remove the master bias...");
1272 overscans = mos_load_overscans_fors(header);
1273 cpl_propertylist_delete(header); header = NULL;
1276 int xlow = cpl_table_get_int(overscans,
"xlow", 0, NULL);
1277 int ylow = cpl_table_get_int(overscans,
"ylow", 0, NULL);
1278 int xhig = cpl_table_get_int(overscans,
"xhig", 0, NULL);
1279 int yhig = cpl_table_get_int(overscans,
"yhig", 0, NULL);
1280 dummy = cpl_image_extract(master_bias, xlow+1, ylow+1, xhig, yhig);
1281 cpl_image_delete(master_bias); master_bias = dummy;
1284 NULL, parlist, recipe, version))
1285 fors_pmos_calib_exit(NULL);
1289 multi_bias = cpl_image_multiply_scalar_create(master_bias, nflats);
1293 cpl_image_delete(multi_bias);
1298 cpl_image_delete(master_flat);
1299 master_flat = dummy;
1301 if (master_flat == NULL)
1302 fors_pmos_calib_exit(
"Cannot remove bias from flat field");
1305 cpl_image_delete(added_flat);
1306 added_flat = add_dummy;
1308 if (added_flat == NULL)
1309 fors_pmos_calib_exit(
"Cannot remove bias from added flat field");
1311 trace_flat = added_flat;
1314 trace_flat = master_flat;
1318 if (wavelengths == NULL)
1319 fors_pmos_calib_exit(
"Cannot load line catalog");
1325 nlines = cpl_table_get_nrow(wavelengths);
1328 fors_pmos_calib_exit(
"Empty input line catalog");
1330 if (cpl_table_has_column(wavelengths, wcolumn) != 1) {
1331 cpl_msg_error(recipe,
"Missing column %s in input line catalog table",
1333 fors_pmos_calib_exit(NULL);
1336 line = cpl_malloc(nlines *
sizeof(
double));
1338 for (i = 0; i < nlines; i++)
1339 line[i] = cpl_table_get(wavelengths, wcolumn, i, NULL);
1341 lines = cpl_vector_wrap(nlines, line);
1343 for (j = 0; j < pmos; j++) {
1346 cpl_msg_indent_less();
1347 cpl_msg_info(recipe,
"Processing arc lamp nb %d out of %d ...",
1349 cpl_msg_indent_more();
1351 cpl_msg_info(recipe,
"Load arc lamp exposure...");
1352 cpl_msg_indent_more();
1354 spectra =
dfs_load_image(frameset, arc_tag, CPL_TYPE_FLOAT, 0, 0);
1361 for (k = 0; k < j; k ++) {
1362 cpl_image_delete(spectra);
1366 if (spectra == NULL)
1367 fors_pmos_calib_exit(
"Cannot load arc lamp exposure");
1373 cpl_msg_info(recipe,
"Remove the master bias...");
1376 cpl_image_delete(spectra); spectra = dummy;
1378 if (spectra == NULL)
1379 fors_pmos_calib_exit(
"Cannot remove bias from arc lamp exposure");
1381 cpl_msg_indent_less();
1382 cpl_msg_info(recipe,
"Load input line catalog...");
1383 cpl_msg_indent_more();
1390 fors_pmos_calib_exit(
"Cannot process saturation");
1393 fors_pmos_calib_exit(
"Cannot subtract the background");
1400 cpl_msg_indent_less();
1401 cpl_msg_info(recipe,
"Detecting spectra on CCD...");
1402 cpl_msg_indent_more();
1404 nx = cpl_image_get_size_x(spectra);
1405 ccd_ysize = ny = cpl_image_get_size_y(spectra);
1407 refmask = cpl_mask_new(nx, ny);
1411 peakdetection, wradius,
1412 wdegree, wreject, reference,
1413 &startwavelength, &endwavelength,
1414 NULL, NULL, NULL, NULL, NULL,
1415 NULL, refmask, NULL);
1417 if (checkwave == NULL)
1418 fors_pmos_calib_exit(
"Wavelength calibration failure.");
1424 header = cpl_propertylist_new();
1425 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
1426 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
1427 cpl_propertylist_update_double(header,
"CRVAL1",
1428 startwavelength + dispersion/2);
1429 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
1432 cpl_propertylist_update_double(header,
"CD1_1", dispersion);
1433 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
1434 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
1435 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
1436 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
1437 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
1442 spectra_detection_tag,
1444 fors_pmos_calib_exit(NULL);
1449 spectra_detection_tag, header)) {
1450 fors_pmos_calib_exit(NULL);
1454 cpl_image_delete(checkwave); checkwave = NULL;
1455 cpl_propertylist_delete(header); header = NULL;
1457 if (cpl_mask_is_empty(refmask))
1458 fors_pmos_calib_exit(
"Wavelength calibration failure.");
1461 fors_pmos_calib_exit(
"The gaps could not be found");
1463 cpl_msg_info(recipe,
1464 "Locate slits at reference wavelength on CCD...");
1468 cpl_msg_error(cpl_error_get_where(),
"%s",
1469 cpl_error_get_message());
1470 fors_pmos_calib_exit(
"No slits could be detected!");
1474 if (ny != 400 && ny != 500) {
1475 float rescale = (float) rebin_dist / rebin;
1477 fors_pmos_calib_exit(
"Some slits are missing. "
1483 refimage = cpl_image_new_from_mask(refmask);
1484 cpl_mask_delete(refmask); refmask = NULL;
1491 fors_pmos_calib_exit(NULL);
1497 for (k = 0; k < j; k ++) {
1498 cpl_propertylist_delete(save_header);
1503 fors_pmos_calib_exit(NULL);
1505 cpl_propertylist_delete(save_header); save_header = NULL;
1508 cpl_image_delete(refimage); refimage = NULL;
1531 cpl_msg_indent_less();
1532 cpl_msg_info(recipe,
1533 "Attempt slit identification (optional)...");
1534 cpl_msg_indent_more();
1539 cpl_table_delete(slits);
1546 cpl_table_and_selected_double(slits,
1547 "ytop", CPL_GREATER_THAN, ny);
1548 cpl_table_or_selected_double(slits,
1549 "ybottom", CPL_LESS_THAN, 0);
1550 cpl_table_erase_selected(slits);
1552 nslits = cpl_table_get_nrow(slits);
1555 fors_pmos_calib_exit(
"No slits found on the CCD");
1557 cpl_msg_info(recipe,
1558 "%d slits are entirely contained in CCD",
1563 cpl_msg_info(recipe,
1564 "Global distortion model cannot be computed");
1565 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1566 fors_pmos_calib_exit(NULL);
1572 if (ny == 400 || ny == 500) {
1579 nslits = cpl_table_get_nrow(slits);
1582 cpl_table_unselect_all(slits);
1583 for (k = 0; k < cpl_table_get_nrow(slits); k++) {
1584 double jump = cpl_table_get(slits,
"ytop", k, NULL)
1585 - cpl_table_get(slits,
"ybottom", k, NULL);
1587 cpl_table_select_row(slits, k);
1590 cpl_table_erase_selected(slits);
1591 nslits = cpl_table_get_nrow(slits);
1595 fors_pmos_calib_exit(
"No slits found on the CCD");
1598 cpl_table_unselect_all(slits);
1599 cpl_table_select_row(slits, 0);
1600 cpl_table_select_row(slits, cpl_table_get_nrow(slits)-1);
1601 cpl_table_erase_selected(slits);
1604 cpl_msg_info(recipe,
1605 "%d slits are entirely contained in CCD", nslits);
1608 cpl_table_unselect_all(slits);
1609 for (k = 0; k < cpl_table_get_nrow(slits); k++) {
1610 double jump = cpl_table_get(slits,
"ytop", k, NULL)
1611 - cpl_table_get(slits,
"ybottom", k, NULL);
1613 cpl_table_select_row(slits, k);
1616 cpl_table_erase_selected(slits);
1617 nslits = cpl_table_get_nrow(slits);
1625 cpl_msg_indent_less();
1626 cpl_msg_info(recipe,
"Determining spectral curvature...");
1627 cpl_msg_indent_more();
1629 cpl_msg_info(recipe,
"Tracing master flat field spectra edges...");
1631 startwavelength, endwavelength, dispersion);
1634 fors_pmos_calib_exit(
"Tracing failure");
1636 cpl_image_delete(added_flat); added_flat = NULL;
1638 cpl_msg_info(recipe,
"Fitting flat field spectra edges...");
1642 fors_pmos_calib_exit(
"Trace fitting failure");
1645 cpl_msg_info(recipe,
1646 "Computing global spectral curvature model...");
1653 fors_pmos_calib_exit(NULL);
1658 fors_pmos_calib_exit(NULL);
1661 cpl_table_delete(traces); traces = NULL;
1663 coordinate = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1669 startwavelength, endwavelength,
1670 dispersion, 0, j ? NULL: coordinate);
1675 cpl_image_delete(spectra); spectra = NULL;
1684 cpl_msg_indent_less();
1685 cpl_msg_info(recipe,
"Perform flat field normalisation...");
1686 cpl_msg_indent_more();
1688 norm_flat = cpl_image_duplicate(master_flat);
1691 polytraces, reference,
1692 startwavelength, endwavelength,
1693 dispersion, dradius, ddegree);
1696 cpl_image_delete(smo_flat); smo_flat = NULL;
1700 cpl_propertylist_update_int(save_header,
"ESO PRO DATANCOM",
1704 reference, startwavelength,
1705 endwavelength, dispersion, 0,
1708 reference, startwavelength,
1709 endwavelength, dispersion, 0,
1713 if (
dfs_save_image(frameset, master_flat, master_screen_flat_tag,
1714 save_header, parlist, recipe, version))
1715 fors_pmos_calib_exit(NULL);
1719 save_header, parlist, recipe, version))
1720 fors_pmos_calib_exit(NULL);
1722 cpl_image_delete(norm_flat); norm_flat = NULL;
1723 cpl_propertylist_delete(save_header); save_header = NULL;
1733 cpl_msg_indent_less();
1734 cpl_msg_info(recipe,
"Perform final wavelength calibration...");
1735 cpl_msg_indent_more();
1737 nx = cpl_image_get_size_x(spatial);
1738 ny = cpl_image_get_size_y(spatial);
1740 idscoeff = cpl_table_new(ny);
1741 restable = cpl_table_new(nlines);
1742 rainbow = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1744 residual = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1745 fiterror = cpl_calloc(ny,
sizeof(
double));
1746 fitlines = cpl_calloc(ny,
sizeof(
int));
1749 dispersion, peakdetection,
1750 wradius, wdegree, wreject,
1753 &endwavelength, fitlines,
1756 residual, restable, NULL);
1758 if (rectified == NULL)
1759 fors_pmos_calib_exit(
"Wavelength calibration failure.");
1764 fors_pmos_calib_exit(NULL);
1770 for (k = 0; k < j; k ++) {
1771 cpl_propertylist_delete(header);
1776 fors_pmos_calib_exit(NULL);
1779 cpl_propertylist_delete(header);
1781 cpl_table_delete(restable); restable = NULL;
1783 cpl_table_wrap_double(idscoeff, fiterror,
"error"); fiterror = NULL;
1784 cpl_table_set_column_unit(idscoeff,
"error",
"pixel");
1785 cpl_table_wrap_int(idscoeff, fitlines,
"nlines"); fitlines = NULL;
1787 for (i = 0; i < ny; i++)
1788 if (!cpl_table_is_valid(idscoeff,
"c0", i))
1789 cpl_table_set_invalid(idscoeff,
"error", i);
1792 endwavelength, dispersion, 2);
1796 for (k = 0; k < j; k ++) {
1797 cpl_propertylist_delete(header);
1801 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
1802 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
1803 cpl_propertylist_update_double(header,
"CRVAL1",
1804 startwavelength + dispersion/2);
1805 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
1808 cpl_propertylist_update_double(header,
"CD1_1", dispersion);
1809 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
1810 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
1811 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
1812 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
1813 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
1818 fors_pmos_calib_exit(NULL);
1823 fors_pmos_calib_exit(NULL);
1826 cpl_image_delete(delta); delta = NULL;
1827 cpl_propertylist_delete(header); header = NULL;
1832 cpl_msg_info(recipe,
"Mean residual: %f pixel", mean_rms);
1834 mean_rms = cpl_table_get_column_mean(idscoeff,
"error");
1835 mean_rms_err = cpl_table_get_column_stdev(idscoeff,
"error");
1837 cpl_msg_info(recipe,
"Mean model accuracy: %f pixel (%f A)",
1838 mean_rms, mean_rms * dispersion);
1844 cpl_msg_info(recipe,
"Mean spectral resolution: %.2f",
1845 cpl_table_get_column_mean(restab,
"resolution"));
1846 cpl_msg_info(recipe,
1847 "Mean reference lines FWHM: %.2f +/- %.2f pixel",
1848 cpl_table_get_column_mean(restab,
"fwhm") / dispersion,
1849 cpl_table_get_column_mean(restab,
"fwhm_rms") / dispersion);
1851 cpl_table_duplicate_column(restab,
"dlambda",
1853 cpl_table_multiply_scalar(restab,
"dlambda", dispersion);
1854 cpl_table_duplicate_column(restab,
"dlambda_rms",
1855 restab,
"fwhm_rms");
1856 cpl_table_multiply_scalar(restab,
"dlambda_rms", dispersion);
1860 qclist = cpl_propertylist_new();
1870 "QC1 dictionary")) {
1871 fors_pmos_calib_exit(
"Cannot write dictionary version "
1876 keyname =
"QC.PMOS.RESOLUTION";
1879 cpl_table_get_column_mean(restab,
1883 "Mean spectral resolution")) {
1884 fors_pmos_calib_exit(
"Cannot write mean spectral "
1885 "resolution to QC log file");
1888 keyname =
"QC.PMOS.RESOLUTION.RMS";
1891 cpl_table_get_column_stdev(restab,
1895 "Scatter of spectral resolution")) {
1896 fors_pmos_calib_exit(
"Cannot write spectral resolution "
1897 "scatter to QC log file");
1900 keyname =
"QC.PMOS.RESOLUTION.NWAVE";
1902 if (fors_header_write_int(qclist, cpl_table_get_nrow(restab) -
1903 cpl_table_count_invalid(restab,
1907 "Number of examined wavelengths "
1908 "for resolution computation")) {
1909 fors_pmos_calib_exit(
"Cannot write number of lines used "
1910 "in spectral resolution computation "
1914 keyname =
"QC.PMOS.RESOLUTION.MEANRMS";
1917 cpl_table_get_column_mean(restab,
1920 "Mean error on spectral "
1921 "resolution computation")) {
1922 fors_pmos_calib_exit(
"Cannot write mean error in "
1923 "spectral resolution computation "
1927 keyname =
"QC.PMOS.RESOLUTION.NLINES";
1929 if (fors_header_write_int(qclist,
1930 cpl_table_get_column_mean(restab,
1932 cpl_table_get_nrow(restab),
1934 "Number of lines for spectral "
1935 "resolution computation")) {
1936 fors_pmos_calib_exit(
"Cannot write number of examined "
1937 "wavelengths in spectral resolution "
1938 "computation to QC log file");
1945 spectral_resolution_tag,
1947 fors_pmos_calib_exit(NULL);
1953 for (k = 0; k < j; k ++) {
1954 cpl_propertylist_delete(header);
1958 cpl_propertylist_append(header, qclist);
1961 fors_pmos_calib_exit(NULL);
1964 cpl_table_delete(restab); restab = NULL;
1965 cpl_propertylist_delete(qclist); qclist = NULL;
1966 cpl_propertylist_delete(header); header = NULL;
1970 fors_pmos_calib_exit(
"Cannot compute the spectral "
1971 "resolution table");
1976 fors_pmos_calib_exit(NULL);
1982 for (k = 0; k < j; k ++) {
1983 cpl_propertylist_delete(header);
1988 fors_pmos_calib_exit(NULL);
1991 cpl_propertylist_delete(header);
1997 dispersion, idscoeff, 0);
2002 dispersion, idscoeff, 0);
2004 cpl_image_delete(rect_flat); rect_flat = NULL;
2005 cpl_image_delete(rect_nflat); rect_nflat = NULL;
2010 cpl_table_delete(idscoeff); idscoeff = NULL;
2014 for (k = 0; k < j; k ++) {
2015 cpl_propertylist_delete(header);
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/2);
2023 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
2026 cpl_propertylist_update_double(header,
"CD1_1", dispersion);
2027 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
2028 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
2029 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
2030 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
2031 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
2032 cpl_propertylist_update_int(header,
"ESO PRO DATANCOM", 1);
2037 fors_pmos_calib_exit(NULL);
2042 fors_pmos_calib_exit(NULL);
2045 cpl_image_delete(rectified); rectified = NULL;
2047 cpl_propertylist_update_int(header,
"ESO PRO DATANCOM", nflats);
2050 if (
dfs_save_image(frameset, mapped_flat, mapped_screen_flat_tag,
2051 header, parlist, recipe, version))
2052 fors_pmos_calib_exit(NULL);
2053 cpl_image_delete(mapped_flat); mapped_flat = NULL;
2056 header, parlist, recipe, version))
2057 fors_pmos_calib_exit(NULL);
2058 cpl_image_delete(mapped_nflat); mapped_nflat = NULL;
2061 cpl_propertylist_delete(header); header = NULL;
2065 for (k = 0; k < j; k ++) {
2066 cpl_propertylist_delete(save_header);
2070 cpl_propertylist_update_double(save_header,
"CRPIX2", 1.0);
2071 cpl_propertylist_update_double(save_header,
"CRVAL2", 1.0);
2073 cpl_propertylist_update_double(save_header,
"CD1_1", 1.0);
2074 cpl_propertylist_update_double(save_header,
"CD1_2", 0.0);
2075 cpl_propertylist_update_double(save_header,
"CD2_1", 0.0);
2076 cpl_propertylist_update_double(save_header,
"CD2_2", 1.0);
2077 cpl_propertylist_update_string(save_header,
"CTYPE1",
"LINEAR");
2078 cpl_propertylist_update_string(save_header,
"CTYPE2",
"PIXEL");
2083 fors_pmos_calib_exit(NULL);
2088 fors_pmos_calib_exit(NULL);
2091 cpl_image_delete(residual); residual = NULL;
2092 cpl_propertylist_delete(save_header); save_header = NULL;
2096 reference, startwavelength, endwavelength,
2099 cpl_image_delete(rainbow); rainbow = NULL;
2103 for (k = 0; k < j; k ++) {
2104 cpl_propertylist_delete(save_header);
2116 "QC1 dictionary")) {
2117 fors_pmos_calib_exit(
"Cannot write dictionary version "
2125 "Mean accuracy of wavecalib model")) {
2126 fors_pmos_calib_exit(
"Cannot write mean wavelength calibration "
2127 "accuracy to QC log file");
2133 "QC.WAVE.ACCURACY.ERROR",
2135 "Error on accuracy of wavecalib model")) {
2136 fors_pmos_calib_exit(
"Cannot write error on wavelength "
2137 "calibration accuracy to QC log file");
2140 if (same_offset && fabs(mxpos) < 0.05) {
2143 data = cpl_image_get_data(wavemap);
2146 data[nx/2 + ccd_ysize*nx/2],
2147 "QC.PMOS.CENTRAL.WAVELENGTH",
2149 "Wavelength at CCD center")) {
2150 fors_pmos_calib_exit(
"Cannot write central wavelength "
2160 fors_pmos_calib_exit(NULL);
2165 fors_pmos_calib_exit(NULL);
2168 cpl_image_delete(wavemap); wavemap = NULL;
2170 cpl_propertylist_erase_regexp(save_header,
"^ESO QC ", 0);
2172 cpl_propertylist_delete(save_header); save_header = NULL;
2174 cpl_msg_indent_less();
2178 if (
dfs_save_image(frameset, coordinate, spatial_map_tag, save_header,
2179 parlist, recipe, version))
2180 fors_pmos_calib_exit(NULL);
2182 cpl_image_delete(coordinate); coordinate = NULL;
2183 cpl_propertylist_delete(save_header); save_header = NULL;
2189 double maxpos, maxneg, maxcurve, maxslope;
2199 "QC1 dictionary")) {
2200 fors_pmos_calib_exit(
"Cannot write dictionary version "
2204 maxpos = fabs(cpl_table_get_column_max(polytraces,
"c2"));
2205 maxneg = fabs(cpl_table_get_column_min(polytraces,
"c2"));
2206 maxcurve = maxpos > maxneg ? maxpos : maxneg;
2209 "QC.TRACE.MAX.CURVATURE",
2210 "Y pixel / X pixel ^2",
2211 "Max observed curvature "
2212 "in spectral tracing")) {
2213 fors_pmos_calib_exit(
"Cannot write max observed curvature in "
2214 "spectral tracing to QC log file");
2217 maxpos = fabs(cpl_table_get_column_max(polytraces,
"c1"));
2218 maxneg = fabs(cpl_table_get_column_min(polytraces,
"c1"));
2219 maxslope = maxpos > maxneg ? maxpos : maxneg;
2223 "QC.TRACE.MAX.SLOPE",
2224 "Y pixel / X pixel",
2225 "Max observed slope in spectral tracing")) {
2226 fors_pmos_calib_exit(
"Cannot write max observed slope in spectral "
2227 "tracing to QC log file");
2232 parlist, recipe, version)) {
2233 fors_pmos_calib_exit(NULL);
2236 cpl_propertylist_delete(header); header = NULL;
2237 cpl_table_delete(polytraces); polytraces = NULL;
2243 cpl_table *globaltbl;
2248 double *ytop = cpl_table_get_data_double(slits,
"ytop");
2249 double *ybot = cpl_table_get_data_double(slits,
"ybottom");
2254 nslits = cpl_table_get_nrow(slits);
2256 cpl_table_new_column(slits,
"pair_id", CPL_TYPE_INT);
2259 if (ccd_ysize == 400 || ccd_ysize == 500) {
2265 l_ytop = cpl_malloc(
sizeof(
double));
2267 l_id = cpl_malloc(
sizeof(
double));
2274 l_ytop = cpl_table_get_data_double(slitpos,
"ytop");
2275 l_id = cpl_table_get_data_int(slitpos,
"slit_id");
2276 npairs = cpl_table_get_nrow(slitpos);
2277 if (rebin_dist != rebin) {
2278 float rescale = (float)rebin_dist / rebin;
2279 for (i = 0; i < npairs; i++) {
2280 l_ytop[i] *= rescale;
2285 for (k = 0; k < npairs; k++) {
2288 for (h = 0; h < nslits; h++) {
2290 if (l_ytop[k] < ytop[h] && l_ytop[k] > ybot[h]) {
2291 if (h + 1 < nslits) {
2292 cpl_table_set_int(slits,
"pair_id", h, l_id[k]);
2293 cpl_table_set_int(slits,
"pair_id", h + 1, l_id[k]);
2301 cpl_table_fill_invalid_int(slits,
"pair_id", -1);
2303 if (ccd_ysize == 400 || ccd_ysize == 500) {
2308 cpl_table_delete(slitpos); slitpos = NULL;
2309 cpl_table_delete(globaltbl); globaltbl = NULL;
2311 cpl_table_delete(maskslits); maskslits = NULL;
2316 parlist, recipe, version)) {
2317 fors_pmos_calib_exit(NULL);
2320 cpl_table_delete(slits); slits = NULL;
2322 cpl_image_delete(spatial); spatial = NULL;
2324 cpl_free(instrume); instrume = NULL;
2326 cpl_table_delete(overscans); overscans = NULL;
2327 cpl_image_delete(master_bias); master_bias = NULL;
2328 cpl_image_delete(master_flat); master_flat = NULL;
2330 cpl_table_delete(wavelengths); wavelengths = NULL;
2331 cpl_vector_delete(lines); lines = NULL;
2333 if (cpl_error_get_code()) {
2334 cpl_msg_error(cpl_error_get_where(),
"%s", cpl_error_get_message());
2335 fors_pmos_calib_exit(NULL);
cpl_image * mos_spatial_calibration(cpl_image *spectra, cpl_table *slits, cpl_table *polytraces, double reference, double blue, double red, double dispersion, int flux, cpl_image *calibration)
Spatial remapping of CCD spectra eliminating the spectral curvature.
cpl_image * mos_map_pixel(cpl_table *idscoeff, double reference, double blue, double red, double dispersion, int trend)
Create a pixel map from an IDS coefficients table.
int cpl_plugin_get_info(cpl_pluginlist *list)
Build the list of available plugins, for this module.
cpl_image * dfs_load_image(cpl_frameset *frameset, const char *category, cpl_type type, int ext, int calib)
Loading image data of given category.
const char * dfs_get_parameter_string(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe string parameter value.
cpl_image * mos_wavelength_calibration_raw(const cpl_image *image, cpl_vector *lines, double dispersion, float level, int sradius, int order, double reject, double refwave, double *wavestart, double *waveend, int *nlines, double *error, cpl_table *idscoeff, cpl_image *calibration, cpl_image *residuals, cpl_table *restable, cpl_mask *refmask, cpl_table *detected_lines)
Derive wavelength calibration from a raw arc lamp or sky exposure.
double mos_distortions_rms(cpl_image *rectified, cpl_vector *lines, double wavestart, double dispersion, int radius, int highres)
Estimate the spectral distortion modeling goodness.
cpl_propertylist * dfs_load_header(cpl_frameset *frameset, const char *category, int ext)
Loading header associated to data of given category.
cpl_error_code dfs_save_image_null(cpl_frameset *frameset, cpl_parameterlist *parlist, const char *tag, const char *recipename, const char *version)
Save a product with an empty primary extension.
cpl_error_code dfs_save_image_ext(cpl_image *image, const char *tag, cpl_propertylist *extheader)
Save an image in a extension.
cpl_image * mos_normalise_flat(cpl_image *flat, cpl_image *spatial, cpl_table *slits, cpl_table *polytraces, double reference, double blue, double red, double dispersion, int sradius, int polyorder)
Normalise a flat field exposure.
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_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_identify_slits(cpl_table *slits, cpl_table *maskslits, cpl_table *global)
Identify slits listed in a slit location table.
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_error_code fors_header_write_double(cpl_propertylist *header, double value, const char *name, const char *unit, const char *comment)
Write an integer value to the active QC1 PAF object and to a header.
cpl_error_code mos_subtract_background(cpl_image *image)
Subtract the background.
cpl_image * mos_remove_bias(cpl_image *image, cpl_image *bias, cpl_table *overscans)
Subtract the bias from a CCD exposure.
cpl_table * mos_poly_trace(cpl_table *slits, cpl_table *traces, int order)
Fit spectral traces.
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.
cpl_error_code dfs_save_table_ext(cpl_table *table, const char *tag, cpl_propertylist *extheader)
Save a table in a extension (different from the first one)
cpl_error_code mos_global_trace(cpl_table *slits, cpl_table *polytraces, int mode)
Recompute tracing coefficients globally.
void fors_stack_define_parameters(cpl_parameterlist *parameters, const char *context, const char *default_method)
Define recipe parameters.
int dfs_save_image(cpl_frameset *frameset, const cpl_image *image, const char *category, cpl_propertylist *header, const cpl_parameterlist *parlist, const char *recipename, const char *version)
Saving image data of given category.
cpl_table * dfs_load_table(cpl_frameset *frameset, const char *category, int ext)
Loading table data of given category.
cpl_table * mos_trace_flat(cpl_image *flat, cpl_table *slits, double reference, double blue, double red, double dispersion)
Trace flat field spectra.
cpl_image * mos_wavelength_calibration_final(cpl_image *image, cpl_table *slits, cpl_vector *lines, double dispersion, float level, int sradius, int order, double reject, double refwave, double *wavestart, double *waveend, int *nlines, double *error, cpl_table *idscoeff, cpl_image *calibration, cpl_image *residuals, cpl_table *restable, cpl_table *detected_lines)
Derive wavelength calibration from a rectified arc lamp or sky exposure.
int dfs_get_parameter_int(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe integer parameter value.
int mos_check_slits(cpl_table *slits, float rescale)
Check that all slit have been detected, insert them if not.
int dfs_save_table(cpl_frameset *frameset, const cpl_table *table, const char *category, cpl_propertylist *header, const cpl_parameterlist *parlist, const char *recipename, const char *version)
Saving table data of given category.
cpl_error_code mos_refmask_find_gaps(cpl_mask *refmask, cpl_image *master_flat, double level)
Reconstruct the gaps required for slit location.
cpl_image * mos_ksigma_stack(cpl_imagelist *imlist, double klow, double khigh, int kiter, cpl_image **good)
Stack images using k-sigma clipping.
cpl_table * mos_resolution_table(cpl_image *image, double startwave, double dispersion, int saturation, cpl_vector *lines)
Compute mean spectral resolution at a given arc lamp line.
cpl_error_code mos_randomise_image(cpl_image *image, double ron, double gain, double bias)
Randomise image.
cpl_table * mos_locate_spectra(cpl_mask *mask)
Find the location of detected spectra on the CCD.
double dfs_get_parameter_double(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe double parameter value.
cpl_error_code fors_header_write_string(cpl_propertylist *header, const char *name, const char *value, const char *comment)
Write a string value to the active QC1 PAF object and to a header.
cpl_error_code mos_saturation_process(cpl_image *image)
Process saturation.
cpl_table * mos_build_slit_location(cpl_table *global, cpl_table *maskslits, int ysize)
Build the slit location table from a global distortions table.