MUSE Pipeline Reference Manual  0.18.5
muse_standard_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_standard_z.h" /* in turn includes muse.h */
36 
37 /*----------------------------------------------------------------------------*/
64 /*----------------------------------------------------------------------------*/
67 /*----------------------------------------------------------------------------*
68  * Static variables *
69  *----------------------------------------------------------------------------*/
70 static const char *muse_standard_help =
71  "Merge pixel tables from all IFUs and correct for differential atmospheric refraction. To derive the flux response curve, integrate the flux of all objects detected within the field of view using the given profile. Use the brightest object as the standard star and compare its measured fluxes to tabulated fluxes to derive the sensitivity over wavelength. Postprocess this sensitivity curve to mark wavelength ranges affected by telluric absorption. Interpolate over the telluric regions and derive a telluric correction spectrum for them. The final response cuve is then linearly extrapolated to the largest possible MUSE wavelength range and smoothed (with a 15 Angstrom median filter). The derivation of the telluric correction spectrum assumes that the star has a smooth spectrum within the telluric regions. If there are more than one exposure given in the input data, the derivation of the flux response and telluric corrections are done separately for each exposure. For each exposure, the datacube used for flux integration is saved, together with collapsed images for each given filter.";
72 
73 static const char *muse_standard_help_esorex =
74  "\n\nInput frames for raw frame tag \"PIXTABLE_STD\":\n"
75  "\n Frame tag Type Req #Fr Description"
76  "\n -------------------- ---- --- --- ------------"
77  "\n PIXTABLE_STD raw Y Pixel table of a standard star field"
78  "\n EXTINCT_TABLE calib Y 1 Atmospheric extinction table"
79  "\n STD_FLUX_TABLE calib Y Flux reference table for standard stars"
80  "\n TELLURIC_REGIONS calib . 1 Definition of telluric regions"
81  "\n FILTER_LIST calib . 1 File to be used to create field-of-view images."
82  "\n\nProduct frames for raw frame tag \"PIXTABLE_STD\":\n"
83  "\n Frame tag Level Description"
84  "\n -------------------- -------- ------------"
85  "\n DATACUBE_STD final Reduced standard star field exposure"
86  "\n STD_RESPONSE final Response curve as derived from standard star(s)"
87  "\n STD_TELLURIC final Telluric absorption as derived from standard star(s)";
88 
89 /*----------------------------------------------------------------------------*/
97 /*----------------------------------------------------------------------------*/
98 static cpl_recipeconfig *
99 muse_standard_new_recipeconfig(void)
100 {
101  cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
102  const char *tag;
103 
104  tag = "PIXTABLE_STD";
105  cpl_recipeconfig_set_tag(recipeconfig, tag, 1, -1);
106  cpl_recipeconfig_set_input(recipeconfig, tag, "EXTINCT_TABLE", 1, 1);
107  cpl_recipeconfig_set_input(recipeconfig, tag, "STD_FLUX_TABLE", 1, -1);
108  cpl_recipeconfig_set_input(recipeconfig, tag, "TELLURIC_REGIONS", -1, 1);
109  cpl_recipeconfig_set_input(recipeconfig, tag, "FILTER_LIST", -1, 1);
110  cpl_recipeconfig_set_output(recipeconfig, tag, "DATACUBE_STD");
111  cpl_recipeconfig_set_output(recipeconfig, tag, "STD_RESPONSE");
112  cpl_recipeconfig_set_output(recipeconfig, tag, "STD_TELLURIC");
113 
114  return recipeconfig;
115 } /* muse_standard_new_recipeconfig() */
116 
117 /*----------------------------------------------------------------------------*/
127 /*----------------------------------------------------------------------------*/
128 static cpl_error_code
129 muse_standard_prepare_header(const char *aFrametag, cpl_propertylist *aHeader)
130 {
131  cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
132  cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
133  if (!strcmp(aFrametag, "DATACUBE_STD")) {
134  muse_processing_prepare_property(aHeader, "ESO QC STANDARD POS[0-9]+ X",
135  CPL_TYPE_FLOAT,
136  "[pix] Position of source k in x-direction in combined frame");
137  muse_processing_prepare_property(aHeader, "ESO QC STANDARD POS[0-9]+ Y",
138  CPL_TYPE_FLOAT,
139  "[pix] Position of source k in y-direction in combined frame");
140  muse_processing_prepare_property(aHeader, "ESO QC STANDARD FWHM[0-9]+ X",
141  CPL_TYPE_FLOAT,
142  "[arcsec] FWHM of source k in x-direction in combined frame");
143  muse_processing_prepare_property(aHeader, "ESO QC STANDARD FWHM[0-9]+ Y",
144  CPL_TYPE_FLOAT,
145  "[arcsec] FWHM of source k in y-direction in combined frame");
146  } else if (!strcmp(aFrametag, "STD_RESPONSE")) {
147  } else if (!strcmp(aFrametag, "STD_TELLURIC")) {
148  } else {
149  cpl_msg_warning(__func__, "Frame tag %s is not defined", aFrametag);
150  return CPL_ERROR_ILLEGAL_INPUT;
151  }
152  return CPL_ERROR_NONE;
153 } /* muse_standard_prepare_header() */
154 
155 /*----------------------------------------------------------------------------*/
164 /*----------------------------------------------------------------------------*/
165 static cpl_frame_level
166 muse_standard_get_frame_level(const char *aFrametag)
167 {
168  if (!aFrametag) {
169  return CPL_FRAME_LEVEL_NONE;
170  }
171  if (!strcmp(aFrametag, "DATACUBE_STD")) {
172  return CPL_FRAME_LEVEL_FINAL;
173  }
174  if (!strcmp(aFrametag, "STD_RESPONSE")) {
175  return CPL_FRAME_LEVEL_FINAL;
176  }
177  if (!strcmp(aFrametag, "STD_TELLURIC")) {
178  return CPL_FRAME_LEVEL_FINAL;
179  }
180  return CPL_FRAME_LEVEL_NONE;
181 } /* muse_standard_get_frame_level() */
182 
183 /*----------------------------------------------------------------------------*/
192 /*----------------------------------------------------------------------------*/
193 static muse_frame_mode
194 muse_standard_get_frame_mode(const char *aFrametag)
195 {
196  if (!aFrametag) {
197  return MUSE_FRAME_MODE_ALL;
198  }
199  if (!strcmp(aFrametag, "DATACUBE_STD")) {
201  }
202  if (!strcmp(aFrametag, "STD_RESPONSE")) {
204  }
205  if (!strcmp(aFrametag, "STD_TELLURIC")) {
207  }
208  return MUSE_FRAME_MODE_ALL;
209 } /* muse_standard_get_frame_mode() */
210 
211 /*----------------------------------------------------------------------------*/
221 /*----------------------------------------------------------------------------*/
222 static int
223 muse_standard_create(cpl_plugin *aPlugin)
224 {
225  /* Check that the plugin is part of a valid recipe */
226  cpl_recipe *recipe;
227  if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
228  recipe = (cpl_recipe *)aPlugin;
229  } else {
230  return -1;
231  }
232 
233  /* register the extended processing information (new FITS header creation, *
234  * getting of the frame level for a certain tag) */
236  muse_standard_new_recipeconfig(),
237  muse_standard_prepare_header,
238  muse_standard_get_frame_level,
239  muse_standard_get_frame_mode);
240 
241  /* XXX initialize timing in messages *
242  * since at least esorex is too stupid to turn it on, we have to do it */
244  cpl_msg_set_time_on();
245  }
246 
247  /* Create the parameter list in the cpl_recipe object */
248  recipe->parameters = cpl_parameterlist_new();
249  /* Fill the parameters list */
250  cpl_parameter *p;
251 
252  /* --profile: Type of flux integration to use. "gaussian" and "moffat" use 2D profile fitting, circle and square are non-optimal flux integrators. */
253  p = cpl_parameter_new_enum("muse.muse_standard.profile",
254  CPL_TYPE_STRING,
255  "Type of flux integration to use. \"gaussian\" and \"moffat\" use 2D profile fitting, circle and square are non-optimal flux integrators.",
256  "muse.muse_standard",
257  (const char *)"moffat",
258  4,
259  (const char *)"gaussian",
260  (const char *)"moffat",
261  (const char *)"circle",
262  (const char *)"square");
263  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "profile");
264  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "profile");
265 
266  cpl_parameterlist_append(recipe->parameters, p);
267 
268  /* --lambdamin: Cut off the data below this wavelength after loading the pixel table(s). */
269  p = cpl_parameter_new_value("muse.muse_standard.lambdamin",
270  CPL_TYPE_DOUBLE,
271  "Cut off the data below this wavelength after loading the pixel table(s).",
272  "muse.muse_standard",
273  (double)4000.);
274  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "lambdamin");
275  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lambdamin");
276 
277  cpl_parameterlist_append(recipe->parameters, p);
278 
279  /* --lambdamax: Cut off the data above this wavelength after loading the pixel table(s). */
280  p = cpl_parameter_new_value("muse.muse_standard.lambdamax",
281  CPL_TYPE_DOUBLE,
282  "Cut off the data above this wavelength after loading the pixel table(s).",
283  "muse.muse_standard",
284  (double)10000.);
285  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "lambdamax");
286  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lambdamax");
287 
288  cpl_parameterlist_append(recipe->parameters, p);
289 
290  /* --lambdaref: Reference wavelength used for correction of differential atmospheric refraction. The R-band (peak wavelength ~7000 Angstrom) that is usually used for guiding, is close to the central wavelength of MUSE, so a value of 7000.0 Angstrom should be used if nothing else is known. A value less than zero switches DAR correction off. */
291  p = cpl_parameter_new_value("muse.muse_standard.lambdaref",
292  CPL_TYPE_DOUBLE,
293  "Reference wavelength used for correction of differential atmospheric refraction. The R-band (peak wavelength ~7000 Angstrom) that is usually used for guiding, is close to the central wavelength of MUSE, so a value of 7000.0 Angstrom should be used if nothing else is known. A value less than zero switches DAR correction off.",
294  "muse.muse_standard",
295  (double)7000.);
296  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "lambdaref");
297  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lambdaref");
298 
299  cpl_parameterlist_append(recipe->parameters, p);
300 
301  /* --darcheck: Carry out a check of the theoretical DAR correction using source centroiding. If "correct" it will also apply an empirical correction. */
302  p = cpl_parameter_new_enum("muse.muse_standard.darcheck",
303  CPL_TYPE_STRING,
304  "Carry out a check of the theoretical DAR correction using source centroiding. If \"correct\" it will also apply an empirical correction.",
305  "muse.muse_standard",
306  (const char *)"none",
307  3,
308  (const char *)"none",
309  (const char *)"check",
310  (const char *)"correct");
311  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "darcheck");
312  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "darcheck");
313 
314  cpl_parameterlist_append(recipe->parameters, p);
315 
316  /* --filter: The filter name(s) to be used for the output field-of-view image. Each name has to correspond to an EXTNAME in an extension of the FILTER_LIST file. If an unsupported filter name is given, creation of the respective image is omitted. If multiple filter names are given, they have to be comma separated. */
317  p = cpl_parameter_new_value("muse.muse_standard.filter",
318  CPL_TYPE_STRING,
319  "The filter name(s) to be used for the output field-of-view image. Each name has to correspond to an EXTNAME in an extension of the FILTER_LIST file. If an unsupported filter name is given, creation of the respective image is omitted. If multiple filter names are given, they have to be comma separated.",
320  "muse.muse_standard",
321  (const char *)"white");
322  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "filter");
323  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "filter");
324 
325  cpl_parameterlist_append(recipe->parameters, p);
326 
327  return 0;
328 } /* muse_standard_create() */
329 
330 /*----------------------------------------------------------------------------*/
341 /*----------------------------------------------------------------------------*/
342 static int
343 muse_standard_params_fill(muse_standard_params_t *aParams, cpl_parameterlist *aParameters)
344 {
345  cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
346  cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
347  cpl_parameter *p;
348 
349  p = cpl_parameterlist_find(aParameters, "muse.muse_standard.profile");
350  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
351  aParams->profile_s = cpl_parameter_get_string(p);
352  aParams->profile =
353  (!strcasecmp(aParams->profile_s, "gaussian")) ? MUSE_STANDARD_PARAM_PROFILE_GAUSSIAN :
354  (!strcasecmp(aParams->profile_s, "moffat")) ? MUSE_STANDARD_PARAM_PROFILE_MOFFAT :
355  (!strcasecmp(aParams->profile_s, "circle")) ? MUSE_STANDARD_PARAM_PROFILE_CIRCLE :
356  (!strcasecmp(aParams->profile_s, "square")) ? MUSE_STANDARD_PARAM_PROFILE_SQUARE :
357  MUSE_STANDARD_PARAM_PROFILE_INVALID_VALUE;
358  cpl_ensure_code(aParams->profile != MUSE_STANDARD_PARAM_PROFILE_INVALID_VALUE,
359  CPL_ERROR_ILLEGAL_INPUT);
360 
361  p = cpl_parameterlist_find(aParameters, "muse.muse_standard.lambdamin");
362  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
363  aParams->lambdamin = cpl_parameter_get_double(p);
364 
365  p = cpl_parameterlist_find(aParameters, "muse.muse_standard.lambdamax");
366  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
367  aParams->lambdamax = cpl_parameter_get_double(p);
368 
369  p = cpl_parameterlist_find(aParameters, "muse.muse_standard.lambdaref");
370  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
371  aParams->lambdaref = cpl_parameter_get_double(p);
372 
373  p = cpl_parameterlist_find(aParameters, "muse.muse_standard.darcheck");
374  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
375  aParams->darcheck_s = cpl_parameter_get_string(p);
376  aParams->darcheck =
377  (!strcasecmp(aParams->darcheck_s, "none")) ? MUSE_STANDARD_PARAM_DARCHECK_NONE :
378  (!strcasecmp(aParams->darcheck_s, "check")) ? MUSE_STANDARD_PARAM_DARCHECK_CHECK :
379  (!strcasecmp(aParams->darcheck_s, "correct")) ? MUSE_STANDARD_PARAM_DARCHECK_CORRECT :
380  MUSE_STANDARD_PARAM_DARCHECK_INVALID_VALUE;
381  cpl_ensure_code(aParams->darcheck != MUSE_STANDARD_PARAM_DARCHECK_INVALID_VALUE,
382  CPL_ERROR_ILLEGAL_INPUT);
383 
384  p = cpl_parameterlist_find(aParameters, "muse.muse_standard.filter");
385  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
386  aParams->filter = cpl_parameter_get_string(p);
387 
388  return 0;
389 } /* muse_standard_params_fill() */
390 
391 /*----------------------------------------------------------------------------*/
398 /*----------------------------------------------------------------------------*/
399 static int
400 muse_standard_exec(cpl_plugin *aPlugin)
401 {
402  if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
403  return -1;
404  }
405  cpl_recipe *recipe = (cpl_recipe *)aPlugin;
406  cpl_msg_set_threadid_on();
407 
408  cpl_frameset *usedframes = cpl_frameset_new(),
409  *outframes = cpl_frameset_new();
410  muse_standard_params_t params;
411  muse_standard_params_fill(&params, recipe->parameters);
412 
413  cpl_errorstate prestate = cpl_errorstate_get();
414 
415  muse_processing *proc = muse_processing_new("muse_standard",
416  recipe);
417  int rc = muse_standard_compute(proc, &params);
418  cpl_frameset_join(usedframes, proc->usedFrames);
419  cpl_frameset_join(outframes, proc->outputFrames);
421 
422  if (!cpl_errorstate_is_equal(prestate)) {
423  /* dump all errors from this recipe in chronological order */
424  cpl_errorstate_dump(prestate, CPL_FALSE, muse_cplerrorstate_dump_some);
425  /* reset message level to not get the same errors displayed again by esorex */
426  cpl_msg_set_level(CPL_MSG_INFO);
427  }
428  /* clean up duplicates in framesets of used and output frames */
431  /* to get esorex to see our classification (frame groups etc.), *
432  * replace the original frameset with the list of used frames *
433  * before appending product output frames */
434  /* keep the same pointer, so just erase all frames, not delete the frameset */
435  muse_cplframeset_erase_all(recipe->frames);
436  cpl_frameset_join(recipe->frames, usedframes);
437  cpl_frameset_join(recipe->frames, outframes);
438  cpl_frameset_delete(usedframes);
439  cpl_frameset_delete(outframes);
440  return rc;
441 } /* muse_standard_exec() */
442 
443 /*----------------------------------------------------------------------------*/
450 /*----------------------------------------------------------------------------*/
451 static int
452 muse_standard_destroy(cpl_plugin *aPlugin)
453 {
454  /* Get the recipe from the plugin */
455  cpl_recipe *recipe;
456  if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
457  recipe = (cpl_recipe *)aPlugin;
458  } else {
459  return -1;
460  }
461 
462  /* Clean up */
463  cpl_parameterlist_delete(recipe->parameters);
465  return 0;
466 } /* muse_standard_destroy() */
467 
468 /*----------------------------------------------------------------------------*/
478 /*----------------------------------------------------------------------------*/
479 int
480 cpl_plugin_get_info(cpl_pluginlist *aList)
481 {
482  cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
483  cpl_plugin *plugin = &recipe->interface;
484 
485  char *helptext;
487  helptext = cpl_sprintf("%s%s", muse_standard_help,
488  muse_standard_help_esorex);
489  } else {
490  helptext = cpl_sprintf("%s", muse_standard_help);
491  }
492 
493  /* Initialize the CPL plugin stuff for this module */
494  cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
495  CPL_PLUGIN_TYPE_RECIPE,
496  "muse_standard",
497  "Create a flux response curve from a standard star exposure.",
498  helptext,
499  "Peter Weilbacher",
500  "usd-help@eso.org",
502  muse_standard_create,
503  muse_standard_exec,
504  muse_standard_destroy);
505  cpl_pluginlist_append(aList, plugin);
506  cpl_free(helptext);
507 
508  return 0;
509 } /* cpl_plugin_get_info() */
510 
void muse_processing_delete(muse_processing *aProcessing)
Free the muse_processing structure.
int profile
Type of flux integration to use. "gaussian" and "moffat" use 2D profile fitting, circle and square ar...
muse_cplframework_type muse_cplframework(void)
Return the CPL framework the recipe is run under.
const char * profile_s
Type of flux integration to use. "gaussian" and "moffat" use 2D profile fitting, circle and square ar...
const char * darcheck_s
Carry out a check of the theoretical DAR correction using source centroiding. If "correct" it will al...
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
double lambdamin
Cut off the data below this wavelength after loading the pixel table(s).
cpl_frameset * outputFrames
void muse_cplerrorstate_dump_some(unsigned aCurrent, unsigned aFirst, unsigned aLast)
Dump some CPL errors.
double lambdaref
Reference wavelength used for correction of differential atmospheric refraction. The R-band (peak wav...
void muse_processinginfo_delete(cpl_recipe *)
Clear all information from the processing info and from the recipe config.
double lambdamax
Cut off the data above this wavelength after loading the pixel table(s).
Structure to hold the parameters of the muse_standard recipe.
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.
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.
int darcheck
Carry out a check of the theoretical DAR correction using source centroiding. If "correct" it will al...
cpl_frameset * usedFrames
const char * filter
The filter name(s) to be used for the output field-of-view image. Each name has to correspond to an E...
cpl_error_code muse_processing_prepare_property(cpl_propertylist *, const char *, cpl_type, const char *)
Prepare and check the specified property.