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, first into separate images for each lamp. If --lampwise is not given or if --resample is given, these lamp-separate exposures are summed to create a single combined master arc. 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. If --lampwise is switched on, 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 . 1 Bad pixel table"
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"
102 "\n ARC_RED final Reduced master ARC image"
103 "\n ARC_RESAMPLED final Resampled arc images (if --resampled=true)"
104 "\n WAVE_MAP final Wavelength map of the input images";
115 static cpl_recipeconfig *
116 muse_wavecal_new_recipeconfig(
void)
118 cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
122 cpl_recipeconfig_set_tag(recipeconfig, tag, 1, -1);
123 cpl_recipeconfig_set_input(recipeconfig, tag,
"MASTER_BIAS", 1, 1);
124 cpl_recipeconfig_set_input(recipeconfig, tag,
"MASTER_DARK", -1, 1);
125 cpl_recipeconfig_set_input(recipeconfig, tag,
"MASTER_FLAT", -1, 1);
126 cpl_recipeconfig_set_input(recipeconfig, tag,
"TRACE_TABLE", 1, 1);
127 cpl_recipeconfig_set_input(recipeconfig, tag,
"LINE_CATALOG", 1, 1);
128 cpl_recipeconfig_set_input(recipeconfig, tag,
"BADPIX_TABLE", -1, 1);
129 cpl_recipeconfig_set_output(recipeconfig, tag,
"WAVECAL_TABLE");
130 cpl_recipeconfig_set_output(recipeconfig, tag,
"WAVECAL_RESIDUALS");
131 cpl_recipeconfig_set_output(recipeconfig, tag,
"ARC_RED_LAMP");
132 cpl_recipeconfig_set_output(recipeconfig, tag,
"ARC_RED");
133 cpl_recipeconfig_set_output(recipeconfig, tag,
"ARC_RESAMPLED");
134 cpl_recipeconfig_set_output(recipeconfig, tag,
"WAVE_MAP");
150 static cpl_error_code
151 muse_wavecal_prepare_header(
const char *aFrametag, cpl_propertylist *aHeader)
153 cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
154 cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
155 if (!strcmp(aFrametag,
"WAVECAL_TABLE")) {
158 "Number of detected arc lines in slice j");
161 "Number of identified arc lines in slice j");
164 "[count] Mean peak count level above background of detected arc lines in slice j");
167 "[count] Standard deviation of peak count level above background of detected arc lines in slice j");
170 "[count] Peak count level above background of the faintest line in slice j");
173 "[count] Peak count level above background of the brightest line in slice j");
176 "[count] Mean peak count level of lines of lamp l above background of detected arc lines in slice j. Not produced with --lampwise=FALSE!");
179 "[count] Standard deviation of peak count level of lines of lamp l above background of detected arc lines in slice j. Not produced with --lampwise=FALSE!");
182 "[count] Peak count level above background of the brightest line of lamp l in slice j. Not produced with --lampwise=FALSE!");
185 "Mean FWHM of detected arc lines in slice j");
188 "Standard deviation of FWHM of detected arc lines in slice j");
191 "Minimum FWHM of detected arc lines in slice j");
194 "Maximum FWHM of detected arc lines in slice j");
197 "Mean spectral resolution R determined in slice j");
200 "Number of arc lines used in calibration solution fit in slice j");
203 "[Angstrom] RMS of the wavelength calibration fit in slice j");
206 "[Angstrom] Difference in wavelength computed for the bottom left and bottom right corners of the slice on the CCD");
209 "[Angstrom] Difference in wavelength computed for the top left and top right corners of the slice on the CCD");
212 "[pix] Position of wavelength given in WLEN in slice j");
215 "[Angstrom] Wavelength associated to WLPOS in slice j");
216 }
else if (!strcmp(aFrametag,
"WAVECAL_RESIDUALS")) {
217 }
else if (!strcmp(aFrametag,
"ARC_RED_LAMP")) {
220 "Number of saturated pixels in raw arc i in input list");
223 "Number of saturated pixels in output data");
224 }
else if (!strcmp(aFrametag,
"ARC_RED")) {
227 "Number of saturated pixels in raw arc i of lamp l in input list");
230 "Number of saturated pixels in output data");
231 }
else if (!strcmp(aFrametag,
"ARC_RESAMPLED")) {
232 }
else if (!strcmp(aFrametag,
"WAVE_MAP")) {
234 cpl_msg_warning(__func__,
"Frame tag %s is not defined", aFrametag);
235 return CPL_ERROR_ILLEGAL_INPUT;
237 return CPL_ERROR_NONE;
250 static cpl_frame_level
251 muse_wavecal_get_frame_level(
const char *aFrametag)
254 return CPL_FRAME_LEVEL_NONE;
256 if (!strcmp(aFrametag,
"WAVECAL_TABLE")) {
257 return CPL_FRAME_LEVEL_FINAL;
259 if (!strcmp(aFrametag,
"WAVECAL_RESIDUALS")) {
260 return CPL_FRAME_LEVEL_FINAL;
262 if (!strcmp(aFrametag,
"ARC_RED_LAMP")) {
263 return CPL_FRAME_LEVEL_FINAL;
265 if (!strcmp(aFrametag,
"ARC_RED")) {
266 return CPL_FRAME_LEVEL_FINAL;
268 if (!strcmp(aFrametag,
"ARC_RESAMPLED")) {
269 return CPL_FRAME_LEVEL_FINAL;
271 if (!strcmp(aFrametag,
"WAVE_MAP")) {
272 return CPL_FRAME_LEVEL_FINAL;
274 return CPL_FRAME_LEVEL_NONE;
288 muse_wavecal_get_frame_mode(
const char *aFrametag)
293 if (!strcmp(aFrametag,
"WAVECAL_TABLE")) {
296 if (!strcmp(aFrametag,
"WAVECAL_RESIDUALS")) {
299 if (!strcmp(aFrametag,
"ARC_RED_LAMP")) {
302 if (!strcmp(aFrametag,
"ARC_RED")) {
305 if (!strcmp(aFrametag,
"ARC_RESAMPLED")) {
308 if (!strcmp(aFrametag,
"WAVE_MAP")) {
326 muse_wavecal_create(cpl_plugin *aPlugin)
330 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
331 recipe = (cpl_recipe *)aPlugin;
339 muse_wavecal_new_recipeconfig(),
340 muse_wavecal_prepare_header,
341 muse_wavecal_get_frame_level,
342 muse_wavecal_get_frame_mode);
347 cpl_msg_set_time_on();
351 recipe->parameters = cpl_parameterlist_new();
356 p = cpl_parameter_new_range(
"muse.muse_wavecal.nifu",
358 "IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in parallel.",
363 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"nifu");
364 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"nifu");
366 cpl_parameterlist_append(recipe->parameters, p);
369 p = cpl_parameter_new_value(
"muse.muse_wavecal.overscan",
371 "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.",
373 (
const char *)
"vpoly");
374 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"overscan");
375 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"overscan");
377 cpl_parameterlist_append(recipe->parameters, p);
380 p = cpl_parameter_new_value(
"muse.muse_wavecal.ovscreject",
382 "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\").",
384 (
const char *)
"dcr");
385 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscreject");
386 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscreject");
388 cpl_parameterlist_append(recipe->parameters, p);
391 p = cpl_parameter_new_value(
"muse.muse_wavecal.ovscsigma",
393 "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\".",
396 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscsigma");
397 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscsigma");
399 cpl_parameterlist_append(recipe->parameters, p);
402 p = cpl_parameter_new_value(
"muse.muse_wavecal.ovscignore",
404 "The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when computing statistics or fits.",
407 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscignore");
408 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscignore");
410 cpl_parameterlist_append(recipe->parameters, p);
413 p = cpl_parameter_new_enum(
"muse.muse_wavecal.combine",
415 "Type of lampwise image combination to use.",
417 (
const char *)
"sigclip",
419 (
const char *)
"average",
420 (
const char *)
"median",
421 (
const char *)
"minmax",
422 (
const char *)
"sigclip");
423 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"combine");
424 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"combine");
426 cpl_parameterlist_append(recipe->parameters, p);
429 p = cpl_parameter_new_value(
"muse.muse_wavecal.lampwise",
431 "Identify and measure the arc emission lines on images separately for each lamp setup.",
434 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lampwise");
435 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lampwise");
437 cpl_parameterlist_append(recipe->parameters, p);
440 p = cpl_parameter_new_value(
"muse.muse_wavecal.sigma",
442 "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",
445 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"sigma");
446 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"sigma");
448 cpl_parameterlist_append(recipe->parameters, p);
451 p = cpl_parameter_new_value(
"muse.muse_wavecal.dres",
453 "The allowed range of resolutions for pattern matching (of detected arc lines to line list) in fractions relative to the expected value",
456 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"dres");
457 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"dres");
459 cpl_parameterlist_append(recipe->parameters, p);
462 p = cpl_parameter_new_value(
"muse.muse_wavecal.tolerance",
464 "Tolerance for pattern matching (of detected arc lines to line list)",
467 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"tolerance");
468 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"tolerance");
470 cpl_parameterlist_append(recipe->parameters, p);
473 p = cpl_parameter_new_value(
"muse.muse_wavecal.xorder",
475 "Order of the polynomial for the horizontal curvature within each slice",
478 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"xorder");
479 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"xorder");
481 cpl_parameterlist_append(recipe->parameters, p);
484 p = cpl_parameter_new_value(
"muse.muse_wavecal.yorder",
486 "Order of the polynomial used to fit the dispersion relation",
489 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"yorder");
490 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"yorder");
492 cpl_parameterlist_append(recipe->parameters, p);
495 p = cpl_parameter_new_value(
"muse.muse_wavecal.linesigma",
497 "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).",
500 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"linesigma");
501 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"linesigma");
503 cpl_parameterlist_append(recipe->parameters, p);
506 p = cpl_parameter_new_value(
"muse.muse_wavecal.residuals",
508 "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.",
511 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"residuals");
512 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"residuals");
514 cpl_parameterlist_append(recipe->parameters, p);
517 p = cpl_parameter_new_value(
"muse.muse_wavecal.fitsigma",
519 "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).",
522 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"fitsigma");
523 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"fitsigma");
525 cpl_parameterlist_append(recipe->parameters, p);
528 p = cpl_parameter_new_enum(
"muse.muse_wavecal.fitweighting",
530 "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.",
532 (
const char *)
"cerrscatter",
534 (
const char *)
"uniform",
535 (
const char *)
"cerr",
536 (
const char *)
"scatter",
537 (
const char *)
"cerrscatter");
538 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"fitweighting");
539 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"fitweighting");
541 cpl_parameterlist_append(recipe->parameters, p);
544 p = cpl_parameter_new_value(
"muse.muse_wavecal.resample",
546 "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!",
549 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"resample");
550 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"resample");
552 cpl_parameterlist_append(recipe->parameters, p);
555 p = cpl_parameter_new_value(
"muse.muse_wavecal.wavemap",
557 "Create a wavelength map of the input images",
560 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"wavemap");
561 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"wavemap");
563 cpl_parameterlist_append(recipe->parameters, p);
566 p = cpl_parameter_new_value(
"muse.muse_wavecal.merge",
568 "Merge output products from different IFUs into a common file.",
571 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"merge");
572 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"merge");
574 cpl_parameterlist_append(recipe->parameters, p);
594 cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
595 cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
598 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.nifu");
599 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
600 aParams->
nifu = cpl_parameter_get_int(p);
602 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.overscan");
603 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
604 aParams->
overscan = cpl_parameter_get_string(p);
606 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.ovscreject");
607 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
608 aParams->
ovscreject = cpl_parameter_get_string(p);
610 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.ovscsigma");
611 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
612 aParams->
ovscsigma = cpl_parameter_get_double(p);
614 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.ovscignore");
615 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
616 aParams->
ovscignore = cpl_parameter_get_int(p);
618 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.combine");
619 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
620 aParams->
combine_s = cpl_parameter_get_string(p);
622 (!strcasecmp(aParams->
combine_s,
"average")) ? MUSE_WAVECAL_PARAM_COMBINE_AVERAGE :
623 (!strcasecmp(aParams->
combine_s,
"median")) ? MUSE_WAVECAL_PARAM_COMBINE_MEDIAN :
624 (!strcasecmp(aParams->
combine_s,
"minmax")) ? MUSE_WAVECAL_PARAM_COMBINE_MINMAX :
625 (!strcasecmp(aParams->
combine_s,
"sigclip")) ? MUSE_WAVECAL_PARAM_COMBINE_SIGCLIP :
626 MUSE_WAVECAL_PARAM_COMBINE_INVALID_VALUE;
627 cpl_ensure_code(aParams->
combine != MUSE_WAVECAL_PARAM_COMBINE_INVALID_VALUE,
628 CPL_ERROR_ILLEGAL_INPUT);
630 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.lampwise");
631 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
632 aParams->
lampwise = cpl_parameter_get_bool(p);
634 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.sigma");
635 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
636 aParams->
sigma = cpl_parameter_get_double(p);
638 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.dres");
639 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
640 aParams->
dres = cpl_parameter_get_double(p);
642 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.tolerance");
643 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
644 aParams->
tolerance = cpl_parameter_get_double(p);
646 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.xorder");
647 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
648 aParams->
xorder = cpl_parameter_get_int(p);
650 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.yorder");
651 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
652 aParams->
yorder = cpl_parameter_get_int(p);
654 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.linesigma");
655 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
656 aParams->
linesigma = cpl_parameter_get_double(p);
658 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.residuals");
659 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
660 aParams->
residuals = cpl_parameter_get_bool(p);
662 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.fitsigma");
663 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
664 aParams->
fitsigma = cpl_parameter_get_double(p);
666 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.fitweighting");
667 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
670 (!strcasecmp(aParams->
fitweighting_s,
"uniform")) ? MUSE_WAVECAL_PARAM_FITWEIGHTING_UNIFORM :
671 (!strcasecmp(aParams->
fitweighting_s,
"cerr")) ? MUSE_WAVECAL_PARAM_FITWEIGHTING_CERR :
672 (!strcasecmp(aParams->
fitweighting_s,
"scatter")) ? MUSE_WAVECAL_PARAM_FITWEIGHTING_SCATTER :
673 (!strcasecmp(aParams->
fitweighting_s,
"cerrscatter")) ? MUSE_WAVECAL_PARAM_FITWEIGHTING_CERRSCATTER :
674 MUSE_WAVECAL_PARAM_FITWEIGHTING_INVALID_VALUE;
675 cpl_ensure_code(aParams->
fitweighting != MUSE_WAVECAL_PARAM_FITWEIGHTING_INVALID_VALUE,
676 CPL_ERROR_ILLEGAL_INPUT);
678 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.resample");
679 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
680 aParams->
resample = cpl_parameter_get_bool(p);
682 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.wavemap");
683 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
684 aParams->
wavemap = cpl_parameter_get_bool(p);
686 p = cpl_parameterlist_find(aParameters,
"muse.muse_wavecal.merge");
687 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
688 aParams->
merge = cpl_parameter_get_bool(p);
702 muse_wavecal_exec(cpl_plugin *aPlugin)
704 if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
707 cpl_recipe *recipe = (cpl_recipe *)aPlugin;
708 cpl_msg_set_threadid_on();
710 cpl_frameset *usedframes = cpl_frameset_new(),
711 *outframes = cpl_frameset_new();
713 muse_wavecal_params_fill(¶ms, recipe->parameters);
715 cpl_errorstate prestate = cpl_errorstate_get();
717 if (params.
nifu < -1 || params.
nifu > kMuseNumIFUs) {
718 cpl_msg_error(__func__,
"Please specify a valid IFU number (between 1 and "
719 "%d), 0 (to process all IFUs consecutively), or -1 (to "
720 "process all IFUs in parallel) using --nifu.", kMuseNumIFUs);
724 cpl_boolean donotmerge = CPL_FALSE;
726 if (params.
nifu > 0) {
729 rc = muse_wavecal_compute(proc, ¶ms);
730 cpl_frameset_join(usedframes, proc->
usedframes);
731 cpl_frameset_join(outframes, proc->
outframes);
733 donotmerge = CPL_TRUE;
734 }
else if (params.
nifu < 0) {
735 int *rcs = cpl_calloc(kMuseNumIFUs,
sizeof(
int));
737 #pragma omp parallel for default(none) \
738 shared(outframes, params, rcs, recipe, usedframes)
739 for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
745 int *rci = rcs + (nifu - 1);
746 *rci = muse_wavecal_compute(proc, pars);
747 if (rci && cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
751 #pragma omp critical(muse_processing_used_frames)
752 cpl_frameset_join(usedframes, proc->
usedframes);
753 #pragma omp critical(muse_processing_output_frames)
754 cpl_frameset_join(outframes, proc->
outframes);
759 for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
760 if (rcs[nifu-1] != 0) {
766 for (params.
nifu = 1; params.
nifu <= kMuseNumIFUs && !rc; params.
nifu++) {
769 rc = muse_wavecal_compute(proc, ¶ms);
770 if (rc && cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
773 cpl_frameset_join(usedframes, proc->
usedframes);
774 cpl_frameset_join(outframes, proc->
outframes);
778 UNUSED_ARGUMENT(donotmerge);
780 if (!cpl_errorstate_is_equal(prestate)) {
784 cpl_msg_set_level(CPL_MSG_INFO);
791 if (params.
merge && !donotmerge) {
792 muse_utils_frameset_merge_frames(outframes);
800 cpl_frameset_join(recipe->frames, usedframes);
801 cpl_frameset_join(recipe->frames, outframes);
802 cpl_frameset_delete(usedframes);
803 cpl_frameset_delete(outframes);
816 muse_wavecal_destroy(cpl_plugin *aPlugin)
820 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
821 recipe = (cpl_recipe *)aPlugin;
827 cpl_parameterlist_delete(recipe->parameters);
844 cpl_plugin_get_info(cpl_pluginlist *aList)
846 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
847 cpl_plugin *plugin = &recipe->interface;
851 helptext = cpl_sprintf(
"%s%s", muse_wavecal_help,
852 muse_wavecal_help_esorex);
854 helptext = cpl_sprintf(
"%s", muse_wavecal_help);
858 cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
859 CPL_PLUGIN_TYPE_RECIPE,
861 "Detect arc emission lines and determine the wavelength solution for each slice.",
868 muse_wavecal_destroy);
869 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 region of the CCD that are ignored when com...
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)
const char * fitweighting_s
Type of weighting to use in the final polynomial wavelength solution fit, using centroiding error est...
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.