FORS Pipeline Reference Manual  4.12.5
fors_extract_slits.c
1 /* $Id: fors_extract_slits.c,v 1.8 2013-08-20 17:02:58 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-08-20 17:02:58 $
24  * $Revision: 1.8 $
25  * $Name: not supported by cvs2svn $
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 #include <math.h>
33 #include <cpl.h>
34 #include <moses.h>
35 #include <fors_dfs.h>
36 
37 static int fors_extract_slits_create(cpl_plugin *);
38 static int fors_extract_slits_exec(cpl_plugin *);
39 static int fors_extract_slits_destroy(cpl_plugin *);
40 static int fors_extract_slits(cpl_parameterlist *, cpl_frameset *);
41 
42 static char fors_extract_slits_description[] =
43 "This recipe is used to extract MOS/MXU slit spectra, following their\n"
44 "curvature, and to remap them into a spatially rectified image.\n"
45 "Please refer to the FORS Pipeline User's Manual for details about\n"
46 "the spectra remapping technique. Note however that the interpolation\n"
47 "is done exclusively along the spatial direction, and therefore the\n"
48 "output rectified image will have the same x size of the input spectral\n"
49 "image.\n"
50 "\n"
51 "In the table below the MXU acronym can be alternatively read as MOS.\n\n"
52 "Input files:\n\n"
53 " DO category: Type: Explanation: Required:\n"
54 " LAMP_UNBIAS_MXU\n"
55 " or SCIENCE_UNBIAS_MXU\n"
56 " or SCIENCE_UNFLAT_MXU\n"
57 " or STANDARD_UNBIAS_MXU\n"
58 " or STANDARD_UNFLAT_MXU\n"
59 " or UNMAPPED_SCI_MXU\n"
60 " or UNMAPPED_STD_MXU\n"
61 " or UNMAPPED_SKY_SCI_MXU\n"
62 " or UNMAPPED_SKY_STD_MXU Calib Spectral frame Y\n"
63 " SLIT_LOCATION_DETECT_MXU\n"
64 " or SLIT_LOCATION_MXU Calib Master flat frame Y\n"
65 " CURV_COEFF_MXU Calib Spectral curvature Y\n"
66 " GRISM_TABLE Calib Grism table .\n\n"
67 "Output files:\n\n"
68 " DO category: Data type: Explanation:\n"
69 " RECTIFIED_LAMP_MXU\n"
70 " or RECTIFIED_ALL_SCI_MXU\n"
71 " or RECTIFIED_ALL_STD_MXU\n"
72 " or RECTIFIED_SCI_MXU\n"
73 " or RECTIFIED_STD_MXU\n"
74 " or RECTIFIED_SKY_SCI_MXU\n"
75 " or RECTIFIED_SKY_STD_MXU FITS image Rectified slit spectra\n\n";
76 
77 #define fors_extract_slits_exit(message) \
78 { \
79 if (message) cpl_msg_error(recipe, message); \
80 cpl_image_delete(spectra); \
81 cpl_image_delete(spatial); \
82 cpl_table_delete(grism_table); \
83 cpl_table_delete(maskslits); \
84 cpl_table_delete(slits); \
85 cpl_table_delete(polytraces); \
86 cpl_propertylist_delete(header); \
87 cpl_msg_indent_less(); \
88 return -1; \
89 }
90 
91 #define fors_extract_slits_exit_memcheck(message) \
92 { \
93 if (message) cpl_msg_info(recipe, message); \
94 printf("free spectra (%p)\n", spectra); \
95 cpl_image_delete(spectra); \
96 printf("free spatial (%p)\n", spatial); \
97 cpl_image_delete(spatial); \
98 printf("free grism_table (%p)\n", grism_table); \
99 cpl_table_delete(grism_table); \
100 printf("free maskslits (%p)\n", maskslits); \
101 cpl_table_delete(maskslits); \
102 printf("free slits (%p)\n", slits); \
103 cpl_table_delete(slits); \
104 printf("free polytraces (%p)\n", polytraces); \
105 cpl_table_delete(polytraces); \
106 printf("free header (%p)\n", header); \
107 cpl_propertylist_delete(header); \
108 cpl_msg_indent_less(); \
109 return 0; \
110 }
111 
112 
124 int cpl_plugin_get_info(cpl_pluginlist *list)
125 {
126  cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe );
127  cpl_plugin *plugin = &recipe->interface;
128 
129  cpl_plugin_init(plugin,
130  CPL_PLUGIN_API,
131  FORS_BINARY_VERSION,
132  CPL_PLUGIN_TYPE_RECIPE,
133  "fors_extract_slits",
134  "Spatial rectification of spectral image",
135  fors_extract_slits_description,
136  "Carlo Izzo",
137  PACKAGE_BUGREPORT,
138  "This file is currently part of the FORS Instrument Pipeline\n"
139  "Copyright (C) 2002-2010 European Southern Observatory\n\n"
140  "This program is free software; you can redistribute it and/or modify\n"
141  "it under the terms of the GNU General Public License as published by\n"
142  "the Free Software Foundation; either version 2 of the License, or\n"
143  "(at your option) any later version.\n\n"
144  "This program is distributed in the hope that it will be useful,\n"
145  "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
146  "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
147  "GNU General Public License for more details.\n\n"
148  "You should have received a copy of the GNU General Public License\n"
149  "along with this program; if not, write to the Free Software Foundation,\n"
150  "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n",
151  fors_extract_slits_create,
152  fors_extract_slits_exec,
153  fors_extract_slits_destroy);
154 
155  cpl_pluginlist_append(list, plugin);
156 
157  return 0;
158 }
159 
160 
171 static int fors_extract_slits_create(cpl_plugin *plugin)
172 {
173  cpl_recipe *recipe;
174  cpl_parameter *p;
175 
176  /*
177  * Check that the plugin is part of a valid recipe
178  */
179 
180  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
181  recipe = (cpl_recipe *)plugin;
182  else
183  return -1;
184 
185  /*
186  * Create the (empty) parameters list in the cpl_recipe object
187  */
188 
189  recipe->parameters = cpl_parameterlist_new();
190 
191  /*
192  * Dispersion
193  */
194 
195  p = cpl_parameter_new_value("fors.fors_extract_slits.dispersion",
196  CPL_TYPE_DOUBLE,
197  "Expected spectral dispersion (Angstrom/pixel)",
198  "fors.fors_extract_slits",
199  0.0);
200  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dispersion");
201  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
202  cpl_parameterlist_append(recipe->parameters, p);
203 
204  /*
205  * Start wavelength for spectral extraction
206  */
207 
208  p = cpl_parameter_new_value("fors.fors_extract_slits.startwavelength",
209  CPL_TYPE_DOUBLE,
210  "Start wavelength in spectral extraction",
211  "fors.fors_extract_slits",
212  0.0);
213  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "startwavelength");
214  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
215  cpl_parameterlist_append(recipe->parameters, p);
216 
217  /*
218  * End wavelength for spectral extraction
219  */
220 
221  p = cpl_parameter_new_value("fors.fors_extract_slits.endwavelength",
222  CPL_TYPE_DOUBLE,
223  "End wavelength in spectral extraction",
224  "fors.fors_extract_slits",
225  0.0);
226  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "endwavelength");
227  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
228  cpl_parameterlist_append(recipe->parameters, p);
229 
230  /*
231  * Flux conservation
232  */
233 
234  p = cpl_parameter_new_value("fors.fors_extract_slits.flux",
235  CPL_TYPE_BOOL,
236  "Apply flux conservation",
237  "fors.fors_extract_slits",
238  TRUE);
239  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux");
240  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
241  cpl_parameterlist_append(recipe->parameters, p);
242 
243  return 0;
244 }
245 
246 
255 static int fors_extract_slits_exec(cpl_plugin *plugin)
256 {
257  cpl_recipe *recipe;
258 
259  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
260  recipe = (cpl_recipe *)plugin;
261  else
262  return -1;
263 
264  return fors_extract_slits(recipe->parameters, recipe->frames);
265 }
266 
267 
276 static int fors_extract_slits_destroy(cpl_plugin *plugin)
277 {
278  cpl_recipe *recipe;
279 
280  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
281  recipe = (cpl_recipe *)plugin;
282  else
283  return -1;
284 
285  cpl_parameterlist_delete(recipe->parameters);
286 
287  return 0;
288 }
289 
290 
300 static int fors_extract_slits(cpl_parameterlist *parlist,
301  cpl_frameset *frameset)
302 {
303 
304  const char *recipe = "fors_extract_slits";
305 
306 
307  /*
308  * Input parameters
309  */
310 
311  double dispersion;
312  double startwavelength;
313  double endwavelength;
314  int flux;
315 
316  /*
317  * CPL objects
318  */
319 
320  cpl_image *spectra = NULL;
321  cpl_image *spatial = NULL;
322  cpl_table *grism_table = NULL;
323  cpl_table *slits = NULL;
324  cpl_table *polytraces = NULL;
325  cpl_table *maskslits = NULL;
326  cpl_propertylist *header = NULL;
327 
328  /*
329  * Auxiliary variables
330  */
331 
332  char version[80];
333  const char *input_tag;
334  const char *output_tag;
335  const char *slit_location_tag;
336  const char *curv_coeff_tag;
337  int nframes;
338  int rebin;
339  int treat_as_lss;
340  double reference;
341  double mxpos;
342  int mxu, mos, lss;
343  int slit_l, slit_d;
344  int lamp_mxu;
345  int lamp_mos;
346  int lamp_lss;
347  int scib_mxu;
348  int scib_mos;
349  int scib_lss;
350  int scif_mxu;
351  int scif_mos;
352  int scif_lss;
353  int stab_mxu;
354  int stab_mos;
355  int stab_lss;
356  int staf_mxu;
357  int staf_mos;
358  int staf_lss;
359  int sciu_mxu;
360  int sciu_mos;
361  int sciu_lss;
362  int stau_mxu;
363  int stau_mos;
364  int stau_lss;
365  int scis_mxu;
366  int scis_mos;
367  int scis_lss;
368  int stas_mxu;
369  int stas_mos;
370  int stas_lss;
371  int nslits_out_det = 0;
372 
373  char *instrume = NULL;
374 
375 
376  cpl_msg_set_indentation(2);
377 
378 
379  /*
380  * Get configuration parameters
381  */
382 
383  cpl_msg_info(recipe, "Recipe %s configuration parameters:", recipe);
384  cpl_msg_indent_more();
385 
386  if (cpl_frameset_count_tags(frameset, "GRISM_TABLE") > 1)
387  fors_extract_slits_exit("Too many in input: GRISM_TABLE");
388 
389  grism_table = dfs_load_table(frameset, "GRISM_TABLE", 1);
390 
391  dispersion = dfs_get_parameter_double(parlist,
392  "fors.fors_extract_slits.dispersion", grism_table);
393 
394  if (dispersion <= 0.0)
395  fors_extract_slits_exit("Invalid spectral dispersion value");
396 
397  startwavelength = dfs_get_parameter_double(parlist,
398  "fors.fors_extract_slits.startwavelength", grism_table);
399  if (startwavelength > 1.0)
400  if (startwavelength < 3000.0 || startwavelength > 13000.0)
401  fors_extract_slits_exit("Invalid wavelength");
402 
403  endwavelength = dfs_get_parameter_double(parlist,
404  "fors.fors_extract_slits.endwavelength", grism_table);
405  if (endwavelength > 1.0) {
406  if (endwavelength < 3000.0 || endwavelength > 13000.0)
407  fors_extract_slits_exit("Invalid wavelength");
408  if (startwavelength < 1.0)
409  fors_extract_slits_exit("Invalid wavelength interval");
410  }
411 
412  if (startwavelength > 1.0)
413  if (endwavelength - startwavelength <= 0.0)
414  fors_extract_slits_exit("Invalid wavelength interval");
415 
416  flux = dfs_get_parameter_bool(parlist,
417  "fors.fors_extract_slits.flux", NULL);
418 
419  cpl_table_delete(grism_table); grism_table = NULL;
420 
421  if (cpl_error_get_code())
422  fors_extract_slits_exit("Failure reading the configuration parameters");
423 
424 
425  cpl_msg_indent_less();
426  cpl_msg_info(recipe, "Check input set-of-frames:");
427  cpl_msg_indent_more();
428 
429  mxu = lamp_mxu = cpl_frameset_count_tags(frameset, "LAMP_UNBIAS_MXU");
430  mos = lamp_mos = cpl_frameset_count_tags(frameset, "LAMP_UNBIAS_MOS");
431  lss = lamp_lss = cpl_frameset_count_tags(frameset, "LAMP_UNBIAS_LSS");
432  mxu += scib_mxu = cpl_frameset_count_tags(frameset, "SCIENCE_UNBIAS_MXU");
433  mos += scib_mos = cpl_frameset_count_tags(frameset, "SCIENCE_UNBIAS_MOS");
434  lss += scib_lss = cpl_frameset_count_tags(frameset, "SCIENCE_UNBIAS_LSS");
435  mxu += scif_mxu = cpl_frameset_count_tags(frameset, "SCIENCE_UNFLAT_MXU");
436  mos += scif_mos = cpl_frameset_count_tags(frameset, "SCIENCE_UNFLAT_MOS");
437  lss += scif_lss = cpl_frameset_count_tags(frameset, "SCIENCE_UNFLAT_LSS");
438  mxu += stab_mxu = cpl_frameset_count_tags(frameset, "STANDARD_UNBIAS_MXU");
439  mos += stab_mos = cpl_frameset_count_tags(frameset, "STANDARD_UNBIAS_MOS");
440  lss += stab_lss = cpl_frameset_count_tags(frameset, "STANDARD_UNBIAS_LSS");
441  mxu += staf_mxu = cpl_frameset_count_tags(frameset, "STANDARD_UNFLAT_MXU");
442  mos += staf_mos = cpl_frameset_count_tags(frameset, "STANDARD_UNFLAT_MOS");
443  lss += staf_lss = cpl_frameset_count_tags(frameset, "STANDARD_UNFLAT_LSS");
444  mxu += sciu_mxu = cpl_frameset_count_tags(frameset, "UNMAPPED_SCI_MXU");
445  mos += sciu_mos = cpl_frameset_count_tags(frameset, "UNMAPPED_SCI_MOS");
446  lss += sciu_lss = cpl_frameset_count_tags(frameset, "UNMAPPED_SCI_LSS");
447  mxu += stau_mxu = cpl_frameset_count_tags(frameset, "UNMAPPED_STD_MXU");
448  mos += stau_mos = cpl_frameset_count_tags(frameset, "UNMAPPED_STD_MOS");
449  lss += stau_lss = cpl_frameset_count_tags(frameset, "UNMAPPED_STD_LSS");
450  mxu += scis_mxu = cpl_frameset_count_tags(frameset, "UNMAPPED_SKY_SCI_MXU");
451  mos += scis_mos = cpl_frameset_count_tags(frameset, "UNMAPPED_SKY_SCI_MOS");
452  lss += scis_lss = cpl_frameset_count_tags(frameset, "UNMAPPED_SKY_SCI_LSS");
453  mxu += stas_mxu = cpl_frameset_count_tags(frameset, "UNMAPPED_SKY_STD_MXU");
454  mos += stas_mos = cpl_frameset_count_tags(frameset, "UNMAPPED_SKY_STD_MOS");
455  lss += stas_lss = cpl_frameset_count_tags(frameset, "UNMAPPED_SKY_STD_LSS");
456 
457  nframes = mos + mxu + lss;
458 
459  if (nframes == 0) {
460  fors_extract_slits_exit("Missing input spectral frame");
461  }
462  if (nframes > 1) {
463  cpl_msg_error(recipe,
464  "Too many input spectral frames (%d > 1)", nframes);
465  fors_extract_slits_exit(NULL);
466  }
467 
468  if (lss)
469  fors_extract_slits_exit("Use this recipe just with MOS/MXU data.");
470 
471  if (mxu) {
472  slit_l = cpl_frameset_count_tags(frameset, "SLIT_LOCATION_MXU");
473  slit_d = cpl_frameset_count_tags(frameset, "SLIT_LOCATION_DETECT_MXU");
474  }
475  else {
476  slit_l = cpl_frameset_count_tags(frameset, "SLIT_LOCATION_MOS");
477  slit_d = cpl_frameset_count_tags(frameset, "SLIT_LOCATION_DETECT_MOS");
478  }
479 
480  nframes = slit_l + slit_d;
481 
482  if (nframes == 0) {
483  fors_extract_slits_exit("Missing input slit location table");
484  }
485  if (nframes > 1) {
486  cpl_msg_error(recipe,
487  "Too many input slit location tables (%d > 1)", nframes);
488  fors_extract_slits_exit(NULL);
489  }
490 
491  if (slit_l) {
492  if (mxu)
493  slit_location_tag = "SLIT_LOCATION_MXU";
494  else
495  slit_location_tag = "SLIT_LOCATION_MOS";
496  }
497  else {
498  if (mxu)
499  slit_location_tag = "SLIT_LOCATION_DETECT_MXU";
500  else
501  slit_location_tag = "SLIT_LOCATION_DETECT_MOS";
502  }
503 
504  if (mxu)
505  curv_coeff_tag = "CURV_COEFF_MXU";
506  else
507  curv_coeff_tag = "CURV_COEFF_MOS";
508 
509  if (lamp_mxu) {
510  input_tag = "LAMP_UNBIAS_MXU";
511  output_tag = "RECTIFIED_LAMP_MXU";
512  }
513  else if (lamp_mos) {
514  input_tag = "LAMP_UNBIAS_MOS";
515  output_tag = "RECTIFIED_LAMP_MOS";
516  }
517  else if (scib_mxu) {
518  input_tag = "SCIENCE_UNBIAS_MXU";
519  output_tag = "RECTIFIED_ALL_SCI_MXU";
520  }
521  else if (scib_mos) {
522  input_tag = "SCIENCE_UNBIAS_MOS";
523  output_tag = "RECTIFIED_ALL_SCI_MOS";
524  }
525  else if (scif_mxu) {
526  input_tag = "SCIENCE_UNFLAT_MXU";
527  output_tag = "RECTIFIED_ALL_SCI_MXU";
528  }
529  else if (scif_mos) {
530  input_tag = "SCIENCE_UNFLAT_MOS";
531  output_tag = "RECTIFIED_ALL_SCI_MOS";
532  }
533  else if (stab_mxu) {
534  input_tag = "STANDARD_UNBIAS_MXU";
535  output_tag = "RECTIFIED_ALL_STD_MXU";
536  }
537  else if (stab_mos) {
538  input_tag = "STANDARD_UNBIAS_MOS";
539  output_tag = "RECTIFIED_ALL_STD_MOS";
540  }
541  else if (staf_mxu) {
542  input_tag = "STANDARD_UNFLAT_MXU";
543  output_tag = "RECTIFIED_ALL_STD_MXU";
544  }
545  else if (staf_mos) {
546  input_tag = "STANDARD_UNFLAT_MOS";
547  output_tag = "RECTIFIED_ALL_STD_MOS";
548  }
549  else if (sciu_mxu) {
550  input_tag = "UNMAPPED_SCI_MXU";
551  output_tag = "RECTIFIED_SCI_MXU";
552  }
553  else if (sciu_mos) {
554  input_tag = "UNMAPPED_SCI_MOS";
555  output_tag = "RECTIFIED_SCI_MOS";
556  }
557  else if (stau_mxu) {
558  input_tag = "UNMAPPED_STD_MXU";
559  output_tag = "RECTIFIED_STD_MXU";
560  }
561  else if (stau_mos) {
562  input_tag = "UNMAPPED_STD_MOS";
563  output_tag = "RECTIFIED_STD_MOS";
564  }
565  else if (scis_mxu) {
566  input_tag = "UNMAPPED_SKY_SCI_MXU";
567  output_tag = "RECTIFIED_SKY_SCI_MXU";
568  }
569  else if (scis_mos) {
570  input_tag = "UNMAPPED_SKY_SCI_MOS";
571  output_tag = "RECTIFIED_SKY_SCI_MOS";
572  }
573  else if (stas_mxu) {
574  input_tag = "UNMAPPED_SKY_STD_MXU";
575  output_tag = "RECTIFIED_SKY_STD_MXU";
576  }
577  else if (stas_mos) {
578  input_tag = "UNMAPPED_SKY_STD_MOS";
579  output_tag = "RECTIFIED_SKY_STD_MOS";
580  }
581 
582  header = dfs_load_header(frameset, input_tag, 0);
583 
584  if (header == NULL)
585  fors_extract_slits_exit("Cannot load master flat frame header");
586 
587  if (mos)
588  maskslits = mos_load_slits_fors_mos(header, &nslits_out_det);
589  else
590  maskslits = mos_load_slits_fors_mxu(header);
591 
592  /*
593  * Check if all slits have the same X offset: in such case, abort!
594  */
595 
596  treat_as_lss = fors_mos_is_lss_like(maskslits, nslits_out_det);
597 
598  cpl_table_delete(maskslits); maskslits = NULL;
599 
600  if (treat_as_lss) {
601  cpl_msg_error(recipe, "All slits have the same offset: %.2f mm\n"
602  "The LSS data reduction strategy must be applied.",
603  mxpos);
604  fors_extract_slits_exit(NULL);
605  }
606 
607  if (!dfs_equal_keyword(frameset, "ESO INS GRIS1 ID"))
608  fors_extract_slits_exit("Input frames are not from the same grism");
609 
610  if (!dfs_equal_keyword(frameset, "ESO INS FILT1 ID"))
611  fors_extract_slits_exit("Input frames are not from the same filter");
612 
613  if (!dfs_equal_keyword(frameset, "ESO DET CHIP1 ID"))
614  fors_extract_slits_exit("Input frames are not from the same chip");
615 
616 
617  /*
618  * Get the reference wavelength and the rebin factor along the
619  * dispersion direction from the master flat frame
620  */
621 
622  instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME");
623  if (instrume == NULL)
624  fors_extract_slits_exit("Missing keyword INSTRUME in master "
625  "flat header");
626 
627  if (instrume[4] == '1')
628  snprintf(version, 80, "%s/%s", "fors1", VERSION);
629  if (instrume[4] == '2')
630  snprintf(version, 80, "%s/%s", "fors2", VERSION);
631 
632  reference = cpl_propertylist_get_double(header, "ESO INS GRIS1 WLEN");
633 
634  if (cpl_error_get_code() != CPL_ERROR_NONE)
635  fors_extract_slits_exit("Missing keyword ESO INS GRIS1 WLEN "
636  "in master flat frame header");
637 
638  if (reference < 3000.0) /* Perhaps in nanometers... */
639  reference *= 10;
640 
641  if (reference < 3000.0 || reference > 13000.0) {
642  cpl_msg_error(recipe, "Invalid central wavelength %.2f read from "
643  "keyword ESO INS GRIS1 WLEN in master flat header",
644  reference);
645  fors_extract_slits_exit(NULL);
646  }
647 
648  cpl_msg_info(recipe, "The central wavelength is: %.2f", reference);
649 
650  rebin = cpl_propertylist_get_int(header, "ESO DET WIN1 BINX");
651 
652  if (cpl_error_get_code() != CPL_ERROR_NONE)
653  fors_extract_slits_exit("Missing keyword ESO DET WIN1 BINX "
654  "in master flat header");
655 
656  if (rebin != 1) {
657  dispersion *= rebin;
658  cpl_msg_warning(recipe, "The rebin factor is %d, and therefore the "
659  "working dispersion used is %f A/pixel", rebin,
660  dispersion);
661  }
662 
663  cpl_msg_indent_less();
664  cpl_msg_info(recipe, "Load input frames...");
665  cpl_msg_indent_more();
666 
667  spectra = dfs_load_image(frameset, input_tag, CPL_TYPE_FLOAT, 0, 0);
668  if (spectra == NULL)
669  fors_extract_slits_exit("Cannot load input spectral frame");
670 
671  slits = dfs_load_table(frameset, slit_location_tag, 1);
672  if (slits == NULL)
673  fors_extract_slits_exit("Cannot load slits location table");
674 
675  polytraces = dfs_load_table(frameset, curv_coeff_tag, 1);
676  if (slits == NULL)
677  fors_extract_slits_exit("Cannot load spectral curvature table");
678 
679  spatial = mos_spatial_calibration(spectra, slits, polytraces, reference,
680  startwavelength, endwavelength,
681  dispersion, flux, NULL);
682 
683  cpl_image_delete(spectra); spectra = NULL;
684  cpl_table_delete(polytraces); polytraces = NULL;
685  cpl_table_delete(slits); slits = NULL;
686 
687  cpl_propertylist_delete(header); header = NULL;
688  header = cpl_propertylist_new();
689 
690  cpl_propertylist_update_double(header, "CRPIX2", 1.0);
691  cpl_propertylist_update_double(header, "CRVAL2", 1.0);
692  /* cpl_propertylist_update_double(header, "CDELT2", 1.0); */
693  cpl_propertylist_update_double(header, "CD1_1", 1.0);
694  cpl_propertylist_update_double(header, "CD1_2", 0.0);
695  cpl_propertylist_update_double(header, "CD2_1", 0.0);
696  cpl_propertylist_update_double(header, "CD2_2", 1.0);
697  cpl_propertylist_update_string(header, "CTYPE1", "LINEAR");
698  cpl_propertylist_update_string(header, "CTYPE2", "PIXEL");
699 
700  if (dfs_save_image(frameset, spatial, output_tag,
701  header, parlist, recipe, version))
702  fors_extract_slits_exit(NULL);
703 
704  cpl_image_delete(spatial); spatial = NULL;
705  cpl_propertylist_delete(header); header = NULL;
706 
707  return 0;
708 }
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
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
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_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
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
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
Definition: list.c:74
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