35 #include "muse_wavecal_z.h" 82 static const char *muse_wavecal_help =
83 "This recipe detects arc emission lines and fits a wavelength solution to each slice of the instrument. The wavelength calibration table contains polynomials defining the wavelength solution of the slices on the CCD. Processing trims the raw data and records the overscan statistics, subtracts the bias (taking account of the overscan, if --overscan is not \"none\") and converts them from adu to count. Optionally, the dark can be subtracted and the data can be divided by the flat-field, but this is not recommended. The data is then combined using input parameters, into separate images for each lamp. To compute the wavelength solution, arc lines are detected at the center of each slice (using threshold detection on a S/N image) and subsequently assigned wavelengths, using pattern matching to identify lines from the input line catalog. Each line is then traced to the edges of the slice, using Gaussian centering in each CCD column. The Gaussians not only yield center, but also centering error, and line properties (e.g. FWHM). Deviant fits are detected using polynomial fits to each arc line (using the xorder parameter) and rejected. These analysis and measuring steps are carried out separately on images exposed by the different arc lamps, reducing the amount of blending, that can otherwise influence line identification and Gaussian centering. The final two-dimensional fit uses all positions (of all lamps), their wavelengths, and the given polynomial orders to compute the final wavelength solution for each slice, iteratively rejecting outliers. This final fit can be either unweighted (fitweighting=\"uniform\", for fastest processing) or weighted (other values of fitweighting, for higher accuracy).";
85 static const char *muse_wavecal_help_esorex =
86 "\n\nInput frames for raw frame tag \"ARC\":\n" 87 "\n Frame tag Type Req #Fr Description" 88 "\n -------------------- ---- --- --- ------------" 89 "\n ARC raw Y Raw arc lamp exposures" 90 "\n MASTER_BIAS calib Y 1 Master bias" 91 "\n MASTER_DARK calib . 1 Master dark" 92 "\n MASTER_FLAT calib . 1 Master flat" 93 "\n TRACE_TABLE calib Y 1 Trace table" 94 "\n LINE_CATALOG calib Y 1 Arc line catalog" 95 "\n BADPIX_TABLE calib . Known bad pixels" 96 "\n\nProduct frames for raw frame tag \"ARC\":\n" 97 "\n Frame tag Level Description" 98 "\n -------------------- -------- ------------" 99 "\n WAVECAL_TABLE final Wavelength calibration table" 100 "\n WAVECAL_RESIDUALS final Fit residuals of all arc lines (if --residuals=true)" 101 "\n ARC_RED_LAMP final Reduced ARC image, per lamp";
112 static cpl_recipeconfig *
113 muse_wavecal_new_recipeconfig(
void)
115 cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
117 cpl_recipeconfig_set_tag(recipeconfig,
"ARC", 1, -1);
118 cpl_recipeconfig_set_input(recipeconfig,
"ARC",
"MASTER_BIAS", 1, 1);
119 cpl_recipeconfig_set_input(recipeconfig,
"ARC",
"MASTER_DARK", -1, 1);
120 cpl_recipeconfig_set_input(recipeconfig,
"ARC",
"MASTER_FLAT", -1, 1);
121 cpl_recipeconfig_set_input(recipeconfig,
"ARC",
"TRACE_TABLE", 1, 1);
122 cpl_recipeconfig_set_input(recipeconfig,
"ARC",
"LINE_CATALOG", 1, 1);
123 cpl_recipeconfig_set_input(recipeconfig,
"ARC",
"BADPIX_TABLE", -1, -1);
124 cpl_recipeconfig_set_output(recipeconfig,
"ARC",
"WAVECAL_TABLE");
125 cpl_recipeconfig_set_output(recipeconfig,
"ARC",
"WAVECAL_RESIDUALS");
126 cpl_recipeconfig_set_output(recipeconfig,
"ARC",
"ARC_RED_LAMP");
142 static cpl_error_code
143 muse_wavecal_prepare_header(
const char *aFrametag, cpl_propertylist *aHeader)
145 cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
146 cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
147 if (!strcmp(aFrametag,
"WAVECAL_TABLE")) {
150 "Number of detected arc lines in slice j");
153 "Number of identified arc lines in slice j");
156 "[count] Mean peak count level above background of detected arc lines in slice j");
159 "[count] Standard deviation of peak count level above background of detected arc lines in slice j");
162 "[count] Peak count level above background of the faintest line in slice j");
165 "[count] Peak count level above background of the brightest line in slice j");
168 "[count] Mean peak count level of lines of lamp l above background of detected arc lines in slice j.");
171 "[count] Standard deviation of peak count level of lines of lamp l above background of detected arc lines in slice j.");
174 "[count] Peak count level above background of the brightest line of lamp l in slice j.");
177 "Mean FWHM of detected arc lines in slice j");
180 "Standard deviation of FWHM of detected arc lines in slice j");
183 "Minimum FWHM of detected arc lines in slice j");
186 "Maximum FWHM of detected arc lines in slice j");
189 "Mean spectral resolution R determined in slice j");
192 "Number of arc lines used in calibration solution fit in slice j");
195 "[Angstrom] RMS of the wavelength calibration fit in slice j");
198 "[Angstrom] Difference in wavelength computed for the bottom left and bottom right corners of the slice on the CCD");
201 "[Angstrom] Difference in wavelength computed for the top left and top right corners of the slice on the CCD");
204 "[pix] Position of wavelength given in WLEN in slice j");
207 "[Angstrom] Wavelength associated to WLPOS in slice j");
208 }
else if (!strcmp(aFrametag,
"WAVECAL_RESIDUALS")) {
209 }
else if (!strcmp(aFrametag,
"ARC_RED_LAMP")) {
212 "Number of saturated pixels in raw arc i in input list");
215 "Number of saturated pixels in output data");
217 cpl_msg_warning(__func__,
"Frame tag %s is not defined", aFrametag);
218 return CPL_ERROR_ILLEGAL_INPUT;
220 return CPL_ERROR_NONE;
233 static cpl_frame_level
234 muse_wavecal_get_frame_level(
const char *aFrametag)
237 return CPL_FRAME_LEVEL_NONE;
239 if (!strcmp(aFrametag,
"WAVECAL_TABLE")) {
240 return CPL_FRAME_LEVEL_FINAL;
242 if (!strcmp(aFrametag,
"WAVECAL_RESIDUALS")) {
243 return CPL_FRAME_LEVEL_FINAL;
245 if (!strcmp(aFrametag,
"ARC_RED_LAMP")) {
246 return CPL_FRAME_LEVEL_FINAL;
248 return CPL_FRAME_LEVEL_NONE;
262 muse_wavecal_get_frame_mode(
const char *aFrametag)
267 if (!strcmp(aFrametag,
"WAVECAL_TABLE")) {
270 if (!strcmp(aFrametag,
"WAVECAL_RESIDUALS")) {
273 if (!strcmp(aFrametag,
"ARC_RED_LAMP")) {
291 muse_wavecal_create(cpl_plugin *aPlugin)
295 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
296 recipe = (cpl_recipe *)aPlugin;
304 muse_wavecal_new_recipeconfig(),
305 muse_wavecal_prepare_header,
306 muse_wavecal_get_frame_level,
307 muse_wavecal_get_frame_mode);
312 cpl_msg_set_time_on();
316 recipe->parameters = cpl_parameterlist_new();
321 p = cpl_parameter_new_range(
"muse.muse_wavecal.nifu",
323 "IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in parallel.",
328 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"nifu");
329 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"nifu");
331 cpl_parameterlist_append(recipe->parameters, p);
334 p = cpl_parameter_new_value(
"muse.muse_wavecal.overscan",
336 "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.",
338 (
const char *)
"vpoly");
339 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"overscan");
340 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"overscan");
342 cpl_parameterlist_append(recipe->parameters, p);
345 p = cpl_parameter_new_value(
"muse.muse_wavecal.ovscreject",
347 "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\").",
349 (
const char *)
"dcr");
350 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscreject");
351 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscreject");
353 cpl_parameterlist_append(recipe->parameters, p);
356 p = cpl_parameter_new_value(
"muse.muse_wavecal.ovscsigma",
358 "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\".",
361 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscsigma");
362 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscsigma");
364 cpl_parameterlist_append(recipe->parameters, p);
367 p = cpl_parameter_new_value(
"muse.muse_wavecal.ovscignore",
369 "The number of pixels of the overscan adjacent to the data section of the CCD that are ignored when computing statistics or fits.",
372 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscignore");
373 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscignore");
375 cpl_parameterlist_append(recipe->parameters, p);
378 p = cpl_parameter_new_enum(
"muse.muse_wavecal.combine",
380 "Type of lampwise image combination to use.",
382 (
const char *)
"sigclip",
384 (
const char *)
"average",
385 (
const char *)
"median",
386 (
const char *)
"minmax",
387 (
const char *)
"sigclip");
388 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"combine");
389 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"combine");
391 cpl_parameterlist_append(recipe->parameters, p);
394 p = cpl_parameter_new_value(
"muse.muse_wavecal.lampwise",
396 "Identify and measure the arc emission lines on images separately for each lamp setup.",
399 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lampwise");
400 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lampwise");
401 if (!getenv(
"MUSE_EXPERT_USER")) {
402 cpl_parameter_disable(p, CPL_PARAMETER_MODE_CLI);
405 cpl_parameterlist_append(recipe->parameters, p);
408 p = cpl_parameter_new_value(
"muse.muse_wavecal.sigma",
410 "Sigma level used to detect arc emission lines above the median background level in the S/N image of the central column of each slice",
413 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"sigma");
414 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"sigma");
416 cpl_parameterlist_append(recipe->parameters, p);
419 p = cpl_parameter_new_value(
"muse.muse_wavecal.dres",
421 "The allowed range of resolutions for pattern matching (of detected arc lines to line list) in fractions relative to the expected value",
424 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"dres");
425 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"dres");
427 cpl_parameterlist_append(recipe->parameters, p);
430 p = cpl_parameter_new_value(
"muse.muse_wavecal.tolerance",
432 "Tolerance for pattern matching (of detected arc lines to line list)",
435 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"tolerance");
436 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"tolerance");
438 cpl_parameterlist_append(recipe->parameters, p);
441 p = cpl_parameter_new_value(
"muse.muse_wavecal.xorder",
443 "Order of the polynomial for the horizontal curvature within each slice",
446 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"xorder");
447 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"xorder");
449 cpl_parameterlist_append(recipe->parameters, p);
452 p = cpl_parameter_new_value(
"muse.muse_wavecal.yorder",
454 "Order of the polynomial used to fit the dispersion relation",
457 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"yorder");
458 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"yorder");
460 cpl_parameterlist_append(recipe->parameters, p);
463 p = cpl_parameter_new_value(
"muse.muse_wavecal.linesigma",
465 "Sigma level for iterative rejection of deviant fits for each arc line within each slice, a negative value means to use the default (2.5).",
468 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"linesigma");
469 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"linesigma");
471 cpl_parameterlist_append(recipe->parameters, p);
474 p = cpl_parameter_new_value(
"muse.muse_wavecal.residuals",
476 "Create a table containing residuals of the fits to the data of all arc lines. This is useful to assess the quality of the wavelength solution in detail.",
479 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"residuals");
480 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"residuals");
482 cpl_parameterlist_append(recipe->parameters, p);
485 p = cpl_parameter_new_value(
"muse.muse_wavecal.fitsigma",
487 "Sigma level for iterative rejection of deviant datapoints during the final polynomial wavelength solution within each slice, a negative value means to use the default (3.0).",
490 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"fitsigma");
491 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"fitsigma");
493 cpl_parameterlist_append(recipe->parameters, p);
496 p = cpl_parameter_new_enum(
"muse.muse_wavecal.fitweighting",
498 "Type of weighting to use in the final polynomial wavelength solution fit, using centroiding error estimate and/or scatter of each single line as estimates of its accuracy.",
500 (
const char *)
"cerrscatter",
502 (
const char *)
"uniform",
503 (
const char *)
"cerr",
504 (
const char *)
"scatter",
505 (
const char *)
"cerrscatter");
506 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"fitweighting");
507 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"fitweighting");
509 cpl_parameterlist_append(recipe->parameters, p);
512 p = cpl_parameter_new_value(
"muse.muse_wavecal.resample",
514 "Resample the input arc images onto 2D images for a visual check using tracing and wavelength calibration solutions. Note that the image produced will show small wiggles even when the calibration was successful!",
517 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"resample");
518 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"resample");
519 if (!getenv(
"MUSE_EXPERT_USER")) {
520 cpl_parameter_disable(p, CPL_PARAMETER_MODE_CLI);
523 cpl_parameterlist_append(recipe->parameters, p);
526 p = cpl_parameter_new_value(
"muse.muse_wavecal.wavemap",
528 "Create a wavelength map of the input images",
531 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"wavemap");
532 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wavemap");
533 if (!getenv(
"MUSE_EXPERT_USER")) {
534 cpl_parameter_disable(p, CPL_PARAMETER_MODE_CLI);
537 cpl_parameterlist_append(recipe->parameters, p);
540 p = cpl_parameter_new_value(
"muse.muse_wavecal.merge",
542 "Merge output products from different IFUs into a common file.",
545 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"merge");
546 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"merge");
548 cpl_parameterlist_append(recipe->parameters, p);
568 cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
569 cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
572 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.nifu");
573 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
574 aParams->
nifu = cpl_parameter_get_int(p);
576 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.overscan");
577 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
578 aParams->
overscan = cpl_parameter_get_string(p);
580 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.ovscreject");
581 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
582 aParams->
ovscreject = cpl_parameter_get_string(p);
584 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.ovscsigma");
585 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
586 aParams->
ovscsigma = cpl_parameter_get_double(p);
588 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.ovscignore");
589 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
590 aParams->
ovscignore = cpl_parameter_get_int(p);
592 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.combine");
593 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
594 aParams->
combine_s = cpl_parameter_get_string(p);
596 (!strcasecmp(aParams->
combine_s,
"average")) ? MUSE_WAVECAL_PARAM_COMBINE_AVERAGE :
597 (!strcasecmp(aParams->
combine_s,
"median")) ? MUSE_WAVECAL_PARAM_COMBINE_MEDIAN :
598 (!strcasecmp(aParams->
combine_s,
"minmax")) ? MUSE_WAVECAL_PARAM_COMBINE_MINMAX :
599 (!strcasecmp(aParams->
combine_s,
"sigclip")) ? MUSE_WAVECAL_PARAM_COMBINE_SIGCLIP :
600 MUSE_WAVECAL_PARAM_COMBINE_INVALID_VALUE;
601 cpl_ensure_code(aParams->
combine != MUSE_WAVECAL_PARAM_COMBINE_INVALID_VALUE,
602 CPL_ERROR_ILLEGAL_INPUT);
604 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.lampwise");
605 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
606 aParams->
lampwise = cpl_parameter_get_bool(p);
608 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.sigma");
609 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
610 aParams->
sigma = cpl_parameter_get_double(p);
612 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.dres");
613 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
614 aParams->
dres = cpl_parameter_get_double(p);
616 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.tolerance");
617 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
618 aParams->
tolerance = cpl_parameter_get_double(p);
620 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.xorder");
621 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
622 aParams->
xorder = cpl_parameter_get_int(p);
624 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.yorder");
625 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
626 aParams->
yorder = cpl_parameter_get_int(p);
628 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.linesigma");
629 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
630 aParams->
linesigma = cpl_parameter_get_double(p);
632 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.residuals");
633 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
634 aParams->
residuals = cpl_parameter_get_bool(p);
636 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.fitsigma");
637 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
638 aParams->
fitsigma = cpl_parameter_get_double(p);
640 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.fitweighting");
641 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
644 (!strcasecmp(aParams->
fitweighting_s,
"uniform")) ? MUSE_WAVECAL_PARAM_FITWEIGHTING_UNIFORM :
645 (!strcasecmp(aParams->
fitweighting_s,
"cerr")) ? MUSE_WAVECAL_PARAM_FITWEIGHTING_CERR :
646 (!strcasecmp(aParams->
fitweighting_s,
"scatter")) ? MUSE_WAVECAL_PARAM_FITWEIGHTING_SCATTER :
647 (!strcasecmp(aParams->
fitweighting_s,
"cerrscatter")) ? MUSE_WAVECAL_PARAM_FITWEIGHTING_CERRSCATTER :
648 MUSE_WAVECAL_PARAM_FITWEIGHTING_INVALID_VALUE;
649 cpl_ensure_code(aParams->
fitweighting != MUSE_WAVECAL_PARAM_FITWEIGHTING_INVALID_VALUE,
650 CPL_ERROR_ILLEGAL_INPUT);
652 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.resample");
653 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
654 aParams->
resample = cpl_parameter_get_bool(p);
656 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.wavemap");
657 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
658 aParams->
wavemap = cpl_parameter_get_bool(p);
660 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.merge");
661 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
662 aParams->
merge = cpl_parameter_get_bool(p);
676 muse_wavecal_exec(cpl_plugin *aPlugin)
678 if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
682 cpl_recipe *recipe = (cpl_recipe *)aPlugin;
683 cpl_msg_set_threadid_on();
685 cpl_frameset *usedframes = cpl_frameset_new(),
686 *outframes = cpl_frameset_new();
688 muse_wavecal_params_fill(¶ms, recipe->parameters);
690 cpl_errorstate prestate = cpl_errorstate_get();
692 if (params.
nifu < -1 || params.
nifu > kMuseNumIFUs) {
693 cpl_msg_error(__func__,
"Please specify a valid IFU number (between 1 and " 694 "%d), 0 (to process all IFUs consecutively), or -1 (to " 695 "process all IFUs in parallel) using --nifu.", kMuseNumIFUs);
699 cpl_boolean donotmerge = CPL_FALSE;
701 if (params.
nifu > 0) {
704 rc = muse_wavecal_compute(proc, ¶ms);
705 cpl_frameset_join(usedframes, proc->
usedframes);
706 cpl_frameset_join(outframes, proc->
outframes);
708 donotmerge = CPL_TRUE;
709 }
else if (params.
nifu < 0) {
710 int *rcs = cpl_calloc(kMuseNumIFUs,
sizeof(
int));
712 #pragma omp parallel for default(none) \ 713 shared(outframes, params, rcs, recipe, usedframes) 714 for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
720 int *rci = rcs + (nifu - 1);
721 *rci = muse_wavecal_compute(proc, pars);
722 if (rci && (
int)cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
726 #pragma omp critical(muse_processing_used_frames) 727 cpl_frameset_join(usedframes, proc->
usedframes);
728 #pragma omp critical(muse_processing_output_frames) 729 cpl_frameset_join(outframes, proc->
outframes);
734 for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
735 if (rcs[nifu-1] != 0) {
741 for (params.
nifu = 1; params.
nifu <= kMuseNumIFUs && !rc; params.
nifu++) {
744 rc = muse_wavecal_compute(proc, ¶ms);
745 if (rc && (
int)cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
748 cpl_frameset_join(usedframes, proc->
usedframes);
749 cpl_frameset_join(outframes, proc->
outframes);
753 UNUSED_ARGUMENT(donotmerge);
755 if (!cpl_errorstate_is_equal(prestate)) {
759 cpl_msg_set_level(CPL_MSG_INFO);
766 if (params.
merge && !donotmerge) {
775 cpl_frameset_join(recipe->frames, usedframes);
776 cpl_frameset_join(recipe->frames, outframes);
777 cpl_frameset_delete(usedframes);
778 cpl_frameset_delete(outframes);
791 muse_wavecal_destroy(cpl_plugin *aPlugin)
795 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
796 recipe = (cpl_recipe *)aPlugin;
802 cpl_parameterlist_delete(recipe->parameters);
819 cpl_plugin_get_info(cpl_pluginlist *aList)
821 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
822 cpl_plugin *plugin = &recipe->interface;
826 helptext = cpl_sprintf(
"%s%s", muse_wavecal_help,
827 muse_wavecal_help_esorex);
829 helptext = cpl_sprintf(
"%s", muse_wavecal_help);
833 cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
834 CPL_PLUGIN_TYPE_RECIPE,
836 "Detect arc emission lines and determine the wavelength solution for each slice.",
843 muse_wavecal_destroy);
844 cpl_pluginlist_append(aList, plugin);
void muse_processing_delete(muse_processing *aProcessing)
Free the muse_processing structure.
double fitsigma
Sigma level for iterative rejection of deviant datapoints during the final polynomial wavelength solu...
double linesigma
Sigma level for iterative rejection of deviant fits for each arc line within each slice...
const char * ovscreject
This influences how values are rejected when computing overscan statistics. Either no rejection at al...
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.
int ovscignore
The number of pixels of the overscan adjacent to the data section of the CCD that are ignored when co...
double dres
The allowed range of resolutions for pattern matching (of detected arc lines to line list) in fractio...
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.
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.
void muse_cplerrorstate_dump_some(unsigned aCurrent, unsigned aFirst, unsigned aLast)
Dump some CPL errors.
int wavemap
Create a wavelength map of the input images.
int lampwise
Identify and measure the arc emission lines on images separately for each lamp setup.
int residuals
Create a table containing residuals of the fits to the data of all arc lines. This is useful to asses...
void muse_processinginfo_delete(cpl_recipe *)
Clear all information from the processing info and from the recipe config.
int resample
Resample the input arc images onto 2D images for a visual check using tracing and wavelength calibrat...
int yorder
Order of the polynomial used to fit the dispersion relation.
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 fitweighting
Type of weighting to use in the final polynomial wavelength solution fit, using centroiding error est...
const char * combine_s
Type of lampwise image combination to use. (as string)
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 combine
Type of lampwise image combination to use.
Structure to hold the parameters of the muse_wavecal recipe.
double tolerance
Tolerance for pattern matching (of detected arc lines to line list)
void muse_processing_recipeinfo(cpl_plugin *)
Output main pipeline configuration, inputs, and parameters.
const char * fitweighting_s
Type of weighting to use in the final polynomial wavelength solution fit, using centroiding error est...
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.
double sigma
Sigma level used to detect arc emission lines above the median background level in the S/N image of t...
int merge
Merge output products from different IFUs into a common file.
int xorder
Order of the polynomial for the horizontal curvature within each slice.
cpl_error_code muse_processing_prepare_property(cpl_propertylist *, const char *, cpl_type, const char *)
Prepare and check the specified property.