35 #include "muse_standard_z.h"
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.";
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)";
98 static cpl_recipeconfig *
99 muse_standard_new_recipeconfig(
void)
101 cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
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");
128 static cpl_error_code
129 muse_standard_prepare_header(
const char *aFrametag, cpl_propertylist *aHeader)
131 cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
132 cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
133 if (!strcmp(aFrametag,
"DATACUBE_STD")) {
136 "[pix] Position of source k in x-direction in combined frame");
139 "[pix] Position of source k in y-direction in combined frame");
142 "[arcsec] FWHM of source k in x-direction in combined frame");
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")) {
149 cpl_msg_warning(__func__,
"Frame tag %s is not defined", aFrametag);
150 return CPL_ERROR_ILLEGAL_INPUT;
152 return CPL_ERROR_NONE;
165 static cpl_frame_level
166 muse_standard_get_frame_level(
const char *aFrametag)
169 return CPL_FRAME_LEVEL_NONE;
171 if (!strcmp(aFrametag,
"DATACUBE_STD")) {
172 return CPL_FRAME_LEVEL_FINAL;
174 if (!strcmp(aFrametag,
"STD_RESPONSE")) {
175 return CPL_FRAME_LEVEL_FINAL;
177 if (!strcmp(aFrametag,
"STD_TELLURIC")) {
178 return CPL_FRAME_LEVEL_FINAL;
180 return CPL_FRAME_LEVEL_NONE;
194 muse_standard_get_frame_mode(
const char *aFrametag)
199 if (!strcmp(aFrametag,
"DATACUBE_STD")) {
202 if (!strcmp(aFrametag,
"STD_RESPONSE")) {
205 if (!strcmp(aFrametag,
"STD_TELLURIC")) {
223 muse_standard_create(cpl_plugin *aPlugin)
227 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
228 recipe = (cpl_recipe *)aPlugin;
236 muse_standard_new_recipeconfig(),
237 muse_standard_prepare_header,
238 muse_standard_get_frame_level,
239 muse_standard_get_frame_mode);
244 cpl_msg_set_time_on();
248 recipe->parameters = cpl_parameterlist_new();
253 p = cpl_parameter_new_enum(
"muse.muse_standard.profile",
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",
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");
266 cpl_parameterlist_append(recipe->parameters, p);
269 p = cpl_parameter_new_value(
"muse.muse_standard.lambdamin",
271 "Cut off the data below this wavelength after loading the pixel table(s).",
272 "muse.muse_standard",
274 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdamin");
275 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdamin");
277 cpl_parameterlist_append(recipe->parameters, p);
280 p = cpl_parameter_new_value(
"muse.muse_standard.lambdamax",
282 "Cut off the data above this wavelength after loading the pixel table(s).",
283 "muse.muse_standard",
285 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdamax");
286 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdamax");
288 cpl_parameterlist_append(recipe->parameters, p);
291 p = cpl_parameter_new_value(
"muse.muse_standard.lambdaref",
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",
296 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdaref");
297 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdaref");
299 cpl_parameterlist_append(recipe->parameters, p);
302 p = cpl_parameter_new_enum(
"muse.muse_standard.darcheck",
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",
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");
314 cpl_parameterlist_append(recipe->parameters, p);
317 p = cpl_parameter_new_value(
"muse.muse_standard.filter",
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");
325 cpl_parameterlist_append(recipe->parameters, p);
345 cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
346 cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
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);
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);
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);
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);
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);
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);
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);
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);
400 muse_standard_exec(cpl_plugin *aPlugin)
402 if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
405 cpl_recipe *recipe = (cpl_recipe *)aPlugin;
406 cpl_msg_set_threadid_on();
408 cpl_frameset *usedframes = cpl_frameset_new(),
409 *outframes = cpl_frameset_new();
411 muse_standard_params_fill(¶ms, recipe->parameters);
413 cpl_errorstate prestate = cpl_errorstate_get();
417 int rc = muse_standard_compute(proc, ¶ms);
418 cpl_frameset_join(usedframes, proc->
usedFrames);
422 if (!cpl_errorstate_is_equal(prestate)) {
426 cpl_msg_set_level(CPL_MSG_INFO);
436 cpl_frameset_join(recipe->frames, usedframes);
437 cpl_frameset_join(recipe->frames, outframes);
438 cpl_frameset_delete(usedframes);
439 cpl_frameset_delete(outframes);
452 muse_standard_destroy(cpl_plugin *aPlugin)
456 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
457 recipe = (cpl_recipe *)aPlugin;
463 cpl_parameterlist_delete(recipe->parameters);
480 cpl_plugin_get_info(cpl_pluginlist *aList)
482 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
483 cpl_plugin *plugin = &recipe->interface;
487 helptext = cpl_sprintf(
"%s%s", muse_standard_help,
488 muse_standard_help_esorex);
490 helptext = cpl_sprintf(
"%s", muse_standard_help);
494 cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
495 CPL_PLUGIN_TYPE_RECIPE,
497 "Create a flux response curve from a standard star exposure.",
502 muse_standard_create,
504 muse_standard_destroy);
505 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.
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.
muse_processing * muse_processing_new(const char *aRecipeName, cpl_recipe *aRecipe)
Create a new processing structure.
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.