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 . Known bad pixels" 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();
91 cpl_recipeconfig_set_tag(recipeconfig,
"BIAS", 3, -1);
92 cpl_recipeconfig_set_input(recipeconfig,
"BIAS",
"BADPIX_TABLE", -1, -1);
93 cpl_recipeconfig_set_output(recipeconfig,
"BIAS",
"MASTER_BIAS");
109 static cpl_error_code
110 muse_bias_prepare_header(
const char *aFrametag, cpl_propertylist *aHeader)
112 cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
113 cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
114 if (!strcmp(aFrametag,
"MASTER_BIAS")) {
117 "Number of saturated pixels in raw bias i in input list");
120 "Median value of master bias in quadrant n");
123 "Mean value of master bias in quadrant n");
126 "Standard deviation value of master bias in quadrant n");
129 "Minimum value of master bias in quadrant n");
132 "Maximum value of master bias in quadrant n");
135 "[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");
138 "[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");
141 "[adu/pix] Average horizontal slope of master bias in quadrant n");
144 "[adu/pix] Average vertical slope of master bias in quadrant n");
147 "Bad pixels found as part of the bad column search in the master bias");
150 "Number of saturated pixels in output data");
153 "[adu] Average of the raw median values of all input files in quadrant n");
156 "[adu] Standard deviation of the raw median values of all input files in quadrant n");
159 "[adu] Median of the raw median values of all input files in quadrant n");
161 cpl_msg_warning(__func__,
"Frame tag %s is not defined", aFrametag);
162 return CPL_ERROR_ILLEGAL_INPUT;
164 return CPL_ERROR_NONE;
177 static cpl_frame_level
178 muse_bias_get_frame_level(
const char *aFrametag)
181 return CPL_FRAME_LEVEL_NONE;
183 if (!strcmp(aFrametag,
"MASTER_BIAS")) {
184 return CPL_FRAME_LEVEL_FINAL;
186 return CPL_FRAME_LEVEL_NONE;
200 muse_bias_get_frame_mode(
const char *aFrametag)
205 if (!strcmp(aFrametag,
"MASTER_BIAS")) {
223 muse_bias_create(cpl_plugin *aPlugin)
227 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
228 recipe = (cpl_recipe *)aPlugin;
236 muse_bias_new_recipeconfig(),
237 muse_bias_prepare_header,
238 muse_bias_get_frame_level,
239 muse_bias_get_frame_mode);
244 cpl_msg_set_time_on();
248 recipe->parameters = cpl_parameterlist_new();
253 p = cpl_parameter_new_range(
"muse.muse_bias.nifu",
255 "IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in parallel.",
260 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"nifu");
261 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"nifu");
263 cpl_parameterlist_append(recipe->parameters, p);
266 p = cpl_parameter_new_value(
"muse.muse_bias.overscan",
268 "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.",
270 (
const char *)
"vpoly");
271 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"overscan");
272 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"overscan");
274 cpl_parameterlist_append(recipe->parameters, p);
277 p = cpl_parameter_new_value(
"muse.muse_bias.ovscreject",
279 "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\").",
281 (
const char *)
"dcr");
282 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscreject");
283 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscreject");
285 cpl_parameterlist_append(recipe->parameters, p);
288 p = cpl_parameter_new_value(
"muse.muse_bias.ovscsigma",
290 "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\".",
293 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscsigma");
294 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscsigma");
296 cpl_parameterlist_append(recipe->parameters, p);
299 p = cpl_parameter_new_value(
"muse.muse_bias.ovscignore",
301 "The number of pixels of the overscan adjacent to the data section of the CCD that are ignored when computing statistics or fits.",
304 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscignore");
305 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscignore");
307 cpl_parameterlist_append(recipe->parameters, p);
310 p = cpl_parameter_new_enum(
"muse.muse_bias.combine",
312 "Type of image combination to use.",
314 (
const char *)
"sigclip",
316 (
const char *)
"average",
317 (
const char *)
"median",
318 (
const char *)
"minmax",
319 (
const char *)
"sigclip");
320 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"combine");
321 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"combine");
323 cpl_parameterlist_append(recipe->parameters, p);
326 p = cpl_parameter_new_value(
"muse.muse_bias.nlow",
328 "Number of minimum pixels to reject with minmax.",
331 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"nlow");
332 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"nlow");
334 cpl_parameterlist_append(recipe->parameters, p);
337 p = cpl_parameter_new_value(
"muse.muse_bias.nhigh",
339 "Number of maximum pixels to reject with minmax.",
342 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"nhigh");
343 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"nhigh");
345 cpl_parameterlist_append(recipe->parameters, p);
348 p = cpl_parameter_new_value(
"muse.muse_bias.nkeep",
350 "Number of pixels to keep with minmax.",
353 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"nkeep");
354 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"nkeep");
356 cpl_parameterlist_append(recipe->parameters, p);
359 p = cpl_parameter_new_value(
"muse.muse_bias.lsigma",
361 "Low sigma for pixel rejection with sigclip.",
364 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lsigma");
365 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lsigma");
367 cpl_parameterlist_append(recipe->parameters, p);
370 p = cpl_parameter_new_value(
"muse.muse_bias.hsigma",
372 "High sigma for pixel rejection with sigclip.",
375 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"hsigma");
376 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"hsigma");
378 cpl_parameterlist_append(recipe->parameters, p);
381 p = cpl_parameter_new_value(
"muse.muse_bias.losigmabadpix",
383 "Low sigma to find dark columns in the combined bias",
386 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"losigmabadpix");
387 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"losigmabadpix");
389 cpl_parameterlist_append(recipe->parameters, p);
392 p = cpl_parameter_new_value(
"muse.muse_bias.hisigmabadpix",
394 "High sigma to find bright columns in the combined bias",
397 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"hisigmabadpix");
398 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"hisigmabadpix");
400 cpl_parameterlist_append(recipe->parameters, p);
403 p = cpl_parameter_new_value(
"muse.muse_bias.merge",
405 "Merge output products from different IFUs into a common file.",
408 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"merge");
409 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"merge");
411 cpl_parameterlist_append(recipe->parameters, p);
431 cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
432 cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
435 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.nifu");
436 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
437 aParams->
nifu = cpl_parameter_get_int(p);
439 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.overscan");
440 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
441 aParams->
overscan = cpl_parameter_get_string(p);
443 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.ovscreject");
444 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
445 aParams->
ovscreject = cpl_parameter_get_string(p);
447 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.ovscsigma");
448 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
449 aParams->
ovscsigma = cpl_parameter_get_double(p);
451 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.ovscignore");
452 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
453 aParams->
ovscignore = cpl_parameter_get_int(p);
455 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.combine");
456 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
457 aParams->
combine_s = cpl_parameter_get_string(p);
459 (!strcasecmp(aParams->
combine_s,
"average")) ? MUSE_BIAS_PARAM_COMBINE_AVERAGE :
460 (!strcasecmp(aParams->
combine_s,
"median")) ? MUSE_BIAS_PARAM_COMBINE_MEDIAN :
461 (!strcasecmp(aParams->
combine_s,
"minmax")) ? MUSE_BIAS_PARAM_COMBINE_MINMAX :
462 (!strcasecmp(aParams->
combine_s,
"sigclip")) ? MUSE_BIAS_PARAM_COMBINE_SIGCLIP :
463 MUSE_BIAS_PARAM_COMBINE_INVALID_VALUE;
464 cpl_ensure_code(aParams->
combine != MUSE_BIAS_PARAM_COMBINE_INVALID_VALUE,
465 CPL_ERROR_ILLEGAL_INPUT);
467 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.nlow");
468 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
469 aParams->
nlow = cpl_parameter_get_int(p);
471 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.nhigh");
472 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
473 aParams->
nhigh = cpl_parameter_get_int(p);
475 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.nkeep");
476 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
477 aParams->
nkeep = cpl_parameter_get_int(p);
479 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.lsigma");
480 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
481 aParams->
lsigma = cpl_parameter_get_double(p);
483 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.hsigma");
484 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
485 aParams->
hsigma = cpl_parameter_get_double(p);
487 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.losigmabadpix");
488 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
491 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.hisigmabadpix");
492 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
495 p = cpl_parameterlist_find(aParameters,
"muse.muse_bias.merge");
496 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
497 aParams->
merge = cpl_parameter_get_bool(p);
511 muse_bias_exec(cpl_plugin *aPlugin)
513 if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
517 cpl_recipe *recipe = (cpl_recipe *)aPlugin;
518 cpl_msg_set_threadid_on();
520 cpl_frameset *usedframes = cpl_frameset_new(),
521 *outframes = cpl_frameset_new();
523 muse_bias_params_fill(¶ms, recipe->parameters);
525 cpl_errorstate prestate = cpl_errorstate_get();
527 if (params.
nifu < -1 || params.
nifu > kMuseNumIFUs) {
528 cpl_msg_error(__func__,
"Please specify a valid IFU number (between 1 and " 529 "%d), 0 (to process all IFUs consecutively), or -1 (to " 530 "process all IFUs in parallel) using --nifu.", kMuseNumIFUs);
534 cpl_boolean donotmerge = CPL_FALSE;
536 if (params.
nifu > 0) {
539 rc = muse_bias_compute(proc, ¶ms);
540 cpl_frameset_join(usedframes, proc->
usedframes);
541 cpl_frameset_join(outframes, proc->
outframes);
543 donotmerge = CPL_TRUE;
544 }
else if (params.
nifu < 0) {
545 int *rcs = cpl_calloc(kMuseNumIFUs,
sizeof(
int));
547 #pragma omp parallel for default(none) \ 548 shared(outframes, params, rcs, recipe, usedframes) 549 for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
555 int *rci = rcs + (nifu - 1);
556 *rci = muse_bias_compute(proc, pars);
557 if (rci && (
int)cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
561 #pragma omp critical(muse_processing_used_frames) 562 cpl_frameset_join(usedframes, proc->
usedframes);
563 #pragma omp critical(muse_processing_output_frames) 564 cpl_frameset_join(outframes, proc->
outframes);
569 for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
570 if (rcs[nifu-1] != 0) {
576 for (params.
nifu = 1; params.
nifu <= kMuseNumIFUs && !rc; params.
nifu++) {
579 rc = muse_bias_compute(proc, ¶ms);
580 if (rc && (
int)cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
583 cpl_frameset_join(usedframes, proc->
usedframes);
584 cpl_frameset_join(outframes, proc->
outframes);
588 UNUSED_ARGUMENT(donotmerge);
590 if (!cpl_errorstate_is_equal(prestate)) {
594 cpl_msg_set_level(CPL_MSG_INFO);
601 if (params.
merge && !donotmerge) {
610 cpl_frameset_join(recipe->frames, usedframes);
611 cpl_frameset_join(recipe->frames, outframes);
612 cpl_frameset_delete(usedframes);
613 cpl_frameset_delete(outframes);
626 muse_bias_destroy(cpl_plugin *aPlugin)
630 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
631 recipe = (cpl_recipe *)aPlugin;
637 cpl_parameterlist_delete(recipe->parameters);
654 cpl_plugin_get_info(cpl_pluginlist *aList)
656 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
657 cpl_plugin *plugin = &recipe->interface;
661 helptext = cpl_sprintf(
"%s%s", muse_bias_help,
662 muse_bias_help_esorex);
664 helptext = cpl_sprintf(
"%s", muse_bias_help);
668 cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
669 CPL_PLUGIN_TYPE_RECIPE,
671 "Combine several separate bias images into one master bias file.",
679 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 section of the CCD that are ignored when co...
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.
void muse_processing_recipeinfo(cpl_plugin *)
Output main pipeline configuration, inputs, and parameters.
int nlow
Number of minimum pixels to reject with minmax.
cpl_error_code muse_utils_frameset_merge_frames(cpl_frameset *aFrames, cpl_boolean aDelete)
Merge IFU-specific files from a frameset to create multi-IFU outputs.
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.