35 #include "muse_sky_lsf_z.h"
52 static const char *muse_sky_lsf_help =
53 "Compute the LSF model of the slices from the response to a lines spectrum (ARC lamp).";
55 static const char *muse_sky_lsf_help_esorex =
56 "\n\nInput frames for raw frame tag \"PIXTABLE_SKY\":\n"
57 "\n Frame tag Type Req #Fr Description"
58 "\n -------------------- ---- --- --- ------------"
59 "\n PIXTABLE_SKY raw Y 1 Input pixel table"
60 "\n SKY_LINES calib Y 1 Sky line list"
61 "\n SKY_CONTINUUM calib Y 1 Sky continuum spectrum"
62 "\n LSF_TABLE calib . First guess for slice parameters"
63 "\n THROUGHPUT_SKY calib . 1 Detector throughput spectrum"
64 "\n\nProduct frames for raw frame tag \"PIXTABLE_SKY\":\n"
65 "\n Frame tag Level Description"
66 "\n -------------------- -------- ------------"
67 "\n LSF_TABLE final Slice specific parameters"
68 "\n PIXTABLE_REDUCED final Subtracted pixel table (if --store_subtracted=true)";
79 static cpl_recipeconfig *
80 muse_sky_lsf_new_recipeconfig(
void)
82 cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
86 cpl_recipeconfig_set_tag(recipeconfig, tag, 1, 1);
87 cpl_recipeconfig_set_input(recipeconfig, tag,
"SKY_LINES", 1, 1);
88 cpl_recipeconfig_set_input(recipeconfig, tag,
"SKY_CONTINUUM", 1, 1);
89 cpl_recipeconfig_set_input(recipeconfig, tag,
"LSF_TABLE", 0, -1);
90 cpl_recipeconfig_set_input(recipeconfig, tag,
"THROUGHPUT_SKY", 0, 1);
91 cpl_recipeconfig_set_output(recipeconfig, tag,
"LSF_TABLE");
92 cpl_recipeconfig_set_output(recipeconfig, tag,
"PIXTABLE_REDUCED");
108 static cpl_error_code
109 muse_sky_lsf_prepare_header(
const char *aFrametag, cpl_propertylist *aHeader)
111 cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
112 cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
113 if (!strcmp(aFrametag,
"LSF_TABLE")) {
116 "[Angstrom] Wavelength of line l");
119 "[Angstrom] LSF width in IFU i, slice j at the wavelength of line l");
122 "[Angstrom] Wavelength calibration offset in IFU i, slice j at the wavelength of line l");
125 "Relative error of wavelength calibration of IFU i, slice j");
128 "Maximum of the mean normalized error");
129 }
else if (!strcmp(aFrametag,
"PIXTABLE_REDUCED")) {
131 cpl_msg_warning(__func__,
"Frame tag %s is not defined", aFrametag);
132 return CPL_ERROR_ILLEGAL_INPUT;
134 return CPL_ERROR_NONE;
147 static cpl_frame_level
148 muse_sky_lsf_get_frame_level(
const char *aFrametag)
151 return CPL_FRAME_LEVEL_NONE;
153 if (!strcmp(aFrametag,
"LSF_TABLE")) {
154 return CPL_FRAME_LEVEL_FINAL;
156 if (!strcmp(aFrametag,
"PIXTABLE_REDUCED")) {
157 return CPL_FRAME_LEVEL_FINAL;
159 return CPL_FRAME_LEVEL_NONE;
173 muse_sky_lsf_get_frame_mode(
const char *aFrametag)
178 if (!strcmp(aFrametag,
"LSF_TABLE")) {
181 if (!strcmp(aFrametag,
"PIXTABLE_REDUCED")) {
199 muse_sky_lsf_create(cpl_plugin *aPlugin)
203 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
204 recipe = (cpl_recipe *)aPlugin;
212 muse_sky_lsf_new_recipeconfig(),
213 muse_sky_lsf_prepare_header,
214 muse_sky_lsf_get_frame_level,
215 muse_sky_lsf_get_frame_mode);
220 cpl_msg_set_time_on();
224 recipe->parameters = cpl_parameterlist_new();
229 p = cpl_parameter_new_value(
"muse.muse_sky_lsf.lambdamin",
231 "Cut off the data below this wavelength after loading the pixel table(s).",
234 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdamin");
235 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdamin");
237 cpl_parameterlist_append(recipe->parameters, p);
240 p = cpl_parameter_new_value(
"muse.muse_sky_lsf.lambdamax",
242 "Cut off the data above this wavelength after loading the pixel table(s).",
245 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdamax");
246 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdamax");
248 cpl_parameterlist_append(recipe->parameters, p);
251 p = cpl_parameter_new_value(
"muse.muse_sky_lsf.max_iterations",
253 "Maximum number of minimization steps for the slice parameter fit. If set to zero, the slice parameter fit is omitted at all and the first guess is used. Note that this number is meant per degree of freedom, so the total number is 14 times higher.",
256 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"max_iterations");
257 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"max_iterations");
259 cpl_parameterlist_append(recipe->parameters, p);
262 p = cpl_parameter_new_value(
"muse.muse_sky_lsf.store_subtracted",
264 "Output the pixel table after the LSF subtraction.",
267 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"store_subtracted");
268 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"store_subtracted");
270 cpl_parameterlist_append(recipe->parameters, p);
274 p = cpl_parameter_new_value(
"muse.muse_sky_lsf.orig",
276 "If specified, write an additional column containing the original data to the pixel table.",
279 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"orig");
280 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"orig");
282 cpl_parameterlist_append(recipe->parameters, p);
285 p = cpl_parameter_new_value(
"muse.muse_sky_lsf.slice_fit_offset",
287 "Use wavelength offset as slice dependent fit parameter.",
290 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"slice_fit_offset");
291 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slice_fit_offset");
293 cpl_parameterlist_append(recipe->parameters, p);
296 p = cpl_parameter_new_value(
"muse.muse_sky_lsf.slice_fit_refraction",
298 "Use the refraction index as slice dependent fit parameter.",
301 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"slice_fit_refraction");
302 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slice_fit_refraction");
304 cpl_parameterlist_append(recipe->parameters, p);
307 p = cpl_parameter_new_value(
"muse.muse_sky_lsf.slice_fit_slit_width",
309 "Use the slit width as fit parameter.",
312 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"slice_fit_slit_width");
313 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slice_fit_slit_width");
315 cpl_parameterlist_append(recipe->parameters, p);
318 p = cpl_parameter_new_value(
"muse.muse_sky_lsf.slice_fit_bin_width",
320 "Use the bin width as fit parameter.",
323 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"slice_fit_bin_width");
324 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slice_fit_bin_width");
326 cpl_parameterlist_append(recipe->parameters, p);
329 p = cpl_parameter_new_range(
"muse.muse_sky_lsf.slice_fit_lsf_width",
331 "Polynomial order for the LSF width fit parameter. Use -1 to not fit the LSF width.",
336 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"slice_fit_lsf_width");
337 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slice_fit_lsf_width");
339 cpl_parameterlist_append(recipe->parameters, p);
342 p = cpl_parameter_new_range(
"muse.muse_sky_lsf.slice_fit_h3",
344 "Polynomial order for the H3 fit parameter. Use -1 to not fit H3.",
349 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"slice_fit_h3");
350 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slice_fit_h3");
352 cpl_parameterlist_append(recipe->parameters, p);
355 p = cpl_parameter_new_range(
"muse.muse_sky_lsf.slice_fit_h4",
357 "Polynomial order for the H4 fit parameter. Use -1 to not fit H4.",
362 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"slice_fit_h4");
363 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slice_fit_h4");
365 cpl_parameterlist_append(recipe->parameters, p);
368 p = cpl_parameter_new_range(
"muse.muse_sky_lsf.slice_fit_h5",
370 "Polynomial order for the H5 fit parameter. Use -1 to not fit H5.",
375 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"slice_fit_h5");
376 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slice_fit_h5");
378 cpl_parameterlist_append(recipe->parameters, p);
381 p = cpl_parameter_new_range(
"muse.muse_sky_lsf.slice_fit_h6",
383 "Polynomial order for the H6 fit parameter. Use -1 to not fit H6.",
388 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"slice_fit_h6");
389 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"slice_fit_h6");
391 cpl_parameterlist_append(recipe->parameters, p);
411 cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
412 cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
415 p = cpl_parameterlist_find(aParameters,
"muse.muse_sky_lsf.lambdamin");
416 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
417 aParams->
lambdamin = cpl_parameter_get_double(p);
419 p = cpl_parameterlist_find(aParameters,
"muse.muse_sky_lsf.lambdamax");
420 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
421 aParams->
lambdamax = cpl_parameter_get_double(p);
423 p = cpl_parameterlist_find(aParameters,
"muse.muse_sky_lsf.max_iterations");
424 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
427 p = cpl_parameterlist_find(aParameters,
"muse.muse_sky_lsf.store_subtracted");
428 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
431 p = cpl_parameterlist_find(aParameters,
"muse.muse_sky_lsf.orig");
432 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
433 aParams->
orig = cpl_parameter_get_string(p);
435 p = cpl_parameterlist_find(aParameters,
"muse.muse_sky_lsf.slice_fit_offset");
436 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
439 p = cpl_parameterlist_find(aParameters,
"muse.muse_sky_lsf.slice_fit_refraction");
440 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
443 p = cpl_parameterlist_find(aParameters,
"muse.muse_sky_lsf.slice_fit_slit_width");
444 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
447 p = cpl_parameterlist_find(aParameters,
"muse.muse_sky_lsf.slice_fit_bin_width");
448 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
451 p = cpl_parameterlist_find(aParameters,
"muse.muse_sky_lsf.slice_fit_lsf_width");
452 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
455 p = cpl_parameterlist_find(aParameters,
"muse.muse_sky_lsf.slice_fit_h3");
456 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
459 p = cpl_parameterlist_find(aParameters,
"muse.muse_sky_lsf.slice_fit_h4");
460 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
463 p = cpl_parameterlist_find(aParameters,
"muse.muse_sky_lsf.slice_fit_h5");
464 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
467 p = cpl_parameterlist_find(aParameters,
"muse.muse_sky_lsf.slice_fit_h6");
468 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
483 muse_sky_lsf_exec(cpl_plugin *aPlugin)
485 if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
488 cpl_recipe *recipe = (cpl_recipe *)aPlugin;
489 cpl_msg_set_threadid_on();
491 cpl_frameset *usedframes = cpl_frameset_new(),
492 *outframes = cpl_frameset_new();
494 muse_sky_lsf_params_fill(¶ms, recipe->parameters);
496 cpl_errorstate prestate = cpl_errorstate_get();
500 int rc = muse_sky_lsf_compute(proc, ¶ms);
501 cpl_frameset_join(usedframes, proc->
usedFrames);
505 if (!cpl_errorstate_is_equal(prestate)) {
509 cpl_msg_set_level(CPL_MSG_INFO);
519 cpl_frameset_join(recipe->frames, usedframes);
520 cpl_frameset_join(recipe->frames, outframes);
521 cpl_frameset_delete(usedframes);
522 cpl_frameset_delete(outframes);
535 muse_sky_lsf_destroy(cpl_plugin *aPlugin)
539 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
540 recipe = (cpl_recipe *)aPlugin;
546 cpl_parameterlist_delete(recipe->parameters);
563 cpl_plugin_get_info(cpl_pluginlist *aList)
565 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
566 cpl_plugin *plugin = &recipe->interface;
570 helptext = cpl_sprintf(
"%s%s", muse_sky_lsf_help,
571 muse_sky_lsf_help_esorex);
573 helptext = cpl_sprintf(
"%s", muse_sky_lsf_help);
577 cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
578 CPL_PLUGIN_TYPE_RECIPE,
587 muse_sky_lsf_destroy);
588 cpl_pluginlist_append(aList, plugin);
int slice_fit_lsf_width
Polynomial order for the LSF width fit parameter. Use -1 to not fit the LSF width.
int store_subtracted
Output the pixel table after the LSF subtraction.
int slice_fit_slit_width
Use the slit width as fit parameter.
void muse_processing_delete(muse_processing *aProcessing)
Free the muse_processing structure.
const char * orig
If specified, write an additional column containing the original data to the pixel table...
int max_iterations
Maximum number of minimization steps for the slice parameter fit. If set to zero, the slice parameter...
muse_cplframework_type muse_cplframework(void)
Return the CPL framework the recipe is run under.
int slice_fit_h4
Polynomial order for the H4 fit parameter. Use -1 to not fit H4.
double lambdamin
Cut off the data below this wavelength after loading the pixel table(s).
int slice_fit_h5
Polynomial order for the H5 fit parameter. Use -1 to not fit H5.
int slice_fit_h3
Polynomial order for the H3 fit parameter. Use -1 to not fit H3.
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.
int slice_fit_refraction
Use the refraction index as slice dependent fit parameter.
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.
int slice_fit_offset
Use wavelength offset as slice dependent fit parameter.
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.
Structure to hold the parameters of the muse_sky_lsf recipe.
int slice_fit_bin_width
Use the bin width as fit parameter.
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 slice_fit_h6
Polynomial order for the H6 fit parameter. Use -1 to not fit H6.
double lambdamax
Cut off the data above this wavelength after loading the pixel table(s).
cpl_frameset * usedFrames
cpl_error_code muse_processing_prepare_property(cpl_propertylist *, const char *, cpl_type, const char *)
Prepare and check the specified property.