35 #include "muse_lsf_z.h"
51 static const char *muse_lsf_help =
52 "Compute the slice and wavelength dependent LSF from a lines spectrum (ARC lamp).";
54 static const char *muse_lsf_help_esorex =
55 "\n\nInput frames for raw frame tag \"ARC\":\n"
56 "\n Frame tag Type Req #Fr Description"
57 "\n -------------------- ---- --- --- ------------"
58 "\n ARC raw Y Raw arc lamp exposures"
59 "\n MASTER_BIAS calib Y 1 Master bias"
60 "\n MASTER_DARK calib . 1 Master dark"
61 "\n MASTER_FLAT calib . 1 Master flat"
62 "\n TRACE_TABLE calib Y 1 Trace table"
63 "\n WAVECAL_TABLE calib Y 1 Wavelength calibration table"
64 "\n BADPIX_TABLE calib . 1 Known bad pixels"
65 "\n LINE_CATALOG calib Y 1 Arc line catalog"
66 "\n\nProduct frames for raw frame tag \"ARC\":\n"
67 "\n Frame tag Level Description"
68 "\n -------------------- -------- ------------"
69 "\n LSF_PROFILE final Slice specific LSF parameters (if --lsf=true)"
70 "\n PIXTABLE_SUBTRACTED final Subtracted pixel table (if --save_subtracted=true), for debugging.";
81 static cpl_recipeconfig *
82 muse_lsf_new_recipeconfig(
void)
84 cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
88 cpl_recipeconfig_set_tag(recipeconfig, tag, 1, -1);
89 cpl_recipeconfig_set_input(recipeconfig, tag,
"MASTER_BIAS", 1, 1);
90 cpl_recipeconfig_set_input(recipeconfig, tag,
"MASTER_DARK", -1, 1);
91 cpl_recipeconfig_set_input(recipeconfig, tag,
"MASTER_FLAT", -1, 1);
92 cpl_recipeconfig_set_input(recipeconfig, tag,
"TRACE_TABLE", 1, 1);
93 cpl_recipeconfig_set_input(recipeconfig, tag,
"WAVECAL_TABLE", 1, 1);
94 cpl_recipeconfig_set_input(recipeconfig, tag,
"BADPIX_TABLE", -1, 1);
95 cpl_recipeconfig_set_input(recipeconfig, tag,
"LINE_CATALOG", 1, 1);
96 cpl_recipeconfig_set_output(recipeconfig, tag,
"LSF_PROFILE");
97 cpl_recipeconfig_set_output(recipeconfig, tag,
"PIXTABLE_SUBTRACTED");
113 static cpl_error_code
114 muse_lsf_prepare_header(
const char *aFrametag, cpl_propertylist *aHeader)
116 cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
117 cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
118 if (!strcmp(aFrametag,
"LSF_PROFILE")) {
121 "Mean FWHM of the LSF slice j");
124 "Standard deviation of the LSF in slice j");
127 "Minimum FWHM of the LSF in slice j");
130 "Maximum FWHM of the LSF in slice j");
131 }
else if (!strcmp(aFrametag,
"PIXTABLE_SUBTRACTED")) {
133 cpl_msg_warning(__func__,
"Frame tag %s is not defined", aFrametag);
134 return CPL_ERROR_ILLEGAL_INPUT;
136 return CPL_ERROR_NONE;
149 static cpl_frame_level
150 muse_lsf_get_frame_level(
const char *aFrametag)
153 return CPL_FRAME_LEVEL_NONE;
155 if (!strcmp(aFrametag,
"LSF_PROFILE")) {
156 return CPL_FRAME_LEVEL_FINAL;
158 if (!strcmp(aFrametag,
"PIXTABLE_SUBTRACTED")) {
159 return CPL_FRAME_LEVEL_FINAL;
161 return CPL_FRAME_LEVEL_NONE;
175 muse_lsf_get_frame_mode(
const char *aFrametag)
180 if (!strcmp(aFrametag,
"LSF_PROFILE")) {
183 if (!strcmp(aFrametag,
"PIXTABLE_SUBTRACTED")) {
201 muse_lsf_create(cpl_plugin *aPlugin)
205 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
206 recipe = (cpl_recipe *)aPlugin;
214 muse_lsf_new_recipeconfig(),
215 muse_lsf_prepare_header,
216 muse_lsf_get_frame_level,
217 muse_lsf_get_frame_mode);
222 cpl_msg_set_time_on();
226 recipe->parameters = cpl_parameterlist_new();
231 p = cpl_parameter_new_range(
"muse.muse_lsf.nifu",
233 "IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in parallel.",
238 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"nifu");
239 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"nifu");
241 cpl_parameterlist_append(recipe->parameters, p);
244 p = cpl_parameter_new_value(
"muse.muse_lsf.overscan",
246 "If this is \"none\", stop when detecting discrepant overscan levels (see ovscsigma), for \"offset\" it assumes that the mean overscan level represents the real offset in the bias levels of the exposures involved, and adjusts the data accordingly; for \"vpoly\", a polynomial is fit to the vertical overscan and subtracted from the whole quadrant.",
248 (
const char *)
"vpoly");
249 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"overscan");
250 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"overscan");
252 cpl_parameterlist_append(recipe->parameters, p);
255 p = cpl_parameter_new_value(
"muse.muse_lsf.ovscreject",
257 "This influences how values are rejected when computing overscan statistics. Either no rejection at all (\"none\"), rejection using the DCR algorithm (\"dcr\"), or rejection using an iterative constant fit (\"fit\").",
259 (
const char *)
"dcr");
260 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscreject");
261 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscreject");
263 cpl_parameterlist_append(recipe->parameters, p);
266 p = cpl_parameter_new_value(
"muse.muse_lsf.ovscsigma",
268 "If the deviation of mean overscan levels between a raw input image and the reference image is higher than |ovscsigma x stdev|, stop the processing. If overscan=\"vpoly\", this is used as sigma rejection level for the iterative polynomial fit (the level comparison is then done afterwards with |100 x stdev| to guard against incompatible settings). Has no effect for overscan=\"offset\".",
271 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscsigma");
272 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscsigma");
274 cpl_parameterlist_append(recipe->parameters, p);
277 p = cpl_parameter_new_value(
"muse.muse_lsf.ovscignore",
279 "The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when computing statistics or fits.",
282 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscignore");
283 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscignore");
285 cpl_parameterlist_append(recipe->parameters, p);
288 p = cpl_parameter_new_enum(
"muse.muse_lsf.combine",
290 "Type of lampwise image combination to use.",
292 (
const char *)
"sigclip",
294 (
const char *)
"average",
295 (
const char *)
"median",
296 (
const char *)
"minmax",
297 (
const char *)
"sigclip");
298 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"combine");
299 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"combine");
301 cpl_parameterlist_append(recipe->parameters, p);
304 p = cpl_parameter_new_value(
"muse.muse_lsf.save_subtracted",
306 "Save the pixel table after the LSF subtraction.",
309 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"save_subtracted");
310 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"save_subtracted");
312 cpl_parameterlist_append(recipe->parameters, p);
315 p = cpl_parameter_new_value(
"muse.muse_lsf.line_quality",
317 "Minimal quality flag in line catalog for selection",
320 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"line_quality");
321 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"line_quality");
323 cpl_parameterlist_append(recipe->parameters, p);
326 p = cpl_parameter_new_value(
"muse.muse_lsf.merge",
328 "Merge output products from different IFUs into a common file.",
331 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"merge");
332 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"merge");
334 cpl_parameterlist_append(recipe->parameters, p);
354 cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
355 cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
358 p = cpl_parameterlist_find(aParameters,
"muse.muse_lsf.nifu");
359 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
360 aParams->
nifu = cpl_parameter_get_int(p);
362 p = cpl_parameterlist_find(aParameters,
"muse.muse_lsf.overscan");
363 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
364 aParams->
overscan = cpl_parameter_get_string(p);
366 p = cpl_parameterlist_find(aParameters,
"muse.muse_lsf.ovscreject");
367 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
368 aParams->
ovscreject = cpl_parameter_get_string(p);
370 p = cpl_parameterlist_find(aParameters,
"muse.muse_lsf.ovscsigma");
371 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
372 aParams->
ovscsigma = cpl_parameter_get_double(p);
374 p = cpl_parameterlist_find(aParameters,
"muse.muse_lsf.ovscignore");
375 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
376 aParams->
ovscignore = cpl_parameter_get_int(p);
378 p = cpl_parameterlist_find(aParameters,
"muse.muse_lsf.combine");
379 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
380 aParams->
combine_s = cpl_parameter_get_string(p);
382 (!strcasecmp(aParams->
combine_s,
"average")) ? MUSE_LSF_PARAM_COMBINE_AVERAGE :
383 (!strcasecmp(aParams->
combine_s,
"median")) ? MUSE_LSF_PARAM_COMBINE_MEDIAN :
384 (!strcasecmp(aParams->
combine_s,
"minmax")) ? MUSE_LSF_PARAM_COMBINE_MINMAX :
385 (!strcasecmp(aParams->
combine_s,
"sigclip")) ? MUSE_LSF_PARAM_COMBINE_SIGCLIP :
386 MUSE_LSF_PARAM_COMBINE_INVALID_VALUE;
387 cpl_ensure_code(aParams->
combine != MUSE_LSF_PARAM_COMBINE_INVALID_VALUE,
388 CPL_ERROR_ILLEGAL_INPUT);
390 p = cpl_parameterlist_find(aParameters,
"muse.muse_lsf.save_subtracted");
391 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
394 p = cpl_parameterlist_find(aParameters,
"muse.muse_lsf.line_quality");
395 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
398 p = cpl_parameterlist_find(aParameters,
"muse.muse_lsf.merge");
399 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
400 aParams->
merge = cpl_parameter_get_bool(p);
414 muse_lsf_exec(cpl_plugin *aPlugin)
416 if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
419 cpl_recipe *recipe = (cpl_recipe *)aPlugin;
420 cpl_msg_set_threadid_on();
422 cpl_frameset *usedframes = cpl_frameset_new(),
423 *outframes = cpl_frameset_new();
425 muse_lsf_params_fill(¶ms, recipe->parameters);
427 cpl_errorstate prestate = cpl_errorstate_get();
429 if (params.
nifu < -1 || params.
nifu > kMuseNumIFUs) {
430 cpl_msg_error(__func__,
"Please specify a valid IFU number (between 1 and "
431 "%d), 0 (to process all IFUs consecutively), or -1 (to "
432 "process all IFUs in parallel) using --nifu.", kMuseNumIFUs);
436 cpl_boolean donotmerge = CPL_FALSE;
438 if (params.
nifu > 0) {
441 rc = muse_lsf_compute(proc, ¶ms);
442 cpl_frameset_join(usedframes, proc->
usedframes);
443 cpl_frameset_join(outframes, proc->
outframes);
445 donotmerge = CPL_TRUE;
446 }
else if (params.
nifu < 0) {
447 int *rcs = cpl_calloc(kMuseNumIFUs,
sizeof(
int));
449 #pragma omp parallel for default(none) \
450 shared(outframes, params, rcs, recipe, usedframes)
451 for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
457 int *rci = rcs + (nifu - 1);
458 *rci = muse_lsf_compute(proc, pars);
459 if (rci && cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
463 #pragma omp critical(muse_processing_used_frames)
464 cpl_frameset_join(usedframes, proc->
usedframes);
465 #pragma omp critical(muse_processing_output_frames)
466 cpl_frameset_join(outframes, proc->
outframes);
471 for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
472 if (rcs[nifu-1] != 0) {
478 for (params.
nifu = 1; params.
nifu <= kMuseNumIFUs && !rc; params.
nifu++) {
481 rc = muse_lsf_compute(proc, ¶ms);
482 if (rc && cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
485 cpl_frameset_join(usedframes, proc->
usedframes);
486 cpl_frameset_join(outframes, proc->
outframes);
490 UNUSED_ARGUMENT(donotmerge);
492 if (!cpl_errorstate_is_equal(prestate)) {
496 cpl_msg_set_level(CPL_MSG_INFO);
503 if (params.
merge && !donotmerge) {
504 muse_utils_frameset_merge_frames(outframes);
512 cpl_frameset_join(recipe->frames, usedframes);
513 cpl_frameset_join(recipe->frames, outframes);
514 cpl_frameset_delete(usedframes);
515 cpl_frameset_delete(outframes);
528 muse_lsf_destroy(cpl_plugin *aPlugin)
532 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
533 recipe = (cpl_recipe *)aPlugin;
539 cpl_parameterlist_delete(recipe->parameters);
556 cpl_plugin_get_info(cpl_pluginlist *aList)
558 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
559 cpl_plugin *plugin = &recipe->interface;
563 helptext = cpl_sprintf(
"%s%s", muse_lsf_help,
564 muse_lsf_help_esorex);
566 helptext = cpl_sprintf(
"%s", muse_lsf_help);
570 cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
571 CPL_PLUGIN_TYPE_RECIPE,
581 cpl_pluginlist_append(aList, plugin);
void muse_processing_delete(muse_processing *aProcessing)
Free the muse_processing structure.
double ovscsigma
If the deviation of mean overscan levels between a raw input image and the reference image is higher ...
muse_cplframework_type muse_cplframework(void)
Return the CPL framework the recipe is run under.
const char * ovscreject
This influences how values are rejected when computing overscan statistics. Either no rejection at al...
int nifu
IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in ...
const char * overscan
If this is "none", stop when detecting discrepant overscan levels (see ovscsigma), for "offset" it assumes that the mean overscan level represents the real offset in the bias levels of the exposures involved, and adjusts the data accordingly; for "vpoly", a polynomial is fit to the vertical overscan and subtracted from the whole quadrant.
int save_subtracted
Save the pixel table after the LSF subtraction.
int merge
Merge output products from different IFUs into a common file.
int ovscignore
The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when com...
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.
const char * combine_s
Type of lampwise image combination to use. (as string)
Structure to hold the parameters of the muse_lsf recipe.
int line_quality
Minimal quality flag in line catalog for selection.
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 combine
Type of lampwise image combination to use.
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.
cpl_error_code muse_processing_prepare_property(cpl_propertylist *, const char *, cpl_type, const char *)
Prepare and check the specified property.