35 #include "muse_scibasic_z.h" 84 static const char *muse_scibasic_help =
85 "Processing handles each raw input image separately: it trims the raw data and records the overscan statistics, subtracts the bias (taking account of the overscan, if --overscan is not \"none\"), optionally detects cosmic rays (note that by default cosmic ray rejection is handled in the post processing recipes while the data is reformatted into a datacube, so that the default setting is cr=\"none\" here), converts the images from adu to count, subtracts the dark, divides by the flat-field, and (optionally) propagates the integrated flux value from the twilight-sky cube. The reduced image is then saved (if --saveimage=true). The input calibrations geometry table, trace table, and wavelength calibration table are used to assign 3D coordinates to each CCD-based pixel, thereby creating a pixel table for each exposure. If --skylines contains one or more wavelengths for (bright and isolated) sky emission lines, these lines are used to correct the wavelength calibration using an offset. The data is then cut to a useful wavelength range (if --crop=true). If an ILLUM exposure was given as input, it is then used to correct the relative illumination between all slices of one IFU. For this, the data of each slice is multiplied by the normalized median flux of that slice in the ILLUM exposure. As last step, the data is divided by the normalized twilight cube (if given), using the 3D coordinate of each pixel in the pixel table to interpolate the twilight correction onto the data. This pre-reduced pixel table for each exposure is then saved to disk.";
87 static const char *muse_scibasic_help_esorex =
88 "\n\nInput frames for raw frame tag \"OBJECT\":\n" 89 "\n Frame tag Type Req #Fr Description" 90 "\n -------------------- ---- --- --- ------------" 91 "\n OBJECT raw . Raw exposure of a science target" 92 "\n STD raw . Raw exposure of a standard star field" 93 "\n SKY raw . Raw exposure of an (almost) empty sky field" 94 "\n ASTROMETRY raw . Raw exposure of an astrometric field" 95 "\n ILLUM raw . 1 Single optional raw (attached/illumination) flat-field exposure" 96 "\n MASTER_BIAS calib Y 1 Master bias" 97 "\n MASTER_DARK calib . 1 Master dark" 98 "\n MASTER_FLAT calib Y 1 Master flat" 99 "\n TRACE_TABLE calib Y 1 Trace table" 100 "\n WAVECAL_TABLE calib Y 1 Wavelength calibration table" 101 "\n GEOMETRY_TABLE calib Y 1 Relative positions of the slices in the field of view" 102 "\n TWILIGHT_CUBE calib . Smoothed cube of twilight sky" 103 "\n BADPIX_TABLE calib . Known bad pixels" 104 "\n\nProduct frames for raw frame tag \"OBJECT\":\n" 105 "\n Frame tag Level Description" 106 "\n -------------------- -------- ------------" 107 "\n OBJECT_RED intermed Pre-processed CCD-based images for OBJECT input (if --saveimage=true)" 108 "\n OBJECT_RESAMPLED intermed Resampled 2D image for OBJECT input (if --resample=true)" 109 "\n PIXTABLE_OBJECT intermed Output pixel table for OBJECT input" 110 "\n STD_RED intermed Pre-processed CCD-based images for STD input (if --saveimage=true)" 111 "\n STD_RESAMPLED intermed Resampled 2D image for STD input (if --resample=true)" 112 "\n PIXTABLE_STD intermed Output pixel table for STD input" 113 "\n SKY_RED intermed Pre-processed CCD-based images for SKY input (if --saveimage=true)" 114 "\n SKY_RESAMPLED intermed Resampled 2D image for SKY input (if --resample=true)" 115 "\n PIXTABLE_SKY intermed Output pixel table for SKY input" 116 "\n ASTROMETRY_RED intermed Pre-processed CCD-based images for ASTROMETRY input (if --saveimage=true)" 117 "\n ASTROMETRY_RESAMPLED intermed Resampled 2D image for ASTROMETRY input (if --resample=true)" 118 "\n PIXTABLE_ASTROMETRY intermed Output pixel table for ASTROMETRY input" "\n\nInput frames for raw frame tag \"REDUCED\":\n" 119 "\n Frame tag Type Req #Fr Description" 120 "\n -------------------- ---- --- --- ------------" 121 "\n REDUCED raw Y Reduced CCD image" 122 "\n TRACE_TABLE calib Y 1 Trace table" 123 "\n WAVECAL_TABLE calib Y 1 Wavelength calibration table" 124 "\n GEOMETRY_TABLE calib Y 1 Relative positions of the slices in the field of view" 125 "\n\nProduct frames for raw frame tag \"REDUCED\":\n" 126 "\n Frame tag Level Description" 127 "\n -------------------- -------- ------------" 128 "\n REDUCED_RESAMPLED intermed Resampled 2D image (if --resample=true)" 129 "\n PIXTABLE_REDUCED intermed Output pixel table";
140 static cpl_recipeconfig *
141 muse_scibasic_new_recipeconfig(
void)
143 cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
145 cpl_recipeconfig_set_tag(recipeconfig,
"OBJECT", -1, -1);
146 cpl_recipeconfig_set_input(recipeconfig,
"OBJECT",
"MASTER_BIAS", 1, 1);
147 cpl_recipeconfig_set_input(recipeconfig,
"OBJECT",
"MASTER_DARK", -1, 1);
148 cpl_recipeconfig_set_input(recipeconfig,
"OBJECT",
"MASTER_FLAT", 1, 1);
149 cpl_recipeconfig_set_input(recipeconfig,
"OBJECT",
"TRACE_TABLE", 1, 1);
150 cpl_recipeconfig_set_input(recipeconfig,
"OBJECT",
"WAVECAL_TABLE", 1, 1);
151 cpl_recipeconfig_set_input(recipeconfig,
"OBJECT",
"GEOMETRY_TABLE", 1, 1);
152 cpl_recipeconfig_set_input(recipeconfig,
"OBJECT",
"TWILIGHT_CUBE", -1, -1);
153 cpl_recipeconfig_set_input(recipeconfig,
"OBJECT",
"BADPIX_TABLE", -1, -1);
154 cpl_recipeconfig_set_output(recipeconfig,
"OBJECT",
"OBJECT_RED");
155 cpl_recipeconfig_set_output(recipeconfig,
"OBJECT",
"OBJECT_RESAMPLED");
156 cpl_recipeconfig_set_output(recipeconfig,
"OBJECT",
"PIXTABLE_OBJECT");
157 cpl_recipeconfig_set_tag(recipeconfig,
"STD", -1, -1);
158 cpl_recipeconfig_set_input(recipeconfig,
"STD",
"MASTER_BIAS", 1, 1);
159 cpl_recipeconfig_set_input(recipeconfig,
"STD",
"MASTER_DARK", -1, 1);
160 cpl_recipeconfig_set_input(recipeconfig,
"STD",
"MASTER_FLAT", 1, 1);
161 cpl_recipeconfig_set_input(recipeconfig,
"STD",
"TRACE_TABLE", 1, 1);
162 cpl_recipeconfig_set_input(recipeconfig,
"STD",
"WAVECAL_TABLE", 1, 1);
163 cpl_recipeconfig_set_input(recipeconfig,
"STD",
"GEOMETRY_TABLE", 1, 1);
164 cpl_recipeconfig_set_input(recipeconfig,
"STD",
"TWILIGHT_CUBE", -1, -1);
165 cpl_recipeconfig_set_input(recipeconfig,
"STD",
"BADPIX_TABLE", -1, -1);
166 cpl_recipeconfig_set_output(recipeconfig,
"STD",
"STD_RED");
167 cpl_recipeconfig_set_output(recipeconfig,
"STD",
"STD_RESAMPLED");
168 cpl_recipeconfig_set_output(recipeconfig,
"STD",
"PIXTABLE_STD");
169 cpl_recipeconfig_set_tag(recipeconfig,
"SKY", -1, -1);
170 cpl_recipeconfig_set_input(recipeconfig,
"SKY",
"MASTER_BIAS", 1, 1);
171 cpl_recipeconfig_set_input(recipeconfig,
"SKY",
"MASTER_DARK", -1, 1);
172 cpl_recipeconfig_set_input(recipeconfig,
"SKY",
"MASTER_FLAT", 1, 1);
173 cpl_recipeconfig_set_input(recipeconfig,
"SKY",
"TRACE_TABLE", 1, 1);
174 cpl_recipeconfig_set_input(recipeconfig,
"SKY",
"WAVECAL_TABLE", 1, 1);
175 cpl_recipeconfig_set_input(recipeconfig,
"SKY",
"GEOMETRY_TABLE", 1, 1);
176 cpl_recipeconfig_set_input(recipeconfig,
"SKY",
"TWILIGHT_CUBE", -1, -1);
177 cpl_recipeconfig_set_input(recipeconfig,
"SKY",
"BADPIX_TABLE", -1, -1);
178 cpl_recipeconfig_set_output(recipeconfig,
"SKY",
"SKY_RED");
179 cpl_recipeconfig_set_output(recipeconfig,
"SKY",
"SKY_RESAMPLED");
180 cpl_recipeconfig_set_output(recipeconfig,
"SKY",
"PIXTABLE_SKY");
181 cpl_recipeconfig_set_tag(recipeconfig,
"ASTROMETRY", -1, -1);
182 cpl_recipeconfig_set_input(recipeconfig,
"ASTROMETRY",
"MASTER_BIAS", 1, 1);
183 cpl_recipeconfig_set_input(recipeconfig,
"ASTROMETRY",
"MASTER_DARK", -1, 1);
184 cpl_recipeconfig_set_input(recipeconfig,
"ASTROMETRY",
"MASTER_FLAT", 1, 1);
185 cpl_recipeconfig_set_input(recipeconfig,
"ASTROMETRY",
"TRACE_TABLE", 1, 1);
186 cpl_recipeconfig_set_input(recipeconfig,
"ASTROMETRY",
"WAVECAL_TABLE", 1, 1);
187 cpl_recipeconfig_set_input(recipeconfig,
"ASTROMETRY",
"GEOMETRY_TABLE", 1, 1);
188 cpl_recipeconfig_set_input(recipeconfig,
"ASTROMETRY",
"TWILIGHT_CUBE", -1, -1);
189 cpl_recipeconfig_set_input(recipeconfig,
"ASTROMETRY",
"BADPIX_TABLE", -1, -1);
190 cpl_recipeconfig_set_output(recipeconfig,
"ASTROMETRY",
"ASTROMETRY_RED");
191 cpl_recipeconfig_set_output(recipeconfig,
"ASTROMETRY",
"ASTROMETRY_RESAMPLED");
192 cpl_recipeconfig_set_output(recipeconfig,
"ASTROMETRY",
"PIXTABLE_ASTROMETRY");
193 cpl_recipeconfig_set_tag(recipeconfig,
"ILLUM", -1, 1);
194 cpl_recipeconfig_set_input(recipeconfig,
"ILLUM",
"MASTER_BIAS", 1, 1);
195 cpl_recipeconfig_set_input(recipeconfig,
"ILLUM",
"MASTER_DARK", -1, 1);
196 cpl_recipeconfig_set_input(recipeconfig,
"ILLUM",
"MASTER_FLAT", 1, 1);
197 cpl_recipeconfig_set_input(recipeconfig,
"ILLUM",
"TRACE_TABLE", 1, 1);
198 cpl_recipeconfig_set_input(recipeconfig,
"ILLUM",
"WAVECAL_TABLE", 1, 1);
199 cpl_recipeconfig_set_input(recipeconfig,
"ILLUM",
"GEOMETRY_TABLE", 1, 1);
200 cpl_recipeconfig_set_input(recipeconfig,
"ILLUM",
"TWILIGHT_CUBE", -1, -1);
201 cpl_recipeconfig_set_input(recipeconfig,
"ILLUM",
"BADPIX_TABLE", -1, -1);
203 cpl_recipeconfig_set_tag(recipeconfig,
"REDUCED", 1, -1);
204 cpl_recipeconfig_set_input(recipeconfig,
"REDUCED",
"TRACE_TABLE", 1, 1);
205 cpl_recipeconfig_set_input(recipeconfig,
"REDUCED",
"WAVECAL_TABLE", 1, 1);
206 cpl_recipeconfig_set_input(recipeconfig,
"REDUCED",
"GEOMETRY_TABLE", 1, 1);
207 cpl_recipeconfig_set_output(recipeconfig,
"REDUCED",
"REDUCED_RESAMPLED");
208 cpl_recipeconfig_set_output(recipeconfig,
"REDUCED",
"PIXTABLE_REDUCED");
224 static cpl_error_code
225 muse_scibasic_prepare_header(
const char *aFrametag, cpl_propertylist *aHeader)
227 cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
228 cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
229 if (!strcmp(aFrametag,
"OBJECT_RED")) {
232 "Number of saturated pixels in output data");
233 }
else if (!strcmp(aFrametag,
"OBJECT_RESAMPLED")) {
234 }
else if (!strcmp(aFrametag,
"PIXTABLE_OBJECT")) {
237 "Number of saturated pixels in output data");
240 "[Angstrom] Shift in wavelength applied to the data using sky emission line(s)");
241 }
else if (!strcmp(aFrametag,
"STD_RED")) {
244 "Number of saturated pixels in output data");
245 }
else if (!strcmp(aFrametag,
"STD_RESAMPLED")) {
246 }
else if (!strcmp(aFrametag,
"PIXTABLE_STD")) {
249 "Number of saturated pixels in output data");
250 }
else if (!strcmp(aFrametag,
"SKY_RED")) {
253 "Number of saturated pixels in output data");
254 }
else if (!strcmp(aFrametag,
"SKY_RESAMPLED")) {
255 }
else if (!strcmp(aFrametag,
"PIXTABLE_SKY")) {
258 "Number of saturated pixels in output data");
259 }
else if (!strcmp(aFrametag,
"ASTROMETRY_RED")) {
262 "Number of saturated pixels in output data");
263 }
else if (!strcmp(aFrametag,
"ASTROMETRY_RESAMPLED")) {
264 }
else if (!strcmp(aFrametag,
"PIXTABLE_ASTROMETRY")) {
267 "Number of saturated pixels in output data");
268 }
else if (!strcmp(aFrametag,
"REDUCED_RESAMPLED")) {
269 }
else if (!strcmp(aFrametag,
"PIXTABLE_REDUCED")) {
271 cpl_msg_warning(__func__,
"Frame tag %s is not defined", aFrametag);
272 return CPL_ERROR_ILLEGAL_INPUT;
274 return CPL_ERROR_NONE;
287 static cpl_frame_level
288 muse_scibasic_get_frame_level(
const char *aFrametag)
291 return CPL_FRAME_LEVEL_NONE;
293 if (!strcmp(aFrametag,
"OBJECT_RED")) {
294 return CPL_FRAME_LEVEL_INTERMEDIATE;
296 if (!strcmp(aFrametag,
"OBJECT_RESAMPLED")) {
297 return CPL_FRAME_LEVEL_INTERMEDIATE;
299 if (!strcmp(aFrametag,
"PIXTABLE_OBJECT")) {
300 return CPL_FRAME_LEVEL_INTERMEDIATE;
302 if (!strcmp(aFrametag,
"STD_RED")) {
303 return CPL_FRAME_LEVEL_INTERMEDIATE;
305 if (!strcmp(aFrametag,
"STD_RESAMPLED")) {
306 return CPL_FRAME_LEVEL_INTERMEDIATE;
308 if (!strcmp(aFrametag,
"PIXTABLE_STD")) {
309 return CPL_FRAME_LEVEL_INTERMEDIATE;
311 if (!strcmp(aFrametag,
"SKY_RED")) {
312 return CPL_FRAME_LEVEL_INTERMEDIATE;
314 if (!strcmp(aFrametag,
"SKY_RESAMPLED")) {
315 return CPL_FRAME_LEVEL_INTERMEDIATE;
317 if (!strcmp(aFrametag,
"PIXTABLE_SKY")) {
318 return CPL_FRAME_LEVEL_INTERMEDIATE;
320 if (!strcmp(aFrametag,
"ASTROMETRY_RED")) {
321 return CPL_FRAME_LEVEL_INTERMEDIATE;
323 if (!strcmp(aFrametag,
"ASTROMETRY_RESAMPLED")) {
324 return CPL_FRAME_LEVEL_INTERMEDIATE;
326 if (!strcmp(aFrametag,
"PIXTABLE_ASTROMETRY")) {
327 return CPL_FRAME_LEVEL_INTERMEDIATE;
329 if (!strcmp(aFrametag,
"REDUCED_RESAMPLED")) {
330 return CPL_FRAME_LEVEL_INTERMEDIATE;
332 if (!strcmp(aFrametag,
"PIXTABLE_REDUCED")) {
333 return CPL_FRAME_LEVEL_INTERMEDIATE;
335 return CPL_FRAME_LEVEL_NONE;
349 muse_scibasic_get_frame_mode(
const char *aFrametag)
354 if (!strcmp(aFrametag,
"OBJECT_RED")) {
357 if (!strcmp(aFrametag,
"OBJECT_RESAMPLED")) {
360 if (!strcmp(aFrametag,
"PIXTABLE_OBJECT")) {
363 if (!strcmp(aFrametag,
"STD_RED")) {
366 if (!strcmp(aFrametag,
"STD_RESAMPLED")) {
369 if (!strcmp(aFrametag,
"PIXTABLE_STD")) {
372 if (!strcmp(aFrametag,
"SKY_RED")) {
375 if (!strcmp(aFrametag,
"SKY_RESAMPLED")) {
378 if (!strcmp(aFrametag,
"PIXTABLE_SKY")) {
381 if (!strcmp(aFrametag,
"ASTROMETRY_RED")) {
384 if (!strcmp(aFrametag,
"ASTROMETRY_RESAMPLED")) {
387 if (!strcmp(aFrametag,
"PIXTABLE_ASTROMETRY")) {
390 if (!strcmp(aFrametag,
"REDUCED_RESAMPLED")) {
393 if (!strcmp(aFrametag,
"PIXTABLE_REDUCED")) {
411 muse_scibasic_create(cpl_plugin *aPlugin)
415 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
416 recipe = (cpl_recipe *)aPlugin;
424 muse_scibasic_new_recipeconfig(),
425 muse_scibasic_prepare_header,
426 muse_scibasic_get_frame_level,
427 muse_scibasic_get_frame_mode);
432 cpl_msg_set_time_on();
436 recipe->parameters = cpl_parameterlist_new();
441 p = cpl_parameter_new_range(
"muse.muse_scibasic.nifu",
443 "IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in parallel.",
444 "muse.muse_scibasic",
448 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"nifu");
449 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"nifu");
451 cpl_parameterlist_append(recipe->parameters, p);
454 p = cpl_parameter_new_value(
"muse.muse_scibasic.overscan",
456 "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.",
457 "muse.muse_scibasic",
458 (
const char *)
"vpoly");
459 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"overscan");
460 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"overscan");
462 cpl_parameterlist_append(recipe->parameters, p);
465 p = cpl_parameter_new_value(
"muse.muse_scibasic.ovscreject",
467 "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\").",
468 "muse.muse_scibasic",
469 (
const char *)
"dcr");
470 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscreject");
471 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscreject");
473 cpl_parameterlist_append(recipe->parameters, p);
476 p = cpl_parameter_new_value(
"muse.muse_scibasic.ovscsigma",
478 "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\".",
479 "muse.muse_scibasic",
481 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscsigma");
482 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscsigma");
484 cpl_parameterlist_append(recipe->parameters, p);
487 p = cpl_parameter_new_value(
"muse.muse_scibasic.ovscignore",
489 "The number of pixels of the overscan adjacent to the data section of the CCD that are ignored when computing statistics or fits.",
490 "muse.muse_scibasic",
492 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ovscignore");
493 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ovscignore");
495 cpl_parameterlist_append(recipe->parameters, p);
498 p = cpl_parameter_new_value(
"muse.muse_scibasic.crop",
500 "Automatically crop the output pixel tables in wavelength depending on the expected useful wavelength range of the observation mode used (4750-9350 Angstrom for nominal mode, 4600-9350 Angstrom for extended mode, 4700-9350 Angstrom for nominal AO mode).",
501 "muse.muse_scibasic",
503 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"crop");
504 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"crop");
506 cpl_parameterlist_append(recipe->parameters, p);
509 p = cpl_parameter_new_enum(
"muse.muse_scibasic.cr",
511 "Type of cosmic ray cleaning to use (for quick-look data processing).",
512 "muse.muse_scibasic",
513 (
const char *)
"none",
515 (
const char *)
"none",
516 (
const char *)
"dcr");
517 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"cr");
518 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"cr");
520 cpl_parameterlist_append(recipe->parameters, p);
523 p = cpl_parameter_new_value(
"muse.muse_scibasic.xbox",
525 "Search box size in x. Only used if cr=dcr.",
526 "muse.muse_scibasic",
528 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"xbox");
529 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"xbox");
531 cpl_parameterlist_append(recipe->parameters, p);
534 p = cpl_parameter_new_value(
"muse.muse_scibasic.ybox",
536 "Search box size in y. Only used if cr=dcr.",
537 "muse.muse_scibasic",
539 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"ybox");
540 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ybox");
542 cpl_parameterlist_append(recipe->parameters, p);
545 p = cpl_parameter_new_value(
"muse.muse_scibasic.passes",
547 "Maximum number of cleaning passes. Only used if cr=dcr.",
548 "muse.muse_scibasic",
550 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"passes");
551 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"passes");
553 cpl_parameterlist_append(recipe->parameters, p);
556 p = cpl_parameter_new_value(
"muse.muse_scibasic.thres",
558 "Threshold for detection gap in factors of standard deviation. Only used if cr=dcr.",
559 "muse.muse_scibasic",
561 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"thres");
562 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"thres");
564 cpl_parameterlist_append(recipe->parameters, p);
567 p = cpl_parameter_new_enum(
"muse.muse_scibasic.combine",
569 "Type of combination to use. Note that in most cases, science exposures cannot easily be combined on the CCD level, so this should usually be kept as \"none\"! This does not pay attention about the type of input data, and will combine all raw inputs!",
570 "muse.muse_scibasic",
571 (
const char *)
"none",
573 (
const char *)
"none",
574 (
const char *)
"average",
575 (
const char *)
"median",
576 (
const char *)
"minmax",
577 (
const char *)
"sigclip");
578 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"combine");
579 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"combine");
580 if (!getenv(
"MUSE_EXPERT_USER")) {
581 cpl_parameter_disable(p, CPL_PARAMETER_MODE_CLI);
584 cpl_parameterlist_append(recipe->parameters, p);
587 p = cpl_parameter_new_value(
"muse.muse_scibasic.nlow",
589 "Number of minimum pixels to reject with minmax",
590 "muse.muse_scibasic",
592 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"nlow");
593 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"nlow");
594 if (!getenv(
"MUSE_EXPERT_USER")) {
595 cpl_parameter_disable(p, CPL_PARAMETER_MODE_CLI);
598 cpl_parameterlist_append(recipe->parameters, p);
601 p = cpl_parameter_new_value(
"muse.muse_scibasic.nhigh",
603 "Number of maximum pixels to reject with minmax",
604 "muse.muse_scibasic",
606 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"nhigh");
607 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"nhigh");
608 if (!getenv(
"MUSE_EXPERT_USER")) {
609 cpl_parameter_disable(p, CPL_PARAMETER_MODE_CLI);
612 cpl_parameterlist_append(recipe->parameters, p);
615 p = cpl_parameter_new_value(
"muse.muse_scibasic.nkeep",
617 "Number of pixels to keep with minmax",
618 "muse.muse_scibasic",
620 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"nkeep");
621 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"nkeep");
622 if (!getenv(
"MUSE_EXPERT_USER")) {
623 cpl_parameter_disable(p, CPL_PARAMETER_MODE_CLI);
626 cpl_parameterlist_append(recipe->parameters, p);
629 p = cpl_parameter_new_value(
"muse.muse_scibasic.lsigma",
631 "Low sigma for pixel rejection with sigclip",
632 "muse.muse_scibasic",
634 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"lsigma");
635 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"lsigma");
636 if (!getenv(
"MUSE_EXPERT_USER")) {
637 cpl_parameter_disable(p, CPL_PARAMETER_MODE_CLI);
640 cpl_parameterlist_append(recipe->parameters, p);
643 p = cpl_parameter_new_value(
"muse.muse_scibasic.hsigma",
645 "High sigma for pixel rejection with sigclip",
646 "muse.muse_scibasic",
648 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"hsigma");
649 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"hsigma");
650 if (!getenv(
"MUSE_EXPERT_USER")) {
651 cpl_parameter_disable(p, CPL_PARAMETER_MODE_CLI);
654 cpl_parameterlist_append(recipe->parameters, p);
657 p = cpl_parameter_new_value(
"muse.muse_scibasic.scale",
659 "Scale the individual images to a common exposure time before combining them.",
660 "muse.muse_scibasic",
662 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"scale");
663 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"scale");
664 if (!getenv(
"MUSE_EXPERT_USER")) {
665 cpl_parameter_disable(p, CPL_PARAMETER_MODE_CLI);
668 cpl_parameterlist_append(recipe->parameters, p);
671 p = cpl_parameter_new_value(
"muse.muse_scibasic.saveimage",
673 "Save the pre-processed CCD-based image of each input exposure before it is transformed into a pixel table.",
674 "muse.muse_scibasic",
676 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"saveimage");
677 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"saveimage");
679 cpl_parameterlist_append(recipe->parameters, p);
682 p = cpl_parameter_new_value(
"muse.muse_scibasic.skylines",
684 "List of wavelengths of sky emission lines (in Angstrom) to use as reference for wavelength offset correction using a Gaussian fit. It can contain multiple (isolated) lines, as comma-separated list, individual shifts are then combined into one weighted average offset. Set to \"none\" to deactivate.",
685 "muse.muse_scibasic",
686 (
const char *)
"5577.339,6300.304");
687 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"skylines");
688 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"skylines");
690 cpl_parameterlist_append(recipe->parameters, p);
693 p = cpl_parameter_new_value(
"muse.muse_scibasic.skyhalfwidth",
695 "Half-width of the extraction box (in Angstrom) around each sky emission line.",
696 "muse.muse_scibasic",
698 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"skyhalfwidth");
699 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"skyhalfwidth");
701 cpl_parameterlist_append(recipe->parameters, p);
704 p = cpl_parameter_new_value(
"muse.muse_scibasic.skybinsize",
706 "Size of the bins (in Angstrom per pixel) for the intermediate spectrum to do the Gaussian fit to each sky emission line.",
707 "muse.muse_scibasic",
709 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"skybinsize");
710 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"skybinsize");
712 cpl_parameterlist_append(recipe->parameters, p);
715 p = cpl_parameter_new_value(
"muse.muse_scibasic.skyreject",
717 "Sigma clipping parameters for the intermediate spectrum to do the Gaussian fit to each sky emission line. Up to three comma-separated numbers can be given, which are interpreted as high sigma-clipping limit (float), low limit (float), and number of iterations (integer), respectively.",
718 "muse.muse_scibasic",
719 (
const char *)
"15.,15.,1");
720 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"skyreject");
721 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"skyreject");
723 cpl_parameterlist_append(recipe->parameters, p);
726 p = cpl_parameter_new_value(
"muse.muse_scibasic.resample",
728 "Resample the input science data into 2D spectral images using all supplied calibrations for a visual check. Note that the image produced will show small wiggles even when the input calibrations are good and were applied successfully!",
729 "muse.muse_scibasic",
731 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"resample");
732 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"resample");
734 cpl_parameterlist_append(recipe->parameters, p);
737 p = cpl_parameter_new_value(
"muse.muse_scibasic.dlambda",
739 "Wavelength step (in Angstrom per pixel) to use for resampling.",
740 "muse.muse_scibasic",
742 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"dlambda");
743 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"dlambda");
745 cpl_parameterlist_append(recipe->parameters, p);
748 p = cpl_parameter_new_value(
"muse.muse_scibasic.merge",
750 "Merge output products from different IFUs into a common file.",
751 "muse.muse_scibasic",
753 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG,
"merge");
754 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"merge");
756 cpl_parameterlist_append(recipe->parameters, p);
776 cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
777 cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
780 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.nifu");
781 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
782 aParams->
nifu = cpl_parameter_get_int(p);
784 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.overscan");
785 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
786 aParams->
overscan = cpl_parameter_get_string(p);
788 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.ovscreject");
789 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
790 aParams->
ovscreject = cpl_parameter_get_string(p);
792 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.ovscsigma");
793 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
794 aParams->
ovscsigma = cpl_parameter_get_double(p);
796 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.ovscignore");
797 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
798 aParams->
ovscignore = cpl_parameter_get_int(p);
800 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.crop");
801 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
802 aParams->
crop = cpl_parameter_get_bool(p);
804 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.cr");
805 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
806 aParams->
cr_s = cpl_parameter_get_string(p);
808 (!strcasecmp(aParams->
cr_s,
"none")) ? MUSE_SCIBASIC_PARAM_CR_NONE :
809 (!strcasecmp(aParams->
cr_s,
"dcr")) ? MUSE_SCIBASIC_PARAM_CR_DCR :
810 MUSE_SCIBASIC_PARAM_CR_INVALID_VALUE;
811 cpl_ensure_code(aParams->
cr != MUSE_SCIBASIC_PARAM_CR_INVALID_VALUE,
812 CPL_ERROR_ILLEGAL_INPUT);
814 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.xbox");
815 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
816 aParams->
xbox = cpl_parameter_get_int(p);
818 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.ybox");
819 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
820 aParams->
ybox = cpl_parameter_get_int(p);
822 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.passes");
823 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
824 aParams->
passes = cpl_parameter_get_int(p);
826 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.thres");
827 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
828 aParams->
thres = cpl_parameter_get_double(p);
830 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.combine");
831 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
832 aParams->
combine_s = cpl_parameter_get_string(p);
834 (!strcasecmp(aParams->
combine_s,
"none")) ? MUSE_SCIBASIC_PARAM_COMBINE_NONE :
835 (!strcasecmp(aParams->
combine_s,
"average")) ? MUSE_SCIBASIC_PARAM_COMBINE_AVERAGE :
836 (!strcasecmp(aParams->
combine_s,
"median")) ? MUSE_SCIBASIC_PARAM_COMBINE_MEDIAN :
837 (!strcasecmp(aParams->
combine_s,
"minmax")) ? MUSE_SCIBASIC_PARAM_COMBINE_MINMAX :
838 (!strcasecmp(aParams->
combine_s,
"sigclip")) ? MUSE_SCIBASIC_PARAM_COMBINE_SIGCLIP :
839 MUSE_SCIBASIC_PARAM_COMBINE_INVALID_VALUE;
840 cpl_ensure_code(aParams->
combine != MUSE_SCIBASIC_PARAM_COMBINE_INVALID_VALUE,
841 CPL_ERROR_ILLEGAL_INPUT);
843 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.nlow");
844 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
845 aParams->
nlow = cpl_parameter_get_int(p);
847 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.nhigh");
848 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
849 aParams->
nhigh = cpl_parameter_get_int(p);
851 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.nkeep");
852 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
853 aParams->
nkeep = cpl_parameter_get_int(p);
855 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.lsigma");
856 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
857 aParams->
lsigma = cpl_parameter_get_double(p);
859 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.hsigma");
860 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
861 aParams->
hsigma = cpl_parameter_get_double(p);
863 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.scale");
864 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
865 aParams->
scale = cpl_parameter_get_bool(p);
867 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.saveimage");
868 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
869 aParams->
saveimage = cpl_parameter_get_bool(p);
871 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.skylines");
872 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
873 aParams->
skylines = cpl_parameter_get_string(p);
875 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.skyhalfwidth");
876 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
879 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.skybinsize");
880 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
881 aParams->
skybinsize = cpl_parameter_get_double(p);
883 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.skyreject");
884 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
885 aParams->
skyreject = cpl_parameter_get_string(p);
887 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.resample");
888 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
889 aParams->
resample = cpl_parameter_get_bool(p);
891 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.dlambda");
892 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
893 aParams->
dlambda = cpl_parameter_get_double(p);
895 p = cpl_parameterlist_find(aParameters,
"muse.muse_scibasic.merge");
896 cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
897 aParams->
merge = cpl_parameter_get_bool(p);
911 muse_scibasic_exec(cpl_plugin *aPlugin)
913 if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
917 cpl_recipe *recipe = (cpl_recipe *)aPlugin;
918 cpl_msg_set_threadid_on();
920 cpl_frameset *usedframes = cpl_frameset_new(),
921 *outframes = cpl_frameset_new();
923 muse_scibasic_params_fill(¶ms, recipe->parameters);
925 cpl_errorstate prestate = cpl_errorstate_get();
927 if (params.
nifu < -1 || params.
nifu > kMuseNumIFUs) {
928 cpl_msg_error(__func__,
"Please specify a valid IFU number (between 1 and " 929 "%d), 0 (to process all IFUs consecutively), or -1 (to " 930 "process all IFUs in parallel) using --nifu.", kMuseNumIFUs);
934 cpl_boolean donotmerge = CPL_FALSE;
936 if (params.
nifu > 0) {
939 rc = muse_scibasic_compute(proc, ¶ms);
940 cpl_frameset_join(usedframes, proc->
usedframes);
941 cpl_frameset_join(outframes, proc->
outframes);
943 donotmerge = CPL_TRUE;
944 }
else if (params.
nifu < 0) {
945 int *rcs = cpl_calloc(kMuseNumIFUs,
sizeof(
int));
947 #pragma omp parallel for default(none) \ 948 shared(outframes, params, rcs, recipe, usedframes) 949 for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
955 int *rci = rcs + (nifu - 1);
956 *rci = muse_scibasic_compute(proc, pars);
957 if (rci && (
int)cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
961 #pragma omp critical(muse_processing_used_frames) 962 cpl_frameset_join(usedframes, proc->
usedframes);
963 #pragma omp critical(muse_processing_output_frames) 964 cpl_frameset_join(outframes, proc->
outframes);
969 for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
970 if (rcs[nifu-1] != 0) {
976 for (params.
nifu = 1; params.
nifu <= kMuseNumIFUs && !rc; params.
nifu++) {
979 rc = muse_scibasic_compute(proc, ¶ms);
980 if (rc && (
int)cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
983 cpl_frameset_join(usedframes, proc->
usedframes);
984 cpl_frameset_join(outframes, proc->
outframes);
988 UNUSED_ARGUMENT(donotmerge);
990 if (!cpl_errorstate_is_equal(prestate)) {
994 cpl_msg_set_level(CPL_MSG_INFO);
1001 if (params.
merge && !donotmerge) {
1010 cpl_frameset_join(recipe->frames, usedframes);
1011 cpl_frameset_join(recipe->frames, outframes);
1012 cpl_frameset_delete(usedframes);
1013 cpl_frameset_delete(outframes);
1026 muse_scibasic_destroy(cpl_plugin *aPlugin)
1030 if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
1031 recipe = (cpl_recipe *)aPlugin;
1037 cpl_parameterlist_delete(recipe->parameters);
1054 cpl_plugin_get_info(cpl_pluginlist *aList)
1056 cpl_recipe *recipe = cpl_calloc(1,
sizeof *recipe);
1057 cpl_plugin *plugin = &recipe->interface;
1061 helptext = cpl_sprintf(
"%s%s", muse_scibasic_help,
1062 muse_scibasic_help_esorex);
1064 helptext = cpl_sprintf(
"%s", muse_scibasic_help);
1068 cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
1069 CPL_PLUGIN_TYPE_RECIPE,
1071 "Remove the instrumental signature from the data of each CCD and convert them from an image into a pixel table.",
1076 muse_scibasic_create,
1078 muse_scibasic_destroy);
1079 cpl_pluginlist_append(aList, plugin);
const char * skyreject
Sigma clipping parameters for the intermediate spectrum to do the Gaussian fit to each sky emission l...
void muse_processing_delete(muse_processing *aProcessing)
Free the muse_processing structure.
int nkeep
Number of pixels to keep with minmax.
double hsigma
High sigma for pixel rejection with sigclip.
muse_cplframework_type muse_cplframework(void)
Return the CPL framework the recipe is run under.
int passes
Maximum number of cleaning passes. Only used if cr=dcr.
double ovscsigma
If the deviation of mean overscan levels between a raw input image and the reference image is higher ...
const char * combine_s
Type of combination to use. Note that in most cases, science exposures cannot easily be combined on t...
double dlambda
Wavelength step (in Angstrom per pixel) to use for resampling.
double lsigma
Low sigma for pixel rejection with sigclip.
int combine
Type of combination to use. Note that in most cases, science exposures cannot easily be combined on t...
int scale
Scale the individual images to a common exposure time before combining them.
cpl_frameset * usedframes
muse_processing * muse_processing_new(const char *aName, cpl_recipe *aRecipe)
Create a new processing structure.
int saveimage
Save the pre-processed CCD-based image of each input exposure before it is transformed into a pixel t...
const char * muse_get_license(void)
Get the pipeline copyright and license.
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 cr
Type of cosmic ray cleaning to use (for quick-look data processing).
int resample
Resample the input science data into 2D spectral images using all supplied calibrations for a visual ...
int merge
Merge output products from different IFUs into a common file.
int nifu
IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in ...
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.
double skyhalfwidth
Half-width of the extraction box (in Angstrom) around each sky emission line.
int crop
Automatically crop the output pixel tables in wavelength depending on the expected useful wavelength ...
const char * ovscreject
This influences how values are rejected when computing overscan statistics. Either no rejection at al...
int xbox
Search box size in x. Only used if cr=dcr.
int nhigh
Number of maximum pixels to reject with minmax.
cpl_error_code muse_cplframeset_erase_duplicate(cpl_frameset *aFrames)
Erase all duplicate frames from a frameset.
int ybox
Search box size in y. Only used if cr=dcr.
double thres
Threshold for detection gap in factors of standard deviation. Only used if cr=dcr.
Structure to hold the parameters of the muse_scibasic recipe.
double skybinsize
Size of the bins (in Angstrom per pixel) for the intermediate spectrum to do the Gaussian fit to each...
cpl_error_code muse_cplframeset_erase_all(cpl_frameset *aFrames)
Erase all frames in a frameset.
const char * cr_s
Type of cosmic ray cleaning to use (for quick-look data processing). (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.
const char * skylines
List of wavelengths of sky emission lines (in Angstrom) to use as reference for wavelength offset cor...
int ovscignore
The number of pixels of the overscan adjacent to the data section of the CCD that are ignored when co...
void muse_processing_recipeinfo(cpl_plugin *)
Output main pipeline configuration, inputs, and parameters.
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.
int nlow
Number of minimum pixels to reject with minmax.
cpl_error_code muse_processing_prepare_property(cpl_propertylist *, const char *, cpl_type, const char *)
Prepare and check the specified property.