35 #include "muse_standard_z.h"
71 static const char *muse_standard_help =
72 "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. Select one object as the standard star (either the brightest or the one nearest one, depending on --select) 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 the method given by --smooth). 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.";
74 static const char *muse_standard_help_esorex =
75 "\n\nInput frames for raw frame tag \"PIXTABLE_STD\":\n"
76 "\n Frame tag Type Req #Fr Description"
77 "\n -------------------- ---- --- --- ------------"
78 "\n PIXTABLE_STD raw Y Pixel table of a standard star field"
79 "\n EXTINCT_TABLE calib Y 1 Atmospheric extinction table"
80 "\n STD_FLUX_TABLE calib Y Flux reference table for standard stars"
81 "\n TELLURIC_REGIONS calib . 1 Definition of telluric regions"
82 "\n FILTER_LIST calib . 1 File to be used to create field-of-view images."
83 "\n\nProduct frames for raw frame tag \"PIXTABLE_STD\":\n"
84 "\n Frame tag Level Description"
85 "\n -------------------- -------- ------------"
86 "\n DATACUBE_STD final Reduced standard star field exposure"
87 "\n STD_FLUXES final The integrated flux per wavelength of all detected sources"
88 "\n STD_RESPONSE final Response curve as derived from standard star(s)"
89 "\n STD_TELLURIC final Telluric absorption as derived from standard star(s)";
100 static cpl_recipeconfig *
101 muse_standard_new_recipeconfig(
void)
103 cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
106 tag =
"PIXTABLE_STD";
107 cpl_recipeconfig_set_tag(recipeconfig, tag, 1, -1);
108 cpl_recipeconfig_set_input(recipeconfig, tag,
"EXTINCT_TABLE", 1, 1);
109 cpl_recipeconfig_set_input(recipeconfig, tag,
"STD_FLUX_TABLE", 1, -1);
110 cpl_recipeconfig_set_input(recipeconfig, tag,
"TELLURIC_REGIONS", -1, 1);
111 cpl_recipeconfig_set_input(recipeconfig, tag,
"FILTER_LIST", -1, 1);
112 cpl_recipeconfig_set_output(recipeconfig, tag,
"DATACUBE_STD");
113 cpl_recipeconfig_set_output(recipeconfig, tag,
"STD_FLUXES");
114 cpl_recipeconfig_set_output(recipeconfig, tag,
"STD_RESPONSE");
115 cpl_recipeconfig_set_output(recipeconfig, tag,
"STD_TELLURIC");
131 static cpl_error_code
132 muse_standard_prepare_header(
const char *aFrametag, cpl_propertylist *aHeader)
134 cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
135 cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
136 if (!strcmp(aFrametag,
"DATACUBE_STD")) {
139 "[pix] Position of source k in x-direction in combined frame");
142 "[pix] Position of source k in y-direction in combined frame");
145 "[arcsec] FWHM of source k in x-direction in combined frame");
148 "[arcsec] FWHM of source k in y-direction in combined frame");
149 }
else if (!strcmp(aFrametag,
"STD_FLUXES")) {
150 }
else if (!strcmp(aFrametag,
"STD_RESPONSE")) {
151 }
else if (!strcmp(aFrametag,
"STD_TELLURIC")) {
153 cpl_msg_warning(__func__,
"Frame tag %s is not defined", aFrametag);
154 return CPL_ERROR_ILLEGAL_INPUT;
156 return CPL_ERROR_NONE;
169 static cpl_frame_level
170 muse_standard_get_frame_level(
const char *aFrametag)
173 return CPL_FRAME_LEVEL_NONE;
175 if (!strcmp(aFrametag,
"DATACUBE_STD")) {
176 return CPL_FRAME_LEVEL_FINAL;
178 if (!strcmp(aFrametag,
"STD_FLUXES")) {
179 return CPL_FRAME_LEVEL_FINAL;
181 if (!strcmp(aFrametag,
"STD_RESPONSE")) {
182 return CPL_FRAME_LEVEL_FINAL;
184 if (!strcmp(aFrametag,
"STD_TELLURIC")) {
185 return CPL_FRAME_LEVEL_FINAL;
187 return CPL_FRAME_LEVEL_NONE;
201 muse_standard_get_frame_mode(
const char *aFrametag)
206 if (!strcmp(aFrametag,
"DATACUBE_STD")) {
209 if (!strcmp(aFrametag,
"STD_FLUXES")) {
212 if (!strcmp(aFrametag,
"STD_RESPONSE")) {
215 if (!strcmp(aFrametag,
"STD_TELLURIC")) {
233 muse_standard_create(cpl_plugin *aPlugin)
237 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
238 recipe = (cpl_recipe *)aPlugin;
246 muse_standard_new_recipeconfig(),
247 muse_standard_prepare_header,
248 muse_standard_get_frame_level,
249 muse_standard_get_frame_mode);
254 cpl_msg_set_time_on();
258 recipe->parameters = cpl_parameterlist_new();
263 p = cpl_parameter_new_enum(
"muse.muse_standard.profile",
265 "Type of flux integration to use. \"gaussian\" and \"moffat\" use 2D profile fitting, circle and square are non-optimal flux integrators.",
266 "muse.muse_standard",
267 (
const char *)
"moffat",
269 (
const char *)
"gaussian",
270 (
const char *)
"moffat",
271 (
const char *)
"circle",
272 (
const char *)
"square");
273 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"profile");
274 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"profile");
276 cpl_parameterlist_append(recipe->parameters, p);
279 p = cpl_parameter_new_enum(
"muse.muse_standard.select",
281 "How to select the star for flux integration, \"flux\" uses the brightest star in the field, \"distance\" uses the detection nearest to the approximate coordinates of the reference source.",
282 "muse.muse_standard",
283 (
const char *)
"flux",
285 (
const char *)
"flux",
286 (
const char *)
"distance");
287 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"select");
288 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"select");
290 cpl_parameterlist_append(recipe->parameters, p);
293 p = cpl_parameter_new_enum(
"muse.muse_standard.smooth",
295 "How to smooth the response curve before writing it to disk. \"none\" does not do any kind of smoothing (such a response curve is only useful, if smoothed externally; \"median\" does a median-filter of 15 Angstrom half-width; \"ppoly\" fits piecewise cubic polynomials postprocessed by a sliding average filter of 15 Angstrom half-width.",
296 "muse.muse_standard",
297 (
const char *)
"ppoly",
299 (
const char *)
"none",
300 (
const char *)
"median",
301 (
const char *)
"ppoly");
302 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"smooth");
303 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"smooth");
305 cpl_parameterlist_append(recipe->parameters, p);
308 p = cpl_parameter_new_value(
"muse.muse_standard.lambdamin",
310 "Cut off the data below this wavelength after loading the pixel table(s).",
311 "muse.muse_standard",
313 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdamin");
314 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdamin");
316 cpl_parameterlist_append(recipe->parameters, p);
319 p = cpl_parameter_new_value(
"muse.muse_standard.lambdamax",
321 "Cut off the data above this wavelength after loading the pixel table(s).",
322 "muse.muse_standard",
324 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdamax");
325 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdamax");
327 cpl_parameterlist_append(recipe->parameters, p);
330 p = cpl_parameter_new_value(
"muse.muse_standard.lambdaref",
332 "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.",
333 "muse.muse_standard",
335 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdaref");
336 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdaref");
338 cpl_parameterlist_append(recipe->parameters, p);
341 p = cpl_parameter_new_enum(
"muse.muse_standard.darcheck",
343 "Carry out a check of the theoretical DAR correction using source centroiding. If \"correct\" it will also apply an empirical correction.",
344 "muse.muse_standard",
345 (
const char *)
"none",
347 (
const char *)
"none",
348 (
const char *)
"check",
349 (
const char *)
"correct");
350 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"darcheck");
351 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"darcheck");
353 cpl_parameterlist_append(recipe->parameters, p);
356 p = cpl_parameter_new_value(
"muse.muse_standard.filter",
358 "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.",
359 "muse.muse_standard",
360 (
const char *)
"white");
361 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"filter");
362 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"filter");
364 cpl_parameterlist_append(recipe->parameters, p);
384 cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
385 cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
388 p = cpl_parameterlist_find(aParameters,
"muse.muse_standard.profile");
389 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
390 aParams->
profile_s = cpl_parameter_get_string(p);
392 (!strcasecmp(aParams->
profile_s,
"gaussian")) ? MUSE_STANDARD_PARAM_PROFILE_GAUSSIAN :
393 (!strcasecmp(aParams->
profile_s,
"moffat")) ? MUSE_STANDARD_PARAM_PROFILE_MOFFAT :
394 (!strcasecmp(aParams->
profile_s,
"circle")) ? MUSE_STANDARD_PARAM_PROFILE_CIRCLE :
395 (!strcasecmp(aParams->
profile_s,
"square")) ? MUSE_STANDARD_PARAM_PROFILE_SQUARE :
396 MUSE_STANDARD_PARAM_PROFILE_INVALID_VALUE;
397 cpl_ensure_code(aParams->
profile != MUSE_STANDARD_PARAM_PROFILE_INVALID_VALUE,
398 CPL_ERROR_ILLEGAL_INPUT);
400 p = cpl_parameterlist_find(aParameters,
"muse.muse_standard.select");
401 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
402 aParams->
select_s = cpl_parameter_get_string(p);
404 (!strcasecmp(aParams->
select_s,
"flux")) ? MUSE_STANDARD_PARAM_SELECT_FLUX :
405 (!strcasecmp(aParams->
select_s,
"distance")) ? MUSE_STANDARD_PARAM_SELECT_DISTANCE :
406 MUSE_STANDARD_PARAM_SELECT_INVALID_VALUE;
407 cpl_ensure_code(aParams->
select != MUSE_STANDARD_PARAM_SELECT_INVALID_VALUE,
408 CPL_ERROR_ILLEGAL_INPUT);
410 p = cpl_parameterlist_find(aParameters,
"muse.muse_standard.smooth");
411 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
412 aParams->
smooth_s = cpl_parameter_get_string(p);
414 (!strcasecmp(aParams->
smooth_s,
"none")) ? MUSE_STANDARD_PARAM_SMOOTH_NONE :
415 (!strcasecmp(aParams->
smooth_s,
"median")) ? MUSE_STANDARD_PARAM_SMOOTH_MEDIAN :
416 (!strcasecmp(aParams->
smooth_s,
"ppoly")) ? MUSE_STANDARD_PARAM_SMOOTH_PPOLY :
417 MUSE_STANDARD_PARAM_SMOOTH_INVALID_VALUE;
418 cpl_ensure_code(aParams->
smooth != MUSE_STANDARD_PARAM_SMOOTH_INVALID_VALUE,
419 CPL_ERROR_ILLEGAL_INPUT);
421 p = cpl_parameterlist_find(aParameters,
"muse.muse_standard.lambdamin");
422 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
423 aParams->
lambdamin = cpl_parameter_get_double(p);
425 p = cpl_parameterlist_find(aParameters,
"muse.muse_standard.lambdamax");
426 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
427 aParams->
lambdamax = cpl_parameter_get_double(p);
429 p = cpl_parameterlist_find(aParameters,
"muse.muse_standard.lambdaref");
430 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
431 aParams->
lambdaref = cpl_parameter_get_double(p);
433 p = cpl_parameterlist_find(aParameters,
"muse.muse_standard.darcheck");
434 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
435 aParams->
darcheck_s = cpl_parameter_get_string(p);
437 (!strcasecmp(aParams->
darcheck_s,
"none")) ? MUSE_STANDARD_PARAM_DARCHECK_NONE :
438 (!strcasecmp(aParams->
darcheck_s,
"check")) ? MUSE_STANDARD_PARAM_DARCHECK_CHECK :
439 (!strcasecmp(aParams->
darcheck_s,
"correct")) ? MUSE_STANDARD_PARAM_DARCHECK_CORRECT :
440 MUSE_STANDARD_PARAM_DARCHECK_INVALID_VALUE;
441 cpl_ensure_code(aParams->
darcheck != MUSE_STANDARD_PARAM_DARCHECK_INVALID_VALUE,
442 CPL_ERROR_ILLEGAL_INPUT);
444 p = cpl_parameterlist_find(aParameters,
"muse.muse_standard.filter");
445 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
446 aParams->
filter = cpl_parameter_get_string(p);
460 muse_standard_exec(cpl_plugin *aPlugin)
462 if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
465 cpl_recipe *recipe = (cpl_recipe *)aPlugin;
466 cpl_msg_set_threadid_on();
468 cpl_frameset *usedframes = cpl_frameset_new(),
469 *outframes = cpl_frameset_new();
471 muse_standard_params_fill(¶ms, recipe->parameters);
473 cpl_errorstate prestate = cpl_errorstate_get();
477 int rc = muse_standard_compute(proc, ¶ms);
478 cpl_frameset_join(usedframes, proc->
usedframes);
479 cpl_frameset_join(outframes, proc->
outframes);
482 if (!cpl_errorstate_is_equal(prestate)) {
486 cpl_msg_set_level(CPL_MSG_INFO);
497 cpl_frameset_join(recipe->frames, usedframes);
498 cpl_frameset_join(recipe->frames, outframes);
499 cpl_frameset_delete(usedframes);
500 cpl_frameset_delete(outframes);
513 muse_standard_destroy(cpl_plugin *aPlugin)
517 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
518 recipe = (cpl_recipe *)aPlugin;
524 cpl_parameterlist_delete(recipe->parameters);
541 cpl_plugin_get_info(cpl_pluginlist *aList)
543 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
544 cpl_plugin *plugin = &recipe->interface;
548 helptext = cpl_sprintf(
"%s%s", muse_standard_help,
549 muse_standard_help_esorex);
551 helptext = cpl_sprintf(
"%s", muse_standard_help);
555 cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
556 CPL_PLUGIN_TYPE_RECIPE,
558 "Create a flux response curve from a standard star exposure.",
563 muse_standard_create,
565 muse_standard_destroy);
566 cpl_pluginlist_append(aList, plugin);
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.
int select
How to select the star for flux integration, "flux" uses the brightest star in the field...
int smooth
How to smooth the response curve before writing it to disk. "none" does not do any kind of smoothing ...
const char * profile_s
Type of flux integration to use. "gaussian" and "moffat" use 2D profile fitting, circle and square ar...
const char * select_s
How to select the star for flux integration, "flux" uses the brightest star in the field...
const char * darcheck_s
Carry out a check of the theoretical DAR correction using source centroiding. If "correct" it will al...
cpl_frameset * usedframes
muse_processing * muse_processing_new(const char *aName, cpl_recipe *aRecipe)
Create a new processing structure.
const char * muse_get_license(void)
Get the pipeline copyright and license.
double lambdamin
Cut off the data below this wavelength after loading the pixel table(s).
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...
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...
const char * smooth_s
How to smooth the response curve before writing it to disk. "none" does not do any kind of smoothing ...
cpl_error_code muse_processing_prepare_property(cpl_propertylist *, const char *, cpl_type, const char *)
Prepare and check the specified property.