FORS Pipeline Reference Manual  4.12.5
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 (message) 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 (message) 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 nslits;
254  int nscience;
255  double *xpos;
256  double mxpos;
257  int nx, ny;
258  int standard;
259  float *data;
260  float *sdata;
261  int i, j;
262 
263 
264  snprintf(version, 80, "%s-%s", PACKAGE, PACKAGE_VERSION);
265 
266  cpl_msg_set_indentation(2);
267 
268 
269  /*
270  * Get configuration parameters (none)
271  */
272 
273  /*
274  * Check input set-of-frames
275  */
276 
277  cpl_msg_indent_less();
278  cpl_msg_info(recipe, "Check input set-of-frames:");
279  cpl_msg_indent_more();
280 
281  mxu = cpl_frameset_count_tags(frameset, "MAPPED_ALL_SCI_MXU");
282  mos = cpl_frameset_count_tags(frameset, "MAPPED_ALL_SCI_MOS");
283  lss = cpl_frameset_count_tags(frameset, "MAPPED_ALL_SCI_LSS");
284  standard = 0;
285 
286  if (mxu + mos + lss == 0) {
287  mxu = cpl_frameset_count_tags(frameset, "MAPPED_ALL_STD_MXU");
288  mos = cpl_frameset_count_tags(frameset, "MAPPED_ALL_STD_MOS");
289  lss = cpl_frameset_count_tags(frameset, "MAPPED_ALL_STD_LSS");
290  standard = 1;
291  }
292 
293  if (mxu + mos + lss == 0)
294  fors_subtract_sky_lss_exit("Missing input scientific frame");
295 
296  nscience = mxu + mos + lss;
297 
298  if (nscience > 1)
299  fors_subtract_sky_lss_exit("More than one scientific frame in input");
300 
301  if (mxu) {
302  if (standard) {
303  cpl_msg_info(recipe, "MXU data found");
304  mapped_science_tag = "MAPPED_STD_MXU";
305  mapped_science_sky_tag = "MAPPED_ALL_STD_MXU";
306  mapped_sky_tag = "MAPPED_SKY_STD_MXU";
307  }
308  else {
309  cpl_msg_info(recipe, "MXU data found");
310  mapped_science_tag = "MAPPED_SCI_MXU";
311  mapped_science_sky_tag = "MAPPED_ALL_SCI_MXU";
312  mapped_sky_tag = "MAPPED_SKY_SCI_MXU";
313  }
314  }
315 
316  if (lss) {
317  if (standard) {
318  cpl_msg_info(recipe, "LSS data found");
319  mapped_science_tag = "MAPPED_STD_LSS";
320  mapped_science_sky_tag = "MAPPED_ALL_STD_LSS";
321  mapped_sky_tag = "MAPPED_SKY_STD_LSS";
322  }
323  else {
324  cpl_msg_info(recipe, "LSS data found");
325  mapped_science_tag = "MAPPED_SCI_LSS";
326  mapped_science_sky_tag = "MAPPED_ALL_SCI_LSS";
327  mapped_sky_tag = "MAPPED_SKY_SCI_LSS";
328  }
329  }
330 
331  if (mos) {
332  if (standard) {
333  cpl_msg_info(recipe, "MOS data found");
334  mapped_science_tag = "MAPPED_STD_MOS";
335  mapped_science_sky_tag = "MAPPED_ALL_STD_MOS";
336  mapped_sky_tag = "MAPPED_SKY_STD_MOS";
337  }
338  else {
339  cpl_msg_info(recipe, "MOS data found");
340  mapped_science_tag = "MAPPED_SCI_MOS";
341  mapped_science_sky_tag = "MAPPED_ALL_SCI_MOS";
342  mapped_sky_tag = "MAPPED_SKY_SCI_MOS";
343  }
344  }
345 
346  /*
347  * Loading input data
348  */
349 
350  cpl_msg_info(recipe, "Load mapped scientific exposure...");
351  cpl_msg_indent_more();
352 
353  spectra = dfs_load_image(frameset, mapped_science_sky_tag,
354  CPL_TYPE_FLOAT, 0, 0);
355 
356  if (spectra == NULL)
357  fors_subtract_sky_lss_exit("Cannot load input frame");
358 
359  header = dfs_load_header(frameset, mapped_science_sky_tag, 0);
360 
361  if (header == NULL)
362  fors_subtract_sky_lss_exit("Cannot load input frame header");
363 
364  instrume = (char *)cpl_propertylist_get_string(header, "INSTRUME");
365  if (instrume == NULL)
366  fors_subtract_sky_lss_exit("Missing keyword INSTRUME in scientific header");
367  instrume = cpl_strdup(instrume);
368 
369  if (instrume[4] == '1')
370  snprintf(version, 80, "%s/%s", "fors1", VERSION);
371  if (instrume[4] == '2')
372  snprintf(version, 80, "%s/%s", "fors2", VERSION);
373 
374  cpl_free(instrume); instrume = NULL;
375 
376  cpl_msg_indent_less();
377 
378  if (mos || mxu) {
379  int nslits_out_det = 0;
380 
381  if (mos)
382  maskslits = mos_load_slits_fors_mos(header, &nslits_out_det);
383  else
384  maskslits = mos_load_slits_fors_mxu(header);
385 
386  /*
387  * Check if all slits have the same X offset: in such case,
388  * treat the observation as a long-slit one!
389  */
390 
391  treat_as_lss = fors_mos_is_lss_like(maskslits, nslits_out_det);
392 
393  cpl_table_delete(maskslits); maskslits = NULL;
394 
395  if (treat_as_lss)
396  cpl_msg_info(recipe, "All MOS slits have the same offset: %.2f\n"
397  "The LSS data reduction strategy is applied.",
398  mxpos);
399  else
400  fors_subtract_sky_lss_exit("This recipe can only be used "
401  "with LSS-like data");
402  }
403 
404  nx = cpl_image_get_size_x(spectra);
405  ny = cpl_image_get_size_y(spectra);
406 
407  skymap = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
408  sky = cpl_image_collapse_median_create(spectra, 0, 0, 1);
409 
410  data = cpl_image_get_data(skymap);
411 
412  for (i = 0; i < ny; i++) {
413  sdata = cpl_image_get_data(sky);
414  for (j = 0; j < nx; j++) {
415  *data++ = *sdata++;
416  }
417  }
418 
419  cpl_image_delete(sky); sky = NULL;
420  cpl_image_subtract(spectra, skymap);
421 
422  if (dfs_save_image(frameset, skymap, mapped_sky_tag, header,
423  parlist, recipe, version))
424  fors_subtract_sky_lss_exit(NULL);
425 
426  cpl_image_delete(skymap); skymap = NULL;
427 
428  if (dfs_save_image(frameset, spectra, mapped_science_tag, header,
429  parlist, recipe, version))
430  fors_subtract_sky_lss_exit(NULL);
431 
432  cpl_image_delete(spectra); spectra = NULL;
433 
434  cpl_propertylist_delete(header); header = NULL;
435 
436  if (cpl_error_get_code()) {
437  cpl_msg_error(cpl_error_get_where(), "%s", cpl_error_get_message());
438  fors_subtract_sky_lss_exit(NULL);
439  }
440  else
441  return 0;
442 }
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_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
Definition: list.c:74