MUSE Pipeline Reference Manual  1.0.2
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-2014 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 /*----------------------------------------------------------------------------*/
82 /*----------------------------------------------------------------------------*/
85 /*----------------------------------------------------------------------------*
86  * Static variables *
87  *----------------------------------------------------------------------------*/
88 static const char *muse_scibasic_help =
89  "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. [For special cases, users can choose to combine all input files at the image level, so that the pixel table is only created once, for the combined data. This is not recommended for science data, where the combination should take place after correcting for atmospheric effects, before the creation of the final 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.";
90 
91 static const char *muse_scibasic_help_esorex =
92  "\n\nInput frames for raw frame tag \"OBJECT\":\n"
93  "\n Frame tag Type Req #Fr Description"
94  "\n -------------------- ---- --- --- ------------"
95  "\n OBJECT raw . Raw exposure of a science target"
96  "\n STD raw . Raw exposure of a standard star field"
97  "\n SKY raw . Raw exposure of an (almost) empty sky field"
98  "\n ASTROMETRY raw . Raw exposure of an astrometric field"
99  "\n ILLUM raw . 1 Single optional raw attached-field field exposure"
100  "\n MASTER_BIAS calib Y 1 Master bias"
101  "\n MASTER_DARK calib . 1 Master dark"
102  "\n MASTER_FLAT calib Y 1 Master flat"
103  "\n TRACE_TABLE calib Y 1 Trace table"
104  "\n WAVECAL_TABLE calib Y 1 Wavelength calibration table"
105  "\n GEOMETRY_TABLE calib Y 1 Relative positions of the slices in the field of view"
106  "\n TWILIGHT_CUBE calib . Smoothed cube of twilight sky"
107  "\n BADPIX_TABLE calib . 1 Known bad pixels"
108  "\n\nProduct frames for raw frame tag \"OBJECT\":\n"
109  "\n Frame tag Level Description"
110  "\n -------------------- -------- ------------"
111  "\n OBJECT_RED intermed Pre-processed CCD-based images for OBJECT input (if --saveimage=true)"
112  "\n OBJECT_RESAMPLED intermed Resampled 2D image for OBJECT input (if --resample=true)"
113  "\n PIXTABLE_OBJECT intermed Output pixel table for OBJECT input"
114  "\n STD_RED intermed Pre-processed CCD-based images for STD input (if --saveimage=true)"
115  "\n STD_RESAMPLED intermed Resampled 2D image for STD input (if --resample=true)"
116  "\n PIXTABLE_STD intermed Output pixel table for STD input"
117  "\n SKY_RED intermed Pre-processed CCD-based images for SKY input (if --saveimage=true)"
118  "\n SKY_RESAMPLED intermed Resampled 2D image for SKY input (if --resample=true)"
119  "\n PIXTABLE_SKY intermed Output pixel table for SKY input"
120  "\n ASTROMETRY_RED intermed Pre-processed CCD-based images for ASTROMETRY input (if --saveimage=true)"
121  "\n ASTROMETRY_RESAMPLED intermed Resampled 2D image for ASTROMETRY input (if --resample=true)"
122  "\n PIXTABLE_ASTROMETRY intermed Output pixel table for ASTROMETRY input" "\n\nInput frames for raw frame tag \"REDUCED\":\n"
123  "\n Frame tag Type Req #Fr Description"
124  "\n -------------------- ---- --- --- ------------"
125  "\n REDUCED raw Y Reduced CCD image"
126  "\n TRACE_TABLE calib Y 1 Trace table"
127  "\n WAVECAL_TABLE calib Y 1 Wavelength calibration table"
128  "\n GEOMETRY_TABLE calib Y 1 Relative positions of the slices in the field of view"
129  "\n\nProduct frames for raw frame tag \"REDUCED\":\n"
130  "\n Frame tag Level Description"
131  "\n -------------------- -------- ------------"
132  "\n REDUCED_RESAMPLED intermed Resampled 2D image (if --resample=true)"
133  "\n PIXTABLE_REDUCED intermed Output pixel table";
134 
135 /*----------------------------------------------------------------------------*/
143 /*----------------------------------------------------------------------------*/
144 static cpl_recipeconfig *
145 muse_scibasic_new_recipeconfig(void)
146 {
147  cpl_recipeconfig *recipeconfig = cpl_recipeconfig_new();
148  const char *tag;
149 
150  tag = "OBJECT";
151  cpl_recipeconfig_set_tag(recipeconfig, tag, -1, -1);
152  tag = "STD";
153  cpl_recipeconfig_set_tag(recipeconfig, tag, -1, -1);
154  tag = "SKY";
155  cpl_recipeconfig_set_tag(recipeconfig, tag, -1, -1);
156  tag = "ASTROMETRY";
157  cpl_recipeconfig_set_tag(recipeconfig, tag, -1, -1);
158  tag = "ILLUM";
159  cpl_recipeconfig_set_tag(recipeconfig, tag, -1, 1);
160  cpl_recipeconfig_set_input(recipeconfig, tag, "MASTER_BIAS", 1, 1);
161  cpl_recipeconfig_set_input(recipeconfig, tag, "MASTER_DARK", -1, 1);
162  cpl_recipeconfig_set_input(recipeconfig, tag, "MASTER_FLAT", 1, 1);
163  cpl_recipeconfig_set_input(recipeconfig, tag, "TRACE_TABLE", 1, 1);
164  cpl_recipeconfig_set_input(recipeconfig, tag, "WAVECAL_TABLE", 1, 1);
165  cpl_recipeconfig_set_input(recipeconfig, tag, "GEOMETRY_TABLE", 1, 1);
166  cpl_recipeconfig_set_input(recipeconfig, tag, "TWILIGHT_CUBE", -1, -1);
167  cpl_recipeconfig_set_input(recipeconfig, tag, "BADPIX_TABLE", -1, 1);
168  cpl_recipeconfig_set_output(recipeconfig, tag, "OBJECT_RED");
169  cpl_recipeconfig_set_output(recipeconfig, tag, "OBJECT_RESAMPLED");
170  cpl_recipeconfig_set_output(recipeconfig, tag, "PIXTABLE_OBJECT");
171  cpl_recipeconfig_set_output(recipeconfig, tag, "STD_RED");
172  cpl_recipeconfig_set_output(recipeconfig, tag, "STD_RESAMPLED");
173  cpl_recipeconfig_set_output(recipeconfig, tag, "PIXTABLE_STD");
174  cpl_recipeconfig_set_output(recipeconfig, tag, "SKY_RED");
175  cpl_recipeconfig_set_output(recipeconfig, tag, "SKY_RESAMPLED");
176  cpl_recipeconfig_set_output(recipeconfig, tag, "PIXTABLE_SKY");
177  cpl_recipeconfig_set_output(recipeconfig, tag, "ASTROMETRY_RED");
178  cpl_recipeconfig_set_output(recipeconfig, tag, "ASTROMETRY_RESAMPLED");
179  cpl_recipeconfig_set_output(recipeconfig, tag, "PIXTABLE_ASTROMETRY");
180 
181  tag = "REDUCED";
182  cpl_recipeconfig_set_tag(recipeconfig, tag, 1, -1);
183  cpl_recipeconfig_set_input(recipeconfig, tag, "TRACE_TABLE", 1, 1);
184  cpl_recipeconfig_set_input(recipeconfig, tag, "WAVECAL_TABLE", 1, 1);
185  cpl_recipeconfig_set_input(recipeconfig, tag, "GEOMETRY_TABLE", 1, 1);
186  cpl_recipeconfig_set_output(recipeconfig, tag, "REDUCED_RESAMPLED");
187  cpl_recipeconfig_set_output(recipeconfig, tag, "PIXTABLE_REDUCED");
188 
189  return recipeconfig;
190 } /* muse_scibasic_new_recipeconfig() */
191 
192 /*----------------------------------------------------------------------------*/
202 /*----------------------------------------------------------------------------*/
203 static cpl_error_code
204 muse_scibasic_prepare_header(const char *aFrametag, cpl_propertylist *aHeader)
205 {
206  cpl_ensure_code(aFrametag, CPL_ERROR_NULL_INPUT);
207  cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
208  if (!strcmp(aFrametag, "OBJECT_RED")) {
209  muse_processing_prepare_property(aHeader, "ESO QC SCIBASIC NSATURATED",
210  CPL_TYPE_INT,
211  "Number of saturated pixels in output data");
212  } else if (!strcmp(aFrametag, "OBJECT_RESAMPLED")) {
213  } else if (!strcmp(aFrametag, "PIXTABLE_OBJECT")) {
214  muse_processing_prepare_property(aHeader, "ESO QC SCIBASIC NSATURATED",
215  CPL_TYPE_INT,
216  "Number of saturated pixels in output data");
217  muse_processing_prepare_property(aHeader, "ESO QC SCIBASIC LAMBDA SHIFT",
218  CPL_TYPE_FLOAT,
219  "[Angstrom] Shift in wavelength applied to the data using sky emission line(s)");
220  } else if (!strcmp(aFrametag, "STD_RED")) {
221  muse_processing_prepare_property(aHeader, "ESO QC SCIBASIC NSATURATED",
222  CPL_TYPE_INT,
223  "Number of saturated pixels in output data");
224  } else if (!strcmp(aFrametag, "STD_RESAMPLED")) {
225  } else if (!strcmp(aFrametag, "PIXTABLE_STD")) {
226  muse_processing_prepare_property(aHeader, "ESO QC SCIBASIC NSATURATED",
227  CPL_TYPE_INT,
228  "Number of saturated pixels in output data");
229  } else if (!strcmp(aFrametag, "SKY_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, "SKY_RESAMPLED")) {
234  } else if (!strcmp(aFrametag, "PIXTABLE_SKY")) {
235  muse_processing_prepare_property(aHeader, "ESO QC SCIBASIC NSATURATED",
236  CPL_TYPE_INT,
237  "Number of saturated pixels in output data");
238  } else if (!strcmp(aFrametag, "ASTROMETRY_RED")) {
239  muse_processing_prepare_property(aHeader, "ESO QC SCIBASIC NSATURATED",
240  CPL_TYPE_INT,
241  "Number of saturated pixels in output data");
242  } else if (!strcmp(aFrametag, "ASTROMETRY_RESAMPLED")) {
243  } else if (!strcmp(aFrametag, "PIXTABLE_ASTROMETRY")) {
244  muse_processing_prepare_property(aHeader, "ESO QC SCIBASIC NSATURATED",
245  CPL_TYPE_INT,
246  "Number of saturated pixels in output data");
247  } else if (!strcmp(aFrametag, "REDUCED_RESAMPLED")) {
248  } else if (!strcmp(aFrametag, "PIXTABLE_REDUCED")) {
249  } else {
250  cpl_msg_warning(__func__, "Frame tag %s is not defined", aFrametag);
251  return CPL_ERROR_ILLEGAL_INPUT;
252  }
253  return CPL_ERROR_NONE;
254 } /* muse_scibasic_prepare_header() */
255 
256 /*----------------------------------------------------------------------------*/
265 /*----------------------------------------------------------------------------*/
266 static cpl_frame_level
267 muse_scibasic_get_frame_level(const char *aFrametag)
268 {
269  if (!aFrametag) {
270  return CPL_FRAME_LEVEL_NONE;
271  }
272  if (!strcmp(aFrametag, "OBJECT_RED")) {
273  return CPL_FRAME_LEVEL_INTERMEDIATE;
274  }
275  if (!strcmp(aFrametag, "OBJECT_RESAMPLED")) {
276  return CPL_FRAME_LEVEL_INTERMEDIATE;
277  }
278  if (!strcmp(aFrametag, "PIXTABLE_OBJECT")) {
279  return CPL_FRAME_LEVEL_INTERMEDIATE;
280  }
281  if (!strcmp(aFrametag, "STD_RED")) {
282  return CPL_FRAME_LEVEL_INTERMEDIATE;
283  }
284  if (!strcmp(aFrametag, "STD_RESAMPLED")) {
285  return CPL_FRAME_LEVEL_INTERMEDIATE;
286  }
287  if (!strcmp(aFrametag, "PIXTABLE_STD")) {
288  return CPL_FRAME_LEVEL_INTERMEDIATE;
289  }
290  if (!strcmp(aFrametag, "SKY_RED")) {
291  return CPL_FRAME_LEVEL_INTERMEDIATE;
292  }
293  if (!strcmp(aFrametag, "SKY_RESAMPLED")) {
294  return CPL_FRAME_LEVEL_INTERMEDIATE;
295  }
296  if (!strcmp(aFrametag, "PIXTABLE_SKY")) {
297  return CPL_FRAME_LEVEL_INTERMEDIATE;
298  }
299  if (!strcmp(aFrametag, "ASTROMETRY_RED")) {
300  return CPL_FRAME_LEVEL_INTERMEDIATE;
301  }
302  if (!strcmp(aFrametag, "ASTROMETRY_RESAMPLED")) {
303  return CPL_FRAME_LEVEL_INTERMEDIATE;
304  }
305  if (!strcmp(aFrametag, "PIXTABLE_ASTROMETRY")) {
306  return CPL_FRAME_LEVEL_INTERMEDIATE;
307  }
308  if (!strcmp(aFrametag, "REDUCED_RESAMPLED")) {
309  return CPL_FRAME_LEVEL_INTERMEDIATE;
310  }
311  if (!strcmp(aFrametag, "PIXTABLE_REDUCED")) {
312  return CPL_FRAME_LEVEL_INTERMEDIATE;
313  }
314  return CPL_FRAME_LEVEL_NONE;
315 } /* muse_scibasic_get_frame_level() */
316 
317 /*----------------------------------------------------------------------------*/
326 /*----------------------------------------------------------------------------*/
327 static muse_frame_mode
328 muse_scibasic_get_frame_mode(const char *aFrametag)
329 {
330  if (!aFrametag) {
331  return MUSE_FRAME_MODE_ALL;
332  }
333  if (!strcmp(aFrametag, "OBJECT_RED")) {
335  }
336  if (!strcmp(aFrametag, "OBJECT_RESAMPLED")) {
338  }
339  if (!strcmp(aFrametag, "PIXTABLE_OBJECT")) {
341  }
342  if (!strcmp(aFrametag, "STD_RED")) {
344  }
345  if (!strcmp(aFrametag, "STD_RESAMPLED")) {
347  }
348  if (!strcmp(aFrametag, "PIXTABLE_STD")) {
350  }
351  if (!strcmp(aFrametag, "SKY_RED")) {
353  }
354  if (!strcmp(aFrametag, "SKY_RESAMPLED")) {
356  }
357  if (!strcmp(aFrametag, "PIXTABLE_SKY")) {
359  }
360  if (!strcmp(aFrametag, "ASTROMETRY_RED")) {
362  }
363  if (!strcmp(aFrametag, "ASTROMETRY_RESAMPLED")) {
365  }
366  if (!strcmp(aFrametag, "PIXTABLE_ASTROMETRY")) {
368  }
369  if (!strcmp(aFrametag, "REDUCED_RESAMPLED")) {
371  }
372  if (!strcmp(aFrametag, "PIXTABLE_REDUCED")) {
374  }
375  return MUSE_FRAME_MODE_ALL;
376 } /* muse_scibasic_get_frame_mode() */
377 
378 /*----------------------------------------------------------------------------*/
388 /*----------------------------------------------------------------------------*/
389 static int
390 muse_scibasic_create(cpl_plugin *aPlugin)
391 {
392  /* Check that the plugin is part of a valid recipe */
393  cpl_recipe *recipe;
394  if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
395  recipe = (cpl_recipe *)aPlugin;
396  } else {
397  return -1;
398  }
399 
400  /* register the extended processing information (new FITS header creation, *
401  * getting of the frame level for a certain tag) */
403  muse_scibasic_new_recipeconfig(),
404  muse_scibasic_prepare_header,
405  muse_scibasic_get_frame_level,
406  muse_scibasic_get_frame_mode);
407 
408  /* XXX initialize timing in messages *
409  * since at least esorex is too stupid to turn it on, we have to do it */
411  cpl_msg_set_time_on();
412  }
413 
414  /* Create the parameter list in the cpl_recipe object */
415  recipe->parameters = cpl_parameterlist_new();
416  /* Fill the parameters list */
417  cpl_parameter *p;
418 
419  /* --nifu: IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in parallel. */
420  p = cpl_parameter_new_range("muse.muse_scibasic.nifu",
421  CPL_TYPE_INT,
422  "IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in parallel.",
423  "muse.muse_scibasic",
424  (int)0,
425  (int)-1,
426  (int)24);
427  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nifu");
428  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nifu");
429 
430  cpl_parameterlist_append(recipe->parameters, p);
431 
432  /* --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. */
433  p = cpl_parameter_new_value("muse.muse_scibasic.overscan",
434  CPL_TYPE_STRING,
435  "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.",
436  "muse.muse_scibasic",
437  (const char *)"vpoly");
438  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "overscan");
439  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "overscan");
440 
441  cpl_parameterlist_append(recipe->parameters, p);
442 
443  /* --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"). */
444  p = cpl_parameter_new_value("muse.muse_scibasic.ovscreject",
445  CPL_TYPE_STRING,
446  "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\").",
447  "muse.muse_scibasic",
448  (const char *)"dcr");
449  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscreject");
450  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscreject");
451 
452  cpl_parameterlist_append(recipe->parameters, p);
453 
454  /* --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". */
455  p = cpl_parameter_new_value("muse.muse_scibasic.ovscsigma",
456  CPL_TYPE_DOUBLE,
457  "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\".",
458  "muse.muse_scibasic",
459  (double)30.);
460  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscsigma");
461  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscsigma");
462 
463  cpl_parameterlist_append(recipe->parameters, p);
464 
465  /* --ovscignore: The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when computing statistics or fits. */
466  p = cpl_parameter_new_value("muse.muse_scibasic.ovscignore",
467  CPL_TYPE_INT,
468  "The number of pixels of the overscan adjacent to the data region of the CCD that are ignored when computing statistics or fits.",
469  "muse.muse_scibasic",
470  (int)3);
471  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ovscignore");
472  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ovscignore");
473 
474  cpl_parameterlist_append(recipe->parameters, p);
475 
476  /* --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). */
477  p = cpl_parameter_new_value("muse.muse_scibasic.crop",
478  CPL_TYPE_BOOL,
479  "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).",
480  "muse.muse_scibasic",
481  (int)TRUE);
482  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "crop");
483  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "crop");
484 
485  cpl_parameterlist_append(recipe->parameters, p);
486 
487  /* --cr: Type of cosmic ray cleaning to use (for quick-look data processing). */
488  p = cpl_parameter_new_enum("muse.muse_scibasic.cr",
489  CPL_TYPE_STRING,
490  "Type of cosmic ray cleaning to use (for quick-look data processing).",
491  "muse.muse_scibasic",
492  (const char *)"none",
493  2,
494  (const char *)"none",
495  (const char *)"dcr");
496  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "cr");
497  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "cr");
498 
499  cpl_parameterlist_append(recipe->parameters, p);
500 
501  /* --xbox: Search box size in x. Only used if cr=dcr. */
502  p = cpl_parameter_new_value("muse.muse_scibasic.xbox",
503  CPL_TYPE_INT,
504  "Search box size in x. Only used if cr=dcr.",
505  "muse.muse_scibasic",
506  (int)15);
507  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "xbox");
508  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "xbox");
509 
510  cpl_parameterlist_append(recipe->parameters, p);
511 
512  /* --ybox: Search box size in y. Only used if cr=dcr. */
513  p = cpl_parameter_new_value("muse.muse_scibasic.ybox",
514  CPL_TYPE_INT,
515  "Search box size in y. Only used if cr=dcr.",
516  "muse.muse_scibasic",
517  (int)40);
518  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "ybox");
519  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "ybox");
520 
521  cpl_parameterlist_append(recipe->parameters, p);
522 
523  /* --passes: Maximum number of cleaning passes. Only used if cr=dcr. */
524  p = cpl_parameter_new_value("muse.muse_scibasic.passes",
525  CPL_TYPE_INT,
526  "Maximum number of cleaning passes. Only used if cr=dcr.",
527  "muse.muse_scibasic",
528  (int)2);
529  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "passes");
530  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "passes");
531 
532  cpl_parameterlist_append(recipe->parameters, p);
533 
534  /* --thres: Threshold for detection gap in factors of standard deviation. Only used if cr=dcr. */
535  p = cpl_parameter_new_value("muse.muse_scibasic.thres",
536  CPL_TYPE_DOUBLE,
537  "Threshold for detection gap in factors of standard deviation. Only used if cr=dcr.",
538  "muse.muse_scibasic",
539  (double)5.8);
540  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "thres");
541  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "thres");
542 
543  cpl_parameterlist_append(recipe->parameters, p);
544 
545  /* --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! */
546  p = cpl_parameter_new_enum("muse.muse_scibasic.combine",
547  CPL_TYPE_STRING,
548  "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!",
549  "muse.muse_scibasic",
550  (const char *)"none",
551  5,
552  (const char *)"none",
553  (const char *)"average",
554  (const char *)"median",
555  (const char *)"minmax",
556  (const char *)"sigclip");
557  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "combine");
558  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "combine");
559 
560  cpl_parameterlist_append(recipe->parameters, p);
561 
562  /* --nlow: Number of minimum pixels to reject with minmax */
563  p = cpl_parameter_new_value("muse.muse_scibasic.nlow",
564  CPL_TYPE_INT,
565  "Number of minimum pixels to reject with minmax",
566  "muse.muse_scibasic",
567  (int)1);
568  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nlow");
569  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nlow");
570 
571  cpl_parameterlist_append(recipe->parameters, p);
572 
573  /* --nhigh: Number of maximum pixels to reject with minmax */
574  p = cpl_parameter_new_value("muse.muse_scibasic.nhigh",
575  CPL_TYPE_INT,
576  "Number of maximum pixels to reject with minmax",
577  "muse.muse_scibasic",
578  (int)1);
579  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nhigh");
580  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nhigh");
581 
582  cpl_parameterlist_append(recipe->parameters, p);
583 
584  /* --nkeep: Number of pixels to keep with minmax */
585  p = cpl_parameter_new_value("muse.muse_scibasic.nkeep",
586  CPL_TYPE_INT,
587  "Number of pixels to keep with minmax",
588  "muse.muse_scibasic",
589  (int)1);
590  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "nkeep");
591  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "nkeep");
592 
593  cpl_parameterlist_append(recipe->parameters, p);
594 
595  /* --lsigma: Low sigma for pixel rejection with sigclip */
596  p = cpl_parameter_new_value("muse.muse_scibasic.lsigma",
597  CPL_TYPE_DOUBLE,
598  "Low sigma for pixel rejection with sigclip",
599  "muse.muse_scibasic",
600  (double)3);
601  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "lsigma");
602  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lsigma");
603 
604  cpl_parameterlist_append(recipe->parameters, p);
605 
606  /* --hsigma: High sigma for pixel rejection with sigclip */
607  p = cpl_parameter_new_value("muse.muse_scibasic.hsigma",
608  CPL_TYPE_DOUBLE,
609  "High sigma for pixel rejection with sigclip",
610  "muse.muse_scibasic",
611  (double)3);
612  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "hsigma");
613  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "hsigma");
614 
615  cpl_parameterlist_append(recipe->parameters, p);
616 
617  /* --scale: Scale the individual images to a common exposure time before combining them. */
618  p = cpl_parameter_new_value("muse.muse_scibasic.scale",
619  CPL_TYPE_BOOL,
620  "Scale the individual images to a common exposure time before combining them.",
621  "muse.muse_scibasic",
622  (int)TRUE);
623  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "scale");
624  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "scale");
625 
626  cpl_parameterlist_append(recipe->parameters, p);
627 
628  /* --saveimage: Save the pre-processed CCD-based image of each input exposure before it is transformed into a pixel table. */
629  p = cpl_parameter_new_value("muse.muse_scibasic.saveimage",
630  CPL_TYPE_BOOL,
631  "Save the pre-processed CCD-based image of each input exposure before it is transformed into a pixel table.",
632  "muse.muse_scibasic",
633  (int)TRUE);
634  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "saveimage");
635  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "saveimage");
636 
637  cpl_parameterlist_append(recipe->parameters, p);
638 
639  /* --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. */
640  p = cpl_parameter_new_value("muse.muse_scibasic.skylines",
641  CPL_TYPE_STRING,
642  "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.",
643  "muse.muse_scibasic",
644  (const char *)"5577.339,6300.304");
645  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "skylines");
646  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skylines");
647 
648  cpl_parameterlist_append(recipe->parameters, p);
649 
650  /* --skyhalfwidth: Half-width of the extraction box (in Angstrom) around each sky emission line. */
651  p = cpl_parameter_new_value("muse.muse_scibasic.skyhalfwidth",
652  CPL_TYPE_DOUBLE,
653  "Half-width of the extraction box (in Angstrom) around each sky emission line.",
654  "muse.muse_scibasic",
655  (double)5.);
656  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "skyhalfwidth");
657  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skyhalfwidth");
658 
659  cpl_parameterlist_append(recipe->parameters, p);
660 
661  /* --skybinsize: Size of the bins (in Angstrom per pixel) for the intermediate spectrum to do the Gaussian fit to each sky emission line. */
662  p = cpl_parameter_new_value("muse.muse_scibasic.skybinsize",
663  CPL_TYPE_DOUBLE,
664  "Size of the bins (in Angstrom per pixel) for the intermediate spectrum to do the Gaussian fit to each sky emission line.",
665  "muse.muse_scibasic",
666  (double)0.1);
667  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "skybinsize");
668  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "skybinsize");
669 
670  cpl_parameterlist_append(recipe->parameters, p);
671 
672  /* --resample: Resample the input science data into 2D spectral images using tracing and wavelength calibration solutions for a visual check. Note that the image produced will show small wiggles even when the input calibrations are good and were applied successfully! */
673  p = cpl_parameter_new_value("muse.muse_scibasic.resample",
674  CPL_TYPE_BOOL,
675  "Resample the input science data into 2D spectral images using tracing and wavelength calibration solutions for a visual check. Note that the image produced will show small wiggles even when the input calibrations are good and were applied successfully!",
676  "muse.muse_scibasic",
677  (int)FALSE);
678  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "resample");
679  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "resample");
680 
681  cpl_parameterlist_append(recipe->parameters, p);
682 
683  /* --dlambda: Wavelength step (in Angstrom per pixel) to use for resampling. */
684  p = cpl_parameter_new_value("muse.muse_scibasic.dlambda",
685  CPL_TYPE_DOUBLE,
686  "Wavelength step (in Angstrom per pixel) to use for resampling.",
687  "muse.muse_scibasic",
688  (double)1.25);
689  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "dlambda");
690  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "dlambda");
691 
692  cpl_parameterlist_append(recipe->parameters, p);
693 
694  /* --merge: Merge output products from different IFUs into a common file. */
695  p = cpl_parameter_new_value("muse.muse_scibasic.merge",
696  CPL_TYPE_BOOL,
697  "Merge output products from different IFUs into a common file.",
698  "muse.muse_scibasic",
699  (int)FALSE);
700  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CFG, "merge");
701  cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "merge");
702 
703  cpl_parameterlist_append(recipe->parameters, p);
704 
705  return 0;
706 } /* muse_scibasic_create() */
707 
708 /*----------------------------------------------------------------------------*/
719 /*----------------------------------------------------------------------------*/
720 static int
721 muse_scibasic_params_fill(muse_scibasic_params_t *aParams, cpl_parameterlist *aParameters)
722 {
723  cpl_ensure_code(aParams, CPL_ERROR_NULL_INPUT);
724  cpl_ensure_code(aParameters, CPL_ERROR_NULL_INPUT);
725  cpl_parameter *p;
726 
727  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.nifu");
728  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
729  aParams->nifu = cpl_parameter_get_int(p);
730 
731  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.overscan");
732  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
733  aParams->overscan = cpl_parameter_get_string(p);
734 
735  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.ovscreject");
736  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
737  aParams->ovscreject = cpl_parameter_get_string(p);
738 
739  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.ovscsigma");
740  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
741  aParams->ovscsigma = cpl_parameter_get_double(p);
742 
743  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.ovscignore");
744  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
745  aParams->ovscignore = cpl_parameter_get_int(p);
746 
747  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.crop");
748  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
749  aParams->crop = cpl_parameter_get_bool(p);
750 
751  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.cr");
752  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
753  aParams->cr_s = cpl_parameter_get_string(p);
754  aParams->cr =
755  (!strcasecmp(aParams->cr_s, "none")) ? MUSE_SCIBASIC_PARAM_CR_NONE :
756  (!strcasecmp(aParams->cr_s, "dcr")) ? MUSE_SCIBASIC_PARAM_CR_DCR :
757  MUSE_SCIBASIC_PARAM_CR_INVALID_VALUE;
758  cpl_ensure_code(aParams->cr != MUSE_SCIBASIC_PARAM_CR_INVALID_VALUE,
759  CPL_ERROR_ILLEGAL_INPUT);
760 
761  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.xbox");
762  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
763  aParams->xbox = cpl_parameter_get_int(p);
764 
765  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.ybox");
766  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
767  aParams->ybox = cpl_parameter_get_int(p);
768 
769  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.passes");
770  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
771  aParams->passes = cpl_parameter_get_int(p);
772 
773  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.thres");
774  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
775  aParams->thres = cpl_parameter_get_double(p);
776 
777  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.combine");
778  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
779  aParams->combine_s = cpl_parameter_get_string(p);
780  aParams->combine =
781  (!strcasecmp(aParams->combine_s, "none")) ? MUSE_SCIBASIC_PARAM_COMBINE_NONE :
782  (!strcasecmp(aParams->combine_s, "average")) ? MUSE_SCIBASIC_PARAM_COMBINE_AVERAGE :
783  (!strcasecmp(aParams->combine_s, "median")) ? MUSE_SCIBASIC_PARAM_COMBINE_MEDIAN :
784  (!strcasecmp(aParams->combine_s, "minmax")) ? MUSE_SCIBASIC_PARAM_COMBINE_MINMAX :
785  (!strcasecmp(aParams->combine_s, "sigclip")) ? MUSE_SCIBASIC_PARAM_COMBINE_SIGCLIP :
786  MUSE_SCIBASIC_PARAM_COMBINE_INVALID_VALUE;
787  cpl_ensure_code(aParams->combine != MUSE_SCIBASIC_PARAM_COMBINE_INVALID_VALUE,
788  CPL_ERROR_ILLEGAL_INPUT);
789 
790  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.nlow");
791  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
792  aParams->nlow = cpl_parameter_get_int(p);
793 
794  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.nhigh");
795  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
796  aParams->nhigh = cpl_parameter_get_int(p);
797 
798  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.nkeep");
799  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
800  aParams->nkeep = cpl_parameter_get_int(p);
801 
802  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.lsigma");
803  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
804  aParams->lsigma = cpl_parameter_get_double(p);
805 
806  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.hsigma");
807  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
808  aParams->hsigma = cpl_parameter_get_double(p);
809 
810  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.scale");
811  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
812  aParams->scale = cpl_parameter_get_bool(p);
813 
814  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.saveimage");
815  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
816  aParams->saveimage = cpl_parameter_get_bool(p);
817 
818  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.skylines");
819  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
820  aParams->skylines = cpl_parameter_get_string(p);
821 
822  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.skyhalfwidth");
823  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
824  aParams->skyhalfwidth = cpl_parameter_get_double(p);
825 
826  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.skybinsize");
827  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
828  aParams->skybinsize = cpl_parameter_get_double(p);
829 
830  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.resample");
831  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
832  aParams->resample = cpl_parameter_get_bool(p);
833 
834  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.dlambda");
835  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
836  aParams->dlambda = cpl_parameter_get_double(p);
837 
838  p = cpl_parameterlist_find(aParameters, "muse.muse_scibasic.merge");
839  cpl_ensure_code(p, CPL_ERROR_DATA_NOT_FOUND);
840  aParams->merge = cpl_parameter_get_bool(p);
841 
842  return 0;
843 } /* muse_scibasic_params_fill() */
844 
845 /*----------------------------------------------------------------------------*/
852 /*----------------------------------------------------------------------------*/
853 static int
854 muse_scibasic_exec(cpl_plugin *aPlugin)
855 {
856  if (cpl_plugin_get_type(aPlugin) != CPL_PLUGIN_TYPE_RECIPE) {
857  return -1;
858  }
859  cpl_recipe *recipe = (cpl_recipe *)aPlugin;
860  cpl_msg_set_threadid_on();
861 
862  cpl_frameset *usedframes = cpl_frameset_new(),
863  *outframes = cpl_frameset_new();
864  muse_scibasic_params_t params;
865  muse_scibasic_params_fill(&params, recipe->parameters);
866 
867  cpl_errorstate prestate = cpl_errorstate_get();
868 
869  if (params.nifu < -1 || params.nifu > kMuseNumIFUs) {
870  cpl_msg_error(__func__, "Please specify a valid IFU number (between 1 and "
871  "%d), 0 (to process all IFUs consecutively), or -1 (to "
872  "process all IFUs in parallel) using --nifu.", kMuseNumIFUs);
873  return -1;
874  } /* if invalid params.nifu */
875 
876  cpl_boolean donotmerge = CPL_FALSE; /* depending on nifu we may not merge */
877  int rc = 0;
878  if (params.nifu > 0) {
879  muse_processing *proc = muse_processing_new("muse_scibasic",
880  recipe);
881  rc = muse_scibasic_compute(proc, &params);
882  cpl_frameset_join(usedframes, proc->usedframes);
883  cpl_frameset_join(outframes, proc->outframes);
885  donotmerge = CPL_TRUE; /* after processing one IFU, merging cannot work */
886  } else if (params.nifu < 0) { /* parallel processing */
887  int *rcs = cpl_calloc(kMuseNumIFUs, sizeof(int));
888  int nifu;
889  #pragma omp parallel for default(none) \
890  shared(outframes, params, rcs, recipe, usedframes)
891  for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
892  muse_processing *proc = muse_processing_new("muse_scibasic",
893  recipe);
894  muse_scibasic_params_t *pars = cpl_malloc(sizeof(muse_scibasic_params_t));
895  memcpy(pars, &params, sizeof(muse_scibasic_params_t));
896  pars->nifu = nifu;
897  int *rci = rcs + (nifu - 1);
898  *rci = muse_scibasic_compute(proc, pars);
899  if (rci && cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
900  *rci = 0;
901  }
902  cpl_free(pars);
903  #pragma omp critical(muse_processing_used_frames)
904  cpl_frameset_join(usedframes, proc->usedframes);
905  #pragma omp critical(muse_processing_output_frames)
906  cpl_frameset_join(outframes, proc->outframes);
908  } /* for nifu */
909  /* non-parallel loop to propagate the "worst" return code; *
910  * since we only ever return -1, any non-zero code is propagated */
911  for (nifu = 1; nifu <= kMuseNumIFUs; nifu++) {
912  if (rcs[nifu-1] != 0) {
913  rc = rcs[nifu-1];
914  } /* if */
915  } /* for nifu */
916  cpl_free(rcs);
917  } else { /* serial processing */
918  for (params.nifu = 1; params.nifu <= kMuseNumIFUs && !rc; params.nifu++) {
919  muse_processing *proc = muse_processing_new("muse_scibasic",
920  recipe);
921  rc = muse_scibasic_compute(proc, &params);
922  if (rc && cpl_error_get_code() == MUSE_ERROR_CHIP_NOT_LIVE) {
923  rc = 0;
924  }
925  cpl_frameset_join(usedframes, proc->usedframes);
926  cpl_frameset_join(outframes, proc->outframes);
928  } /* for nifu */
929  } /* else */
930  UNUSED_ARGUMENT(donotmerge); /* maybe this is not going to be used below */
931 
932  if (!cpl_errorstate_is_equal(prestate)) {
933  /* dump all errors from this recipe in chronological order */
934  cpl_errorstate_dump(prestate, CPL_FALSE, muse_cplerrorstate_dump_some);
935  /* reset message level to not get the same errors displayed again by esorex */
936  cpl_msg_set_level(CPL_MSG_INFO);
937  }
938  /* clean up duplicates in framesets of used and output frames */
941 
942  /* merge output products from the up to 24 IFUs */
943  if (params.merge && !donotmerge) {
944  muse_utils_frameset_merge_frames(outframes);
945  }
946 
947  /* to get esorex to see our classification (frame groups etc.), *
948  * replace the original frameset with the list of used frames *
949  * before appending product output frames */
950  /* keep the same pointer, so just erase all frames, not delete the frameset */
951  muse_cplframeset_erase_all(recipe->frames);
952  cpl_frameset_join(recipe->frames, usedframes);
953  cpl_frameset_join(recipe->frames, outframes);
954  cpl_frameset_delete(usedframes);
955  cpl_frameset_delete(outframes);
956  return rc;
957 } /* muse_scibasic_exec() */
958 
959 /*----------------------------------------------------------------------------*/
966 /*----------------------------------------------------------------------------*/
967 static int
968 muse_scibasic_destroy(cpl_plugin *aPlugin)
969 {
970  /* Get the recipe from the plugin */
971  cpl_recipe *recipe;
972  if (cpl_plugin_get_type(aPlugin) == CPL_PLUGIN_TYPE_RECIPE) {
973  recipe = (cpl_recipe *)aPlugin;
974  } else {
975  return -1;
976  }
977 
978  /* Clean up */
979  cpl_parameterlist_delete(recipe->parameters);
981  return 0;
982 } /* muse_scibasic_destroy() */
983 
984 /*----------------------------------------------------------------------------*/
994 /*----------------------------------------------------------------------------*/
995 int
996 cpl_plugin_get_info(cpl_pluginlist *aList)
997 {
998  cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
999  cpl_plugin *plugin = &recipe->interface;
1000 
1001  char *helptext;
1003  helptext = cpl_sprintf("%s%s", muse_scibasic_help,
1004  muse_scibasic_help_esorex);
1005  } else {
1006  helptext = cpl_sprintf("%s", muse_scibasic_help);
1007  }
1008 
1009  /* Initialize the CPL plugin stuff for this module */
1010  cpl_plugin_init(plugin, CPL_PLUGIN_API, MUSE_BINARY_VERSION,
1011  CPL_PLUGIN_TYPE_RECIPE,
1012  "muse_scibasic",
1013  "Remove the instrumental signature from the data of each CCD and convert them from an image into a pixel table.",
1014  helptext,
1015  "Peter Weilbacher",
1016  "usd-help@eso.org",
1017  muse_get_license(),
1018  muse_scibasic_create,
1019  muse_scibasic_exec,
1020  muse_scibasic_destroy);
1021  cpl_pluginlist_append(aList, plugin);
1022  cpl_free(helptext);
1023 
1024  return 0;
1025 } /* cpl_plugin_get_info() */
1026 
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:84
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 tracing and wavelength calibration solu...
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 region of the CCD that are ignored when com...
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.