FORS Pipeline Reference Manual  4.12.5
recipes/fors_extract.c
1 /* $Id: fors_extract.c,v 1.12 2013-10-09 15:59:38 cgarcia Exp $
2  *
3  * This file is part of the FORS Data Reduction Pipeline
4  * Copyright (C) 2002-2010 European Southern Observatory
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /*
22  * $Author: cgarcia $
23  * $Date: 2013-10-09 15:59:38 $
24  * $Revision: 1.12 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 #include <string.h>
33 #include <math.h>
34 #include <cpl.h>
35 #include <moses.h>
36 #include <fors_dfs.h>
37 
38 static int fors_extract_create(cpl_plugin *);
39 static int fors_extract_exec(cpl_plugin *);
40 static int fors_extract_destroy(cpl_plugin *);
41 static int fors_extract(cpl_parameterlist *, cpl_frameset *);
42 
43 static char fors_extract_description[] =
44 "This recipe is used to reduce scientific spectra using the global\n"
45 "distortion table created by the recipe fors_calib. The spectra are\n"
46 "bias subtracted, flat fielded (if a normalised flat field is specified)\n"
47 "and remapped eliminating the optical distortions. The wavelength calibration\n"
48 "can be optionally upgraded using a number of sky lines: if no sky lines\n"
49 "catalog of wavelengths is specified, an internal one is used instead.\n"
50 "If the alignment to the sky lines is performed, the applied dispersion\n"
51 "coefficient table is upgraded and saved to disk, and a new CCD wavelengths\n"
52 "map is created.\n"
53 "This recipe accepts both FORS1 and FORS2 frames. A grism table (typically\n"
54 "depending on the instrument mode, and in particular on the grism used)\n"
55 "may also be specified: this table contains a default recipe parameter\n"
56 "setting to control the way spectra are extracted for a specific instrument\n"
57 "mode, as it is used for automatic run of the pipeline on Paranal and in\n"
58 "Garching. If this table is specified, it will modify the default recipe\n"
59 "parameter setting, with the exception of those parameters which have been\n"
60 "explicitly modifyed on the command line. If a grism table is not specified,\n"
61 "the input recipe parameters values will always be read from the command\n"
62 "line, or from an esorex configuration file if present, or from their\n"
63 "generic default values (that are rarely meaningful).\n"
64 "In the table below the MXU acronym can be read alternatively as MOS\n"
65 "and LSS, depending on the instrument mode of the input data. Either a\n"
66 "scientific or a standard star exposure can be specified in input (not\n"
67 "both).\n\n"
68 "Input files:\n\n"
69 " DO category: Type: Explanation: Required:\n"
70 " SCIENCE_MXU Raw Scientific exposure Y\n"
71 " or STANDARD_MXU Raw Standard star exposure Y\n"
72 " MASTER_BIAS Calib Master bias Y\n"
73 " GRISM_TABLE Calib Grism table .\n"
74 " MASTER_SKYLINECAT Calib Sky lines catalog .\n"
75 "\n"
76 " MASTER_NORM_FLAT_MXU Calib Normalised flat field .\n"
77 " MASTER_DISTORTION_TABLE Calib Global distortion model .\n"
78 "\n"
79 " or, in case of LSS-like MOS/MXU data,\n"
80 "\n"
81 " MASTER_NORM_FLAT_LONG_MXU Calib Normalised flat field .\n"
82 "Output files:\n\n"
83 " DO category: Data type: Explanation:\n"
84 " REDUCED_SCI_MXU FITS image Extracted scientific spectra\n"
85 " REDUCED_SKY_SCI_MXU FITS image Extracted sky spectra\n"
86 " REDUCED_ERROR_SCI_MXU FITS image Errors on extracted spectra\n"
87 " UNMAPPED_SCI_MXU FITS image Sky subtracted scientific spectra\n"
88 " MAPPED_SCI_MXU FITS image Rectified scientific spectra\n"
89 " MAPPED_ALL_SCI_MXU FITS image Rectified science spectra with sky\n"
90 " MAPPED_SKY_SCI_MXU FITS image Rectified sky spectra\n"
91 " UNMAPPED_SKY_SCI_MXU FITS image Sky on CCD\n"
92 " GLOBAL_SKY_SPECTRUM_MXU FITS table Global sky spectrum\n"
93 " OBJECT_TABLE_SCI_MXU FITS table Positions of detected objects\n"
94 "\n"
95 " Only if the sky-alignment of the wavelength solution is requested:\n"
96 " SKY_SHIFTS_LONG_SCI_MXU FITS table Sky lines offsets (LSS-like data)\n"
97 " or SKY_SHIFTS_SLIT_SCI_MXU FITS table Sky lines offsets (MOS-like data)\n"
98 " DISP_COEFF_SCI_MXU FITS table Upgraded dispersion coefficients\n"
99 " WAVELENGTH_MAP_SCI_MXU FITS image Upgraded wavelength map\n\n";
100 
101 #define fors_extract_exit(message) \
102 { \
103 if (message) cpl_msg_error(recipe, message); \
104 cpl_free(exptime); \
105 cpl_free(instrume); \
106 cpl_image_delete(dummy); \
107 cpl_image_delete(mapped); \
108 cpl_image_delete(mapped_sky); \
109 cpl_image_delete(mapped_cleaned); \
110 cpl_image_delete(skylocalmap); \
111 cpl_image_delete(skymap); \
112 cpl_image_delete(smapped); \
113 cpl_table_delete(offsets); \
114 cpl_table_delete(global); \
115 cpl_table_delete(sky); \
116 cpl_image_delete(bias); \
117 cpl_image_delete(spectra); \
118 cpl_image_delete(coordinate); \
119 cpl_image_delete(norm_flat); \
120 cpl_image_delete(rainbow); \
121 cpl_image_delete(rectified); \
122 cpl_image_delete(wavemap); \
123 cpl_propertylist_delete(header); \
124 cpl_propertylist_delete(save_header); \
125 cpl_table_delete(grism_table); \
126 cpl_table_delete(idscoeff); \
127 cpl_table_delete(maskslits); \
128 cpl_table_delete(overscans); \
129 cpl_table_delete(polytraces); \
130 cpl_table_delete(slits); \
131 cpl_table_delete(wavelengths); \
132 cpl_vector_delete(lines); \
133 cpl_msg_indent_less(); \
134 return -1; \
135 }
136 
137 
138 #define fors_extract_exit_memcheck(message) \
139 { \
140 if (message) cpl_msg_info(recipe, message); \
141 printf("free exptime (%p)\n", exptime); \
142 cpl_free(exptime); \
143 printf("free instrume (%p)\n", instrume); \
144 cpl_free(instrume); \
145 printf("free dummy (%p)\n", dummy); \
146 cpl_image_delete(dummy); \
147 printf("free mapped (%p)\n", mapped); \
148 cpl_image_delete(mapped); \
149 printf("free mapped_cleaned (%p)\n", mapped_cleaned); \
150 cpl_image_delete(mapped_cleaned); \
151 printf("free mapped_sky (%p)\n", mapped_sky); \
152 cpl_image_delete(mapped_sky); \
153 printf("free skylocalmap (%p)\n", skylocalmap); \
154 cpl_image_delete(skylocalmap); \
155 printf("free skymap (%p)\n", skymap); \
156 cpl_image_delete(skymap); \
157 printf("free smapped (%p)\n", smapped); \
158 cpl_image_delete(smapped); \
159 printf("free offsets (%p)\n", offsets); \
160 cpl_table_delete(offsets); \
161 printf("free global (%p)\n", global); \
162 cpl_table_delete(global); \
163 printf("free sky (%p)\n", sky); \
164 cpl_table_delete(sky); \
165 printf("free bias (%p)\n", bias); \
166 cpl_image_delete(bias); \
167 printf("free spectra (%p)\n", spectra); \
168 cpl_image_delete(spectra); \
169 printf("free coordinate (%p)\n", coordinate); \
170 cpl_image_delete(coordinate); \
171 printf("free norm_flat (%p)\n", norm_flat); \
172 cpl_image_delete(norm_flat); \
173 printf("free rainbow (%p)\n", rainbow); \
174 cpl_image_delete(rainbow); \
175 printf("free rectified (%p)\n", rectified); \
176 cpl_image_delete(rectified); \
177 printf("free wavemap (%p)\n", wavemap); \
178 cpl_image_delete(wavemap); \
179 printf("free header (%p)\n", header); \
180 cpl_propertylist_delete(header); \
181 printf("free save_header (%p)\n", save_header); \
182 cpl_propertylist_delete(save_header); \
183 printf("free grism_table (%p)\n", grism_table); \
184 cpl_table_delete(grism_table); \
185 printf("free idscoeff (%p)\n", idscoeff); \
186 cpl_table_delete(idscoeff); \
187 printf("free maskslits (%p)\n", maskslits); \
188 cpl_table_delete(maskslits); \
189 printf("free overscans (%p)\n", overscans); \
190 cpl_table_delete(overscans); \
191 printf("free polytraces (%p)\n", polytraces); \
192 cpl_table_delete(polytraces); \
193 printf("free slits (%p)\n", slits); \
194 cpl_table_delete(slits); \
195 printf("free wavelengths (%p)\n", wavelengths); \
196 cpl_table_delete(wavelengths); \
197 printf("free lines (%p)\n", lines); \
198 cpl_vector_delete(lines); \
199 cpl_msg_indent_less(); \
200 return 0; \
201 }
202 
203 
215 int cpl_plugin_get_info(cpl_pluginlist *list)
216 {
217  cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe );
218  cpl_plugin *plugin = &recipe->interface;
219 
220  cpl_plugin_init(plugin,
221  CPL_PLUGIN_API,
222  FORS_BINARY_VERSION,
223  CPL_PLUGIN_TYPE_RECIPE,
224  "fors_extract",
225  "Extraction of scientific spectra",
226  fors_extract_description,
227  "Carlo Izzo",
228  PACKAGE_BUGREPORT,
229  "This file is currently part of the FORS Instrument Pipeline\n"
230  "Copyright (C) 2002-2010 European Southern Observatory\n\n"
231  "This program is free software; you can redistribute it and/or modify\n"
232  "it under the terms of the GNU General Public License as published by\n"
233  "the Free Software Foundation; either version 2 of the License, or\n"
234  "(at your option) any later version.\n\n"
235  "This program is distributed in the hope that it will be useful,\n"
236  "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
237  "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
238  "GNU General Public License for more details.\n\n"
239  "You should have received a copy of the GNU General Public License\n"
240  "along with this program; if not, write to the Free Software Foundation,\n"
241  "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n",
242  fors_extract_create,
243  fors_extract_exec,
244  fors_extract_destroy);
245 
246  cpl_pluginlist_append(list, plugin);
247 
248  return 0;
249 }
250 
251 
262 static int fors_extract_create(cpl_plugin *plugin)
263 {
264  cpl_recipe *recipe;
265  cpl_parameter *p;
266 
267 
268  /*
269  * Check that the plugin is part of a valid recipe
270  */
271 
272  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
273  recipe = (cpl_recipe *)plugin;
274  else
275  return -1;
276 
277  /*
278  * Create the parameters list in the cpl_recipe object
279  */
280 
281  recipe->parameters = cpl_parameterlist_new();
282 
283 
284  /*
285  * Dispersion
286  */
287 
288  p = cpl_parameter_new_value("fors.fors_extract.dispersion",
289  CPL_TYPE_DOUBLE,
290  "Resampling step (Angstrom/pixel)",
291  "fors.fors_extract",
292  0.0);
293  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dispersion");
294  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
295  cpl_parameterlist_append(recipe->parameters, p);
296 
297  /*
298  * Sky lines alignment
299  */
300 
301  p = cpl_parameter_new_value("fors.fors_extract.skyalign",
302  CPL_TYPE_INT,
303  "Polynomial order for sky lines alignment, "
304  "or -1 to avoid alignment",
305  "fors.fors_extract",
306  0);
307  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skyalign");
308  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
309  cpl_parameterlist_append(recipe->parameters, p);
310 
311  /*
312  * Line catalog table column containing the sky reference wavelengths
313  */
314 
315  p = cpl_parameter_new_value("fors.fors_extract.wcolumn",
316  CPL_TYPE_STRING,
317  "Name of sky line catalog table column "
318  "with wavelengths",
319  "fors.fors_extract",
320  "WLEN");
321  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "wcolumn");
322  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
323  cpl_parameterlist_append(recipe->parameters, p);
324 
325  /*
326  * Start wavelength for spectral extraction
327  */
328 
329  p = cpl_parameter_new_value("fors.fors_extract.startwavelength",
330  CPL_TYPE_DOUBLE,
331  "Start wavelength in spectral extraction",
332  "fors.fors_extract",
333  0.0);
334  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "startwavelength");
335  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
336  cpl_parameterlist_append(recipe->parameters, p);
337 
338  /*
339  * End wavelength for spectral extraction
340  */
341 
342  p = cpl_parameter_new_value("fors.fors_extract.endwavelength",
343  CPL_TYPE_DOUBLE,
344  "End wavelength in spectral extraction",
345  "fors.fors_extract",
346  0.0);
347  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "endwavelength");
348  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
349  cpl_parameterlist_append(recipe->parameters, p);
350 
351  /*
352  * Flux conservation
353  */
354 
355  p = cpl_parameter_new_value("fors.fors_extract.flux",
356  CPL_TYPE_BOOL,
357  "Apply flux conservation",
358  "fors.fors_extract",
359  TRUE);
360  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux");
361  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
362  cpl_parameterlist_append(recipe->parameters, p);
363 
364  /*
365  * Apply flat field
366  */
367 
368  p = cpl_parameter_new_value("fors.fors_extract.flatfield",
369  CPL_TYPE_BOOL,
370  "Apply flat field",
371  "fors.fors_extract",
372  FALSE);
373  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flatfield");
374  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
375  cpl_parameterlist_append(recipe->parameters, p);
376 
377  /*
378  * Global sky subtraction
379  */
380 
381  p = cpl_parameter_new_value("fors.fors_extract.skyglobal",
382  CPL_TYPE_BOOL,
383  "Subtract global sky spectrum from CCD",
384  "fors.fors_extract",
385  FALSE);
386  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skyglobal");
387  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
388  cpl_parameterlist_append(recipe->parameters, p);
389 
390  /*
391  * Local sky subtraction on extracted spectra
392  */
393 
394 /*** New sky subtraction (search NSS)
395  p = cpl_parameter_new_value("fors.fors_extract.skymedian",
396  CPL_TYPE_INT,
397  "Degree of sky fitting polynomial for "
398  "sky subtraction from extracted "
399  "slit spectra (MOS/MXU only, -1 to disable it)",
400  "fors.fors_extract",
401  0);
402  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skymedian");
403  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
404  cpl_parameterlist_append(recipe->parameters, p);
405 ***/
406 
407  p = cpl_parameter_new_value("fors.fors_extract.skymedian",
408  CPL_TYPE_BOOL,
409  "Sky subtraction from extracted slit spectra",
410  "fors.fors_extract",
411  FALSE);
412  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skymedian");
413  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
414  cpl_parameterlist_append(recipe->parameters, p);
415 
416  /*
417  * Local sky subtraction on CCD spectra
418  */
419 
420  p = cpl_parameter_new_value("fors.fors_extract.skylocal",
421  CPL_TYPE_BOOL,
422  "Sky subtraction from CCD slit spectra",
423  "fors.fors_extract",
424  TRUE);
425  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skylocal");
426  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
427  cpl_parameterlist_append(recipe->parameters, p);
428 
429  /*
430  * Cosmic rays removal
431  */
432 
433  p = cpl_parameter_new_value("fors.fors_extract.cosmics",
434  CPL_TYPE_BOOL,
435  "Eliminate cosmic rays hits (only if global "
436  "sky subtraction is also requested)",
437  "fors.fors_extract",
438  FALSE);
439  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "cosmics");
440  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
441  cpl_parameterlist_append(recipe->parameters, p);
442 
443  /*
444  * Slit margin
445  */
446 
447  p = cpl_parameter_new_value("fors.fors_extract.slit_margin",
448  CPL_TYPE_INT,
449  "Number of pixels to exclude at each slit "
450  "in object detection and extraction",
451  "fors.fors_extract",
452  3);
453  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "slit_margin");
454  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
455  cpl_parameterlist_append(recipe->parameters, p);
456 
457  /*
458  * Extraction radius
459  */
460 
461  p = cpl_parameter_new_value("fors.fors_extract.ext_radius",
462  CPL_TYPE_INT,
463  "Maximum extraction radius for detected "
464  "objects (pixel)",
465  "fors.fors_extract",
466  6);
467  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ext_radius");
468  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
469  cpl_parameterlist_append(recipe->parameters, p);
470 
471  /*
472  * Contamination radius
473  */
474 
475  p = cpl_parameter_new_value("fors.fors_extract.cont_radius",
476  CPL_TYPE_INT,
477  "Minimum distance at which two objects "
478  "of equal luminosity do not contaminate "
479  "each other (pixel)",
480  "fors.fors_extract",
481  0);
482  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "cont_radius");
483  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
484  cpl_parameterlist_append(recipe->parameters, p);
485 
486  /*
487  * Object extraction method
488  */
489 
490  p = cpl_parameter_new_value("fors.fors_extract.ext_mode",
491  CPL_TYPE_INT,
492  "Object extraction method: 0 = aperture, "
493  "1 = Horne optimal extraction",
494  "fors.fors_extract",
495  1);
496  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ext_mode");
497  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
498  cpl_parameterlist_append(recipe->parameters, p);
499 
500  /*
501  * Normalise output by exposure time
502  */
503 
504  p = cpl_parameter_new_value("fors.fors_extract.time_normalise",
505  CPL_TYPE_BOOL,
506  "Normalise output spectra by the exposure time",
507  "fors.fors_extract",
508  TRUE);
509  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "time_normalise");
510  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
511  cpl_parameterlist_append(recipe->parameters, p);
512 
513  return 0;
514 }
515 
516 
525 static int fors_extract_exec(cpl_plugin *plugin)
526 {
527  cpl_recipe *recipe;
528 
529  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
530  recipe = (cpl_recipe *)plugin;
531  else
532  return -1;
533 
534  return fors_extract(recipe->parameters, recipe->frames);
535 }
536 
537 
546 static int fors_extract_destroy(cpl_plugin *plugin)
547 {
548  cpl_recipe *recipe;
549 
550  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
551  recipe = (cpl_recipe *)plugin;
552  else
553  return -1;
554 
555  cpl_parameterlist_delete(recipe->parameters);
556 
557  return 0;
558 }
559 
560 
570 static int fors_extract(cpl_parameterlist *parlist, cpl_frameset *frameset)
571 {
572 
573  const char *recipe = "fors_extract";
574 
575 
576  /*
577  * Input parameters
578  */
579 
580  double dispersion;
581  int skyalign;
582  const char *wcolumn;
583  double startwavelength;
584  double endwavelength;
585  int flux;
586  int flatfield;
587  int skyglobal;
588  int skylocal;
589  int skymedian;
590  int cosmics;
591  int slit_margin;
592  int ext_radius;
593  int cont_radius;
594  int ext_mode;
595  int time_normalise;
596 
597 
598  /*
599  * CPL objects
600  */
601 
602  cpl_imagelist *all_science;
603  cpl_image **images;
604 
605  cpl_image *bias = NULL;
606  cpl_image *norm_flat = NULL;
607  cpl_image *spectra = NULL;
608  cpl_image *rectified = NULL;
609  cpl_image *coordinate = NULL;
610  cpl_image *rainbow = NULL;
611  cpl_image *mapped = NULL;
612  cpl_image *mapped_sky = NULL;
613  cpl_image *mapped_cleaned = NULL;
614  cpl_image *smapped = NULL;
615  cpl_image *wavemap = NULL;
616  cpl_image *skymap = NULL;
617  cpl_image *skylocalmap = NULL;
618  cpl_image *dummy = NULL;
619 
620  cpl_table *grism_table = NULL;
621  cpl_table *overscans = NULL;
622  cpl_table *wavelengths = NULL;
623  cpl_table *idscoeff = NULL;
624  cpl_table *slits = NULL;
625  cpl_table *maskslits = NULL;
626  cpl_table *polytraces = NULL;
627  cpl_table *offsets = NULL;
628  cpl_table *sky = NULL;
629  cpl_table *global = NULL;
630 
631  cpl_vector *lines = NULL;
632 
633  cpl_propertylist *header = NULL;
634  cpl_propertylist *save_header = NULL;
635 
636  /*
637  * Auxiliary variables
638  */
639 
640  char version[80];
641  char *instrume = NULL;
642  char *wheel4 = NULL;
643  const char *science_tag;
644  const char *master_norm_flat_tag;
645  const char *disp_coeff_sky_tag;
646  const char *wavelength_map_sky_tag;
647  const char *reduced_science_tag;
648  const char *reduced_sky_tag;
649  const char *reduced_error_tag;
650  const char *mapped_science_tag;
651  const char *unmapped_science_tag;
652  const char *mapped_science_sky_tag;
653  const char *mapped_sky_tag;
654  const char *unmapped_sky_tag;
655  const char *global_sky_spectrum_tag;
656  const char *object_table_tag;
657  const char *skylines_offsets_tag;
658  const char *global_distortion_tag = "MASTER_DISTORTION_TABLE";
659  char *coll;
660  int mxu, mos, lss;
661  int nscience;
662  double *exptime = NULL;
663  double alltime;
664  double mean_rms;
665  int nlines;
666  int rebin;
667  double *line;
668  int nx, ny;
669  double reference;
670  double gain;
671  double ron;
672  int standard;
673  int highres;
674  int narrow = 0;
675  int i;
676 
677 
678  snprintf(version, 80, "%s-%s", PACKAGE, PACKAGE_VERSION);
679 
680  cpl_msg_set_indentation(2);
681 
682  /*
683  * Get configuration parameters
684  */
685 
686  cpl_msg_info(recipe, "Recipe %s configuration parameters:", recipe);
687  cpl_msg_indent_more();
688 
689  if (cpl_frameset_count_tags(frameset, "GRISM_TABLE") > 1)
690  fors_extract_exit("Too many in input: GRISM_TABLE");
691 
692  grism_table = dfs_load_table(frameset, "GRISM_TABLE", 1);
693 
694  dispersion = dfs_get_parameter_double(parlist,
695  "fors.fors_extract.dispersion", grism_table);
696 
697  if (dispersion <= 0.0)
698  fors_extract_exit("Invalid resampling step");
699 
700  skyalign = dfs_get_parameter_int(parlist,
701  "fors.fors_extract.skyalign", NULL);
702 
703  if (skyalign > 2)
704  fors_extract_exit("Max polynomial degree for sky alignment is 2");
705 
706  wcolumn = dfs_get_parameter_string(parlist,
707  "fors.fors_extract.wcolumn", NULL);
708 
709  startwavelength = dfs_get_parameter_double(parlist,
710  "fors.fors_extract.startwavelength", grism_table);
711  if (startwavelength < 3000.0 || startwavelength > 13000.0)
712  fors_extract_exit("Invalid wavelength");
713 
714  endwavelength = dfs_get_parameter_double(parlist,
715  "fors.fors_extract.endwavelength", grism_table);
716  if (endwavelength < 3000.0 || endwavelength > 13000.0)
717  fors_extract_exit("Invalid wavelength");
718 
719  if (endwavelength - startwavelength <= 0.0)
720  fors_extract_exit("Invalid wavelength interval");
721 
722  flux = dfs_get_parameter_bool(parlist, "fors.fors_extract.flux", NULL);
723 
724  flatfield = dfs_get_parameter_bool(parlist, "fors.fors_extract.flatfield",
725  NULL);
726 
727  skyglobal = dfs_get_parameter_bool(parlist, "fors.fors_extract.skyglobal",
728  NULL);
729  skylocal = dfs_get_parameter_bool(parlist, "fors.fors_extract.skylocal",
730  NULL);
731  skymedian = dfs_get_parameter_bool(parlist, "fors.fors_extract.skymedian",
732  NULL);
733 /* NSS
734  skymedian = dfs_get_parameter_int(parlist, "fors.fors_extract.skymedian",
735  NULL);
736 */
737 
738  if (skylocal && skyglobal)
739  fors_extract_exit("Cannot apply both local and global sky subtraction");
740 
741  if (skylocal && skymedian)
742  fors_extract_exit("Cannot apply sky subtraction both on extracted "
743  "and non-extracted spectra");
744 
745  cosmics = dfs_get_parameter_bool(parlist,
746  "fors.fors_extract.cosmics", NULL);
747 
748  if (cosmics)
749  if (!(skyglobal || skylocal))
750  fors_extract_exit("Cosmic rays correction requires "
751  "either skylocal=true or skyglobal=true");
752 
753  slit_margin = dfs_get_parameter_int(parlist,
754  "fors.fors_extract.slit_margin",
755  NULL);
756  if (slit_margin < 0)
757  fors_extract_exit("Value must be zero or positive");
758 
759  ext_radius = dfs_get_parameter_int(parlist,
760  "fors.fors_extract.ext_radius",
761  NULL);
762  if (ext_radius < 0)
763  fors_extract_exit("Value must be zero or positive");
764 
765  cont_radius = dfs_get_parameter_int(parlist,
766  "fors.fors_extract.cont_radius",
767  NULL);
768  if (cont_radius < 0)
769  fors_extract_exit("Value must be zero or positive");
770 
771  ext_mode = dfs_get_parameter_int(parlist, "fors.fors_extract.ext_mode",
772  NULL);
773  if (ext_mode < 0 || ext_mode > 1)
774  fors_extract_exit("Invalid object extraction mode");
775 
776  time_normalise = dfs_get_parameter_bool(parlist,
777  "fors.fors_extract.time_normalise", NULL);
778 
779  cpl_table_delete(grism_table); grism_table = NULL;
780 
781  if (cpl_error_get_code())
782  fors_extract_exit("Failure getting the configuration parameters");
783 
784 
785  /*
786  * Check input set-of-frames
787  */
788 
789  cpl_msg_indent_less();
790  cpl_msg_info(recipe, "Check input set-of-frames:");
791  cpl_msg_indent_more();
792 
793  if (!dfs_equal_keyword(frameset, "ESO INS GRIS1 ID"))
794  fors_extract_exit("Input frames are not from the same grism");
795 
796  if (!dfs_equal_keyword(frameset, "ESO INS FILT1 ID"))
797  fors_extract_exit("Input frames are not from the same filter");
798 
799  if (!dfs_equal_keyword(frameset, "ESO DET CHIP1 ID"))
800  fors_extract_exit("Input frames are not from the same chip");
801 
802  mxu = cpl_frameset_count_tags(frameset, "SCIENCE_MXU");
803  mos = cpl_frameset_count_tags(frameset, "SCIENCE_MOS");
804  lss = cpl_frameset_count_tags(frameset, "SCIENCE_LSS");
805  standard = 0;
806 
807  if (mxu + mos + lss == 0) {
808  mxu = cpl_frameset_count_tags(frameset, "STANDARD_MXU");
809  mos = cpl_frameset_count_tags(frameset, "STANDARD_MOS");
810  lss = cpl_frameset_count_tags(frameset, "STANDARD_LSS");
811  standard = 1;
812  }
813 
814  if (mxu + mos + lss == 0)
815  fors_extract_exit("Missing input scientific frame");
816 
817  nscience = mxu + mos + lss;
818 
819  if (mxu && mxu < nscience)
820  fors_extract_exit("Input scientific frames must be of the same type");
821 
822  if (mos && mos < nscience)
823  fors_extract_exit("Input scientific frames must be of the same type");
824 
825  if (lss && lss < nscience)
826  fors_extract_exit("Input scientific frames must be of the same type");
827 
828  if (mxu) {
829  if (standard) {
830  cpl_msg_info(recipe, "MXU data found");
831  science_tag = "STANDARD_MXU";
832  reduced_science_tag = "REDUCED_STD_MXU";
833  unmapped_science_tag = "UNMAPPED_STD_MXU";
834  mapped_science_tag = "MAPPED_STD_MXU";
835  mapped_science_sky_tag = "MAPPED_ALL_STD_MXU";
836  skylines_offsets_tag = "SKY_SHIFTS_SLIT_STD_MXU";
837  wavelength_map_sky_tag = "WAVELENGTH_MAP_STD_MXU";
838  disp_coeff_sky_tag = "DISP_COEFF_STD_MXU";
839  mapped_sky_tag = "MAPPED_SKY_STD_MXU";
840  unmapped_sky_tag = "UNMAPPED_SKY_STD_MXU";
841  object_table_tag = "OBJECT_TABLE_STD_MXU";
842  reduced_sky_tag = "REDUCED_SKY_STD_MXU";
843  reduced_error_tag = "REDUCED_ERROR_STD_MXU";
844  }
845  else {
846  cpl_msg_info(recipe, "MXU data found");
847  science_tag = "SCIENCE_MXU";
848  reduced_science_tag = "REDUCED_SCI_MXU";
849  unmapped_science_tag = "UNMAPPED_SCI_MXU";
850  mapped_science_tag = "MAPPED_SCI_MXU";
851  mapped_science_sky_tag = "MAPPED_ALL_SCI_MXU";
852  skylines_offsets_tag = "SKY_SHIFTS_SLIT_SCI_MXU";
853  wavelength_map_sky_tag = "WAVELENGTH_MAP_SCI_MXU";
854  disp_coeff_sky_tag = "DISP_COEFF_SCI_MXU";
855  mapped_sky_tag = "MAPPED_SKY_SCI_MXU";
856  unmapped_sky_tag = "UNMAPPED_SKY_SCI_MXU";
857  object_table_tag = "OBJECT_TABLE_SCI_MXU";
858  reduced_sky_tag = "REDUCED_SKY_SCI_MXU";
859  reduced_error_tag = "REDUCED_ERROR_SCI_MXU";
860  }
861 
862  master_norm_flat_tag = "MASTER_NORM_FLAT_MXU";
863  global_sky_spectrum_tag = "GLOBAL_SKY_SPECTRUM_MXU";
864 
865  if (!cpl_frameset_count_tags(frameset, master_norm_flat_tag)) {
866  master_norm_flat_tag = "MASTER_NORM_FLAT_LONG_MXU";
867  }
868  }
869 
870  if (lss) {
871 
872  if (cosmics && !skyglobal)
873  fors_extract_exit("Cosmic rays correction for LSS "
874  "data requires --skyglobal=true");
875 
876  cpl_msg_info(recipe, "LSS data found");
877 
878  if (standard) {
879  science_tag = "STANDARD_LSS";
880  reduced_science_tag = "REDUCED_STD_LSS";
881  unmapped_science_tag = "UNMAPPED_STD_LSS";
882  mapped_science_tag = "MAPPED_STD_LSS";
883  mapped_science_sky_tag = "MAPPED_ALL_STD_LSS";
884  skylines_offsets_tag = "SKY_SHIFTS_LONG_STD_LSS";
885  wavelength_map_sky_tag = "WAVELENGTH_MAP_STD_LSS";
886  disp_coeff_sky_tag = "DISP_COEFF_STD_LSS";
887  mapped_sky_tag = "MAPPED_SKY_STD_LSS";
888  unmapped_sky_tag = "UNMAPPED_SKY_STD_LSS";
889  object_table_tag = "OBJECT_TABLE_STD_LSS";
890  reduced_sky_tag = "REDUCED_SKY_STD_LSS";
891  reduced_error_tag = "REDUCED_ERROR_STD_LSS";
892  }
893  else {
894  science_tag = "SCIENCE_LSS";
895  reduced_science_tag = "REDUCED_SCI_LSS";
896  unmapped_science_tag = "UNMAPPED_SCI_LSS";
897  mapped_science_tag = "MAPPED_SCI_LSS";
898  mapped_science_sky_tag = "MAPPED_ALL_SCI_LSS";
899  skylines_offsets_tag = "SKY_SHIFTS_LONG_SCI_LSS";
900  wavelength_map_sky_tag = "WAVELENGTH_MAP_SCI_LSS";
901  disp_coeff_sky_tag = "DISP_COEFF_SCI_LSS";
902  mapped_sky_tag = "MAPPED_SKY_SCI_LSS";
903  unmapped_sky_tag = "UNMAPPED_SKY_SCI_LSS";
904  object_table_tag = "OBJECT_TABLE_SCI_LSS";
905  reduced_sky_tag = "REDUCED_SKY_SCI_LSS";
906  reduced_error_tag = "REDUCED_ERROR_SCI_LSS";
907  }
908 
909  master_norm_flat_tag = "MASTER_NORM_FLAT_LSS";
910  global_sky_spectrum_tag = "GLOBAL_SKY_SPECTRUM_LSS";
911  }
912 
913  if (mos) {
914  cpl_msg_info(recipe, "MOS data found");
915  if (standard) {
916  science_tag = "STANDARD_MOS";
917  reduced_science_tag = "REDUCED_STD_MOS";
918  unmapped_science_tag = "UNMAPPED_STD_MOS";
919  mapped_science_tag = "MAPPED_STD_MOS";
920  mapped_science_sky_tag = "MAPPED_ALL_STD_MOS";
921  skylines_offsets_tag = "SKY_SHIFTS_SLIT_STD_MOS";
922  wavelength_map_sky_tag = "WAVELENGTH_MAP_STD_MOS";
923  disp_coeff_sky_tag = "DISP_COEFF_STD_MOS";
924  mapped_sky_tag = "MAPPED_SKY_STD_MOS";
925  unmapped_sky_tag = "UNMAPPED_SKY_STD_MOS";
926  object_table_tag = "OBJECT_TABLE_STD_MOS";
927  reduced_sky_tag = "REDUCED_SKY_STD_MOS";
928  reduced_error_tag = "REDUCED_ERROR_STD_MOS";
929  }
930  else {
931  science_tag = "SCIENCE_MOS";
932  reduced_science_tag = "REDUCED_SCI_MOS";
933  unmapped_science_tag = "UNMAPPED_SCI_MOS";
934  mapped_science_tag = "MAPPED_SCI_MOS";
935  mapped_science_sky_tag = "MAPPED_ALL_SCI_MOS";
936  skylines_offsets_tag = "SKY_SHIFTS_SLIT_SCI_MOS";
937  wavelength_map_sky_tag = "WAVELENGTH_MAP_SCI_MOS";
938  disp_coeff_sky_tag = "DISP_COEFF_SCI_MOS";
939  mapped_sky_tag = "MAPPED_SKY_SCI_MOS";
940  unmapped_sky_tag = "UNMAPPED_SKY_SCI_MOS";
941  object_table_tag = "OBJECT_TABLE_SCI_MOS";
942  reduced_sky_tag = "REDUCED_SKY_SCI_MOS";
943  reduced_error_tag = "REDUCED_ERROR_SCI_MOS";
944  }
945 
946  master_norm_flat_tag = "MASTER_NORM_FLAT_MOS";
947  global_sky_spectrum_tag = "GLOBAL_SKY_SPECTRUM_MOS";
948 
949  if (!cpl_frameset_count_tags(frameset, master_norm_flat_tag)) {
950  master_norm_flat_tag = "MASTER_NORM_FLAT_LONG_MOS";
951  }
952  }
953 
954  if (cpl_frameset_count_tags(frameset, "MASTER_BIAS") == 0)
955  fors_extract_exit("Missing required input: MASTER_BIAS");
956 
957  if (cpl_frameset_count_tags(frameset, "MASTER_BIAS") > 1)
958  fors_extract_exit("Too many in input: MASTER_BIAS");
959 
960  if (skyalign >= 0)
961  if (cpl_frameset_count_tags(frameset, "MASTER_SKYLINECAT") > 1)
962  fors_extract_exit("Too many in input: MASTER_SKYLINECAT");
963 
964  if (cpl_frameset_count_tags(frameset, global_distortion_tag) == 0)
965  fors_extract_exit("Missing required input: MASTER_DISTORTION_TABLE");
966 
967  if (cpl_frameset_count_tags(frameset, global_distortion_tag) > 1)
968  fors_extract_exit("Too many in input: MASTER_DISTORTION_TABLE");
969 
970  if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) > 1) {
971  if (flatfield) {
972  cpl_msg_error(recipe, "Too many in input: %s",
973  master_norm_flat_tag);
974  fors_extract_exit(NULL);
975  }
976  else {
977  cpl_msg_warning(recipe, "%s in input are ignored, "
978  "since flat field correction was not requested",
979  master_norm_flat_tag);
980  }
981  }
982 
983  if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) == 1) {
984  if (!flatfield) {
985  cpl_msg_warning(recipe, "%s in input is ignored, "
986  "since flat field correction was not requested",
987  master_norm_flat_tag);
988  }
989  }
990 
991  if (cpl_frameset_count_tags(frameset, master_norm_flat_tag) == 0) {
992  if (flatfield) {
993  cpl_msg_error(recipe, "Flat field correction was requested, "
994  "but no %s are found in input",
995  master_norm_flat_tag);
996  fors_extract_exit(NULL);
997  }
998  }
999 
1000  cpl_msg_indent_less();
1001 
1002 
1003  /*
1004  * Loading input data
1005  */
1006 
1007  exptime = cpl_calloc(nscience, sizeof(double));
1008 
1009  if (nscience > 1) {
1010 
1011  cpl_msg_info(recipe, "Load %d scientific frames and median them...",
1012  nscience);
1013  cpl_msg_indent_more();
1014 
1015  all_science = cpl_imagelist_new();
1016 
1017  header = dfs_load_header(frameset, science_tag, 0);
1018 
1019  if (header == NULL)
1020  fors_extract_exit("Cannot load scientific frame header");
1021 
1022  alltime = exptime[0] = cpl_propertylist_get_double(header, "EXPTIME");
1023 
1024  if (cpl_error_get_code() != CPL_ERROR_NONE)
1025  fors_extract_exit("Missing keyword EXPTIME in scientific "
1026  "frame header");
1027 
1028  cpl_propertylist_delete(header); header = NULL;
1029 
1030  cpl_msg_info(recipe, "Scientific frame 1 exposure time: %.2f s",
1031  exptime[0]);
1032 
1033  for (i = 1; i < nscience; i++) {
1034 
1035  header = dfs_load_header(frameset, NULL, 0);
1036 
1037  if (header == NULL)
1038  fors_extract_exit("Cannot load scientific frame header");
1039 
1040  exptime[i] = cpl_propertylist_get_double(header, "EXPTIME");
1041 
1042  alltime += exptime[i];
1043 
1044  if (cpl_error_get_code() != CPL_ERROR_NONE)
1045  fors_extract_exit("Missing keyword EXPTIME in scientific "
1046  "frame header");
1047 
1048  cpl_propertylist_delete(header); header = NULL;
1049 
1050  cpl_msg_info(recipe, "Scientific frame %d exposure time: %.2f s",
1051  i+1, exptime[i]);
1052  }
1053 
1054  spectra = dfs_load_image(frameset, science_tag, CPL_TYPE_FLOAT, 0, 0);
1055 
1056  if (spectra == NULL)
1057  fors_extract_exit("Cannot load scientific frame");
1058 
1059  cpl_image_divide_scalar(spectra, exptime[0]);
1060  cpl_imagelist_set(all_science, spectra, 0); spectra = NULL;
1061 
1062  for (i = 1; i < nscience; i++) {
1063 
1064  spectra = dfs_load_image(frameset, NULL, CPL_TYPE_FLOAT, 0, 0);
1065 
1066  if (spectra) {
1067  cpl_image_divide_scalar(spectra, exptime[i]);
1068  cpl_imagelist_set(all_science, spectra, i); spectra = NULL;
1069  }
1070  else
1071  fors_extract_exit("Cannot load scientific frame");
1072 
1073  }
1074 
1075  spectra = cpl_imagelist_collapse_median_create(all_science);
1076  cpl_image_multiply_scalar(spectra, alltime);
1077 
1078  cpl_imagelist_delete(all_science);
1079  }
1080  else {
1081  cpl_msg_info(recipe, "Load scientific exposure...");
1082  cpl_msg_indent_more();
1083 
1084  header = dfs_load_header(frameset, science_tag, 0);
1085 
1086  if (header == NULL)
1087  fors_extract_exit("Cannot load scientific frame header");
1088 
1089 
1090  /*
1091  * Insert here a check on supported filters:
1092  */
1093 
1094  wheel4 = (char *)cpl_propertylist_get_string(header,
1095  "ESO INS OPTI9 TYPE");
1096  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1097  fors_extract_exit("Missing ESO INS OPTI9 TYPE in flat header");
1098  }
1099 
1100  if (strcmp("FILT", wheel4) == 0) {
1101  wheel4 = (char *)cpl_propertylist_get_string(header,
1102  "ESO INS OPTI9 NAME");
1103  cpl_msg_error(recipe, "Unsupported filter: %s", wheel4);
1104  fors_extract_exit(NULL);
1105  }
1106 
1107 
1108  alltime = exptime[0] = cpl_propertylist_get_double(header, "EXPTIME");
1109 
1110  if (cpl_error_get_code() != CPL_ERROR_NONE)
1111  fors_extract_exit("Missing keyword EXPTIME in scientific "
1112  "frame header");
1113 
1114  cpl_propertylist_delete(header); header = NULL;
1115 
1116  cpl_msg_info(recipe, "Scientific frame exposure time: %.2f s",
1117  exptime[0]);
1118 
1119  spectra = dfs_load_image(frameset, science_tag, CPL_TYPE_FLOAT, 0, 0);
1120  }
1121 
1122  if (spectra == NULL)
1123  fors_extract_exit("Cannot load scientific frame");
1124 
1125  cpl_free(exptime); exptime = NULL;
1126 
1127  cpl_msg_indent_less();
1128 
1129 
1130  /*
1131  * Get the reference wavelength and the rebin factor along the
1132  * dispersion direction from a scientific exposure
1133  */
1134 
1135  header = dfs_load_header(frameset, science_tag, 0);
1136 
1137  if (header == NULL)
1138  fors_extract_exit("Cannot load scientific frame header");
1139 
1140  instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME");
1141  if (instrume == NULL)
1142  fors_extract_exit("Missing keyword INSTRUME in sientific header");
1143  instrume = cpl_strdup(instrume);
1144 
1145  if (instrume[4] == '1')
1146  snprintf(version, 80, "%s/%s", "fors1", VERSION);
1147  if (instrume[4] == '2')
1148  snprintf(version, 80, "%s/%s", "fors2", VERSION);
1149 
1150  cpl_free(instrume); instrume = NULL;
1151 
1152  reference = cpl_propertylist_get_double(header, "ESO INS GRIS1 WLEN");
1153 
1154  if (cpl_error_get_code() != CPL_ERROR_NONE)
1155  fors_extract_exit("Missing keyword ESO INS GRIS1 WLEN in scientific "
1156  "frame header");
1157 
1158  if (reference < 3000.0) /* Perhaps in nanometers... */
1159  reference *= 10;
1160 
1161  if (reference < 3000.0 || reference > 13000.0) {
1162  cpl_msg_error(recipe, "Invalid central wavelength %.2f read from "
1163  "keyword ESO INS GRIS1 WLEN in scientific frame header",
1164  reference);
1165  fors_extract_exit(NULL);
1166  }
1167 
1168  cpl_msg_info(recipe, "The central wavelength is: %.2f", reference);
1169 
1170  rebin = cpl_propertylist_get_int(header, "ESO DET WIN1 BINX");
1171 
1172  if (cpl_error_get_code() != CPL_ERROR_NONE)
1173  fors_extract_exit("Missing keyword ESO DET WIN1 BINX in scientific "
1174  "frame header");
1175 
1176  if (rebin != 1) {
1177  dispersion *= rebin;
1178  cpl_msg_warning(recipe, "The rebin factor is %d, and therefore the "
1179  "resampling step used is %f A/pixel", rebin,
1180  dispersion);
1181  }
1182 
1183  gain = cpl_propertylist_get_double(header, "ESO DET OUT1 CONAD");
1184 
1185  if (cpl_error_get_code() != CPL_ERROR_NONE)
1186  fors_extract_exit("Missing keyword ESO DET OUT1 CONAD in scientific "
1187  "frame header");
1188 
1189  cpl_msg_info(recipe, "The gain factor is: %.2f e-/ADU", gain);
1190 
1191  ron = cpl_propertylist_get_double(header, "ESO DET OUT1 RON");
1192 
1193  if (cpl_error_get_code() != CPL_ERROR_NONE)
1194  fors_extract_exit("Missing keyword ESO DET OUT1 RON in scientific "
1195  "frame header");
1196 
1197  ron /= gain; /* Convert from electrons to ADU */
1198 
1199  cpl_msg_info(recipe, "The read-out-noise is: %.2f ADU", ron);
1200 
1201  coll = (char *)cpl_propertylist_get_string(header, "ESO INS COLL NAME");
1202 
1203  if (cpl_error_get_code() != CPL_ERROR_NONE)
1204  fors_extract_exit("Missing keyword ESO INS COLL NAME in scientific "
1205  "frame header");
1206 
1207  cpl_msg_info(recipe, "The collimator is : %s", coll);
1208 
1209  if (strcmp(coll, "COLL_HR") == 0)
1210  fors_extract_exit("HR collimator is not yet supported by this recipe");
1211 
1212 
1213  if (mos)
1214  {
1215  int nslits_out_det;
1216  maskslits = mos_load_slits_fors_mos(header, &nslits_out_det);
1217  }
1218  else if (lss)
1219  maskslits = mos_load_slits_fors_lss(header);
1220  else
1221  maskslits = mos_load_slits_fors_mxu(header);
1222 
1223  if (lss) {
1224  if (skylocal) {
1225  if (cosmics)
1226  fors_extract_exit("Cosmic rays correction for LSS "
1227  "data requires --skyglobal=true");
1228  skymedian = skylocal;
1229  skylocal = 0;
1230  }
1231  }
1232 
1233  global = dfs_load_table(frameset, global_distortion_tag, 1);
1234  if (global == NULL)
1235  fors_extract_exit("Cannot load global distortion table");
1236 
1237  /* Leave the header on for the next step... */
1238 
1239 
1240  /*
1241  * Remove the master bias
1242  */
1243 
1244  cpl_msg_info(recipe, "Remove the master bias...");
1245 
1246  bias = dfs_load_image(frameset, "MASTER_BIAS", CPL_TYPE_FLOAT, 0, 1);
1247 
1248  if (bias == NULL)
1249  fors_extract_exit("Cannot load master bias");
1250 
1251  overscans = mos_load_overscans_vimos(header, 1);
1252  cpl_propertylist_delete(header); header = NULL;
1253  dummy = mos_remove_bias(spectra, bias, overscans);
1254  cpl_image_delete(spectra); spectra = dummy; dummy = NULL;
1255  cpl_image_delete(bias); bias = NULL;
1256  cpl_table_delete(overscans); overscans = NULL;
1257 
1258  if (spectra == NULL)
1259  fors_extract_exit("Cannot remove bias from scientific frame");
1260 
1261  nx = cpl_image_get_size_x(spectra);
1262  ny = cpl_image_get_size_y(spectra);
1263 
1264  if (ny == 400 && nx == 2048)
1265  narrow = 1;
1266 
1267  if (narrow) {
1268  ny = 2048;
1269  dummy = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1270  cpl_image_copy(dummy, spectra, 1, 825); /* (2048 - 400)/2 + 1 */
1271  if (cpl_error_get_code())
1272  fors_extract_exit("Problems expanding scientific image");
1273  cpl_image_delete(spectra); spectra = dummy; dummy = NULL;
1274  }
1275 
1276  cpl_msg_indent_less();
1277  cpl_msg_info(recipe, "Load normalised flat field (if present)...");
1278  cpl_msg_indent_more();
1279 
1280  if (flatfield) {
1281 
1282  norm_flat = dfs_load_image(frameset, master_norm_flat_tag,
1283  CPL_TYPE_FLOAT, 0, 1);
1284 
1285  if (norm_flat) {
1286  if (narrow) {
1287  dummy = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1288  cpl_image_copy(dummy, norm_flat, 1, 825);
1289  if (cpl_error_get_code())
1290  fors_extract_exit("Problems expanding flat image");
1291  cpl_image_delete(norm_flat); norm_flat = dummy; dummy = NULL;
1292  }
1293  cpl_msg_info(recipe, "Apply flat field correction...");
1294  if (cpl_image_divide(spectra, norm_flat) != CPL_ERROR_NONE) {
1295  cpl_msg_error(recipe, "Failure of flat field correction: %s",
1296  cpl_error_get_message());
1297  fors_extract_exit(NULL);
1298  }
1299  cpl_image_delete(norm_flat); norm_flat = NULL;
1300  }
1301  else {
1302  cpl_msg_error(recipe, "Cannot load input %s for flat field "
1303  "correction", master_norm_flat_tag);
1304  fors_extract_exit(NULL);
1305  }
1306 
1307  }
1308 
1309 
1310  if (skyalign >= 0) {
1311  cpl_msg_indent_less();
1312  cpl_msg_info(recipe, "Load input sky line catalog...");
1313  cpl_msg_indent_more();
1314 
1315  wavelengths = dfs_load_table(frameset, "MASTER_SKYLINECAT", 1);
1316 
1317  if (wavelengths) {
1318 
1319  /*
1320  * Cast the wavelengths into a (double precision) CPL vector
1321  */
1322 
1323  nlines = cpl_table_get_nrow(wavelengths);
1324 
1325  if (nlines == 0)
1326  fors_extract_exit("Empty input sky line catalog");
1327 
1328  if (cpl_table_has_column(wavelengths, wcolumn) != 1) {
1329  cpl_msg_error(recipe, "Missing column %s in input line "
1330  "catalog table", wcolumn);
1331  fors_extract_exit(NULL);
1332  }
1333 
1334  line = cpl_malloc(nlines * sizeof(double));
1335 
1336  for (i = 0; i < nlines; i++)
1337  line[i] = cpl_table_get(wavelengths, wcolumn, i, NULL);
1338 
1339  cpl_table_delete(wavelengths); wavelengths = NULL;
1340 
1341  lines = cpl_vector_wrap(nlines, line);
1342  }
1343  else {
1344  cpl_msg_info(recipe, "No sky line catalog found in input - fine!");
1345  }
1346  }
1347 
1348 
1349  /*
1350  * Load the slit location table, or provide a dummy one in case
1351  * of LSS data (single slit spanning whole image)
1352  */
1353 
1354  slits = mos_build_slit_location(global, maskslits, ny);
1355  if (slits == NULL)
1356  fors_extract_exit("Cannot create slits location table");
1357 
1358 
1359  /*
1360  * Load the spectral curvature table in case of MOS or MXU data
1361  */
1362 
1363  polytraces = mos_build_curv_coeff(global, maskslits, slits);
1364  if (polytraces == NULL)
1365  fors_extract_exit("Cannot create spectral curvature table");
1366 
1367  cpl_table_delete(maskslits); maskslits = NULL;
1368 
1369  cpl_msg_indent_less();
1370  cpl_msg_info(recipe, "Processing scientific spectra...");
1371  cpl_msg_indent_more();
1372 
1373  /*
1374  * This one will also generate the spatial map from the spectral
1375  * curvature table (in the case of multislit data)
1376  */
1377 
1378  coordinate = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1379 
1380  smapped = mos_spatial_calibration(spectra, slits, polytraces, reference,
1381  startwavelength, endwavelength,
1382  dispersion, flux, coordinate);
1383 
1384 
1385  /*
1386  * Load the wavelength calibration table
1387  */
1388 
1389  idscoeff = mos_build_disp_coeff(global, slits);
1390  if (idscoeff == NULL)
1391  fors_extract_exit("Cannot create wavelength calibration table");
1392 
1393  cpl_table_delete(global); global = NULL;
1394 
1395 
1396  /*
1397  * Generate a rectified wavelength map from the wavelength calibration
1398  * table
1399  */
1400 
1401  rainbow = mos_map_idscoeff(idscoeff, nx, reference, startwavelength,
1402  endwavelength);
1403 
1404  if (dispersion > 1.0)
1405  highres = 0;
1406  else
1407  highres = 1;
1408 
1409  if (skyalign >= 0) {
1410  if (skyalign) {
1411  cpl_msg_info(recipe, "Align wavelength solution to reference "
1412  "skylines applying %d order residual fit...", skyalign);
1413  }
1414  else {
1415  cpl_msg_info(recipe, "Align wavelength solution to reference "
1416  "skylines applying median offset...");
1417  }
1418 
1419  if (lss) {
1420  offsets = mos_wavelength_align_lss(smapped, reference,
1421  startwavelength, endwavelength,
1422  idscoeff, lines, highres,
1423  skyalign, rainbow, 4);
1424  }
1425  else {
1426  offsets = mos_wavelength_align(smapped, slits, reference,
1427  startwavelength, endwavelength,
1428  idscoeff, lines, highres, skyalign,
1429  rainbow, 4);
1430  }
1431 
1432  cpl_vector_delete(lines); lines = NULL;
1433 
1434  if (offsets) {
1435  if (standard)
1436  cpl_msg_warning(recipe, "Alignment of the wavelength solution "
1437  "to reference sky lines may be unreliable in "
1438  "this case!");
1439 
1440  if (dfs_save_table(frameset, offsets, skylines_offsets_tag, NULL,
1441  parlist, recipe, version))
1442  fors_extract_exit(NULL);
1443 
1444  cpl_table_delete(offsets); offsets = NULL;
1445  }
1446  else {
1447  cpl_msg_warning(recipe, "Alignment of the wavelength solution "
1448  "to reference sky lines could not be done!");
1449  skyalign = -1;
1450  }
1451 
1452  }
1453 
1454  wavemap = mos_map_wavelengths(coordinate, rainbow, slits,
1455  polytraces, reference,
1456  startwavelength, endwavelength,
1457  dispersion);
1458 
1459  cpl_image_delete(rainbow); rainbow = NULL;
1460  cpl_image_delete(coordinate); coordinate = NULL;
1461 
1462  /*
1463  * Here the wavelength calibrated slit spectra are created. This frame
1464  * contains sky_science.
1465  */
1466 
1467  mapped_sky = mos_wavelength_calibration(smapped, reference,
1468  startwavelength, endwavelength,
1469  dispersion, idscoeff, flux);
1470 
1471  cpl_msg_indent_less();
1472  cpl_msg_info(recipe, "Check applied wavelength against skylines...");
1473  cpl_msg_indent_more();
1474 
1475  mean_rms = mos_distortions_rms(mapped_sky, NULL, startwavelength,
1476  dispersion, 6, highres);
1477 
1478  cpl_msg_info(recipe, "Mean residual: %f", mean_rms);
1479 
1480  mean_rms = cpl_table_get_column_mean(idscoeff, "error");
1481 
1482  header = cpl_propertylist_new();
1483  cpl_propertylist_update_double(header, "CRPIX1", 1.0);
1484  cpl_propertylist_update_double(header, "CRPIX2", 1.0);
1485  cpl_propertylist_update_double(header, "CRVAL1",
1486  startwavelength + dispersion/2);
1487  cpl_propertylist_update_double(header, "CRVAL2", 1.0);
1488  /* cpl_propertylist_update_double(header, "CDELT1", dispersion);
1489  cpl_propertylist_update_double(header, "CDELT2", 1.0); */
1490  cpl_propertylist_update_double(header, "CD1_1", dispersion);
1491  cpl_propertylist_update_double(header, "CD1_2", 0.0);
1492  cpl_propertylist_update_double(header, "CD2_1", 0.0);
1493  cpl_propertylist_update_double(header, "CD2_2", 1.0);
1494  cpl_propertylist_update_string(header, "CTYPE1", "LINEAR");
1495  cpl_propertylist_update_string(header, "CTYPE2", "PIXEL");
1496 
1497  if (time_normalise) {
1498  dummy = cpl_image_divide_scalar_create(mapped_sky, alltime);
1499  if (dfs_save_image(frameset, dummy, mapped_science_sky_tag, header,
1500  parlist, recipe, version))
1501  fors_extract_exit(NULL);
1502  cpl_image_delete(dummy); dummy = NULL;
1503  }
1504  else {
1505  if (dfs_save_image(frameset, mapped_sky, mapped_science_sky_tag,
1506  header, parlist, recipe, version))
1507  fors_extract_exit(NULL);
1508  }
1509 
1510 /* if (skyglobal == 0 && skymedian < 0) { NSS */
1511  if (skyglobal == 0 && skymedian == 0 && skylocal == 0) {
1512  cpl_image_delete(mapped_sky); mapped_sky = NULL;
1513  }
1514 
1515  if (skyglobal || skylocal) {
1516 
1517  cpl_msg_indent_less();
1518 
1519  if (skyglobal) {
1520  cpl_msg_info(recipe, "Global sky determination...");
1521  cpl_msg_indent_more();
1522  skymap = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
1523  sky = mos_sky_map_super(spectra, wavemap, dispersion,
1524  2.0, 50, skymap);
1525  if (sky)
1526  cpl_image_subtract(spectra, skymap);
1527  else
1528  cpl_image_delete(skymap); skymap = NULL;
1529  }
1530  else {
1531  cpl_msg_info(recipe, "Local sky determination...");
1532  cpl_msg_indent_more();
1533  skymap = mos_subtract_sky(spectra, slits, polytraces, reference,
1534  startwavelength, endwavelength, dispersion);
1535  }
1536 
1537  if (skymap) {
1538  if (skyglobal) {
1539  if (time_normalise)
1540  cpl_table_divide_scalar(sky, "sky", alltime);
1541  if (dfs_save_table(frameset, sky, global_sky_spectrum_tag,
1542  NULL, parlist, recipe, version))
1543  fors_extract_exit(NULL);
1544 
1545  cpl_table_delete(sky); sky = NULL;
1546  }
1547 
1548  save_header = dfs_load_header(frameset, science_tag, 0);
1549 
1550  if (time_normalise)
1551  cpl_image_divide_scalar(skymap, alltime);
1552  if (dfs_save_image(frameset, skymap, unmapped_sky_tag,
1553  save_header, parlist, recipe, version))
1554  fors_extract_exit(NULL);
1555 
1556  cpl_image_delete(skymap); skymap = NULL;
1557 
1558  if (dfs_save_image(frameset, spectra, unmapped_science_tag,
1559  save_header, parlist, recipe, version))
1560  fors_extract_exit(NULL);
1561 
1562  cpl_propertylist_delete(save_header); save_header = NULL;
1563 
1564  if (cosmics) {
1565  cpl_msg_info(recipe, "Removing cosmic rays...");
1566  mos_clean_cosmics(spectra, gain, -1., -1.);
1567  }
1568 
1569  /*
1570  * The spatially rectified image, that contained the sky,
1571  * is replaced by a sky-subtracted spatially rectified image:
1572  */
1573 
1574  cpl_image_delete(smapped); smapped = NULL;
1575 
1576  if (lss) {
1577  smapped = cpl_image_duplicate(spectra);
1578  }
1579  else {
1580  smapped = mos_spatial_calibration(spectra, slits, polytraces,
1581  reference, startwavelength,
1582  endwavelength, dispersion,
1583  flux, NULL);
1584  }
1585  }
1586  else {
1587  cpl_msg_warning(recipe, "Sky subtraction failure");
1588  if (cosmics)
1589  cpl_msg_warning(recipe, "Cosmic rays removal not performed!");
1590  cosmics = skylocal = skyglobal = 0;
1591  }
1592  }
1593 
1594  cpl_image_delete(spectra); spectra = NULL;
1595  cpl_table_delete(polytraces); polytraces = NULL;
1596 
1597  if (skyalign >= 0) {
1598  save_header = dfs_load_header(frameset, science_tag, 0);
1599  if (dfs_save_image(frameset, wavemap, wavelength_map_sky_tag,
1600  save_header, parlist, recipe, version))
1601  fors_extract_exit(NULL);
1602  cpl_propertylist_delete(save_header); save_header = NULL;
1603  }
1604 
1605  cpl_image_delete(wavemap); wavemap = NULL;
1606 
1607  mapped = mos_wavelength_calibration(smapped, reference,
1608  startwavelength, endwavelength,
1609  dispersion, idscoeff, flux);
1610 
1611  cpl_image_delete(smapped); smapped = NULL;
1612 
1613 /* if (skymedian >= 0) { NSS */
1614  if (skymedian) {
1615  cpl_msg_indent_less();
1616  cpl_msg_info(recipe, "Local sky determination...");
1617  cpl_msg_indent_more();
1618 
1619 /* NSS skylocalmap = mos_sky_local(mapped, slits, skymedian); */
1620 /* skylocalmap = mos_sky_local(mapped, slits, 0); */
1621  skylocalmap = mos_sky_local_old(mapped, slits);
1622  cpl_image_subtract(mapped, skylocalmap);
1623 /*
1624  if (dfs_save_image(frameset, skylocalmap, mapped_sky_tag, header,
1625  parlist, recipe, version))
1626  fors_extract_exit(NULL);
1627 */
1628  cpl_image_delete(skylocalmap); skylocalmap = NULL;
1629  }
1630 
1631 /* if (skyglobal || skymedian >= 0 || skylocal) { NSS */
1632  if (skyglobal || skymedian || skylocal) {
1633 
1634  skylocalmap = cpl_image_subtract_create(mapped_sky, mapped);
1635 
1636  cpl_image_delete(mapped_sky); mapped_sky = NULL;
1637 
1638  if (time_normalise) {
1639  dummy = cpl_image_divide_scalar_create(skylocalmap, alltime);
1640  if (dfs_save_image(frameset, dummy, mapped_sky_tag, header,
1641  parlist, recipe, version))
1642  fors_extract_exit(NULL);
1643  cpl_image_delete(dummy); dummy = NULL;
1644  }
1645  else {
1646  if (dfs_save_image(frameset, skylocalmap, mapped_sky_tag, header,
1647  parlist, recipe, version))
1648  fors_extract_exit(NULL);
1649  }
1650 
1651  cpl_msg_indent_less();
1652  cpl_msg_info(recipe, "Object detection...");
1653  cpl_msg_indent_more();
1654 
1655  if (cosmics || nscience > 1) {
1656  dummy = mos_detect_objects(mapped, slits, slit_margin, ext_radius,
1657  cont_radius);
1658  }
1659  else {
1660  mapped_cleaned = cpl_image_duplicate(mapped);
1661  mos_clean_cosmics(mapped_cleaned, gain, -1., -1.);
1662  dummy = mos_detect_objects(mapped_cleaned, slits, slit_margin,
1663  ext_radius, cont_radius);
1664 
1665  cpl_image_delete(mapped_cleaned); mapped_cleaned = NULL;
1666  }
1667 
1668  cpl_image_delete(dummy); dummy = NULL;
1669 
1670  if (dfs_save_table(frameset, slits, object_table_tag, NULL, parlist,
1671  recipe, version))
1672  fors_extract_exit(NULL);
1673 
1674  cpl_msg_indent_less();
1675  cpl_msg_info(recipe, "Object extraction...");
1676  cpl_msg_indent_more();
1677 
1678  images = mos_extract_objects(mapped, skylocalmap, slits,
1679  ext_mode, ron, gain, 1);
1680 
1681  cpl_image_delete(skylocalmap); skylocalmap = NULL;
1682 
1683  if (images) {
1684  if (time_normalise)
1685  cpl_image_divide_scalar(images[0], alltime);
1686  if (dfs_save_image(frameset, images[0], reduced_science_tag, header,
1687  parlist, recipe, version))
1688  fors_extract_exit(NULL);
1689  cpl_image_delete(images[0]);
1690 
1691  if (time_normalise)
1692  cpl_image_divide_scalar(images[1], alltime);
1693  if (dfs_save_image(frameset, images[1], reduced_sky_tag, header,
1694  parlist, recipe, version))
1695  fors_extract_exit(NULL);
1696  cpl_image_delete(images[1]);
1697 
1698  if (time_normalise)
1699  cpl_image_divide_scalar(images[2], alltime);
1700  if (dfs_save_image(frameset, images[2], reduced_error_tag, header,
1701  parlist, recipe, version))
1702  fors_extract_exit(NULL);
1703  cpl_image_delete(images[2]);
1704 
1705  cpl_free(images);
1706  }
1707  else {
1708  cpl_msg_warning(recipe, "No objects found: the products "
1709  "%s, %s, and %s are not created",
1710  reduced_science_tag, reduced_sky_tag,
1711  reduced_error_tag);
1712  }
1713 
1714  }
1715 
1716  cpl_table_delete(slits); slits = NULL;
1717 
1718  if (skyalign >= 0) {
1719  if (dfs_save_table(frameset, idscoeff, disp_coeff_sky_tag, NULL,
1720  parlist, recipe, version))
1721  fors_extract_exit(NULL);
1722  }
1723 
1724  cpl_table_delete(idscoeff); idscoeff = NULL;
1725 
1726 /* if (skyglobal || skymedian >= 0) { NSS */
1727  if (skyglobal || skymedian || skylocal) {
1728  if (time_normalise)
1729  cpl_image_divide_scalar(mapped, alltime);
1730  if (dfs_save_image(frameset, mapped, mapped_science_tag, header,
1731  parlist, recipe, version))
1732  fors_extract_exit(NULL);
1733  }
1734 
1735  cpl_image_delete(mapped); mapped = NULL;
1736  cpl_propertylist_delete(header); header = NULL;
1737 
1738  if (cpl_error_get_code()) {
1739  cpl_msg_error(cpl_error_get_where(), "%s", cpl_error_get_message());
1740  fors_extract_exit(NULL);
1741  }
1742 
1743  return 0;
1744 }
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.
Definition: moses.c:8264
cpl_table * mos_build_disp_coeff(cpl_table *global, cpl_table *slits)
Build the IDS coefficients table from a global distortions table.
Definition: moses.c:1845
int cpl_plugin_get_info(cpl_pluginlist *list)
Build the list of available plugins, for this module.
Definition: fors_bias.c:62
cpl_image * dfs_load_image(cpl_frameset *frameset, const char *category, cpl_type type, int ext, int calib)
Loading image data of given category.
Definition: fors_dfs.c:845
const char * dfs_get_parameter_string(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe string parameter value.
Definition: fors_dfs.c:587
double mos_distortions_rms(cpl_image *rectified, cpl_vector *lines, double wavestart, double dispersion, int radius, int highres)
Estimate the spectral distortion modeling goodness.
Definition: moses.c:10754
cpl_propertylist * dfs_load_header(cpl_frameset *frameset, const char *category, int ext)
Loading header associated to data of given category.
Definition: fors_dfs.c:951
cpl_table * mos_load_slits_fors_mxu(cpl_propertylist *header)
Create slit location table from FITS header of FORS2-MXU data.
Definition: moses.c:14561
cpl_image ** mos_extract_objects(cpl_image *science, cpl_image *sky, cpl_table *objects, int extraction, double ron, double gain, int ncombined)
Extract detected objects from rectified scientific frame.
Definition: moses.c:14002
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.
Definition: moses.c:11087
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.
Definition: moses.c:9412
cpl_table * mos_sky_map_super(cpl_image *spectra, cpl_image *wavemap, double dispersion, double factor, int minpoints, cpl_image *skymap)
Create a CCD median sky map.
Definition: moses.c:11849
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.
Definition: moses.c:14801
cpl_table * mos_wavelength_align(cpl_image *image, cpl_table *slits, double refwave, double firstLambda, double lastLambda, cpl_table *idscoeff, cpl_vector *skylines, int highres, int order, cpl_image *calibration, int sradius)
Modify the input wavelength solution to match reference sky lines.
Definition: moses.c:9693
cpl_image * mos_remove_bias(cpl_image *image, cpl_image *bias, cpl_table *overscans)
Subtract the bias from a CCD exposure.
Definition: moses.c:3422
cpl_image * mos_detect_objects(cpl_image *image, cpl_table *slits, int margin, int maxradius, int conradius)
Detect objects in rectified scientific frame.
Definition: moses.c:13651
cpl_image * mos_sky_local_old(cpl_image *spectra, cpl_table *slits)
Local determination of sky.
Definition: moses.c:12424
int dfs_get_parameter_bool(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe boolean parameter value.
Definition: fors_dfs.c:686
int dfs_equal_keyword(cpl_frameset *frameset, const char *keyword)
Saving table data of given category.
Definition: fors_dfs.c:1685
cpl_table * mos_wavelength_align_lss(cpl_image *image, double refwave, double firstLambda, double lastLambda, cpl_table *idscoeff, cpl_vector *skylines, int highres, int order, cpl_image *calibration, int sradius)
Modify the input wavelength solution to match reference sky lines (LSS).
Definition: moses.c:10246
cpl_image * mos_subtract_sky(cpl_image *science, cpl_table *slits, cpl_table *polytraces, double reference, double blue, double red, double dispersion)
Subtract the sky from the scientific CCD exposure.
Definition: moses.c:1969
cpl_image * mos_map_idscoeff(cpl_table *idscoeff, int xsize, double reference, double blue, double red)
Create a wavelengths map from an IDS coefficients table.
Definition: moses.c:10976
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.
Definition: fors_dfs.c:1447
cpl_table * dfs_load_table(cpl_frameset *frameset, const char *category, int ext)
Loading table data of given category.
Definition: fors_dfs.c:901
int dfs_get_parameter_int(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe integer parameter value.
Definition: fors_dfs.c:392
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.
Definition: fors_dfs.c:1574
Definition: list.c:74
cpl_error_code mos_clean_cosmics(cpl_image *image, float gain, float threshold, float ratio)
Remove cosmic rays from sky-subtracted CCD spectral exposure.
Definition: moses.c:12881
cpl_table * mos_build_curv_coeff(cpl_table *global, cpl_table *maskslits, cpl_table *slits)
Build the curvature coefficients table from a global distortions table.
Definition: moses.c:1690
double dfs_get_parameter_double(cpl_parameterlist *parlist, const char *name, const cpl_table *defaults)
Reading a recipe double parameter value.
Definition: fors_dfs.c:489
cpl_table * mos_load_slits_fors_lss(cpl_propertylist *header)
Create slit location table from FITS header of FORS1/2 LSS data.
Definition: moses.c:15003
fors_star_list * fors_extract(const fors_image *image, const fors_setting *setting, const extract_method *em, double magsyserr, fors_extract_sky_stats *sky_stats, cpl_image **background, cpl_table **extracted_sources)
Extract sources.
cpl_table * mos_load_overscans_vimos(const cpl_propertylist *header, int check_consistency)
Get the overscan positions from FITS header of VIMOS data.
Definition: moses.c:15426
cpl_table * mos_build_slit_location(cpl_table *global, cpl_table *maskslits, int ysize)
Build the slit location table from a global distortions table.
Definition: moses.c:1543