FORS Pipeline Reference Manual  5.0.9
fors_subtract_sky_lss.c
1 /* $Id: fors_subtract_sky_lss.c,v 1.6 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.6 $
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_subtract_sky_lss_create(cpl_plugin *);
38 static int fors_subtract_sky_lss_exec(cpl_plugin *);
39 static int fors_subtract_sky_lss_destroy(cpl_plugin *);
40 static int fors_subtract_sky_lss(cpl_parameterlist *, cpl_frameset *);
41 
42 static char fors_subtract_sky_lss_description[] =
43 "This recipe is used to subtract the sky from wavelength calibrated\n"
44 "scientific spectra produced by the recipe fors_resample. A simple median\n"
45 "signal level is subtracted from each image column.\n"
46 "In the table below the MXU acronym can be read alternatively as MOS\n"
47 "and LSS, depending on the instrument mode of the input data. The acronym\n"
48 "SCI may be read STD in case of standard stars observations.\n"
49 "Note that only LSS or LSS-like MOS/MXU data are to be processed by this\n"
50 "recipe.\n\n"
51 "Input files:\n\n"
52 " DO category: Type: Explanation: Required:\n"
53 " MAPPED_ALL_SCI_MXU Raw Scientific exposure Y\n\n"
54 "Output files:\n\n"
55 " DO category: Data type: Explanation:\n"
56 " MAPPED_SCI_MXU FITS image Rectified scientific spectra\n"
57 " MAPPED_SKY_SCI_MXU FITS image Rectified sky spectra\n\n";
58 
59 #define fors_subtract_sky_lss_exit(message) \
60 { \
61 if ((const char *)message != NULL) cpl_msg_error(recipe, message); \
62 cpl_image_delete(skymap); \
63 cpl_image_delete(sky); \
64 cpl_image_delete(spectra); \
65 cpl_propertylist_delete(header); \
66 cpl_msg_indent_less(); \
67 return -1; \
68 }
69 
70 
71 #define fors_subtract_sky_lss_exit_memcheck(message) \
72 { \
73 if ((const char *)message != NULL) cpl_msg_info(recipe, message); \
74 cpl_image_delete(skymap); \
75 cpl_image_delete(sky); \
76 cpl_image_delete(spectra); \
77 cpl_propertylist_delete(header); \
78 cpl_msg_indent_less(); \
79 return 0; \
80 }
81 
82 
94 int cpl_plugin_get_info(cpl_pluginlist *list)
95 {
96  cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe );
97  cpl_plugin *plugin = &recipe->interface;
98 
99  cpl_plugin_init(plugin,
100  CPL_PLUGIN_API,
101  FORS_BINARY_VERSION,
102  CPL_PLUGIN_TYPE_RECIPE,
103  "fors_subtract_sky_lss",
104  "Subtract sky from calibrated long slit exposure",
105  fors_subtract_sky_lss_description,
106  "Carlo Izzo",
107  PACKAGE_BUGREPORT,
108  "This file is currently part of the FORS Instrument Pipeline\n"
109  "Copyright (C) 2002-2010 European Southern Observatory\n\n"
110  "This program is free software; you can redistribute it and/or modify\n"
111  "it under the terms of the GNU General Public License as published by\n"
112  "the Free Software Foundation; either version 2 of the License, or\n"
113  "(at your option) any later version.\n\n"
114  "This program is distributed in the hope that it will be useful,\n"
115  "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
116  "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
117  "GNU General Public License for more details.\n\n"
118  "You should have received a copy of the GNU General Public License\n"
119  "along with this program; if not, write to the Free Software Foundation,\n"
120  "Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n",
121  fors_subtract_sky_lss_create,
122  fors_subtract_sky_lss_exec,
123  fors_subtract_sky_lss_destroy);
124 
125  cpl_pluginlist_append(list, plugin);
126 
127  return 0;
128 }
129 
130 
141 static int fors_subtract_sky_lss_create(cpl_plugin *plugin)
142 {
143  cpl_recipe *recipe;
144 /* Uncomment in case parameters are defined
145  cpl_parameter *p;
146 */
147 
148  /*
149  * Check that the plugin is part of a valid recipe
150  */
151 
152  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
153  recipe = (cpl_recipe *)plugin;
154  else
155  return -1;
156 
157  /*
158  * Create the parameters list in the cpl_recipe object
159  */
160 
161  recipe->parameters = cpl_parameterlist_new();
162 
163  return 0;
164 }
165 
166 
175 static int fors_subtract_sky_lss_exec(cpl_plugin *plugin)
176 {
177  cpl_recipe *recipe;
178 
179  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
180  recipe = (cpl_recipe *)plugin;
181  else
182  return -1;
183 
184  return fors_subtract_sky_lss(recipe->parameters, recipe->frames);
185 }
186 
187 
196 static int fors_subtract_sky_lss_destroy(cpl_plugin *plugin)
197 {
198  cpl_recipe *recipe;
199 
200  if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
201  recipe = (cpl_recipe *)plugin;
202  else
203  return -1;
204 
205  cpl_parameterlist_delete(recipe->parameters);
206 
207  return 0;
208 }
209 
210 
220 static int fors_subtract_sky_lss(cpl_parameterlist *parlist,
221  cpl_frameset *frameset)
222 {
223 
224  const char *recipe = "fors_subtract_sky_lss";
225 
226 
227  /*
228  * Input parameters (none)
229  */
230 
231  /*
232  * CPL objects
233  */
234 
235  cpl_image *spectra = NULL;
236  cpl_image *skymap = NULL;
237  cpl_image *sky = NULL;
238  cpl_table *maskslits = NULL;
239 
240  cpl_propertylist *header = NULL;
241 
242  /*
243  * Auxiliary variables
244  */
245 
246  char version[80];
247  char *instrume = NULL;
248  const char *mapped_science_tag;
249  const char *mapped_science_sky_tag;
250  const char *mapped_sky_tag;
251  int mxu, mos, lss;
252  int treat_as_lss = 0;
253  int nscience;
254  double mxpos;
255  int nx, ny;
256  int standard;
257  float *data;
258  float *sdata;
259  int i, j;
260 
261 
262  snprintf(version, 80, "%s-%s", PACKAGE, PACKAGE_VERSION);
263 
264  cpl_msg_set_indentation(2);
265 
266 
267  /*
268  * Get configuration parameters (none)
269  */
270 
271  /*
272  * Check input set-of-frames
273  */
274 
275  cpl_msg_indent_less();
276  cpl_msg_info(recipe, "Check input set-of-frames:");
277  cpl_msg_indent_more();
278 
279  mxu = cpl_frameset_count_tags(frameset, "MAPPED_ALL_SCI_MXU");
280  mos = cpl_frameset_count_tags(frameset, "MAPPED_ALL_SCI_MOS");
281  lss = cpl_frameset_count_tags(frameset, "MAPPED_ALL_SCI_LSS");
282  standard = 0;
283 
284  if (mxu + mos + lss == 0) {
285  mxu = cpl_frameset_count_tags(frameset, "MAPPED_ALL_STD_MXU");
286  mos = cpl_frameset_count_tags(frameset, "MAPPED_ALL_STD_MOS");
287  lss = cpl_frameset_count_tags(frameset, "MAPPED_ALL_STD_LSS");
288  standard = 1;
289  }
290 
291  if (mxu + mos + lss == 0)
292  fors_subtract_sky_lss_exit("Missing input scientific frame");
293 
294  nscience = mxu + mos + lss;
295 
296  if (nscience > 1)
297  fors_subtract_sky_lss_exit("More than one scientific frame in input");
298 
299  if (mxu) {
300  if (standard) {
301  cpl_msg_info(recipe, "MXU data found");
302  mapped_science_tag = "MAPPED_STD_MXU";
303  mapped_science_sky_tag = "MAPPED_ALL_STD_MXU";
304  mapped_sky_tag = "MAPPED_SKY_STD_MXU";
305  }
306  else {
307  cpl_msg_info(recipe, "MXU data found");
308  mapped_science_tag = "MAPPED_SCI_MXU";
309  mapped_science_sky_tag = "MAPPED_ALL_SCI_MXU";
310  mapped_sky_tag = "MAPPED_SKY_SCI_MXU";
311  }
312  }
313 
314  if (lss) {
315  if (standard) {
316  cpl_msg_info(recipe, "LSS data found");
317  mapped_science_tag = "MAPPED_STD_LSS";
318  mapped_science_sky_tag = "MAPPED_ALL_STD_LSS";
319  mapped_sky_tag = "MAPPED_SKY_STD_LSS";
320  }
321  else {
322  cpl_msg_info(recipe, "LSS data found");
323  mapped_science_tag = "MAPPED_SCI_LSS";
324  mapped_science_sky_tag = "MAPPED_ALL_SCI_LSS";
325  mapped_sky_tag = "MAPPED_SKY_SCI_LSS";
326  }
327  }
328 
329  if (mos) {
330  if (standard) {
331  cpl_msg_info(recipe, "MOS data found");
332  mapped_science_tag = "MAPPED_STD_MOS";
333  mapped_science_sky_tag = "MAPPED_ALL_STD_MOS";
334  mapped_sky_tag = "MAPPED_SKY_STD_MOS";
335  }
336  else {
337  cpl_msg_info(recipe, "MOS data found");
338  mapped_science_tag = "MAPPED_SCI_MOS";
339  mapped_science_sky_tag = "MAPPED_ALL_SCI_MOS";
340  mapped_sky_tag = "MAPPED_SKY_SCI_MOS";
341  }
342  }
343 
344  /*
345  * Loading input data
346  */
347 
348  cpl_msg_info(recipe, "Load mapped scientific exposure...");
349  cpl_msg_indent_more();
350 
351  spectra = dfs_load_image(frameset, mapped_science_sky_tag,
352  CPL_TYPE_FLOAT, 0, 0);
353 
354  if (spectra == NULL)
355  fors_subtract_sky_lss_exit("Cannot load input frame");
356 
357  header = dfs_load_header(frameset, mapped_science_sky_tag, 0);
358 
359  if (header == NULL)
360  fors_subtract_sky_lss_exit("Cannot load input frame header");
361 
362  instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME");
363  if (instrume == NULL)
364  fors_subtract_sky_lss_exit("Missing keyword INSTRUME in scientific header");
365  instrume = cpl_strdup(instrume);
366 
367  if (instrume[4] == '1')
368  snprintf(version, 80, "%s/%s", "fors1", VERSION);
369  if (instrume[4] == '2')
370  snprintf(version, 80, "%s/%s", "fors2", VERSION);
371 
372  cpl_free(instrume); instrume = NULL;
373 
374  cpl_msg_indent_less();
375 
376  if (mos || mxu) {
377  int nslits_out_det = 0;
378 
379  if (mos)
380  maskslits = mos_load_slits_fors_mos(header, &nslits_out_det);
381  else
382  maskslits = mos_load_slits_fors_mxu(header);
383 
384  /*
385  * Check if all slits have the same X offset: in such case,
386  * treat the observation as a long-slit one!
387  */
388 
389  treat_as_lss = fors_mos_is_lss_like(maskslits, nslits_out_det);
390 
391  cpl_table_delete(maskslits); maskslits = NULL;
392 
393  if (treat_as_lss)
394  cpl_msg_info(recipe, "All MOS slits have the same offset: %.2f\n"
395  "The LSS data reduction strategy is applied.",
396  mxpos);
397  else
398  fors_subtract_sky_lss_exit("This recipe can only be used "
399  "with LSS-like data");
400  }
401 
402  nx = cpl_image_get_size_x(spectra);
403  ny = cpl_image_get_size_y(spectra);
404 
405  skymap = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
406  sky = cpl_image_collapse_median_create(spectra, 0, 0, 1);
407 
408  data = cpl_image_get_data(skymap);
409 
410  for (i = 0; i < ny; i++) {
411  sdata = cpl_image_get_data(sky);
412  for (j = 0; j < nx; j++) {
413  *data++ = *sdata++;
414  }
415  }
416 
417  cpl_image_delete(sky); sky = NULL;
418  cpl_image_subtract(spectra, skymap);
419 
420  if (dfs_save_image(frameset, skymap, mapped_sky_tag, header,
421  parlist, recipe, version))
422  fors_subtract_sky_lss_exit(NULL);
423 
424  cpl_image_delete(skymap); skymap = NULL;
425 
426  if (dfs_save_image(frameset, spectra, mapped_science_tag, header,
427  parlist, recipe, version))
428  fors_subtract_sky_lss_exit(NULL);
429 
430  cpl_image_delete(spectra); spectra = NULL;
431 
432  cpl_propertylist_delete(header); header = NULL;
433 
434  if (cpl_error_get_code()) {
435  cpl_msg_error(cpl_error_get_where(), "%s", cpl_error_get_message());
436  fors_subtract_sky_lss_exit(NULL);
437  }
438  else
439  return 0;
440 }
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_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_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
Definition: list.c:74