FORS Pipeline Reference Manual  5.0.9
fors_resample.c
1 /* $Id: fors_resample.c,v 1.11 2013-08-14 16:11:42 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-14 16:11:42 $
24  * $Revision: 1.11 $
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_resample_create(cpl_plugin *);
38 static int fors_resample_exec(cpl_plugin *);
39 static int fors_resample_destroy(cpl_plugin *);
40 static int fors_resample(cpl_parameterlist *, cpl_frameset *);
41 
42 static char fors_resample_description[] =
43 "This recipe is used to resample at constant wavelength step spatially\n"
44 "rectified spectra. The input frames are produced using either the recipe\n"
45 "fors_extract_slits in the case of MOS/MXU multi slit exposures, or the\n"
46 "recipes fors_remove_bias and fors_flatfield in the case of LSS or long-slit\n"
47 "like MOS/MXU data. Only in case of LSS or LSS-like data the SLIT_LOCATION\n"
48 "table is required in input. Please refer to the FORS Pipeline User's Manual\n"
49 "for more details.\n"
50 "\n"
51 "In the table below the MXU acronym can also be read as MOS and LSS, SCI\n"
52 "can be read as STD, and SCIENCE as STANDARD.\n\n"
53 "Input files:\n\n"
54 " DO category: Type: Explanation: Required:\n"
55 " LAMP_UNBIAS_MXU\n"
56 " or SCIENCE_UNBIAS_MXU\n"
57 " or SCIENCE_UNFLAT_MXU\n"
58 " or RECTIFIED_LAMP_MXU\n"
59 " or RECTIFIED_ALL_SCI_MXU\n"
60 " or RECTIFIED_SCI_MXU\n"
61 " or RECTIFIED_SKY_SCI_MXU Calib Frame to resample Y\n"
62 " DISP_COEFF_MXU\n"
63 " or DISP_COEFF_SCI_MXU Calib Dispersion coefficients Y\n"
64 " SLIT_LOCATION_MXU Calib Slit location table Y\n"
65 " GRISM_TABLE Calib Grism table .\n\n"
66 "Output files:\n\n"
67 " DO category: Data type: Explanation:\n"
68 " MAPPED_LAMP_MXU\n"
69 " or MAPPED_ALL_SCI_MXU\n"
70 " or MAPPED_SCI_MXU\n"
71 " or MAPPED_SKY_SCI_MXU FITS image Resampled spectra\n\n";
72 
73 #define fors_resample_exit(message) \
74 { \
75 if ((const char *)message != NULL) cpl_msg_error(recipe, message); \
76 cpl_image_delete(spectra); \
77 cpl_image_delete(mapped); \
78 cpl_table_delete(grism_table); \
79 cpl_table_delete(idscoeff); \
80 cpl_table_delete(slits); \
81 cpl_propertylist_delete(header); \
82 cpl_msg_indent_less(); \
83 return -1; \
84 }
85 
86 #define fors_resample_exit_memcheck(message) \
87 { \
88 if ((const char *)message != NULL) cpl_msg_info(recipe, message); \
89 printf("free spectra (%p)\n", spectra); \
90 cpl_image_delete(spectra); \
91 printf("free mapped (%p)\n", mapped); \
92 cpl_image_delete(mapped); \
93 printf("free grism_table (%p)\n", grism_table); \
94 cpl_table_delete(grism_table); \
95 printf("free idscoeff (%p)\n", idscoeff); \
96 cpl_table_delete(idscoeff); \
97 printf("free slits (%p)\n", slits); \
98 cpl_table_delete(slits); \
99 printf("free header (%p)\n", header); \
100 cpl_propertylist_delete(header); \
101 cpl_msg_indent_less(); \
102 return 0; \
103 }
104 
105 
117 int cpl_plugin_get_info(cpl_pluginlist *list)
118 {
119  cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe );
120  cpl_plugin *plugin = &recipe->interface;
121 
122  cpl_plugin_init(plugin,
123  CPL_PLUGIN_API,
124  FORS_BINARY_VERSION,
125  CPL_PLUGIN_TYPE_RECIPE,
126  "fors_resample",
127  "Resample input spectra at constant wavelength step",
128  fors_resample_description,
129  "Carlo Izzo",
130  PACKAGE_BUGREPORT,
131  "This file is currently part of the FORS Instrument Pipeline\n"
132  "Copyright (C) 2002-2010 European Southern Observatory\n\n"
133  "This program is free software; you can redistribute it and/or modify\n"
134  "it under the terms of the GNU General Public License as published by\n"
135  "the Free Software Foundation; either version 2 of the License, or\n"
136  "(at your option) any later version.\n\n"
137  "This program is distributed in the hope that it will be useful,\n"
138  "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
139  "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
140  "GNU General Public License for more details.\n\n"
141  "You should have received a copy of the GNU General Public License\n"
142  "along with this program; if not, write to the Free Software Foundation,\n"
143  "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n",
144  fors_resample_create,
145  fors_resample_exec,
146  fors_resample_destroy);
147 
148  cpl_pluginlist_append(list, plugin);
149 
150  return 0;
151 }
152 
153 
164 static int fors_resample_create(cpl_plugin *plugin)
165 {
166  cpl_recipe *recipe;
167  cpl_parameter *p;
168 
169  /*
170  * Check that the plugin is part of a valid recipe
171  */
172 
173  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
174  recipe = (cpl_recipe *)plugin;
175  else
176  return -1;
177 
178  /*
179  * Create the (empty) parameters list in the cpl_recipe object
180  */
181 
182  recipe->parameters = cpl_parameterlist_new();
183 
184  /*
185  * Dispersion
186  */
187 
188  p = cpl_parameter_new_value("fors.fors_resample.dispersion",
189  CPL_TYPE_DOUBLE,
190  "Expected spectral dispersion (Angstrom/pixel)",
191  "fors.fors_resample",
192  0.0);
193  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dispersion");
194  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
195  cpl_parameterlist_append(recipe->parameters, p);
196 
197  /*
198  * Start wavelength for spectral extraction
199  */
200 
201  p = cpl_parameter_new_value("fors.fors_resample.startwavelength",
202  CPL_TYPE_DOUBLE,
203  "Start wavelength in spectral extraction",
204  "fors.fors_resample",
205  0.0);
206  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "startwavelength");
207  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
208  cpl_parameterlist_append(recipe->parameters, p);
209 
210  /*
211  * End wavelength for spectral extraction
212  */
213 
214  p = cpl_parameter_new_value("fors.fors_resample.endwavelength",
215  CPL_TYPE_DOUBLE,
216  "End wavelength in spectral extraction",
217  "fors.fors_resample",
218  0.0);
219  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "endwavelength");
220  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
221  cpl_parameterlist_append(recipe->parameters, p);
222 
223  /*
224  * Flux conservation
225  */
226 
227  p = cpl_parameter_new_value("fors.fors_resample.flux",
228  CPL_TYPE_BOOL,
229  "Apply flux conservation",
230  "fors.fors_resample",
231  TRUE);
232  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "flux");
233  cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
234  cpl_parameterlist_append(recipe->parameters, p);
235 
236  return 0;
237 }
238 
239 
248 static int fors_resample_exec(cpl_plugin *plugin)
249 {
250  cpl_recipe *recipe;
251 
252  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
253  recipe = (cpl_recipe *)plugin;
254  else
255  return -1;
256 
257  return fors_resample(recipe->parameters, recipe->frames);
258 }
259 
260 
269 static int fors_resample_destroy(cpl_plugin *plugin)
270 {
271  cpl_recipe *recipe;
272 
273  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
274  recipe = (cpl_recipe *)plugin;
275  else
276  return -1;
277 
278  cpl_parameterlist_delete(recipe->parameters);
279 
280  return 0;
281 }
282 
283 
293 static int fors_resample(cpl_parameterlist *parlist,
294  cpl_frameset *frameset)
295 {
296 
297  const char *recipe = "fors_resample";
298 
299 
300  /*
301  * Input parameters
302  */
303 
304  double dispersion;
305  double startwavelength;
306  double endwavelength;
307  int flux;
308 
309  /*
310  * CPL objects
311  */
312 
313  cpl_image *spectra = NULL;
314  cpl_image *mapped = NULL;
315  cpl_table *grism_table = NULL;
316  cpl_table *maskslits = NULL;
317  cpl_table *slits = NULL;
318  cpl_table *idscoeff = NULL;
319  cpl_propertylist *header = NULL;
320 
321  /*
322  * Auxiliary variables
323  */
324 
325  char version[80];
326  const char *disp_coeff_tag;
327  const char *slit_location_tag;
328  const char *rectified_tag;
329  const char *mapped_tag;
330  int nframes;
331  int rebin;
332  double reference;
333  int treat_as_lss = 0;
334  int mxu, mos, lss;
335  int disp;
336  int dispsci;
337  int dispstd;
338  int sciall;
339  int stdall;
340  int scisky;
341  int stdsky;
342  int sci;
343  int std;
344  int lamp;
345 
346  char *instrume = NULL;
347 
348 
349  cpl_msg_set_indentation(2);
350 
351  /*
352  * Get configuration parameters
353  */
354 
355  cpl_msg_info(recipe, "Recipe %s configuration parameters:", recipe);
356  cpl_msg_indent_more();
357 
358  if (cpl_frameset_count_tags(frameset, "GRISM_TABLE") > 1)
359  fors_resample_exit("Too many in input: GRISM_TABLE");
360 
361  grism_table = dfs_load_table(frameset, "GRISM_TABLE", 1);
362 
363  dispersion = dfs_get_parameter_double(parlist,
364  "fors.fors_resample.dispersion", grism_table);
365 
366  if (dispersion <= 0.0)
367  fors_resample_exit("Invalid spectral dispersion value");
368 
369  startwavelength = dfs_get_parameter_double(parlist,
370  "fors.fors_resample.startwavelength", grism_table);
371  if (startwavelength > 1.0)
372  if (startwavelength < 3000.0 || startwavelength > 13000.0)
373  fors_resample_exit("Invalid wavelength");
374 
375  endwavelength = dfs_get_parameter_double(parlist,
376  "fors.fors_resample.endwavelength", grism_table);
377  if (endwavelength > 1.0) {
378  if (endwavelength < 3000.0 || endwavelength > 13000.0)
379  fors_resample_exit("Invalid wavelength");
380  if (startwavelength < 1.0)
381  fors_resample_exit("Invalid wavelength interval");
382  }
383 
384  if (startwavelength > 1.0)
385  if (endwavelength - startwavelength <= 0.0)
386  fors_resample_exit("Invalid wavelength interval");
387 
388  flux = dfs_get_parameter_bool(parlist, "fors.fors_resample.flux", NULL);
389 
390  cpl_table_delete(grism_table); grism_table = NULL;
391 
392  if (cpl_error_get_code())
393  fors_resample_exit("Failure reading the configuration parameters");
394 
395 
396  cpl_msg_indent_less();
397  cpl_msg_info(recipe, "Check input set-of-frames:");
398  cpl_msg_indent_more();
399 
400  mxu = cpl_frameset_count_tags(frameset, "DISP_COEFF_MXU");
401  mxu += cpl_frameset_count_tags(frameset, "DISP_COEFF_SCI_MXU");
402  mxu += cpl_frameset_count_tags(frameset, "DISP_COEFF_STD_MXU");
403  mos = cpl_frameset_count_tags(frameset, "DISP_COEFF_MOS");
404  mos += cpl_frameset_count_tags(frameset, "DISP_COEFF_SCI_MOS");
405  mos += cpl_frameset_count_tags(frameset, "DISP_COEFF_STD_MOS");
406  lss = cpl_frameset_count_tags(frameset, "DISP_COEFF_LSS");
407  lss += cpl_frameset_count_tags(frameset, "DISP_COEFF_SCI_LSS");
408  lss += cpl_frameset_count_tags(frameset, "DISP_COEFF_STD_LSS");
409 
410  nframes = mos + mxu + lss;
411 
412  if (nframes == 0) {
413  fors_resample_exit("Missing dispersion coefficients table");
414  }
415  if (nframes > 1) {
416  cpl_msg_error(recipe,
417  "Too many input dispersion coefficients tables (%d > 1)",
418  nframes);
419  fors_resample_exit(NULL);
420  }
421 
422  disp = cpl_frameset_count_tags(frameset, "DISP_COEFF_MXU");
423  disp += cpl_frameset_count_tags(frameset, "DISP_COEFF_MOS");
424  disp += cpl_frameset_count_tags(frameset, "DISP_COEFF_LSS");
425  dispsci = cpl_frameset_count_tags(frameset, "DISP_COEFF_SCI_MXU");
426  dispsci += cpl_frameset_count_tags(frameset, "DISP_COEFF_SCI_MOS");
427  dispsci += cpl_frameset_count_tags(frameset, "DISP_COEFF_SCI_LSS");
428  dispstd = cpl_frameset_count_tags(frameset, "DISP_COEFF_STD_MXU");
429  dispstd += cpl_frameset_count_tags(frameset, "DISP_COEFF_STD_MOS");
430  dispstd += cpl_frameset_count_tags(frameset, "DISP_COEFF_STD_LSS");
431 
432  if (mxu) {
433  slit_location_tag = "SLIT_LOCATION_MXU";
434  if (disp)
435  disp_coeff_tag = "DISP_COEFF_MXU";
436  else if (dispsci)
437  disp_coeff_tag = "DISP_COEFF_SCI_MXU";
438  else
439  disp_coeff_tag = "DISP_COEFF_STD_MXU";
440  }
441  else if (mos) {
442  slit_location_tag = "SLIT_LOCATION_MOS";
443  if (disp)
444  disp_coeff_tag = "DISP_COEFF_MOS";
445  else if (dispsci)
446  disp_coeff_tag = "DISP_COEFF_SCI_MOS";
447  else
448  disp_coeff_tag = "DISP_COEFF_STD_MOS";
449  }
450  else {
451  slit_location_tag = "SLIT_LOCATION_LSS";
452  if (disp)
453  disp_coeff_tag = "DISP_COEFF_LSS";
454  else if (dispsci)
455  disp_coeff_tag = "DISP_COEFF_SCI_LSS";
456  else
457  disp_coeff_tag = "DISP_COEFF_STD_LSS";
458  }
459 
460  header = dfs_load_header(frameset, disp_coeff_tag, 0);
461 
462  if (header == NULL)
463  fors_resample_exit("Cannot load dispersion coefficients table header");
464 
465  if (mos || mxu) {
466  int nslits_out_det = 0;
467 
468  if (mos)
469  maskslits = mos_load_slits_fors_mos(header, &nslits_out_det);
470  else
471  maskslits = mos_load_slits_fors_mxu(header);
472 
473  /*
474  * Check if all slits have the same X offset.
475  */
476 
477  treat_as_lss = fors_mos_is_lss_like(maskslits, nslits_out_det);
478 
479  cpl_table_delete(maskslits); maskslits = NULL;
480  }
481 
482  cpl_propertylist_delete(header); header = NULL;
483 
484  if (mxu) {
485  if (treat_as_lss) {
486  sciall = cpl_frameset_count_tags(frameset, "SCIENCE_UNFLAT_MXU");
487  stdall = cpl_frameset_count_tags(frameset, "STANDARD_UNFLAT_MXU");
488  scisky = 0;
489  stdsky = 0;
490  sci = cpl_frameset_count_tags(frameset, "SCIENCE_UNBIAS_MXU");
491  std = cpl_frameset_count_tags(frameset, "STANDARD_UNBIAS_MXU");
492  lamp = cpl_frameset_count_tags(frameset, "LAMP_UNBIAS_MXU");
493  }
494  else {
495  sciall = cpl_frameset_count_tags(frameset, "RECTIFIED_ALL_SCI_MXU");
496  stdall = cpl_frameset_count_tags(frameset, "RECTIFIED_ALL_STD_MXU");
497  scisky = cpl_frameset_count_tags(frameset, "RECTIFIED_SKY_SCI_MXU");
498  stdsky = cpl_frameset_count_tags(frameset, "RECTIFIED_SKY_STD_MXU");
499  sci = cpl_frameset_count_tags(frameset, "RECTIFIED_SCI_MXU");
500  std = cpl_frameset_count_tags(frameset, "RECTIFIED_STD_MXU");
501  lamp = cpl_frameset_count_tags(frameset, "RECTIFIED_LAMP_MXU");
502  }
503  }
504  else if (mos) {
505  if (treat_as_lss) {
506  sciall = cpl_frameset_count_tags(frameset, "SCIENCE_UNFLAT_MOS");
507  stdall = cpl_frameset_count_tags(frameset, "STANDARD_UNFLAT_MOS");
508  scisky = 0;
509  stdsky = 0;
510  sci = cpl_frameset_count_tags(frameset, "SCIENCE_UNBIAS_MOS");
511  std = cpl_frameset_count_tags(frameset, "STANDARD_UNBIAS_MOS");
512  lamp = cpl_frameset_count_tags(frameset, "LAMP_UNBIAS_MOS");
513  }
514  else {
515  sciall = cpl_frameset_count_tags(frameset, "RECTIFIED_ALL_SCI_MOS");
516  stdall = cpl_frameset_count_tags(frameset, "RECTIFIED_ALL_STD_MOS");
517  scisky = cpl_frameset_count_tags(frameset, "RECTIFIED_SKY_SCI_MOS");
518  stdsky = cpl_frameset_count_tags(frameset, "RECTIFIED_SKY_STD_MOS");
519  sci = cpl_frameset_count_tags(frameset, "RECTIFIED_SCI_MOS");
520  std = cpl_frameset_count_tags(frameset, "RECTIFIED_STD_MOS");
521  lamp = cpl_frameset_count_tags(frameset, "RECTIFIED_LAMP_MOS");
522  }
523  }
524  else {
525  sciall = cpl_frameset_count_tags(frameset, "SCIENCE_UNFLAT_LSS");
526  stdall = cpl_frameset_count_tags(frameset, "STANDARD_UNFLAT_LSS");
527  scisky = 0;
528  stdsky = 0;
529  sci = cpl_frameset_count_tags(frameset, "SCIENCE_UNBIAS_LSS");
530  std = cpl_frameset_count_tags(frameset, "STANDARD_UNBIAS_LSS");
531  lamp = cpl_frameset_count_tags(frameset, "LAMP_UNBIAS_LSS");
532  }
533 
534  nframes = sciall + stdall + scisky + stdsky + sci + std + lamp;
535 
536  if (nframes == 0)
537  fors_resample_exit("Missing input spectral frame");
538 
539  if (nframes > 1) {
540  cpl_msg_error(recipe, "Too many input spectral frames (%d > 1)",
541  nframes);
542  fors_resample_exit(NULL);
543  }
544 
545  if (sciall) {
546  if (mxu) {
547  if (treat_as_lss) {
548  rectified_tag = "SCIENCE_UNFLAT_MXU";
549  mapped_tag = "MAPPED_ALL_SCI_MXU";
550  }
551  else {
552  rectified_tag = "RECTIFIED_ALL_SCI_MXU";
553  mapped_tag = "MAPPED_ALL_SCI_MXU";
554  }
555  }
556  else if (mos) {
557  if (treat_as_lss) {
558  rectified_tag = "SCIENCE_UNFLAT_MOS";
559  mapped_tag = "MAPPED_ALL_SCI_MOS";
560  }
561  else {
562  rectified_tag = "RECTIFIED_ALL_SCI_MOS";
563  mapped_tag = "MAPPED_ALL_SCI_MOS";
564  }
565  }
566  else {
567  rectified_tag = "SCIENCE_UNFLAT_LSS";
568  mapped_tag = "MAPPED_ALL_SCI_LSS";
569  }
570  }
571  else if (stdall) {
572  if (mxu) {
573  if (treat_as_lss) {
574  rectified_tag = "STANDARD_UNFLAT_MXU";
575  mapped_tag = "MAPPED_ALL_STD_MXU";
576  }
577  else {
578  rectified_tag = "RECTIFIED_ALL_STD_MXU";
579  mapped_tag = "MAPPED_ALL_STD_MXU";
580  }
581  }
582  else if (mos) {
583  if (treat_as_lss) {
584  rectified_tag = "STANDARD_UNFLAT_MOS";
585  mapped_tag = "MAPPED_ALL_STD_MOS";
586  }
587  else {
588  rectified_tag = "RECTIFIED_ALL_STD_MOS";
589  mapped_tag = "MAPPED_ALL_STD_MOS";
590  }
591  }
592  else {
593  rectified_tag = "STANDARD_UNFLAT_LSS";
594  mapped_tag = "MAPPED_ALL_STD_LSS";
595  }
596  }
597  else if (scisky) {
598  if (mxu) {
599  rectified_tag = "RECTIFIED_SKY_SCI_MXU";
600  mapped_tag = "MAPPED_SKY_SCI_MXU";
601  }
602  else {
603  rectified_tag = "RECTIFIED_SKY_SCI_MOS";
604  mapped_tag = "MAPPED_SKY_SCI_MOS";
605  }
606  }
607  else if (stdsky) {
608  if (mxu) {
609  rectified_tag = "RECTIFIED_SKY_STD_MXU";
610  mapped_tag = "MAPPED_SKY_STD_MXU";
611  }
612  else {
613  rectified_tag = "RECTIFIED_SKY_STD_MOS";
614  mapped_tag = "MAPPED_SKY_STD_MOS";
615  }
616  }
617  else if (sci) {
618  if (mxu) {
619  if (treat_as_lss) {
620  rectified_tag = "SCIENCE_UNBIAS_MXU";
621  mapped_tag = "MAPPED_ALL_SCI_MXU";
622  }
623  else {
624  rectified_tag = "RECTIFIED_SCI_MXU";
625  mapped_tag = "MAPPED_SCI_MXU";
626  }
627  }
628  else if (mos) {
629  if (treat_as_lss) {
630  rectified_tag = "SCIENCE_UNBIAS_MOS";
631  mapped_tag = "MAPPED_ALL_SCI_MOS";
632  }
633  else {
634  rectified_tag = "RECTIFIED_SCI_MOS";
635  mapped_tag = "MAPPED_SCI_MOS";
636  }
637  }
638  else {
639  rectified_tag = "SCIENCE_UNBIAS_LSS";
640  mapped_tag = "MAPPED_ALL_SCI_LSS";
641  }
642  }
643  else if (std) {
644  if (mxu) {
645  if (treat_as_lss) {
646  rectified_tag = "STANDARD_UNBIAS_MXU";
647  mapped_tag = "MAPPED_ALL_STD_MXU";
648  }
649  else {
650  rectified_tag = "RECTIFIED_STD_MXU";
651  mapped_tag = "MAPPED_STD_MXU";
652  }
653  }
654  else if (mos) {
655  if (treat_as_lss) {
656  rectified_tag = "STANDARD_UNBIAS_MOS";
657  mapped_tag = "MAPPED_ALL_STD_MOS";
658  }
659  else {
660  rectified_tag = "RECTIFIED_STD_MOS";
661  mapped_tag = "MAPPED_STD_MOS";
662  }
663  }
664  else {
665  rectified_tag = "STANDARD_UNBIAS_LSS";
666  mapped_tag = "MAPPED_ALL_STD_LSS";
667  }
668  }
669  else if (lamp) {
670  if (mxu) {
671  if (treat_as_lss) {
672  rectified_tag = "LAMP_UNBIAS_MXU";
673  mapped_tag = "MAPPED_LAMP_MXU";
674  }
675  else {
676  rectified_tag = "RECTIFIED_LAMP_MXU";
677  mapped_tag = "MAPPED_LAMP_MXU";
678  }
679  }
680  else if (mos) {
681  if (treat_as_lss) {
682  rectified_tag = "LAMP_UNBIAS_MOS";
683  mapped_tag = "MAPPED_LAMP_MOS";
684  }
685  else {
686  rectified_tag = "RECTIFIED_LAMP_MOS";
687  mapped_tag = "MAPPED_LAMP_MOS";
688  }
689  }
690  else {
691  rectified_tag = "LAMP_UNBIAS_LSS";
692  mapped_tag = "MAPPED_LAMP_LSS";
693  }
694  }
695 
696  header = dfs_load_header(frameset, rectified_tag, 0);
697 
698  if (header == NULL)
699  fors_resample_exit("Cannot load spectral frame header");
700 
701 
702  if (!dfs_equal_keyword(frameset, "ESO INS GRIS1 ID"))
703  cpl_msg_warning(cpl_func,"Input frames are not from the same grism");
704 
705  if (!dfs_equal_keyword(frameset, "ESO INS FILT1 ID"))
706  cpl_msg_warning(cpl_func,"Input frames are not from the same filter");
707 
708  if (!dfs_equal_keyword(frameset, "ESO DET CHIP1 ID"))
709  cpl_msg_warning(cpl_func,"Input frames are not from the same chip");
710 
711 
712  /*
713  * Get the reference wavelength and the rebin factor along the
714  * dispersion direction from the reference frame
715  */
716 
717  instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME");
718  if (instrume == NULL)
719  fors_resample_exit("Missing keyword INSTRUME in reference frame "
720  "header");
721 
722  if (instrume[4] == '1')
723  snprintf(version, 80, "%s/%s", "fors1", VERSION);
724  if (instrume[4] == '2')
725  snprintf(version, 80, "%s/%s", "fors2", VERSION);
726 
727  reference = cpl_propertylist_get_double(header, "ESO INS GRIS1 WLEN");
728 
729  if (cpl_error_get_code() != CPL_ERROR_NONE)
730  fors_resample_exit("Missing keyword ESO INS GRIS1 WLEN "
731  "in reference frame header");
732 
733  if (reference < 3000.0) /* Perhaps in nanometers... */
734  reference *= 10;
735 
736  if (reference < 3000.0 || reference > 13000.0) {
737  cpl_msg_error(recipe, "Invalid central wavelength %.2f read from "
738  "keyword ESO INS GRIS1 WLEN in reference frame header",
739  reference);
740  fors_resample_exit(NULL);
741  }
742 
743  cpl_msg_info(recipe, "The central wavelength is: %.2f", reference);
744 
745  rebin = cpl_propertylist_get_int(header, "ESO DET WIN1 BINX");
746 
747  if (cpl_error_get_code() != CPL_ERROR_NONE)
748  fors_resample_exit("Missing keyword ESO DET WIN1 BINX "
749  "in reference frame header");
750 
751  if (rebin != 1) {
752  dispersion *= rebin;
753  cpl_msg_warning(recipe, "The rebin factor is %d, and therefore the "
754  "working dispersion used is %f A/pixel", rebin,
755  dispersion);
756  }
757 
758 
759  cpl_msg_indent_less();
760  cpl_msg_info(recipe, "Load input frames...");
761  cpl_msg_indent_more();
762 
763  spectra = dfs_load_image(frameset, rectified_tag, CPL_TYPE_FLOAT, 0, 0);
764  if (spectra == NULL)
765  fors_resample_exit("Cannot load input spectral frame");
766 
767  idscoeff = dfs_load_table(frameset, disp_coeff_tag, 1);
768  if (idscoeff == NULL)
769  fors_resample_exit("Cannot load dispersion solution table");
770 
771  if (lss || treat_as_lss) {
772  int first_row, last_row, ylow, yhig, nx;
773  cpl_image *dummy;
774 
775  slits = dfs_load_table(frameset, slit_location_tag, 1);
776  if (slits == NULL)
777  fors_resample_exit("Cannot load slit location table");
778 
779  first_row = cpl_table_get_double(slits, "ybottom", 0, NULL);
780  last_row = cpl_table_get_double(slits, "ytop", 0, NULL);
781 
782  ylow = first_row + 1;
783  yhig = last_row + 1;
784 
785  nx = cpl_image_get_size_x(spectra);
786 
787  dummy = cpl_image_extract(spectra, 1, ylow, nx, yhig);
788  cpl_image_delete(spectra); spectra = dummy;
789  }
790 
791  cpl_msg_indent_less();
792  cpl_msg_info(recipe, "Spectral resampling...");
793  cpl_msg_indent_more();
794 
795  mapped = mos_wavelength_calibration(spectra, reference,
796  startwavelength, endwavelength,
797  dispersion, idscoeff, flux);
798 
799  cpl_table_delete(idscoeff); idscoeff = NULL;
800  cpl_image_delete(spectra); spectra = NULL;
801 
802  cpl_propertylist_update_double(header, "CRPIX1", 1.0);
803  cpl_propertylist_update_double(header, "CRPIX2", 1.0);
804  cpl_propertylist_update_double(header, "CRVAL1",
805  startwavelength + dispersion/2);
806  cpl_propertylist_update_double(header, "CRVAL2", 1.0);
807  /* cpl_propertylist_update_double(header, "CDELT1", dispersion);
808  cpl_propertylist_update_double(header, "CDELT2", 1.0); */
809  cpl_propertylist_update_double(header, "CD1_1", dispersion);
810  cpl_propertylist_update_double(header, "CD1_2", 0.0);
811  cpl_propertylist_update_double(header, "CD2_1", 0.0);
812  cpl_propertylist_update_double(header, "CD2_2", 1.0);
813  cpl_propertylist_update_string(header, "CTYPE1", "LINEAR");
814  cpl_propertylist_update_string(header, "CTYPE2", "PIXEL");
815 
816  if (dfs_save_image(frameset, mapped, mapped_tag,
817  header, parlist, recipe, version))
818  fors_resample_exit(NULL);
819 
820  cpl_image_delete(mapped); mapped = NULL;
821  cpl_propertylist_delete(header); header = NULL;
822 
823  return 0;
824 }
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:860
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:964
cpl_table * mos_load_slits_fors_mxu(cpl_propertylist *header)
Create slit location table from FITS header of FORS2-MXU data.
Definition: moses.c:14858
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:9697
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:15098
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:701
int dfs_equal_keyword(cpl_frameset *frameset, const char *keyword)
Saving table data of given category.
Definition: fors_dfs.c:1683
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:1451
cpl_table * dfs_load_table(cpl_frameset *frameset, const char *category, int ext)
Loading table data of given category.
Definition: fors_dfs.c:916
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:504