35 #include "muse_bias_z.h"
63 static const char *muse_bias_help =
64 "This recipe combines several separate bias images into one master bias file. The master bias contains the combined pixel values, in adu, of the raw bias exposures, with respect to the image combination method used. Processing trims the raw data and records the overscan statistics, corrects the data levels using the overscan (if overscan is not &none&) and combines the exposures using input parameters. The read-out noise is computed for each quadrant of the raw input images and stored as QC parameter. The variance extension is filled with an initial value accordingly, before image combination. Further QC statistics are computed on the output master bias. Additionally, bad columns are searched for and marked in the data quality extension.";
66 static const char *muse_bias_help_esorex =
67 "\n\nInput frames for raw frame tag \"BIAS\":\n"
68 "\n Frame tag Type Req #Fr Description"
69 "\n -------------------- ---- --- --- ------------"
70 "\n BIAS raw Y >=3 Raw bias"
71 "\n BADPIX_TABLE calib . 1 Bad pixel table"
72 "\n\nProduct frames for raw frame tag \"BIAS\":\n"
73 "\n Frame tag Level Description"
74 "\n -------------------- -------- ------------"
75 "\n MASTER_BIAS final Master bias";
86 static cpl_recipeconfig *
87 muse_bias_new_recipeconfig(
void)
89 cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
93 cpl_recipeconfig_set_tag(recipeconfig, tag, 3, -1);
94 cpl_recipeconfig_set_input(recipeconfig, tag,
"BADPIX_TABLE", -1, 1);
95 cpl_recipeconfig_set_output(recipeconfig, tag,
"MASTER_BIAS");
111 static cpl_error_code
112 muse_bias_prepare_header(
const char *aFrametag, cpl_propertylist *aHeader)
114 cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
115 cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
116 if (!strcmp(aFrametag,
"MASTER_BIAS")) {
119 "Number of saturated pixels in raw bias i in input list");
122 "Median value of master bias in quadrant n");
125 "Mean value of master bias in quadrant n");
128 "Standard deviation value of master bias in quadrant n");
131 "Minimum value of master bias in quadrant n");
134 "Maximum value of master bias in quadrant n");
137 "[count] Read-out noise in quadrant n determined from difference images of each adjacent pair of biases in the input dataset in randomly placed windows");
140 "[count] Read-out noise error in quadrant n determined from difference images of each adjacent pair of biases in the input dataset in randomly placed windows");
143 "[adu/pix] Average horizontal slope of master bias in quadrant n");
146 "[adu/pix] Average vertical slope of master bias in quadrant n");
149 "Bad pixels found as part of the bad column search in the master bias");
152 "Number of saturated pixels in output data");
155 "[adu] Average of the raw median values of all input files in quadrant n");
158 "[adu] Standard deviation of the raw median values of all input files in quadrant n");
161 "[adu] Median of the raw median values of all input files in quadrant n");
163 cpl_msg_warning(__func__,
"Frame tag %s is not defined", aFrametag);
164 return CPL_ERROR_ILLEGAL_INPUT;
166 return CPL_ERROR_NONE;
179 static cpl_frame_level
180 muse_bias_get_frame_level(
const char *aFrametag)
183 return CPL_FRAME_LEVEL_NONE;
185 if (!strcmp(aFrametag,
"MASTER_BIAS")) {
186 return CPL_FRAME_LEVEL_FINAL;
188 return CPL_FRAME_LEVEL_NONE;
202 muse_bias_get_frame_mode(
const char *aFrametag)
207 if (!strcmp(aFrametag,
"MASTER_BIAS")) {
225 muse_bias_create(cpl_plugin *aPlugin)
229 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
230 recipe = (cpl_recipe *)aPlugin;
238 muse_bias_new_recipeconfig(),
239 muse_bias_prepare_header,
240 muse_bias_get_frame_level,
241 muse_bias_get_frame_mode);
246 cpl_msg_set_time_on();
250 recipe->parameters = cpl_parameterlist_new();
255 p = cpl_parameter_new_range(
"muse.muse_bias.nifu",
257 "IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in parallel.",
262 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"nifu");
263 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"nifu");
265 cpl_parameterlist_append(recipe->parameters, p);
268 p = cpl_parameter_new_value(
"muse.muse_bias.overscan",
270 "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.",
272 (
const char *)
"vpoly");
273 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"overscan");
274 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"overscan");
276 cpl_parameterlist_append(recipe->parameters, p);
279 p = cpl_parameter_new_value(
"muse.muse_bias.ovscreject",
281 "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\").",
283 (
const char *)
"dcr");
284 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscreject");
285 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscreject");
287 cpl_parameterlist_append(recipe->parameters, p);
290 p = cpl_parameter_new_value(
"muse.muse_bias.ovscsigma",
292 "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\".",
295 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscsigma");
296 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscsigma");
298 cpl_parameterlist_append(recipe->parameters, p);
301 p = cpl_parameter_new_value(
"muse.muse_bias.ovscignore",
303 "The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when computing statistics or fits.",
306 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscignore");
307 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscignore");
309 cpl_parameterlist_append(recipe->parameters, p);
312 p = cpl_parameter_new_enum(
"muse.muse_bias.combine",
314 "Type of image combination to use.",
316 (
const char *)
"sigclip",
318 (
const char *)
"average",
319 (
const char *)
"median",
320 (
const char *)
"minmax",
321 (
const char *)
"sigclip");
322 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"combine");
323 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"combine");
325 cpl_parameterlist_append(recipe->parameters, p);
328 p = cpl_parameter_new_value(
"muse.muse_bias.nlow",
330 "Number of minimum pixels to reject with minmax.",
333 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"nlow");
334 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"nlow");
336 cpl_parameterlist_append(recipe->parameters, p);
339 p = cpl_parameter_new_value(
"muse.muse_bias.nhigh",
341 "Number of maximum pixels to reject with minmax.",
344 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"nhigh");
345 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"nhigh");
347 cpl_parameterlist_append(recipe->parameters, p);
350 p = cpl_parameter_new_value(
"muse.muse_bias.nkeep",
352 "Number of pixels to keep with minmax.",
355 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"nkeep");
356 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"nkeep");
358 cpl_parameterlist_append(recipe->parameters, p);
361 p = cpl_parameter_new_value(
"muse.muse_bias.lsigma",
363 "Low sigma for pixel rejection with sigclip.",
366 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lsigma");
367 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lsigma");
369 cpl_parameterlist_append(recipe->parameters, p);
372 p = cpl_parameter_new_value(
"muse.muse_bias.hsigma",
374 "High sigma for pixel rejection with sigclip.",
377 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"hsigma");
378 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"hsigma");
380 cpl_parameterlist_append(recipe->parameters, p);
383 p = cpl_parameter_new_value(
"muse.muse_bias.losigmabadpix",
385 "Low sigma to find dark columns in the combined bias",
388 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"losigmabadpix");
389 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"losigmabadpix");
391 cpl_parameterlist_append(recipe->parameters, p);
394 p = cpl_parameter_new_value(
"muse.muse_bias.hisigmabadpix",
396 "High sigma to find bright columns in the combined bias",
399 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"hisigmabadpix");
400 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"hisigmabadpix");
402 cpl_parameterlist_append(recipe->parameters, p);
405 p = cpl_parameter_new_value(
"muse.muse_bias.merge",
407 "Merge output products from different IFUs into a common file.",
410 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"merge");
411 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"merge");
413 cpl_parameterlist_append(recipe->parameters, p);
433 cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
434 cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
437 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.nifu");
438 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
439 aParams->
nifu = cpl_parameter_get_int(p);
441 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.overscan");
442 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
443 aParams->
overscan = cpl_parameter_get_string(p);
445 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.ovscreject");
446 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
447 aParams->
ovscreject = cpl_parameter_get_string(p);
449 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.ovscsigma");
450 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
451 aParams->
ovscsigma = cpl_parameter_get_double(p);
453 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.ovscignore");
454 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
455 aParams->
ovscignore = cpl_parameter_get_int(p);
457 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.combine");
458 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
459 aParams->
combine_s = cpl_parameter_get_string(p);
461 (!strcasecmp(aParams->
combine_s,
"average")) ? MUSE_BIAS_PARAM_COMBINE_AVERAGE :
462 (!strcasecmp(aParams->
combine_s,
"median")) ? MUSE_BIAS_PARAM_COMBINE_MEDIAN :
463 (!strcasecmp(aParams->
combine_s,
"minmax")) ? MUSE_BIAS_PARAM_COMBINE_MINMAX :
464 (!strcasecmp(aParams->
combine_s,
"sigclip")) ? MUSE_BIAS_PARAM_COMBINE_SIGCLIP :
465 MUSE_BIAS_PARAM_COMBINE_INVALID_VALUE;
466 cpl_ensure_code(aParams->
combine != MUSE_BIAS_PARAM_COMBINE_INVALID_VALUE,
467 CPL_ERROR_ILLEGAL_INPUT);
469 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.nlow");
470 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
471 aParams->
nlow = cpl_parameter_get_int(p);
473 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.nhigh");
474 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
475 aParams->
nhigh = cpl_parameter_get_int(p);
477 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.nkeep");
478 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
479 aParams->
nkeep = cpl_parameter_get_int(p);
481 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.lsigma");
482 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
483 aParams->
lsigma = cpl_parameter_get_double(p);
485 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.hsigma");
486 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
487 aParams->
hsigma = cpl_parameter_get_double(p);
489 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.losigmabadpix");
490 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
493 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.hisigmabadpix");
494 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
497 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.merge");
498 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
499 aParams->
merge = cpl_parameter_get_bool(p);
513 muse_bias_exec(cpl_plugin *aPlugin)
515 if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
518 cpl_recipe *recipe = (cpl_recipe *)aPlugin;
519 cpl_msg_set_threadid_on();
521 cpl_frameset *usedframes = cpl_frameset_new(),
522 *outframes = cpl_frameset_new();
524 muse_bias_params_fill(¶ms, recipe->parameters);
526 cpl_errorstate prestate = cpl_errorstate_get();
528 if (params.
nifu < -1 || params.
nifu > kMuseNumIFUs) {
529 cpl_msg_error(__func__,
"Please specify a valid IFU number (between 1 and "
530 "%d), 0 (to process all IFUs consecutively), or -1 (to "
531 "process all IFUs in parallel) using --nifu.", kMuseNumIFUs);
535 cpl_boolean donotmerge = CPL_FALSE;
537 if (params.
nifu > 0) {
540 rc = muse_bias_compute(proc, ¶ms);
541 cpl_frameset_join(usedframes, proc->
usedframes);
542 cpl_frameset_join(outframes, proc->
outframes);
544 donotmerge = CPL_TRUE;
545 }
else if (params.
nifu < 0) {
546 int *rcs = cpl_calloc(kMuseNumIFUs,
sizeof(
int));
548 #pragma omp parallel for default(none) \
549 shared(outframes, params, rcs, recipe, usedframes)
550 for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
556 int *rci = rcs + (nifu - 1);
557 *rci = muse_bias_compute(proc, pars);
558 if (rci && cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
562 #pragma omp critical(muse_processing_used_frames)
563 cpl_frameset_join(usedframes, proc->
usedframes);
564 #pragma omp critical(muse_processing_output_frames)
565 cpl_frameset_join(outframes, proc->
outframes);
570 for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
571 if (rcs[nifu-1] != 0) {
577 for (params.
nifu = 1; params.
nifu <= kMuseNumIFUs && !rc; params.
nifu++) {
580 rc = muse_bias_compute(proc, ¶ms);
581 if (rc && cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
584 cpl_frameset_join(usedframes, proc->
usedframes);
585 cpl_frameset_join(outframes, proc->
outframes);
589 UNUSED_ARGUMENT(donotmerge);
591 if (!cpl_errorstate_is_equal(prestate)) {
595 cpl_msg_set_level(CPL_MSG_INFO);
602 if (params.
merge && !donotmerge) {
603 muse_utils_frameset_merge_frames(outframes);
611 cpl_frameset_join(recipe->frames, usedframes);
612 cpl_frameset_join(recipe->frames, outframes);
613 cpl_frameset_delete(usedframes);
614 cpl_frameset_delete(outframes);
627 muse_bias_destroy(cpl_plugin *aPlugin)
631 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
632 recipe = (cpl_recipe *)aPlugin;
638 cpl_parameterlist_delete(recipe->parameters);
655 cpl_plugin_get_info(cpl_pluginlist *aList)
657 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
658 cpl_plugin *plugin = &recipe->interface;
662 helptext = cpl_sprintf(
"%s%s", muse_bias_help,
663 muse_bias_help_esorex);
665 helptext = cpl_sprintf(
"%s", muse_bias_help);
669 cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
670 CPL_PLUGIN_TYPE_RECIPE,
672 "Combine several separate bias images into one master bias file.",
680 cpl_pluginlist_append(aList, plugin);
const char * combine_s
Type of image combination to use. (as string)
double lsigma
Low sigma for pixel rejection with sigclip.
void muse_processing_delete(muse_processing *aProcessing)
Free the muse_processing structure.
int nhigh
Number of maximum pixels to reject with minmax.
double hisigmabadpix
High sigma to find bright columns in the combined bias.
muse_cplframework_type muse_cplframework(void)
Return the CPL framework the recipe is run under.
int combine
Type of image combination to use.
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 * ovscreject
This influences how values are rejected when computing overscan statistics. Either no rejection at al...
cpl_frameset * usedframes
muse_processing * muse_processing_new(const char *aName, cpl_recipe *aRecipe)
Create a new processing structure.
int nkeep
Number of pixels to keep with minmax.
double losigmabadpix
Low sigma to find dark columns in the combined bias.
const char * muse_get_license(void)
Get the pipeline copyright and license.
double ovscsigma
If the deviation of mean overscan levels between a raw input image and the reference image is higher ...
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.
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.
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 ovscignore
The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when com...
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 merge
Merge output products from different IFUs into a common file.
int nlow
Number of minimum pixels to reject with minmax.
Structure to hold the parameters of the muse_bias recipe.
double hsigma
High sigma for pixel rejection with sigclip.
cpl_error_code muse_processing_prepare_property(cpl_propertylist *, const char *, cpl_type, const char *)
Prepare and check the specified property.