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 . 1 Atmospheric extinction table"
62 "\n STD_RESPONSE calib . 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_TABLE 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", 0, 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_TABLE", 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 k");
141 "[erg/(s cm2 arcsec2)] Flux of the strongest line of group k");
144 "[Angstrom] Estimated wavelength offset for the strongest line of group k");
145 }
else if (!strcmp(aFrametag,
"SKY_CONTINUUM")) {
148 "[erg/(s cm2 arcsec2)] Total flux of the continuum");
151 "[erg/(s cm2 arcsec2 Angstrom)] Maximum (absolute value) of the derivative of the continuum spectrum");
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_create_sky_get_frame_level(
const char *aFrametag)
173 return CPL_FRAME_LEVEL_NONE;
175 if (!strcmp(aFrametag,
"SKY_MASK")) {
176 return CPL_FRAME_LEVEL_INTERMEDIATE;
178 if (!strcmp(aFrametag,
"IMAGE_FOV")) {
179 return CPL_FRAME_LEVEL_INTERMEDIATE;
181 if (!strcmp(aFrametag,
"SKY_SPECTRUM")) {
182 return CPL_FRAME_LEVEL_INTERMEDIATE;
184 if (!strcmp(aFrametag,
"SKY_LINES")) {
185 return CPL_FRAME_LEVEL_FINAL;
187 if (!strcmp(aFrametag,
"SKY_CONTINUUM")) {
188 return CPL_FRAME_LEVEL_FINAL;
190 return CPL_FRAME_LEVEL_NONE;
204 muse_create_sky_get_frame_mode(
const char *aFrametag)
209 if (!strcmp(aFrametag,
"SKY_MASK")) {
212 if (!strcmp(aFrametag,
"IMAGE_FOV")) {
215 if (!strcmp(aFrametag,
"SKY_SPECTRUM")) {
218 if (!strcmp(aFrametag,
"SKY_LINES")) {
221 if (!strcmp(aFrametag,
"SKY_CONTINUUM")) {
239 muse_create_sky_create(cpl_plugin *aPlugin)
243 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
244 recipe = (cpl_recipe *)aPlugin;
252 muse_create_sky_new_recipeconfig(),
253 muse_create_sky_prepare_header,
254 muse_create_sky_get_frame_level,
255 muse_create_sky_get_frame_mode);
260 cpl_msg_set_time_on();
264 recipe->parameters = cpl_parameterlist_new();
269 p = cpl_parameter_new_value(
"muse.muse_create_sky.fraction",
271 "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.",
272 "muse.muse_create_sky",
274 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"fraction");
275 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"fraction");
277 cpl_parameterlist_append(recipe->parameters, p);
280 p = cpl_parameter_new_value(
"muse.muse_create_sky.sampling",
282 "Spectral sampling of the sky spectrum [Angstrom].",
283 "muse.muse_create_sky",
285 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"sampling");
286 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"sampling");
287 if (!getenv(
"MUSE_EXPERT_USER")) {
288 cpl_parameter_disable(p, CPL_PARAMETER_MODE_CLI);
291 cpl_parameterlist_append(recipe->parameters, p);
294 p = cpl_parameter_new_value(
"muse.muse_create_sky.csampling",
296 "Spectral sampling of the continuum spectrum [Angstrom].",
297 "muse.muse_create_sky",
299 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"csampling");
300 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"csampling");
301 if (!getenv(
"MUSE_EXPERT_USER")) {
302 cpl_parameter_disable(p, CPL_PARAMETER_MODE_CLI);
305 cpl_parameterlist_append(recipe->parameters, p);
308 p = cpl_parameter_new_enum(
"muse.muse_create_sky.cr",
310 "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.",
311 "muse.muse_create_sky",
312 (
const char *)
"cube",
314 (
const char *)
"none",
315 (
const char *)
"cube",
316 (
const char *)
"spectrum");
317 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"cr");
318 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"cr");
319 if (!getenv(
"MUSE_EXPERT_USER")) {
320 cpl_parameter_disable(p, CPL_PARAMETER_MODE_CLI);
323 cpl_parameterlist_append(recipe->parameters, p);
326 p = cpl_parameter_new_value(
"muse.muse_create_sky.lambdamin",
328 "Cut off the data below this wavelength after loading the pixel table(s).",
329 "muse.muse_create_sky",
331 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdamin");
332 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdamin");
334 cpl_parameterlist_append(recipe->parameters, p);
337 p = cpl_parameter_new_value(
"muse.muse_create_sky.lambdamax",
339 "Cut off the data above this wavelength after loading the pixel table(s).",
340 "muse.muse_create_sky",
342 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdamax");
343 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdamax");
345 cpl_parameterlist_append(recipe->parameters, p);
365 cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
366 cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
369 p = cpl_parameterlist_find(aParameters,
"muse.muse_create_sky.fraction");
370 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
371 aParams->
fraction = cpl_parameter_get_double(p);
373 p = cpl_parameterlist_find(aParameters,
"muse.muse_create_sky.sampling");
374 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
375 aParams->
sampling = cpl_parameter_get_double(p);
377 p = cpl_parameterlist_find(aParameters,
"muse.muse_create_sky.csampling");
378 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
379 aParams->
csampling = cpl_parameter_get_double(p);
381 p = cpl_parameterlist_find(aParameters,
"muse.muse_create_sky.cr");
382 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
383 aParams->
cr_s = cpl_parameter_get_string(p);
385 (!strcasecmp(aParams->
cr_s,
"none")) ? MUSE_CREATE_SKY_PARAM_CR_NONE :
386 (!strcasecmp(aParams->
cr_s,
"cube")) ? MUSE_CREATE_SKY_PARAM_CR_CUBE :
387 (!strcasecmp(aParams->
cr_s,
"spectrum")) ? MUSE_CREATE_SKY_PARAM_CR_SPECTRUM :
388 MUSE_CREATE_SKY_PARAM_CR_INVALID_VALUE;
389 cpl_ensure_code(aParams->
cr != MUSE_CREATE_SKY_PARAM_CR_INVALID_VALUE,
390 CPL_ERROR_ILLEGAL_INPUT);
392 p = cpl_parameterlist_find(aParameters,
"muse.muse_create_sky.lambdamin");
393 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
394 aParams->
lambdamin = cpl_parameter_get_double(p);
396 p = cpl_parameterlist_find(aParameters,
"muse.muse_create_sky.lambdamax");
397 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
398 aParams->
lambdamax = cpl_parameter_get_double(p);
412 muse_create_sky_exec(cpl_plugin *aPlugin)
414 if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
417 cpl_recipe *recipe = (cpl_recipe *)aPlugin;
418 cpl_msg_set_threadid_on();
420 cpl_frameset *usedframes = cpl_frameset_new(),
421 *outframes = cpl_frameset_new();
423 muse_create_sky_params_fill(¶ms, recipe->parameters);
425 cpl_errorstate prestate = cpl_errorstate_get();
429 int rc = muse_create_sky_compute(proc, ¶ms);
430 cpl_frameset_join(usedframes, proc->
usedFrames);
434 if (!cpl_errorstate_is_equal(prestate)) {
438 cpl_msg_set_level(CPL_MSG_INFO);
448 cpl_frameset_join(recipe->frames, usedframes);
449 cpl_frameset_join(recipe->frames, outframes);
450 cpl_frameset_delete(usedframes);
451 cpl_frameset_delete(outframes);
464 muse_create_sky_destroy(cpl_plugin *aPlugin)
468 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
469 recipe = (cpl_recipe *)aPlugin;
475 cpl_parameterlist_delete(recipe->parameters);
492 cpl_plugin_get_info(cpl_pluginlist *aList)
494 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
495 cpl_plugin *plugin = &recipe->interface;
499 helptext = cpl_sprintf(
"%s%s", muse_create_sky_help,
500 muse_create_sky_help_esorex);
502 helptext = cpl_sprintf(
"%s", muse_create_sky_help);
506 cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
507 CPL_PLUGIN_TYPE_RECIPE,
509 "Create night sky model from selected pixels of an exposure of empty sky.",
514 muse_create_sky_create,
515 muse_create_sky_exec,
516 muse_create_sky_destroy);
517 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...
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.
cpl_frameset * outputFrames
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).
const char * cr_s
Type of cosmic ray cleaning to use. "Cube" is the standard CR cleaning which works on a datacube...
cpl_frameset * usedFrames
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.