35 #include "muse_create_sky_z.h"
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.";
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 Y 1 Atmospheric extinction table"
62 "\n STD_RESPONSE calib Y 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_PROFILE 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";
86 static cpl_recipeconfig *
87 muse_create_sky_new_recipeconfig(
void)
89 cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
93 cpl_recipeconfig_set_tag(recipeconfig, tag, 1, -1);
94 cpl_recipeconfig_set_input(recipeconfig, tag,
"EXTINCT_TABLE", 1, 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_PROFILE", 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");
121 static cpl_error_code
122 muse_create_sky_prepare_header(
const char *aFrametag, cpl_propertylist *aHeader)
124 cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
125 cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
126 if (!strcmp(aFrametag,
"SKY_MASK")) {
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")) {
135 "Name of the strongest line in group k");
138 "[Angstrom] Wavelength (air) of the strongest line of group l");
141 "[erg/(s cm2 arcsec2)] Flux of the strongest line of group l");
142 }
else if (!strcmp(aFrametag,
"SKY_CONTINUUM")) {
145 "[erg/(s cm2 arcsec2)] Total flux of the continuum");
148 "[erg/(s cm2 arcsec2 Angstrom)] Maximum (absolute value) of the derivative of the continuum spectrum");
150 cpl_msg_warning(__func__,
"Frame tag %s is not defined", aFrametag);
151 return CPL_ERROR_ILLEGAL_INPUT;
153 return CPL_ERROR_NONE;
166 static cpl_frame_level
167 muse_create_sky_get_frame_level(
const char *aFrametag)
170 return CPL_FRAME_LEVEL_NONE;
172 if (!strcmp(aFrametag,
"SKY_MASK")) {
173 return CPL_FRAME_LEVEL_INTERMEDIATE;
175 if (!strcmp(aFrametag,
"IMAGE_FOV")) {
176 return CPL_FRAME_LEVEL_INTERMEDIATE;
178 if (!strcmp(aFrametag,
"SKY_SPECTRUM")) {
179 return CPL_FRAME_LEVEL_INTERMEDIATE;
181 if (!strcmp(aFrametag,
"SKY_LINES")) {
182 return CPL_FRAME_LEVEL_FINAL;
184 if (!strcmp(aFrametag,
"SKY_CONTINUUM")) {
185 return CPL_FRAME_LEVEL_FINAL;
187 return CPL_FRAME_LEVEL_NONE;
201 muse_create_sky_get_frame_mode(
const char *aFrametag)
206 if (!strcmp(aFrametag,
"SKY_MASK")) {
209 if (!strcmp(aFrametag,
"IMAGE_FOV")) {
212 if (!strcmp(aFrametag,
"SKY_SPECTRUM")) {
215 if (!strcmp(aFrametag,
"SKY_LINES")) {
218 if (!strcmp(aFrametag,
"SKY_CONTINUUM")) {
236 muse_create_sky_create(cpl_plugin *aPlugin)
240 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
241 recipe = (cpl_recipe *)aPlugin;
249 muse_create_sky_new_recipeconfig(),
250 muse_create_sky_prepare_header,
251 muse_create_sky_get_frame_level,
252 muse_create_sky_get_frame_mode);
257 cpl_msg_set_time_on();
261 recipe->parameters = cpl_parameterlist_new();
266 p = cpl_parameter_new_value(
"muse.muse_create_sky.fraction",
268 "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 "muse.muse_create_sky",
271 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"fraction");
272 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"fraction");
274 cpl_parameterlist_append(recipe->parameters, p);
277 p = cpl_parameter_new_value(
"muse.muse_create_sky.sampling",
279 "Spectral sampling of the sky spectrum [Angstrom].",
280 "muse.muse_create_sky",
282 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"sampling");
283 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"sampling");
284 if (!getenv(
"MUSE_EXPERT_USER")) {
285 cpl_parameter_disable(p, CPL_PARAMETER_MODE_CLI);
288 cpl_parameterlist_append(recipe->parameters, p);
291 p = cpl_parameter_new_value(
"muse.muse_create_sky.csampling",
293 "Spectral sampling of the continuum spectrum [Angstrom].",
294 "muse.muse_create_sky",
296 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"csampling");
297 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"csampling");
298 if (!getenv(
"MUSE_EXPERT_USER")) {
299 cpl_parameter_disable(p, CPL_PARAMETER_MODE_CLI);
302 cpl_parameterlist_append(recipe->parameters, p);
305 p = cpl_parameter_new_enum(
"muse.muse_create_sky.cr",
307 "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 "muse.muse_create_sky",
309 (
const char *)
"cube",
311 (
const char *)
"none",
312 (
const char *)
"cube",
313 (
const char *)
"spectrum");
314 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"cr");
315 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"cr");
316 if (!getenv(
"MUSE_EXPERT_USER")) {
317 cpl_parameter_disable(p, CPL_PARAMETER_MODE_CLI);
320 cpl_parameterlist_append(recipe->parameters, p);
323 p = cpl_parameter_new_value(
"muse.muse_create_sky.lambdamin",
325 "Cut off the data below this wavelength after loading the pixel table(s).",
326 "muse.muse_create_sky",
328 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdamin");
329 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdamin");
331 cpl_parameterlist_append(recipe->parameters, p);
334 p = cpl_parameter_new_value(
"muse.muse_create_sky.lambdamax",
336 "Cut off the data above this wavelength after loading the pixel table(s).",
337 "muse.muse_create_sky",
339 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdamax");
340 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdamax");
342 cpl_parameterlist_append(recipe->parameters, p);
345 p = cpl_parameter_new_value(
"muse.muse_create_sky.lambdaref",
347 "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.",
348 "muse.muse_create_sky",
350 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdaref");
351 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdaref");
353 cpl_parameterlist_append(recipe->parameters, p);
373 cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
374 cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
377 p = cpl_parameterlist_find(aParameters,
"muse.muse_create_sky.fraction");
378 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
379 aParams->
fraction = cpl_parameter_get_double(p);
381 p = cpl_parameterlist_find(aParameters,
"muse.muse_create_sky.sampling");
382 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
383 aParams->
sampling = cpl_parameter_get_double(p);
385 p = cpl_parameterlist_find(aParameters,
"muse.muse_create_sky.csampling");
386 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
387 aParams->
csampling = cpl_parameter_get_double(p);
389 p = cpl_parameterlist_find(aParameters,
"muse.muse_create_sky.cr");
390 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
391 aParams->
cr_s = cpl_parameter_get_string(p);
393 (!strcasecmp(aParams->
cr_s,
"none")) ? MUSE_CREATE_SKY_PARAM_CR_NONE :
394 (!strcasecmp(aParams->
cr_s,
"cube")) ? MUSE_CREATE_SKY_PARAM_CR_CUBE :
395 (!strcasecmp(aParams->
cr_s,
"spectrum")) ? MUSE_CREATE_SKY_PARAM_CR_SPECTRUM :
396 MUSE_CREATE_SKY_PARAM_CR_INVALID_VALUE;
397 cpl_ensure_code(aParams->
cr != MUSE_CREATE_SKY_PARAM_CR_INVALID_VALUE,
398 CPL_ERROR_ILLEGAL_INPUT);
400 p = cpl_parameterlist_find(aParameters,
"muse.muse_create_sky.lambdamin");
401 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
402 aParams->
lambdamin = cpl_parameter_get_double(p);
404 p = cpl_parameterlist_find(aParameters,
"muse.muse_create_sky.lambdamax");
405 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
406 aParams->
lambdamax = cpl_parameter_get_double(p);
408 p = cpl_parameterlist_find(aParameters,
"muse.muse_create_sky.lambdaref");
409 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
410 aParams->
lambdaref = cpl_parameter_get_double(p);
424 muse_create_sky_exec(cpl_plugin *aPlugin)
426 if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
429 cpl_recipe *recipe = (cpl_recipe *)aPlugin;
430 cpl_msg_set_threadid_on();
432 cpl_frameset *usedframes = cpl_frameset_new(),
433 *outframes = cpl_frameset_new();
435 muse_create_sky_params_fill(¶ms, recipe->parameters);
437 cpl_errorstate prestate = cpl_errorstate_get();
441 int rc = muse_create_sky_compute(proc, ¶ms);
442 cpl_frameset_join(usedframes, proc->
usedframes);
443 cpl_frameset_join(outframes, proc->
outframes);
446 if (!cpl_errorstate_is_equal(prestate)) {
450 cpl_msg_set_level(CPL_MSG_INFO);
461 cpl_frameset_join(recipe->frames, usedframes);
462 cpl_frameset_join(recipe->frames, outframes);
463 cpl_frameset_delete(usedframes);
464 cpl_frameset_delete(outframes);
477 muse_create_sky_destroy(cpl_plugin *aPlugin)
481 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
482 recipe = (cpl_recipe *)aPlugin;
488 cpl_parameterlist_delete(recipe->parameters);
505 cpl_plugin_get_info(cpl_pluginlist *aList)
507 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
508 cpl_plugin *plugin = &recipe->interface;
512 helptext = cpl_sprintf(
"%s%s", muse_create_sky_help,
513 muse_create_sky_help_esorex);
515 helptext = cpl_sprintf(
"%s", muse_create_sky_help);
519 cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
520 CPL_PLUGIN_TYPE_RECIPE,
522 "Create night sky model from selected pixels of an exposure of empty sky.",
527 muse_create_sky_create,
528 muse_create_sky_exec,
529 muse_create_sky_destroy);
530 cpl_pluginlist_append(aList, plugin);
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...
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.
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).
double lambdaref
Reference wavelength used for correction of differential atmospheric refraction. The R-band (peak wav...
const char * cr_s
Type of cosmic ray cleaning to use. "Cube" is the standard CR cleaning which works on a datacube...
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.