35 #include "muse_skyflat_z.h"
69 static const char *muse_skyflat_help =
70 "Processing trims the raw data and records the overscan statistics, subtracts the bias (taking account of the overscan, if --overscan is not &none&), and optionally, the dark from each raw input image, converts them from adu to count, and combines the exposures using input parameters. Bad pixels are then interpolated from surrounding good ones before computing the integrated flux in all slices by summing the pixel values of all within the boundaries given by the trace table and the --lambdamin and --lambdamax parameters. The integrated flux value is then later used as estimate for the relative throughput of each IFU, to scale values to a common flux level. Since twilight sky flat-fields will have an illumination similar to that of science exposures, they should preferably be used as input to this recipe. Normal lamp flat-fields can be used, if twilight sky flats are not available. The output image is not further used by the pipeline, only the FITS header with the integrated flux is propagated to the science data.";
72 static const char *muse_skyflat_help_esorex =
73 "\n\nInput frames for raw frame tag \"SKYFLAT\":\n"
74 "\n Frame tag Type Req #Fr Description"
75 "\n -------------------- ---- --- --- ------------"
76 "\n SKYFLAT raw Y >=3 Master twilight skyflat"
77 "\n MASTER_BIAS calib Y 1 Master bias"
78 "\n MASTER_DARK calib . 1 Master dark"
79 "\n BADPIX_TABLE calib . 1 Known bad pixels"
80 "\n TRACE_TABLE calib Y 1 Tracing table for all slices"
81 "\n WAVECAL_TABLE calib Y 1 Wavelength calibration table"
82 "\n\nProduct frames for raw frame tag \"SKYFLAT\":\n"
83 "\n Frame tag Level Description"
84 "\n -------------------- -------- ------------"
85 "\n MASTER_SKYFLAT final Master twilight skyflat";
96 static cpl_recipeconfig *
97 muse_skyflat_new_recipeconfig(
void)
99 cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
103 cpl_recipeconfig_set_tag(recipeconfig, tag, 3, -1);
104 cpl_recipeconfig_set_input(recipeconfig, tag,
"MASTER_BIAS", 1, 1);
105 cpl_recipeconfig_set_input(recipeconfig, tag,
"MASTER_DARK", -1, 1);
106 cpl_recipeconfig_set_input(recipeconfig, tag,
"BADPIX_TABLE", -1, 1);
107 cpl_recipeconfig_set_input(recipeconfig, tag,
"TRACE_TABLE", 1, 1);
108 cpl_recipeconfig_set_input(recipeconfig, tag,
"WAVECAL_TABLE", 1, 1);
109 cpl_recipeconfig_set_output(recipeconfig, tag,
"MASTER_SKYFLAT");
125 static cpl_error_code
126 muse_skyflat_prepare_header(
const char *aFrametag, cpl_propertylist *aHeader)
128 cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
129 cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
130 if (!strcmp(aFrametag,
"MASTER_SKYFLAT")) {
133 "Median value of raw flat i in input list");
136 "Mean value of raw flat i in input list");
139 "Standard deviation of raw flat i in input list");
142 "Minimum value of raw flat i in input list");
145 "Maximum value of raw flat i in input list");
148 "Number of saturated pixels in raw flat i in input list");
151 "Median value of the master flat");
154 "Mean value of the master flat");
157 "Standard deviation of the master flat");
160 "Minimum value of the master flat");
163 "Maximum value of the master flat");
166 "Number of saturated pixels in output data");
169 "Flux integrated over all slices");
172 "Flux integrated over slice j");
174 cpl_msg_warning(__func__,
"Frame tag %s is not defined", aFrametag);
175 return CPL_ERROR_ILLEGAL_INPUT;
177 return CPL_ERROR_NONE;
190 static cpl_frame_level
191 muse_skyflat_get_frame_level(
const char *aFrametag)
194 return CPL_FRAME_LEVEL_NONE;
196 if (!strcmp(aFrametag,
"MASTER_SKYFLAT")) {
197 return CPL_FRAME_LEVEL_FINAL;
199 return CPL_FRAME_LEVEL_NONE;
213 muse_skyflat_get_frame_mode(
const char *aFrametag)
218 if (!strcmp(aFrametag,
"MASTER_SKYFLAT")) {
236 muse_skyflat_create(cpl_plugin *aPlugin)
240 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
241 recipe = (cpl_recipe *)aPlugin;
249 muse_skyflat_new_recipeconfig(),
250 muse_skyflat_prepare_header,
251 muse_skyflat_get_frame_level,
252 muse_skyflat_get_frame_mode);
257 cpl_msg_set_time_on();
261 recipe->parameters = cpl_parameterlist_new();
266 p = cpl_parameter_new_range(
"muse.muse_skyflat.nifu",
268 "IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in parallel.",
273 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"nifu");
274 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"nifu");
276 cpl_parameterlist_append(recipe->parameters, p);
279 p = cpl_parameter_new_value(
"muse.muse_skyflat.overscan",
281 "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.",
283 (
const char *)
"vpoly");
284 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"overscan");
285 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"overscan");
287 cpl_parameterlist_append(recipe->parameters, p);
290 p = cpl_parameter_new_value(
"muse.muse_skyflat.ovscreject",
292 "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\").",
294 (
const char *)
"dcr");
295 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscreject");
296 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscreject");
298 cpl_parameterlist_append(recipe->parameters, p);
301 p = cpl_parameter_new_value(
"muse.muse_skyflat.ovscsigma",
303 "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. Has no effect for overscan=\"offset\".",
306 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscsigma");
307 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscsigma");
309 cpl_parameterlist_append(recipe->parameters, p);
312 p = cpl_parameter_new_value(
"muse.muse_skyflat.ovscignore",
314 "The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when computing statistics or fits.",
317 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscignore");
318 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscignore");
320 cpl_parameterlist_append(recipe->parameters, p);
323 p = cpl_parameter_new_enum(
"muse.muse_skyflat.combine",
325 "Type of combination to use",
327 (
const char *)
"sigclip",
329 (
const char *)
"average",
330 (
const char *)
"median",
331 (
const char *)
"minmax",
332 (
const char *)
"sigclip");
333 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"combine");
334 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"combine");
336 cpl_parameterlist_append(recipe->parameters, p);
339 p = cpl_parameter_new_value(
"muse.muse_skyflat.nlow",
341 "Number of minimum pixels to reject with minmax",
344 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"nlow");
345 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"nlow");
347 cpl_parameterlist_append(recipe->parameters, p);
350 p = cpl_parameter_new_value(
"muse.muse_skyflat.nhigh",
352 "Number of maximum pixels to reject with minmax",
355 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"nhigh");
356 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"nhigh");
358 cpl_parameterlist_append(recipe->parameters, p);
361 p = cpl_parameter_new_value(
"muse.muse_skyflat.nkeep",
363 "Number of pixels to keep with minmax",
366 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"nkeep");
367 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"nkeep");
369 cpl_parameterlist_append(recipe->parameters, p);
372 p = cpl_parameter_new_value(
"muse.muse_skyflat.lsigma",
374 "Low sigma for pixel rejection with sigclip",
377 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lsigma");
378 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lsigma");
380 cpl_parameterlist_append(recipe->parameters, p);
383 p = cpl_parameter_new_value(
"muse.muse_skyflat.hsigma",
385 "High sigma for pixel rejection with sigclip",
388 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"hsigma");
389 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"hsigma");
391 cpl_parameterlist_append(recipe->parameters, p);
394 p = cpl_parameter_new_value(
"muse.muse_skyflat.scale",
396 "Scale the individual images to a common exposure time before combining them.",
399 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"scale");
400 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"scale");
402 cpl_parameterlist_append(recipe->parameters, p);
405 p = cpl_parameter_new_value(
"muse.muse_skyflat.lambdamin",
407 "Minimum wavelength to use for flux integration.",
410 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdamin");
411 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdamin");
413 cpl_parameterlist_append(recipe->parameters, p);
416 p = cpl_parameter_new_value(
"muse.muse_skyflat.lambdamax",
418 "Maximum wavelength to use for flux integration.",
421 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lambdamax");
422 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lambdamax");
424 cpl_parameterlist_append(recipe->parameters, p);
427 p = cpl_parameter_new_value(
"muse.muse_skyflat.normalize",
429 "Normalize the master skyflat to the flux integrated over the given wavelength range.",
432 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"normalize");
433 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"normalize");
435 cpl_parameterlist_append(recipe->parameters, p);
455 cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
456 cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
459 p = cpl_parameterlist_find(aParameters,
"muse.muse_skyflat.nifu");
460 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
461 aParams->
nifu = cpl_parameter_get_int(p);
463 p = cpl_parameterlist_find(aParameters,
"muse.muse_skyflat.overscan");
464 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
465 aParams->
overscan = cpl_parameter_get_string(p);
467 p = cpl_parameterlist_find(aParameters,
"muse.muse_skyflat.ovscreject");
468 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
469 aParams->
ovscreject = cpl_parameter_get_string(p);
471 p = cpl_parameterlist_find(aParameters,
"muse.muse_skyflat.ovscsigma");
472 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
473 aParams->
ovscsigma = cpl_parameter_get_double(p);
475 p = cpl_parameterlist_find(aParameters,
"muse.muse_skyflat.ovscignore");
476 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
477 aParams->
ovscignore = cpl_parameter_get_int(p);
479 p = cpl_parameterlist_find(aParameters,
"muse.muse_skyflat.combine");
480 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
481 aParams->
combine_s = cpl_parameter_get_string(p);
483 (!strcasecmp(aParams->
combine_s,
"average")) ? MUSE_SKYFLAT_PARAM_COMBINE_AVERAGE :
484 (!strcasecmp(aParams->
combine_s,
"median")) ? MUSE_SKYFLAT_PARAM_COMBINE_MEDIAN :
485 (!strcasecmp(aParams->
combine_s,
"minmax")) ? MUSE_SKYFLAT_PARAM_COMBINE_MINMAX :
486 (!strcasecmp(aParams->
combine_s,
"sigclip")) ? MUSE_SKYFLAT_PARAM_COMBINE_SIGCLIP :
487 MUSE_SKYFLAT_PARAM_COMBINE_INVALID_VALUE;
488 cpl_ensure_code(aParams->
combine != MUSE_SKYFLAT_PARAM_COMBINE_INVALID_VALUE,
489 CPL_ERROR_ILLEGAL_INPUT);
491 p = cpl_parameterlist_find(aParameters,
"muse.muse_skyflat.nlow");
492 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
493 aParams->
nlow = cpl_parameter_get_int(p);
495 p = cpl_parameterlist_find(aParameters,
"muse.muse_skyflat.nhigh");
496 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
497 aParams->
nhigh = cpl_parameter_get_int(p);
499 p = cpl_parameterlist_find(aParameters,
"muse.muse_skyflat.nkeep");
500 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
501 aParams->
nkeep = cpl_parameter_get_int(p);
503 p = cpl_parameterlist_find(aParameters,
"muse.muse_skyflat.lsigma");
504 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
505 aParams->
lsigma = cpl_parameter_get_double(p);
507 p = cpl_parameterlist_find(aParameters,
"muse.muse_skyflat.hsigma");
508 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
509 aParams->
hsigma = cpl_parameter_get_double(p);
511 p = cpl_parameterlist_find(aParameters,
"muse.muse_skyflat.scale");
512 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
513 aParams->
scale = cpl_parameter_get_bool(p);
515 p = cpl_parameterlist_find(aParameters,
"muse.muse_skyflat.lambdamin");
516 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
517 aParams->
lambdamin = cpl_parameter_get_double(p);
519 p = cpl_parameterlist_find(aParameters,
"muse.muse_skyflat.lambdamax");
520 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
521 aParams->
lambdamax = cpl_parameter_get_double(p);
523 p = cpl_parameterlist_find(aParameters,
"muse.muse_skyflat.normalize");
524 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
525 aParams->
normalize = cpl_parameter_get_bool(p);
539 muse_skyflat_exec(cpl_plugin *aPlugin)
541 if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
544 cpl_recipe *recipe = (cpl_recipe *)aPlugin;
545 cpl_msg_set_threadid_on();
547 cpl_frameset *usedframes = cpl_frameset_new(),
548 *outframes = cpl_frameset_new();
550 muse_skyflat_params_fill(¶ms, recipe->parameters);
552 cpl_errorstate prestate = cpl_errorstate_get();
554 if (params.
nifu < -1 || params.
nifu > kMuseNumIFUs) {
555 cpl_msg_error(__func__,
"Please specify a valid IFU number (between 1 and "
556 "%d), 0 (to process all IFUs consecutively), or -1 (to "
557 "process all IFUs in parallel) using --nifu.", kMuseNumIFUs);
562 if (params.
nifu > 0) {
565 rc = muse_skyflat_compute(proc, ¶ms);
566 cpl_frameset_join(usedframes, proc->
usedFrames);
569 }
else if (params.
nifu < 0) {
570 int *rcs = cpl_calloc(kMuseNumIFUs,
sizeof(
int));
572 #pragma omp parallel for default(none) \
573 shared(outframes, params, rcs, recipe, usedframes)
574 for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
580 int *rci = rcs + (nifu - 1);
581 *rci = muse_skyflat_compute(proc, pars);
582 if (rci && cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
586 #pragma omp critical(muse_processing_used_frames)
587 cpl_frameset_join(usedframes, proc->
usedFrames);
588 #pragma omp critical(muse_processing_output_frames)
594 for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
595 if (rcs[nifu-1] != 0) {
601 for (params.
nifu = 1; params.
nifu <= kMuseNumIFUs && !rc; params.
nifu++) {
604 rc = muse_skyflat_compute(proc, ¶ms);
605 if (rc && cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
608 cpl_frameset_join(usedframes, proc->
usedFrames);
614 if (!cpl_errorstate_is_equal(prestate)) {
618 cpl_msg_set_level(CPL_MSG_INFO);
628 cpl_frameset_join(recipe->frames, usedframes);
629 cpl_frameset_join(recipe->frames, outframes);
630 cpl_frameset_delete(usedframes);
631 cpl_frameset_delete(outframes);
644 muse_skyflat_destroy(cpl_plugin *aPlugin)
648 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
649 recipe = (cpl_recipe *)aPlugin;
655 cpl_parameterlist_delete(recipe->parameters);
672 cpl_plugin_get_info(cpl_pluginlist *aList)
674 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
675 cpl_plugin *plugin = &recipe->interface;
679 helptext = cpl_sprintf(
"%s%s", muse_skyflat_help,
680 muse_skyflat_help_esorex);
682 helptext = cpl_sprintf(
"%s", muse_skyflat_help);
686 cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
687 CPL_PLUGIN_TYPE_RECIPE,
689 "Combine several separate (twilight) sky flat-fields into one master skyflat, and compute the integrated flux within the given wavelength range of the IFU.",
696 muse_skyflat_destroy);
697 cpl_pluginlist_append(aList, plugin);
Structure to hold the parameters of the muse_skyflat recipe.
void muse_processing_delete(muse_processing *aProcessing)
Free the muse_processing structure.
int combine
Type of combination to use.
const char * ovscreject
This influences how values are rejected when computing overscan statistics. Either no rejection at al...
muse_cplframework_type muse_cplframework(void)
Return the CPL framework the recipe is run under.
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 nlow
Number of minimum pixels to reject with minmax.
double ovscsigma
If the deviation of mean overscan levels between a raw input image and the reference image is higher ...
double lsigma
Low sigma for pixel rejection with sigclip.
int ovscignore
The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when com...
double hsigma
High sigma for pixel rejection with sigclip.
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.
int nhigh
Number of maximum pixels to reject with minmax.
const char * combine_s
Type of combination to use (as string)
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.
int nkeep
Number of pixels to keep with minmax.
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 normalize
Normalize the master skyflat to the flux integrated over the given wavelength range.
int scale
Scale the individual images to a common exposure time before combining them.
cpl_frameset * usedFrames
int nifu
IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in ...
double lambdamax
Maximum wavelength to use for flux integration.
double lambdamin
Minimum wavelength to use for flux integration.
cpl_error_code muse_processing_prepare_property(cpl_propertylist *, const char *, cpl_type, const char *)
Prepare and check the specified property.