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 (message) 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_image_delete(mapped_flat); \
131 cpl_image_delete(mapped_nflat); \
132 cpl_mask_delete(refmask); \
133 cpl_propertylist_delete(header); \
134 cpl_propertylist_delete(save_header); \
135 cpl_propertylist_delete(qclist); \
136 cpl_table_delete(grism_table); \
137 cpl_table_delete(idscoeff); \
138 cpl_table_delete(idscoeff_all); \
139 cpl_table_delete(restable); \
140 cpl_table_delete(maskslits); \
141 cpl_table_delete(overscans); \
142 cpl_table_delete(traces); \
143 cpl_table_delete(polytraces); \
144 cpl_table_delete(slits); \
145 cpl_table_delete(restab); \
146 cpl_table_delete(global); \
147 cpl_table_delete(wavelengths); \
148 cpl_vector_delete(lines); \
149 cpl_msg_indent_less(); \
153 #define fors_pmos_calib_exit_memcheck(message) \
155 if (message) cpl_msg_info(recipe, message); \
156 printf("free instrume (%p)\n", instrume); \
157 cpl_free(instrume); \
158 printf("free pipefile (%p)\n", pipefile); \
159 cpl_free(pipefile); \
160 printf("free fiterror (%p)\n", fiterror); \
161 cpl_free(fiterror); \
162 printf("free fitlines (%p)\n", fitlines); \
163 cpl_free(fitlines); \
164 printf("free bias (%p)\n", bias); \
165 cpl_image_delete(bias); \
166 printf("free master_bias (%p)\n", master_bias); \
167 cpl_image_delete(master_bias); \
168 printf("free coordinate (%p)\n", coordinate); \
169 cpl_image_delete(coordinate); \
170 printf("free checkwave (%p)\n", checkwave); \
171 cpl_image_delete(checkwave); \
172 printf("free flat (%p)\n", flat); \
173 cpl_image_delete(flat); \
174 printf("free master_flat (%p)\n", master_flat); \
175 cpl_image_delete(master_flat); \
176 printf("free norm_flat (%p)\n", norm_flat); \
177 cpl_image_delete(norm_flat); \
178 printf("free mapped_flat (%p)\n", mapped_flat); \
179 cpl_image_delete(mapped_flat); \
180 printf("free mapped_nflat (%p)\n", mapped_nflat); \
181 cpl_image_delete(mapped_nflat); \
182 printf("free rainbow (%p)\n", rainbow); \
183 cpl_image_delete(rainbow); \
184 printf("free rectified (%p)\n", rectified); \
185 cpl_image_delete(rectified); \
186 printf("free residual (%p)\n", residual); \
187 cpl_image_delete(residual); \
188 printf("free smo_flat (%p)\n", smo_flat); \
189 cpl_image_delete(smo_flat); \
190 printf("free spatial (%p)\n", spatial); \
191 cpl_image_delete(spatial); \
192 printf("free spectra (%p)\n", spectra); \
193 cpl_image_delete(spectra); \
194 printf("free wavemap (%p)\n", wavemap); \
195 cpl_image_delete(wavemap); \
196 printf("free delta (%p)\n", delta); \
197 cpl_image_delete(delta); \
198 printf("free rect_flat (%p)\n", rect_flat); \
199 cpl_image_delete(rect_flat); \
200 printf("free rect_nflat (%p)\n", rect_nflat); \
201 cpl_image_delete(rect_nflat); \
202 printf("free refmask (%p)\n", refmask); \
203 cpl_mask_delete(refmask); \
204 printf("free header (%p)\n", header); \
205 cpl_propertylist_delete(header); \
206 printf("free save_header (%p)\n", save_header); \
207 cpl_propertylist_delete(save_header); \
208 printf("free qclist (%p)\n", qclist); \
209 cpl_propertylist_delete(qclist); \
210 printf("free grism_table (%p)\n", grism_table); \
211 cpl_table_delete(grism_table); \
212 printf("free idscoeff (%p)\n", idscoeff); \
213 cpl_table_delete(idscoeff); \
214 printf("free idscoeff_all (%p)\n", idscoeff_all); \
215 cpl_table_delete(idscoeff_all); \
216 printf("free restable (%p)\n", restable); \
217 cpl_table_delete(restable); \
218 printf("free maskslits (%p)\n", maskslits); \
219 cpl_table_delete(maskslits); \
220 printf("free overscans (%p)\n", overscans); \
221 cpl_table_delete(overscans); \
222 printf("free traces (%p)\n", traces); \
223 cpl_table_delete(traces); \
224 printf("free polytraces (%p)\n", polytraces); \
225 cpl_table_delete(polytraces); \
226 printf("free slits (%p)\n", slits); \
227 cpl_table_delete(slits); \
228 printf("free restab (%p)\n", restab); \
229 cpl_table_delete(restab); \
230 printf("free global (%p)\n", global); \
231 cpl_table_delete(global); \
232 printf("free wavelengths (%p)\n", wavelengths); \
233 cpl_table_delete(wavelengths); \
234 printf("free lines (%p)\n", lines); \
235 cpl_vector_delete(lines); \
236 cpl_msg_indent_less(); \
254 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe );
255 cpl_plugin *plugin = &recipe->interface;
257 cpl_plugin_init(plugin,
260 CPL_PLUGIN_TYPE_RECIPE,
262 "Determination of the extraction mask",
263 fors_pmos_calib_description,
266 "This file is currently part of the FORS Instrument Pipeline\n"
267 "Copyright (C) 2002-2010 European Southern Observatory\n\n"
268 "This program is free software; you can redistribute it and/or modify\n"
269 "it under the terms of the GNU General Public License as published by\n"
270 "the Free Software Foundation; either version 2 of the License, or\n"
271 "(at your option) any later version.\n\n"
272 "This program is distributed in the hope that it will be useful,\n"
273 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
274 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
275 "GNU General Public License for more details.\n\n"
276 "You should have received a copy of the GNU General Public License\n"
277 "along with this program; if not, write to the Free Software Foundation,\n"
278 "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n",
279 fors_pmos_calib_create,
280 fors_pmos_calib_exec,
281 fors_pmos_calib_destroy);
283 cpl_pluginlist_append(list, plugin);
299 static int fors_pmos_calib_create(cpl_plugin *plugin)
309 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
310 recipe = (cpl_recipe *)plugin;
318 recipe->parameters = cpl_parameterlist_new();
325 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.dispersion",
327 "Expected spectral dispersion (Angstrom/pixel)",
328 "fors.fors_pmos_calib",
330 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"dispersion");
331 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
332 cpl_parameterlist_append(recipe->parameters, p);
338 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.peakdetection",
340 "Initial peak detection threshold (ADU)",
341 "fors.fors_pmos_calib",
343 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"peakdetection");
344 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
345 cpl_parameterlist_append(recipe->parameters, p);
351 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.wdegree",
353 "Degree of wavelength calibration polynomial",
354 "fors.fors_pmos_calib",
356 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wdegree");
357 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
358 cpl_parameterlist_append(recipe->parameters, p);
364 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.wradius",
366 "Search radius if iterating pattern-matching "
367 "with first-guess method",
368 "fors.fors_pmos_calib",
370 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wradius");
371 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
372 cpl_parameterlist_append(recipe->parameters, p);
378 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.wreject",
380 "Rejection threshold in dispersion "
381 "relation fit (pixel)",
382 "fors.fors_pmos_calib",
384 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wreject");
385 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
386 cpl_parameterlist_append(recipe->parameters, p);
392 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.wcolumn",
394 "Name of line catalog table column "
396 "fors.fors_pmos_calib",
398 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wcolumn");
399 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
400 cpl_parameterlist_append(recipe->parameters, p);
406 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.cdegree",
408 "Degree of spectral curvature polynomial",
409 "fors.fors_pmos_calib",
411 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"cdegree");
412 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
413 cpl_parameterlist_append(recipe->parameters, p);
419 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.cmode",
421 "Interpolation mode of curvature solution "
423 "interpolation, 1 = fill gaps, 2 = global "
425 "fors.fors_pmos_calib",
427 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"cmode");
428 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
429 cpl_parameterlist_append(recipe->parameters, p);
435 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.startwavelength",
437 "Start wavelength in spectral extraction",
438 "fors.fors_pmos_calib",
440 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"startwavelength");
441 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
442 cpl_parameterlist_append(recipe->parameters, p);
448 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.endwavelength",
450 "End wavelength in spectral extraction",
451 "fors.fors_pmos_calib",
453 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"endwavelength");
454 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
455 cpl_parameterlist_append(recipe->parameters, p);
468 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.ddegree",
470 "Degree of flat field fitting polynomial "
471 "along dispersion direction",
472 "fors.fors_pmos_calib",
474 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ddegree");
475 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
476 cpl_parameterlist_append(recipe->parameters, p);
482 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.dradius",
484 "Smooth box radius for flat field along "
485 "dispersion direction",
486 "fors.fors_pmos_calib",
488 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"dradius");
489 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
490 cpl_parameterlist_append(recipe->parameters, p);
496 p = cpl_parameter_new_value(
"fors.fors_pmos_calib.qc",
498 "Compute QC1 parameters",
499 "fors.fors_pmos_calib",
501 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"qc");
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_calib.check",
511 "Create intermediate products",
512 "fors.fors_pmos_calib",
514 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"check");
515 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
516 cpl_parameterlist_append(recipe->parameters, p);
530 static int fors_pmos_calib_exec(cpl_plugin *plugin)
534 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
535 recipe = (cpl_recipe *)plugin;
539 return fors_pmos_calib(recipe->parameters, recipe->frames);
551 static int fors_pmos_calib_destroy(cpl_plugin *plugin)
555 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
556 recipe = (cpl_recipe *)plugin;
560 cpl_parameterlist_delete(recipe->parameters);
575 static int fors_pmos_calib(cpl_parameterlist *parlist, cpl_frameset *frameset)
578 const char *recipe =
"fors_pmos_calib";
586 double peakdetection;
593 double startwavelength;
594 double endwavelength;
599 const char *stack_method;
611 cpl_imagelist *biases = NULL;
612 cpl_image *bias = NULL;
613 cpl_image *master_bias = NULL;
614 cpl_image *multi_bias = NULL;
615 cpl_image *flat = NULL;
616 cpl_image *master_flat = NULL;
617 cpl_image *added_flat = NULL;
618 cpl_image *trace_flat = NULL;
619 cpl_image *smo_flat = NULL;
620 cpl_image *norm_flat = NULL;
621 cpl_image *spectra = NULL;
622 cpl_image *wavemap = NULL;
623 cpl_image *delta = NULL;
624 cpl_image *residual = NULL;
625 cpl_image *checkwave = NULL;
626 cpl_image *rectified = NULL;
627 cpl_image *dummy = NULL;
628 cpl_image *add_dummy = NULL;
629 cpl_image *refimage = NULL;
630 cpl_image *coordinate = NULL;
631 cpl_image *rainbow = NULL;
632 cpl_image *spatial = NULL;
633 cpl_image *rect_flat = NULL;
634 cpl_image *rect_nflat = NULL;
635 cpl_image *mapped_flat = NULL;
636 cpl_image *mapped_nflat = NULL;
638 cpl_mask *refmask = NULL;
640 cpl_table *grism_table = NULL;
641 cpl_table *overscans = NULL;
642 cpl_table *wavelengths = NULL;
643 cpl_table *idscoeff = NULL;
644 cpl_table *idscoeff_all = NULL;
645 cpl_table *restable = NULL;
646 cpl_table *slits = NULL;
647 cpl_table *positions = NULL;
648 cpl_table *maskslits = NULL;
649 cpl_table *traces = NULL;
650 cpl_table *polytraces = NULL;
651 cpl_table *restab = NULL;
652 cpl_table *global = NULL;
654 cpl_vector *lines = NULL;
656 cpl_propertylist *header_dist = NULL;
657 cpl_propertylist *header = NULL;
658 cpl_propertylist *save_header = NULL;
659 cpl_propertylist *qclist = NULL;
667 const char *flat_tag;
668 const char *master_screen_flat_tag;
669 const char *master_norm_flat_tag;
670 const char *reduced_lamp_tag;
671 const char *disp_residuals_tag;
672 const char *disp_coeff_tag;
673 const char *wavelength_map_tag;
674 const char *spectra_detection_tag;
675 const char *spectral_resolution_tag;
676 const char *slit_map_tag;
677 const char *curv_traces_tag;
678 const char *curv_coeff_tag;
679 const char *spatial_map_tag;
680 const char *slit_location_tag;
681 const char *master_distortion_tag =
"MASTER_DISTORTION_TABLE";
682 const char *disp_residuals_table_tag;
683 const char *delta_image_tag;
684 const char *mapped_screen_flat_tag;
685 const char *mapped_norm_flat_tag;
699 int rebin, rebin_dist;
701 double *fiterror = NULL;
702 int *fitlines = NULL;
709 char *instrume = NULL;
720 snprintf(version, 80,
"%s-%s", PACKAGE, PACKAGE_VERSION);
722 cpl_msg_set_indentation(2);
730 cpl_msg_info(recipe,
"Recipe %s configuration parameters:", recipe);
731 cpl_msg_indent_more();
733 if (cpl_frameset_count_tags(frameset,
"GRISM_TABLE") > 1)
734 fors_pmos_calib_exit(
"Too many in input: GRISM_TABLE");
739 "fors.fors_pmos_calib.dispersion", grism_table);
741 if (dispersion <= 0.0)
742 fors_pmos_calib_exit(
"Invalid spectral dispersion value");
745 "fors.fors_pmos_calib.peakdetection", grism_table);
746 if (peakdetection <= 0.0)
747 fors_pmos_calib_exit(
"Invalid peak detection level");
750 "fors.fors_pmos_calib.wdegree", grism_table);
753 fors_pmos_calib_exit(
"Invalid polynomial degree");
756 fors_pmos_calib_exit(
"Max allowed polynomial degree is 5");
759 "fors.fors_pmos_calib.wradius", NULL);
762 fors_pmos_calib_exit(
"Invalid search radius");
765 "fors.fors_pmos_calib.wreject", NULL);
768 fors_pmos_calib_exit(
"Invalid rejection threshold");
771 "fors.fors_pmos_calib.wcolumn", NULL);
774 "fors.fors_pmos_calib.cdegree", grism_table);
777 fors_pmos_calib_exit(
"Invalid polynomial degree");
780 fors_pmos_calib_exit(
"Max allowed polynomial degree is 5");
784 if (cmode < 0 || cmode > 2)
785 fors_pmos_calib_exit(
"Invalid curvature solution interpolation mode");
788 "fors.fors_pmos_calib.startwavelength", grism_table);
789 if (startwavelength > 1.0)
790 if (startwavelength < 3000.0 || startwavelength > 13000.0)
791 fors_pmos_calib_exit(
"Invalid wavelength");
794 "fors.fors_pmos_calib.endwavelength", grism_table);
795 if (endwavelength > 1.0) {
796 if (endwavelength < 3000.0 || endwavelength > 13000.0)
797 fors_pmos_calib_exit(
"Invalid wavelength");
798 if (startwavelength < 1.0)
799 fors_pmos_calib_exit(
"Invalid wavelength interval");
802 if (startwavelength > 1.0)
803 if (endwavelength - startwavelength <= 0.0)
804 fors_pmos_calib_exit(
"Invalid wavelength interval");
807 "fors.fors_pmos_calib.stack_method",
810 if (strcmp(stack_method,
"minmax") == 0) {
812 "fors.fors_pmos_calib.minrejection", NULL);
814 fors_pmos_calib_exit(
"Invalid number of lower rejections");
817 "fors.fors_pmos_calib.maxrejection", NULL);
819 fors_pmos_calib_exit(
"Invalid number of upper rejections");
822 if (strcmp(stack_method,
"ksigma") == 0) {
824 "fors.fors_pmos_calib.klow", NULL);
826 fors_pmos_calib_exit(
"Invalid lower K-sigma");
829 "fors.fors_pmos_calib.khigh", NULL);
831 fors_pmos_calib_exit(
"Invalid lower K-sigma");
834 "fors.fors_pmos_calib.kiter", NULL);
836 fors_pmos_calib_exit(
"Invalid number of iterations");
840 "fors.fors_pmos_calib.ddegree", NULL);
842 "fors.fors_pmos_calib.dradius", NULL);
845 fors_pmos_calib_exit(
"Invalid smoothing box radius");
851 cpl_table_delete(grism_table); grism_table = NULL;
853 if (cpl_error_get_code())
854 fors_pmos_calib_exit(
"Failure getting the configuration parameters");
861 cpl_msg_indent_less();
862 cpl_msg_info(recipe,
"Check input set-of-frames:");
863 cpl_msg_indent_more();
866 cpl_frameset *subframeset = cpl_frameset_duplicate(frameset);
867 cpl_frameset_erase(subframeset,
"BIAS");
868 cpl_frameset_erase(subframeset,
"MASTER_BIAS");
871 fors_pmos_calib_exit(
"Input frames are not from the same grism");
874 fors_pmos_calib_exit(
"Input frames are not from the same filter");
877 fors_pmos_calib_exit(
"Input frames are not from the same chip");
879 cpl_frameset_delete(subframeset);
882 pmos = cpl_frameset_count_tags(frameset,
"LAMP_PMOS");
885 fors_pmos_calib_exit(
"Missing input arc lamp frame");
888 cpl_msg_info(recipe,
"PMOS data found");
889 arc_tag =
"LAMP_PMOS";
890 flat_tag =
"SCREEN_FLAT_PMOS";
891 master_screen_flat_tag =
"MASTER_SCREEN_FLAT_PMOS";
892 master_norm_flat_tag =
"MASTER_NORM_FLAT_PMOS";
893 reduced_lamp_tag =
"REDUCED_LAMP_PMOS";
894 disp_residuals_tag =
"DISP_RESIDUALS_PMOS";
895 disp_coeff_tag =
"DISP_COEFF_PMOS";
896 wavelength_map_tag =
"WAVELENGTH_MAP_PMOS";
897 spectra_detection_tag =
"SPECTRA_DETECTION_PMOS";
898 spectral_resolution_tag =
"SPECTRAL_RESOLUTION_PMOS";
899 slit_map_tag =
"SLIT_MAP_PMOS";
900 curv_traces_tag =
"CURV_TRACES_PMOS";
901 curv_coeff_tag =
"CURV_COEFF_PMOS";
902 spatial_map_tag =
"SPATIAL_MAP_PMOS";
903 slit_location_tag =
"SLIT_LOCATION_PMOS";
904 disp_residuals_table_tag =
"DISP_RESIDUALS_TABLE_PMOS";
905 delta_image_tag =
"DELTA_IMAGE_PMOS";
906 mapped_screen_flat_tag =
"MAPPED_SCREEN_FLAT_PMOS";
907 mapped_norm_flat_tag =
"MAPPED_NORM_FLAT_PMOS";
911 if (cpl_frameset_count_tags(frameset,
"MASTER_BIAS") == 0) {
912 if (cpl_frameset_count_tags(frameset,
"BIAS") == 0)
913 fors_pmos_calib_exit(
"Missing required input: MASTER_BIAS or BIAS");
914 nbias = cpl_frameset_count_tags(frameset,
"BIAS");
917 if (cpl_frameset_count_tags(frameset,
"MASTER_BIAS") > 1)
918 fors_pmos_calib_exit(
"Too many in input: MASTER_BIAS");
920 if (cpl_frameset_count_tags(frameset,
"MASTER_LINECAT") == 0)
921 fors_pmos_calib_exit(
"Missing required input: MASTER_LINECAT");
923 if (cpl_frameset_count_tags(frameset,
"MASTER_LINECAT") > 1)
924 fors_pmos_calib_exit(
"Too many in input: MASTER_LINECAT");
926 if (cpl_frameset_count_tags(frameset,
"MASTER_LINECAT") == 0)
927 fors_pmos_calib_exit(
"Missing required input: MASTER_LINECAT");
929 if (cpl_frameset_count_tags(frameset,
"MASTER_LINECAT") > 1)
930 fors_pmos_calib_exit(
"Too many in input: MASTER_LINECAT");
937 if (cpl_frameset_count_tags(frameset, master_distortion_tag) > 1)
938 fors_pmos_calib_exit(
"Too many in input: MASTER_DISTORTION_TABLE");
940 nflats = cpl_frameset_count_tags(frameset, flat_tag);
943 cpl_msg_error(recipe,
"Missing required input: %s", flat_tag);
944 fors_pmos_calib_exit(NULL);
947 cpl_msg_indent_less();
950 cpl_msg_info(recipe,
"Load %d flat field frames and stack them "
951 "with method \"%s\"", nflats, stack_method);
953 cpl_msg_info(recipe,
"Load flat field exposure...");
955 cpl_msg_indent_more();
960 fors_pmos_calib_exit(
"Cannot load flat field frame header");
962 alltime = cpl_propertylist_get_double(header,
"EXPTIME");
964 if (cpl_error_get_code() != CPL_ERROR_NONE)
965 fors_pmos_calib_exit(
"Missing keyword EXPTIME in flat field "
968 cpl_propertylist_delete(header);
970 for (i = 1; i < nflats; i++) {
975 fors_pmos_calib_exit(
"Cannot load flat field frame header");
977 alltime += cpl_propertylist_get_double(header,
"EXPTIME");
979 if (cpl_error_get_code() != CPL_ERROR_NONE)
980 fors_pmos_calib_exit(
"Missing keyword EXPTIME in flat field "
983 cpl_propertylist_delete(header);
988 char *montecarlo = getenv(
"MONTECARLO");
991 doit = atoi(montecarlo);
995 CPL_TYPE_FLOAT, 0, 1);
996 if (master_bias == NULL)
997 fors_pmos_calib_exit(
"Cannot load master bias");
999 blevel = cpl_image_get_mean(master_bias);
1001 cpl_image_delete(master_bias);
1005 master_flat =
dfs_load_image(frameset, flat_tag, CPL_TYPE_FLOAT, 0, 0);
1007 if (master_flat == NULL)
1008 fors_pmos_calib_exit(
"Cannot load flat field");
1013 gain = cpl_propertylist_get_double(header,
"ESO DET OUT1 CONAD");
1015 if (cpl_error_get_code() != CPL_ERROR_NONE)
1016 fors_pmos_calib_exit(
"Missing keyword ESO DET OUT1 CONAD "
1017 "in flat field frame header");
1019 ron = cpl_propertylist_get_double(header,
"ESO DET OUT1 RON");
1021 if (cpl_error_get_code() != CPL_ERROR_NONE)
1022 fors_pmos_calib_exit(
"Missing keyword ESO DET OUT1 RON "
1023 "in flat field frame header");
1025 cpl_propertylist_delete(header);
1032 ny = cpl_image_get_size_y(master_flat);
1035 if (strcmp(stack_method,
"average") == 0) {
1036 for (i = 1; i < nflats; i++) {
1042 cpl_image_add(master_flat, flat);
1043 cpl_image_delete(flat); flat = NULL;
1046 fors_pmos_calib_exit(
"Cannot load flat field");
1056 cpl_imagelist *flatlist = NULL;
1059 added_flat = cpl_image_duplicate(master_flat);
1061 flatlist = cpl_imagelist_new();
1062 cpl_imagelist_set(flatlist, master_flat,
1063 cpl_imagelist_get_size(flatlist));
1074 rflux = cpl_image_get_mean(master_flat);
1076 for (i = 1; i < nflats; i++) {
1082 cpl_image_add(added_flat, flat);
1083 flux = cpl_image_get_mean(flat);
1084 cpl_image_multiply_scalar(flat, rflux / flux);
1085 cpl_imagelist_set(flatlist, flat,
1086 cpl_imagelist_get_size(flatlist));
1089 fors_pmos_calib_exit(
"Cannot load flat field");
1093 if (strcmp(stack_method,
"median") == 0) {
1094 master_flat = cpl_imagelist_collapse_median_create(flatlist);
1097 if (strcmp(stack_method,
"minmax") == 0) {
1098 master_flat = cpl_imagelist_collapse_minmax_create(flatlist,
1103 if (strcmp(stack_method,
"ksigma") == 0) {
1105 klow, khigh, kiter, NULL);
1119 fors_pmos_calib_exit(
"Cannot load arc lamp header");
1121 instrume = (
char *)cpl_propertylist_get_string(header,
"INSTRUME");
1122 if (instrume == NULL)
1123 fors_pmos_calib_exit(
"Missing keyword INSTRUME in arc lamp header");
1125 instrume = cpl_strdup(instrume);
1127 if (instrume[4] ==
'1')
1128 snprintf(version, 80,
"%s/%s",
"fors1", VERSION);
1129 if (instrume[4] ==
'2')
1130 snprintf(version, 80,
"%s/%s",
"fors2", VERSION);
1132 reference = cpl_propertylist_get_double(header,
"ESO INS GRIS1 WLEN");
1134 if (cpl_error_get_code() != CPL_ERROR_NONE)
1135 fors_pmos_calib_exit(
"Missing keyword ESO INS GRIS1 WLEN in arc lamp "
1138 if (reference < 3000.0)
1141 if (reference < 3000.0 || reference > 13000.0) {
1142 cpl_msg_error(recipe,
"Invalid central wavelength %.2f read from "
1143 "keyword ESO INS GRIS1 WLEN in arc lamp frame header",
1145 fors_pmos_calib_exit(NULL);
1148 cpl_msg_info(recipe,
"The central wavelength is: %.2f", reference);
1150 rebin = cpl_propertylist_get_int(header,
"ESO DET WIN1 BINX");
1152 if (cpl_error_get_code() != CPL_ERROR_NONE)
1153 fors_pmos_calib_exit(
"Missing keyword ESO DET WIN1 BINX in arc lamp "
1157 dispersion *= rebin;
1158 cpl_msg_warning(recipe,
"The rebin factor is %d, and therefore the "
1159 "working dispersion used is %f A/pixel", rebin,
1163 gain = cpl_propertylist_get_double(header,
"ESO DET OUT1 CONAD");
1165 if (cpl_error_get_code() != CPL_ERROR_NONE)
1166 fors_pmos_calib_exit(
"Missing keyword ESO DET OUT1 CONAD in arc lamp "
1169 cpl_msg_info(recipe,
"The gain factor is: %.2f e-/ADU", gain);
1173 cpl_msg_info(recipe,
"Produce mask slit position table...");
1182 mxpos = cpl_table_get_column_median(maskslits,
"xtop");
1183 xpos = cpl_table_get_data_double(maskslits,
"xtop");
1184 nslits = cpl_table_get_nrow(maskslits);
1187 for (i = 0; i < nslits; i++) {
1188 if (fabs(mxpos-xpos[i]) > 0.01) {
1195 if(nslits_out_det != 0)
1199 cpl_msg_info(recipe,
"All slits have same offset: %.2f", mxpos);
1202 cpl_msg_info(recipe,
"All slits have different offsets");
1205 if (ny != 400 && ny != 500) {
1206 if (cpl_frameset_count_tags(frameset,
1207 master_distortion_tag) == 0)
1208 fors_pmos_calib_exit(
1209 "Missing required input: MASTER_DISTORTION_TABLE");
1212 master_distortion_tag, 0);
1213 rebin_dist = cpl_propertylist_get_int(header_dist,
1214 "ESO DET WIN1 BINX");
1215 cpl_propertylist_delete(header_dist);
1232 cpl_msg_info(recipe,
"Generate the master from input raw biases...");
1236 biases = cpl_imagelist_new();
1241 fors_pmos_calib_exit(
"Cannot load bias frame");
1243 cpl_imagelist_set(biases, bias, 0);
1245 for (i = 1; i < nbias; i++) {
1248 cpl_imagelist_set(biases, bias, i);
1250 fors_pmos_calib_exit(
"Cannot load bias frame");
1253 master_bias = cpl_imagelist_collapse_median_create(biases);
1255 cpl_imagelist_delete(biases);
1259 CPL_TYPE_FLOAT, 0, 1);
1260 if (master_bias == NULL)
1261 fors_pmos_calib_exit(
"Cannot load bias");
1267 CPL_TYPE_FLOAT, 0, 1);
1268 if (master_bias == NULL)
1269 fors_pmos_calib_exit(
"Cannot load master bias");
1272 cpl_msg_info(recipe,
"Remove the master bias...");
1274 overscans = mos_load_overscans_fors(header);
1275 cpl_propertylist_delete(header); header = NULL;
1278 int xlow = cpl_table_get_int(overscans,
"xlow", 0, NULL);
1279 int ylow = cpl_table_get_int(overscans,
"ylow", 0, NULL);
1280 int xhig = cpl_table_get_int(overscans,
"xhig", 0, NULL);
1281 int yhig = cpl_table_get_int(overscans,
"yhig", 0, NULL);
1282 dummy = cpl_image_extract(master_bias, xlow+1, ylow+1, xhig, yhig);
1283 cpl_image_delete(master_bias); master_bias = dummy;
1286 NULL, parlist, recipe, version))
1287 fors_pmos_calib_exit(NULL);
1291 multi_bias = cpl_image_multiply_scalar_create(master_bias, nflats);
1295 cpl_image_delete(multi_bias);
1300 cpl_image_delete(master_flat);
1301 master_flat = dummy;
1303 if (master_flat == NULL)
1304 fors_pmos_calib_exit(
"Cannot remove bias from flat field");
1307 cpl_image_delete(added_flat);
1308 added_flat = add_dummy;
1310 if (added_flat == NULL)
1311 fors_pmos_calib_exit(
"Cannot remove bias from added flat field");
1313 trace_flat = added_flat;
1316 trace_flat = master_flat;
1320 if (wavelengths == NULL)
1321 fors_pmos_calib_exit(
"Cannot load line catalog");
1327 nlines = cpl_table_get_nrow(wavelengths);
1330 fors_pmos_calib_exit(
"Empty input line catalog");
1332 if (cpl_table_has_column(wavelengths, wcolumn) != 1) {
1333 cpl_msg_error(recipe,
"Missing column %s in input line catalog table",
1335 fors_pmos_calib_exit(NULL);
1338 line = cpl_malloc(nlines *
sizeof(
double));
1340 for (i = 0; i < nlines; i++)
1341 line[i] = cpl_table_get(wavelengths, wcolumn, i, NULL);
1343 lines = cpl_vector_wrap(nlines, line);
1345 for (j = 0; j < pmos; j++) {
1348 cpl_msg_indent_less();
1349 cpl_msg_info(recipe,
"Processing arc lamp nb %d out of %d ...",
1351 cpl_msg_indent_more();
1353 cpl_msg_info(recipe,
"Load arc lamp exposure...");
1354 cpl_msg_indent_more();
1356 spectra =
dfs_load_image(frameset, arc_tag, CPL_TYPE_FLOAT, 0, 0);
1363 for (k = 0; k < j; k ++) {
1364 cpl_image_delete(spectra);
1368 if (spectra == NULL)
1369 fors_pmos_calib_exit(
"Cannot load arc lamp exposure");
1375 cpl_msg_info(recipe,
"Remove the master bias...");
1378 cpl_image_delete(spectra); spectra = dummy;
1380 if (spectra == NULL)
1381 fors_pmos_calib_exit(
"Cannot remove bias from arc lamp exposure");
1383 cpl_msg_indent_less();
1384 cpl_msg_info(recipe,
"Load input line catalog...");
1385 cpl_msg_indent_more();
1392 fors_pmos_calib_exit(
"Cannot process saturation");
1395 fors_pmos_calib_exit(
"Cannot subtract the background");
1402 cpl_msg_indent_less();
1403 cpl_msg_info(recipe,
"Detecting spectra on CCD...");
1404 cpl_msg_indent_more();
1406 nx = cpl_image_get_size_x(spectra);
1407 ccd_ysize = ny = cpl_image_get_size_y(spectra);
1409 refmask = cpl_mask_new(nx, ny);
1413 peakdetection, wradius,
1414 wdegree, wreject, reference,
1415 &startwavelength, &endwavelength,
1416 NULL, NULL, NULL, NULL, NULL,
1417 NULL, refmask, NULL);
1419 if (checkwave == NULL)
1420 fors_pmos_calib_exit(
"Wavelength calibration failure.");
1426 header = cpl_propertylist_new();
1427 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
1428 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
1429 cpl_propertylist_update_double(header,
"CRVAL1",
1430 startwavelength + dispersion/2);
1431 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
1434 cpl_propertylist_update_double(header,
"CD1_1", dispersion);
1435 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
1436 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
1437 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
1438 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
1439 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
1444 spectra_detection_tag,
1446 fors_pmos_calib_exit(NULL);
1451 spectra_detection_tag, header)) {
1452 fors_pmos_calib_exit(NULL);
1456 cpl_image_delete(checkwave); checkwave = NULL;
1457 cpl_propertylist_delete(header); header = NULL;
1459 if (cpl_mask_is_empty(refmask))
1460 fors_pmos_calib_exit(
"Wavelength calibration failure.");
1463 fors_pmos_calib_exit(
"The gaps could not be found");
1465 cpl_msg_info(recipe,
1466 "Locate slits at reference wavelength on CCD...");
1470 cpl_msg_error(cpl_error_get_where(),
"%s",
1471 cpl_error_get_message());
1472 fors_pmos_calib_exit(
"No slits could be detected!");
1476 if (ny != 400 && ny != 500) {
1477 float rescale = (float) rebin_dist / rebin;
1479 fors_pmos_calib_exit(
"Some slits are missing. "
1485 refimage = cpl_image_new_from_mask(refmask);
1486 cpl_mask_delete(refmask); refmask = NULL;
1493 fors_pmos_calib_exit(NULL);
1499 for (k = 0; k < j; k ++) {
1500 cpl_propertylist_delete(save_header);
1505 fors_pmos_calib_exit(NULL);
1507 cpl_propertylist_delete(save_header); save_header = NULL;
1510 cpl_image_delete(refimage); refimage = NULL;
1533 cpl_msg_indent_less();
1534 cpl_msg_info(recipe,
1535 "Attempt slit identification (optional)...");
1536 cpl_msg_indent_more();
1541 cpl_table_delete(slits);
1548 cpl_table_and_selected_double(slits,
1549 "ytop", CPL_GREATER_THAN, ny);
1550 cpl_table_or_selected_double(slits,
1551 "ybottom", CPL_LESS_THAN, 0);
1552 cpl_table_erase_selected(slits);
1554 nslits = cpl_table_get_nrow(slits);
1557 fors_pmos_calib_exit(
"No slits found on the CCD");
1559 cpl_msg_info(recipe,
1560 "%d slits are entirely contained in CCD",
1565 cpl_msg_info(recipe,
1566 "Global distortion model cannot be computed");
1567 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1568 fors_pmos_calib_exit(NULL);
1574 if (ny == 400 || ny == 500) {
1581 nslits = cpl_table_get_nrow(slits);
1584 cpl_table_unselect_all(slits);
1585 for (k = 0; k < cpl_table_get_nrow(slits); k++) {
1586 double jump = cpl_table_get(slits,
"ytop", k, NULL)
1587 - cpl_table_get(slits,
"ybottom", k, NULL);
1589 cpl_table_select_row(slits, k);
1592 cpl_table_erase_selected(slits);
1593 nslits = cpl_table_get_nrow(slits);
1597 fors_pmos_calib_exit(
"No slits found on the CCD");
1600 cpl_table_unselect_all(slits);
1601 cpl_table_select_row(slits, 0);
1602 cpl_table_select_row(slits, cpl_table_get_nrow(slits)-1);
1603 cpl_table_erase_selected(slits);
1606 cpl_msg_info(recipe,
1607 "%d slits are entirely contained in CCD", nslits);
1610 cpl_table_unselect_all(slits);
1611 for (k = 0; k < cpl_table_get_nrow(slits); k++) {
1612 double jump = cpl_table_get(slits,
"ytop", k, NULL)
1613 - cpl_table_get(slits,
"ybottom", k, NULL);
1615 cpl_table_select_row(slits, k);
1618 cpl_table_erase_selected(slits);
1619 nslits = cpl_table_get_nrow(slits);
1627 cpl_msg_indent_less();
1628 cpl_msg_info(recipe,
"Determining spectral curvature...");
1629 cpl_msg_indent_more();
1631 cpl_msg_info(recipe,
"Tracing master flat field spectra edges...");
1633 startwavelength, endwavelength, dispersion);
1636 fors_pmos_calib_exit(
"Tracing failure");
1638 cpl_image_delete(added_flat); added_flat = NULL;
1640 cpl_msg_info(recipe,
"Fitting flat field spectra edges...");
1644 fors_pmos_calib_exit(
"Trace fitting failure");
1647 cpl_msg_info(recipe,
1648 "Computing global spectral curvature model...");
1655 fors_pmos_calib_exit(NULL);
1660 fors_pmos_calib_exit(NULL);
1663 cpl_table_delete(traces); traces = NULL;
1665 coordinate = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1671 startwavelength, endwavelength,
1672 dispersion, 0, j ? NULL: coordinate);
1677 cpl_image_delete(spectra); spectra = NULL;
1686 cpl_msg_indent_less();
1687 cpl_msg_info(recipe,
"Perform flat field normalisation...");
1688 cpl_msg_indent_more();
1690 norm_flat = cpl_image_duplicate(master_flat);
1693 polytraces, reference,
1694 startwavelength, endwavelength,
1695 dispersion, dradius, ddegree);
1698 cpl_image_delete(smo_flat); smo_flat = NULL;
1702 cpl_propertylist_update_int(save_header,
"ESO PRO DATANCOM",
1706 reference, startwavelength,
1707 endwavelength, dispersion, 0,
1710 reference, startwavelength,
1711 endwavelength, dispersion, 0,
1715 if (
dfs_save_image(frameset, master_flat, master_screen_flat_tag,
1716 save_header, parlist, recipe, version))
1717 fors_pmos_calib_exit(NULL);
1721 save_header, parlist, recipe, version))
1722 fors_pmos_calib_exit(NULL);
1724 cpl_image_delete(norm_flat); norm_flat = NULL;
1725 cpl_propertylist_delete(save_header); save_header = NULL;
1735 cpl_msg_indent_less();
1736 cpl_msg_info(recipe,
"Perform final wavelength calibration...");
1737 cpl_msg_indent_more();
1739 nx = cpl_image_get_size_x(spatial);
1740 ny = cpl_image_get_size_y(spatial);
1742 idscoeff = cpl_table_new(ny);
1743 restable = cpl_table_new(nlines);
1744 rainbow = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1746 residual = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1747 fiterror = cpl_calloc(ny,
sizeof(
double));
1748 fitlines = cpl_calloc(ny,
sizeof(
int));
1751 dispersion, peakdetection,
1752 wradius, wdegree, wreject,
1755 &endwavelength, fitlines,
1758 residual, restable, NULL);
1760 if (rectified == NULL)
1761 fors_pmos_calib_exit(
"Wavelength calibration failure.");
1766 fors_pmos_calib_exit(NULL);
1772 for (k = 0; k < j; k ++) {
1773 cpl_propertylist_delete(header);
1778 fors_pmos_calib_exit(NULL);
1781 cpl_propertylist_delete(header);
1783 cpl_table_delete(restable); restable = NULL;
1785 cpl_table_wrap_double(idscoeff, fiterror,
"error"); fiterror = NULL;
1786 cpl_table_set_column_unit(idscoeff,
"error",
"pixel");
1787 cpl_table_wrap_int(idscoeff, fitlines,
"nlines"); fitlines = NULL;
1789 for (i = 0; i < ny; i++)
1790 if (!cpl_table_is_valid(idscoeff,
"c0", i))
1791 cpl_table_set_invalid(idscoeff,
"error", i);
1794 endwavelength, dispersion, 2);
1798 for (k = 0; k < j; k ++) {
1799 cpl_propertylist_delete(header);
1803 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
1804 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
1805 cpl_propertylist_update_double(header,
"CRVAL1",
1806 startwavelength + dispersion/2);
1807 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
1810 cpl_propertylist_update_double(header,
"CD1_1", dispersion);
1811 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
1812 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
1813 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
1814 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
1815 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
1820 fors_pmos_calib_exit(NULL);
1825 fors_pmos_calib_exit(NULL);
1828 cpl_image_delete(delta); delta = NULL;
1829 cpl_propertylist_delete(header); header = NULL;
1834 cpl_msg_info(recipe,
"Mean residual: %f pixel", mean_rms);
1836 mean_rms = cpl_table_get_column_mean(idscoeff,
"error");
1837 mean_rms_err = cpl_table_get_column_stdev(idscoeff,
"error");
1839 cpl_msg_info(recipe,
"Mean model accuracy: %f pixel (%f A)",
1840 mean_rms, mean_rms * dispersion);
1846 cpl_msg_info(recipe,
"Mean spectral resolution: %.2f",
1847 cpl_table_get_column_mean(restab,
"resolution"));
1848 cpl_msg_info(recipe,
1849 "Mean reference lines FWHM: %.2f +/- %.2f pixel",
1850 cpl_table_get_column_mean(restab,
"fwhm") / dispersion,
1851 cpl_table_get_column_mean(restab,
"fwhm_rms") / dispersion);
1853 cpl_table_duplicate_column(restab,
"dlambda",
1855 cpl_table_multiply_scalar(restab,
"dlambda", dispersion);
1856 cpl_table_duplicate_column(restab,
"dlambda_rms",
1857 restab,
"fwhm_rms");
1858 cpl_table_multiply_scalar(restab,
"dlambda_rms", dispersion);
1862 qclist = cpl_propertylist_new();
1872 "QC1 dictionary")) {
1873 fors_pmos_calib_exit(
"Cannot write dictionary version "
1878 keyname =
"QC.PMOS.RESOLUTION";
1881 cpl_table_get_column_mean(restab,
1885 "Mean spectral resolution")) {
1886 fors_pmos_calib_exit(
"Cannot write mean spectral "
1887 "resolution to QC log file");
1890 keyname =
"QC.PMOS.RESOLUTION.RMS";
1893 cpl_table_get_column_stdev(restab,
1897 "Scatter of spectral resolution")) {
1898 fors_pmos_calib_exit(
"Cannot write spectral resolution "
1899 "scatter to QC log file");
1902 keyname =
"QC.PMOS.RESOLUTION.NWAVE";
1904 if (fors_header_write_int(qclist, cpl_table_get_nrow(restab) -
1905 cpl_table_count_invalid(restab,
1909 "Number of examined wavelengths "
1910 "for resolution computation")) {
1911 fors_pmos_calib_exit(
"Cannot write number of lines used "
1912 "in spectral resolution computation "
1916 keyname =
"QC.PMOS.RESOLUTION.MEANRMS";
1919 cpl_table_get_column_mean(restab,
1922 "Mean error on spectral "
1923 "resolution computation")) {
1924 fors_pmos_calib_exit(
"Cannot write mean error in "
1925 "spectral resolution computation "
1929 keyname =
"QC.PMOS.RESOLUTION.NLINES";
1931 if (fors_header_write_int(qclist,
1932 cpl_table_get_column_mean(restab,
1934 cpl_table_get_nrow(restab),
1936 "Number of lines for spectral "
1937 "resolution computation")) {
1938 fors_pmos_calib_exit(
"Cannot write number of examined "
1939 "wavelengths in spectral resolution "
1940 "computation to QC log file");
1947 spectral_resolution_tag,
1949 fors_pmos_calib_exit(NULL);
1955 for (k = 0; k < j; k ++) {
1956 cpl_propertylist_delete(header);
1960 cpl_propertylist_append(header, qclist);
1963 fors_pmos_calib_exit(NULL);
1966 cpl_table_delete(restab); restab = NULL;
1967 cpl_propertylist_delete(qclist); qclist = NULL;
1968 cpl_propertylist_delete(header); header = NULL;
1972 fors_pmos_calib_exit(
"Cannot compute the spectral "
1973 "resolution table");
1978 fors_pmos_calib_exit(NULL);
1984 for (k = 0; k < j; k ++) {
1985 cpl_propertylist_delete(header);
1990 fors_pmos_calib_exit(NULL);
1993 cpl_propertylist_delete(header);
1999 dispersion, idscoeff, 0);
2004 dispersion, idscoeff, 0);
2006 cpl_image_delete(rect_flat); rect_flat = NULL;
2007 cpl_image_delete(rect_nflat); rect_nflat = NULL;
2012 cpl_table_delete(idscoeff); idscoeff = NULL;
2016 for (k = 0; k < j; k ++) {
2017 cpl_propertylist_delete(header);
2021 cpl_propertylist_update_double(header,
"CRPIX1", 1.0);
2022 cpl_propertylist_update_double(header,
"CRPIX2", 1.0);
2023 cpl_propertylist_update_double(header,
"CRVAL1",
2024 startwavelength + dispersion/2);
2025 cpl_propertylist_update_double(header,
"CRVAL2", 1.0);
2028 cpl_propertylist_update_double(header,
"CD1_1", dispersion);
2029 cpl_propertylist_update_double(header,
"CD1_2", 0.0);
2030 cpl_propertylist_update_double(header,
"CD2_1", 0.0);
2031 cpl_propertylist_update_double(header,
"CD2_2", 1.0);
2032 cpl_propertylist_update_string(header,
"CTYPE1",
"LINEAR");
2033 cpl_propertylist_update_string(header,
"CTYPE2",
"PIXEL");
2034 cpl_propertylist_update_int(header,
"ESO PRO DATANCOM", 1);
2039 fors_pmos_calib_exit(NULL);
2044 fors_pmos_calib_exit(NULL);
2047 cpl_image_delete(rectified); rectified = NULL;
2049 cpl_propertylist_update_int(header,
"ESO PRO DATANCOM", nflats);
2052 if (
dfs_save_image(frameset, mapped_flat, mapped_screen_flat_tag,
2053 header, parlist, recipe, version))
2054 fors_pmos_calib_exit(NULL);
2055 cpl_image_delete(mapped_flat); mapped_flat = NULL;
2058 header, parlist, recipe, version))
2059 fors_pmos_calib_exit(NULL);
2060 cpl_image_delete(mapped_nflat); mapped_nflat = NULL;
2063 cpl_propertylist_delete(header); header = NULL;
2067 for (k = 0; k < j; k ++) {
2068 cpl_propertylist_delete(save_header);
2072 cpl_propertylist_update_double(save_header,
"CRPIX2", 1.0);
2073 cpl_propertylist_update_double(save_header,
"CRVAL2", 1.0);
2075 cpl_propertylist_update_double(save_header,
"CD1_1", 1.0);
2076 cpl_propertylist_update_double(save_header,
"CD1_2", 0.0);
2077 cpl_propertylist_update_double(save_header,
"CD2_1", 0.0);
2078 cpl_propertylist_update_double(save_header,
"CD2_2", 1.0);
2079 cpl_propertylist_update_string(save_header,
"CTYPE1",
"LINEAR");
2080 cpl_propertylist_update_string(save_header,
"CTYPE2",
"PIXEL");
2085 fors_pmos_calib_exit(NULL);
2090 fors_pmos_calib_exit(NULL);
2093 cpl_image_delete(residual); residual = NULL;
2094 cpl_propertylist_delete(save_header); save_header = NULL;
2098 reference, startwavelength, endwavelength,
2101 cpl_image_delete(rainbow); rainbow = NULL;
2105 for (k = 0; k < j; k ++) {
2106 cpl_propertylist_delete(save_header);
2118 "QC1 dictionary")) {
2119 fors_pmos_calib_exit(
"Cannot write dictionary version "
2127 "Mean accuracy of wavecalib model")) {
2128 fors_pmos_calib_exit(
"Cannot write mean wavelength calibration "
2129 "accuracy to QC log file");
2135 "QC.WAVE.ACCURACY.ERROR",
2137 "Error on accuracy of wavecalib model")) {
2138 fors_pmos_calib_exit(
"Cannot write error on wavelength "
2139 "calibration accuracy to QC log file");
2142 if (same_offset && fabs(mxpos) < 0.05) {
2145 data = cpl_image_get_data(wavemap);
2148 data[nx/2 + ccd_ysize*nx/2],
2149 "QC.PMOS.CENTRAL.WAVELENGTH",
2151 "Wavelength at CCD center")) {
2152 fors_pmos_calib_exit(
"Cannot write central wavelength "
2162 fors_pmos_calib_exit(NULL);
2167 fors_pmos_calib_exit(NULL);
2170 cpl_image_delete(wavemap); wavemap = NULL;
2172 cpl_propertylist_erase_regexp(save_header,
"^ESO QC ", 0);
2174 cpl_propertylist_delete(save_header); save_header = NULL;
2176 cpl_msg_indent_less();
2180 if (
dfs_save_image(frameset, coordinate, spatial_map_tag, save_header,
2181 parlist, recipe, version))
2182 fors_pmos_calib_exit(NULL);
2184 cpl_image_delete(coordinate); coordinate = NULL;
2185 cpl_propertylist_delete(save_header); save_header = NULL;
2191 double maxpos, maxneg, maxcurve, maxslope;
2201 "QC1 dictionary")) {
2202 fors_pmos_calib_exit(
"Cannot write dictionary version "
2206 maxpos = fabs(cpl_table_get_column_max(polytraces,
"c2"));
2207 maxneg = fabs(cpl_table_get_column_min(polytraces,
"c2"));
2208 maxcurve = maxpos > maxneg ? maxpos : maxneg;
2211 "QC.TRACE.MAX.CURVATURE",
2212 "Y pixel / X pixel ^2",
2213 "Max observed curvature "
2214 "in spectral tracing")) {
2215 fors_pmos_calib_exit(
"Cannot write max observed curvature in "
2216 "spectral tracing to QC log file");
2219 maxpos = fabs(cpl_table_get_column_max(polytraces,
"c1"));
2220 maxneg = fabs(cpl_table_get_column_min(polytraces,
"c1"));
2221 maxslope = maxpos > maxneg ? maxpos : maxneg;
2225 "QC.TRACE.MAX.SLOPE",
2226 "Y pixel / X pixel",
2227 "Max observed slope in spectral tracing")) {
2228 fors_pmos_calib_exit(
"Cannot write max observed slope in spectral "
2229 "tracing to QC log file");
2234 parlist, recipe, version)) {
2235 fors_pmos_calib_exit(NULL);
2238 cpl_propertylist_delete(header); header = NULL;
2239 cpl_table_delete(polytraces); polytraces = NULL;
2245 cpl_table *globaltbl;
2250 double *ytop = cpl_table_get_data_double(slits,
"ytop");
2251 double *ybot = cpl_table_get_data_double(slits,
"ybottom");
2256 nslits = cpl_table_get_nrow(slits);
2258 cpl_table_new_column(slits,
"pair_id", CPL_TYPE_INT);
2261 if (ccd_ysize == 400 || ccd_ysize == 500) {
2267 l_ytop = cpl_malloc(
sizeof(
double));
2269 l_id = cpl_malloc(
sizeof(
double));
2276 l_ytop = cpl_table_get_data_double(slitpos,
"ytop");
2277 l_id = cpl_table_get_data_int(slitpos,
"slit_id");
2278 npairs = cpl_table_get_nrow(slitpos);
2279 if (rebin_dist != rebin) {
2280 float rescale = (float)rebin_dist / rebin;
2281 for (i = 0; i < npairs; i++) {
2282 l_ytop[i] *= rescale;
2287 for (k = 0; k < npairs; k++) {
2290 for (h = 0; h < nslits; h++) {
2292 if (l_ytop[k] < ytop[h] && l_ytop[k] > ybot[h]) {
2293 if (h + 1 < nslits) {
2294 cpl_table_set_int(slits,
"pair_id", h, l_id[k]);
2295 cpl_table_set_int(slits,
"pair_id", h + 1, l_id[k]);
2303 cpl_table_fill_invalid_int(slits,
"pair_id", -1);
2305 if (ccd_ysize == 400 || ccd_ysize == 500) {
2310 cpl_table_delete(slitpos); slitpos = NULL;
2311 cpl_table_delete(globaltbl); globaltbl = NULL;
2313 cpl_table_delete(maskslits); maskslits = NULL;
2318 parlist, recipe, version)) {
2319 fors_pmos_calib_exit(NULL);
2322 cpl_table_delete(slits); slits = NULL;
2324 cpl_image_delete(spatial); spatial = NULL;
2326 cpl_free(instrume); instrume = NULL;
2328 cpl_table_delete(overscans); overscans = NULL;
2329 cpl_image_delete(master_bias); master_bias = NULL;
2330 cpl_image_delete(master_flat); master_flat = NULL;
2332 cpl_table_delete(wavelengths); wavelengths = NULL;
2333 cpl_vector_delete(lines); lines = NULL;
2335 if (cpl_error_get_code()) {
2336 cpl_msg_error(cpl_error_get_where(),
"%s", cpl_error_get_message());
2337 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.