MUSE Pipeline Reference Manual  2.1.1
muse_scibasic_z.c
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set sw=2 sts=2 et cin: */
3 /*
4  * This file is part of the MUSE Instrument Pipeline
5  * Copyright (C) 2005-2015 European Southern Observatory
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21 
22 /* This file was automatically generated */
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 /*----------------------------------------------------------------------------*
29  * Includes *
30  *----------------------------------------------------------------------------*/
31 #include <string.h> /* strcmp(), strstr() */
32 #include <strings.h> /* strcasecmp() */
33 #include <cpl.h>
34 
35 #include "muse_scibasic_z.h" /* in turn includes muse.h */
36 
37 /*----------------------------------------------------------------------------*/
78 /*----------------------------------------------------------------------------*/
81 /*----------------------------------------------------------------------------*
82  * Static variables *
83  *----------------------------------------------------------------------------*/
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.";
86 
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";
130 
131 /*----------------------------------------------------------------------------*/
139 /*----------------------------------------------------------------------------*/
140 static cpl_recipeconfig *
141 muse_scibasic_new_recipeconfig(void)
142 {
143  cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
144 
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);
202 
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");
209 
210  return recipeconfig;
211 } /* muse_scibasic_new_recipeconfig() */
212 
213 /*----------------------------------------------------------------------------*/
223 /*----------------------------------------------------------------------------*/
224 static cpl_error_code
225 muse_scibasic_prepare_header(const char *aFrametag, cpl_propertylist *aHeader)
226 {
227  cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
228  cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
229  if (!strcmp(aFrametag, "OBJECT_RED")) {
230  muse_processing_prepare_property(aHeader, "ESO QC SCIBASIC NSATURATED",
231  CPL_TYPE_INT,
232  "Number of saturated pixels in output data");
233  } else if (!strcmp(aFrametag, "OBJECT_RESAMPLED")) {
234  } else if (!strcmp(aFrametag, "PIXTABLE_OBJECT")) {
235  muse_processing_prepare_property(aHeader, "ESO QC SCIBASIC NSATURATED",
236  CPL_TYPE_INT,
237  "Number of saturated pixels in output data");
238  muse_processing_prepare_property(aHeader, "ESO QC SCIBASIC LAMBDA SHIFT",
239  CPL_TYPE_FLOAT,
240  "[Angstrom] Shift in wavelength applied to the data using sky emission line(s)");
241  } else if (!strcmp(aFrametag, "STD_RED")) {
242  muse_processing_prepare_property(aHeader, "ESO QC SCIBASIC NSATURATED",
243  CPL_TYPE_INT,
244  "Number of saturated pixels in output data");
245  } else if (!strcmp(aFrametag, "STD_RESAMPLED")) {
246  } else if (!strcmp(aFrametag, "PIXTABLE_STD")) {
247  muse_processing_prepare_property(aHeader, "ESO QC SCIBASIC NSATURATED",
248  CPL_TYPE_INT,
249  "Number of saturated pixels in output data");
250  } else if (!strcmp(aFrametag, "SKY_RED")) {
251  muse_processing_prepare_property(aHeader, "ESO QC SCIBASIC NSATURATED",
252  CPL_TYPE_INT,
253  "Number of saturated pixels in output data");
254  } else if (!strcmp(aFrametag, "SKY_RESAMPLED")) {
255  } else if (!strcmp(aFrametag, "PIXTABLE_SKY")) {
256  muse_processing_prepare_property(aHeader, "ESO QC SCIBASIC NSATURATED",
257  CPL_TYPE_INT,
258  "Number of saturated pixels in output data");
259  } else if (!strcmp(aFrametag, "ASTROMETRY_RED")) {
260  muse_processing_prepare_property(aHeader, "ESO QC SCIBASIC NSATURATED",
261  CPL_TYPE_INT,
262  "Number of saturated pixels in output data");
263  } else if (!strcmp(aFrametag, "ASTROMETRY_RESAMPLED")) {
264  } else if (!strcmp(aFrametag, "PIXTABLE_ASTROMETRY")) {
265  muse_processing_prepare_property(aHeader, "ESO QC SCIBASIC NSATURATED",
266  CPL_TYPE_INT,
267  "Number of saturated pixels in output data");
268  } else if (!strcmp(aFrametag, "REDUCED_RESAMPLED")) {
269  } else if (!strcmp(aFrametag, "PIXTABLE_REDUCED")) {
270  } else {
271  cpl_msg_warning(__func__, "Frame tag %s is not defined", aFrametag);
272  return CPL_ERROR_ILLEGAL_INPUT;
273  }
274  return CPL_ERROR_NONE;
275 } /* muse_scibasic_prepare_header() */
276 
277 /*----------------------------------------------------------------------------*/
286 /*----------------------------------------------------------------------------*/
287 static cpl_frame_level
288 muse_scibasic_get_frame_level(const char *aFrametag)
289 {
290  if (!aFrametag) {
291  return CPL_FRAME_LEVEL_NONE;
292  }
293  if (!strcmp(aFrametag, "OBJECT_RED")) {
294  return CPL_FRAME_LEVEL_INTERMEDIATE;
295  }
296  if (!strcmp(aFrametag, "OBJECT_RESAMPLED")) {
297  return CPL_FRAME_LEVEL_INTERMEDIATE;
298  }
299  if (!strcmp(aFrametag, "PIXTABLE_OBJECT")) {
300  return CPL_FRAME_LEVEL_INTERMEDIATE;
301  }
302  if (!strcmp(aFrametag, "STD_RED")) {
303  return CPL_FRAME_LEVEL_INTERMEDIATE;
304  }
305  if (!strcmp(aFrametag, "STD_RESAMPLED")) {
306  return CPL_FRAME_LEVEL_INTERMEDIATE;
307  }
308  if (!strcmp(aFrametag, "PIXTABLE_STD")) {
309  return CPL_FRAME_LEVEL_INTERMEDIATE;
310  }
311  if (!strcmp(aFrametag, "SKY_RED")) {
312  return CPL_FRAME_LEVEL_INTERMEDIATE;
313  }
314  if (!strcmp(aFrametag, "SKY_RESAMPLED")) {
315  return CPL_FRAME_LEVEL_INTERMEDIATE;
316  }
317  if (!strcmp(aFrametag, "PIXTABLE_SKY")) {
318  return CPL_FRAME_LEVEL_INTERMEDIATE;
319  }
320  if (!strcmp(aFrametag, "ASTROMETRY_RED")) {
321  return CPL_FRAME_LEVEL_INTERMEDIATE;
322  }
323  if (!strcmp(aFrametag, "ASTROMETRY_RESAMPLED")) {
324  return CPL_FRAME_LEVEL_INTERMEDIATE;
325  }
326  if (!strcmp(aFrametag, "PIXTABLE_ASTROMETRY")) {
327  return CPL_FRAME_LEVEL_INTERMEDIATE;
328  }
329  if (!strcmp(aFrametag, "REDUCED_RESAMPLED")) {
330  return CPL_FRAME_LEVEL_INTERMEDIATE;
331  }
332  if (!strcmp(aFrametag, "PIXTABLE_REDUCED")) {
333  return CPL_FRAME_LEVEL_INTERMEDIATE;
334  }
335  return CPL_FRAME_LEVEL_NONE;
336 } /* muse_scibasic_get_frame_level() */
337 
338 /*----------------------------------------------------------------------------*/
347 /*----------------------------------------------------------------------------*/
348 static muse_frame_mode
349 muse_scibasic_get_frame_mode(const char *aFrametag)
350 {
351  if (!aFrametag) {
352  return MUSE_FRAME_MODE_ALL;
353  }
354  if (!strcmp(aFrametag, "OBJECT_RED")) {
356  }
357  if (!strcmp(aFrametag, "OBJECT_RESAMPLED")) {
359  }
360  if (!strcmp(aFrametag, "PIXTABLE_OBJECT")) {
362  }
363  if (!strcmp(aFrametag, "STD_RED")) {
365  }
366  if (!strcmp(aFrametag, "STD_RESAMPLED")) {
368  }
369  if (!strcmp(aFrametag, "PIXTABLE_STD")) {
371  }
372  if (!strcmp(aFrametag, "SKY_RED")) {
374  }
375  if (!strcmp(aFrametag, "SKY_RESAMPLED")) {
377  }
378  if (!strcmp(aFrametag, "PIXTABLE_SKY")) {
380  }
381  if (!strcmp(aFrametag, "ASTROMETRY_RED")) {
383  }
384  if (!strcmp(aFrametag, "ASTROMETRY_RESAMPLED")) {
386  }
387  if (!strcmp(aFrametag, "PIXTABLE_ASTROMETRY")) {
389  }
390  if (!strcmp(aFrametag, "REDUCED_RESAMPLED")) {
392  }
393  if (!strcmp(aFrametag, "PIXTABLE_REDUCED")) {
395  }
396  return MUSE_FRAME_MODE_ALL;
397 } /* muse_scibasic_get_frame_mode() */
398 
399 /*----------------------------------------------------------------------------*/
409 /*----------------------------------------------------------------------------*/
410 static int
411 muse_scibasic_create(cpl_plugin *aPlugin)
412 {
413  /* Check that the plugin is part of a valid recipe */
414  cpl_recipe *recipe;
415  if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
416  recipe = (cpl_recipe *)aPlugin;
417  } else {
418  return -1;
419  }
420 
421  /* register the extended processing information (new FITS header creation, *
422  * getting of the frame level for a certain tag) */
424  muse_scibasic_new_recipeconfig(),
425  muse_scibasic_prepare_header,
426  muse_scibasic_get_frame_level,
427  muse_scibasic_get_frame_mode);
428 
429  /* XXX initialize timing in messages *
430  * since at least esorex is too stupid to turn it on, we have to do it */
432  cpl_msg_set_time_on();
433  }
434 
435  /* Create the parameter list in the cpl_recipe object */
436  recipe->parameters = cpl_parameterlist_new();
437  /* Fill the parameters list */
438  cpl_parameter *p;
439 
440  /* --nifu: IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in parallel. */
441  p = cpl_parameter_new_range("muse.muse_scibasic.nifu",
442  CPL_TYPE_INT,
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",
445  (int)0,
446  (int)-1,
447  (int)24);
448  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nifu");
449  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nifu");
450 
451  cpl_parameterlist_append(recipe->parameters, p);
452 
453  /* --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. */
454  p = cpl_parameter_new_value("muse.muse_scibasic.overscan",
455  CPL_TYPE_STRING,
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");
461 
462  cpl_parameterlist_append(recipe->parameters, p);
463 
464  /* --ovscreject: 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"). */
465  p = cpl_parameter_new_value("muse.muse_scibasic.ovscreject",
466  CPL_TYPE_STRING,
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");
472 
473  cpl_parameterlist_append(recipe->parameters, p);
474 
475  /* --ovscsigma: 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". */
476  p = cpl_parameter_new_value("muse.muse_scibasic.ovscsigma",
477  CPL_TYPE_DOUBLE,
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",
480  (double)30.);
481  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscsigma");
482  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscsigma");
483 
484  cpl_parameterlist_append(recipe->parameters, p);
485 
486  /* --ovscignore: The number of pixels of the overscan adjacent to the data section of the CCD that are ignored when computing statistics or fits. */
487  p = cpl_parameter_new_value("muse.muse_scibasic.ovscignore",
488  CPL_TYPE_INT,
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",
491  (int)3);
492  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscignore");
493  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscignore");
494 
495  cpl_parameterlist_append(recipe->parameters, p);
496 
497  /* --crop: 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). */
498  p = cpl_parameter_new_value("muse.muse_scibasic.crop",
499  CPL_TYPE_BOOL,
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",
502  (int)TRUE);
503  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "crop");
504  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "crop");
505 
506  cpl_parameterlist_append(recipe->parameters, p);
507 
508  /* --cr: Type of cosmic ray cleaning to use (for quick-look data processing). */
509  p = cpl_parameter_new_enum("muse.muse_scibasic.cr",
510  CPL_TYPE_STRING,
511  "Type of cosmic ray cleaning to use (for quick-look data processing).",
512  "muse.muse_scibasic",
513  (const char *)"none",
514  2,
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");
519 
520  cpl_parameterlist_append(recipe->parameters, p);
521 
522  /* --xbox: Search box size in x. Only used if cr=dcr. */
523  p = cpl_parameter_new_value("muse.muse_scibasic.xbox",
524  CPL_TYPE_INT,
525  "Search box size in x. Only used if cr=dcr.",
526  "muse.muse_scibasic",
527  (int)15);
528  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "xbox");
529  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xbox");
530 
531  cpl_parameterlist_append(recipe->parameters, p);
532 
533  /* --ybox: Search box size in y. Only used if cr=dcr. */
534  p = cpl_parameter_new_value("muse.muse_scibasic.ybox",
535  CPL_TYPE_INT,
536  "Search box size in y. Only used if cr=dcr.",
537  "muse.muse_scibasic",
538  (int)40);
539  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ybox");
540  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ybox");
541 
542  cpl_parameterlist_append(recipe->parameters, p);
543 
544  /* --passes: Maximum number of cleaning passes. Only used if cr=dcr. */
545  p = cpl_parameter_new_value("muse.muse_scibasic.passes",
546  CPL_TYPE_INT,
547  "Maximum number of cleaning passes. Only used if cr=dcr.",
548  "muse.muse_scibasic",
549  (int)2);
550  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "passes");
551  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "passes");
552 
553  cpl_parameterlist_append(recipe->parameters, p);
554 
555  /* --thres: Threshold for detection gap in factors of standard deviation. Only used if cr=dcr. */
556  p = cpl_parameter_new_value("muse.muse_scibasic.thres",
557  CPL_TYPE_DOUBLE,
558  "Threshold for detection gap in factors of standard deviation. Only used if cr=dcr.",
559  "muse.muse_scibasic",
560  (double)5.8);
561  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "thres");
562  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "thres");
563 
564  cpl_parameterlist_append(recipe->parameters, p);
565 
566  /* --combine: 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! */
567  p = cpl_parameter_new_enum("muse.muse_scibasic.combine",
568  CPL_TYPE_STRING,
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",
572  5,
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);
582  }
583 
584  cpl_parameterlist_append(recipe->parameters, p);
585 
586  /* --nlow: Number of minimum pixels to reject with minmax */
587  p = cpl_parameter_new_value("muse.muse_scibasic.nlow",
588  CPL_TYPE_INT,
589  "Number of minimum pixels to reject with minmax",
590  "muse.muse_scibasic",
591  (int)1);
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);
596  }
597 
598  cpl_parameterlist_append(recipe->parameters, p);
599 
600  /* --nhigh: Number of maximum pixels to reject with minmax */
601  p = cpl_parameter_new_value("muse.muse_scibasic.nhigh",
602  CPL_TYPE_INT,
603  "Number of maximum pixels to reject with minmax",
604  "muse.muse_scibasic",
605  (int)1);
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);
610  }
611 
612  cpl_parameterlist_append(recipe->parameters, p);
613 
614  /* --nkeep: Number of pixels to keep with minmax */
615  p = cpl_parameter_new_value("muse.muse_scibasic.nkeep",
616  CPL_TYPE_INT,
617  "Number of pixels to keep with minmax",
618  "muse.muse_scibasic",
619  (int)1);
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);
624  }
625 
626  cpl_parameterlist_append(recipe->parameters, p);
627 
628  /* --lsigma: Low sigma for pixel rejection with sigclip */
629  p = cpl_parameter_new_value("muse.muse_scibasic.lsigma",
630  CPL_TYPE_DOUBLE,
631  "Low sigma for pixel rejection with sigclip",
632  "muse.muse_scibasic",
633  (double)3);
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);
638  }
639 
640  cpl_parameterlist_append(recipe->parameters, p);
641 
642  /* --hsigma: High sigma for pixel rejection with sigclip */
643  p = cpl_parameter_new_value("muse.muse_scibasic.hsigma",
644  CPL_TYPE_DOUBLE,
645  "High sigma for pixel rejection with sigclip",
646  "muse.muse_scibasic",
647  (double)3);
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);
652  }
653 
654  cpl_parameterlist_append(recipe->parameters, p);
655 
656  /* --scale: Scale the individual images to a common exposure time before combining them. */
657  p = cpl_parameter_new_value("muse.muse_scibasic.scale",
658  CPL_TYPE_BOOL,
659  "Scale the individual images to a common exposure time before combining them.",
660  "muse.muse_scibasic",
661  (int)TRUE);
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);
666  }
667 
668  cpl_parameterlist_append(recipe->parameters, p);
669 
670  /* --saveimage: Save the pre-processed CCD-based image of each input exposure before it is transformed into a pixel table. */
671  p = cpl_parameter_new_value("muse.muse_scibasic.saveimage",
672  CPL_TYPE_BOOL,
673  "Save the pre-processed CCD-based image of each input exposure before it is transformed into a pixel table.",
674  "muse.muse_scibasic",
675  (int)TRUE);
676  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "saveimage");
677  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "saveimage");
678 
679  cpl_parameterlist_append(recipe->parameters, p);
680 
681  /* --skylines: 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. */
682  p = cpl_parameter_new_value("muse.muse_scibasic.skylines",
683  CPL_TYPE_STRING,
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");
689 
690  cpl_parameterlist_append(recipe->parameters, p);
691 
692  /* --skyhalfwidth: Half-width of the extraction box (in Angstrom) around each sky emission line. */
693  p = cpl_parameter_new_value("muse.muse_scibasic.skyhalfwidth",
694  CPL_TYPE_DOUBLE,
695  "Half-width of the extraction box (in Angstrom) around each sky emission line.",
696  "muse.muse_scibasic",
697  (double)5.);
698  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "skyhalfwidth");
699  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skyhalfwidth");
700 
701  cpl_parameterlist_append(recipe->parameters, p);
702 
703  /* --skybinsize: Size of the bins (in Angstrom per pixel) for the intermediate spectrum to do the Gaussian fit to each sky emission line. */
704  p = cpl_parameter_new_value("muse.muse_scibasic.skybinsize",
705  CPL_TYPE_DOUBLE,
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",
708  (double)0.1);
709  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "skybinsize");
710  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skybinsize");
711 
712  cpl_parameterlist_append(recipe->parameters, p);
713 
714  /* --skyreject: 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. */
715  p = cpl_parameter_new_value("muse.muse_scibasic.skyreject",
716  CPL_TYPE_STRING,
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");
722 
723  cpl_parameterlist_append(recipe->parameters, p);
724 
725  /* --resample: 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! */
726  p = cpl_parameter_new_value("muse.muse_scibasic.resample",
727  CPL_TYPE_BOOL,
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",
730  (int)FALSE);
731  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "resample");
732  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "resample");
733 
734  cpl_parameterlist_append(recipe->parameters, p);
735 
736  /* --dlambda: Wavelength step (in Angstrom per pixel) to use for resampling. */
737  p = cpl_parameter_new_value("muse.muse_scibasic.dlambda",
738  CPL_TYPE_DOUBLE,
739  "Wavelength step (in Angstrom per pixel) to use for resampling.",
740  "muse.muse_scibasic",
741  (double)1.25);
742  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "dlambda");
743  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dlambda");
744 
745  cpl_parameterlist_append(recipe->parameters, p);
746 
747  /* --merge: Merge output products from different IFUs into a common file. */
748  p = cpl_parameter_new_value("muse.muse_scibasic.merge",
749  CPL_TYPE_BOOL,
750  "Merge output products from different IFUs into a common file.",
751  "muse.muse_scibasic",
752  (int)FALSE);
753  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "merge");
754  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "merge");
755 
756  cpl_parameterlist_append(recipe->parameters, p);
757 
758  return 0;
759 } /* muse_scibasic_create() */
760 
761 /*----------------------------------------------------------------------------*/
772 /*----------------------------------------------------------------------------*/
773 static int
774 muse_scibasic_params_fill(muse_scibasic_params_t *aParams, cpl_parameterlist *aParameters)
775 {
776  cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
777  cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
778  cpl_parameter *p;
779 
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);
783 
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);
787 
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);
791 
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);
795 
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);
799 
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);
803 
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);
807  aParams->cr =
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);
813 
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);
817 
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);
821 
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);
825 
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);
829 
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);
833  aParams->combine =
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);
842 
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);
846 
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);
850 
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);
854 
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);
858 
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);
862 
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);
866 
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);
870 
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);
874 
875  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.skyhalfwidth");
876  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
877  aParams->skyhalfwidth = cpl_parameter_get_double(p);
878 
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);
882 
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);
886 
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);
890 
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);
894 
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);
898 
899  return 0;
900 } /* muse_scibasic_params_fill() */
901 
902 /*----------------------------------------------------------------------------*/
909 /*----------------------------------------------------------------------------*/
910 static int
911 muse_scibasic_exec(cpl_plugin *aPlugin)
912 {
913  if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
914  return -1;
915  }
917  cpl_recipe *recipe = (cpl_recipe *)aPlugin;
918  cpl_msg_set_threadid_on();
919 
920  cpl_frameset *usedframes = cpl_frameset_new(),
921  *outframes = cpl_frameset_new();
922  muse_scibasic_params_t params;
923  muse_scibasic_params_fill(&params, recipe->parameters);
924 
925  cpl_errorstate prestate = cpl_errorstate_get();
926 
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);
931  return -1;
932  } /* if invalid params.nifu */
933 
934  cpl_boolean donotmerge = CPL_FALSE; /* depending on nifu we may not merge */
935  int rc = 0;
936  if (params.nifu > 0) {
937  muse_processing *proc = muse_processing_new("muse_scibasic",
938  recipe);
939  rc = muse_scibasic_compute(proc, &params);
940  cpl_frameset_join(usedframes, proc->usedframes);
941  cpl_frameset_join(outframes, proc->outframes);
943  donotmerge = CPL_TRUE; /* after processing one IFU, merging cannot work */
944  } else if (params.nifu < 0) { /* parallel processing */
945  int *rcs = cpl_calloc(kMuseNumIFUs, sizeof(int));
946  int nifu;
947  #pragma omp parallel for default(none) \
948  shared(outframes, params, rcs, recipe, usedframes)
949  for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
950  muse_processing *proc = muse_processing_new("muse_scibasic",
951  recipe);
952  muse_scibasic_params_t *pars = cpl_malloc(sizeof(muse_scibasic_params_t));
953  memcpy(pars, &params, sizeof(muse_scibasic_params_t));
954  pars->nifu = 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) {
958  *rci = 0;
959  }
960  cpl_free(pars);
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);
966  } /* for nifu */
967  /* non-parallel loop to propagate the "worst" return code; *
968  * since we only ever return -1, any non-zero code is propagated */
969  for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
970  if (rcs[nifu-1] != 0) {
971  rc = rcs[nifu-1];
972  } /* if */
973  } /* for nifu */
974  cpl_free(rcs);
975  } else { /* serial processing */
976  for (params.nifu = 1; params.nifu <= kMuseNumIFUs && !rc; params.nifu++) {
977  muse_processing *proc = muse_processing_new("muse_scibasic",
978  recipe);
979  rc = muse_scibasic_compute(proc, &params);
980  if (rc && (int)cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
981  rc = 0;
982  }
983  cpl_frameset_join(usedframes, proc->usedframes);
984  cpl_frameset_join(outframes, proc->outframes);
986  } /* for nifu */
987  } /* else */
988  UNUSED_ARGUMENT(donotmerge); /* maybe this is not going to be used below */
989 
990  if (!cpl_errorstate_is_equal(prestate)) {
991  /* dump all errors from this recipe in chronological order */
992  cpl_errorstate_dump(prestate, CPL_FALSE, muse_cplerrorstate_dump_some);
993  /* reset message level to not get the same errors displayed again by esorex */
994  cpl_msg_set_level(CPL_MSG_INFO);
995  }
996  /* clean up duplicates in framesets of used and output frames */
999 
1000  /* merge output products from the up to 24 IFUs */
1001  if (params.merge && !donotmerge) {
1002  muse_utils_frameset_merge_frames(outframes, CPL_TRUE);
1003  }
1004 
1005  /* to get esorex to see our classification (frame groups etc.), *
1006  * replace the original frameset with the list of used frames *
1007  * before appending product output frames */
1008  /* keep the same pointer, so just erase all frames, not delete the frameset */
1009  muse_cplframeset_erase_all(recipe->frames);
1010  cpl_frameset_join(recipe->frames, usedframes);
1011  cpl_frameset_join(recipe->frames, outframes);
1012  cpl_frameset_delete(usedframes);
1013  cpl_frameset_delete(outframes);
1014  return rc;
1015 } /* muse_scibasic_exec() */
1016 
1017 /*----------------------------------------------------------------------------*/
1024 /*----------------------------------------------------------------------------*/
1025 static int
1026 muse_scibasic_destroy(cpl_plugin *aPlugin)
1027 {
1028  /* Get the recipe from the plugin */
1029  cpl_recipe *recipe;
1030  if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
1031  recipe = (cpl_recipe *)aPlugin;
1032  } else {
1033  return -1;
1034  }
1035 
1036  /* Clean up */
1037  cpl_parameterlist_delete(recipe->parameters);
1039  return 0;
1040 } /* muse_scibasic_destroy() */
1041 
1042 /*----------------------------------------------------------------------------*/
1052 /*----------------------------------------------------------------------------*/
1053 int
1054 cpl_plugin_get_info(cpl_pluginlist *aList)
1055 {
1056  cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
1057  cpl_plugin *plugin = &recipe->interface;
1058 
1059  char *helptext;
1061  helptext = cpl_sprintf("%s%s", muse_scibasic_help,
1062  muse_scibasic_help_esorex);
1063  } else {
1064  helptext = cpl_sprintf("%s", muse_scibasic_help);
1065  }
1066 
1067  /* Initialize the CPL plugin stuff for this module */
1068  cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
1069  CPL_PLUGIN_TYPE_RECIPE,
1070  "muse_scibasic",
1071  "Remove the instrumental signature from the data of each CCD and convert them from an image into a pixel table.",
1072  helptext,
1073  "Peter Weilbacher",
1074  "usd-help@eso.org",
1075  muse_get_license(),
1076  muse_scibasic_create,
1077  muse_scibasic_exec,
1078  muse_scibasic_destroy);
1079  cpl_pluginlist_append(aList, plugin);
1080  cpl_free(helptext);
1081 
1082  return 0;
1083 } /* cpl_plugin_get_info() */
1084 
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.
Definition: muse_utils.c:83
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).
muse_frame_mode
int resample
Resample the input science data into 2D spectral images using all supplied calibrations for a visual ...
cpl_frameset * outframes
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.
Definition: muse_utils.c:589
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.