35 #include "muse_standard_z.h" 72 static const char *muse_standard_help =
73 "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, an image containing the extracted stellar spectra and the datacube used for flux integration are saved, together with collapsed images for each given filter.";
75 static const char *muse_standard_help_esorex =
76 "\n\nInput frames for raw frame tag \"PIXTABLE_STD\":\n" 77 "\n Frame tag Type Req #Fr Description" 78 "\n -------------------- ---- --- --- ------------" 79 "\n PIXTABLE_STD raw Y Pixel table of a standard star field" 80 "\n EXTINCT_TABLE calib Y 1 Atmospheric extinction table" 81 "\n STD_FLUX_TABLE calib Y Flux reference table for standard stars" 82 "\n TELLURIC_REGIONS calib . 1 Definition of telluric regions" 83 "\n FILTER_LIST calib . 1 File to be used to create field-of-view images." 84 "\n\nProduct frames for raw frame tag \"PIXTABLE_STD\":\n" 85 "\n Frame tag Level Description" 86 "\n -------------------- -------- ------------" 87 "\n DATACUBE_STD final Reduced standard star field exposure" 88 "\n STD_FLUXES final The integrated flux per wavelength of all detected sources" 89 "\n STD_RESPONSE final Response curve as derived from standard star(s)" 90 "\n STD_TELLURIC final Telluric absorption as derived from standard star(s)";
101 static cpl_recipeconfig *
102 muse_standard_new_recipeconfig(
void)
104 cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
106 cpl_recipeconfig_set_tag(recipeconfig,
"PIXTABLE_STD", 1, -1);
107 cpl_recipeconfig_set_input(recipeconfig,
"PIXTABLE_STD",
"EXTINCT_TABLE", 1, 1);
108 cpl_recipeconfig_set_input(recipeconfig,
"PIXTABLE_STD",
"STD_FLUX_TABLE", 1, -1);
109 cpl_recipeconfig_set_input(recipeconfig,
"PIXTABLE_STD",
"TELLURIC_REGIONS", -1, 1);
110 cpl_recipeconfig_set_input(recipeconfig,
"PIXTABLE_STD",
"FILTER_LIST", -1, 1);
111 cpl_recipeconfig_set_output(recipeconfig,
"PIXTABLE_STD",
"DATACUBE_STD");
112 cpl_recipeconfig_set_output(recipeconfig,
"PIXTABLE_STD",
"STD_FLUXES");
113 cpl_recipeconfig_set_output(recipeconfig,
"PIXTABLE_STD",
"STD_RESPONSE");
114 cpl_recipeconfig_set_output(recipeconfig,
"PIXTABLE_STD",
"STD_TELLURIC");
130 static cpl_error_code
131 muse_standard_prepare_header(
const char *aFrametag, cpl_propertylist *aHeader)
133 cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
134 cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
135 if (!strcmp(aFrametag,
"DATACUBE_STD")) {
138 "Number of detected sources in output cube.");
141 "[Angstrom] Wavelength of plane in combined cube that was used for object detection.");
144 "[pix] Position of source k in x-direction in output cube. If the FWHM measurement fails, this value will be -1.");
147 "[pix] Position of source k in y-direction in output cube. If the FWHM measurement fails, this value will be -1.");
150 "[arcsec] FWHM of source k in x-direction in output cube. If the FWHM measurement fails, this value will be -1.");
153 "[arcsec] FWHM of source k in y-direction in output cube. If the FWHM measurement fails, this value will be -1.");
156 "Number of detected sources with valid FWHM in output cube.");
159 "[arcsec] Median FWHM of all sources with valid FWHM measurement (in x- and y-direction) in output cube. If less than three sources with valid FWHM are detected, this value is zero.");
162 "[arcsec] Median absolute deviation of the FWHM of all sources with valid FWHM measurement (in x- and y-direction) in output cube. If less than three sources with valid FWHM are detected, this value is zero.");
163 }
else if (!strcmp(aFrametag,
"STD_FLUXES")) {
164 }
else if (!strcmp(aFrametag,
"STD_RESPONSE")) {
167 "Name of the standard star used for the throughput / zeropoint calculation.");
170 "Throughput computed at 5000 +/- 100 Angstrom.");
173 "Throughput computed at 6000 +/- 100 Angstrom.");
176 "Throughput computed at 7000 +/- 100 Angstrom.");
179 "Throughput computed at 8000 +/- 100 Angstrom.");
182 "Throughput computed at 9000 +/- 100 Angstrom.");
185 "[mag] Zeropoint in Johnson V filter. zp = -2.5 log10(fobs_V / fref_V), where fobs_V was integrated over the filter curve and converted to f_lambda using the known effective VLT area. (optional) Only computed if FILTER_LIST and corresponding --filter is given.");
188 "[mag] Zeropoint in Cousins R filter. zp = -2.5 log10(fobs_R / fref_R), where fobs_R was integrated over the filter curve and converted to f_lambda using the known effective VLT area. (optional) Only computed if FILTER_LIST and corresponding --filter is given.");
191 "[mag] Zeropoint in Cousins I filter. zp = -2.5 log10(fobs_I / fref_I), where fobs_I was integrated over the filter curve and converted to f_lambda using the known effective VLT area. (optional) Only computed if FILTER_LIST and corresponding --filter is given.");
192 }
else if (!strcmp(aFrametag,
"STD_TELLURIC")) {
194 cpl_msg_warning(__func__,
"Frame tag %s is not defined", aFrametag);
195 return CPL_ERROR_ILLEGAL_INPUT;
197 return CPL_ERROR_NONE;
210 static cpl_frame_level
211 muse_standard_get_frame_level(
const char *aFrametag)
214 return CPL_FRAME_LEVEL_NONE;
216 if (!strcmp(aFrametag,
"DATACUBE_STD")) {
217 return CPL_FRAME_LEVEL_FINAL;
219 if (!strcmp(aFrametag,
"STD_FLUXES")) {
220 return CPL_FRAME_LEVEL_FINAL;
222 if (!strcmp(aFrametag,
"STD_RESPONSE")) {
223 return CPL_FRAME_LEVEL_FINAL;
225 if (!strcmp(aFrametag,
"STD_TELLURIC")) {
226 return CPL_FRAME_LEVEL_FINAL;
228 return CPL_FRAME_LEVEL_NONE;
242 muse_standard_get_frame_mode(
const char *aFrametag)
247 if (!strcmp(aFrametag,
"DATACUBE_STD")) {
250 if (!strcmp(aFrametag,
"STD_FLUXES")) {
253 if (!strcmp(aFrametag,
"STD_RESPONSE")) {
256 if (!strcmp(aFrametag,
"STD_TELLURIC")) {
274 muse_standard_create(cpl_plugin *aPlugin)
278 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
279 recipe = (cpl_recipe *)aPlugin;
287 muse_standard_new_recipeconfig(),
288 muse_standard_prepare_header,
289 muse_standard_get_frame_level,
290 muse_standard_get_frame_mode);
295 cpl_msg_set_time_on();
299 recipe->parameters = cpl_parameterlist_new();
304 p = cpl_parameter_new_enum(
"muse.muse_standard.profile",
306 "Type of flux integration to use. \"gaussian\" and \"moffat\" use 2D profile fitting, circle and square are non-optimal flux integrators.",
307 "muse.muse_standard",
308 (
const char *)
"moffat",
310 (
const char *)
"gaussian",
311 (
const char *)
"moffat",
312 (
const char *)
"circle",
313 (
const char *)
"square");
314 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"profile");
315 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"profile");
317 cpl_parameterlist_append(recipe->parameters, p);
320 p = cpl_parameter_new_enum(
"muse.muse_standard.select",
322 "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.",
323 "muse.muse_standard",
324 (
const char *)
"distance",
326 (
const char *)
"flux",
327 (
const char *)
"distance");
328 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"select");
329 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"select");
331 cpl_parameterlist_append(recipe->parameters, p);
334 p = cpl_parameter_new_enum(
"muse.muse_standard.smooth",
336 "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 (each one across 2x150 Angstrom width) postprocessed by a sliding average filter of 15 Angstrom half-width.",
337 "muse.muse_standard",
338 (
const char *)
"ppoly",
340 (
const char *)
"none",
341 (
const char *)
"median",
342 (
const char *)
"ppoly");
343 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"smooth");
344 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"smooth");
346 cpl_parameterlist_append(recipe->parameters, p);
349 p = cpl_parameter_new_value(
"muse.muse_standard.lambdamin",
351 "Cut off the data below this wavelength after loading the pixel table(s).",
352 "muse.muse_standard",
354 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdamin");
355 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdamin");
357 cpl_parameterlist_append(recipe->parameters, p);
360 p = cpl_parameter_new_value(
"muse.muse_standard.lambdamax",
362 "Cut off the data above this wavelength after loading the pixel table(s).",
363 "muse.muse_standard",
365 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdamax");
366 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdamax");
368 cpl_parameterlist_append(recipe->parameters, p);
371 p = cpl_parameter_new_value(
"muse.muse_standard.lambdaref",
373 "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.",
374 "muse.muse_standard",
376 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdaref");
377 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdaref");
379 cpl_parameterlist_append(recipe->parameters, p);
382 p = cpl_parameter_new_enum(
"muse.muse_standard.darcheck",
384 "Carry out a check of the theoretical DAR correction using source centroiding. If \"correct\" it will also apply an empirical correction.",
385 "muse.muse_standard",
386 (
const char *)
"none",
388 (
const char *)
"none",
389 (
const char *)
"check",
390 (
const char *)
"correct");
391 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"darcheck");
392 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"darcheck");
394 cpl_parameterlist_append(recipe->parameters, p);
397 p = cpl_parameter_new_value(
"muse.muse_standard.filter",
399 "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. If the zeropoint QC parameters are wanted, make sure to add \"Johnson_V,Cousins_R,Cousins_I\".",
400 "muse.muse_standard",
401 (
const char *)
"white");
402 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"filter");
403 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"filter");
405 cpl_parameterlist_append(recipe->parameters, p);
425 cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
426 cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
429 p = cpl_parameterlist_find(aParameters,
"muse.muse_standard.profile");
430 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
431 aParams->
profile_s = cpl_parameter_get_string(p);
433 (!strcasecmp(aParams->
profile_s,
"gaussian")) ? MUSE_STANDARD_PARAM_PROFILE_GAUSSIAN :
434 (!strcasecmp(aParams->
profile_s,
"moffat")) ? MUSE_STANDARD_PARAM_PROFILE_MOFFAT :
435 (!strcasecmp(aParams->
profile_s,
"circle")) ? MUSE_STANDARD_PARAM_PROFILE_CIRCLE :
436 (!strcasecmp(aParams->
profile_s,
"square")) ? MUSE_STANDARD_PARAM_PROFILE_SQUARE :
437 MUSE_STANDARD_PARAM_PROFILE_INVALID_VALUE;
438 cpl_ensure_code(aParams->
profile != MUSE_STANDARD_PARAM_PROFILE_INVALID_VALUE,
439 CPL_ERROR_ILLEGAL_INPUT);
441 p = cpl_parameterlist_find(aParameters,
"muse.muse_standard.select");
442 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
443 aParams->
select_s = cpl_parameter_get_string(p);
445 (!strcasecmp(aParams->
select_s,
"flux")) ? MUSE_STANDARD_PARAM_SELECT_FLUX :
446 (!strcasecmp(aParams->
select_s,
"distance")) ? MUSE_STANDARD_PARAM_SELECT_DISTANCE :
447 MUSE_STANDARD_PARAM_SELECT_INVALID_VALUE;
448 cpl_ensure_code(aParams->
select != MUSE_STANDARD_PARAM_SELECT_INVALID_VALUE,
449 CPL_ERROR_ILLEGAL_INPUT);
451 p = cpl_parameterlist_find(aParameters,
"muse.muse_standard.smooth");
452 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
453 aParams->
smooth_s = cpl_parameter_get_string(p);
455 (!strcasecmp(aParams->
smooth_s,
"none")) ? MUSE_STANDARD_PARAM_SMOOTH_NONE :
456 (!strcasecmp(aParams->
smooth_s,
"median")) ? MUSE_STANDARD_PARAM_SMOOTH_MEDIAN :
457 (!strcasecmp(aParams->
smooth_s,
"ppoly")) ? MUSE_STANDARD_PARAM_SMOOTH_PPOLY :
458 MUSE_STANDARD_PARAM_SMOOTH_INVALID_VALUE;
459 cpl_ensure_code(aParams->
smooth != MUSE_STANDARD_PARAM_SMOOTH_INVALID_VALUE,
460 CPL_ERROR_ILLEGAL_INPUT);
462 p = cpl_parameterlist_find(aParameters,
"muse.muse_standard.lambdamin");
463 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
464 aParams->
lambdamin = cpl_parameter_get_double(p);
466 p = cpl_parameterlist_find(aParameters,
"muse.muse_standard.lambdamax");
467 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
468 aParams->
lambdamax = cpl_parameter_get_double(p);
470 p = cpl_parameterlist_find(aParameters,
"muse.muse_standard.lambdaref");
471 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
472 aParams->
lambdaref = cpl_parameter_get_double(p);
474 p = cpl_parameterlist_find(aParameters,
"muse.muse_standard.darcheck");
475 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
476 aParams->
darcheck_s = cpl_parameter_get_string(p);
478 (!strcasecmp(aParams->
darcheck_s,
"none")) ? MUSE_STANDARD_PARAM_DARCHECK_NONE :
479 (!strcasecmp(aParams->
darcheck_s,
"check")) ? MUSE_STANDARD_PARAM_DARCHECK_CHECK :
480 (!strcasecmp(aParams->
darcheck_s,
"correct")) ? MUSE_STANDARD_PARAM_DARCHECK_CORRECT :
481 MUSE_STANDARD_PARAM_DARCHECK_INVALID_VALUE;
482 cpl_ensure_code(aParams->
darcheck != MUSE_STANDARD_PARAM_DARCHECK_INVALID_VALUE,
483 CPL_ERROR_ILLEGAL_INPUT);
485 p = cpl_parameterlist_find(aParameters,
"muse.muse_standard.filter");
486 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
487 aParams->
filter = cpl_parameter_get_string(p);
501 muse_standard_exec(cpl_plugin *aPlugin)
503 if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
507 cpl_recipe *recipe = (cpl_recipe *)aPlugin;
508 cpl_msg_set_threadid_on();
510 cpl_frameset *usedframes = cpl_frameset_new(),
511 *outframes = cpl_frameset_new();
513 muse_standard_params_fill(¶ms, recipe->parameters);
515 cpl_errorstate prestate = cpl_errorstate_get();
519 int rc = muse_standard_compute(proc, ¶ms);
520 cpl_frameset_join(usedframes, proc->
usedframes);
521 cpl_frameset_join(outframes, proc->
outframes);
524 if (!cpl_errorstate_is_equal(prestate)) {
528 cpl_msg_set_level(CPL_MSG_INFO);
539 cpl_frameset_join(recipe->frames, usedframes);
540 cpl_frameset_join(recipe->frames, outframes);
541 cpl_frameset_delete(usedframes);
542 cpl_frameset_delete(outframes);
555 muse_standard_destroy(cpl_plugin *aPlugin)
559 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
560 recipe = (cpl_recipe *)aPlugin;
566 cpl_parameterlist_delete(recipe->parameters);
583 cpl_plugin_get_info(cpl_pluginlist *aList)
585 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
586 cpl_plugin *plugin = &recipe->interface;
590 helptext = cpl_sprintf(
"%s%s", muse_standard_help,
591 muse_standard_help_esorex);
593 helptext = cpl_sprintf(
"%s", muse_standard_help);
597 cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
598 CPL_PLUGIN_TYPE_RECIPE,
600 "Create a flux response curve from a standard star exposure.",
605 muse_standard_create,
607 muse_standard_destroy);
608 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...
void muse_processing_recipeinfo(cpl_plugin *)
Output main pipeline configuration, inputs, and parameters.
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.