MUSE Pipeline Reference Manual  0.18.5
muse_create_sky_z.c
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set sw=2 sts=2 et cin: */
3 /*
4  * This file is part of the MUSE Instrument Pipeline
5  * Copyright (C) 2005-2013 European Southern Observatory
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21 
22 /* This file was automatically generated */
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 /*----------------------------------------------------------------------------*
29  * Includes *
30  *----------------------------------------------------------------------------*/
31 #include <string.h> /* strcmp(), strstr() */
32 #include <strings.h> /* strcasecmp() */
33 #include <cpl.h>
34 
35 #include "muse_create_sky_z.h" /* in turn includes muse.h */
36 
37 /*----------------------------------------------------------------------------*/
47 /*----------------------------------------------------------------------------*/
50 /*----------------------------------------------------------------------------*
51  * Static variables *
52  *----------------------------------------------------------------------------*/
53 static const char *muse_create_sky_help =
54  "This recipe creates the continuum and the atmospheric transition line spectra of the night sky from the data in a pixel table(s) belonging to one exposure of (mostly) empty sky.";
55 
56 static const char *muse_create_sky_help_esorex =
57  "\n\nInput frames for raw frame tag \"PIXTABLE_SKY\":\n"
58  "\n Frame tag Type Req #Fr Description"
59  "\n -------------------- ---- --- --- ------------"
60  "\n PIXTABLE_SKY raw Y Input pixel table. If the pixel table is not already flux calibrated, the corresponding flux calibration frames should be given as well."
61  "\n EXTINCT_TABLE calib . 1 Atmospheric extinction table"
62  "\n STD_RESPONSE calib . 1 Response curve as derived from standard star(s)"
63  "\n STD_TELLURIC calib . 1 Telluric absorption as derived from standard star(s)"
64  "\n SKY_LINES calib Y 1 List of OH transitions and other sky lines"
65  "\n SKY_CONTINUUM calib . 1 Sky continuum to use"
66  "\n LSF_TABLE calib . Slice specific LSF parameters."
67  "\n SKY_MASK calib . 1 Sky mask to use"
68  "\n\nProduct frames for raw frame tag \"PIXTABLE_SKY\":\n"
69  "\n Frame tag Level Description"
70  "\n -------------------- -------- ------------"
71  "\n SKY_MASK intermed Created sky mask"
72  "\n IMAGE_FOV intermed Whitelight image used to create the sky mask"
73  "\n SKY_SPECTRUM intermed Sky spectrum within the sky mask"
74  "\n SKY_LINES final Estimated sky line flux table"
75  "\n SKY_CONTINUUM final Estimated continuum flux spectrum";
76 
77 /*----------------------------------------------------------------------------*/
85 /*----------------------------------------------------------------------------*/
86 static cpl_recipeconfig *
87 muse_create_sky_new_recipeconfig(void)
88 {
89  cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
90  const char *tag;
91 
92  tag = "PIXTABLE_SKY";
93  cpl_recipeconfig_set_tag(recipeconfig, tag, 1, -1);
94  cpl_recipeconfig_set_input(recipeconfig, tag, "EXTINCT_TABLE", 0, 1);
95  cpl_recipeconfig_set_input(recipeconfig, tag, "STD_RESPONSE", -1, 1);
96  cpl_recipeconfig_set_input(recipeconfig, tag, "STD_TELLURIC", -1, 1);
97  cpl_recipeconfig_set_input(recipeconfig, tag, "SKY_LINES", 1, 1);
98  cpl_recipeconfig_set_input(recipeconfig, tag, "SKY_CONTINUUM", 0, 1);
99  cpl_recipeconfig_set_input(recipeconfig, tag, "LSF_TABLE", 0, -1);
100  cpl_recipeconfig_set_input(recipeconfig, tag, "SKY_MASK", 0, 1);
101  cpl_recipeconfig_set_output(recipeconfig, tag, "SKY_MASK");
102  cpl_recipeconfig_set_output(recipeconfig, tag, "IMAGE_FOV");
103  cpl_recipeconfig_set_output(recipeconfig, tag, "SKY_SPECTRUM");
104  cpl_recipeconfig_set_output(recipeconfig, tag, "SKY_LINES");
105  cpl_recipeconfig_set_output(recipeconfig, tag, "SKY_CONTINUUM");
106 
107  return recipeconfig;
108 } /* muse_create_sky_new_recipeconfig() */
109 
110 /*----------------------------------------------------------------------------*/
120 /*----------------------------------------------------------------------------*/
121 static cpl_error_code
122 muse_create_sky_prepare_header(const char *aFrametag, cpl_propertylist *aHeader)
123 {
124  cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
125  cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
126  if (!strcmp(aFrametag, "SKY_MASK")) {
127  muse_processing_prepare_property(aHeader, "ESO QC SKY THRESHOLD",
128  CPL_TYPE_DOUBLE,
129  "Threshold in the white light considered as sky, used to create this mask");
130  } else if (!strcmp(aFrametag, "IMAGE_FOV")) {
131  } else if (!strcmp(aFrametag, "SKY_SPECTRUM")) {
132  } else if (!strcmp(aFrametag, "SKY_LINES")) {
133  muse_processing_prepare_property(aHeader, "ESO QC SKY LINE[0-9]+ NAME",
134  CPL_TYPE_STRING,
135  "Name of the strongest line in group k");
136  muse_processing_prepare_property(aHeader, "ESO QC SKY LINE[0-9]+ AWAV",
137  CPL_TYPE_DOUBLE,
138  "[Angstrom] Wavelength (air) of the strongest line of group k");
139  muse_processing_prepare_property(aHeader, "ESO QC SKY LINE[0-9]+ FLUX",
140  CPL_TYPE_DOUBLE,
141  "[erg/(s cm2 arcsec2)] Flux of the strongest line of group k");
142  muse_processing_prepare_property(aHeader, "ESO QC SKY LINE[0-9]+ OFFSET",
143  CPL_TYPE_DOUBLE,
144  "[Angstrom] Estimated wavelength offset for the strongest line of group k");
145  } else if (!strcmp(aFrametag, "SKY_CONTINUUM")) {
146  muse_processing_prepare_property(aHeader, "ESO QC SKY CONT FLUX",
147  CPL_TYPE_DOUBLE,
148  "[erg/(s cm2 arcsec2)] Total flux of the continuum");
149  muse_processing_prepare_property(aHeader, "ESO QC SKY CONT MAXDEV",
150  CPL_TYPE_DOUBLE,
151  "[erg/(s cm2 arcsec2 Angstrom)] Maximum (absolute value) of the derivative of the continuum spectrum");
152  } else {
153  cpl_msg_warning(__func__, "Frame tag %s is not defined", aFrametag);
154  return CPL_ERROR_ILLEGAL_INPUT;
155  }
156  return CPL_ERROR_NONE;
157 } /* muse_create_sky_prepare_header() */
158 
159 /*----------------------------------------------------------------------------*/
168 /*----------------------------------------------------------------------------*/
169 static cpl_frame_level
170 muse_create_sky_get_frame_level(const char *aFrametag)
171 {
172  if (!aFrametag) {
173  return CPL_FRAME_LEVEL_NONE;
174  }
175  if (!strcmp(aFrametag, "SKY_MASK")) {
176  return CPL_FRAME_LEVEL_INTERMEDIATE;
177  }
178  if (!strcmp(aFrametag, "IMAGE_FOV")) {
179  return CPL_FRAME_LEVEL_INTERMEDIATE;
180  }
181  if (!strcmp(aFrametag, "SKY_SPECTRUM")) {
182  return CPL_FRAME_LEVEL_INTERMEDIATE;
183  }
184  if (!strcmp(aFrametag, "SKY_LINES")) {
185  return CPL_FRAME_LEVEL_FINAL;
186  }
187  if (!strcmp(aFrametag, "SKY_CONTINUUM")) {
188  return CPL_FRAME_LEVEL_FINAL;
189  }
190  return CPL_FRAME_LEVEL_NONE;
191 } /* muse_create_sky_get_frame_level() */
192 
193 /*----------------------------------------------------------------------------*/
202 /*----------------------------------------------------------------------------*/
203 static muse_frame_mode
204 muse_create_sky_get_frame_mode(const char *aFrametag)
205 {
206  if (!aFrametag) {
207  return MUSE_FRAME_MODE_ALL;
208  }
209  if (!strcmp(aFrametag, "SKY_MASK")) {
210  return MUSE_FRAME_MODE_MASTER;
211  }
212  if (!strcmp(aFrametag, "IMAGE_FOV")) {
213  return MUSE_FRAME_MODE_MASTER;
214  }
215  if (!strcmp(aFrametag, "SKY_SPECTRUM")) {
216  return MUSE_FRAME_MODE_MASTER;
217  }
218  if (!strcmp(aFrametag, "SKY_LINES")) {
219  return MUSE_FRAME_MODE_MASTER;
220  }
221  if (!strcmp(aFrametag, "SKY_CONTINUUM")) {
222  return MUSE_FRAME_MODE_MASTER;
223  }
224  return MUSE_FRAME_MODE_ALL;
225 } /* muse_create_sky_get_frame_mode() */
226 
227 /*----------------------------------------------------------------------------*/
237 /*----------------------------------------------------------------------------*/
238 static int
239 muse_create_sky_create(cpl_plugin *aPlugin)
240 {
241  /* Check that the plugin is part of a valid recipe */
242  cpl_recipe *recipe;
243  if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
244  recipe = (cpl_recipe *)aPlugin;
245  } else {
246  return -1;
247  }
248 
249  /* register the extended processing information (new FITS header creation, *
250  * getting of the frame level for a certain tag) */
252  muse_create_sky_new_recipeconfig(),
253  muse_create_sky_prepare_header,
254  muse_create_sky_get_frame_level,
255  muse_create_sky_get_frame_mode);
256 
257  /* XXX initialize timing in messages *
258  * since at least esorex is too stupid to turn it on, we have to do it */
260  cpl_msg_set_time_on();
261  }
262 
263  /* Create the parameter list in the cpl_recipe object */
264  recipe->parameters = cpl_parameterlist_new();
265  /* Fill the parameters list */
266  cpl_parameter *p;
267 
268  /* --fraction: Fraction of the image to be considered as sky. If an input sky mask is provided, the fraction is applied to the regions within the mask. If the whole sky mask should be used, set this parameter to 1. */
269  p = cpl_parameter_new_value("muse.muse_create_sky.fraction",
270  CPL_TYPE_DOUBLE,
271  "Fraction of the image to be considered as sky. If an input sky mask is provided, the fraction is applied to the regions within the mask. If the whole sky mask should be used, set this parameter to 1.",
272  "muse.muse_create_sky",
273  (double)0.05);
274  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "fraction");
275  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "fraction");
276 
277  cpl_parameterlist_append(recipe->parameters, p);
278 
279  /* --sampling: Spectral sampling of the sky spectrum [Angstrom]. */
280  p = cpl_parameter_new_value("muse.muse_create_sky.sampling",
281  CPL_TYPE_DOUBLE,
282  "Spectral sampling of the sky spectrum [Angstrom].",
283  "muse.muse_create_sky",
284  (double)1.25);
285  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "sampling");
286  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sampling");
287  if (!getenv("MUSE_EXPERT_USER")) {
288  cpl_parameter_disable(p, CPL_PARAMETER_MODE_CLI);
289  }
290 
291  cpl_parameterlist_append(recipe->parameters, p);
292 
293  /* --csampling: Spectral sampling of the continuum spectrum [Angstrom]. */
294  p = cpl_parameter_new_value("muse.muse_create_sky.csampling",
295  CPL_TYPE_DOUBLE,
296  "Spectral sampling of the continuum spectrum [Angstrom].",
297  "muse.muse_create_sky",
298  (double)20.);
299  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "csampling");
300  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "csampling");
301  if (!getenv("MUSE_EXPERT_USER")) {
302  cpl_parameter_disable(p, CPL_PARAMETER_MODE_CLI);
303  }
304 
305  cpl_parameterlist_append(recipe->parameters, p);
306 
307  /* --cr: Type of cosmic ray cleaning to use. "Cube" is the standard CR cleaning which works on a datacube, "spectrum" uses sigma clipping on the spectrum. */
308  p = cpl_parameter_new_enum("muse.muse_create_sky.cr",
309  CPL_TYPE_STRING,
310  "Type of cosmic ray cleaning to use. \"Cube\" is the standard CR cleaning which works on a datacube, \"spectrum\" uses sigma clipping on the spectrum.",
311  "muse.muse_create_sky",
312  (const char *)"cube",
313  3,
314  (const char *)"none",
315  (const char *)"cube",
316  (const char *)"spectrum");
317  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "cr");
318  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "cr");
319  if (!getenv("MUSE_EXPERT_USER")) {
320  cpl_parameter_disable(p, CPL_PARAMETER_MODE_CLI);
321  }
322 
323  cpl_parameterlist_append(recipe->parameters, p);
324 
325  /* --lambdamin: Cut off the data below this wavelength after loading the pixel table(s). */
326  p = cpl_parameter_new_value("muse.muse_create_sky.lambdamin",
327  CPL_TYPE_DOUBLE,
328  "Cut off the data below this wavelength after loading the pixel table(s).",
329  "muse.muse_create_sky",
330  (double)4000.);
331  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "lambdamin");
332  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lambdamin");
333 
334  cpl_parameterlist_append(recipe->parameters, p);
335 
336  /* --lambdamax: Cut off the data above this wavelength after loading the pixel table(s). */
337  p = cpl_parameter_new_value("muse.muse_create_sky.lambdamax",
338  CPL_TYPE_DOUBLE,
339  "Cut off the data above this wavelength after loading the pixel table(s).",
340  "muse.muse_create_sky",
341  (double)10000.);
342  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "lambdamax");
343  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lambdamax");
344 
345  cpl_parameterlist_append(recipe->parameters, p);
346 
347  return 0;
348 } /* muse_create_sky_create() */
349 
350 /*----------------------------------------------------------------------------*/
361 /*----------------------------------------------------------------------------*/
362 static int
363 muse_create_sky_params_fill(muse_create_sky_params_t *aParams, cpl_parameterlist *aParameters)
364 {
365  cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
366  cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
367  cpl_parameter *p;
368 
369  p = cpl_parameterlist_find(aParameters, "muse.muse_create_sky.fraction");
370  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
371  aParams->fraction = cpl_parameter_get_double(p);
372 
373  p = cpl_parameterlist_find(aParameters, "muse.muse_create_sky.sampling");
374  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
375  aParams->sampling = cpl_parameter_get_double(p);
376 
377  p = cpl_parameterlist_find(aParameters, "muse.muse_create_sky.csampling");
378  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
379  aParams->csampling = cpl_parameter_get_double(p);
380 
381  p = cpl_parameterlist_find(aParameters, "muse.muse_create_sky.cr");
382  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
383  aParams->cr_s = cpl_parameter_get_string(p);
384  aParams->cr =
385  (!strcasecmp(aParams->cr_s, "none")) ? MUSE_CREATE_SKY_PARAM_CR_NONE :
386  (!strcasecmp(aParams->cr_s, "cube")) ? MUSE_CREATE_SKY_PARAM_CR_CUBE :
387  (!strcasecmp(aParams->cr_s, "spectrum")) ? MUSE_CREATE_SKY_PARAM_CR_SPECTRUM :
388  MUSE_CREATE_SKY_PARAM_CR_INVALID_VALUE;
389  cpl_ensure_code(aParams->cr != MUSE_CREATE_SKY_PARAM_CR_INVALID_VALUE,
390  CPL_ERROR_ILLEGAL_INPUT);
391 
392  p = cpl_parameterlist_find(aParameters, "muse.muse_create_sky.lambdamin");
393  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
394  aParams->lambdamin = cpl_parameter_get_double(p);
395 
396  p = cpl_parameterlist_find(aParameters, "muse.muse_create_sky.lambdamax");
397  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
398  aParams->lambdamax = cpl_parameter_get_double(p);
399 
400  return 0;
401 } /* muse_create_sky_params_fill() */
402 
403 /*----------------------------------------------------------------------------*/
410 /*----------------------------------------------------------------------------*/
411 static int
412 muse_create_sky_exec(cpl_plugin *aPlugin)
413 {
414  if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
415  return -1;
416  }
417  cpl_recipe *recipe = (cpl_recipe *)aPlugin;
418  cpl_msg_set_threadid_on();
419 
420  cpl_frameset *usedframes = cpl_frameset_new(),
421  *outframes = cpl_frameset_new();
423  muse_create_sky_params_fill(&params, recipe->parameters);
424 
425  cpl_errorstate prestate = cpl_errorstate_get();
426 
427  muse_processing *proc = muse_processing_new("muse_create_sky",
428  recipe);
429  int rc = muse_create_sky_compute(proc, &params);
430  cpl_frameset_join(usedframes, proc->usedFrames);
431  cpl_frameset_join(outframes, proc->outputFrames);
433 
434  if (!cpl_errorstate_is_equal(prestate)) {
435  /* dump all errors from this recipe in chronological order */
436  cpl_errorstate_dump(prestate, CPL_FALSE, muse_cplerrorstate_dump_some);
437  /* reset message level to not get the same errors displayed again by esorex */
438  cpl_msg_set_level(CPL_MSG_INFO);
439  }
440  /* clean up duplicates in framesets of used and output frames */
443  /* to get esorex to see our classification (frame groups etc.), *
444  * replace the original frameset with the list of used frames *
445  * before appending product output frames */
446  /* keep the same pointer, so just erase all frames, not delete the frameset */
447  muse_cplframeset_erase_all(recipe->frames);
448  cpl_frameset_join(recipe->frames, usedframes);
449  cpl_frameset_join(recipe->frames, outframes);
450  cpl_frameset_delete(usedframes);
451  cpl_frameset_delete(outframes);
452  return rc;
453 } /* muse_create_sky_exec() */
454 
455 /*----------------------------------------------------------------------------*/
462 /*----------------------------------------------------------------------------*/
463 static int
464 muse_create_sky_destroy(cpl_plugin *aPlugin)
465 {
466  /* Get the recipe from the plugin */
467  cpl_recipe *recipe;
468  if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
469  recipe = (cpl_recipe *)aPlugin;
470  } else {
471  return -1;
472  }
473 
474  /* Clean up */
475  cpl_parameterlist_delete(recipe->parameters);
477  return 0;
478 } /* muse_create_sky_destroy() */
479 
480 /*----------------------------------------------------------------------------*/
490 /*----------------------------------------------------------------------------*/
491 int
492 cpl_plugin_get_info(cpl_pluginlist *aList)
493 {
494  cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
495  cpl_plugin *plugin = &recipe->interface;
496 
497  char *helptext;
499  helptext = cpl_sprintf("%s%s", muse_create_sky_help,
500  muse_create_sky_help_esorex);
501  } else {
502  helptext = cpl_sprintf("%s", muse_create_sky_help);
503  }
504 
505  /* Initialize the CPL plugin stuff for this module */
506  cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
507  CPL_PLUGIN_TYPE_RECIPE,
508  "muse_create_sky",
509  "Create night sky model from selected pixels of an exposure of empty sky.",
510  helptext,
511  "Ole Streicher",
512  "usd-help@eso.org",
514  muse_create_sky_create,
515  muse_create_sky_exec,
516  muse_create_sky_destroy);
517  cpl_pluginlist_append(aList, plugin);
518  cpl_free(helptext);
519 
520  return 0;
521 } /* cpl_plugin_get_info() */
522 
void muse_processing_delete(muse_processing *aProcessing)
Free the muse_processing structure.
muse_cplframework_type muse_cplframework(void)
Return the CPL framework the recipe is run under.
double csampling
Spectral sampling of the continuum spectrum [Angstrom].
int cr
Type of cosmic ray cleaning to use. "Cube" is the standard CR cleaning which works on a datacube...
const char * muse_get_license(void)
Get the pipeline copyright and license.
Definition: muse_utils.c:80
muse_processing * muse_processing_new(const char *aRecipeName, cpl_recipe *aRecipe)
Create a new processing structure.
muse_frame_mode
cpl_frameset * outputFrames
void muse_cplerrorstate_dump_some(unsigned aCurrent, unsigned aFirst, unsigned aLast)
Dump some CPL errors.
void muse_processinginfo_delete(cpl_recipe *)
Clear all information from the processing info and from the recipe config.
cpl_error_code muse_cplframeset_erase_duplicate(cpl_frameset *aFrames)
Erase all duplicate frames from a frameset.
cpl_error_code muse_cplframeset_erase_all(cpl_frameset *aFrames)
Erase all frames in a frameset.
double lambdamin
Cut off the data below this wavelength after loading the pixel table(s).
double sampling
Spectral sampling of the sky spectrum [Angstrom].
void muse_processinginfo_register(cpl_recipe *, cpl_recipeconfig *, muse_processing_prepare_header_func *, muse_processing_get_frame_level_func *, muse_processing_get_frame_mode_func *)
Register extended functionalities for MUSE recipes.
double fraction
Fraction of the image to be considered as sky. If an input sky mask is provided, the fraction is appl...
double lambdamax
Cut off the data above this wavelength after loading the pixel table(s).
const char * cr_s
Type of cosmic ray cleaning to use. "Cube" is the standard CR cleaning which works on a datacube...
cpl_frameset * usedFrames
Structure to hold the parameters of the muse_create_sky recipe.
cpl_error_code muse_processing_prepare_property(cpl_propertylist *, const char *, cpl_type, const char *)
Prepare and check the specified property.